| version 1.1.1.1, 2003/10/16 17:58:10 | version 1.17, 2006/12/16 22:23:24 | 
| Line 2 | Line 2 | 
 | #include        "midiout.h" | #include        "midiout.h" | 
 |  |  | 
 |  |  | 
| #define MIDIOUT_VERSION         0x101 | #define MIDIOUT_VERSION         0x116 | 
| #define MIDIOUT_VERSTRING       "VERMOUTH 1.01" | #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 ((v->phase & (VOICE_ON | VOICE_SUSTAIN)) && (v->channel == ch)) { | 
 |  | voice_off(v); | 
 |  | } | 
 |  | #else | 
 | if ((v->phase & VOICE_ON) && (v->channel == ch)) { | if ((v->phase & VOICE_ON) && (v->channel == ch)) { | 
 | if (ch->flag & CHANNEL_SUSTAIN) { | if (ch->flag & CHANNEL_SUSTAIN) { | 
 | voice_setphase(v, VOICE_SUSTAIN); | voice_setphase(v, VOICE_SUSTAIN); | 
| Line 414  static void allnotesoff(MIDIHDL midi, CH | Line 465  static void allnotesoff(MIDIHDL midi, CH | 
 | voice_off(v); | voice_off(v); | 
 | } | } | 
 | } | } | 
 |  | #endif | 
 | v++; | v++; | 
 | } 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 438  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 447  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 469  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 494  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 547  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 565  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 576  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 584  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 604  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; | 
 |  |  | 
| ch = midi->channel; | hdl->master = 127; | 
| chterm = ch + 16; | ch = hdl->channel; | 
| ZeroMemory(ch, sizeof(_CHANNEL) * 16); | chterm = ch + CHANNEL_MAX; | 
|  | 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); | 
 | worksize = max(worksize, 16384); | worksize = max(worksize, 16384); | 
 | size = sizeof(_MIDIHDL); | size = sizeof(_MIDIHDL); | 
| size += sizeof(SINT32) * worksize; | size += sizeof(SINT32) * 2 * worksize; | 
 | 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); | 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 725  void midiout_shortmsg(MIDIHDL hdl, UINT3 | Line 815  void midiout_shortmsg(MIDIHDL hdl, UINT3 | 
 | } | } | 
 | } | } | 
 |  |  | 
| void midiout_longmsg(MIDIHDL hdl, const BYTE *msg, UINT size) { | static void VERMOUTHCL longmsg_uni(MIDIHDL hdl, const UINT8 *msg, UINT size) { | 
|  |  | 
|  | if ((size >= 6) && (msg[2] == 0x7f)) { | 
|  | switch(msg[3]) { | 
|  | case 0x04: | 
|  | if ((msg[4] == 0x01) && (size >= 8)) { | 
|  | hdl->master = msg[6] & 0x7f; | 
|  | allvolupdate(hdl); | 
|  | } | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | 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    part; | 
|  | 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 defined(ENABLE_GSRX) | 
|  | case 0x16:                                                      // PITCH KEY SHIFT | 
|  | 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 | 
|  | allresetmidi(hdl, TRUE); | 
|  | TRACEOUT(("GS-Reset")); | 
|  | } | 
|  | else if ((addr & 0xfff00000) == 0x00400000) { | 
|  | rolandcmd4(hdl, addr, data); | 
|  | } | 
|  | #if defined(ENABLE_PORTB) | 
|  | else if ((addr & 0xfff00000) == 0x00500000) { | 
|  | if (hdl->portb) { | 
|  | rolandcmd4(hdl->portb, addr, data); | 
|  | } | 
|  | } | 
|  | #endif  // defined(ENABLE_PORTB) | 
|  | addr++; | 
|  | } | 
|  | } | 
|  |  | 
|  | VEXTERN void VEXPORT midiout_longmsg(MIDIHDL hdl, const UINT8 *msg, UINT size) { | 
|  |  | 
|  | UINT    id; | 
 |  |  | 
 | if ((hdl == NULL) || (msg == NULL)) { | if ((hdl == NULL) || (msg == NULL)) { | 
 | return; | return; | 
 | } | } | 
| if ((size > 5) && (msg[1] == 0x7e)) {                   // GM | if (size > 3) {                                                 // (msg[size - 1] == 0xf7) | 
| if ((msg[2] == 0x7f) && (msg[3] == 0x09)) { | id = msg[1]; | 
| allresetmidi(hdl);                                              // GM reset | if (id == 0x7f) {                                       // Universal realtime | 
|  | longmsg_uni(hdl, msg, size); | 
|  | } | 
|  | else if (id == 0x7e) {                          // GM | 
|  | longmsg_gm(hdl, msg, size); | 
|  | } | 
|  | else if (id == 0x41) {                          // Roland | 
|  | 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 759  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 810  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; | 
|  | VOICE   v; | 
|  | VOICE   vterm; | 
|  | SINT32  *buf; | 
|  | SAMPLE  src; | 
|  | SAMPLE  srcterm; | 
|  | UINT    cnt; | 
|  | UINT    pos; | 
|  | UINT    rem; | 
|  | SINT32  l; | 
|  | SINT32  r; | 
|  |  | 
|  | 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 { | 
|  | 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; | UINT    step; | 
 | VOICE   v; | VOICE   v; | 
| Line 824  UINT midiout_get32(MIDIHDL hdl, SINT32 * | Line 1285  UINT midiout_get32(MIDIHDL hdl, SINT32 * | 
 |  |  | 
 | if ((hdl != NULL) && (size)) { | if ((hdl != NULL) && (size)) { | 
 | do { | do { | 
 |  |  | 
 | step = min(size, hdl->worksize); | step = min(size, hdl->worksize); | 
 | 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 862  UINT midiout_get32(MIDIHDL hdl, SINT32 * | Line 1324  UINT midiout_get32(MIDIHDL hdl, SINT32 * | 
 | } | } | 
 | v++; | v++; | 
 | } while(v < vterm); | } while(v < vterm); | 
 |  |  | 
 | do { | 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); | 
| Line 873  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 882  void midiout_setgain(MIDIHDL hdl, int ga | Line 1345  void midiout_setgain(MIDIHDL hdl, int ga | 
 | else if (gain > 8) { | else if (gain > 8) { | 
 | gain = 8; | gain = 8; | 
 | } | } | 
| hdl->gain = (char)gain; | hdl->gain = (SINT8)gain; | 
 | allvolupdate(hdl); | allvolupdate(hdl); | 
 | } | } | 
 | } | } | 
 |  |  | 
 |  | 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) | 
 |  | } | 
 |  |  |