PureData, SuperCollider... quelles alternatives?
Lorsqu’on veut développer des logiciels “maison” de traitement du son en temps réel, la réponse standard (dans le monde du libre) est PureData. La courbe d’apprentissage en est très sympathique en effet, mais j’ai appris à me méfier des langage de programmation graphiques: passé un certain niveau de complexité, le “code” devient ingérable - et comme il se prête moins bien au versionning que du code texte, ça n’arrange rien pour débusquer les bugs.
“Qu’à cela ne tienne, il y a SuperCollider” me rétorqueront certains. Eh bien j’ai une confession à vous faire: malgré plusieurs tentatives sérieuses de m’y mettre, je n’ai jamais réussi à comprendre la logique du truc et à l’utiliser un peu sérieusement. Ce n’est pas une critique du produit en tant que tel, mais il y a clairement une incompatibilité de caractère entre lui et moi.
Dans cet article, je vais vous présenter rapidement trois alternatives moins connues à ces mastodontes: ChucK, Faust et pyo. Les trois sont libres et multi-plateforme.
Chuck
ChucK se décrit comme un “Strongly-timed, Concurrent, and On-the-fly Music Programming Language”.
La gestion du temps est donc mise en avant (à raison), ainsi que celle de la concurrence (discutable) et la possibilité (comme pour SuperCollider) de modifier le code d’un système pendant qu’il tourne.
À quoi ça ressemble?
// patch
adc => DelayL delay => dac;
// set delay parameters
.75::second => delay.max => delay.delay;
// infinite time loop
while( true ) 1::second => now;
Cet exemple est tiré de la très utile liste d’exemples de la documentation de ChucK.
Quelques caractéristiques
- Gestion explicite du temps: le temps n’avance pas tant que le programme ne le demande pas explicitement. Il faut se mettre dans la logique, mais c’est parfois bien utile.
- Gestion presque graphique du “câblage”: la première ligne de code de l’exemple ci-dessus est très explicite: on branche l’entrée (adc=analogic digital concverter) dans un delay, et celui-ci dans la sortie (dac).
Avantages
- Langage assez facile d’accès
- “Câblage” explicite
- Certains outils livrés en standard sont très puissants, tels LiSa, sorte de méta-looper permettant de tout faire, de la simple boucle à la synthèse granulaire.
- Assez bien documenté, forum plutôt réactif.
Inconvénients
- Langage jeune et parfois incomplet; par exemple, pour l’instant pas de directive d’inclusion de fichier ni pratiquement aucune autre manière d’organiser et factoriser le code en plusieurs fichiers.
- La gestion de la concurrence, pourtant mise en avant dans la présentation du langage, me semble assez élémentaire.
- Sous Linux, ne joue pas bien le jeu de jack: le processus crée autant d’entrée et de sorties que la carte son (impossible d’en avoir plus), et les connecte automatiquement aux entrées-sorties système.
- Développement pas très actif; réactivité faible en cas de bugs/propositions d’améliorations.
- La syntaxe est parfois contre-intuitive quand on vient de langages plus “classiques”. On dirait même parfois que le langage se complaît dans ses différences: en ChucK, on spork un shred là où les tous les autres startent un thread… (comme le dit la doc: “In its own screwed-up way, this is kind of nice.”)
- Compilé vers une machine virtuelle. Raisonnablement efficace, mais n’essayez pas de faire du traitement de signal avec ça…
- Pas d’outil intégré pour réaliser une interface graphique, même rudimentaire.
Mon verdict
J’ai utilisé ChucK dans plusieurs concerts et il s’est révélé utile et très fiable; cependant, je vois venir le moment où ses inconvénients prendront le pas sur ses avantages et je ne jurerais pas que je l’utiliserai encore dans cinq ans.
Faust
“Faust (Functional Audio Stream) is a functional programming language specifically designed for real-time signal processing and synthesis. FAUST targets high-performance signal processing applications and audio plug-ins for a variety of platforms and standards.”
On change donc là d’univers: l’accent sera mis sur de strictes vérifications à la compilation, la description de très haut niveau et l’efficacité à l’exécution.
À quoi ça ressemble?
Un delay tiré des exemples livrés avec le langage:
declare name "SmoothDelay";
declare author "Yann Orlarey";
declare copyright "Grame";
declare version "1.0";
declare license "STK-4.3";
//--------------------------process----------------------------
//
// A stereo smooth delay with a feedback control
//
// This example shows how to use sdelay, a delay that doesn't
// click and doesn't transpose when the delay time is changed
//-------------------------------------------------------------
import("music.lib");
process = par(i, 2, voice)
with
{
voice = (+ : sdelay(N, interp, dtime)) ~ *(fback);
N = int(2^19);
interp = hslider("interpolation[unit:ms][style:knob]",10,1,100,0.1)*SR/1000.0;
dtime = hslider("delay[unit:ms][style:knob]", 0, 0, 5000, 0.1)*SR/1000.0;
fback = hslider("feedback[style:knob]",0,0,100,0.1)/100.0;
};
En d’autres termes: attachez vos ceintures, on décolle vers le monde merveilleux de la programmation fonctionnelle.
Caractéristiques
- Spécification fonctionnelle de haut niveau du traitement à effectuer: les flux sonores sont vus comme des fonctions N→R (à voir comme une fonction d’un temps discret vers des échantillons) et on combine ces fonctions pour obtenir le résultat désiré…
- Compilé vers du C++ ultra-optimisé
- Peut être compilé vers des exécutables standalone pour différentes architectures, mais aussi comme plugin VST, ou comme UGen pour SuperCollider… il existe des dizaines de “cibles” différentes
- Génération d’interfaces graphiques quasi automatique.
Avantages
- Code très ramassé
- Très efficace à l’exécution; ici, pas de problème pour faire directement du traitement de signal complexe!
- Bonne documentation
- Communauté assez active
- S’intègre bien dans des systèmes existants par la myriade de “cibles” possibles pour la compilation.
Inconvénients
- Beaucoup plus difficile d’accès que ChucK; oblige le programmeur à penser totalement différemment (sauf s’il est déjà bilingue avec Haskell, par exemple…)
- Ne semble pas complètement mûr: beaucoup de discussions sur la liste dédiée portent sur des segfaults et autres problèmes de compilation…
- Langage ultra-spécialisé: se prête bien à faire ce pour quoi il est prévu, mais si on veut sortir de ce cadre, on va sûrement galérer…
Mon verdict
Je n’ai pas dépassé quelques expérimentations préliminaires avec ce langage. Mais il semble très bien conçu et ce sera mon premier choix si je dois faire du traitement de bas niveau très optimisé.
pyo
“pyo is a Python module written in C to help digital signal processing script creation.”
Ça sent donc le meilleur des deux mondes: l’élégance de Python avec l’efficacité du C…
À quoi ça ressemble?
Le tutoriel propose quelques exemples comme:
from pyo import *
s = Server().boot()
f = Adsr(attack=.01, decay=.2, sustain=.5, release=.1, dur=5, mul=.5)
a = Sine(mul=f).out()
f.play()
s.gui(locals())
Caractéristiques
- Ce n’est pas un langage spécifique, mais un module pour un langage généraliste, en l’occurrence python
- L’idée des flux sonores comme objets de premier ordre, très claire dans Faust, est ici conservée
- Le code s’écrit en python, mais tous les éléments “critiques” sont déportés en C
Avantages
- Langage de programmation généraliste - donc mieux outillé et réutilisable dans d’autres contextes
- Beaucoup plus facile d’accès que Faust pour la plupart des développeurs
- Génération automatique d’interfaces graphiques élémentaires - et si on veut des interfaces plus développées, on a accès à toutes les bibliothèques disposant de bindings python (c’est-à-dire à peu près tout!)
- Développement très réactif: j’ai posé une question du type “est-il possible de…” et la réponse a été, “pas encore mais je m’en occupe”, ce qui a été fait dans les 24 heures!
Inconvénients
- Comme ChucK, ne se prête pas à du traitement de signal pur
- Pas forcément facile à installer
Mon verdict
L’utilisation d’un langage généraliste (qui plus est, python) est un gros avantage. J’ai fait par exemple des essais d’un système piloté à distance depuis une tablette numérique avec un push de l’interface du serveur vers le client; facile en python, ça se serait probablement situé quelque part entre “hyper-difficile” et “impossible” pour les deux autres systèmes considérés.
Il me reste à voir comment implémenter un équivalent du LiSa de ChucK dans pyo (ce qui ne devrait pas être trop difficile), et pyo deviendra pour moi un concurrent plus que sérieux à ChucK!
Conclusion
On connaît tous PureData et certains connaissent aussi SuperCollider… mais il est bon de savoir qu’on a du choix avec de vraies alternatives à ces deux géants.
De mon point de vue, je recommanderais
- ChucK pour des systèmes où la gestion du timing est prépondérante
- Faust si on doit tirer le maximum d’efficacité du processeur (traitement du signal, système embarqué, …)
- pyo pour tout le reste
Ceci dit, chacun de ces projets est encore assez jeune (en tout cas en termes de maturité), et il faudra voir comment ils évoluent dans les prochaines années - chacun ayant un très grand potentiel.