Fiche technique musicale 5
Quelques indications
pour lire un fichier en format Midi


1) Rappel sur le format des données informatiques
Le format Hexadécimal :

L'ordinateur parle en langage binaire (deux "digits" possibles : 0 ou 1). Ces digits sont regroupés en octets. (8 digits)
L'usage veut que, plutot que d'écrire les 8 digits à la file, on utilise la notation hexadécimale.
L'octet est alors divisé en deux groupes de 4 digits, chaque groupe donnant un chiffre en hexadécimal, noté de 0 à F. Un octet est donc codifié avec deux chiffres, par exemple F5 ou 3E.  Le premier chiffre hexadécimal (groupe de poids fort) est appelé du doux nom de MSN (Most Significant Nybble),  le second est appelé  LSN (Less Significant Nybble).

Valeure binaire
valeure hexadécimale
Valeur décimale
LSN
Valeure décimale
MSN

Valeure binaire valeure hexadécimale Valeure décimale
 LSN
Valeure décimale
MSN

0000
0
0
0 à 15

1000
8
8
128

0001
1
1
16 à 31

1001
9
9
144

0010
2
2
32 à...

1010
A
10
160

0011
3
3
48 à ...

1011
B
11
176











0100
4
4
64

1100
C
12
192

0101
5
5
80

1101
D
13
208

0110
6
6
96

1110
E
14
224 à 239

0111
7
7
112

1111
F
15
240 à 255


Exemple : le code hexadécimal 3E correspond au code binaire 0011 1110 ,
ce qui en décimal correspond à 48 ( hexa 3 en MSN) + 14 (hexadcimal E en LSN), soit 48+14 = 62

Evidemment il faut spécifier si on est en décimal ou hexadéimal (80 en hexa vaut 128 en décimal)

Le bit de tête :

Le premier "bit"  d'un octet peut être utilisé pour identifier une spécificité, et non pour donner une valeur nuérique. Par exemple pour différencier un octet de donnée d'un octet de commande.
Mais il est aussi utiliser pour indiquer que la valeur numérique de l'octet précédent continue dans l'octet suivant. Par exemple, en code Midi,  dans une donnée qui va indiquer la taille d'un champ, le premier bit à 1 signifie que la taille du champ (la longueur des données qui suivent) continue sur l'octet suivant :  la longeur pourra donc être codifiée sur 2 fois  7 bits ou n fois 7 bits. Onpeut ainsi codifier même une trés gande longueur..


exemple : valeur d'une série d'octets dans un champ de longeur variable

Valeure binaire
valeure hexadécimale
Valeur décimale 
0000 0001
(le nombre est codifié sur 7 bits)
01
1
0111 1111
7F
127
1000 00010000 0000
équivalent de     
       ..00 0000 1
000 0000
(le nombre n'est codifié que sur 14 bits)
80 00
équivalent de
            80
128
1000 00000000 0001
équivalent de     
       ..00 0000 1
000 0001
équivalent de
            81
129
1111 11110111 1111
équivalent de     
       ..11 1111 1
111 1111
équivalent de
            3F FF
faites le calcul
1000 0001 - 0000 00000000 0000
équivalent de     
       ...0 0000 01
00 0000 0000 0000
(le nombre est codifié sur 21 bits)
équivalent de
            40 00
faites le calcul




2) Le Fichier Midi

Un fichier Midi comporte deux grands types de données, regroupés en blocs (en anglais: Chunk) : le bloc d'entête et le ou les blocs pour décrire les pistes (= chaque portée).

Chaque bloc est lui même formé de trois parties:
Un premier mot de 4 octets qui indique le type de bloc (MThd = bloc d'en-tête, en anglais header;  MTrk = bloc de piste ; en anglais : track)
Un mot de 4 octets qui indique la longueur du bloc, c'est à dire le nombre d'octets de données qu'il contient .
Suivent les octets de données.

Voici un exmple: un bloc d'entête suivi d'un seul  bloc de piste.

section MIDI  <-------------Bloc d'en-tête------------> <---Entête de piste---> <---données--> <Fin de piste>
numero Octet 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [de 22 à x] [x+1 à x+4]
Valeur Octet 4D 54 68 64 00 00 00 06 00 00 00 01 00 80 4D 54 72 6B 00 00 00 0A bla bla bla... 00 FF 2F 00
Cf infra A---------> B---------> C---> D---> E---> F---------> G---------> H------------> I------------>


a) Le Bloc d'en-tête (MThd) :

