\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 du fil
qui va générer le signal audio.

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

\section{Seq24}\index{seq24}

Seq24 has a unique convention for entering and editing notes that seems
confusing at first but quickly makes sense once you use it once or twice.

\begin{itemize}
\item{Right-click to activate the pen tool, and left-click (while still
 holding the right-click button) to draw a note.}
\item{Left-click to select a note. Left-click and drag to draw a
 selection box.}
\item{Middle-click and drag to modify the length of a selected note.}
\end{itemize}

% ---------------------------------------------------------
\section{Outils de base}

Le sous-système ALSA vient avec quelques utiltaires bien pratique
dans un usage d'exploration.

\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
 20:0    nanoKONTROL                    nanoKONTROL MIDI 1
\end{verbatim}

Voici ce qu'on obtient quand on remue les boutons d'un
nanoKontrol de Korg, et voyez bien qu'on retrouve les
trois octets dont on causait l'autre jour. Le premier
contient à la fois le numéro ce canal et le type d'évènement,
le second le numéro du contrôle concerné, et le troisième
la nouvelle valeur~:

\begin{verbatim}
tth@fubar:~/Documents/TetaTricks$ aseqdump -p 20
Waiting for data. Press Ctrl+C to end.
Source  Event                  Ch  Data
 20:0   Control change          1, controller 45, value 127
 20:0   Control change          1, controller 45, value 0
 20:0   Control change          1, controller 14, value 120
 20:0   Control change          1, controller 14, value 119
\end{verbatim}

Un exemple d'utilisation d'un nanoKontrol pour piloter Chuck 
se trouve (peut-être) aux alentours de la
page \pageref{chuck-midi}.

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

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

\subsection{pmidi}

Jouer un fichier MIDI (aka \textsl{midifile}) au travers du
séquenceur ALSA.

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


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