Outils pour utilisateurs

Outils du site


issue191:python

When a friend of mine saw last month’s article, he asked if I could do something on Midi. I thought that would be a fun article, so here it is… Let’s take a quick look at the history of Midi. Way back in 1981, the first MIDI standard was created. In 1982, the Prophet-600 synth was the first synth to feature the standard. MIDI was designed as a method for connecting various pieces of electronic musical equipment. And it's done the job pretty well for over 40 years. The original spec was to use 2 5-pin DIN connectors, one for input and one for output. That was changed to allow a Thru port, which takes the input data and sends it directly out to other equipment. These days, this has been extended again to support USB ports. Midi is all about messages. There is no actual audio or sound sent by MIDI. Let's take a look at the types of messages sent.

Lorsqu'un de mes amis a vu l'article du mois dernier, il m'a demandé si je pouvais faire un article sur MIDI. J'ai pensé que ce serait un article amusant, alors le voici…

Jetons un coup d'œil rapide à l'histoire de MIDI.

C'est en 1981 que la première norme MIDI a été créée. En 1982, le synthétiseur Prophet-600 a été le premier synthé à intégrer cette norme. MIDI a été conçue comme une méthode permettant de connecter différents équipements musicaux électroniques. Depuis plus de 40 ans, elle remplit parfaitement sa mission.

La spécification originale prévoyait l'utilisation de deux connecteurs DIN à 5 broches, un pour l'entrée et un pour la sortie. Cette spécification a été modifiée pour permettre un port Thru, qui prend les données d'entrée et les envoie directement à d'autres équipements. Aujourd'hui, ce système a été étendu pour prendre en charge les ports USB.

MIDI est une affaire de messages. Il n'y a pas de son ou d'audio envoyé par MIDI. Examinons les types de messages envoyés.

When you press a key on a midi keyboard, the controller in the keyboard sends an event message that not only has the pitch of that key, but it tells the sound module (synth) to start playing the note. Once you let up on the key, another message to stop playing that note. There are also messages that correspond to the velocity (how hard the key was “hit”), the aftertouch or how hard the key was held down, the pitch bend, pan, modulation, volume, and any other controllable functions. MIDI supports a total of 128 notes which range from C five octaves below middle C to G ten octaves above middle C. It also supports 16 channels (for 16 separate devices), as well as 128 patches (or programs), MIDI clock pulses, and timing sync signals between the various pieces of equipment. In addition to all of that, there are System Exclusive (SysEx) messages that are designed to send messages specific to a manufacturer's equipment that contain a manufacturer specific ID and commands that can be safely ignored by devices not of the manufacturer's product list. You can see that MIDI is a rather busy protocol.

Lorsque vous appuyez sur une touche d'un clavier MIDI, le contrôleur du clavier envoie un message d'événement qui indique non seulement le ton de cette touche, mais aussi invite le module sonore (synthé) à commencer à jouer la note. Lorsque vous relâchez la touche, un autre message indique au module de son (synthé) d'arrêter de jouer la note. Il existe également des messages correspondant à la vélocité (la force avec laquelle la touche a été « frappée »), à l'aftertouch (la force avec laquelle la touche a été maintenue enfoncée), au pitch bend, au panoramique, à la modulation, au volume et à toute autre fonction contrôlable.

MIDI prend en charge un total de 128 notes qui vont du do cinq octaves en dessous du do moyen au sol dix octaves au-dessus du do moyen. Il prend également en charge 16 canaux (pour 16 appareils distincts), ainsi que 128 patchs (ou programmes), des impulsions d'horloge MIDI et des signaux de synchronisation entre les différents équipements. En plus de tout cela, il existe des messages exclusifs au système (SysEx) qui sont conçus pour envoyer des messages spécifiques à l'équipement d'un fabricant et qui contiennent un identifiant spécifique au fabricant et des commandes qui peuvent être ignorées en toute sécurité par les appareils qui ne font pas partie de la liste de produits du fabricant. Vous pouvez constater que MIDI est un protocole plutôt chargé.

I went out on the Internet searching for Python libraries that handle Midi and I found a number of them. The best one looked to be a package called Mido. The github repository can be found at https://github.com/mido/mido. python3 -m pip install mido You will also need Fluidsynth if you want to listen to the midi files. sudo apt-get install fluidsynth You also need to have at least one soundfont file for Fluidsynth. These files contain information on each of the instruments that the midi file should play. You can check your /usr/share/sounds/sf2 folder for these files. The most popular file is named FluidR3_GM.sf2 and the GM stands for “General Midi”. If you don’t have them, check your software manager or the Internet. Most of them are available for free. I then decided to throw together a quick program that will look for certain messages,capture that data, and finally print them out. These messages are called meta messages and carry information about the name of the track (which often holds the name of the instrument, but not always), the tempo of the song, the key signature, the time signature, and more.

