Outils pour utilisateurs

Outils du site


issue191:python

Ceci est une ancienne révision du document !


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.

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.

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.

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.

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.

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

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

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.

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.

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!

issue191/python.1680442066.txt.gz · Dernière modification : 2023/04/02 15:27 de d52fr