Tever
ES

Tutorial · Laboratorio DIY

MIDI vs MusicXML en Python: qué se pierde y qué no

Un experimento con music21 y pretty_midi: la misma frase con digitación, ligadura y dinámica, exportada a MIDI y a MusicXML. Qué sobrevive en cada formato, con cifras reales.

Escritorio con dos ventanas de código Python lado a lado: a la izquierda un editor con el script de music21 y una pantalla de partitura con ligadura, digitación y matiz mp resaltados en naranja; a la derecha una vista hexadecimal de un archivo binario MIDI diminuto, sobre una mesa de laboratorio técnico

MIDI es el formato que todo el mundo que ha tocado con un teclado electrónico conoce, aunque sea de oídas. MusicXML lo conoce mucho menos gente, y sin embargo hay una pregunta que aparece en cuanto se necesita algo más que “que suene”: ¿y si lo que hace falta es la partitura, no el sonido? Digitación, ligaduras, matices de dinámica —todo eso que un intérprete lee y un ordenador puede necesitar conservar—. Este tutorial no explica de nuevo qué es cada formato —para eso están ¿Qué es MIDI? y ¿Qué es MusicXML?— sino que lo demuestra: construye la misma frase musical una sola vez, la exporta a los dos formatos y comprueba, con datos reales, qué sobrevive en cada uno.

El experimento

La idea es sencilla: escribir una frase corta con music21 —digitación en cada nota, una ligadura y una marca de dinámica incluidas— y exportarla dos veces, una a MusicXML y otra a MIDI. Después, leer cada fichero de vuelta y ver qué queda.

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')

Cuatro notas —Do5, Mi5, Sol5, Mi5—, cada una con su dedo indicado, las dos últimas ligadas entre sí y toda la frase marcada mezzopiano. Nada exótico: es exactamente el tipo de información que un intérprete espera ver impresa en una partitura.

Partitura de la frase de ejemplo renderizada desde el MusicXML real generado por el código: cuatro notas en clave de sol con digitación 1, 3, 5, 3, una ligadura entre las dos últimas y la indicación de dinámica mp
La frase de ejemplo tal como queda escrita en el MusicXML generado por el código anterior —digitación, ligadura y dinámica incluidas—, renderizada aquí para verla como la vería un intérprete.

Leyendo el MIDI de vuelta

Con pretty_midi se puede abrir ejemplo.mid y listar las notas tal como quedaron codificadas:

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)

Cuatro eventos de nota, cada uno con altura (pitch), instante de inicio y fin en segundos, y una velocity —81 en las cuatro, resultado de traducir la única dinámica mp de la frase a un valor MIDI fijo—. Es exactamente lo que cabe esperar de MIDI: instrucciones de cuándo suena qué, con qué intensidad. Ni rastro de la digitación, ni de la ligadura, ni de que hubo alguna vez una marca “mp” en la partitura: esa información no tiene dónde vivir en el protocolo. Se toca igual de bien, pero se ha perdido para siempre en cuanto se guardó.

Leyendo el MusicXML de vuelta

Con music21.converter.parse sobre ejemplo.musicxml, la misma frase devuelve mucho más:

C5: digitación=[1]
E5: digitación=[3]
G5: digitación=[5]
E5: digitación=[3]
Ligaduras (slurs) codificadas explícitamente: 2
Marcas de dinámica: ['mp']

Las cuatro digitaciones están intactas, la ligadura sigue codificada como tal —no como una coincidencia de tiempos, sino como un elemento <slur> explícito— y la marca “mp” sigue siendo “mp”, no un número de velocidad. Todo lo que MIDI no tenía dónde guardar, MusicXML lo conserva porque describe la partitura, no la interpretación.

Un fragmento del XML generado deja ver por qué: cada uno de esos elementos es una etiqueta legible, no un número de protocolo.

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

Lo que dicen los bytes

La diferencia también se ve, literalmente, en el tamaño y la forma de cada fichero. ejemplo.mid pesa 99 bytes; ejemplo.musicxml, 3560 bytes —36 veces más para la misma frase de cuatro notas—. No es ineficiencia: es la diferencia entre guardar solo instrucciones de reproducción y guardar una descripción completa de la notación escrita.

Los primeros bytes del MIDI, en hexadecimal, son binario puro:

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

Sin un parser de por medio, esto no dice nada. El MusicXML, en cambio, es texto XML que cualquier persona puede abrir en un editor y leer —los fragmentos de arriba (<dynamics>, <fingering>, <slur>) se entienden sin más contexto que el propio nombre de la etiqueta—.

Tabla comparativa del experimento

MIDI (ejemplo.mid)MusicXML (ejemplo.musicxml)
Notas (altura, tiempo)✔ Conservadas✔ Conservadas
Digitación✘ Perdida✔ Conservada ([1], [3], [5], [3])
Ligadura✘ Perdida (solo tiempos contiguos)✔ Conservada como <slur> explícito
Dinámica (“mp”)Aproximada a velocity=81✔ Conservada como texto (mp)
Tamaño99 bytes3560 bytes
Legible por una persona✘ Binario✔ Texto XML

Por qué importa en la práctica

Esto no es una curiosidad de formato: decide qué herramienta usar según lo que se necesite conservar. Para reproducir, secuenciar o controlar un sintetizador, MIDI sobra y es más ligero. Para notación, pedagogía —una digitación que un alumno necesita ver impresa— o archivo de una partitura que se quiere editar más adelante, MIDI se queda corto por diseño, no por descuido: nunca prometió guardar eso.

Es también la razón de que un sistema de transcripción automática de música tenga que elegir con cuidado su formato de salida según el uso final: MIDI si el objetivo es que la transcripción suene, MusicXML si el objetivo es que alguien la lea, la corrija o la use para enseñar. En mi propia investigación doctoral trabajo con piano como corpus, y esta misma disyuntiva aparece en cuanto un sistema de AMT termina de decidir qué notas sonaron: el siguiente paso es en qué formato entregar ese resultado, y no es una decisión neutra.

Bibliografía

Las referencias en las que se apoya este artículo y por dónde seguir leyendo: