Diff for /np2/sound/vermouth/midiout.c between versions 1.5 and 1.18

version 1.5, 2003/12/01 04:01:42 version 1.18, 2006/12/17 17:53:24
Line 2 Line 2
 #include        "midiout.h"  #include        "midiout.h"
   
   
 #define MIDIOUT_VERSION         0x104  #define MIDIOUT_VERSION         0x116
 #define MIDIOUT_VERSTRING       "VERMOUTH 1.04"  #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;
   
         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);
Line 657  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 731  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) {  static UINT     VERMOUTHCL preparepcm(MIDIHDL hdl, UINT size) {
   
         UINT    size;          UINT    ret;
           SINT32  *buf;
         VOICE   v;          VOICE   v;
         VOICE   vterm;          VOICE   vterm;
         BOOL    playing;  
         SINT32  *buf;  
         SAMPLE  src;          SAMPLE  src;
         SAMPLE  srcterm;          SAMPLE  srcterm;
         UINT    cnt;          UINT    cnt;
         UINT    pos;          UINT    pos;
         UINT    rem;          UINT    rem;
   
         if ((hdl == NULL) || (samples == NULL)) {          ret = 0;
                 goto moget_err;          size = min(size, hdl->worksize);
         }  
         size = min(*samples, hdl->worksize);  
         if (size == 0) {  
                 goto moget_err;  
         }  
         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;  
         do {          do {
                 if (v->phase != VOICE_FREE) {                  if (v->phase != VOICE_FREE) {
                           ret = size;
                         cnt = size;                          cnt = size;
                         if (v->phase & VOICE_REL) {                          if (v->phase & VOICE_REL) {
                                 voice_setfree(v);                                  voice_setfree(v);
Line 797  const SINT32 *midiout_get(MIDIHDL hdl, U Line 1114  const SINT32 *midiout_get(MIDIHDL hdl, U
                         if (src != srcterm) {                          if (src != srcterm) {
                                 v->mix(v, buf, src, srcterm);                                  v->mix(v, buf, src, srcterm);
                         }                          }
                         playing = TRUE;  
                 }                  }
                 v++;                  v++;
         } while(v < vterm);          } while(v < vterm);
           return(ret);
   }
   
         if (playing) {  VEXTERN const SINT32 * VEXPORT midiout_get(MIDIHDL hdl, UINT *samples) {
                 *samples = size;  
                 pos = 0;          UINT    size;
                 do {          SINT32  *buf;
                         buf[pos*2+0] >>= (SAMP_SHIFT + 1);          SINT32  *bufterm;
                         buf[pos*2+1] >>= (SAMP_SHIFT + 1);  
                 } while(++pos < size);          if ((hdl == NULL) || (samples == NULL)) {
                 return(buf);                  goto moget_err;
           }
           size = *samples;
           if (size == 0) {
                   goto moget_err;
         }          }
           size = preparepcm(hdl, size);
           if (size == 0) {
                   goto moget_err;
           }
   
           *samples = size;
           buf = hdl->sampbuf;
           bufterm = buf + (size * 2);
           do {
                   buf[0] >>= (SAMP_SHIFT + 1);
                   buf[1] >>= (SAMP_SHIFT + 1);
                   buf += 2;
           } while(buf < bufterm);
           return(hdl->sampbuf);
   
 moget_err:  moget_err:
         return(NULL);          return(NULL);
 }  }
   
 UINT midiout_get32(MIDIHDL hdl, SINT32 *pcm, UINT size) {  VEXTERN UINT VEXPORT midiout_get16(MIDIHDL hdl, SINT16 *pcm, UINT size) {
   
         UINT    step;          UINT    step;
         VOICE   v;  
         VOICE   vterm;  
         SINT32  *buf;          SINT32  *buf;
         SAMPLE  src;          SINT32  l;
         SAMPLE  srcterm;          SINT32  r;
         UINT    cnt;  
         UINT    pos;  
         UINT    rem;  
   
         if ((hdl != NULL) && (size)) {          if (hdl != NULL) {
                 do {                  while(size) {
                         step = min(size, hdl->worksize);                          step = preparepcm(hdl, size);
                           if (step == 0) {
                                   break;
                           }
                         size -= step;                          size -= step;
                         buf = hdl->sampbuf;                          buf = hdl->sampbuf;
                         ZeroMemory(buf, step * 2 * sizeof(SINT32));  
                         v = hdl->voice;  
                         vterm = v + VOICE_MAX;  
                         do {                          do {
                                 if (v->phase != VOICE_FREE) {                                  l = pcm[0];
                                         cnt = step;                                  r = pcm[1];
                                         if (v->phase & VOICE_REL) {                                  l += buf[0] >> (SAMP_SHIFT + 1);
                                                 voice_setfree(v);                                  r += buf[1] >> (SAMP_SHIFT + 1);
                                                 if (cnt > REL_COUNT) {                                  if (l < -32768) {
                                                         cnt = REL_COUNT;                                          l = -32768;
                                                 }                                  }
                                         }                                  else if (l > 32767) {
                                         if (v->flag & VOICE_FIXPITCH) {                                          l = 32767;
                                                 pos = v->samppos >> FREQ_SHIFT;                                  }
                                                 src = v->sample->data + pos;                                  if (r < -32768) {
                                                 rem = (v->sample->datasize >> FREQ_SHIFT) - pos;                                          r = -32768;
                                                 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++;                                  else if (r > 32767) {
                         } while(v < vterm);                                          r = 32767;
                                   }
                                   pcm[0] = l;
                                   pcm[1] = r;
                                   buf += 2;
                                   pcm += 2;
                           } while(--step);
                   }
           }
           return(0);
   }
   
   VEXTERN UINT VEXPORT midiout_get32(MIDIHDL hdl, SINT32 *pcm, UINT size) {
   
           UINT    step;
           SINT32  *buf;
   
           if (hdl != NULL) {
                   while(size) {
                           step = preparepcm(hdl, size);
                           if (step == 0) {
                                   break;
                           }
                           size -= step;
                           buf = hdl->sampbuf;
                         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);
                                 buf += 2;                                  buf += 2;
                                 pcm += 2;                                  pcm += 2;
                         } while(--step);                          } while(--step);
                 } while(size);                  }
         }          }
         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 893  void midiout_setgain(MIDIHDL hdl, int ga Line 1232  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)
   }
   

Removed from v.1.5  
changed lines
  Added in v.1.18


RetroPC.NET-CVS <cvs@retropc.net>