Multiple midi programs playing simultaneously?

481 views Asked by At

I am using the mido library to control amsynth with python.

So far this is working beautifully...but I can only play one "preset" at a time however.

I'm trying to use "program_change" to switch instruments so I can play several instruments at once.

As a quick example:

import mido
from mido import Message
import time

outport = mido.open_output('amsynth:MIDI IN')

msg = Message('note_on', note = 64)
outport.send(msg)
time.sleep(2.0)

msg = Message('program_change', program = 1)
outport.send(msg)

msg = Message('note_on', note = 68) 
outport.send(msg)
time.sleep(2.0)

msg = Message('note_off', note = 64)
outport.send(msg)
time.sleep(0.5)

msg = Message('note_off', note = 68) 
outport.send(msg)
time.sleep(0.5)

But when I try this, the note from the first program is cut as soon as I switch channels.

So maybe the issue is each program needs to be on a different channel:

import mido
from mido import Message
import time

outport = mido.open_output('amsynth:MIDI IN')

msg = Message('note_on', note = 64, channel = 0)
outport.send(msg)
time.sleep(2.0)

msg = Message('program_change', program = 1)
outport.send(msg)

msg = Message('note_on', note = 68, channel = 1)
outport.send(msg)
time.sleep(2.0)

msg = Message('note_off', note = 64)
outport.send(msg)
time.sleep(0.5)

msg = Message('note_off', note = 68)
outport.send(msg)
time.sleep(0.5)

But this doesn't work either.

As a workaround, I have been considering running multiple instances of amsynth...but that just seems perverse to me.

How can I play several instruments at once?

Edit:

It sounds like I will need to assign programs to channels before starting playback, and then play back per channel like so:

  msg = Message('program_change', program = 23, channel = 1)
  outport.send(msg)

  msg = Message('program_change', program = 3, channel = 2)
  outport.send(msg)

  msg = Message('note_on', note = 64, channel = 1)
  outport.send(msg)
  time.sleep(2.0)

  msg = Message('note_on', note = 68, channel = 2)
  outport.send(msg)
  time.sleep(2.0)

  msg = Message('note_off', note = 64, channel = 1)
  outport.send(msg)
  time.sleep(0.5)

  msg = Message('note_off', note = 68, channel = 2) 
  outport.send(msg)
  time.sleep(0.5)

However, this plays back both notes with program 3, so this doesn't work unfortunately.

1

There are 1 answers

1
Brad On

With MIDI, there are 16 channels. Each channel can be on one program/patch at a given time. When you call program_change, you're changing the patch for that default channel. You should send program_change for another channel, and then send MIDI notes to that other channel as well.