MIDI Synthesizer being nuts when trying to do a crossfade

I’m trying to get the MIDI synthesizer working, and it seems to go completely nuts when I try to get a crossfade going by using multiple channels.

Pretty much it seems to ignore everything I tell it to do when I’m using more than one channel… which is odd, considering you’re supposed to use 16. The Java MIDI instructions are cryptic and unhelpful to someone who doesn’t know much about how MIDI works, so I’m having a lot of trouble getting exactly what the problem is.

It tends to result in when I change the instrument in any channel. Once I do, notes that were previously played never end naturally, they only do if I force them off, which makes a crossfade impossible.


noteTime--;
if (noteTime <= 0)
{
	int otherChannel = noteChannel == 0 ? 1 : 0;
	midiChannels[otherChannel].allNotesOff();
	noteChannel = otherChannel;
	noteTime = (int)(Math.random() * 300 + 100);
	currentNote = (int)(Math.random()*50+5);
	currentInstrument = MUSIC_INSTRUMENTS[(int)(Math.random()*MUSIC_INSTRUMENTS.length)];
	midiChannels[noteChannel].programChange(currentInstrument);
}
midiChannels[noteChannel].noteOn(currentNote,150);

This code is basically to play random notes using random instruments for random lengths of time. Once a note runs out of time, the channel is swapped to the other channel (in order to create a crossfade) and the instrument is changed on that channel. So basically it might go like this:

  • Play note 50 with instrument 100 on channel 0
  • Stop everything playing on channel 1
  • Play note 75 with instrument 25 on channel 1
  • Stop everything playing on channel 0
  • Play note 63 with instrument 111 on channel 0
    etc.
    So there are always two different notes/instruments playing simultaneously on separate channels. Because noteOn is only getting called on one channel, however, this allows the inactive channel to slowly fade out on its own, creating a nice cross fade.

It should do that, anyway. It seems that this works once only. Basically the first sound plays on channel 0, then I tell the instrument on channel 1 to change, and that messes it all up. If I never change the instrument and use the same one on both channels, it seems to work fine.

By “messes it all up” I mean that the second played sound (played right after the first instrument change) will play either forever at a grating single pitch (won’t do any fading or pitch bending or anything like it normally would) or will play for sort of a random length of time.

So basically I can play the same instrument a bunch of times simultaneously with no issues, but once I change the instrument assigned to a channel it goes crazy.

I don’t think program changes were ever intended for mid song. You probably need to wait for the sound to die away completely on a channel before you do a program change. NoteOff doesn’t mean the sound has stopped playing and a note may be actively decaying for quite a while and doing a program change will screw up the synthesizer. Why not pick 16 instruments that sound good at the start and then randomly pick a channel for the next note.