Tever
FR

Tutoriel · Labo DIY

MIDI vs MusicXML en Python : ce qui subsiste

Une expérience avec music21 et pretty_midi : la même phrase avec doigté, liaison et nuance, exportée en MIDI et en MusicXML. Ce qui survit dans chaque format, avec des chiffres réels.

Bureau avec deux fenêtres de code Python côte à côte : à gauche un éditeur avec le script music21 et un écran de partition avec liaison, doigté et nuance mp surlignés en orange ; à droite une vue hexadécimale d'un minuscule fichier binaire MIDI, sur une table de laboratoire technique

MIDI est le format que connaît, ne serait-ce que de nom, toute personne ayant déjà touché un clavier électronique. MusicXML est bien moins connu, et pourtant une question surgit dès qu’il faut plus que « que ça sonne » : et si ce qu’il faut, c’est la partition, pas le son ? Doigté, liaisons, nuances de dynamique —tout ce qu’un interprète lit et qu’un ordinateur peut avoir besoin de conserver—. Ce tutoriel n’explique pas de nouveau ce qu’est chaque format —c’est le rôle de Qu’est-ce que MIDI ? et Qu’est-ce que MusicXML ?— mais le démontre : il construit la même phrase musicale une seule fois, l’exporte dans les deux formats et vérifie, avec des données réelles, ce qui survit dans chacun.

L’expérience

L’idée est simple : écrire une phrase courte avec music21 —doigté sur chaque note, une liaison et une marque de dynamique incluses— et l’exporter deux fois, une fois en MusicXML et une fois en MIDI. Ensuite, relire chaque fichier et voir ce qu’il en reste.

from music21 import stream, note, meter, tempo, dynamics, articulations, spanner, clef

s = stream.Part()
s.append(clef.TrebleClef())
s.append(meter.TimeSignature('4/4'))
s.append(tempo.MetronomeMark(number=100))

n1 = note.Note('C5', quarterLength=1)
n1.articulations.append(articulations.Fingering(1))
n2 = note.Note('E5', quarterLength=1)
n2.articulations.append(articulations.Fingering(3))
n3 = note.Note('G5', quarterLength=0.5)
n3.articulations.append(articulations.Fingering(5))
n4 = note.Note('E5', quarterLength=0.5)
n4.articulations.append(articulations.Fingering(3))

n1.dynamic = dynamics.Dynamic('mp')
slur = spanner.Slur(n3, n4)

s.append(n1); s.append(n2); s.append(n3); s.append(n4)
s.insert(0, dynamics.Dynamic('mp'))
s.insert(0, slur)

s.write('musicxml', fp='ejemplo.musicxml')
s.write('midi', fp='ejemplo.mid')

Quatre notes —Do5, Mi5, Sol5, Mi5—, chacune avec son doigté indiqué, les deux dernières liées entre elles et toute la phrase marquée mezzopiano. Rien d’exotique : c’est exactement le type d’information qu’un interprète s’attend à voir imprimé sur une partition.

Partition de la phrase d'exemple rendue à partir du MusicXML réel généré par le code : quatre notes en clé de sol avec doigté 1, 3, 5, 3, une liaison entre les deux dernières et l'indication de dynamique mp
La phrase d’exemple telle qu’elle est écrite dans le MusicXML généré par le code précédent —doigté, liaison et dynamique inclus—, rendue ici pour la voir comme la verrait un interprète.

Relire le MIDI

Avec pretty_midi, on peut ouvrir ejemplo.mid et lister les notes telles qu’elles ont été codées :

pitch=72 start=0.00 end=0.60 velocity=81   (C5)
pitch=76 start=0.60 end=1.20 velocity=81   (E5)
pitch=79 start=1.20 end=1.50 velocity=81   (G5)
pitch=76 start=1.50 end=1.80 velocity=81   (E5)

