Skip to the content.

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.

synth
Faust, un langage de programmation pour les instruments électroniques.

Exemples réalisés avec 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) :

Essayer →

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

Essayer →

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

Essayer →

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);
	};
};

synth

Essayer →

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 :

Essayer →

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

synth
Scanner le QR code depuis son smartphone.

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 :

drawing


Installer l’application Kisana native sur Android

L’application pour Android est disponible ici ou via le QR code ci-dessous :

drawing


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

Règles de fonctionnement

Contrôles globaux

Stratégie recommandée : “Loop Juggling”

  1. Construire la première boucle (3-4 notes)
  2. Construire la seconde boucle en complément
  3. Laisser tourner pour établir le pattern
  4. Effacer une boucle (→0) pendant que l’autre continue
  5. Reconstruire la boucle effacée avec nouveau matériau
  6. Alterner : effacer/reconstruire l’autre boucle
  7. Répéter ce cycle en faisant évoluer timbres et echo

Timing crucial

Architecture de Kisana

Système de boucles (LOOPS)

Contrôles globaux (CTRL)

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

Technique du “Loop Juggling”

Principe fondamental : Alterner construction/destruction entre les deux boucles

  1. Phase construction : enrichir une boucle pendant que l’autre reste stable
  2. Phase transition : effacer (0) la boucle stable
  3. Phase reconstruction : repeupler la boucle effacée avec nouveau matériau
  4. Répéter en alternant les rôles des boucles

Phase 1 : Établissement (0-45s)

  1. Setup initial
    • master à -15 dB, timbre à 0.7, echo à 0.1
  2. 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
  3. 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)

  1. 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
  2. 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)

  1. 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
  2. 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)

  1. 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”

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

Gestion de la densité

Instructions d’exécution

Règles d’or

  1. Une note à la fois : chaque changement de slider ajoute UNE note
  2. Écouter les cycles : laisser 2-3 cycles entre chaque ajout
  3. Position matters : réfléchir à OÙ dans les 13 pas tu places la note
  4. 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

Objectifs artistiques

Durée recommandée : 4-5 minutes Style : Minimalisme génératif, musique répétitive, ambient techno


Si vous voulez en savoir plus sur Faust