2

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.

jpyams
  • 4,030
  • 9
  • 41
  • 66
cat pants
  • 1,485
  • 4
  • 13
  • 22

1 Answers1

1

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.

Brad
  • 159,648
  • 54
  • 349
  • 530
  • Thank you. I tried this (please see my edit) however this does not work. Did I do something incorrectly perhaps? – cat pants Sep 17 '18 at 22:52