J'ai cherché sur Internet des bibliothèques Python qui gèrent MIDI et j'en ai trouvé un certain nombre. La meilleure semble être un paquet appelé Mido. Le dépôt github se trouve à l'adresse https://github.com/mido/mido.

python3 -m pip install mido

Vous aurez également besoin de Fluidsynth si vous voulez écouter les fichiers midi.

sudo apt-get install fluidsynth

Vous devez également avoir au moins un fichier soundfont pour Fluidsynth. Ces fichiers contiennent des informations sur chacun des instruments que le fichier MIDI doit jouer. Vous pouvez consulter votre dossier /usr/share/sounds/sf2 pour trouver ces fichiers. Le fichier le plus populaire s'appelle FluidR3_GM.sf2 où GM signifie « General MIDI ». Si vous ne les avez pas, consultez votre gestionnaire de logiciels ou Internet. La plupart d'entre eux sont disponibles gratuitement.

J'ai ensuite décidé de créer un programme rapide qui recherchera certains messages, capturera ces données et les imprimera. Ces messages sont appelés méta-messages et contiennent des informations sur le nom de la piste (qui contient souvent le nom de l'instrument, mais pas toujours), le tempo du morceau, la tonalité, la signature temporelle, et plus encore.

I named the program mido_test.py just as a test bed. While the code shows the “default” midi file to work with is “cantaloop.mid”, the output examples will use the file “Bob_Seger_Turn_The_Page.mid”. It is a good example of how a Midi file can be used for more than just music. It turned out that it worked well enough that I felt ok using it as a demo. As always, we start with the import section of the program. import sys import os import subprocess import mido from mido import MidiFile, Message, tempo2bpm import shared Notice I import a file called shared. If you are not familiar with this trick, it’s simply an empty file named shared.py that is used to limit the number of globals used in a program and to share variable data between different program modules. We have only one module, but it’s a neat trick, so I used it this time.

J'ai nommé le programme mido_test.py pour le tester. Alors que le code indique que le fichier MIDI « par défaut » à utiliser est « cantaloop.mid », les exemples de sortie utilisent le fichier « Bob_Seger_Turn_The_Page.mid ». C'est un bon exemple de la façon dont un fichier MIDI peut être utilisé pour autre chose que de la musique.

Il s'est avéré qu'il fonctionnait suffisamment bien pour que je puisse l'utiliser comme démo. Comme toujours, nous commençons par la section d'importation du programme.

import sys import os import subprocess import mido from mido import MidiFile, Message, tempo2bpm

import shared

Remarquez que j'importe un fichier appelé shared. Si vous ne connaissez pas cette astuce, il s'agit simplement d'un fichier vide nommé shared.py qui est utilisé pour limiter le nombre de globales utilisées dans un programme et pour partager des données variables entre différents modules du programme. Nous n'avons qu'un seul module, mais c'est une astuce intéressante, alors je l'ai utilisée cette fois-ci.

Next we have the main function called work_it() shown top right. We start by calling a function called ports that mido uses to determine where to send the midi data, assuming we use that portion of the library. I don’t, I send the data directly to Fluidsynth, but we’ll see that later on. Then, we define the filename of the midi file we are interested in, and pass that to the MidiFile function of mido and get back an object called mid. We set the outport for the mido library, then we set up the shared variables. You need to initialize any shared variables before you try to read them, so I set everything we might possibly use in this function. outport = “TiMidity:TiMidity port 0 128:0” setup_vars() Next, we send the mid object to the parse_midi_file function that will grab each message, and if that message is a meta message, it will grab the information. Only some of the messages really have information that I wanted, but I do look at all of the meta messages that come through.

Ensuite, nous avons la fonction principale appelée work_it() montrée en haut à droite.

Nous commençons par appeler une fonction nommée ports que mido utilise pour déterminer où envoyer les données MIDI, en supposant que nous utilisions cette partie de la bibliothèque. Ce n'est pas le cas et j'envoie les données directement à Fluidsynth, mais nous verrons cela plus tard.

Ensuite, nous définissons le nom du fichier MIDI qui nous intéresse, et nous le passons à la fonction MidiFile de mido pour obtenir en retour un objet appelé mid.

