|
|
| version 1.9, 2003/12/25 19:26:55 | version 1.17, 2006/12/16 22:23:24 |
|---|---|
| Line 2 | Line 2 |
| #include "midiout.h" | #include "midiout.h" |
| #define MIDIOUT_VERSION 0x105 | #define MIDIOUT_VERSION 0x116 |
| #define MIDIOUT_VERSTRING "VERMOUTH 1.05" | #define MIDIOUT_VERSTRING "VERMOUTH 1.16" |
| static const char vermouthver[] = MIDIOUT_VERSTRING; | static const char vermouthver[] = MIDIOUT_VERSTRING; |
| Line 16 static const int gaintbl[24+1] = | Line 15 static const int gaintbl[24+1] = |
| // ---- voice | // ---- voice |
| static void voice_volupdate(VOICE v) { | #define VOICEHDLPTR(hdl) ((hdl)->voice) |
| #define VOICEHDLEND(hdl) (VOICE)((hdl) + 1) | |
| static void VERMOUTHCL voice_volupdate(VOICE v) { | |
| CHANNEL ch; | CHANNEL ch; |
| int vol; | int vol; |
| ch = v->channel; | ch = v->channel; |
| #if defined(VOLUME_ACURVE) | |
| vol = ch->level * acurve[v->velocity]; | |
| vol >>= 8; | |
| #else | |
| vol = ch->level * v->velocity; | vol = ch->level * v->velocity; |
| vol >>= 7; | vol >>= 7; |
| #endif | |
| vol *= v->sample->volume; | vol *= v->sample->volume; |
| vol >>= (21 - 16); | vol >>= (21 - 16); |
| #if defined(PANPOT_REVA) | |
| switch(v->flag & VOICE_MIXMASK) { | |
| case VOICE_MIXNORMAL: | |
| v->volleft = (vol * revacurve[v->panpot ^ 127]) >> 8; | |
| v->volright = (vol * revacurve[v->panpot]) >> 8; | |
| break; | |
| case VOICE_MIXCENTRE: | |
| v->volleft = (vol * 155) >> 8; | |
| break; | |
| default: | |
| v->volleft = vol; | |
| break; | |
| } | |
| #else | |
| v->volleft = vol; | v->volleft = vol; |
| if ((v->flag & VOICE_MIXMASK) == VOICE_MIXNORMAL) { | if ((v->flag & VOICE_MIXMASK) == VOICE_MIXNORMAL) { |
| if (v->panpot < 64) { | if (v->panpot < 64) { |
| Line 40 static void voice_volupdate(VOICE v) { | Line 63 static void voice_volupdate(VOICE v) { |
| v->volleft = vol; | v->volleft = vol; |
| } | } |
| } | } |
| #endif | |
| } | } |
| static INSTLAYER selectlayer(VOICE v, INSTRUMENT inst) { | static INSTLAYER VERMOUTHCL selectlayer(VOICE v, INSTRUMENT inst) { |
| int layers; | int layers; |
| INSTLAYER layer; | INSTLAYER layer; |
| Line 89 static INSTLAYER selectlayer(VOICE v, IN | Line 113 static INSTLAYER selectlayer(VOICE v, IN |
| return(layersel); | return(layersel); |
| } | } |
| static void freq_update(VOICE v) { | static void VERMOUTHCL freq_update(VOICE v) { |
| CHANNEL ch; | CHANNEL ch; |
| float step; | float step; |
| Line 113 static void freq_update(VOICE v) { | Line 137 static void freq_update(VOICE v) { |
| v->sampstep = (int)step; | v->sampstep = (int)step; |
| } | } |
| static void voice_on(MIDIHDL midi, CHANNEL ch, VOICE v, int key, int vel) { | static void VERMOUTHCL voice_on(MIDIHDL hdl, CHANNEL ch, VOICE v, int key, |
| int vel) { | |
| INSTRUMENT inst; | INSTRUMENT inst; |
| INSTLAYER layer; | INSTLAYER layer; |
| Line 137 static void voice_on(MIDIHDL midi, CHANN | Line 162 static void voice_on(MIDIHDL midi, CHANN |
| #if !defined(MIDI_GMONLY) | #if !defined(MIDI_GMONLY) |
| inst = ch->rhythm[key]; | inst = ch->rhythm[key]; |
| if (inst == NULL) { | if (inst == NULL) { |
| inst = midi->bank0[1][key]; | inst = hdl->bank0[1][key]; |
| } | } |
| #else | #else |
| inst = midi->bank0[1][key]; | inst = hdl->bank0[1][key]; |
| #endif | #endif |
| if (inst == NULL) { | if (inst == NULL) { |
| return; | return; |
| Line 183 static void voice_on(MIDIHDL midi, CHANN | Line 208 static void voice_on(MIDIHDL midi, CHANN |
| else { | else { |
| panpot = layer->panpot; | panpot = layer->panpot; |
| } | } |
| #if defined(PANPOT_REVA) | |
| if (panpot == 64) { | |
| v->flag = VOICE_MIXCENTRE; | |
| } | |
| else if (panpot < 3) { | |
| v->flag = VOICE_MIXLEFT; | |
| } | |
| else if (panpot >= 126) { | |
| v->flag = VOICE_MIXRIGHT; | |
| } | |
| else { | |
| v->flag = VOICE_MIXNORMAL; | |
| v->panpot = panpot; | |
| } | |
| #else | |
| if ((panpot >= 60) && (panpot < 68)) { | if ((panpot >= 60) && (panpot < 68)) { |
| v->flag = VOICE_MIXCENTRE; | v->flag = VOICE_MIXCENTRE; |
| } | } |
| Line 196 static void voice_on(MIDIHDL midi, CHANN | Line 236 static void voice_on(MIDIHDL midi, CHANN |
| v->flag = VOICE_MIXNORMAL; | v->flag = VOICE_MIXNORMAL; |
| v->panpot = panpot; | v->panpot = panpot; |
| } | } |
| #endif | |
| if (!layer->samprate) { | if (!layer->samprate) { |
| v->flag |= VOICE_FIXPITCH; | v->flag |= VOICE_FIXPITCH; |
| } | } |
| else { | else { |
| v->freq = (float)layer->samprate / (float)midi->samprate * | v->freq = (float)layer->samprate / (float)hdl->samprate * |
| (float)v->frequency / (float)layer->freqroot; | (float)v->frequency / (float)layer->freqroot; |
| } | } |
| voice_setphase(v, VOICE_ON); | voice_setphase(v, VOICE_ON); |
| Line 218 static void voice_on(MIDIHDL midi, CHANN | Line 259 static void voice_on(MIDIHDL midi, CHANN |
| envelope_updates(v); | envelope_updates(v); |
| } | } |
| static void voice_off(VOICE v) { | static void VERMOUTHCL voice_off(VOICE v) { |
| voice_setphase(v, VOICE_OFF); | voice_setphase(v, VOICE_OFF); |
| if (v->sample->mode & MODE_ENVELOPE) { | if (v->sample->mode & MODE_ENVELOPE) { |
| Line 228 static void voice_off(VOICE v) { | Line 269 static void voice_off(VOICE v) { |
| } | } |
| } | } |
| static void allresetvoices(MIDIHDL midi) { | static void VERMOUTHCL allresetvoices(MIDIHDL hdl) { |
| VOICE v; | VOICE v; |
| VOICE vterm; | VOICE vterm; |
| v = midi->voice; | v = VOICEHDLPTR(hdl); |
| vterm = v + VOICE_MAX; | vterm = VOICEHDLEND(hdl); |
| do { | do { |
| voice_setfree(v); | voice_setfree(v); |
| v++; | v++; |
| Line 244 static void allresetvoices(MIDIHDL midi) | Line 285 static void allresetvoices(MIDIHDL midi) |
| // ---- key | // ---- key |
| static void key_on(MIDIHDL midi, CHANNEL ch, int key, int vel) { | static void VERMOUTHCL key_on(MIDIHDL hdl, CHANNEL ch, int key, int vel) { |
| VOICE v; | VOICE v; |
| VOICE v1; | VOICE v1; |
| Line 253 static void key_on(MIDIHDL midi, CHANNEL | Line 294 static void key_on(MIDIHDL midi, CHANNEL |
| int volmin; | int volmin; |
| v = NULL; | v = NULL; |
| v1 = midi->voice; | v1 = VOICEHDLPTR(hdl); |
| v2 = v1 + VOICE_MAX; | v2 = VOICEHDLEND(hdl); |
| do { | do { |
| v2--; | v2--; |
| if (v2->phase == VOICE_FREE) { | if (v2->phase == VOICE_FREE) { |
| Line 268 static void key_on(MIDIHDL midi, CHANNEL | Line 309 static void key_on(MIDIHDL midi, CHANNEL |
| } while(v1 < v2); | } while(v1 < v2); |
| if (v != NULL) { | if (v != NULL) { |
| voice_on(midi, ch, v, key, vel); | voice_on(hdl, ch, v, key, vel); |
| return; | return; |
| } | } |
| volmin = 0x7fffffff; | volmin = 0x7fffffff; |
| v2 = v1 + VOICE_MAX; | v2 = VOICEHDLEND(hdl); |
| do { | do { |
| v2--; | v2--; |
| if (!(v2->phase & (VOICE_ON | VOICE_REL))) { | if (!(v2->phase & (VOICE_ON | VOICE_REL))) { |
| Line 290 static void key_on(MIDIHDL midi, CHANNEL | Line 331 static void key_on(MIDIHDL midi, CHANNEL |
| if (v != NULL) { | if (v != NULL) { |
| voice_setfree(v); | voice_setfree(v); |
| voice_on(midi, ch, v, key, vel); | voice_on(hdl, ch, v, key, vel); |
| } | } |
| } | } |
| static void key_off(MIDIHDL midi, CHANNEL ch, int key) { | static void VERMOUTHCL key_off(MIDIHDL hdl, CHANNEL ch, int key) { |
| VOICE v; | VOICE v; |
| VOICE vterm; | VOICE vterm; |
| v = midi->voice; | v = VOICEHDLPTR(hdl); |
| vterm = v + VOICE_MAX; | vterm = VOICEHDLEND(hdl); |
| do { | do { |
| if ((v->phase & VOICE_ON) && | if ((v->phase & VOICE_ON) && |
| (v->channel == ch) && (v->note == key)) { | (v->channel == ch) && (v->note == key)) { |
| Line 316 static void key_off(MIDIHDL midi, CHANNE | Line 357 static void key_off(MIDIHDL midi, CHANNE |
| } while(v < vterm); | } while(v < vterm); |
| } | } |
| static void key_pressure(MIDIHDL midi, CHANNEL ch, int key, int vel) { | static void VERMOUTHCL key_pressure(MIDIHDL hdl, CHANNEL ch, int key, |
| int vel) { | |
| VOICE v; | VOICE v; |
| VOICE vterm; | VOICE vterm; |
| v = midi->voice; | v = VOICEHDLPTR(hdl); |
| vterm = v + VOICE_MAX; | vterm = VOICEHDLEND(hdl); |
| do { | do { |
| if ((v->phase & VOICE_ON) && | if ((v->phase & VOICE_ON) && |
| (v->channel == ch) && (v->note == key)) { | (v->channel == ch) && (v->note == key)) { |
| Line 338 static void key_pressure(MIDIHDL midi, C | Line 380 static void key_pressure(MIDIHDL midi, C |
| // ---- control | // ---- control |
| static void volumeupdate(MIDIHDL midi, CHANNEL ch) { | static void VERMOUTHCL volumeupdate(MIDIHDL hdl, CHANNEL ch) { |
| VOICE v; | VOICE v; |
| VOICE vterm; | VOICE vterm; |
| ch->level = (midi->level * ch->volume * ch->expression) >> 14; | #if defined(VOLUME_ACURVE) |
| v = midi->voice; | ch->level = (hdl->level * acurve[ch->volume] * ch->expression) >> 15; |
| vterm = v + VOICE_MAX; | #else |
| ch->level = (hdl->level * ch->volume * ch->expression) >> 14; | |
| #endif | |
| v = VOICEHDLPTR(hdl); | |
| vterm = VOICEHDLEND(hdl); | |
| do { | do { |
| if ((v->phase & (VOICE_ON | VOICE_SUSTAIN)) && (v->channel == ch)) { | if ((v->phase & (VOICE_ON | VOICE_SUSTAIN)) && (v->channel == ch)) { |
| voice_volupdate(v); | voice_volupdate(v); |
| Line 355 static void volumeupdate(MIDIHDL midi, C | Line 401 static void volumeupdate(MIDIHDL midi, C |
| } while(v < vterm); | } while(v < vterm); |
| } | } |
| static void pedaloff(MIDIHDL midi, CHANNEL ch) { | static void VERMOUTHCL pedaloff(MIDIHDL hdl, CHANNEL ch) { |
| VOICE v; | VOICE v; |
| VOICE vterm; | VOICE vterm; |
| v = midi->voice; | v = VOICEHDLPTR(hdl); |
| vterm = v + VOICE_MAX; | vterm = VOICEHDLEND(hdl); |
| do { | do { |
| if ((v->phase & VOICE_SUSTAIN) && (v->channel == ch)) { | if ((v->phase & VOICE_SUSTAIN) && (v->channel == ch)) { |
| voice_off(v); | voice_off(v); |
| Line 370 static void pedaloff(MIDIHDL midi, CHANN | Line 416 static void pedaloff(MIDIHDL midi, CHANN |
| } while(v < vterm); | } while(v < vterm); |
| } | } |
| static void allsoundsoff(MIDIHDL midi, CHANNEL ch) { | static void VERMOUTHCL allsoundsoff(MIDIHDL hdl, CHANNEL ch) { |
| VOICE v; | VOICE v; |
| VOICE vterm; | VOICE vterm; |
| v = midi->voice; | v = VOICEHDLPTR(hdl); |
| vterm = v + VOICE_MAX; | vterm = VOICEHDLEND(hdl); |
| do { | do { |
| if ((v->phase != VOICE_FREE) && (v->channel == ch)) { | if ((v->phase != VOICE_FREE) && (v->channel == ch)) { |
| voice_setphase(v, VOICE_REL); | voice_setphase(v, VOICE_REL); |
| Line 386 static void allsoundsoff(MIDIHDL midi, C | Line 432 static void allsoundsoff(MIDIHDL midi, C |
| } while(v < vterm); | } while(v < vterm); |
| } | } |
| static void resetallcontrollers(CHANNEL ch) { | static void VERMOUTHCL resetallcontrollers(CHANNEL ch) { |
| ch->flag &= CHANNEL_MASK; | ch->flag &= CHANNEL_MASK; |
| if (ch->flag == 9) { | if (ch->flag == 9) { |
| Line 398 static void resetallcontrollers(CHANNEL | Line 444 static void resetallcontrollers(CHANNEL |
| ch->pitchfactor = 1.0; | ch->pitchfactor = 1.0; |
| } | } |
| static void allnotesoff(MIDIHDL midi, CHANNEL ch) { | static void VERMOUTHCL allnotesoff(MIDIHDL hdl, CHANNEL ch) { |
| VOICE v; | VOICE v; |
| VOICE vterm; | VOICE vterm; |
| v = midi->voice; | v = VOICEHDLPTR(hdl); |
| vterm = v + VOICE_MAX; | vterm = VOICEHDLEND(hdl); |
| do { | do { |
| #if 1 | #if 1 |
| if ((v->phase & (VOICE_ON | VOICE_SUSTAIN)) && (v->channel == ch)) { | if ((v->phase & (VOICE_ON | VOICE_SUSTAIN)) && (v->channel == ch)) { |
| Line 424 static void allnotesoff(MIDIHDL midi, CH | Line 470 static void allnotesoff(MIDIHDL midi, CH |
| } while(v < vterm); | } while(v < vterm); |
| } | } |
| static void ctrlchange(MIDIHDL midi, CHANNEL ch, int ctrl, int val) { | static void VERMOUTHCL ctrlchange(MIDIHDL hdl, CHANNEL ch, int ctrl, |
| int val) { | |
| val &= 0x7f; | val &= 0x7f; |
| switch(ctrl & 0x7f) { | switch(ctrl & 0x7f) { |
| #if !defined(MIDI_GMONLY) | |
| case CTRL_PGBANK: | case CTRL_PGBANK: |
| #if defined(ENABLE_GSRX) | |
| if (!(ch->gsrx[2] & GSRX2_BANKSELECT)) { | |
| break; | |
| } | |
| #endif | |
| ch->bank = val; | ch->bank = val; |
| break; | break; |
| #endif | |
| case CTRL_DATA_M: | case CTRL_DATA_M: |
| // TRACEOUT(("data: %x %x %x", c->rpn_l, c->rpn_m, val)); | // TRACEOUT(("data: %x %x %x", c->rpn_l, c->rpn_m, val)); |
| Line 444 static void ctrlchange(MIDIHDL midi, CHA | Line 498 static void ctrlchange(MIDIHDL midi, CHA |
| case CTRL_VOLUME: | case CTRL_VOLUME: |
| ch->volume = val; | ch->volume = val; |
| volumeupdate(midi, ch); | volumeupdate(hdl, ch); |
| break; | break; |
| case CTRL_PANPOT: | case CTRL_PANPOT: |
| Line 453 static void ctrlchange(MIDIHDL midi, CHA | Line 507 static void ctrlchange(MIDIHDL midi, CHA |
| case CTRL_EXPRESS: | case CTRL_EXPRESS: |
| ch->expression = val; | ch->expression = val; |
| volumeupdate(midi, ch); | volumeupdate(hdl, ch); |
| break; | break; |
| case CTRL_PEDAL: | case CTRL_PEDAL: |
| if (val == 0) { | if (val == 0) { |
| ch->flag &= ~CHANNEL_SUSTAIN; | ch->flag &= ~CHANNEL_SUSTAIN; |
| pedaloff(midi, ch); | pedaloff(hdl, ch); |
| } | } |
| else { | else { |
| ch->flag |= CHANNEL_SUSTAIN; | ch->flag |= CHANNEL_SUSTAIN; |
| Line 475 static void ctrlchange(MIDIHDL midi, CHA | Line 529 static void ctrlchange(MIDIHDL midi, CHA |
| break; | break; |
| case CTRL_SOUNDOFF: | case CTRL_SOUNDOFF: |
| allsoundsoff(midi, ch); | allsoundsoff(hdl, ch); |
| break; | break; |
| case CTRL_RESETCTRL: | case CTRL_RESETCTRL: |
| resetallcontrollers(ch); | resetallcontrollers(ch); |
| break; | /*FALLTHROUGH*/ |
| case CTRL_NOTEOFF: | case CTRL_NOTEOFF: |
| allnotesoff(midi, ch); | allnotesoff(hdl, ch); |
| break; | break; |
| case CTRL_MONOON: | case CTRL_MONOON: |
| Line 500 static void ctrlchange(MIDIHDL midi, CHA | Line 554 static void ctrlchange(MIDIHDL midi, CHA |
| } | } |
| } | } |
| static void progchange(MIDIHDL midi, CHANNEL ch, int val) { | static void VERMOUTHCL progchange(MIDIHDL hdl, CHANNEL ch, int val) { |
| #if !defined(MIDI_GMONLY) | #if !defined(MIDI_GMONLY) |
| MIDIMOD module; | MIDIMOD mod; |
| INSTRUMENT *bank; | INSTRUMENT *bank; |
| INSTRUMENT inst; | INSTRUMENT inst; |
| module = midi->module; | mod = hdl->module; |
| inst = NULL; | inst = NULL; |
| if (ch->bank < MIDI_BANKS) { | if (ch->bank < MIDI_BANKS) { |
| bank = module->tone[ch->bank * 2]; | bank = mod->tone[ch->bank * 2]; |
| if (bank) { | if (bank) { |
| inst = bank[val]; | inst = bank[val]; |
| } | } |
| } | } |
| if (inst == NULL) { | if (inst == NULL) { |
| bank = midi->bank0[0]; | bank = hdl->bank0[0]; |
| inst = bank[val]; | inst = bank[val]; |
| } | } |
| ch->inst = inst; | ch->inst = inst; |
| bank = NULL; | bank = NULL; |
| if (ch->bank < MIDI_BANKS) { | if (ch->bank < MIDI_BANKS) { |
| bank = module->tone[ch->bank * 2 + 1]; | bank = mod->tone[ch->bank * 2 + 1]; |
| } | } |
| if (bank == NULL) { | if (bank == NULL) { |
| bank = midi->bank0[1]; | bank = hdl->bank0[1]; |
| } | } |
| ch->rhythm = bank; | ch->rhythm = bank; |
| #else | #else |
| ch->inst = midi->bank0[0][val]; | ch->inst = hdl->bank0[0][val]; |
| #endif | #endif |
| ch->program = val; | ch->program = val; |
| } | } |
| static void chpressure(MIDIHDL midi, CHANNEL ch, int vel) { | static void VERMOUTHCL chpressure(MIDIHDL hdl, CHANNEL ch, int vel) { |
| VOICE v; | VOICE v; |
| VOICE vterm; | VOICE vterm; |
| v = midi->voice; | v = VOICEHDLPTR(hdl); |
| vterm = v + VOICE_MAX; | vterm = VOICEHDLEND(hdl); |
| do { | do { |
| if ((v->phase & VOICE_ON) && (v->channel == ch)) { | if ((v->phase & VOICE_ON) && (v->channel == ch)) { |
| v->velocity = vel; | v->velocity = vel; |
| Line 553 static void chpressure(MIDIHDL midi, CHA | Line 607 static void chpressure(MIDIHDL midi, CHA |
| } while(v < vterm); | } while(v < vterm); |
| } | } |
| static void pitchbendor(MIDIHDL midi, CHANNEL ch, int val1, int val2) { | static void VERMOUTHCL pitchbendor(MIDIHDL hdl, CHANNEL ch, int val1, |
| int val2) { | |
| VOICE v; | VOICE v; |
| VOICE vterm; | VOICE vterm; |
| Line 571 static void pitchbendor(MIDIHDL midi, CH | Line 626 static void pitchbendor(MIDIHDL midi, CH |
| ch->pitchfactor = bendhtbl[(val1 >> (6 + 7)) + 24] * | ch->pitchfactor = bendhtbl[(val1 >> (6 + 7)) + 24] * |
| bendltbl[(val1 >> 7) & 0x3f]; | bendltbl[(val1 >> 7) & 0x3f]; |
| } | } |
| v = midi->voice; | v = VOICEHDLPTR(hdl); |
| vterm = v + VOICE_MAX; | vterm = VOICEHDLEND(hdl); |
| do { | do { |
| if ((v->phase != VOICE_FREE) && (v->channel == ch)) { | if ((v->phase != VOICE_FREE) && (v->channel == ch)) { |
| freq_update(v); | freq_update(v); |
| Line 582 static void pitchbendor(MIDIHDL midi, CH | Line 637 static void pitchbendor(MIDIHDL midi, CH |
| } | } |
| } | } |
| static void allvolupdate(MIDIHDL midi) { | static void VERMOUTHCL allvolupdate(MIDIHDL hdl) { |
| int level; | int level; |
| CHANNEL ch; | CHANNEL ch; |
| Line 590 static void allvolupdate(MIDIHDL midi) { | Line 645 static void allvolupdate(MIDIHDL midi) { |
| VOICE v; | VOICE v; |
| VOICE vterm; | VOICE vterm; |
| level = gaintbl[midi->gain + 16] >> 1; | level = gaintbl[hdl->gain + 16] >> 1; |
| level *= midi->master; | level *= hdl->master; |
| midi->level = level; | hdl->level = level; |
| ch = midi->channel; | ch = hdl->channel; |
| chterm = ch + 16; | chterm = ch + CHANNEL_MAX; |
| do { | do { |
| ch->level = (level * ch->volume * ch->expression) >> 14; | ch->level = (level * ch->volume * ch->expression) >> 14; |
| ch++; | ch++; |
| } while(ch < chterm); | } while(ch < chterm); |
| v = midi->voice; | v = VOICEHDLPTR(hdl); |
| vterm = v + VOICE_MAX; | vterm = VOICEHDLEND(hdl); |
| do { | do { |
| if (v->phase & (VOICE_ON | VOICE_SUSTAIN)) { | if (v->phase & (VOICE_ON | VOICE_SUSTAIN)) { |
| voice_volupdate(v); | voice_volupdate(v); |
| Line 610 static void allvolupdate(MIDIHDL midi) { | Line 665 static void allvolupdate(MIDIHDL midi) { |
| } while(v < vterm); | } while(v < vterm); |
| } | } |
| static void allresetmidi(MIDIHDL midi) { | #if defined(ENABLE_GSRX) |
| static void VERMOUTHCL allresetmidi(MIDIHDL hdl, BOOL gs) | |
| #else | |
| #define allresetmidi(m, g) _allresetmidi(m) | |
| static void VERMOUTHCL _allresetmidi(MIDIHDL hdl) | |
| #endif | |
| { | |
| CHANNEL ch; | CHANNEL ch; |
| CHANNEL chterm; | CHANNEL chterm; |
| UINT flag; | UINT flag; |
| midi->master = 127; | hdl->master = 127; |
| ch = midi->channel; | ch = hdl->channel; |
| chterm = ch + 16; | chterm = ch + CHANNEL_MAX; |
| ZeroMemory(ch, sizeof(_CHANNEL) * 16); | ZeroMemory(ch, sizeof(_CHANNEL) * CHANNEL_MAX); |
| flag = 0; | flag = 0; |
| do { | do { |
| ch->flag = flag++; | ch->flag = flag++; |
| ch->panpot = 64; | |
| ch->pitchsens = 2; | ch->pitchsens = 2; |
| #if !defined(MIDI_GMONLY) | |
| ch->bank = 0; | ch->bank = 0; |
| progchange(midi, ch, 0); | #endif |
| ch->panpot = 64; | |
| progchange(hdl, ch, 0); | |
| resetallcontrollers(ch); | resetallcontrollers(ch); |
| #if defined(ENABLE_GSRX) | |
| ch->keyshift = 0x40; | |
| ch->noterange[0] = 0x00; | |
| ch->noterange[1] = 0x7f; | |
| if (gs) { | |
| ch->gsrx[0] = 0xff; | |
| ch->gsrx[1] = 0xff; | |
| ch->gsrx[2] = 0xff; | |
| } | |
| else { | |
| ch->gsrx[0] = 0x7f; | |
| ch->gsrx[1] = 0xff; | |
| ch->gsrx[2] = 0x02; | |
| } | |
| #endif | |
| ch++; | ch++; |
| } while(ch < chterm); | } while(ch < chterm); |
| allresetvoices(midi); | allresetvoices(hdl); |
| allvolupdate(midi); | allvolupdate(hdl); |
| } | } |
| // ---- | // ---- |
| UINT midiout_getver(char *string, int leng) { | VEXTERN UINT VEXPORT midiout_getver(char *string, int leng) { |
| milstr_ncpy(string, vermouthver, leng); | leng = min(leng, sizeof(vermouthver)); |
| CopyMemory(string, vermouthver, leng); | |
| return((MIDIOUT_VERSION << 8) | 0x00); | return((MIDIOUT_VERSION << 8) | 0x00); |
| } | } |
| MIDIHDL midiout_create(MIDIMOD module, UINT worksize) { | VEXTERN MIDIHDL VEXPORT midiout_create(MIDIMOD mod, UINT worksize) { |
| UINT size; | UINT size; |
| MIDIHDL ret; | MIDIHDL ret; |
| if (module == NULL) { | if (mod == NULL) { |
| return(NULL); | return(NULL); |
| } | } |
| worksize = min(worksize, 512); | worksize = min(worksize, 512); |
| Line 658 MIDIHDL midiout_create(MIDIMOD module, U | Line 736 MIDIHDL midiout_create(MIDIMOD module, U |
| size += sizeof(_SAMPLE) * worksize; | size += sizeof(_SAMPLE) * worksize; |
| ret = (MIDIHDL)_MALLOC(size, "MIDIHDL"); | ret = (MIDIHDL)_MALLOC(size, "MIDIHDL"); |
| if (ret) { | if (ret) { |
| midimod_lock(mod); | |
| ZeroMemory(ret, size); | ZeroMemory(ret, size); |
| ret->samprate = module->samprate; | ret->samprate = mod->samprate; |
| ret->worksize = worksize; | ret->worksize = worksize; |
| ret->module = module; | ret->module = mod; |
| // ret->master = 127; | // ret->master = 127; |
| ret->bank0[0] = module->tone[0]; | ret->bank0[0] = mod->tone[0]; |
| ret->bank0[1] = module->tone[1]; | ret->bank0[1] = mod->tone[1]; |
| ret->sampbuf = (SINT32 *)(ret + 1); | ret->sampbuf = (SINT32 *)(ret + 1); |
| ret->resampbuf = (SAMPLE)(ret->sampbuf + worksize * 2); | ret->resampbuf = (SAMPLE)(ret->sampbuf + worksize * 2); |
| allresetmidi(ret); | allresetmidi(ret, FALSE); |
| } | } |
| return(ret); | return(ret); |
| } | } |
| void midiout_destroy(MIDIHDL hdl) { | VEXTERN void VEXPORT midiout_destroy(MIDIHDL hdl) { |
| MIDIMOD mod; | |
| if (hdl) { | if (hdl) { |
| mod = hdl->module; | |
| _MFREE(hdl); | _MFREE(hdl); |
| midimod_lock(mod); | |
| } | } |
| } | } |
| void midiout_shortmsg(MIDIHDL hdl, UINT32 msg) { | VEXTERN void VEXPORT midiout_shortmsg(MIDIHDL hdl, UINT32 msg) { |
| UINT cmd; | UINT cmd; |
| CHANNEL ch; | CHANNEL ch; |
| Line 732 void midiout_shortmsg(MIDIHDL hdl, UINT3 | Line 815 void midiout_shortmsg(MIDIHDL hdl, UINT3 |
| } | } |
| } | } |
| static void longmsg_gm(MIDIHDL hdl, const BYTE *msg, UINT size) { | static void VERMOUTHCL longmsg_uni(MIDIHDL hdl, const UINT8 *msg, UINT size) { |
| if ((size > 5) && (msg[2] == 0x7f) && (msg[3] == 0x09)) { | if ((size >= 6) && (msg[2] == 0x7f)) { |
| allresetmidi(hdl); // GM reset | switch(msg[3]) { |
| case 0x04: | |
| if ((msg[4] == 0x01) && (size >= 8)) { | |
| hdl->master = msg[6] & 0x7f; | |
| allvolupdate(hdl); | |
| } | |
| break; | |
| } | |
| } | } |
| } | } |
| static void longmsg_roland(MIDIHDL hdl, const BYTE *msg, UINT size) { | static void VERMOUTHCL longmsg_gm(MIDIHDL hdl, const UINT8 *msg, UINT size) { |
| if ((size >= 6) && (msg[2] == 0x7f)) { | |
| switch(msg[3]) { | |
| case 0x09: | |
| if (msg[4] == 0x01) { | |
| allresetmidi(hdl, FALSE); // GM reset | |
| break; | |
| } | |
| #if !defined(MIDI_GMONLY) | |
| else if ((msg[4] == 0x02) || (msg[4] == 0x03)) { | |
| allresetmidi(hdl, TRUE); // GM reset | |
| break; | |
| } | |
| #endif | |
| break; | |
| } | |
| } | |
| } | |
| static void VERMOUTHCL rolandcmd4(MIDIHDL hdl, UINT addr, UINT8 data) { | |
| UINT addr; | |
| UINT part; | UINT part; |
| CHANNEL ch; | CHANNEL ch; |
| #if defined(ENABLE_GSRX) | |
| UINT8 bit; | |
| #endif | |
| addr = addr & 0x000fffff; | |
| if (addr == 0x00004) { // Vol | |
| hdl->master = data; | |
| allvolupdate(hdl); | |
| } | |
| else if ((addr & (~0xff)) == 0x00100) { | |
| const UINT pos = addr & 0xff; | |
| if (pos < 0x30) { // Patch Name | |
| } | |
| else { | |
| switch(addr & 0xff) { | |
| case 0x30: // Reverb Macro | |
| case 0x31: // Reverb Charactor | |
| case 0x32: // Reverb Pre-LPF | |
| case 0x33: // Reverb Level | |
| case 0x34: // Reverb Time | |
| case 0x35: // Reverb Delay FeedBack | |
| case 0x37: // Reverb Predelay Time | |
| case 0x38: // Chorus Macro | |
| case 0x39: // Chorus Pre-LPF | |
| case 0x3a: // Chorus Level | |
| case 0x3b: // Chorus FeedBack | |
| case 0x3c: // Chorus Delay | |
| case 0x3d: // Chorus Rate | |
| case 0x3e: // Chorus Depth | |
| case 0x3f: // Chorus send level to reverb | |
| case 0x40: // Chorus send level to delay | |
| case 0x50: // Delay Macro | |
| case 0x51: // Delay Time Pre-LPF | |
| case 0x52: // Delay Time Center | |
| case 0x53: // Delay Time Ratio Left | |
| case 0x54: // Delay Time Ratio Right | |
| case 0x55: // Delay Level Center | |
| case 0x56: // Delay Level Left | |
| case 0x57: // Delay Level Right | |
| case 0x58: // Delay Level | |
| case 0x59: // Delay Freeback | |
| case 0x5a: // Delay sendlevel to Reverb | |
| break; | |
| } | |
| } | |
| } | |
| else if ((addr & (~(0x0fff))) == 0x01000) { // GS CH | |
| part = (addr >> 8) & 0x0f; | |
| if (part == 0) { // part10 | |
| part = 9; | |
| } | |
| else if (part < 10) { // part1-9 | |
| part--; | |
| } | |
| ch = hdl->channel + part; | |
| switch(addr & 0xff) { | |
| #if !defined(MIDI_GMONLY) | |
| case 0x00: // TONE NUMBER | |
| ch->bank = data; | |
| break; | |
| #endif | |
| case 0x01: // PROGRAM NUMBER | |
| progchange(hdl, ch, data); | |
| break; | |
| case 0x02: // Rx.CHANNEL | |
| TRACEOUT(("RxCHANNEL: %d", data)); | |
| break; | |
| #if defined(ENABLE_GSRX) | |
| case 0x03: // Rx.PITCHBEND | |
| case 0x04: // Rx.CH PRESSURE | |
| case 0x05: // Rx.PROGRAM CHANGE | |
| case 0x06: // Rx.CONTROL CHANGE | |
| case 0x07: // Rx.POLY PRESSURE | |
| case 0x08: // Rx.NOTE MESSAGE | |
| case 0x09: // Rx.PRN | |
| case 0x0a: // Rx.NRPN | |
| bit = 1 << ((addr - 0x03) & 7); | |
| if (data == 0) { | |
| ch->gsrx[0] = ch->gsrx[0] & (~bit); | |
| } | |
| else if (data == 1) { | |
| ch->gsrx[0] = ch->gsrx[0] | bit; | |
| } | |
| break; | |
| case 0x0b: // Rx.MODULATION | |
| case 0x0c: // Rx.VOLUME | |
| case 0x0d: // Rx.PANPOT | |
| case 0x0e: // Rx.EXPRESSION | |
| case 0x0f: // Rx.HOLD1 | |
| case 0x10: // Rx.PORTAMENTO | |
| case 0x11: // Rx.SOSTENUTO | |
| case 0x12: // Rx.SOFT | |
| bit = 1 << ((addr - 0x0b) & 7); | |
| if (data == 0) { | |
| ch->gsrx[1] = ch->gsrx[1] & (~bit); | |
| } | |
| else if (data == 1) { | |
| ch->gsrx[1] = ch->gsrx[1] | bit; | |
| } | |
| break; | |
| #endif | |
| case 0x15: // USE FOR RHYTHM PART | |
| if (data == 0) { | |
| ch->flag &= ~CHANNEL_RHYTHM; | |
| TRACEOUT(("ch%d - tone", part + 1)); | |
| } | |
| else if ((data == 1) || (data == 2)) { | |
| ch->flag |= CHANNEL_RHYTHM; | |
| TRACEOUT(("ch%d - rhythm", part + 1)); | |
| } | |
| break; | |
| if ((size > 10) && (msg[2] == 0x10) && | #if defined(ENABLE_GSRX) |
| (msg[3] == 0x42) && (msg[4] == 0x12)) { // GS data set | case 0x16: // PITCH KEY SHIFT |
| addr = (msg[5] << 16) + (msg[6] << 8) + msg[7]; | if ((data >= 0x28) && (data <= 0x58)) { |
| ch->keyshift = data; | |
| } | |
| break; | |
| case 0x1d: // KEYBOARD RANGE LOW | |
| ch->noterange[0] = data; | |
| break; | |
| case 0x1e: // KEYBOARD RANGE HIGH | |
| ch->noterange[1] = data; | |
| break; | |
| case 0x23: // Rx.BANK SELECT | |
| case 0x24: // Rx.BANK SELECT LSB | |
| bit = 1 << ((addr - 0x23) & 7); | |
| if (data == 0) { | |
| ch->gsrx[2] = ch->gsrx[2] & (~bit); | |
| } | |
| else if (data == 1) { | |
| ch->gsrx[2] = ch->gsrx[2] | bit; | |
| } | |
| break; | |
| #endif | |
| default: | |
| TRACEOUT(("Roland GS - %.6x %.2x", addr, data)); | |
| break; | |
| } | |
| } | |
| else { | |
| TRACEOUT(("Roland GS - %.6x %.2x", addr, data)); | |
| } | |
| } | |
| static void VERMOUTHCL longmsg_roland(MIDIHDL hdl, const UINT8 *msg, | |
| UINT size) { | |
| UINT addr; | |
| UINT8 data; | |
| if (size <= 10) { | |
| return; | |
| } | |
| // GS data set | |
| if ((msg[2] != 0x10) || (msg[3] != 0x42) || (msg[4] != 0x12)) { | |
| return; | |
| } | |
| addr = (msg[5] << 16) + (msg[6] << 8) + msg[7]; | |
| msg += 8; | |
| size -= 10; | |
| while(size) { | |
| size--; | |
| data = (*msg++) & 0x7f; | |
| if ((addr & (~0x400000)) == 0x7f) { // GS reset | if ((addr & (~0x400000)) == 0x7f) { // GS reset |
| allresetmidi(hdl); | allresetmidi(hdl, TRUE); |
| TRACEOUT(("GS-Reset")); | TRACEOUT(("GS-Reset")); |
| } | } |
| else if (addr == 0x400004) { // Vol | else if ((addr & 0xfff00000) == 0x00400000) { |
| hdl->master = msg[8] & 0x7f; | rolandcmd4(hdl, addr, data); |
| allvolupdate(hdl); | |
| } | |
| else if ((addr & (~(0x000f00))) == 0x401015) { // Tone/Rhythm | |
| part = (addr >> 8) & 0x0f; | |
| if (part == 0) { // part10 | |
| part = 9; | |
| } | |
| else if (part < 10) { // part1-9 | |
| part--; | |
| } | |
| ch = hdl->channel + part; | |
| if (msg[8] == 0) { | |
| ch->flag &= ~CHANNEL_RHYTHM; | |
| TRACEOUT(("ch%d - tone", part + 1)); | |
| } | |
| else if ((msg[8] == 1) || (msg[8] == 2)) { | |
| ch->flag |= CHANNEL_RHYTHM; | |
| TRACEOUT(("ch%d - rhythm", part + 1)); | |
| } | |
| } | } |
| else { | #if defined(ENABLE_PORTB) |
| TRACEOUT(("Roland GS - %.6x", addr)); | else if ((addr & 0xfff00000) == 0x00500000) { |
| if (hdl->portb) { | |
| rolandcmd4(hdl->portb, addr, data); | |
| } | |
| } | } |
| #endif // defined(ENABLE_PORTB) | |
| addr++; | |
| } | } |
| } | } |
| void midiout_longmsg(MIDIHDL hdl, const BYTE *msg, UINT size) { | VEXTERN void VEXPORT midiout_longmsg(MIDIHDL hdl, const UINT8 *msg, UINT size) { |
| UINT id; | UINT id; |
| Line 789 void midiout_longmsg(MIDIHDL hdl, const | Line 1051 void midiout_longmsg(MIDIHDL hdl, const |
| } | } |
| if (size > 3) { // (msg[size - 1] == 0xf7) | if (size > 3) { // (msg[size - 1] == 0xf7) |
| id = msg[1]; | id = msg[1]; |
| if (id == 0x7e) { // GM | if (id == 0x7f) { // Universal realtime |
| longmsg_uni(hdl, msg, size); | |
| } | |
| else if (id == 0x7e) { // GM | |
| longmsg_gm(hdl, msg, size); | longmsg_gm(hdl, msg, size); |
| } | } |
| else if (id == 0x41) { // Roland | else if (id == 0x41) { // Roland |
| longmsg_roland(hdl, msg, size); | longmsg_roland(hdl, msg, size); |
| } | } |
| else { | |
| TRACEOUT(("long msg unknown id:%02x", id)); | |
| } | |
| } | } |
| } | } |
| const SINT32 *midiout_get(MIDIHDL hdl, UINT *samples) { | VEXTERN const SINT32 * VEXPORT midiout_get(MIDIHDL hdl, UINT *samples) { |
| UINT size; | UINT size; |
| VOICE v; | VOICE v; |
| Line 820 const SINT32 *midiout_get(MIDIHDL hdl, U | Line 1088 const SINT32 *midiout_get(MIDIHDL hdl, U |
| } | } |
| buf = hdl->sampbuf; | buf = hdl->sampbuf; |
| ZeroMemory(buf, size * 2 * sizeof(SINT32)); | ZeroMemory(buf, size * 2 * sizeof(SINT32)); |
| v = hdl->voice; | v = VOICEHDLPTR(hdl); |
| vterm = v + VOICE_MAX; | vterm = VOICEHDLEND(hdl); |
| playing = FALSE; | playing = FALSE; |
| do { | do { |
| if (v->phase != VOICE_FREE) { | if (v->phase != VOICE_FREE) { |
| Line 871 moget_err: | Line 1139 moget_err: |
| return(NULL); | return(NULL); |
| } | } |
| UINT midiout_get32(MIDIHDL hdl, SINT32 *pcm, UINT size) { | static UINT VERMOUTHCL preparepcm(MIDIHDL hdl, UINT size) |
| { | |
| UINT step; | |
| VOICE v; | |
| VOICE vterm; | |
| SINT32 *buf; | |
| SAMPLE src; | |
| SAMPLE srcterm; | |
| UINT cnt; | |
| UINT pos; | |
| UINT rem; | |
| step = min(size, hdl->worksize); | |
| buf = hdl->sampbuf; | |
| ZeroMemory(buf, step * 2 * sizeof(SINT32)); | |
| v = VOICEHDLPTR(hdl); | |
| vterm = VOICEHDLEND(hdl); | |
| do { | |
| if (v->phase != VOICE_FREE) { | |
| cnt = step; | |
| if (v->phase & VOICE_REL) { | |
| voice_setfree(v); | |
| if (cnt > REL_COUNT) { | |
| cnt = REL_COUNT; | |
| } | |
| } | |
| if (v->flag & VOICE_FIXPITCH) { | |
| pos = v->samppos >> FREQ_SHIFT; | |
| src = v->sample->data + pos; | |
| rem = (v->sample->datasize >> FREQ_SHIFT) - pos; | |
| if (cnt < rem) { | |
| v->samppos += cnt << FREQ_SHIFT; | |
| srcterm = src + cnt; | |
| } | |
| else { | |
| voice_setfree(v); | |
| srcterm = src + rem; | |
| } | |
| } | |
| else { | |
| src = hdl->resampbuf; | |
| srcterm = v->resamp(v, src, src + cnt); | |
| } | |
| if (src != srcterm) { | |
| v->mix(v, buf, src, srcterm); | |
| } | |
| } | |
| v++; | |
| } while(v < vterm); | |
| return(step); | |
| } | |
| VEXTERN UINT VEXPORT midiout_get16(MIDIHDL hdl, SINT16 *pcm, UINT size) { | |
| UINT step; | UINT step; |
| VOICE v; | VOICE v; |
| Line 882 UINT midiout_get32(MIDIHDL hdl, SINT32 * | Line 1202 UINT midiout_get32(MIDIHDL hdl, SINT32 * |
| UINT cnt; | UINT cnt; |
| UINT pos; | UINT pos; |
| UINT rem; | UINT rem; |
| SINT32 l; | |
| SINT32 r; | |
| if ((hdl != NULL) && (size)) { | if ((hdl != NULL) && (size)) { |
| do { | do { |
| Line 889 UINT midiout_get32(MIDIHDL hdl, SINT32 * | Line 1211 UINT midiout_get32(MIDIHDL hdl, SINT32 * |
| size -= step; | size -= step; |
| buf = hdl->sampbuf; | buf = hdl->sampbuf; |
| ZeroMemory(buf, step * 2 * sizeof(SINT32)); | ZeroMemory(buf, step * 2 * sizeof(SINT32)); |
| v = hdl->voice; | v = VOICEHDLPTR(hdl); |
| vterm = v + VOICE_MAX; | vterm = VOICEHDLEND(hdl); |
| do { | do { |
| if (v->phase != VOICE_FREE) { | if (v->phase != VOICE_FREE) { |
| cnt = step; | cnt = step; |
| Line 924 UINT midiout_get32(MIDIHDL hdl, SINT32 * | Line 1246 UINT midiout_get32(MIDIHDL hdl, SINT32 * |
| v++; | v++; |
| } while(v < vterm); | } while(v < vterm); |
| do { | do { |
| l = pcm[0]; | |
| r = pcm[1]; | |
| l += buf[0] >> (SAMP_SHIFT + 1); | |
| r += buf[1] >> (SAMP_SHIFT + 1); | |
| if (l < -32768) { | |
| l = -32768; | |
| } | |
| else if (l > 32767) { | |
| l = 32767; | |
| } | |
| if (r < -32768) { | |
| r = -32768; | |
| } | |
| else if (r > 32767) { | |
| r = 32767; | |
| } | |
| pcm[0] = l; | |
| pcm[1] = r; | |
| buf += 2; | |
| pcm += 2; | |
| } while(--step); | |
| } while(size); | |
| } | |
| return(0);} | |
| VEXTERN UINT VEXPORT midiout_get32(MIDIHDL hdl, SINT32 *pcm, UINT size) { | |
| UINT step; | |
| VOICE v; | |
| VOICE vterm; | |
| SINT32 *buf; | |
| SAMPLE src; | |
| SAMPLE srcterm; | |
| UINT cnt; | |
| UINT pos; | |
| UINT rem; | |
| if ((hdl != NULL) && (size)) { | |
| do { | |
| step = min(size, hdl->worksize); | |
| size -= step; | |
| buf = hdl->sampbuf; | |
| ZeroMemory(buf, step * 2 * sizeof(SINT32)); | |
| v = VOICEHDLPTR(hdl); | |
| vterm = VOICEHDLEND(hdl); | |
| do { | |
| if (v->phase != VOICE_FREE) { | |
| cnt = step; | |
| if (v->phase & VOICE_REL) { | |
| voice_setfree(v); | |
| if (cnt > REL_COUNT) { | |
| cnt = REL_COUNT; | |
| } | |
| } | |
| if (v->flag & VOICE_FIXPITCH) { | |
| pos = v->samppos >> FREQ_SHIFT; | |
| src = v->sample->data + pos; | |
| rem = (v->sample->datasize >> FREQ_SHIFT) - pos; | |
| if (cnt < rem) { | |
| v->samppos += cnt << FREQ_SHIFT; | |
| srcterm = src + cnt; | |
| } | |
| else { | |
| voice_setfree(v); | |
| srcterm = src + rem; | |
| } | |
| } | |
| else { | |
| src = hdl->resampbuf; | |
| srcterm = v->resamp(v, src, src + cnt); | |
| } | |
| if (src != srcterm) { | |
| v->mix(v, buf, src, srcterm); | |
| } | |
| } | |
| v++; | |
| } while(v < vterm); | |
| do { | |
| pcm[0] += buf[0] >> (SAMP_SHIFT + 1); | pcm[0] += buf[0] >> (SAMP_SHIFT + 1); |
| pcm[1] += buf[1] >> (SAMP_SHIFT + 1); | pcm[1] += buf[1] >> (SAMP_SHIFT + 1); |
| buf += 2; | buf += 2; |
| Line 934 UINT midiout_get32(MIDIHDL hdl, SINT32 * | Line 1336 UINT midiout_get32(MIDIHDL hdl, SINT32 * |
| return(0); | return(0); |
| } | } |
| void midiout_setgain(MIDIHDL hdl, int gain) { | VEXTERN void VEXPORT midiout_setgain(MIDIHDL hdl, int gain) { |
| if (hdl) { | if (hdl) { |
| if (gain < -16) { | if (gain < -16) { |
| Line 948 void midiout_setgain(MIDIHDL hdl, int ga | Line 1350 void midiout_setgain(MIDIHDL hdl, int ga |
| } | } |
| } | } |
| VEXTERN void VEXPORT midiout_setmoduleid(MIDIHDL hdl, UINT8 moduleid) { | |
| if (hdl) { | |
| hdl->moduleid = moduleid; | |
| } | |
| } | |
| VEXTERN void VEXPORT midiout_setportb(MIDIHDL hdl, MIDIHDL portb) { | |
| #if defined(ENABLE_PORTB) | |
| if (hdl) { | |
| hdl->portb = portb; | |
| } | |
| #endif // defined(ENABLE_PORTB) | |
| } | |