S9) Le système de hauteurs en cinq couches
De l’acteur au Hz
« Sa » n’est pas une fréquence. C’est un nom. Le chemin entre ce nom et les 261.63 Hz qui sortent du haut-parleur traverse cinq couches — chacune indépendante, chacune remplaçable.
Où se situe cet article ?
On a vu en S3 que chaque acteur a son propre resolver. Ici on ouvre le système de hauteurs pour comprendre ses cinq couches — et pourquoi elles sont séparées.
Pourquoi cinq couches ?
La plupart des systèmes musicaux informatiques traitent les hauteurs en un bloc : un nom de note → un numéro MIDI → une fréquence. Ça marche pour le piano occidental en tempérament égal (12-TET : douze demi-tons identiques). Ça atteint vite ses limites dès qu’on sort de ce cadre :
- Un sitar en 22 shruti (les micro-intervalles de la musique indienne classique) n’utilise pas les mêmes intervalles qu’un piano
- Un maqam arabe (mode mélodique arabe) a des quarts de ton que le MIDI standard ne peut pas représenter
- Un raga indien peut avoir des gammes différentes à la montée et à la descente
- Deux musiciens jouant les mêmes notes peuvent être accordés différemment
BPscript organise ces distinctions en cinq couches :
acteur → contexte (qui joue quoi, où)
alphabet → noms + altérations + registres (comment on l'écrit)
temperament → grille d'intervalles (où se placent les notes)
tuning → gamme concrète (quels degrés on utilise dans la gamme)
resolver → jeton → fréquence (ce qui produit le son)
La première couche — l’acteur — est le contexte qui lie toutes les autres. Les trois suivantes (alphabet, tempérament, tuning) sont des données culturelles et mathématiques. La dernière produit le tout.
Couche 0 — Acteur : l’unité de rattachement
Une scène BPscript peut contenir plusieurs instruments qui partagent le même alphabet. Deux sitaristes jouent les mêmes notes (sargam — le solfège indien : sa re ga ma pa dha ni) mais peuvent aller vers des sorties différentes, utiliser des accords différents, ou des conventions d’octave différentes. L’alphabet seul ne suffit pas : il manque le contexte.
L’acteur est l’unité qui lie toutes les couches de résolution ensemble :
@actor sitar1 alphabet:sargam scale:sargam_22shruti sounds:sitar_timbre transport:webaudio
@actor sitar2 alphabet:sargam scale:sargam_12TET transport:midi(ch:3)
@actor tabla alphabet:tabla_bols sounds:tabla_perc transport:midi(ch:10)
@actor lights alphabet:dmx_fixtures transport:dmx
Les propriétés disponibles de la directive @actor :
| Propriété | Obligatoire | Rôle |
|---|---|---|
alphabet |
oui | vocabulaire (noms des symboles) |
scale |
si l’acteur a des hauteurs | sélection des degrés → hauteur via tempérament |
sounds |
si percussif (sans hauteur) ou timbre spécifique | définitions par terminal (timbre, perc, échantillon) |
transport |
oui | destination de rendu |
eval |
non | clé d’évaluation pour les backticks (défaut : aucun REPL — null) |
Si scale est omis → pas de résolution de fréquence (percussions, DMX). Si sounds est omis → timbre par défaut du transport.
Le . (notation pointée) préfixe un terminal par son acteur, comme un espace de noms :
sitar1.Sa // Sa résolu via sitar1 (sargam + 22shruti + webaudio)
sitar2.Sa // même note, autre acteur (sargam + 12TET + midi ch3)
tabla.tin // tin résolu via tabla (bols + midi ch10)
Si un seul acteur contient un symbole, le préfixe est facultatif (résolution implicite). Si plusieurs acteurs partagent le symbole sans préfixe → erreur. Chaque acteur a son propre resolver : le resolver n’est pas un singleton global, c’est une instance par acteur. C’est ce qui permet à sitar1.Sa et sitar2.Sa — même nom, même octave — de produire des fréquences différentes parce que leur scale (et donc leur tempérament) diffère.
Couche 1 — Alphabet : noms, altérations et registres
L’alphabet définit une séquence ordonnée de noms, les altérations disponibles, et la convention de registre (octaves). Les noms et altérations sont purement nominaux — pas de fréquence, pas de MIDI, pas de ratio. La convention de registre, elle, dit seulement comment s’écrivent les notes — chaque alphabet choisit la sienne (western → registres western, sargam → registres saptak).
{
"western": {
"notes": ["C", "D", "E", "F", "G", "A", "B"],
"alterations": ["bb", "b", "", "#", "##"]
},
"sargam": {
"notes": ["sa", "re", "ga", "ma", "pa", "dha", "ni"],
"alterations": ["", "komal", "tivra"]
}
}
La position dans la liste est l’index (degré) : C = degré 0, D = degré 1, etc.
Chaque tradition a ses propres conventions d’altérations :
| Tradition | Altérations |
|---|---|
| Occidentale | bb, b, #, ## |
| Sargam (Inde) | komal (bémol), tivra (dièse) |
| Arabe | bb, b, half_b, half_#, #, ## |
| Turque | bakiye, kucuk_mucenneb, buyuk_mucenneb |
Les registres (octaves)
Comment nommer les registres (octaves) ? La convention fait partie de l’alphabet — chaque tradition a la sienne :
{
"western": {
"position": "suffix",
"separator": "",
"registers": ["0","1","2","3","4","5","6","7","8","9"],
"default": 4
},
"saptak": {
"position": "suffix",
"separator": "_",
"registers": ["v", "", "^"],
"default": 1
}
}
position:"prefix"ou"suffix"— le registre vient avant ou après la noteseparator: caractère entre note et registre (""= collé,"_"= underscore)registers: liste ordonnée grave→aigu,""= pas de marqueur (registre par défaut)default: index du registre central (celui qui sert de référence)
Exemples de résolution :
- Western :
C4→ noteC, registre index 4 - Saptak :
Sa_^→ noteSa, registre index 2 (taar saptak) - Saptak :
Sa→ noteSa, registre index 1 (madhya, par défaut —""dans la liste)
Couche 2 — Tempérament : la grille mathématique
Le tempérament définit la grille d’intervalles — une division de l’espace des fréquences. Il est indépendant de tout alphabet ou gamme.
Type « table » — ratios fixes
{
"12TET": {
"period_ratio": 2,
"divisions": 12,
"ratios": ["0c", "100c", "200c", "300c", "400c", "500c",
"600c", "700c", "800c", "900c", "1000c", "1100c"]
},
"22shruti": {
"period_ratio": 2,
"divisions": 22,
"ratios": [1, "256/243", "16/15", "10/9", "9/8", "32/27", "6/5", "5/4",
"81/64", "4/3", "27/20", "45/32", "729/512", "3/2", "128/81",
"8/5", "5/3", "27/16", "16/9", "9/5", "15/8", "243/128"]
}
}
period_ratio: l’intervalle qui se répète (2 = octave, 3 = tritave pour Bohlen-Pierce)divisions: nombre de pas dans la périoderatios: le ratio de chaque pas — 3 formats acceptés :
| Format | Usage | Exemple | Précision |
|---|---|---|---|
| Fraction | Intonation juste, shruti, pythagoricien | "9/8" |
Exacte (rationnels) |
| Décimal | Gamelan, systèmes mesurés | 1.05946 |
Approximation |
| Cents | Tempéraments égaux (12-TET, 24-TET) | "100c" |
Convertie en irrationnel |
Le resolver normalise tout en float au chargement. Un seul chemin de calcul ensuite.
Type « parametric » — Dynamic Tonality
Inspiré de la Dynamic Tonality (Milne, Sethares, Plamondon). Au lieu de ratios fixes, le tempérament est défini par un period et un generator dont la taille peut varier continûment :
{
"meantone": {
"type": "parametric",
"period": 1200,
"generator": 697,
"generator_range": [685, 720],
"mapping": [[1,0], [1,1], [0,4]],
"primes": [2, 3, 5],
"commas": ["81/80"]
}
}
En faisant varier le generator de 685 à 720 cents, on traverse un continuum de tempéraments :
| Generator | Tempérament | Caractère |
|---|---|---|
| 694.7¢ | 2/7-comma meantone | Très doux |
| 697¢ | 1/4-comma meantone | Classique |
| 700¢ | 12-TET | Égal |
| 702¢ | Pythagoricien | Brillant |
Tous partagent le même mapping (tierce = 4g-2P, quinte = g). Seule la couleur change.
Le generator est un CV — il peut varier dans le temps via la polymétrie (S5) :
// Morphe du pythagoricien au mésotonique en temps réel
S -> { Sa Re Ga Pa , sitar.tuning.generator(ramp(702, 697)) }
Toutes les fréquences changent simultanément — la structure de la gamme reste, seul le tempérament bouge.
Couche 3 — Tuning : la gamme concrète
Le tuning fait le pont entre les noms (alphabet) et les positions (tempérament) :
{
"Cmaj_just": {
"temperament": "just_5limit",
"degrees": [0, 2, 4, 5, 7, 9, 11],
"alterations": { "#": "25/24", "b": "24/25" },
"baseHz": 440,
"baseNote": "A",
"baseRegister": 4
}
}
degrees: quels pas du tempérament sont utilisés, dans l’ordre de l’alphabetalterations: les altérations, chiffrées de trois façons (voir ci-dessous)baseHz/baseNote/baseRegister: le point de référence
Trois façons de chiffrer une altération
Une altération (#, komal, half_b…) est un décalage appliqué à un degré. Selon le système, on la chiffre de trois manières — toutes ramenées à un rapport de fréquence au chargement :
| Façon | Exemple | Quand |
|---|---|---|
| ratio | "#": "25/24" |
intonation juste : le ½-ton n’est pas un degré, il faut un rapport exact |
| cents | "half_b": "-50c" |
microtonal mesuré : le quart de ton arabe = −50 cents |
| degrés | "#": "+1" |
grille égale : le ½-ton est un degré, on décale d’un pas (ton = 2 degrés) |
C’est exactement la différence diatonique / chromatique :
// Diatonique juste — 7 degrés ; le # n'est PAS un degré → ratio
"Cmaj_just": { "degrees": [0,2,4,5,7,9,11], "alterations": { "#": "25/24" } }
// Chromatique égal — 12 degrés ; le # EST déjà un degré → décalage de pas
"chromatic_12tet": { "degrees": [0,1,2,3,4,5,6,7,8,9,10,11], "alterations": { "#": "+1" } }
En diatonique, C# se calcule (C × 25/24) car la gamme ne contient pas ce ½-ton. En chromatique, C# est simplement le degré suivant. Le ratio reste indispensable dès qu’on quitte la grille égale : 25/24 n’est ni un pas entier ni une fraction propre d’octave dans un système inégal.
Gammes composées — tétracordes et jins
Dans les traditions arabe, turque et grecque, les gammes sont construites par empilement de fragments (tétracordes = 4 notes couvrant une quarte) :
{
"maqam_rast": {
"compose": ["jins_rast", "jins_rast"],
"junction": "3/2",
"description": "Maqam Rast = Rast + Rast sur la quinte"
}
}
Le resolver empile les fragments au chargement → produit un tableau de degrés comme un tuning normal.
Gammes directionnelles — aroha et avaroha
Dans la musique indienne, certains ragas ont des gammes différentes à la montée et à la descente :
{
"bhairav": {
"temperament": "22shruti",
"ascending": [0, 2, 7, 9, 13, 15, 20],
"descending": [0, 4, 7, 9, 13, 17, 20],
"baseHz": 240,
"baseNote": "sa",
"description": "Raga Bhairav — aroha et avaroha différents"
}
}
Quand ascending et descending sont présents (au lieu de degrees), le resolver choisit selon la direction mélodique — déterminée par le contexte (note précédente vs courante).
Couche 4 — Resolver : jeton → fréquence
Le resolver est le composant runtime qui assemble les couches précédentes. Il y a un resolver par acteur (S3) — pas un singleton global. C’est l’acteur (couche 0) qui lui fournit son alphabet (registres compris), son tuning et son tempérament.
Le chemin de résolution :
"Sa_^" (jeton brut)
→ analyse : note="sa", registre="^" (index 2)
→ recherche alphabet : sa = degré 0
→ tuning : degré 0 → pas 0 du tempérament
→ tempérament : pas 0 → ratio 1/1
→ octave : register 2 - default 1 = +1 octave → ratio × 2
→ baseHz : 240 × 1 × 2 = 480 Hz
Même jeton, deux acteurs, deux résultats :
Sa_^viasitar1(22 shruti, base 240) → 480 HzSa_^viasitar2(12-TET, base 261.63) → 523.25 Hz
La transposition : pourquoi c’est compliqué
Un point musicologique fondamental qui justifie cette architecture : la transposition ne fonctionne pas de la même façon dans tous les systèmes.
En tempérament égal (12-TET), transposer = décaler d’un nombre de demi-tons. Simple. Mais :
- En intonation juste, les pas ne sont pas tous égaux : décaler la mélodie sur la grille déforme les intervalles. Transposer Do majeur en Ré en ajoutant un ton à chaque note fait passer la tierce majeure de
5/4(juste, 386 c) à81/64(pythagoricienne, 408 c) — le comma syntonique apparaît. (C’est la même inégalité des pas qui fait queC#etDbn’y ont pas la même fréquence.) - En 22 shruti : même problème, en pire. « Monter d’un pas » change l’intervalle selon la position.
- Solution : plutôt que de compter des pas, on change la tonique (la note de référence) en préservant les intervalles.
BPscript gère ça en séparant tonique (tuning, baseNote/baseHz) et grille (tempérament, ratios). Changer la tonique = changer le tuning, pas le tempérament. Les détails sont dans l’annexe transposition de PITCH.md, développée dans S15.
Ce qu’il faut retenir
- Cinq couches : acteur → alphabet → tempérament → tuning → resolver
- Acteur = contexte de rattachement (alphabet + scale + sounds + transport) — un resolver par acteur
- Alphabet = la notation — noms + altérations + convention de registre (octaves), zéro fréquence ; chaque alphabet choisit ses registres
- Tempérament = grille mathématique — ratios en fractions, décimal ou cents
- Tuning = gamme concrète — degrés + altérations + référence Hz
- Gammes composées (tétracordes/jins) et directionnelles (aroha/avaroha)
- Dynamic Tonality : le generator du tempérament peut varier comme un CV — morph de tempérament en temps réel
Pour aller plus loin
- Milne, A., Sethares, W. & Plamondon, J. (2007) : « Isomorphic controllers and dynamic tuning » — les fondements de la Dynamic Tonality
- Asselin, P.-Y. (1985) : Musique et tempérament — référence francophone sur les systèmes d’accord historiques
- Sethares, W. (2005) : Tuning, Timbre, Spectrum, Scale — le couplage timbre-tuning (spectral matching)
Glossaire
- Acteur : Unité de rattachement qui lie alphabet + scale + sounds + transport — porte un resolver dédié
- Alphabet : Séquence ordonnée de noms de notes + altérations disponibles — purement nominal
- Octaves : Convention de nommage des registres (position, séparateur, liste grave→aigu)
- Tempérament : Grille mathématique d’intervalles — division de l’espace fréquentiel en pas
- Tuning : Gamme concrète = quels pas du tempérament utiliser + fréquence de référence
- Resolver : Instance (1 par acteur) qui traduit un jeton en fréquence en traversant les cinq couches
- Dynamic Tonality : Tempérament paramétrique dont le generator peut varier continûment
- Tétracorde/Jins : Fragment de 4 notes couvrant une quarte — brique de base des gammes arabes et turques
- Aroha/Avaroha : Gamme ascendante/descendante d’un raga indien — peuvent être différentes
- Cents : Unité logarithmique d’intervalle — 1200 cents = 1 octave, 100 cents = 1 demi-ton en 12-TET
- MOS (Moment of Symmetry) : Gamme générée par un seul intervalle (generator) réduit dans une période
Liens dans la série
- S3 — Types, acteurs et rattachements — chaque acteur a son propre resolver
- S5 — Structurer le temps — le generator comme CV dans la polymétrie
- S10 — Le pipeline — comment les cinq couches sont chargées et résolues
- S15 — La transposition au-delà du tempérament égal
Prérequis : S3
Temps de lecture : 16 min
Tags : #BPscript #pitch #tempérament #tuning #alphabet #intonation
Prochain article : S10 — Sous le capot : compilateur, moteur et dispatcher