Modules GMEM - CIRVA

hardware

Cahier des charges

  • Minimum de contact entre le support et l'objet en verre
  • Câbles apparent
  • Possibilité de déplacer transducteur, micro et solénoide à la main afin de continuer
  • l'expérimentation sonore
  • Possibilité de remplacer transducteur, micro et solénoide à la main (?)
  • Entrées et sorties analogiques audio (pour brancher d'autres pièces en mode modulaire)
  • I/O alignées sur un niveau ligne (ce qui implique amplification à l'intérieur du prototype)
  • Entrée numérique pour le contrôle de la machine ou l'upload de partitions pour le
  • mode autonome
  • Entrée alimentation

Modules

Pour satisfaire aux besoins techniques de flexibilité comme aux impératifs artistique du respect de l'esthétique des modules, la structure portant les micros et transducteurs ainsi que l'électronique associée sera articulée autour d'un pied à perche de cymbale. Les câbles restent ainsi visibles et l'électronique se dévoile derrière un boîtier en plexiglas transparent.

Côté électronique chaque module est connecté à un raspberry pi qui utilise jackd pour router l'audio à faible latence, jouer des samples et gérer les ordres reçus sous forme de messages OSC. Il analyse également le signal audio entrant sur l'entrée “cv” et déclenche le solénoïde du module quand des crêtes dépassent un seuil réglable par potentiomètre. Un shield permet l'interface entre les GPIOs du pi et le mosfet de sortie du solénoïde, les entrées potentiomètres (seuil et gain de l'entrée CV) via un MCP3006 ainsi que la led RGB de l'entrée CV. L'acquisition du son et la sortie du signal audio se fait par une carte son USB Behringer U-Phoria UMC202HD équipée de préamplificateurs Midas. La sortie du transducteur passe par un amplificateur 10W à base de LM315.

Serveur

Les raspberry pi de chaque module se connectent par leur wifi à un serveur (un autre raspberry pi) configuré en point d'accès. Celui-ci héberge une interface web qui permet d'assigner à chaque module un nom, une note midi, de régler et consulter ses volumes d'entrées/sorties et de gérer ses fichiers audio. Des fichiers midis peuvent également lui être envoyés. Lorsque leur lecture est déclenchée, le serveur envoie au module concerné (assigné à cette note midi) l'ordre de déclencher son solénoïde pour une durée proportionnelle à la vélocité de la note.

Software :

Cahier des charges :

  • Lecture et stockage de fichier sons
  • Lecture et stockage de fichiers MIDI pour le solénoïde
  • Plusieurs contrôles avec accès OSC
  • Mute on/off micro
  • Mute on/off sample
  • Mute on/off transducteur
  • Mute on/off sortie analo
  • Envoi micro vers transducteur
  • Envoi micro vers sortie analo
  • Envoi sample vers transducteur
  • Envoi sample vers sortie analo
  • Envoi entrée analo vers transducteur
  • Envoi entrée analo vers sortie analo
  • Master sortie transducteur
  • Master sortie analo

Implémentation

Le code implémentant ce cahier des charges est accessible sur Github. Il est principalement rédigé en Python3 pour rester facilement modifiable.

Modules : côté client

Chaque instrument de verre est associé à un raspberry pi contenant le code client qui est automatiquement lançé au démarrage.

solénoïde

Le solénoïde est contrôlé par le module solenoid.py du dossier client, la librairie Rpi.GPIO permet de commander le mosfet et des précautions ont été prises pour éviter un déclenchement trop long du solénoïde pouvant endommager celui-ci. Un temps de récupération évite l'activation à la chaîne du solénoïde, le protégeant contre la surchauffe.

entrée CV

L'entrée CV écoute un signal audio et actionne le solénoïde si la moyenne de ce signal dépasse un seuil réglable par un potentiomètre. Le module peakDetector.py écoute l'entrée micro connectée à une petite carte son USB via pyaudio Un callback est appellé tous les 512 échantillons pour en additionner les valeurs. Si la somme des valeurs est supérieure au seuil, le solénoïde est déclenché et une led RGB s'éclaire en rouge. Si elle dépasse un seuil de signal, la led s'allume en vert pour manifester la présence de son sur l'entrée. Le volume de l'entrée (et l'activation du préampli micro) est réglée par un second potentiomètre marqué gain. Ce volume est directement réglé dans ALSA par amixer. La lecture des potentiomètres se fait au travers d'un MCP3008 connecté au bus SPI natif du raspberry pi et lu via spidev

routing audio

Contrairement à certaines cartes son bien plus onéreuses, la Behringer U-PHORIA UMC202 ne permet pas un monitoring hardware. Le routing audio doit donc se faire par voie logicielle, en passant régulièrement un tampon de l'entrée vers la sortie. Pour garder une latence inférieure à 5ms, ce tampon ne doit pas être trop grand et sa fréquence d'envoi vers la carte doit restée élevée. Ces exigences n'étant pas nécessairement compatibles avec le scheduler natif de raspbian, un noyau compilé en temps réel et tous les services non-utilisés sont désactivés (bluetooth, triggerhappy, dbus…) Le raspbian choisi est une version headless sans interface graphique pour économiser des ressources. Le code implémentant le routing audio se trouve dans le module audio.py du dossier client. La communication avec la carte son se fait via un serveur jackd (v1, la v2 s'appuyant sur dbus qui nécessite un serveur X). Le serveur et client Jack communiquent avec le script python par le module jackclient La lecture des samples s'appuie elle sur jack-play, l'ajustement des volumes se faisant directement sur ALSA via amixer.

serveur OSC

Un serveur OSC écoute en UDP sur le port 9000 pour recevoir les ordres transmis par le serveur comme les messages directement envoyés depuis puredata/maxMSP (cf liste des commandes OSC). Le client envoie également un message /heartbeat toutes les secondes pour permettre au serveur de détecter la déconnexion des clients. Il peut également lui transmettre la liste de ses fichiers audio, son nom d'hôte ainsi que son adresse IP pour permettre à celui-ci de maintenir une liste de clients connectés à jour.

Côté serveur

Le serveur contient son propre code, stocké dans le repertoire server à la racine du git. Le raspbian utilisé est une version complète, avec interface graphique pour pouvoir accéder à son interface web directement à l'aide d'un écran et d'un clavier.

gestion des clients

Le module clients.py gère la tenue d'une liste de clients en ligne comprenant les notes midi de chacun, leur volume, la liste de leurs fichiers wav et la dernière date à laquelle ils ont été vus. Il s'occupe également de marquer les clients comme déconnectés en l'absence de heartbeat et d'ajouter de nouveaux clients au fur et à mesure qu'ils se connectent à lui. La liste des clients connus est écrite dans un fichier json pour garder ces informations en mémoire après un redémarrage du serveur. Ce module permet en outre de découvrir tous les clients présents et de stocker leur adresse IP, envoyant ces informations vers l'interface web où elles peuvent être consultées et modifiée par l'utilisateur.

serveur OSC

Le serveur écoute l'OSC par UDP sur le port 8000, il peut ainsi recevoir des commandes des clients comme de l'utilisateur, voir liste des commandes OSC ci-dessous

interface web

L'interface web se résume à une page servie par flask et mis à jour dynamiquement par flask-socketio. Du javascript utilisant JQuery permet la modification dynamique de la DOM côté utilisateur. Côté fichiers, flask-uploads gère l'envoi de fichiers par requêtes POST/multipart

Liste des commandes OSC

Pour pouvoir communiquer en OSC avec les modules, il est impératif :

  1. d'allumer le serveur (et de lui laisser environ deux minutes pour démarrer)
  2. de se connecter au réseau wifi masterPi qu'il crée

commandes du serveur

Le serveur est joignable à l'IP 10.0.0.1 au sein du réseau wifi ou par son nom d'hôte masterpi.local. Il écoute sur le port 8000.

  • /clients : demande au serveur une liste de clients connectés. Le serveur répondra à l'expéditeur par un message OSC sur le port 9000 contenant en argument le nom de chaque client actuellement connectés
  • /knownClients : renverra à l'expéditeur sur le port 9000 le message OSC “/knownClients” contenant la liste de tous les appareils connus, connectés ou non
  • /shutdown : provoque l'extinction du serveur et de tous ses clients connectés à ce moment
  • /readMidi : lit instantanément un fichier midi préalablement stocké sur l'ensemble des machines
    • str nomDuFichier : nom du fichier midi stocké sur le serveur (sensible à la casse)
  • /stopMidi : stoppe instantanément la lecture du fichier midi en cours
  • /delete : supprime un fichier midi du serveur
    • str nomDuFichier : nom du fichier midi stocké sur le serveur (sensible à la casse)
    • (facultatif) str nomDuFichier : plusieurs noms de fichiers peuvent être donnés en même temps
    • ex : /delete fichier1.mid fichier2.mid fichier3.mid

commandes des clients (modules)

Les clients peut-être directement contacté par son nom d'hôte au sein du réseau wifi. Ce nom peut être édité sur l'interface web. Par exemple, pour un client nommé bidule, les messages OSC peuvent être envoyés à bidule.local au lieu de 192.168.0.24 Chaque client écoute en UDP sur le port 9000.

  • /solenoid : pulse le solénoide une fois
    • (facultatif) int durée : durée d'activation du solénoïde en ms. Limitée en interne pour éviter la surchauffe du solénoïde
    • ex : /solenoid 50
  • /play : lit un fichier audio stocké dans le client
    • str nomDuFichier : nom du fichier sans le chemin complet, ex: groovyTune.wav (peut contenir des espaces, caractères accentués…)
    • (facultatif) str sortie audio : sortie utilisée pour lire le fichier son, par défaut celle du transducteur. Peut être soit transducer soit analogOUT, sensible à la casse
    • (facultatif) str sortie audio2 : seconde sortie utilisée pour lire le fichier son simultanément. Peut être soit transducer soit analogOUT, sensible à la casse
    • ex : /play groovyTune.wav analogOUT
  • /stop : stoppe instantanément la lecture du fichier wav en cours
  • /delete : supprime un fichier audio du serveur
    • str nomDuFichier : nom du fichier audio stocké sur le serveur (sensible à la casse)
    • (facultatif) str nomDuFichier : plusieurs noms de fichiers peuvent être donnés en même temps
    • ex : /delete fichier1.wav fichier2.wav fichier3.wav
  • /route : connecte une entrée audio à une sortie audio
    • str nomDeLentrée : peut être soit microphone soit analogIN, sensible à la casse
    • str nomDeLaSortie : peut être soit transducer soit analogOUT, sensible à la casse
    • ex : /route microphone transducer
  • /disconnect : déconnecte le routing effectué entre une entrée audio et une sortie audio
    • str nomDeLentrée : peut être soit microphone soit analogIN, sensible à la casse
    • str nomDeLaSortie : peut être soit transducer soit analogOUT, sensible à la casse
    • ex : /disconnect microphone transducer
  • /mute : coupe le son de l'entrée ou la sortie sélectionnée
    • str nom : peut être microphone, analogIN, transducer, analogOUT, sensible à la casse
    • (facultatif) str nom : idem, permet de muter plusieurs canaux en même temps
    • ex : /mute analogOUT transducer
  • /unmute : rétablit le son de l'entrée ou la sortie sélectionnée
    • str nom : peut être “microphone”, analogIN, transducer, analogOUT, sensible à la casse
    • (facultatif) str nom : idem, permet de dé-muter plusieurs canaux en même temps
    • ex : /unmute analogOUT
  • /toggle : inverse l'état du mute de l'entrée ou la sortie sélectionnée
    • str nom : peut être microphone, analogIN, transducer, analogOUT, sensible à la casse
    • (facultatif) str nom : idem, permet de basculer le mute de plusieurs canaux en même temps
    • ex : /toggle analogOUT
  • /volume : règle le volume de l'entrée ou la sortie sélectionnée
    • str nomDeLEntreeSortie : peut être microphone, analogIN, transducer, analogOUT, sensible à la casse
    • int volume 0~100 : inaudible à 0%, plein volume à 100%, courbe logarithmique.
    • ex : /volume analogOUT 87
  • /shutdown : provoque l'extinction de cette machine

Dev interface

Photos