Nous définissons le port de sortie de la bibliothèque mido, puis nous configurons les variables partagées. Vous devez initialiser toutes les variables partagées avant d'essayer de les lire, donc j'ai défini tout ce que nous pourrions utiliser dans cette fonction.

  outport = "TiMidity:TiMidity port 0 128:0"
  

setup_vars()

Ensuite, nous envoyons l'objet mid à la fonction parse_midi_file qui va récupérer chaque message et si ce message est un méta-message, il va récupérer l'information. Seuls certains des messages contiennent vraiment l'information que je veux, mais je regarde tous les méta-messages qui arrivent.

Once the file has been read, I print out the tempo, time signature, key signature, the information for each track, and the length of the song in minutes/seconds (shown middle right). Finally, the midi file is sent to Fluidsynth for it to play the midi file. I use subprocess to send it out. Easy, but it does create a blocking call. If you want to terminate the play function, simply do a <Ctrl> C in the terminal window (bottom right). You need to pass the name of the soundfont file that contains all the instruments that Fluidsynth will use to play the midi file. Now we will look at the setup_vars function. Again, this sets up the different variables. I’ll only include a short snippet of the function here (next page, top right). Now for the important function, the parse_midi_file() function. Again, I’ll only include a portion of the function for brevity (middle right). We use the mido library to step through each message in the Midi file. There are only a few messages that I was interested in when I designed the program. One of them is the track_name message (bottom right).

Une fois le fichier lu, j'imprime le tempo, la signature temporelle, la tonalité, les informations pour chaque piste et la durée du morceau en minutes/secondes (au milieu à droite).

Enfin, le fichier midi est envoyé à Fluidsynth pour qu'il le joue. J'utilise subprocess pour l'envoyer. C'est facile, mais cela crée un appel bloquant. Si vous voulez mettre fin à la fonction de lecture, faites simplement un <Ctrl> C dans la fenêtre du terminal (en bas à droite).

Vous devez transmettre le nom du fichier soundfont qui contient tous les instruments que Fluidsynth utilisera pour jouer le fichier MIDI.

Nous allons maintenant examiner la fonction setup_vars. Une fois de plus, cette fonction définit les différentes variables. Je n'inclurai ici qu'un court extrait de la fonction (page suivante, en haut à droite).

Passons maintenant à la fonction la plus importante, la fonction parse_midi_file(). Là encore, je n'inclurai qu'une partie de la fonction par souci de concision (au milieu à droite).

Nous utilisons la bibliothèque mido pour parcourir chaque message du fichier MIDI. Seuls quelques messages m'intéressaient lorsque j'ai conçu le programme. L'un d'entre eux est le message track_name (en bas à droite).

Here is what the message itself looks like when mido passes it back. mesg=“('track_name', name='Soft karaoke', time=0)” mesg=“('track_name', name='Electric Piano', time=0)” Notice that while the track name contains the name of that track, it doesn’t necessarily contain the actual instrument name that the soundfont uses. That comes from a non-meta message called program_change. In addition, you need to check another message called control_change as well, just in case the instrument is in a bank other than bank 0. (I know this doesn’t make much sense without a whole lot of explanation on the midi format and the soundfont format as well. Maybe we’ll look at those in a future article). Anyway, you can see I convert the actual message to a string, then parse the string to pull out the information that I’m interested in. Another message that I was interested in is the tempo or number of beats per minute of the song. The midi format specifies that the tempo is saved as the number of microseconds per quarter note. Luckily, mido provides a function called tempo2bpm to convert this to “human readable” information (bottom left).

Voici à quoi ressemble le message lui-même lorsque mido le renvoie.

mesg=“('track_name', name='Soft karaoke', time=0)”

mesg=“('track_name', name='Electric Piano', time=0)”

Notez que si le nom de la piste contient le nom de cette piste, il ne contient pas nécessairement le nom de l'instrument utilisé par la soundfont (banque de son). Cela provient d'un message non méta appelé program_change. De plus, vous devez également vérifier un autre message appelé control_change, juste au cas où l'instrument se trouve dans une banque autre que la banque 0. (Je sais que cela n'a pas beaucoup de sens sans un grand nombre d'explications sur le format MIDI et le format soundfont également. Nous y reviendrons peut-être dans un prochain article).

Quoi qu'il en soit, vous pouvez voir que je convertis le message en une chaîne, puis que j'analyse cette chaîne pour en extraire les informations qui m'intéressent.

