static int wait_event_time(void *p) { MidiEvent *ev = (MidiEvent *)p; int rc, ch; for(;;){ if(ev->time - (current_tick()*play_mode->rate+30)/60 < 0) break; trace_loop(); YieldToAnyThread(); rc = check_apply_control(); if(RC_IS_SKIP_FILE(rc)){ prescan = 0; for(ch = 0; ch < MAX_CHANNELS; ch++){ if(note_channel[ch] != NULL){ NADisposeNoteChannel(gNoteAllocator, note_channel[ch]); note_channel[ch] = NULL; } channel[ch].bank_lsb = 0; channel[ch].bank_msb = 0; } trace_flush(); return rc; } } return RC_NONE; }
static void play_event_prescan(void *p) { MidiEvent *ev = (MidiEvent *)p; int ch; for(ch = 0; ch < MAX_CHANNELS; ch++){ if(note_channel[ch] != NULL){ NADisposeNoteChannel(gNoteAllocator, note_channel[ch]); note_channel[ch] = NULL; } instrument_number[ch] = -1; instrument_name[ch][0] = '\0'; drum_part[ch] = false; channel[ch].bank_lsb = 0; channel[ch].bank_msb = 0; } drum_part[9] = true; for(;; ev++){ ch = ev->channel; if(ev->type == ME_NOTEON && note_channel[ch] == NULL){ //MidiEvent *ev; ev->channel = ch; ev->a = 0; set_instrument(ev); } else if(ev->type == ME_PROGRAM){ set_instrument(ev); } else if(ev->type == ME_TONE_BANK_LSB && ev->a != channel[ch].bank_lsb){ channel[ch].bank_lsb = ev->a; } else if(ev->type == ME_TONE_BANK_MSB && ev->a != channel[ch].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; } else if(ev->type == ME_DRUMPART && !drum_part[ch]){ //MidiEvent *ev; ev->channel = ch; ev->a = channel[ch].program; set_instrument(ev); drum_part[ch] = true; } else if(ev->type == ME_RESET){ play_system_mode = ev->a; } else if(ev->type == ME_EOT){ prescan = 1; for(ch = 0; ch < MAX_CHANNELS; ch++){ channel[ch].bank_lsb = 0; channel[ch].bank_msb = 0; } init_variable(); break; } } }
void closeQuicktimeMIDIPort(void) { int i; if (!na) return; for (i = 0; i < 16; i++) { /* dispose of note channels */ if (channel[i]) NADisposeNoteChannel(na, channel[i]); channel[i] = nil; } CloseComponent(na); /* close note allocator */ }
static void set_instrument(MidiEvent *ev) { long instrumentNumber; int ch = ev->channel; channel[ch].program = ev->a; if(drum_part[ch]){ if(play_system_mode == GS_SYSTEM_MODE && channel[ch].bank_lsb == 2) // SC-88 Map instrumentNumber = kFirstDrumkit + sc88_drum_kit[ev->a] + 1; else if(play_system_mode == GS_SYSTEM_MODE && channel[ch].bank_lsb == 3) // SC-88Pro Map instrumentNumber = kFirstDrumkit + sc88pro_drum_kit[ev->a] + 1; else instrumentNumber = kFirstDrumkit + ev->a + 1; } else { if(play_system_mode == GS_SYSTEM_MODE) instrumentNumber = kFirstGSInstrument + (channel[ch].bank_msb<<7) + ev->a; else if(play_system_mode == XG_SYSTEM_MODE) instrumentNumber = xg_instrument_number(ch, ev->a); else instrumentNumber = kFirstGMInstrument + ev->a; } if(instrument_number[ch] != instrumentNumber){ NoteRequest nr; long index, part; OSType synthType; Str31 name; SynthesizerConnections connections; MusicComponent mc; instrument_number[ch] = instrumentNumber; if(note_channel[ch] != NULL) NADisposeNoteChannel(gNoteAllocator, note_channel[ch]); nr.info.flags = 0; nr.info.reserved = 0; *(short *)(&nr.info.polyphony) = EndianS16_NtoB(8); // 8 voices poliphonic *(Fixed *)(&nr.info.typicalPolyphony) = EndianU32_NtoB(0x00010000); NAStuffToneDescription(gNoteAllocator, instrumentNumber, &nr.tone); NANewNoteChannel(gNoteAllocator, &nr, ¬e_channel[ch]); NAGetNoteChannelInfo(gNoteAllocator, note_channel[ch], &index, &part); NAGetRegisteredMusicDevice(gNoteAllocator, index, &synthType, name, &connections, &mc); MusicGetPartName(mc, part, name); p2cstrcpy(instrument_name[ch], name); } ctl_prog_event(ch, ev->a); }
static int acntl(int request, void *arg) { int rc, ch; switch(request) { case PM_REQ_MIDI: if(!prescan) play_event_prescan(arg); rc = wait_event_time(arg); if(RC_IS_SKIP_FILE(rc)) return rc; qt_play_event(arg); return RC_NONE; case PM_REQ_INST_NAME: ch = (int)*(char **)arg; *(char **)arg = instrument_name[ch]; return 0; case PM_REQ_GETSAMPLES: *(int32 *)arg = current_samples(); return 0; case PM_REQ_PLAY_START: init_variable(); case PM_REQ_DISCARD: case PM_REQ_FLUSH: for(ch = 0; ch < MAX_CHANNELS; ch++){ if(note_channel[ch] != NULL){ NADisposeNoteChannel(gNoteAllocator, note_channel[ch]); note_channel[ch] = NULL; } channel[ch].bank_lsb = 0; channel[ch].bank_msb = 0; } trace_flush(); return 0; } return -1; }