void performMIDICmd(int cmdByte, int arg1, int arg2) {
	/* Perform the given MIDI command with the given arguments. */

	int ch, cmd, val, instrument, bend;

	ch = cmdByte & 0x0F;
	cmd = cmdByte & 0xF0;
	if (cmd == 128) {  /* note off */
		NAPlayNote(na, channel[ch], arg1, 0);
	}
	if (cmd == 144) {  /* note on */
		NAPlayNote(na, channel[ch], arg1, arg2);
	}
	if (cmd == 176) {  /* control change */
		if ((arg1 >= 32) && (arg1 <= 63)) {
			val = arg2 << 1;  /* LSB of controllers 0-31 */
		} else {
			val = arg2 << 8;  /* scale MSB to QT controller range */
		}
		NASetController(na, channel[ch], arg1, val);
	}
	if (cmd == 192) {  /* program change */
		if (ch == 9) {
			instrument = FIRST_DRUM_KIT + arg1;  /* if channel 10, select a drum set */
		} else {
			instrument = arg1 + 1;
		}
		NASetInstrumentNumber(na, channel[ch], instrument);
		channelInstrument[ch] = instrument;
	}
	if (cmd == 224) {  /* pitch bend */
		bend = ((arg2 << 7) + arg1) - (64 << 7);
		bend = bend / 32;  /* default sensitivity = +/- 2 semitones */
		NASetController(na, channel[ch], kControllerPitchBend, bend);
	}
}
static void qt_play_event(void *p)
{
	MidiEvent *ev = (MidiEvent *)p;
	int ch, i;

	ch = ev->channel;
	switch(ev->type)
	{
	case ME_NOTEON:
		if(play_system_mode == XG_SYSTEM_MODE && channel[ch].bank_msb == 127
			&& ev->a >= XG_DRUM_VOICE_FIRST_NOTE && ev->a <= XG_DRUM_VOICE_LAST_NOTE){
			int a = ev->a - XG_DRUM_VOICE_FIRST_NOTE;
			a = xg_drum_voice[a][1];
			NAPlayNote(gNoteAllocator, note_channel[ch], a, ev->b);
			qt_ctl_note_event(ch, ev->a, ev->b);
		}
		else if(play_system_mode == XG_SYSTEM_MODE && channel[ch].bank_msb == 126){
			NAPlayNote(gNoteAllocator, note_channel[ch], ev->a, ev->b);
			qt_ctl_note_event(ch, ev->a, ev->b);
		}
		else {
			NAPlayNote(gNoteAllocator, note_channel[ch], ev->a, ev->b);
			qt_ctl_note_event(ch, ev->a, ev->b);
		}
		break;
	case ME_NOTEOFF:
		if(play_system_mode == XG_SYSTEM_MODE && channel[ch].bank_msb == 127
			&& ev->a >= XG_DRUM_VOICE_FIRST_NOTE && ev->a <= XG_DRUM_VOICE_LAST_NOTE){
			int a = ev->a - XG_DRUM_VOICE_FIRST_NOTE;
			a = xg_drum_voice[a][1];
			NAPlayNote(gNoteAllocator, note_channel[ch], a, 0);
			qt_ctl_note_event(ch, ev->a, 0);
		}
		else if(play_system_mode == XG_SYSTEM_MODE && channel[ch].bank_msb == 126){
			NAPlayNote(gNoteAllocator, note_channel[ch], ev->a, 0);
			qt_ctl_note_event(ch, ev->a, 0);
		}
		else {
			NAPlayNote(gNoteAllocator, note_channel[ch], ev->a, 0);
			qt_ctl_note_event(ch, ev->a, 0);
		}
		break;
	case ME_PROGRAM:
		set_instrument(ev);
		break;
	/* MIDI Events */
	case ME_KEYPRESSURE:
	case ME_CHANNEL_PRESSURE:
		NASetController(gNoteAllocator, note_channel[ch], kControllerAfterTouch, ev->a<<8);
		break;
	case ME_PITCHWHEEL:
		// kControllerPitchBend 256/halfnote
		i = (ev->b<<7) + ev->a - 0x2000;
		i *= (bend_sense[ch]<<1);
		i += (i > 0 ? (1<<12) : -(1<<12));
		i >>= 13;
		NASetController(gNoteAllocator, note_channel[ch], kControllerPitchBend, i);
		break;
	/* Controls */
	case ME_TONE_BANK_LSB:
		channel[ch].bank_lsb = ev->a;
		break;
	case ME_TONE_BANK_MSB:
		channel[ch].bank_msb = ev->a;
		if(play_system_mode == XG_SYSTEM_MODE && (ev->a == 126 || ev->a == 127) && !drum_part[ch])
			drum_part[ch] = true;
		break;
	case ME_MODULATION_WHEEL:
		NASetController(gNoteAllocator, note_channel[ch], kControllerModulationWheel, ev->a);
		break;
	case ME_BREATH:
		NASetController(gNoteAllocator, note_channel[ch], kControllerBreath, ev->a<<8);
		break;
	case ME_FOOT:
		NASetController(gNoteAllocator, note_channel[ch], kControllerFoot, ev->a<<8);
		break;
	case ME_BALANCE:
		NASetController(gNoteAllocator, note_channel[ch], kControllerBalance, ev->a<<8);
		break;
	case ME_MAINVOLUME:
		NASetController(gNoteAllocator, note_channel[ch], kControllerVolume, ev->a<<8);
		break;
	case ME_PAN:
		// kControllerPan 256-512
		NASetController(gNoteAllocator, note_channel[ch], kControllerPan, (ev->a<<1) + 256);
		ctl_mode_event(CTLE_PANNING, 1, ch, ev->a);
		break;
	case ME_EXPRESSION:
		NASetController(gNoteAllocator, note_channel[ch], kControllerExpression, ev->a<<8);
		ctl_mode_event(CTLE_EXPRESSION, 1, ch, ev->a);
		break;
	case ME_SUSTAIN:
		// kControllerSustain on/off only
		NASetController(gNoteAllocator, note_channel[ch], kControllerSustain, ev->a<<8);
		ctl_mode_event(CTLE_SUSTAIN, 1, ch, ev->a);
		break;
	case ME_PORTAMENTO_TIME_MSB:
	    channel[ch].portamento_time_msb = ev->a;
		NASetController(gNoteAllocator, note_channel[ch], kControllerPortamentoTime,
			(channel[ch].portamento_time_msb + (channel[ch].portamento_time_lsb<<7))<<1);
		break;
	case ME_PORTAMENTO_TIME_LSB:
	    channel[ch].portamento_time_lsb = ev->a;
		NASetController(gNoteAllocator, note_channel[ch], kControllerPortamentoTime,
			(channel[ch].portamento_time_msb + (channel[ch].portamento_time_lsb<<7))<<1);
		break;
	case ME_PORTAMENTO:
		NASetController(gNoteAllocator, note_channel[ch], kControllerPortamento, ev->a<<8);
		break;
	case ME_DATA_ENTRY_MSB:
		if(rpn_flag){
			if(rpn_addr[ch] == 0)			// pitchbend sensitivity
				bend_sense[ch] = (ev->a<<7) + ev->b;
			else if(rpn_addr[ch] == 1){		// master tuning (fine)
				master_tune[ch] |= ev->a;
				NASetController(gNoteAllocator, note_channel[ch], kControllerMasterTune, master_tune[ch]);
			}
			else if(rpn_addr[ch] == 2){		// master tuning (coarse)
				master_tune[ch] |= (ev->a<<7);
				NASetController(gNoteAllocator, note_channel[ch], kControllerMasterTune, master_tune[ch]);
			}
		}
		else {
		}
		break;
	case ME_REVERB_EFFECT:
		NASetController(gNoteAllocator, note_channel[ch], kControllerReverb, ev->a<<8);
	    channel[ch].reverb_level = ev->a;
	    ctl_mode_event(CTLE_REVERB_EFFECT, 1, ch, ev->a);
		break;
	case ME_TREMOLO_EFFECT:
		NASetController(gNoteAllocator, note_channel[ch], kControllerTremolo, ev->a<<8);
		break;
	case ME_CHORUS_EFFECT:
		NASetController(gNoteAllocator, note_channel[ch], kControllerChorus, ev->a<<8);
	    channel[ch].chorus_level = ev->a;
	    ctl_mode_event(CTLE_CHORUS_EFFECT, 1, ch, ev->a);
		break;
	case ME_CELESTE_EFFECT:
		NASetController(gNoteAllocator, note_channel[ch], kControllerCeleste, ev->a<<8);
		break;
	case ME_PHASER_EFFECT:
		NASetController(gNoteAllocator, note_channel[ch], kControllerPhaser, ev->a<<8);
		break;
	case ME_RPN_INC:
		rpn_flag = 1;
		rpn_addr[ch]++;
		break;
	case ME_RPN_DEC:
		rpn_flag = 1;
		rpn_addr[ch]--;
		break;
	case ME_NRPN_LSB:
		rpn_flag = 0;
		nrpn_lsb[ch] = ev->a;
		break;
	case ME_NRPN_MSB:
		rpn_flag = 0;
		nrpn_msb[ch] = ev->a;
		break;
	case ME_RPN_LSB:
		rpn_flag = 1;
		rpn_addr[ch] = ev->a;
		break;
	case ME_RPN_MSB:
		break;
	case ME_ALL_SOUNDS_OFF:
		for(i = 0; i < 128; i++)
			NAPlayNote(gNoteAllocator, note_channel[ch], i, 0);
		break;
	case ME_RESET_CONTROLLERS:
		NAResetNoteChannel(gNoteAllocator, note_channel[ch]);
		ctl_mode_event(CTLE_VOLUME, 1, ch, 0);
		ctl_mode_event(CTLE_EXPRESSION, 1, ch, 127);
		ctl_mode_event(CTLE_SUSTAIN, 1, ch, 0);
		ctl_mode_event(CTLE_MOD_WHEEL, 1, ch, 0);
		ctl_mode_event(CTLE_PITCH_BEND, 1, ch, 0x2000);
		ctl_prog_event(ch, channel[ch].program);
		ctl_mode_event(CTLE_CHORUS_EFFECT, 1, ch, 0);
		ctl_mode_event(CTLE_REVERB_EFFECT, 1, ch, 0);
		break;
	case ME_ALL_NOTES_OFF:
		for(i = 0; i < 128; i++)
			NAPlayNote(gNoteAllocator, note_channel[ch], i, 0);
		break;
	case ME_MONO:
		break;
	case ME_POLY:
		break;
	case ME_SOSTENUTO:
		NASetController(gNoteAllocator, note_channel[ch], kControllerSostenuto, ev->a);
		break;
	case ME_SOFT_PEDAL:
		NASetController(gNoteAllocator, note_channel[ch], kControllerSoftPedal, ev->a);
		break;
	/* TiMidity Extensionals */
	case ME_RANDOM_PAN:
		break;
	case ME_SET_PATCH:
		break;
	case ME_TEMPO:
		break;
	case ME_CHORUS_TEXT:
	case ME_LYRIC:
	case ME_MARKER:
	case ME_INSERT_TEXT:
	case ME_TEXT:
	case ME_KARAOKE_LYRIC:
		i = ev->a | ((int)ev->b << 8);
		ctl_mode_event(CTLE_LYRIC, 1, i, 0);
		break;
	case ME_MASTER_VOLUME:
		NASetController(gNoteAllocator, NULL, kControllerMasterVolume, ev->a + (ev->b<<7));
		break;
	case ME_PATCH_OFFS:
		break;
	case ME_RESET:
		play_system_mode = ev->a;
		break;
	case ME_WRD:
		push_midi_trace2(wrd_midi_event, ch, ev->a | (ev->b<<8));
		break;
	case ME_DRUMPART:
		if(!drum_part[ch]){
			//MidiEvent *ev;

			ev->channel = ch;
			ev->a = channel[ch].program;
			set_instrument(ev);
			drum_part[ch] = true;
		}
		break;
	case ME_KEYSHIFT:
		NASetController(gNoteAllocator, NULL, kControllerMasterTune, ev->a);
		break;
	case ME_NOTE_STEP:
		break;
	case ME_EOT:
		prescan = 0;
		break;
	}
	if(ev->type != ME_EOT)
		ctl_timestamp();
}