bubblesly / luamuse Goto Github PK
View Code? Open in Web Editor NEWUtilities for music in Lua
Utilities for music in Lua
C’est un peu plus lua-tesque.
Salut,
Voici le résultat de ma réflexion de ces dernières 48h.
Certains mots sont en français et en gras, ce sont des éléments importants
de la modélisation. La première fois qu’ils apparaissent, ils doivent être
suivis par leur version en anglais
dans une police monospacée, l’anglais
étant utilisé dans la code informatique qui modélise le concept.
Perso, je suis pour le snake_case
au passage.
Tant qu’on y est j’en profite pour dire qu’on n’a peut-être pas besoin de
programmation orientée objet. Si on est de l’équipe des fonctionnels,
autant ne pas se priver. C’est pourquoi pour certaines listes (on dit « table »
en Lua mais je vais souvent utiliser le mot « liste ») de nombres vous
trouverez peut-être un « tag » pour identifier le « sous-type » de la valeur.
Les tags sont indiqués sans guillemets pour alléger l’écriture, ce qui sera
peut-être le cas dans le code (voir la définition de quelques constantes
tout au long du document). Les « types » au sens informatique, ou classes
en POO n’ont pas besoin d’être explicités car on est censé savoir ce qu’on
manipule, en revanche on peut devoir indiquer un « sous-type » (voir par
exemple les différents sous-types pour position).
C’est peut-être pour garder le lien avec un niveau assez bas que je veux me
débarasser de la POO, que je veux mettre des constantes globales. Ça va
peut-être entraver plus qu’autre chose mais ça pourrait être très facilement
porté vers d’autres langages (OK on n’en est pas là).
Et puis pourquoi pas un seul gros fichier ?
Quelques idées mais je ne suis pas du tout expert. C’est peut-être l’affaire
de Pd sans Lua en fait.
Il faudrait une sorte de séquenceur, qui pourrait écouter et émettre du
MIDI Time Code (MTC
) (voir WP).
Son état serait constitué de ces éléments :
bpm
), 120 par défaut ;meter
) qui, pour simplifier dans un premier temps, seraitfloat
) ;bar_num
), de 1 à l’infini ;beat_num
), de 1 à meter
;sub_beat
) de 1 à 120 (=2.2.2.3.5),Il faudrait peut-être aussi indiquer le nombre de croches par noire, en
supposant que les pulsations sont dénotée par des noires.
Davantage réfléchir là-dessus, ça peut permettre des conversions avec les
indications de mesure de la vraie vie.
Ces trois derniers éléments constituent la position (position
) et valent
1 par défaut.
bpm = 120
meter = 4
position = {1, 1, 1}
On peut indiquer une position de différentes façons :
abs
), ex : « contretemps du troisième temps de la{ABS, 10, 3, 61}
;rel
), ex : « dans exactement trois mesures et deux{REL, 3, 2, 0}
;half_rel
), ex: « au prochain contretemps »{HALF_REL, 0, 0, 60}
.On part sur une harmonie par tierces (« tertiale »). Pas besoin de cadre
spécial pour l’harmonie quartale, on peut toujours l’émuler avec la tertiale.
Ce bouquin de Philip Tagg m’a ouvert les yeux à ce niveau :
Everyday Tonality: Towards a Tonal Theory of What Most People Hear.
C’est p.293. Je reparlerai de ce bouquin un peu plus loin à propos des modes
issus de la gamme « mineure harmonique ».
Pour pouvoir se repérer dans l’harmonie, l’état du système serait constitué de
ces valeurs :
tonality
), valant par défaut 0 et représentantdegree
), c’est-à-dire les célèbres chiffres romains,{1, 0}
(♭VI serait {6, -1}
) ;notes_number
), par défaut 3 ;chord_alteration
) ;chord_bass
).Pour l’altération, deux façons de voir, non exclusives :
"maj"
pour « majorisation » (ex : VIm7 -> VI7 ou tierce picarde),{3, 1}
dans la première façon de voir ;"min"
pour « minorisation » (ex : IV -> IVm),{3, -1}
;"sus2"
et "sus4"
pour les suspensions, qui n’auraient en fait"6"
, "add9"
, …) : idem ;"f5"
, "b5"
ou "♭5"
pour {5, -1}
;"s5"
, "d5"
ou "♯5"
pour {5, 1}
(au passage pour moi c’est"f9"
, "b9"
ou "♭9"
pour {2, -1}
;"7"
pour {{3, 0}, {7, -1}}
;"s9"
, "d9"
ou "♯9"
pour {2, 1}
;"s11"
, "d11"
ou "♯11"
pour {4, 1}
;"f13"
, "b13"
ou "♭13"
pour {6, -1}
;La première solution est puissante et robuste mais peu musicale à mon sens,
et la seconde résout le problème des accords suspendus, qui sont indiqués
dans les grilles mais gérés au niveau du choix des notes.
Dans tous les cas, la valeur est vide par défaut (donc ""
ou {}
).
Raccourci possible : une seule string.
Ce sont des événements ponctuels, sans durée.
abs
),rel_plus
),rel_times
) ;metric_mod
), combinaison des deux précédents ;Quelques exemples de modulations :
tonality += 2
)degree = {6, 0}
)tonality -= 3; degree = {6, 0}
)Un instrument (instrument
) joue un (ou plusieurs) groupe
(notes_group
) de notes (note
) à une position donnée, avec une
certaine durée (duration
).
Un instrument a un état timbral (là je dis Joker, et puis surtout c’est sans
doute du côté Pd que ça va être géré).
Un groupe de notes peut être de trois types (group_type
) pour des
gestions algorithmiques potentiellement différentes) :
melody
), souvent une seule note mais parfois plusieurs ;chord
), souvent plusieurs notes ;bass
), toujours une seule note.Les notes par défaut des deux derniers types pourront par exemple être
calculées à partir du contexte harmonique pour avoir un accompagnement
automatique.
Pour cette gestion algorithmique (conduite de voix par exemple), nous aurons
besoin de savoir quelles notes auront été jouées en dernier, donc un
instrument aura trois « états » : état de sa basse, de ses accords, de sa
mélodie (3 listes de midi_num
car un instrument ne connait pas ses noms de
notes). Si ce n’est pas assez, c’est qu’il faut créer un autre instrument.
Les états sont vides par défaut, et pourraient ressembler à ça pour un
instrument piano
:
piano = {} -- valeur par défaut
piano.bass = C2 -- voir la section notes ci-dessous
piano.chord = {C3, E3, G3}
piano.melody = {E4, C5}
Une note est un nom de note (note_name
) joué à une octave
(octave
). Une note correspond donc à un numéro MIDI (midi_num
) et
un seul, mais un même numéro MIDI peut correspondre à plusieurs notes.
La partie étude et reconnaissance des formes des numéros MIDI peut être
sympa pour faire de l’analyse automatisée, et aussi si vous voulez qu’on
puisse jammer avec votre objet maléfique (jouer des accords en réaction à une
mélodie, soyons fous).
Pour associer des notes à des numéros MIDI, on pourrait définir ces
constantes :
Cf0
, Cb0
, Dob0
avec la valeur 11
C0
, Do0
avec la valeur 12
Gss4
, Soldd4
, A4
, La4
avec la valeur 69
-- https://stackoverflow.com/questions/10842679/lua-multiple-assignment
-- on ne peut pas mettre é, #, ♯ ou ♭ dans les noms de variables
function multi(n)
return n, n, n, n, n
end
N = {}
for i = 0, 9, 1
do
-- Beware: Cf1 is B0
_G["Cf" ..i], _G["Cb" ..i], _G["Dob"..i] = multi(11 + 12*i)
_G["C" ..i], _G["Do" ..i] = multi(12 + 12*i)
_G["Cs" ..i], _G["Dod" ..i],
_G["Db" ..i], _G["Df" ..i], _G["Reb" ..i] = multi(13 + 12*i)
_G["C2s"..i], _G["Do2d"..i],
_G["D" ..i], _G["Re" ..i],
_G["Ebb" ..i], _G["Eff"..i], _G["Mibb"..i] = multi(14 + 12*i)
_G["Ds" ..i], _G["Red" ..i],
_G["Eb" ..i], _G["Ef" ..i], _G["Mib" ..i] = multi(15 + 12*i)
_G["E" ..i], _G["Mi" ..i],
_G["Ff" ..i], _G["Fb" ..i], _G["Fab" ..i] = multi(16 + 12*i)
_G["Es" ..i], _G["Mid" ..i], _G["F" ..i], _G["Fa" ..i] = multi(17 + 12*i)
_G["Fs" ..i], _G["Fad" ..i],
_G["Gb" ..i], _G["Gf" ..i], _G["Solb"..i] = multi(18 + 12*i)
_G["F2s"..i], _G["Fa2d"..i], _G["G" ..i], _G["Sol" ..i] = multi(19 + 12*i)
_G["Gs" ..i], _G["Sold"..i],
_G["Ab" ..i], _G["Af" ..i], _G["Lab" ..i] = multi(20 + 12*i)
_G["A" ..i], _G["La" ..i],
_G["Bbb" ..i], _G["Bff"..i], _G["Sibb"..i] = multi(21 + 12*i)
_G["As" ..i], _G["Lad" ..i],
_G["Bb" ..i], _G["Bf" ..i], _G["Sib" ..i] = multi(22 + 12*i)
_G["B" ..i], _G["Si" ..i],
_G["Cf" ..i], _G["Cb"..i], _G["Dob" ..i] = multi(23 + 12*i)
-- Beware: Bs0 is C1
_G["Bs"..i], _G["Sid" ..i] = multi(24 + 12*i)
-- Last MIDI num is 127 (G9) but here we have some more: Bs9 is 132
end
for k, v in pairs(_G)
do
if type(k) == "string" and type(v) == "number"
then
print(k.." = "..v)
end
end
Petite étude rapide pour les dièses rares :
Pour les bémols :
Non exhaustif sans doute au niveau des justifications, mais deux doubles
altérations de chaque côté ça devrait suffire..
Idée pour la version 2, le micro-tuning avec les numéros MIDI non entiers.
Et puis de toutes façons Lua n’a qu’un type number
.
Exemple pour un B7♭9/D♯ en Ré majeur :
tonality = 2 -- Ré majeur
degree = {6, 0} -- degré VI
notes_number = 5 -- 5 sons pour aller jusqu’à la neuvième
chord_alteration = {{2, -1}} -- ♭9
chord_bass = 3 -- sur sa tierce
Il y aurait aussi un « graphe des transitions probables » à étudier.
A priori pas besoin de modes, issus de GM, MH, MM ou autres car modélisables
via le contexte harmonique si on veut donner un sens à la mélodie à partir de
l’harmonie.
Mais si les gammes sont intéressantes, c’est ici :
Au passage, selon Tagg le mode « phrygien dominant » ne correspond à rien
d’authentique. Voir Hijaz (p129).
J’en reste là pour cette section pour l’instant.
Avant le concept de groupe de notes concret (rappel : notes_group
), il y a le
concept d’arrangement (voicing
), qui aurait deux sous-types : un en
position relative, un en position absolue (la spécification d’une octave de
départ nous permettant de passer du premier au second par simple somme).
Ce sont des listes degré-octave. Par exemple :
{REL, {1, 0}, {3, 0}, {5, 0}}
{REL, {3, 0}, {5, 0}, {1, 1}}
{REL, {5, 0}, {1, 1}, {3, 1}}
S’il y a besoin d’altérer les degrés, le premier nombre de la paire peut être
une autre paire. Par exemple pour forcer une tierce mineure sur un accord
majeur : {REL, {1, 0}, {{3, -1}, 0}, {5, 0}}
.
Pour calculer les notes à jouer, plusieurs idées :
Les noms des notes n’interviennent que peu on dirait pour l’instant. Au pire
ils pourront être calculés pour information. Réfléchir davantage !
{MTC, h, m, s, f}
;{POS, bar, beat, sub_beat}
(liste de trois flottants).-- TAGS
ABS = "ABS"
REL = "REL"
HALF_REL = "HALF_REL"
MTC = "MTC"
POS = "POS"
There is a symbol for double sharp, but maybe you decided not to use it on purpose?
Following a discussion on parts and tracks on 2024-07-13
Chord event : {time, chord}
Scale event : {time, scale}
Nuance, dynamics : {time, nuance}
Nuance can be a float between 0 and 1, eventually later converted to an int between 0 and 127.
An enum-like thing could translate nuance names (piano, forte, fortissimo...) to actual values.
Main theme (melody) : {time, note, duration, (velocity?)}
Theme (if not defined globally or if interpreter wants its own theme)
Nuance (same)
Rhythm (for percussive instruments) : {time, (velocity?)}
A multi-instrument percussion has multiple rhythm tracks (eg. a drummer with kick, snare, hi-hat...)
Generic parameter : {time, value}
Any parameter that a player can interpret, eg. any CC parameter of a synth
Tracks could be accessed in a folder way. Eg. to access the kick rhythm of the drummer part: drummer.get_track({"kick", "rhythm"}).
In a more general/global implementation, each interpreter can be a folder, the conductor level being the root level:
get_track({"drummer","kick","rhythm"})
get_track({"chords"})
get_track({"guitar1","melody"})
OSC implementation would not be far away!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.