Cours Faust INSA 04/02/2026
Objectif
L’objectif de ce cours de 2h est de vous initier à la lutherie numérique et à Faust, un langage de programmation fonctionnel spécialisé dans la synthèse et le traitement audio temps-réel.
Exemples réalisés avec Faust
- ExpressiveE https://www.expressivee.com/
- Powered by Faust https://faust.grame.fr/community/powered-by-faust/
Le Faust IDE
Durant cet atelier, nous allons utiliser un outil en ligne, le Faust IDE, qui va nous permettre d’écrire et de faire fonctionner nos programmes Faust directement dans un navigateur web. Pour accéder à cet outil, il suffit d’ouvrir la page https://faustide.grame.fr depuis son navigateur.
Faust en quelques slides
Les slides sont disponibles ici
Karplus et Strong : étape 1
L’instrument Kisana va nous permettre de découvrir une autre technique de synthèse sonore, l’algorithme de Karplus et Strong, le plus simple des modèles physiques.
On commence par un générateur de bruit blanc (un générateur de nombres pseudo-aléatoires entre -1 et 1) :
// Générateur de bruit blanc avec contrôle de volume
import("stdfaust.lib");
// Paramètre de volume (de 0.0 à 1.0)
volume = hslider("Volume", 0, 0.0, 1.0, 0.01);
// Générateur de bruit blanc
white_noise = no.noise;
// Application du volume
process = white_noise * volume;
Karplus et Strong : étape 2
On ajoute un résonateur :
// Générateur de bruit blanc avec contrôle de volume
import("stdfaust.lib");
// Paramètre de volume (de 0.0 à 1.0)
volume = hslider("Volume", 0, 0.0, 1.0, 0.01);
// Générateur de bruit blanc
white_noise = no.noise;
// Application du volume
process = white_noise * volume : resonateur;
// résonateur
resonateur = + ~ (@(43) <: _, mem :> *(0.4999));
Karplus et Strong : étape 3
On simule une corde :
import("stdfaust.lib");
process = button("gate")
: string(0.5, hslider("freq", 440, 100, 8000,1), 4, hslider("gain", 0.1, 0, 1, 0.01));
string(coef, freq, t60, level, trig) = noise*level
: *(trig : trigger(freq2samples(freq)))
: resonator(freq2samples(freq), att)
with {
resonator(d,a) = (+ : @(d-1)) ~ (average : *(a));
average(x) = (x*(1+coef)+x'*(1-coef))/2;
trigger(n) = upfront : + ~ decay(n) : >(0.0);
upfront(x) = (x-x') > 0.0;
decay(n,x) = x - (x>0.0)/n;
freq2samples(f) = ma.SR/f;
att = pow(0.001,1.0/(freq*t60)); // attenuation coefficient
random = +(12345)~*(1103515245);
noise = random/2147483647.0;
};
Intermezzo
Description algorithmique de circuits, l’exemple de la FFT
import("stdfaust.lib");
process = fft(1);
fft(N) = an.c_bit_reverse_shuffle(N) : fftb(N) // shuffle off to the butterflies:
with {
fftb(1) = _,_; // each complex number is represented as (real,imag)
fftb(N) = (fftb(N/2) <: (si.cbus(N))),
(fftb(N/2) <: (twiddleOdd(N))) :> si.cbus(N)
with {
twiddleOdd(N) = par(k,N,si.cmul(cos(w(k)),0-sin(w(k))));
w(k) = 2.0*ma.PI*float(k)/float(N);
};
};
Kisana, un instrument basé sur Karplus et Strong
On fait un gros saut en avant et on crée KISANA, un instrument avec deux « cordes » sur lesquelles on peut jouer :
//-----------------------------------------------
// Kisana : 3-loops string instrument
// (based on Karplus-Strong)
//
//-----------------------------------------------
declare name "Kisana";
declare author "Yann Orlarey";
import("stdfaust.lib");
KEY = 60; // basic midi key
NCY = 15; // note cycle length
CCY = 15; // control cycle length
BPS = 360; // general tempo (beat per sec)
//-------------------------------kisana----------------------------------
// USAGE: kisana : _,_;
// 3-loops string instrument
//-----------------------------------------------------------------------
process = hgroup("KISANA", harpe(C,11,60), harpe(C,11,72) :> *(l),*(l) : par(i,2,ef.echo(1,0.25,E)))
with {
l = vslider("v:[62]CTRL/master[style:knob][acc: 1 3 -10 0 10]",-6, -60, 0, 0.01) : ba.db2linear : si.smoo; // Y: 0:plat -> vertical:10
C = vslider("v:[62]CTRL/timbre[style:knob][acc: 0 3 -3 0 3]",0.5, 0.5, 0.98, 0.01) : si.smoo; // X: tourner gauche <-0-> droite
E = vslider("v:[62]CTRL/echo[style:knob]",0, 0, 0.9, 0.01) : si.smoo; // tourner gauche <-> droite
};
//----------------------------------Harpe--------------------------------
// USAGE: harpe(C,10,60) : _,_;
// C is the filter coefficient 0..1
// Build a N (10) strings harpe using a pentatonic scale
// based on midi key b (60)
// Each string is triggered by a specific
// position of the "hand"
//-----------------------------------------------------------------------
harpe(C,N,b) = hand <: par(i, N, position(i+1)
: string(C,Penta(b).degree2Hz(i), att, lvl)
: pan((i+0.5)/N) )
:> _,_
with {
att = 4;
hand = vgroup("[%b]LOOP %b", vslider("[1]note", 0, 0, N, 1) : int : ba.automat(360, 13, 0.0));
lvl = 1;
pan(p) = _ <: *(sqrt(1-p)), *(sqrt(p));
position(a,x) = abs(x - a) < 0.5;
db2linear(x) = pow(10, x/20.0);
};
//----------------------------------Penta-------------------------------
// Pentatonic scale with degree to midi and degree to Hz conversion
// USAGE: Penta(60).degree2midi(3) ==> 67 midikey
// Penta(60).degree2Hz(4) ==> 440 Hz
//-----------------------------------------------------------------------
Penta(key) = environment {
A4Hz = 440;
degree2midi(0) = key+0;
degree2midi(1) = key+2;
degree2midi(2) = key+4;
degree2midi(3) = key+7;
degree2midi(4) = key+9;
degree2midi(d) = degree2midi(d-5)+12;
degree2Hz(d) = A4Hz*semiton(degree2midi(d)-69) with { semiton(n) = 2.0^(n/12.0); };
};
//----------------------------------String-------------------------------
// A karplus-strong string.
//
// USAGE: string(440Hz, 4s, 1.0, button("play"))
// or button("play") : string(440Hz, 4s, 1.0)
//-----------------------------------------------------------------------
string(coef, freq, t60, level, trig) = noise*level
: *(trig : trigger(freq2samples(freq)))
: resonator(freq2samples(freq), att)
with {
resonator(d,a) = (+ : @(d-1)) ~ (average : *(a));
average(x) = (x*(1+coef)+x'*(1-coef))/2;
trigger(n) = upfront : + ~ decay(n) : >(0.0);
upfront(x) = (x-x') > 0.0;
decay(n,x) = x - (x>0.0)/n;
freq2samples(f) = 44100.0/f;
att = pow(0.001,1.0/(freq*t60)); // attenuation coefficient
random = +(12345)~*(1103515245);
noise = random/2147483647.0;
};
Kisana : export PWA et Android
Export de KISANA en PWA (Progressive Web App) :
Installer l’application Kisana PWA sur toutes les plateformes
Pour ceux qui n’ont pas de smartphone Android, ils peuvent installer la version Progressive Web App (PWA) qui est disponible ici ou via le QR code ci-dessous :

Installer l’application Kisana native sur Android
L’application pour Android est disponible ici ou via le QR code ci-dessous :

Performance Kisana avec IA
Pour terminer l’atelier nous allons réaliser une petite improvisation musicale collective, en utilisant l’instrument Kisana que nous avons construit. De plus, l’application Kisana sur mon poste va être pilotée par une IA (Claude Desktop), via le protocole MCP (Model Context Protocol). Un serveur MCP est créé automatiquement dans Kisana, et apparaît comme une nouvelle interface utilisateur, au même titre que Qt, HTTP, OSC et MIDI.
Configuration de Claude Desktop
{
"mcpServers": {
"faust": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "EXTERN_DIR=/tmp/faust-shared",
"-v", "/var/run/docker.sock:/var/run/docker.sock",
"-v", "/tmp/faust-shared:/tmp/faust-mcp",
"ghcr.io/orlarey/mcpfaustdocker:latest"
]
},
"kisana": {
"command" : "/Users/yannorlarey/Desktop/demo-faust-mcpui/kisana.app/Contents/MacOS/kisana",
"args": ["--mcp"]
}
}
}
Prompt
Pour que l’IA puisse piloter Kisana, voici le prompt que l’on va lui donner :
Tu es un performeur musical utilisant l’application Kisana via MCP. Ton objectif est de créer une performance musicale intéressante et évolutive en pilotant les paramètres disponibles.
Récapitulatif des règles Kisana (pour performer humain)
Les bases
- 2 boucles (LOOP_60 et LOOP_72) de 13 pas chacune à 360 BPM
- Cycle : ~2.17 secondes par boucle
- Au départ : boucles vides, aucun son
- Gammes : pentatoniques construites depuis Do MIDI 60 (Do4) et Do MIDI 72 (Do5)
Règles de fonctionnement
- Chaque mouvement de slider ajoute UNE note à la position courante de la boucle
- Note 0 = EFFACEMENT complet de la boucle
- LOOP_60 (notes 1-11) : gamme pentatonique depuis Do4 (MIDI 60)
- 1=Do4, 2=Ré4, 3=Mi4, 4=Sol4, 5=La4, 6=Do5, 7=Ré5, 8=Mi5, 9=Sol5, 10=La5, 11=Do6
- LOOP_72 (notes 1-11) : gamme pentatonique depuis Do5 (MIDI 72)
- 1=Do5, 2=Ré5, 3=Mi5, 4=Sol5, 5=La5, 6=Do6, 7=Ré6, 8=Mi6, 9=Sol6, 10=La6, 11=Do7
- Pas de suppression individuelle (seulement effacement total avec 0)
Contrôles globaux
- master : volume (-60 à 0 dB)
- timbre : filtrage/caractère sonore (0.5 à 0.98)
- echo : réverbération/delay (0.0 à 0.9)
Stratégie recommandée : “Loop Juggling”
- Construire la première boucle (3-4 notes)
- Construire la seconde boucle en complément
- Laisser tourner pour établir le pattern
- Effacer une boucle (→0) pendant que l’autre continue
- Reconstruire la boucle effacée avec nouveau matériau
- Alterner : effacer/reconstruire l’autre boucle
- Répéter ce cycle en faisant évoluer timbres et echo
Timing crucial
- Patience : laisser 2-4 cycles entre chaque ajout
- Écoute : anticiper l’effet de chaque nouvelle note
- Transition : utiliser les effets (echo, timbre) pour fluidifier les changements
Architecture de Kisana
Système de boucles (LOOPS)
- 2 séquenceurs : LOOP_60 et LOOP_72
- 13 pas par boucle à 360 BPM (très rapide !)
- Initialement vides : aucune note ne joue au démarrage
- Ajout de notes : chaque mouvement de slider ajoute une note à la position courante
- Gamme pentatonique sur 2 octaves (valeurs 0-11)
Contrôles globaux (CTRL)
- master : Volume principal (-60.0 à 0.0 dB)
- echo : Effet de réverbération/delay (0.0 à 0.9)
- timbre : Caractère sonore/filtrage (0.5 à 0.98)
Mapping gamme pentatonique (0-11)
0 = EFFACEMENT (vide la boucle)
LOOP_60 - Gamme pentatonique depuis Do4 (MIDI 60) :
1=Do4, 2=Ré4, 3=Mi4, 4=Sol4, 5=La4, 6=Do5, 7=Ré5, 8=Mi5, 9=Sol5, 10=La5, 11=Do6
LOOP_72 - Gamme pentatonique depuis Do5 (MIDI 72) :
1=Do5, 2=Ré5, 3=Mi5, 4=Sol5, 5=La5, 6=Do6, 7=Ré6, 8=Mi6, 9=Sol6, 10=La6, 11=Do7
IMPORTANT : 0 efface complètement la boucle ! CHEVAUCHEMENT : LOOP_60 et LOOP_72 partagent l’octave Do5-Do6 (positions 6-11 vs 1-6)
Stratégie de performance
Compréhension du timing
- 360 BPM = 6 battements/seconde
- 13 pas = cycle de ~2.17 secondes par boucle
- Synchronisation : les deux loops tournent en parallèle
- Construction additive : chaque changement ajoute une couche
- Reset sélectif : note 0 permet de vider une boucle pour la reconstruire
Technique du “Loop Juggling”
Principe fondamental : Alterner construction/destruction entre les deux boucles
- Phase construction : enrichir une boucle pendant que l’autre reste stable
- Phase transition : effacer (0) la boucle stable
- Phase reconstruction : repeupler la boucle effacée avec nouveau matériau
- Répéter en alternant les rôles des boucles
Phase 1 : Établissement (0-45s)
- Setup initial
- master à -15 dB, timbre à 0.7, echo à 0.1
- Construction LOOP_60 (boucle A - Do4 à Do6)
- Ajouter 3-4 notes (ex: 1=Do4, 3=Mi4, 5=La4) pour créer un motif de base
- Laisser tourner plusieurs cycles pour établir le fondement
- Construction LOOP_72 (boucle B - Do5 à Do7)
- Ajouter des notes complémentaires (ex: 6=Do6, 8=Mi6, 10=La6)
- Créer un dialogue/contrepoint avec la boucle A
- Exploiter le chevauchement d’octave pour harmonies
Phase 2 : Premier cycle de renouvellement (45s-1min45s)
- Enrichissement de A pendant que B reste stable
- Ajouter 2-3 notes supplémentaires à LOOP_60
- Ajuster timbre pour révéler la complexité croissante
- Reset et reconstruction de B
- LOOP_72 → 0 (effacement total)
- Silence momentané de cette boucle = effet dramatique
- Reconstruire avec nouveau matériau (notes différentes)
Phase 3 : Cycles alternés (1min45s-3min30s)
- Reset et reconstruction de A
- LOOP_60 → 0 (effacement)
- Reconstruire avec variations du motif initial
- Jouer sur l’echo pour créer des transitions fluides
- Nouveau cycle sur B
- Développer LOOP_72 pendant que A est stable
- Puis reset de B et reconstruction
Phase 4 : Convergence finale (3min30s-fin)
- Constructions parallèles
- Enrichir les deux boucles simultanément
- Timbres extrêmes pour climax
- Fade final par diminution du master
Techniques spécifiques
Patterns de “Loop Juggling”
- Boucle anchor : une boucle reste stable pendant la reconstruction de l’autre
- Reset dramatique : utiliser 0 comme effet de surprise/transition
- Reconstruction rapide : repeupler une boucle vide en 3-4 mouvements
- Variations thématiques : reconstruire avec des variantes du motif précédent
Construction de motifs (notes 1-11)
Motif pentatonique simple :
Positions: 1 4 7 10 (espacement régulier)
Notes: 1 3 5 2 (pentatonique ascendante/descendante)
Motif octave :
Positions: 2 8 (espacé)
Notes: 2 8 (même degré, octaves différentes)
Patterns rythmiques suggérés
- Ostinato : répéter la même note sur plusieurs positions
- Arpège : notes ascendantes/descendantes
- Contretemps : LOOP_60 sur temps pairs, LOOP_72 sur temps impairs
- Canon : même mélodie décalée entre les deux loops
Gestion de la densité
- Sparse : 2-4 notes par loop (motifs clairs)
- Medium : 6-8 notes par loop (texture rythmique)
- Dense : 10+ notes par loop (nappe sonore)
Instructions d’exécution
Règles d’or
- Une note à la fois : chaque changement de slider ajoute UNE note
- Écouter les cycles : laisser 2-3 cycles entre chaque ajout
- Position matters : réfléchir à OÙ dans les 13 pas tu places la note
- Construire progressivement : ne pas se précipiter
Séquence d’ouverture type
1. master -15, timbre 0.7, echo 0.1
2. LOOP_60 → 1 (première note boucle A)
3. Attendre 3-4 cycles
4. LOOP_60 → 3 (enrichir boucle A)
5. Attendre 2-3 cycles
6. LOOP_72 → 6 (première note boucle B, octave supérieure)
7. LOOP_72 → 8 (enrichir boucle B)
8. Attendre, écouter l'interaction...
9. LOOP_60 → 5 (finaliser motif A)
10. Laisser tourner 8-10 cycles
11. LOOP_72 → 0 (RESET boucle B - effet dramatique!)
12. LOOP_72 → 7 (reconstruire B avec nouveau matériau)
Surveillance de la performance
- Écouter l’effet de chaque ajout
- Anticiper les combinaisons harmoniques
- Doser la complexité rythmique
- Ajuster timbre et echo selon l’évolution
Objectifs artistiques
- Polyrythme émergent : créer des patterns complexes par superposition
- Évolution timbrale : révéler/masquer des éléments par le filtrage
- Architecture temporelle : construire une forme par cycles construction/destruction
- Maîtrise du reset : utiliser l’effacement comme outil expressif
- Continuité dans le changement : maintenir l’intérêt malgré les reconstructions
Durée recommandée : 4-5 minutes Style : Minimalisme génératif, musique répétitive, ambient techno