Search code examples
pythonmidimidi-instrumentmido

Select GM MIDI Level 2 instruments using the Python Mido library


I'm using the Python Mido library to create MIDI files. I've figured out that to change the instrument you add a program_change message to the track for the given channel:

from mido import Message, MidiFile, MidiTrack
track = MidiTrack()
...
track.append(Message('program_change', program = 36,
                     time = 1234, channel = 0)

This works but I can only access the GM MIDI Level 1 instruments. I want to access the GM MIDI Level 2 instruments too.

Please show me using code how to do this. All the MIDI documentation I've found by googling is incredibly confusing.


Solution

  • The GM 2 specification says:

    3.2 Program Change Message

    […]
    Sets the timbre for the specified Channel.

    When the Channel is a Melody Channel, the timbre is selected from the Bank specified by Bank Select (using Bank Select 79H/xxH, with Bank 79H/00H corresponding to the GM1 sound set). […]

    3.3.1 Bank Select (cc#0/32)

    Bank Select selects the desired Bank for the specified Channel. The first byte listed is the MSB, transmitted on cc#0. The second byte listed is the LSB, transmitted on cc#32. Banks are listed in the GM2 Sound Set table (Appendix A). Bank Select 79H/00H corresponds to the GM1 Sound Set.[…]

    The Bank Select message shall not affect any change in sound until a subsequent Program Change message is received.

    So to access the other instruments, you have to select a different bank before sending the program change message. For example, to select "Bubble":

    track.append(Message('control_change', control =  0, value = 0x79, channel = 0, time = 1233))
    track.append(Message('control_change', control = 32, value = 0x05, channel = 0, time = 1233))
    track.append(Message('program_change', program = 0x7a,             channel = 0, time = 1234))