Giter Site home page Giter Site logo

luamuse's People

Contributors

bubblesly avatar

Stargazers

neo451 avatar Prof Gra avatar

Watchers

Prof Gra avatar  avatar

Forkers

odoare grahack

luamuse's Issues

Idées «éléphant dans le magasin de porcelaine»

Salut,

Voici le résultat de ma réflexion de ces dernières 48h.

Une modélisation informatique de la musique

Conventions dans le document

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 ?

Se repérer dans le temps

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 :

  • le tempo (bpm), 120 par défaut ;
  • la carrure (meter) qui, pour simplifier dans un premier temps, serait
    le nombre de temps par mesure, 4 par défaut (valeur qui peut être un
    float) ;
  • le numéro de mesure (bar_num), de 1 à l’infini ;
  • le numéro de temps (beat_num), de 1 à meter ;
  • le sous-temps (sub_beat) de 1 à 120 (=2.2.2.3.5),
    là je suis sûr ni du nom ni du 120.

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 :

  • « maintenant !!! »
  • de façon absolue (abs), ex : « contretemps du troisième temps de la
    dixième mesure » aka {ABS, 10, 3, 61} ;
  • de façon relative (rel), ex : « dans exactement trois mesures et deux
    temps » aka {REL, 3, 2, 0} ;
  • de façon semi-relative (half_rel), ex: « au prochain contretemps »
    aka {HALF_REL, 0, 0, 60}.

Contexte harmonique

Parti pris tertial

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 ».

Modélisation

Pour pouvoir se repérer dans l’harmonie, l’état du système serait constitué de
ces valeurs :

  • la tonalité courante (tonality), valant par défaut 0 et représentant
    le nombre de dièses à la clef ;
  • le degré courant (degree), c’est-à-dire les célèbres chiffres romains,
    avec une altération, par défaut {1, 0} (♭VI serait {6, -1}) ;
  • le nombre de notes (notes_number), par défaut 3 ;
  • l’altération de l’accord (chord_alteration) ;
  • la basse de l’accord (chord_bass).

Pour l’altération, deux façons de voir, non exclusives :

  • une liste de listes de deux entiers, donnant les degrés à modifier en
    demi-tons, modifs à réaliser toujours à partir des intervalles de la gamme
    majeure (pratique pour les accords 7) ;
  • une liste de strings, dont chacune correspond à une altération à
    appliquer :
    • "maj" pour « majorisation » (ex : VIm7 -> VI7 ou tierce picarde),
      correspond à {3, 1} dans la première façon de voir ;
    • "min" pour « minorisation » (ex : IV -> IVm),
      correspond à {3, -1} ;
    • "sus2" et "sus4" pour les suspensions, qui n’auraient en fait
      aucun effet puisque ça serait plutôt géré avec le choix des notes à
      jouer (voir plus loin) ;
    • notes additionnelles « in » ("6", "add9", …) : idem ;
    • notes additionnelles « out » :
      • "f5", "b5" ou "♭5" pour {5, -1} ;
      • "s5", "d5" ou "♯5" pour {5, 1} (au passage pour moi c’est
        souvent plutôt ♭13) ;
      • "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} ;
  • … (voir la liste des accords du Real Book pour être sûrs de tout couvrir).

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.

Évènements sans notes

Ce sont des événements ponctuels, sans durée.

  • transport du séquenceur, dans le MTC ou changement de position ;
  • changement de carrure ;
  • changement de tempo
    • absolu (abs),
    • relatif addtif (rel_plus),
    • relatif multiplicatif (rel_times) ;
  • modulation métrique (metric_mod), combinaison des deux précédents ;
  • changement du degré et du nombre de notes, de l’altération de
    l’accord
     ;
  • modulation
    • surtout « de majeur à majeur »,
    • mais aussi d’autres (donc combinaison « maj à maj » et changement de
      degré).

Quelques exemples de modulations :

  • tout monter d’un ton (tonality += 2)
  • passer sur le relatif mineur (degree = {6, 0})
  • passer sur le parallèle mineur (tonality -= 3; degree = {6, 0})

Du son !

Un instrument (instrument) joue un (ou plusieurs) groupe
(notes_group) de notes (note) à une position donnée, avec une
certaine durée (duration).

Instrument

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) :

  • mélodie (melody), souvent une seule note mais parfois plusieurs ;
  • accords (chord), souvent plusieurs notes ;
  • basse (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}

Notes, noms de notes et numéros MIDI

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 :

  • E# en F# majeur, et en F#m car C#7 (le V7) a un E#
  • B# en C#m car G#7 (le V7) a un B# (chuis pas hyper pour le C# majeur)
  • 2# en G#m car D#7 (le V7) a un Fx
  • D#m c’est plutôt Ebm, sinon le V7 est A#7 et a donc un Cx, mais pourquoi pas

Pour les bémols :

  • Cb en Gb majeur
  • Fb pour Gb7 qui peut apparaître
  • doubles bémols possibles avec les b9 des accords 7b9 ayant une seconde déjà
    altérée avec un b, soit dans les tonalités ayant une sixte avec un b : Réb
    et Solb, donc Sibb et Mibb.

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.

Basse et accords

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.

Mélodie

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 :

  • soit pour pour « forcer » ces sonorités sur un contexte harmonique pas
    forcément adapté,
  • soit pour juste presser le citron de la connaissance (faire écouter à
    l’utilisateur ou permettre au système de reconnaître des modes).

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.

Groupes de notes

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 :

  • triade 135 (position fondamentale) : {REL, {1, 0}, {3, 0}, {5, 0}}
  • triade 351 (premier renversement) : {REL, {3, 0}, {5, 0}, {1, 1}}
  • triade 513 (second renversement) : {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 :

  • on donne l’arrangement absolu (ou on le calcule à partir de
    l’arrangement relatif) et on utilise l’accord courant pour obtenir les
    notes,
  • on calculé sur notes précédents (état de l’instrument) pour faire de la
    conduite de voix.

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 !

Durée

  • en MTC : {MTC, h, m, s, f} ;
  • en position : {POS, bar, beat, sub_beat} (liste de trois flottants).

TODO, docs ou divers trucs à trier

TODO

  • Anticipations et retards (jouer des notes qui se basent sur le contexte
    harmonique suivant ou précédent, par exemple la walking bass qui anticipe
    souvent d’une noire)
  • Section « Mélodie »

Tags pour sous-types

-- TAGS
ABS = "ABS"
REL = "REL"
HALF_REL = "HALF_REL"
MTC = "MTC"
POS = "POS"

Docs externes

Double sharp

There is a symbol for double sharp, but maybe you decided not to use it on purpose?

Parts and track ideas

Following a discussion on parts and tracks on 2024-07-13

Part

Properties

  • Tempo
  • Time signature
  • Number of Bars

Tracks : tables of events of unique type (one track per type)

Main tracks (defined by the main conductor)

  • Chord event : {time, chord}

  • Scale event : {time, scale}

Optional main tracks

  • 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?)}

Tracks defined at the interpreter level

  • 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

Proposal for accessing tracks

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!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.