Pour un fichier Midi, le bloc d'entête apparait toujours sous la forme suivante:
4D 54 68 64 00 00 00 06 ff ff nn nn dd dd

Il comporte trois parties :
* une première séquence de 4 octets qui signifie qu'on a affaire à un fichier midi (4D 54 68 64, qui correspond à la codification hexadécilale des lettres MThd)
*
une seconde séquence de 4 octets qui indique la longueur  de la séquence de données, enfin on trouve la séquence de  données, qui pour le bloc d'entete d'un fichoier midi sera toujours égale à 6 octets.
* enfin, un groupe de 6 octets de données explicités ci aprés.


A : 4 octets
Identification
4D 54 68 64 Fichier Midi (= code Ascii des lettres MThd)
B : 4 octets
Longueur
00 00 00 06 Les données de l'entête font 6 octets
C;D;E : variables
Données
ff ff nn nn dd dd voir ci-aprés

Trois types de données se trouvent dans l'entête: 

C : 2 Octets
Format 

00 00 ou
00 01 ou
00 02
Il y a pour l'instant 3 formats Midi posisbles:
format Midi 0 : 1 seule piste (16 canaux possibles)
format Midi 1 : plusieurs pistes simultanées
format Midi 2 : plusieurs pistes indépendantes (peu usité)
D : 2 Octets
Nombre de pistes différentes
dans le fichier Midi
("ntrks")
 nn nn Bien sûr, pour le format Midi 0, cette valeur est toujours égale à 00 01.
E : 2 Octets
Résolution temporelle (division) dd dd Pour faire simple, on dira que cette donnée fixe l'emplacement des barres de mesures : elle donne en nombre de pulsions élémentaires - appelées tick d'horloge- la durée d'une noire (en anglais "quart de note"), donc du "temps musical".
On n'en dira pas plus ici, car cela devient vite abstrait et compliqué... Bon, simplement pour détailler un peu: Il y a deux octets donc 16 bits.
Si le premier bit est à zéro, c'est ce qu'on a dit. S'il est à un, c'est plus compliqué.

 

b) Bloc de piste MTrk :

L'entéte est suivie par un certain nombre de blocs de piste qui dépend du format de fichier (Midi 0, Mdi 1 ou Midi 2) et, bien sûr, du nombre de pistes.(Le format Midi 0 n'en comporte évidemment  qu'un seul.)

Il comporte trois parties :
* une première séquence de 4 octets qui signifie qu'on a affaire à un bloc de piste (4D 54 68 64, qui correspond à la codification hexadécilale des lettres MThd)
* une seconde séquence de 4 octets qui indique la longueur  totale du bloc
* enfin les données.
Il est terminé par une indication de fin de bloc.(FF 2F 00) qui est redondante avec la longueur du bloc donnée précédemment

4 octets
Identification
4D 54 72 6B
début de bloc (= code des lettres MTrk)
4 octets
Longueur
00 00 00 22 Longueur variable : ici 22 en hexadécimal =  2*16+2= 34 octets
variables
Données

voir ci-aprés
Fin de bloc

tt FF 2F 00 Il s'agit d'une valeur de données particulière qui confirme la fin des données (également indiquée par la longeur des données)


