--- np2/sound/vermouth/midiout.c 2003/12/01 04:01:42 1.5 +++ np2/sound/vermouth/midiout.c 2006/12/16 22:23:24 1.17 @@ -2,9 +2,8 @@ #include "midiout.h" -#define MIDIOUT_VERSION 0x104 -#define MIDIOUT_VERSTRING "VERMOUTH 1.04" - +#define MIDIOUT_VERSION 0x116 +#define MIDIOUT_VERSTRING "VERMOUTH 1.16" static const char vermouthver[] = MIDIOUT_VERSTRING; @@ -16,16 +15,40 @@ static const int gaintbl[24+1] = // ---- 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; int vol; ch = v->channel; +#if defined(VOLUME_ACURVE) + vol = ch->level * acurve[v->velocity]; + vol >>= 8; +#else vol = ch->level * v->velocity; vol >>= 7; +#endif vol *= v->sample->volume; 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; if ((v->flag & VOICE_MIXMASK) == VOICE_MIXNORMAL) { if (v->panpot < 64) { @@ -40,9 +63,10 @@ static void voice_volupdate(VOICE v) { v->volleft = vol; } } +#endif } -static INSTLAYER selectlayer(VOICE v, INSTRUMENT inst) { +static INSTLAYER VERMOUTHCL selectlayer(VOICE v, INSTRUMENT inst) { int layers; INSTLAYER layer; @@ -89,7 +113,7 @@ static INSTLAYER selectlayer(VOICE v, IN return(layersel); } -static void freq_update(VOICE v) { +static void VERMOUTHCL freq_update(VOICE v) { CHANNEL ch; float step; @@ -113,7 +137,8 @@ static void freq_update(VOICE v) { 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; INSTLAYER layer; @@ -137,10 +162,10 @@ static void voice_on(MIDIHDL midi, CHANN #if !defined(MIDI_GMONLY) inst = ch->rhythm[key]; if (inst == NULL) { - inst = midi->bank0[1][key]; + inst = hdl->bank0[1][key]; } #else - inst = midi->bank0[1][key]; + inst = hdl->bank0[1][key]; #endif if (inst == NULL) { return; @@ -183,6 +208,21 @@ static void voice_on(MIDIHDL midi, CHANN else { 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)) { v->flag = VOICE_MIXCENTRE; } @@ -196,11 +236,12 @@ static void voice_on(MIDIHDL midi, CHANN v->flag = VOICE_MIXNORMAL; v->panpot = panpot; } +#endif if (!layer->samprate) { v->flag |= VOICE_FIXPITCH; } else { - v->freq = (float)layer->samprate / (float)midi->samprate * + v->freq = (float)layer->samprate / (float)hdl->samprate * (float)v->frequency / (float)layer->freqroot; } voice_setphase(v, VOICE_ON); @@ -218,7 +259,7 @@ static void voice_on(MIDIHDL midi, CHANN envelope_updates(v); } -static void voice_off(VOICE v) { +static void VERMOUTHCL voice_off(VOICE v) { voice_setphase(v, VOICE_OFF); if (v->sample->mode & MODE_ENVELOPE) { @@ -228,13 +269,13 @@ static void voice_off(VOICE v) { } } -static void allresetvoices(MIDIHDL midi) { +static void VERMOUTHCL allresetvoices(MIDIHDL hdl) { VOICE v; VOICE vterm; - v = midi->voice; - vterm = v + VOICE_MAX; + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); do { voice_setfree(v); v++; @@ -244,7 +285,7 @@ static void allresetvoices(MIDIHDL midi) // ---- 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 v1; @@ -253,8 +294,8 @@ static void key_on(MIDIHDL midi, CHANNEL int volmin; v = NULL; - v1 = midi->voice; - v2 = v1 + VOICE_MAX; + v1 = VOICEHDLPTR(hdl); + v2 = VOICEHDLEND(hdl); do { v2--; if (v2->phase == VOICE_FREE) { @@ -268,12 +309,12 @@ static void key_on(MIDIHDL midi, CHANNEL } while(v1 < v2); if (v != NULL) { - voice_on(midi, ch, v, key, vel); + voice_on(hdl, ch, v, key, vel); return; } volmin = 0x7fffffff; - v2 = v1 + VOICE_MAX; + v2 = VOICEHDLEND(hdl); do { v2--; if (!(v2->phase & (VOICE_ON | VOICE_REL))) { @@ -290,17 +331,17 @@ static void key_on(MIDIHDL midi, CHANNEL if (v != NULL) { 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 vterm; - v = midi->voice; - vterm = v + VOICE_MAX; + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); do { if ((v->phase & VOICE_ON) && (v->channel == ch) && (v->note == key)) { @@ -316,13 +357,14 @@ static void key_off(MIDIHDL midi, CHANNE } 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 vterm; - v = midi->voice; - vterm = v + VOICE_MAX; + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); do { if ((v->phase & VOICE_ON) && (v->channel == ch) && (v->note == key)) { @@ -338,14 +380,18 @@ static void key_pressure(MIDIHDL midi, C // ---- control -static void volumeupdate(MIDIHDL midi, CHANNEL ch) { +static void VERMOUTHCL volumeupdate(MIDIHDL hdl, CHANNEL ch) { VOICE v; VOICE vterm; - ch->level = (midi->level * ch->volume * ch->expression) >> 14; - v = midi->voice; - vterm = v + VOICE_MAX; +#if defined(VOLUME_ACURVE) + ch->level = (hdl->level * acurve[ch->volume] * ch->expression) >> 15; +#else + ch->level = (hdl->level * ch->volume * ch->expression) >> 14; +#endif + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); do { if ((v->phase & (VOICE_ON | VOICE_SUSTAIN)) && (v->channel == ch)) { voice_volupdate(v); @@ -355,13 +401,13 @@ static void volumeupdate(MIDIHDL midi, C } while(v < vterm); } -static void pedaloff(MIDIHDL midi, CHANNEL ch) { +static void VERMOUTHCL pedaloff(MIDIHDL hdl, CHANNEL ch) { VOICE v; VOICE vterm; - v = midi->voice; - vterm = v + VOICE_MAX; + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); do { if ((v->phase & VOICE_SUSTAIN) && (v->channel == ch)) { voice_off(v); @@ -370,13 +416,13 @@ static void pedaloff(MIDIHDL midi, CHANN } while(v < vterm); } -static void allsoundsoff(MIDIHDL midi, CHANNEL ch) { +static void VERMOUTHCL allsoundsoff(MIDIHDL hdl, CHANNEL ch) { VOICE v; VOICE vterm; - v = midi->voice; - vterm = v + VOICE_MAX; + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); do { if ((v->phase != VOICE_FREE) && (v->channel == ch)) { voice_setphase(v, VOICE_REL); @@ -386,7 +432,7 @@ static void allsoundsoff(MIDIHDL midi, C } while(v < vterm); } -static void resetallcontrollers(CHANNEL ch) { +static void VERMOUTHCL resetallcontrollers(CHANNEL ch) { ch->flag &= CHANNEL_MASK; if (ch->flag == 9) { @@ -398,13 +444,13 @@ static void resetallcontrollers(CHANNEL ch->pitchfactor = 1.0; } -static void allnotesoff(MIDIHDL midi, CHANNEL ch) { +static void VERMOUTHCL allnotesoff(MIDIHDL hdl, CHANNEL ch) { VOICE v; VOICE vterm; - v = midi->voice; - vterm = v + VOICE_MAX; + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); do { #if 1 if ((v->phase & (VOICE_ON | VOICE_SUSTAIN)) && (v->channel == ch)) { @@ -424,13 +470,21 @@ static void allnotesoff(MIDIHDL midi, CH } 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; switch(ctrl & 0x7f) { +#if !defined(MIDI_GMONLY) case CTRL_PGBANK: +#if defined(ENABLE_GSRX) + if (!(ch->gsrx[2] & GSRX2_BANKSELECT)) { + break; + } +#endif ch->bank = val; break; +#endif case CTRL_DATA_M: // TRACEOUT(("data: %x %x %x", c->rpn_l, c->rpn_m, val)); @@ -444,7 +498,7 @@ static void ctrlchange(MIDIHDL midi, CHA case CTRL_VOLUME: ch->volume = val; - volumeupdate(midi, ch); + volumeupdate(hdl, ch); break; case CTRL_PANPOT: @@ -453,13 +507,13 @@ static void ctrlchange(MIDIHDL midi, CHA case CTRL_EXPRESS: ch->expression = val; - volumeupdate(midi, ch); + volumeupdate(hdl, ch); break; case CTRL_PEDAL: if (val == 0) { ch->flag &= ~CHANNEL_SUSTAIN; - pedaloff(midi, ch); + pedaloff(hdl, ch); } else { ch->flag |= CHANNEL_SUSTAIN; @@ -475,15 +529,15 @@ static void ctrlchange(MIDIHDL midi, CHA break; case CTRL_SOUNDOFF: - allsoundsoff(midi, ch); + allsoundsoff(hdl, ch); break; case CTRL_RESETCTRL: resetallcontrollers(ch); - break; + /*FALLTHROUGH*/ case CTRL_NOTEOFF: - allnotesoff(midi, ch); + allnotesoff(hdl, ch); break; case CTRL_MONOON: @@ -500,48 +554,48 @@ 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) - MIDIMOD module; + MIDIMOD mod; INSTRUMENT *bank; INSTRUMENT inst; - module = midi->module; + mod = hdl->module; inst = NULL; if (ch->bank < MIDI_BANKS) { - bank = module->tone[ch->bank * 2]; + bank = mod->tone[ch->bank * 2]; if (bank) { inst = bank[val]; } } if (inst == NULL) { - bank = midi->bank0[0]; + bank = hdl->bank0[0]; inst = bank[val]; } ch->inst = inst; bank = NULL; if (ch->bank < MIDI_BANKS) { - bank = module->tone[ch->bank * 2 + 1]; + bank = mod->tone[ch->bank * 2 + 1]; } if (bank == NULL) { - bank = midi->bank0[1]; + bank = hdl->bank0[1]; } ch->rhythm = bank; #else - ch->inst = midi->bank0[0][val]; + ch->inst = hdl->bank0[0][val]; #endif 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 vterm; - v = midi->voice; - vterm = v + VOICE_MAX; + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); do { if ((v->phase & VOICE_ON) && (v->channel == ch)) { v->velocity = vel; @@ -553,7 +607,8 @@ static void chpressure(MIDIHDL midi, CHA } 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 vterm; @@ -571,8 +626,8 @@ static void pitchbendor(MIDIHDL midi, CH ch->pitchfactor = bendhtbl[(val1 >> (6 + 7)) + 24] * bendltbl[(val1 >> 7) & 0x3f]; } - v = midi->voice; - vterm = v + VOICE_MAX; + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); do { if ((v->phase != VOICE_FREE) && (v->channel == ch)) { freq_update(v); @@ -582,7 +637,7 @@ static void pitchbendor(MIDIHDL midi, CH } } -static void allvolupdate(MIDIHDL midi) { +static void VERMOUTHCL allvolupdate(MIDIHDL hdl) { int level; CHANNEL ch; @@ -590,17 +645,17 @@ static void allvolupdate(MIDIHDL midi) { VOICE v; VOICE vterm; - level = gaintbl[midi->gain + 16] >> 1; - level *= midi->master; - midi->level = level; - ch = midi->channel; - chterm = ch + 16; + level = gaintbl[hdl->gain + 16] >> 1; + level *= hdl->master; + hdl->level = level; + ch = hdl->channel; + chterm = ch + CHANNEL_MAX; do { ch->level = (level * ch->volume * ch->expression) >> 14; ch++; } while(ch < chterm); - v = midi->voice; - vterm = v + VOICE_MAX; + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); do { if (v->phase & (VOICE_ON | VOICE_SUSTAIN)) { voice_volupdate(v); @@ -610,44 +665,68 @@ static void allvolupdate(MIDIHDL midi) { } 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 chterm; UINT flag; - ch = midi->channel; - chterm = ch + 16; - ZeroMemory(ch, sizeof(_CHANNEL) * 16); + hdl->master = 127; + ch = hdl->channel; + chterm = ch + CHANNEL_MAX; + ZeroMemory(ch, sizeof(_CHANNEL) * CHANNEL_MAX); flag = 0; do { ch->flag = flag++; - ch->panpot = 64; ch->pitchsens = 2; +#if !defined(MIDI_GMONLY) ch->bank = 0; - progchange(midi, ch, 0); +#endif + ch->panpot = 64; + progchange(hdl, ch, 0); 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++; } while(ch < chterm); - allresetvoices(midi); - allvolupdate(midi); + allresetvoices(hdl); + 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); } -MIDIHDL midiout_create(MIDIMOD module, UINT worksize) { +VEXTERN MIDIHDL VEXPORT midiout_create(MIDIMOD mod, UINT worksize) { UINT size; MIDIHDL ret; - if (module == NULL) { + if (mod == NULL) { return(NULL); } worksize = min(worksize, 512); @@ -657,28 +736,33 @@ MIDIHDL midiout_create(MIDIMOD module, U size += sizeof(_SAMPLE) * worksize; ret = (MIDIHDL)_MALLOC(size, "MIDIHDL"); if (ret) { + midimod_lock(mod); ZeroMemory(ret, size); - ret->samprate = module->samprate; + ret->samprate = mod->samprate; ret->worksize = worksize; - ret->module = module; - ret->master = 127; - ret->bank0[0] = module->tone[0]; - ret->bank0[1] = module->tone[1]; + ret->module = mod; + // ret->master = 127; + ret->bank0[0] = mod->tone[0]; + ret->bank0[1] = mod->tone[1]; ret->sampbuf = (SINT32 *)(ret + 1); ret->resampbuf = (SAMPLE)(ret->sampbuf + worksize * 2); - allresetmidi(ret); + allresetmidi(ret, FALSE); } return(ret); } -void midiout_destroy(MIDIHDL hdl) { +VEXTERN void VEXPORT midiout_destroy(MIDIHDL hdl) { + + MIDIMOD mod; if (hdl) { + mod = hdl->module; _MFREE(hdl); + midimod_lock(mod); } } -void midiout_shortmsg(MIDIHDL hdl, UINT32 msg) { +VEXTERN void VEXPORT midiout_shortmsg(MIDIHDL hdl, UINT32 msg) { UINT cmd; CHANNEL ch; @@ -731,19 +815,258 @@ 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)) { return; } - if ((size > 5) && (msg[1] == 0x7e)) { // GM - if ((msg[2] == 0x7f) && (msg[3] == 0x09)) { - allresetmidi(hdl); // GM reset + if (size > 3) { // (msg[size - 1] == 0xf7) + id = msg[1]; + 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; VOICE v; @@ -765,8 +1088,8 @@ const SINT32 *midiout_get(MIDIHDL hdl, U } buf = hdl->sampbuf; ZeroMemory(buf, size * 2 * sizeof(SINT32)); - v = hdl->voice; - vterm = v + VOICE_MAX; + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); playing = FALSE; do { if (v->phase != VOICE_FREE) { @@ -816,7 +1139,139 @@ moget_err: 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; VOICE v; @@ -830,12 +1285,13 @@ UINT midiout_get32(MIDIHDL hdl, SINT32 * if ((hdl != NULL) && (size)) { do { + step = min(size, hdl->worksize); size -= step; buf = hdl->sampbuf; ZeroMemory(buf, step * 2 * sizeof(SINT32)); - v = hdl->voice; - vterm = v + VOICE_MAX; + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); do { if (v->phase != VOICE_FREE) { cnt = step; @@ -868,6 +1324,7 @@ UINT midiout_get32(MIDIHDL hdl, SINT32 * } v++; } while(v < vterm); + do { pcm[0] += buf[0] >> (SAMP_SHIFT + 1); pcm[1] += buf[1] >> (SAMP_SHIFT + 1); @@ -879,7 +1336,7 @@ UINT midiout_get32(MIDIHDL hdl, SINT32 * return(0); } -void midiout_setgain(MIDIHDL hdl, int gain) { +VEXTERN void VEXPORT midiout_setgain(MIDIHDL hdl, int gain) { if (hdl) { if (gain < -16) { @@ -893,3 +1350,19 @@ 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) +} +