\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.

% ---------------------------------------------------------
\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{Et après ?}

OSC\index{OSC} (page \pageref{chap:OSC}) semble une possibilité
pour aller au-delà.

% ---------------------------------------------------------
