Programmation

Les codes et programmes d’Interface-Z

Accueil > Didacticiels > Réception des données en Processing

Réception des données en Processing

Mis à jour le vendredi 7 juillet 2017, par zandrine

The MidiBus

Branchements

Processing peut recevoir des données en Midi grâce à des bibliothèques externes. Nous nous concentrerons uniquement sur les messages de type Control Change, qui sont ceux utilisés dans notre matériel.

Pour chaque message Midi arrivant dans une application, plusieurs notions sont à prendre en compte :

Port : correspond physiquement à une prise Midi ;
Canal : configuré sur le matériel, commun à tous les capteurs branchés sur une carte ;
Numéro de Contrôleur : dépend de la carte et de l’emplacement du capteur sur cette carte, spécifique d’une prise capteur ;
Valeur : selon l’état du capteur.

Un message Midi provenant d’une carte à capteurs se reçoit sur un port et contient les 3 paramètres canal / numéro / valeur.

Ces notions sont équivalentes en entrée (input) et en sortie (output). Les capteurs se brachent sur une entrée Midi, les actionneurs se branchent en sortie.

  1. Connecter l’interface Midi USB à l’ordinateur AVANT de lancer Processing.
  2. Si ce n’est fait, configurer le chemin du sketchbook (CELUI qui contient la library).
  3. Installer themidibus

Midibus est une library Midi pour Pg plus simple à utiliser que RWMidi.
Son grand avantage est d’être compatible avec Minim (pas de type Controller ambigu).

Pour l’installer :

  1. télécharger : http://www.smallbutdigital.com/themidibus.php
  2. dézipper
  3. dans le dossier libraries du sketchbook de processing 1.5-MLV.

Sketch de réception : td3_03_midibus.zip

Comme toutes les libraries externes abordées, il faut l’importer et ouvrir un port Midi.

import themidibus.* ;
MidiBus myBus ;

Dans le setup(), on affiche dans la console la liste des périphériques disponibles : interfaces Midi USB ou Midi virtuel.

void setup()
// Liste des peripheriques Midi disponibles
MidiBus.list() ;
// Ouverture de port (this, In, Out)
// In et Out etant les numros des peripheriques correspondants
myBus = new MidiBus(this, 0, -1) ;

Les ports sont attribués par les numéros de la liste. -1 signifie de ne pas ouvrir de port sortant par exemple.

La fonction de réception des données est assez sympathique :

void controllerChange(int channel, int number, int value)

// Recoit les messages Midi de type Control Change
println() ;
println("Control Change Channel : "+channel) ;
println("Number : "+number) ;
println("Value : "+value) ;

Elle décortique les messages entrants et donne directement les diverses valeurs intéressantes.

Les raisons pour lesquelles cela ne marche éventuellement pas :

  • Le capteur n’a pas été actionné et n’envoie rien tant qu’on ne passe pas devant.
  • Erreur de branchement entre prise Midi In et Out
  • Oubli de brancher l’alimentation de l’interface
  • Interface Midi-USB non reconnue par l’ordinateur ou qui a décroché (mise en veille)
  • Interface Midi-USB mal configurée en Processing
  • Interface Midi débranchée / rebranchée sans redémarrer Pg

proMIDI

Le protocole Midi peut aussi être utilisé en Processing grâce à la librairie proMIDI, qui se télécharge ici http://www.texone.org/promidi/index.htm.

Attention cependant, theMidiBus est mieux et reçoit les Control Change de valeur 0...

Il faut donc commencer par installer proMIDI, en dézippant l’archive promidi.zip dans le répertoire libraries de processing.

Port

Dans le code :

  • Il faut importer la librairie pour y avoir accès ;
  • On utilise la classe MidiIO pour gérer les ports Midi.
import promidi.* ;
MidiIO midiIO ;

Dans la fonction setup, il faut détecter les périphériques Midi, en choisir un et ouvrir le port correspondant.

void setup()

// Get an instance of MidiIO
// Ouvre une instance de MidiIO
midiIO = MidiIO.getInstance(this) ;

