Song of the Grid | Documentation
Générateur de musique algorithmique · WebAudio API · JavaScript
Inspiré de « Six Techniques for Algorithmic Music Composition », Peter Langston, 1989.
Table des matières
- Vue d'ensemble
- Les algorithmes
- Synthèse sonore
- Guide des paramètres
- Architecture technique
- Combinaisons et recettes
- Références
1. Vue d'ensemble
Ce projet est un moteur de composition musicale générative fonctionnant entièrement dans le navigateur (aucune dépendance, aucun serveur). La musique est produite en temps réel par la Web Audio API, pilotée par plusieurs couches algorithmiques imbriquées.
L'architecture est hiérarchique, comme dans le système Fun de Langston :
Section (ex. THÈME A)
└── Progression d'accords (ex. I–IV–V–I)
└── Rythme Euclidien (ex. E(3,8))
└── Note (degré de gamme via chaîne de Markov)
Trois voix indépendantes sont générées simultanément :
| Voix | Timbre | Rôle |
|---|---|---|
| Mélodie | Oscillateur (forme d'onde choisie) + filtre | Ligne mélodique principale |
| Basse | Sinusoïde + harmonique | Fondamentale + quinte en alternance |
| Séquenceur Volca | Dent de scie + filtre résonant | Arpège rythmique, style Korg Volca Keys |
Une couche de percussions (kick + hihat) est ajoutée automatiquement.
2. Les algorithmes
Technique 1 : Tables stochastiques
Langston utilisait des tables de lookup comme squelettes musicaux : progressions d'accords, patterns rythmiques, palettes de notes. Dans ce projet :
- 9 gammes prédéfinies (pentatonique, modes grecs, chromatique, tons entiers)
- Progressions d'accords par gamme (ex. I–IV–V–I, I–vi–IV–V)
- Arpèges Volca : à chaque changement d'accord, une palette de tons (fondamentale + tierce + quinte ± degrés additionnels selon la complexité) est générée et triée selon un mode tiré au sort (montant, descendant, aléatoire)
Technique 2 : Chaînes de Markov
La mélodie est générée note à note par une chaîne de Markov dont l'état est le degré courant dans la gamme.
Matrice de transition (implicite) pour chaque degré courant d, les poids sont calculés ainsi :
Distance à d |
Poids de base | Commentaire |
|---|---|---|
| 0 (même note) | 0.07 | Répétition rare |
| 1 (demi-ton/ton) | 0.36 | Mouvement conjoint favorisé |
| 2 degrés | 0.24 | Tierce, courant |
| 3 degrés | 0.12 × complexité | Saut modéré |
| > 3 degrés | 0.06 × cx / distance | Grands sauts rares |
Modulations du comportement :
- Gravité harmonique : les tons de l'accord courant reçoivent un bonus ×1.6, ce qui ancre la mélodie harmoniquement sans la contraindre
- Gravité de registre : si la mélodie monte trop haut ou trop bas, un poids supplémentaire la ramène vers le centre
- Désaccordage : aplatit la distribution (les sauts atypiques deviennent plus probables) et déclenche des intrusions chromatiques (notes hors gamme)
Technique 3 : Réseaux de transitions
La macro-structure de la composition suit un automate probabiliste à 5 états :
┌──────────────────────────────┐
│ │
INTRO ──(0.9)──► THÈME A ──(0.5)──► THÈME B │
└──(0.1)──► PONT ▲ │ │ │
│ │ └─(0.3)──►┤ │
│ └─────────────────►│ │
│ PONT │
│ │ │
└─────────────────►OUTRO ────────┘
└──(0.55)──► INTRO
Chaque section définit :
- Durée en mesures (
bars) - Densité mélodique et basse (
mDens,bDens) : probabilité de jouer à chaque step actif - Transitions vers les sections suivantes avec leurs probabilités
Le changement de section déclenche une nouvelle progression d'accords et un renouvellement du pool d'arpège Volca.
Rythmes Euclidiens (Toussaint, 2005)
L'algorithme euclidien distribue k frappes sur n pas de la façon la plus régulière possible (distance maximale entre les temps). Il est basé sur l'algorithme de Bresenham / Bjorklund.
Implémentation :
function euclid(k, n, rot) {
const base = new Array(n).fill(0);
for (let i = 0; i < k; i++) base[Math.floor(i * n / k)] = 1;
const rotated = [...base.slice(rot), ...base.slice(0, rot)];
return Array.from({length: 16}, (_, i) => rotated[i % n]); // tile sur 16 pas
}
Le résultat est dupliqué (tiled) pour remplir les 16 pas du séquenceur. Une rotation décale le point de départ du pattern, permettant de créer des polyrhythmies en désalignant les trois voix.
Patterns classiques :
| Notation | Pattern (8 pas) | Nom traditionnel |
|---|---|---|
| E(2,8) | 1 0 0 0 1 0 0 0 |
Temps forts |
| E(3,8) | 1 0 0 1 0 0 1 0 |
Tresillo cubain |
| E(5,8) | 1 0 1 1 0 1 1 0 |
Cinquillo |
| E(7,8) | 1 0 1 1 1 1 1 1 |
Très dense |
| E(7,16) | 1 0 0 1 0 1 0 0 1 0 1 0 0 1 0 0 |
Bembé |
3. Synthèse sonore
Tout le son est produit via la Web Audio API, sans samples, sans bibliothèque.
Chaîne de signal
Voix → GainEnveloppe → Filtre → GainVoix ─┬─► GainSec (dry) ──┐
└─► Convolver (reverb) ──► GainHumide ──┤
└─► Compresseur → GainMaître → Analyser → Destination
Voix Mélodie
- Oscillateur : forme d'onde sélectionnable (triangle, sinusoïde, dent de scie, carré)
- Bruit FM : si
noiseAmt > 0, des valeurs de detune aléatoires sont schedulées toutes les 28 ms sur la durée de la note, la hauteur "tremble" de façon continue (random walk) - Bruit spectral : au-dessus de 15% de bruit, un buffer de bruit blanc bouclé est filtré en passe-bande autour de la fréquence de la note et mixé discrètement → texture granuleuse/soufflée
- Enveloppe ADSR : attaque rapide (16 ms), decay (70 ms), sustain ~75%, release variable selon le gate
Voix Basse
- Deux oscillateurs : sinusoïde (fondamentale) + triangle (octave +1, gain ×0.20) pour enrichir le timbre
- Filtre passe-bas fixe (520 Hz, Q=0.5)
- Alternance root/quinte : toutes les demi-phrases, la basse passe du degré fondamental au degré de quinte
Séquenceur Volca
- Oscillateur dent de scie avec légère instabilité de detune (analogique)
- Filtre LP résonant avec enveloppe : le filtre part très bas, monte en attaque rapide (12 ms), puis redescend, c'est cet enveloppage du filtre qui crée le son "boing" caractéristique du Volca Keys
- Gate court (contrôlable) → notes staccato
Percussions
- Kick : oscillateur sinusoïde avec chute rapide de fréquence (155 Hz → 38 Hz en 90 ms) + enveloppe d'amplitude rapide
- Hihat : buffer de bruit blanc court, filtré en passe-haut (9500 Hz fermé / 6800 Hz ouvert), avec enveloppe très courte
Réverbération
Convolution sur une réponse impulsionnelle synthétique générée au démarrage :
// Bruit coloré décroissant exponentiellement
data[i] = (Math.random() * 2 - 1) * Math.pow(1 - i/length, decay);
Durée : 2.8 s, decay : 2.4. Le ratio wet/dry est contrôlable en temps réel.
4. Guide des paramètres
Structure
| Paramètre | Plage | Effet |
|---|---|---|
| Tempo | 50–220 BPM | Vitesse du séquenceur. Affecte toutes les durées de notes et gates proportionnellement |
| Tonalité | C à B | Note fondamentale (MIDI 60–71). Tous les calculs de gamme et d'accords sont relatifs à cette note |
| Gamme / Mode | 9 options | Ensemble d'intervalles utilisé pour la mélodie, la basse et le Volca |
| Complexité | 1–10 | Affecte : amplitude des sauts dans la chaîne de Markov, richesse de la palette d'arpège Volca, volume des hihat |
Gammes disponibles :
| Gamme | Intervalles (demi-tons) | Caractère |
|---|---|---|
| Pentatonique majeure | 0 2 4 7 9 | Clair, ouvert, universel |
| Pentatonique mineure | 0 3 5 7 10 | Bluesy, mélancolique |
| Majeure (Ionien) | 0 2 4 5 7 9 11 | Classique, lumineux |
| Dorien | 0 2 3 5 7 9 10 | Jazz, folk, ambigu |
| Mixolydien | 0 2 4 5 7 9 10 | Rock, modal, dynamique |
| Mineure naturelle | 0 2 3 5 7 8 10 | Sombre, expressif |
| Lydien | 0 2 4 6 7 9 11 | Onirique, suspendu |
| Chromatique | 0 1 2 … 11 | Atonal, expérimental |
| Tons entiers | 0 2 4 6 8 10 | Debussy, flottant |
Mélodie
| Paramètre | Plage | Effet |
|---|---|---|
| Forme d'onde | triangle / sinus / dent de scie / carré | Timbre de l'oscillateur principal. Triangle = chaud, doux. Sinus = pur, épuré. Dent de scie = brillant, riche en harmoniques. Carré = nasillard, rétro |
| Bruit / instabilité | 0–100% | Jusqu'à 15% : instabilité de hauteur (FM noise). Au-delà : ajout de bruit spectral filtré autour de la note. À 100% : le son devient presque entièrement bruité |
| Désaccordage | 0–100% | Aplatit la distribution de Markov (sauts atypiques plus fréquents) + déclenche des intrusions chromatiques + déstabilise l'accordage du Volca. À 100% : musique proche de l'atonalité |
| Gate mélodie | 5–100% | Durée des notes mélodiques. 5% = ultra-staccato, 100% = notes tenues (legato possible si tempo lent) |
Séquenceur Volca
| Paramètre | Plage | Effet |
|---|---|---|
| Cutoff filtre | 80–8000 Hz | Fréquence de coupure cible du filtre LP résonant. Bas = son sombre et rond. Haut = son brillant et ouvert. L'enveloppe du filtre part toujours de cutoff × 6% et descend jusqu'à cutoff × 18% |
| Résonance (Q) | 1–22 | Résonance du filtre. En dessous de 4 : filtre naturel. 6–12 : coloration prononcée. Au-dessus de 15 : auto-oscillation possible |
| Gate séquenceur | 5–95% | Durée des notes Volca (staccato court ↔ tenu). 10–30% recommandé pour l'effet Volca Keys |
| Densité | 10–100% | Probabilité de jouer une note à chaque step actif (défini par l'Euclidien). Combiné avec la densité de section, permet des textures éparpillées |
Rythmes Euclidiens
Chaque voix (Mélodie, Basse, Volca) possède son propre pattern euclidien indépendant.
| Paramètre | Plage | Effet |
|---|---|---|
| k — frappes | 0–n | Nombre de temps actifs dans le cycle. 0 = silence total. Augmenter k densifie le rythme |
| n — pas | 2–16 | Longueur du cycle de base. Le pattern est dupliqué (tiled) pour remplir les 16 pas |
| Rotation | 0–n-1 | Décalage du point de départ dans le cycle. Permet de créer des polyrhythmies en désalignant les voix |
La visualisation en points (ligne de 16 cercles) montre le pattern résultant après tiling, avec des espaces toutes les 4 cases. Les cases grises dans la grille principale indiquent les steps euclidiens actifs.
Astuce polyrhythmie : avec trois voix ayant des n différents (ex. 8, 12, 16), on obtient des cycles qui se combinent et se déphasent, la musique évolue lentement sans jamais se répéter exactement.
Mix
| Paramètre | Plage | Effet |
|---|---|---|
| Réverbération | 0–100% | Ratio wet/dry de la convolution. 0% = son sec. Haut = espace large, brouille la clarté rythmique |
| Swing | 0–66% | Décale les doubles-croches impaires en avant. 0% = mécanique. 30–40% = groove humain. 66% = triolet (jazz, hip-hop) |
5. Architecture technique
Scheduler (Two Clocks Pattern)
Le scheduling s'appuie sur le pattern A Tale of Two Clocks de Chris Wilson (Google, 2013) :
setTimeout(22 ms de lookahead) appelle régulièrement le scheduler- Le scheduler avance tant que
nextNoteTime < audioContext.currentTime + 0.115 s - Les notes sont schedulées avec les méthodes AudioParam précises (
setValueAtTime,linearRampToValueAtTime, etc.) - La mise à jour visuelle est déclenchée via un
setTimeoutdifféré de(noteTime - currentTime) * 1000ms
Ce découplage entre horloge visuelle (JS/DOM) et horloge audio (AudioContext) garantit une précision temporelle de l'ordre de la milliseconde, indépendamment des jank du rendu.
Gestion de la mémoire
Chaque note crée des OscillatorNode et GainNode qui sont détruits automatiquement par le GC après node.stop(). Les buffers de bruit sont de courte durée (max 4096 échantillons en boucle) pour limiter l'allocation. Le buffer de réverbération (2.8 s × 2 canaux × 44100 Hz ≈ 2.4 Mo) est créé une seule fois au démarrage.
Fichiers
peter_langston/
├── index.html ← Application principale (HTML + CSS + JS, tout-en-un)
└── DOCUMENTATION.md ← Ce fichier
6. Combinaisons et recettes
Minimal / Ambient
- Gamme : Pentatonique majeure ou Lydien
- Complexité : 2–3
- Bruit : 0%, Désaccordage : 0%
- Euclidien : Mélodie
E(2,8), BasseE(1,4), VolcaE(3,16) - Gate mélodie : 70–100% (notes longues)
- Réverb : 60–80%, Swing : 0%
- Cutoff Volca : 400–600 Hz, Réso : 3–5
Polyrythme afro-cubain
- Gamme : Pentatonique mineure ou Dorien
- Complexité : 6–7
- Euclidien : Mélodie
E(3,8), BasseE(2,8, rot=4), VolcaE(5,8, rot=2) - Gate mélodie : 40–50%
- Swing : 15–25%
- Cutoff Volca : 1200–2000 Hz, Réso : 5–8
Séquenceur industriel / techno
- Gamme : Mineure naturelle ou Chromatique
- Complexité : 7–9
- Bruit : 10–20%, Désaccordage : 15–30%
- Euclidien : Mélodie
E(5,16), BasseE(4,16), VolcaE(11,16, rot=3) - Gate séquenceur : 8–15% (ultra-staccato)
- Cutoff Volca : 3000–6000 Hz, Réso : 12–18
- Swing : 0% (mécanique)
Expérimental / Noise
- Gamme : Chromatique ou Tons entiers
- Complexité : 9–10
- Bruit : 60–100%, Désaccordage : 70–100%
- Forme d'onde : Carré ou Dent de scie
- Euclidien : densités élevées (
E(13,16)sur le Volca) - Résonance Volca : 18–22
- Réverb : 50%
Bembé (polyrhythmie africaine)
- Euclidien : Mélodie
E(7,16), BasseE(3,16, rot=0), VolcaE(7,16, rot=3) - Complexité : 5–6
- Gamme : Dorien ou Pentatonique mineure
- Swing : 10–20%
7. Références
- Peter Langston — Six Techniques for Algorithmic Music Composition, USENIX 1989 Technical Conference Proceedings
- Peter Langston — Little Music Language, Bell Labs, 1985
- Godfried T. Toussaint — The Euclidean Algorithm Generates Traditional Musical Rhythms, BRIDGES 2005
- Chris Wilson — A Tale of Two Clocks: Scheduling Web Audio with Precision, Google I/O 2013 / Web Dev blog
- Web Audio API Specification — W3C, webaudio.github.io
- Bjorklund, E. — The Theory of Rep-Rate Pattern Generation in the SNS Timing System, 2003 (origine de l'algorithme appliqué aux rythmes par Toussaint)