Plusieurs types de données sont possibles: cela peut être des "évènements Midi" (les notes de musique), des messages système (pour controler différents paramètres d'éxécution diffusés aux appareils raccordés) ou des "évènements non-Midi" (ou méta-évènements, essentiellement des textes comme titre, compositeur, paroles, mais aussi indications  de tempo, armure,  etc...)

On ne parlera pas ici des messages systèmes, spécifiques à chaque contructeur d'instrument electronique


Les Evenements Midi
Un évènement MIDI se compose de deux parties : un élément temporel et un évènement proprement dit composé d'un octet de commande et  (en général) de deux octets de données.
L'élément temporel indique le nombre de ticks d'horloge depuis le dernier évènement. Si le nombre de ticks est inférieur à 127, il est codifié sur un seul octet. Sinon, il est codifié sur plusieurs octets selon ce qui a été dit plus haut (voir
valeur d'une série d'octets dans un champ de longeur variable)


L'octet de commande est de la forme : « 1
sss xxxx »:
*  le premier bit de l'octet doit être égal à 1 pour indiquer qu'il s'agit d'un octet de commande
*  le reste du premier demi-octet ( donc sur 3 bits : sss) indique la commande proprement dite. Il y a 8 commandes Midi possibles
*  Le second demi octet (xxxx) est le numéro de canal midi (qui correspond au choix d'un instrument) sur lequel la commande s'applique (noté x dans le tableau ci aprés). Il y a donc 16 canaux midi  possibles (16 instruments différents dans la même piste)

L'octet de donnée est de la forme
« 0 zzz zzzzz »:
Les deux octets de données peuvent correspondre à des données différentes. Mais dans certains cas et selon le type de données, ils peuvent aussi être lus ensembles pour donner une seule valeur. La donnée est alors sur 14 bits, puisque le premier bit à 0 est à éliminer (cf supra)

Le Running status

Le mode «running status»  permet de gagner quelques octets, donc de la mémoire et du temps de traitement. Pour deux ou plusieurs évènements successifs, si l'octet de commande est le même,  (par exemple plsuieurs débuts de notes), on ne répète pas l'octet de commande et on passe directement à loctet de donnée. Voir l'exemple plus bas


 

Format général de message MIDI

0ctet         <--- octet de statut ---> <----- Données 1 -----> <----- Données 2 ----->
numero bit 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
Valeur bit 1 s s s x x x x 0 n n n n n n n n 0 y y y y y y y
Cf infra A B-----> C---------> D E---------------------> F G----------------->
type de numero de données données
message   canal

Le principe de codage d'une note est d'indiquer par un "évènement midi" le début et la fin de la note (et non le début de la note et sa durée comme dans la notation musicale classique).
Outre la date de l'évènement (début ou fin), une note sera caractérisée par son numéro de note (0 à 127), sa "vélocité" (c'est à dire la force avec la quelle elle est jouée) et le numéro de canal (= l'instrument) où elle doit être adressée (0 à 15)

Quels sont les messages midi possibles ?

Message

octet de statut

Données 1

Données 2

Description

Messages de canal

Note off

8 x

nn
Hauteur note

vv
Vélocité

Fin d’une note avec dynamique pour sa disparition

Note on

9 x

nn
Hauteur note

vv
Vélocité

Début d’une note avec force d’appui ou vitesse d’enclenchement

Polyphonic after touch

A x

nn
Hauteur note

vv
Vélocité

donne pour la suite la vélocité vv du son de hauteur nn sur le canal x: ce n'est pas une nouvelle note mais une manière de jouer différente la note en cours

Control change

B x

cc
No de contrôleur

vv
Valeur

L'évènement envoie au controleur cc la valeur vv pour action.

Chaque instrument (chaque fabricant d'instrument) possède ses propres controleurs (par exemple : pédale, sourdine...)

Program change

C x

pp
N
ode programme

non utilisé

Changement d’instrument pour le canal demandé

Canal After touch

D x
vv
valeur
non utilisé
donne pour la suite la vélocité vv à toutes les notes du canal x

Pitch bend

E x

bb 


tt

Le picth bend est un contrôle qui change légèrement la hauteur de la (les) note jouée vers le haut ou vers le bas.. La Position centrale (note "juste") est  à 00 40

Messages systèmes
Fx


Pour mémoire, on a dit qu'on en parlerait pas.

 

Exemple : enchainement du début de Ah vous dirai-je Maman  :(Fa Fa Do Do Ré Ré Do)


Note     <Début Fa > <--- Fin Fa--->  <Début Fa >  <--- Fin Fa--->  < Début Do >  ...
N° Octet 1 2 3 4 1 2 3 4 5 1 2 3 4 1 2 3 4 5 1 2 3 4
00 80 41 40 81 40 80 41 40 00 90 41 40 81 40 80 41 40 00 90 48 40





Méta-évènements
Les méta-évènements commencent par une séquence du type tt FF.
Le second octet ayant la valeur hexadécimale FF indique qu'il s'agit d'un méta évènement.
Le premier octet indique le "delta temps musical" de l'évènement par rapport à l'évènement précédent, souvent 00 pour un méta évènement (le nombre indiqué correspond au nombre d'impulsion d'horloge entre les deux évènements) .

La liste complète des codifications se trouve sur intenet. Sans être exhaustif, les principaux méta-évènements à retenir sont

Texte tt FF 01 ll xx
tt FF 02  ll xx
tt FF 03  ll xx
tt FF 04 ll xx
tt FF 05  ll xx
longueur (en nombre d'octets) - texte

Ces évènements sont utilisés pour insérer un commentaire.
Certaines informations, habituelles dans les fichiers midi, comme le copyright, les paroles, le nom des pistes, etc... ont leur propre codage (02, 03,...)
.  

Marqueur tt FF 06  ll xx

Met une marque à un moment précis. La signification de la marque est donnée par le texte

Changement de Tempo tt FF 51 03 tt tt tt tt tt tt durée d'une "noire" (unité de temps) en microsecondes
soit 60,000,000 / 'tt tt tt' battements par mn

Le tempo dans un fichier midi s'exprime en nombre  d'unités élémentaires de temps (une microseconde) par "noire". 
Nota: si aucune indication de tempo n'est donnée, alors le tempo est égal à 120 battements par minutes
 

Time signature tt FF 58 04 nn dd cc bb 'nn' / 'dd'  représente la mesure comme notée sur une partition (2/4, 6/8...).
Attention dd est à comprendre comme une puissance de deux (22= 4 ; 23=8 ; exemple 2/4 se note 02 02; 6/8 se note 06 03)
Par défaut, c'est la valeur 4/4 qui est retenue (04 02)

'cc' nombre de "Midi clock" dans un clic de métronome. Un "Midi clock" est égal à  1/24 de "noire (unité de temps)"

'bb' : pour la notation écrite, valeur de la triple croche enen 1/32 durée d'une noire, 24 le plus souvent
paramètre bb exprime le nombre de note dans 24 MIDI clocks

Nota: Par défaut, en l'absence d'indication par un méta-évènement, la mesure est égale à  4/4.

Clé tt FF 59 02 sf mi sf  : -7 pour 7 bémols, -1 pour 1 bémol, 1 pour 1 dièse, 0 pour aucune altération etc
mi
: 0 mode majeur ou 1 mode mineur





c) Exemple complet d'interprétation d'un fichier midi

Voici une partition créée sous harmony assitant
partition de Ah vous dirai-je Maman

En voici l'image du fichier Midi obtenue avc un éditeur hexa décimal
Ah! vou dirai-je maman en hexadécimal

                    Ligne 0000000, colonne 0
4D 54 68 64 : début du bloc d'entête
00 00 00 06 :  Longeur de l'entête
00 01 :    Fichier Midi 1
00 02 :    Deux blocs de piste à venir
00 C0 : tempo : 192 temps élémentaire par noire


                    Ligne 0000000, colonne E
4D 54 72 6B : début du bloc de la première piste
00 00 00 5A : Longueur du bloc : 90 octets

00 FF 03 : indication que le titre va suivre
1B : longeur du titre :  26 octets
41 68 20 21... 61 6E 20 3F 00 :  "Ah! vous dirais-je Maman" (codification Ascii)

                   Ligne 0000003, colonne 5
00 FF 02 0E : indication que le compositeur va suivre sur une longueur de 14 (0E) octets
43 6F...20 3A 00 : "Compositeur"

00 FF 01 0C: commentaire libre  sur 12 (0C) octets
52 65...20 3A 00 : "Remarques"

                    Ligne 0000005, colonne 7
00 FF 51 03 : indication sur le tempo
07 A1 20 : valeur du tempo

00 FF 58 04 : indication de métronome
02 02 : C'est du 2/4
18 : 24 impulsions d'horloge par click de métronome
08 : durée d'une noire 8/32= 1/4

00 FF 59 02 Clé
FF :  -1 ==>1 bémol à la clé
00 : mode Majeur

00 FF 2F 00 Fin du premier bloc de piste, qui, ici,  ne contient pas de note mais uniquement des indications générales

                    Ligne 0000007, colonne 1
4D 54 72 6B Second bloc de piste
00 00 00 A3 :Longueur du second bloc de piste : 163 octets

00 FF 21 01 00 : Port midi numero 0

00 FF 09 1F : Nom du port de périphérique (instrument) sur 31 (1F) octets
52 69 70 .. 72 00 :  il s'agit d'un Synthétiseur

                    Ligne 000000A, colonne 1
00 FF 03 08: Nom de la piste sur 8 octets
4D E9 6C 6F 64 69 65 00 : "Mélodie"

Il s'ensuit une série de commande de controle
00 B0 20 00 : controle change
00 B0 00 00 : controle change
00 C0 00  : programme change pour le programe 00
00 B0 65 00: controle change
00 B0 64 00: controle change
00 B0 06 18: controle change
00 B0 07 7F : controle change
00 E0 00 40: "pitch Bend" à 40 : pas de "désaccordage " de la note
00 B0 0A 40 : controle change


                        Ligne 000000C, colonne F
Début de la partition proprement dite
00 90 41 40 : Simultanément à l'évènement précédent(00), début de la note(90) qui est un Fa2 (41) avec une vélocité de 64 (40)
81 40 80 41 40 : Aprés une durée d'une noire (81 40 = 320 clicks ), fin de la note (80) qui est un Fa2 (41) à la vélocité de 64 (40)

00 90 41 40 : Simultanément à l'évènement précédent,  début note Fa 2
81 40 80 41 40 : fin note Fa 2, qui a duré une noire

                       Ligne 000000E, colonne 2
00 90 48 40 :  début de la note DO3 (48)
81 40 80 48 40 : fin  note Do3

00 90 48 40 :  début note DO3
81 40 80 48 40 : Fin note DO 3

                       Ligne 000000F, colonne 4
00 90 4A 40 : début note Ré 3
81 40 80 4A 40 :  fin note Ré 3

00 90 4A 40 : début note Ré 3

                         Ligne 0000010, colonne 4
81 40 80 4A 40 : fin note Ré 3

00 90 48 40  : début note DO 3
83 00 80 48 40 : fin de note DO 3

DA 03 B0 7B 00 : message controle change
00 B0 78 00 : message controle change

00 FF 2F 00  Fin du bloc de piste

Par comparaison : la même partition créée sous cubasis, beaucoup plus courte.
fichier Hexa de Maman créé sous cubasis


Bon. On va reprendre la partie partition en 63 octets
          00 90 41 40 : Début  note Fa2   vélocité de 64
          81 40 80 41 40 : Fin de  note  Fa2  vélocité de 64
          00 90 41 40 :  début note Fa 2
          81 40 80 41 40 : fin note Fa 2,
          00 90 48 40 :  début de la note DO3
          81 40 80 48 40 : fin  note Do3
          00 90 48 40 :  début note DO3
          81 40 80 48 40 : Fin note DO 3
          00 90 4A 40 : début note Ré 3
          81 40 80 4A 40 :  fin note Ré 3
          00 90 4A 40 : début note Ré 3
          81 40 80 4A 40 : fin note Ré 3
          00 90 48 40  : début note DO 3
          83 00 80 48 40 : fin de note DO 3

On voit qu'il y a trois notes, fa, do et ré, qui tantot sont jouées et résonnent, tantot ne résonnent pas. Plutot que de mettre une fin de note et un début de note (deux commendes différentes), on peut mettreremplacer la commande "fin de note" par une commande "début de note à vélocité 0". Pur éviter la confusion on va les faire arreter juste avant le début de note suivante
          00      90 41 40 : Début  note Fa2 (41)  vélocité de 64
          81 39 90 41 00 : Passage  note  Fa2  en vélocité 0
          01      90 41 40 : Aprés une durée d'1 tick ,  début note Fa 2 avec vélocité 1
          81 39 90 41 00 :  Fa 2 en vélocité 0
          01      90 48 40 :  début de la note DO3 (48)
          81 39 90 48 00 : Vélocité 0  note Do3
          01      90 48 40 :  Vélocité 64 DO3
          81 39 90 48 00 : Vélocité 0 note DO 3
          01      90 4A 40 : début note Ré 3
          81 39 90 4A 00 : Vélocité 0 note Ré 3
          01      90 4A 40 : Vélocité 64 note Ré 3
          81 39 90 4A 00 : Vélocité 0 note Ré 3
          01      90 48 40  : Vélocité 64 note DO 3
          83 00 90 48 00 : Vélocité 0 de note DO 3

Maintenant, on applique le "running statut", donc on ne répète pas les octets d'évènements quand ils sont identiques, ici l'octat 90 qui indique le note ON

         00 90 41 40 : SDébut  note Fa2  vélocité de 64
         81 39  41 00 : Aprés une durée d'une noire moins 1 tick, passage  note  Fa2  en vélocité 0
         01       41 40 : Aprés une durée d'1 tick,  passage note Fa 2 en vélocité 64
         81 39  41 00 : Passage Fa 2 en vélocité 0
         01       48 40 : Début de la note DO3 en vélocité 64
         81 39  48 00 : Vélocité 0  note Do3
         01       48 40 :  Vélocité 64 note DO3
         81 39  48 00 : Vélocité 0 note DO 3
         01       4A 40 : Début note Ré 3 en vélocité 64
         81 39  4A 00 : Vélocité 0 note Ré 3
         01       4A 40 : Vélocité 64note Ré 3
         81 39  4A 00 : Vélocité 0 note Ré 3
         01       48 40  : Vélocité 64 Note DO 3
         83 00 48 00 : Vélocité 0 de note DO 3
Et on n'a plus que 50 octets.