Quatre événements de note, chacun avec une hauteur (pitch), un instant de début et de fin en secondes, et une velocity —81 pour les quatre, résultat de la traduction de l’unique dynamique mp de la phrase en une valeur MIDI fixe—. C’est exactement ce à quoi on peut s’attendre de MIDI : des instructions sur quand joue quoi, avec quelle intensité. Aucune trace du doigté, ni de la liaison, ni du fait qu’il y a eu un jour une marque « mp » sur la partition : cette information n’a nulle part où vivre dans le protocole. Ça se joue tout aussi bien, mais c’est perdu pour toujours dès l’enregistrement.

Relire le MusicXML

Avec music21.converter.parse sur ejemplo.musicxml, la même phrase rend bien plus :

C5 : doigté=[1]
E5 : doigté=[3]
G5 : doigté=[5]
E5 : doigté=[3]
Liaisons codées explicitement : 2
Nuances de dynamique : ['mp']

Les quatre doigtés sont intacts, la liaison reste codée comme telle —non comme une coïncidence de durées, mais comme un élément <slur> explicite— et la marque « mp » reste « mp », pas un nombre de vélocité. Tout ce que MIDI n’avait nulle part où stocker, MusicXML le conserve parce qu’il décrit la partition, pas l’interprétation.

Un extrait du XML généré montre pourquoi : chacun de ces éléments est une balise lisible, pas un nombre de protocole.

<dynamics default-x="-36" default-y="-80">
  <mp />
</dynamics>
...
<fingering alternate="no" substitution="no">1</fingering>
...
<slur number="1" type="start" />

Ce que disent les octets

La différence se voit aussi, littéralement, dans la taille et la forme de chaque fichier. ejemplo.mid pèse 99 octets ; ejemplo.musicxml, 3560 octets —36 fois plus pour la même phrase de quatre notes—. Ce n’est pas de l’inefficacité : c’est la différence entre ne stocker que des instructions de lecture et stocker une description complète de la notation écrite.

Les premiers octets du MIDI, en hexadécimal, sont du binaire pur :

4d54 6864 0000 0006 0001 0002 2760 4d54
726b 0000 0014 00ff 5103 0927 c000 ff58

Sans parser, cela ne dit rien. Le MusicXML, en revanche, est du texte XML que n’importe qui peut ouvrir dans un éditeur et lire —les extraits ci-dessus (<dynamics>, <fingering>, <slur>) se comprennent sans autre contexte que le nom même de la balise—.

Tableau comparatif de l’expérience

MIDI (ejemplo.mid)MusicXML (ejemplo.musicxml)
Notes (hauteur, temps)✔ Conservées✔ Conservées
Doigté✘ Perdu✔ Conservé ([1], [3], [5], [3])
Liaison✘ Perdue (seulement durées contiguës)✔ Conservée comme <slur> explicite
Dynamique (« mp »)Approximée en velocity=81✔ Conservée en texte (mp)
Taille99 octets3560 octets
Lisible par une personne✘ Binaire✔ Texte XML

Pourquoi cela compte en pratique

Ce n’est pas une curiosité de format : cela décide quel outil utiliser selon ce qu’il faut conserver. Pour reproduire, séquencer ou piloter un synthétiseur, MIDI suffit et est plus léger. Pour la notation, la pédagogie —un doigté qu’un élève doit voir imprimé— ou l’archivage d’une partition qu’on veut éditer plus tard, MIDI est insuffisant par conception, pas par négligence : il n’a jamais promis de conserver cela.

C’est aussi pourquoi un système de transcription musicale automatique doit choisir avec soin son format de sortie selon l’usage final : MIDI si l’objectif est que la transcription sonne, MusicXML si l’objectif est que quelqu’un la lise, la corrige ou l’utilise pour enseigner. Dans ma propre recherche doctorale, je travaille avec le piano comme corpus, et ce même dilemme apparaît dès qu’un système d’AMT termine de décider quelles notes ont sonné : l’étape suivante est dans quel format livrer ce résultat, et ce n’est pas une décision neutre.

Bibliographie

Les références sur lesquelles s’appuie cet article, et par où poursuivre la lecture :