\chapter{Musical Instrument Digital Interface} \label{chap:MIDI} \index{MIDI} Dans un premier temps, je vais me concentrer sur les services \textsc{midi} offerts par la couche ALSA d'un système Linux. Ensuite, nous passerons aux \textit{raw devices} (page \pageref{midi:raw}). Mais avant tout, un petit rappel sur ce qu'est le MIDI. \begin{quote} \textsl{Wikipedia} : C'est un protocole de communication et un format de fichier dédiés à la musique, et utilisés pour la communication entre instruments électroniques, contrôleurs, séquenceurs, et logiciels de musique. Apparu dans les années 1980, issu d'une volonté de l'industrie de normaliser les échanges entre les différents instruments, ce protocole est devenu aujourd'hui un standard très répandu dans le matériel électronique de musique. \end{quote} Attention, ce système \textbf{ne} transporte \textbf{pas} de signal audio, mais de petits messages (quelques octets, en général 3) de \textbf{commande} informatique% \footnote{C'est une confusion fréquente qui complique les choses}. Un exemple de message basique, c'est celui-ci, exprimé en hexadécimal\index{hexa.} : \texttt{93 5B 3A} un message qui va déclencher, sur le canal 3, la note \textsf{Sol5}, à un niveau assez bas. Et c'est l'instrument à l'autre bout di fil qui va générer le signal audio. % --------------------------------------------------------- \section{Outils de base} \subsection{aseqdump} \index{aseqdump} Cet outil permet de voir de façon relativement claire \textbf{tous} les évènements \textsc{midi} qui rentre par un chemin donné, et, en première étape, surtout de lister ces chemins. \begin{verbatim} tth@plop:~/Muzak/Samples$ aseqdump -l Port Client name Port name 0:0 System Timer 0:1 System Announce 14:0 Midi Through Midi Through Port-0 \end{verbatim} \subsection{aconnect} Maintenant que nous savons ce qui rentre dans notre machine, il est temps de savoir comment le faire ressortir. Il faut donc créer une connexion quelque part au tréfond des tables obscures de la kernelle. \subsection{aseqnet} \begin{quote} aseqnet is an ALSA sequencer client which sends and receives event packets over the network. \end{quote} % --------------------------------------------------------- \section{ALSA tips} \index{ALSA} \textbf{cat /proc/asound/seq/clients} \begin{verbatim} Client info cur clients : 4 peak clients : 4 max clients : 192 Client 0 : "System" [Kernel] Port 0 : "Timer" (Rwe-) Port 1 : "Announce" (R-e-) Connecting To: 15:0 Client 14 : "Midi Through" [Kernel] Port 0 : "Midi Through Port-0" (RWe-) Client 15 : "OSS sequencer" [Kernel] Port 0 : "Receiver" (-we-) Connected From: 0:1 Client 128 : "TiMidity" [User] Port 0 : "TiMidity port 0" (-We-) Port 1 : "TiMidity port 1" (-We-) Port 2 : "TiMidity port 2" (-We-) Port 3 : "TiMidity port 3" (-We-) Output pool : Pool size : 500 Cells in use : 0 Peak cells in use : 0 Alloc success : 0 Alloc failures : 0 Input pool : Pool size : 1000 Cells in use : 0 Peak cells in use : 0 Alloc success : 0 Alloc failures : 0 \end{verbatim} % --------------------------------------------------------- \section{Raw devices} \label{midi:raw} Plutôt que de passer par la couche ALSA, il est aussi possible d'attaquer directement le \textit{device}, et de blaster soi-même tous les petits octets directement sur le fil. Voici un petit exemple en Python\index{Python}\footnote{Oui, je sais, c'est un langage de djeunz, mais bon, ça fait plaisir à mon gamin}, facilement transposable dans un langage plus sérieux : \begin{lstlisting}[language=python] #!/usr/bin/env python import time def note_on(note): tx.write("%c%c%c" % (0x90, note, 100)) tx.flush() def note_off(note): tx.write("%c%c%c" % (0x90, note, 0)) tx.flush() def progchange(prog): tx.write("%c%c" % (0xc0, prog)) tx.flush() tx = open("/dev/midi", "w") for valeur in range(30,90): progchange(valeur) note_on(valeur) time.sleep(1) note_off(valeur) time.sleep(1) tx.close() \end{lstlisting} % --------------------------------------------------------- \section{Et en Perl ?} \index{Perl} En Perl\footnote{Oui, je sais, c'est un langage de vieux, mais bon, il faut bien se faire plaisir de temps en temps\dots}, il existe un certain nombre de modules très évolués pour jouer avec les fichiers MIDI, ce qui est un domaine légèrement différent, il faut le reconnaitre. \begin{verbatim} MIDI (3pm) - read, compose, modify, and write MIDI files MIDI::Event (3pm) - MIDI events MIDI::Filespec (3pm) - MIDI File Specification MIDI::Opus (3pm) - functions and methods for MIDI opuses MIDI::Score (3pm) - MIDI scores MIDI::Simple (3pm) - procedural/OOP interface for MIDI composition MIDI::Track (3pm) - functions and methods for MIDI tracks \end{verbatim} Un petit essai, par exemple extraire la valeur du \textsc{bpm} d'un fichier \texttt{.mid} ? \lstinputlisting[language=perl]{code/midifile.pl} Voilà. % --------------------------------------------------------- \section{midish} \index{midish} Vous avez aimé \textsl{packet filter} ? Alors vous allez adorer midish\dots % --------------------------------------------------------- \section{Et après ?} OSC\index{OSC} (page \pageref{chap:OSC}) semble une possibilité pour aller au-delà. Mais, \textsl{amho}, rien ne pourra vraiment remplacer le midi tel que nous le connaissons depuis les années 80. % ---------------------------------------------------------