Un autre message qui m'intéresse est le tempo ou le nombre de battements par minute du morceau. Le format MIDI spécifie que le tempo est sauvegardé en tant que nombre de microsecondes par noire. Heureusement, mido fournit une fonction appelée tempo2bpm pour convertir cette information en information « humainement lisible » (en bas à gauche).

Time signature is also a message I was interested in. This is normally seen as a fraction that shows how many of a particular note value are contained in each measure. For example, if the time signature is 4/4, that means that the measure can hold up to 4 quarter notes (one per beat). It also means that if the measure has a whole note it will take all 4 of the beats. If you are old enough to remember the song Money by Pink Floyd, that song has a time signature of 7/4, which means there are 7 beats (quarter notes) in each measure. We have to obtain the numerator and denominator to use this information (top right). The final message I was really interested in was the key signature, which is used to determine how many sharps or flats there are in the scale for this song. A key of C, means that there are normally no sharps or flats, so the scale is C, D, E, F, G, A, B. If the key is G, that means that there is one sharp in the scale, so it would be C, D, E, F#, G, A, B (middle right). Yes, most of this information is really interesting to only a musician, but I am one, so it’s important to me. No apologies. After I got the parsing function done, I threw together a GUI version of the program that looks something like that shown bottom left.

La signature temporelle est également un message qui m'intéresse. Il s'agit normalement d'une fraction qui indique combien de notes d'une valeur particulière sont contenues dans chaque mesure. Par exemple, si la signature temporelle est 4/4, cela signifie que la mesure peut contenir jusqu'à 4 noires (une par battement). Cela signifie également que si la mesure contient une note entière, elle occupera les 4 battements. Si vous êtes assez âgé pour vous souvenir de la chanson Money de Pink Floyd, cette chanson a une signature temporelle de 7/4, ce qui signifie qu'il y a 7 battements (noires) dans chaque mesure. Nous devons obtenir le numérateur et le dénominateur pour utiliser cette information (en haut à droite).

Le dernier message qui m'intéresse vraiment est la tonalité, qui est utilisée pour déterminer combien de dièses ou de bémols il y a dans la gamme de cette chanson. Une tonalité de do signifie qu'il n'y a normalement pas de dièses ou de bémols, donc la gamme est do, ré, mi, fa, sol, la, si. Si la tonalité est sol, cela signifie qu'il y a un dièse dans la gamme, donc elle serait do, ré, mi, fa#, sol, la, si (au milieu à droite).

Oui, la plupart de ces informations ne sont vraiment intéressantes que pour un musicien, mais j'en suis un, donc elles sont importantes pour moi. Pas d'excuses.

Une fois la fonction d'analyse terminée, j'ai créé une version du programme avec une interface utilisateur graphique qui ressemble à ce qui est montré en bas à gauche.

This gives me the ability to choose the midi file I’m interested in and see the track names, song length, time signature, etc. easily, in one quick glance, as well as play the file if I want. I used a scrolled listbox to hold the track names for songs that have many tracks, like the Mars midi file. The Mars midi file uses 27 (28 if you consider track 0) different tracks and instruments. In addition, there are many tempo changes as well. I’ve included the GUI file source as well as a few sample midi files in the repository. Admittedly, Midi is a very old format and many of the free and publicly available files out there on the Internet are either incomplete, klutzy and badly done, don’t correctly follow the format, or a combination of all three. However, there are lots available that are very well done. You might ask why anyone would bother, since MP3 and WAV files are so readily available. I for one, use the midi files as what are called “backing tracks”. With Midi, and a proper player, you can turn off any of the tracks so they don’t play so you can practice vocals, keyboards, drums, guitar, or any other instrument for a song. Many beginner musicians and semi-professionals use this while the rest of the band is not available. With the proper software, you can vary the speed, change the key of the song without affecting the timing of the notes, and much more. So while Midi is not quite as popular any more, it still is a very powerful tool for musicians.

Cela me permet de choisir le fichier MIDI qui m'intéresse et de voir les noms des pistes, la durée de la chanson, la signature temporelle, etc. d'un seul coup d'œil, ainsi que de jouer le fichier si je le souhaite. J'ai utilisé une liste déroulante pour contenir les noms des pistes pour les chansons qui ont plusieurs pistes, comme le fichier MIDI de Mars.