//Print a list of all available devices.
//Imprime une liste de tous les peripheriques Midi disponibles.
midiIO.printDevices() ;

// Default : Open the first midi channel of the first input device.
// Par defaut : Ouvre le premier canal sur le premier peripherique Midi.
midiIO.openInput(0,0) ;

Les méthodes utilisées ici sont :

  • getInstance() pour ouvrir la possibilité de gérer les entrées/sorties Midi ;
  • printDevices() pour imprimer dans la console la liste des périphériques Midi disponibles. Cette étape n’est pas absolument nécessaire mais permet 1) de vérifier rapidement que l’appareil branché est bien reconnu en Processing et 2) de connaître son numéro d’identification dans la liste des ports Midi ;
  • openInput(int,int) permet d’ouvrir un des ports de la liste en choisissant aussi un canal particulier. La structure est midiIO.openInput(numero du peripherique,canal).

Ce n’est pas la seule façon de choisir et d’ouvrir un port Midi mais c’est celle qui a été utilisée dans les sketches téléchargeables sur ce site.

Fonctions controllerIn et noteOn

Il est maintenant possible de récupérer les Control Change et les Note On dans notre sketch.

Définissons une variable globale, commodément appelée valeur. Selon les cartes de captation, cette variable peut être un int ou un array. Dans cette page, nous resterons dans le cas le plus simple.

int valeur ;
void controllerIn(Controller controller, int device, int channel)
int numero = controller.getNumber() ;
if (numero==0)
valeur = controller.getValue() ;
print("Valeur ") ;
println(valeur) ;

Cette variable est utilisée dans une fonction controllerIn, où la variable valeur prend la valeur courante du capteur pour un numéro de Control Change donné. Le numéro de CC est récupéré grâce à controller.getNumber() et, s’il correspond aux critères de tri de la fonction, la valeur est récupérée grâce à controller.getValue().

Les Note On sont récupérés de façon équivalente, à l’aide d’une fonction noteOn. Là aussi le mieux est de définir auparavant une variable globale, par exemple un array d’integers nommé velocite_8 à 8 cases qui contiendra les informations venues de 8 interrupteurs branchés sur des entrées numériques.

int[] velocite_8 = new int[8] ;
void noteOn(Note note, int device, int channel)
int pitch = note.getPitch() ;
if ((pitch>=0)&&(pitch<8))
velocite_8[pitch] = note.getVelocity() ;
print("Capteur tout ou rien de pitch ") ;
print(pitch) ;
print(" valeur ") ;
println(velocite_8[pitch]) ;

Le numéro de Note On est obtenu grâce à note.getPitch(). Si les conditions de tri sont remplies (ici si le pitch est compris entre 0 et 7), la variable prend la valeur du Note On reçu à l’aide de note.getVelocity() et l’engrange à la bonne place de l’array, place correspondant au numéro de Note On.

Les variables valeur et velocite_8[] sont ensuite utilisables à volonté dans le sketch.

Ces fonctions sont communes aux sketches disponibles sur ce site pour les différentes cartes, avec les variantes spécifiques à chacune. Pour les traitements et les tris spécifiques de chaque carte, consulter les pages correspondantes.

Stabilité

Attention, il y a quelques précautions à prendre pour que tout se passe bien. Lorsqu’on teste un code, on relance régulièrement son exécution. Il faut éviter en Processing avec le Midi de faire simplement Stop / Run de nombreuses fois de suite. En effet, au bout d’un moment, l’accès au Midi se bloque complètement et plus rien ne semble fonctionner... Il devient impossible de relancer proprement Processing, il faut redémarrer la machine, avec le bouton Reset, d’ailleurs...

Pour éviter cet inconvénient relativement désagréable, il faut penser à fermer régulièrement Processing avant de tester une modification (peutêtre pas à tous les coups, mais souvent). Cela permet à Processing de fermer proprement les prots Midi, ce qu’il ne fait pas quand on se contente d’enchaîner les Run/Stop.

Il faudrait aussi explorer la méthode closeInput, cependant elle ne permet pas de fermer le port lui-même.