Le fichier MIDI de Mars utilise 27 (28 si l'on considère la piste 0) pistes et instruments différents. De plus, il y a de nombreux changements de tempo.

J'ai inclus la source du fichier GUI ainsi que quelques exemples de fichiers midi dans le dépôt.

Il faut admettre que le format MIDI est très ancien et que de nombreux fichiers gratuits et accessibles au public sur Internet sont soit incomplets, soit maladroits et mal faits, soit ne respectent pas correctement le format, soit une combinaison de ces trois éléments. Cependant, il y a beaucoup de fichiers disponibles qui sont très bien faits.

On peut se demander pourquoi on se donnerait la peine de le faire, puisque les fichiers MP3 et WAV sont si facilement disponibles. Pour ma part, j'utilise les fichiers MIDI comme ce que l'on appelle des « pistes d'accompagnement ». Avec MIDI et un lecteur approprié, vous pouvez désactiver n'importe quelle piste pour qu'elle ne soit pas jouée et que vous puissiez vous entraîner au chant, au clavier, à la batterie, à la guitare ou à tout autre instrument pour une chanson. De nombreux musiciens débutants et semi-professionnels utilisent cette méthode lorsque le reste du groupe n'est pas disponible. Avec le logiciel approprié, vous pouvez varier la vitesse, changer la tonalité du morceau sans affecter le timing des notes, et bien plus encore. Ainsi, même si MIDI n'est plus aussi populaire, il reste un outil très puissant pour les musiciens.

One of the things that I REALLY enjoy doing (when I have some free time) is to load a midi file in LMMS and change the instruments for some of the tracks. I’ve done some very interesting things with midi files for Mars (by Gustav Holst (actually ALL of the available Planets files)), and for Pictures At an Exhibition by Modest Mussorgsky way back in 1874. If you are a fan of artists like Isao Tomita or Wendy Carlos (Switched on Bach), you can change the instruments into really strange, but enjoyable pieces of work, without having to touch a keyboard. If you don’t know what LMMS is, check out Full Circle Magazine issues 165 to 173 (January 2021 to September 2021) written by our own ErikTheUnready. They are a great introduction to using LMMS to create electronic music! (Thank you Erik!) You can find the code at my repository at https://github.com/gregwa1953/FCM-191 . End note: If you have issues with not being able to play midi files on your system, you might try to install the FluidSynth Midi Synthesizer plugin for VLC and/or TiMidity which, according to the website (https://timidity.sourceforge.net/#info )… “TiMidity++ is a software synthesizer. It can play MIDI files by converting them into PCM waveform data; give it a MIDI data along with digital instrument data files, then it synthesizes them in real-time, and plays. It can not only play sounds, but also can save the generated waveforms into hard disks as various audio file formats.” Until next time, as always; stay safe, healthy, positive and creative!

Une des choses que j'aime VRAIMENT faire (quand j'ai un peu de temps libre) est de charger un fichier MIDI dans LMMS et de changer les instruments pour certaines pistes. J'ai fait des choses très intéressantes avec des fichiers MIDI pour Mars, de Gustav Holst (en fait TOUS les fichiers Planets disponibles), et pour Tableaux d'une exposition de Modeste Mussorgsky en 1874. Si vous êtes un fan d'artistes comme Isao Tomita ou Wendy Carlos (Switched on Bach), vous pouvez transformer les instruments en œuvres vraiment étranges, mais agréables, sans avoir à toucher un clavier. Si vous ne savez pas ce qu'est LMMS, lisez les numéros 165 à 173 (janvier 2021 à septembre 2021) de Full Circle Magazine, écrits par notre ErikTheUnready. C'est une excellente introduction à l'utilisation de LMMS pour créer de la musique électronique ! (Merci Erik !)

Vous pouvez trouver le code sur mon dépôt à https://github.com/gregwa1953/FCM-191.

Note de fin : Si vous ne parvenez pas à lire les fichiers MIDI sur votre système, vous pouvez essayer d'installer le plugin FluidSynth Midi Synthesizer pour VLC et/ou TiMidity, que le site Web https://timidity.sourceforge.net/#info décrit ainsi : « TiMidity++ est un synthétiseur logiciel. Il peut lire des fichiers MIDI en les convertissant en données de forme d'onde PCM ; il peut recevoir des données MIDI ainsi que des fichiers de données d'instruments numériques, puis les synthétiser en temps réel et les jouer. Il peut non seulement jouer des sons, mais aussi enregistrer les formes d'onde générées sur des disques durs sous différents formats de fichiers audio. »

Jusqu'à la prochaine fois, comme toujours, restez en sécurité, en bonne santé, positifs et créatifs !

issue191/python.txt · Dernière modification : 2023/04/05 11:35 de auntiee