/* be_midi_key_on: * Triggers a specified voice. */ extern "C" void be_midi_key_on(int inst, int note, int bend, int vol, int pan) { int voice; if (inst > 127) { /* percussion */ /* hack to use channel 10 only */ midi_beos.xmin = midi_beos.xmax = -1; voice = _midi_allocate_voice(10, 10); midi_beos.xmin = midi_beos.xmax = 10; if (voice < 0) return; cur_note[10] = inst - 128; cur_vol[10] = vol; be_midi_set_pan(voice, pan); _be_midisynth->NoteOn(10, inst - 128, vol, B_NOW); } else { /* normal instrument */ voice = _midi_allocate_voice(1, 16); if (voice < 0) return; if (inst != cur_patch[voice]) { _be_midisynth->ProgramChange(voice, inst); cur_patch[voice] = inst; } cur_note[voice] = note; cur_vol[voice] = vol; be_midi_set_pitch(voice, note, bend); be_midi_set_pan(voice, pan); _be_midisynth->NoteOn(voice, note, vol, B_NOW); } }
/* _awe32_do_note: * Actually plays the note as described above; the above function just remaps * the drums. */ static void _awe32_do_note(int inst, int note, int bend, int vol, int pan) { int voice; int i; envparms_t *env; int key,vel; int atten; int pan_pos; /* EMU8000 pan is back-to-front and twice the scale */ pan = 0x100-2*pan; if (pan>0xff) pan = 0xff; if (pan<0x00) pan = 0x00; for (i=0;i<midi_preset[inst].num_splits;i++) { /* envelope for this split */ env=midi_preset[inst].split[i]; /* should we play this split? */ if ((note>=env->minkey)&&(note<=env->maxkey)&&( vol>=env->minvel)&&( vol<=env->maxvel)) { /* get a voice (any voice) to play it on */ voice = _midi_allocate_voice (-1,-1); /* did we get one? */ if (voice>=0) { /* set the current envelope for this voice */ voice_envelope[voice]=env; /* set pitch and velocity */ key = note*0x1000+bend; vel = vol; /* override key and velocity if envelope says so */ if ((env->key>=0)&&(env->key<=127)) key=env->key*0x1000; if ((env->vel>=0)&&(env->vel<=127)) vel=env->vel; /* check key and velocity numbers are within range */ if (key>0x7ffff) key=0x7ffff; if (key<0) key=0; if (vel>127) vel=127; if (vel<0) vel=0; /* add one-off information to the envelope (these have no side-effects on the other voices using this envelope) */ env->ip=env->ipbase+(env->ipscale*key)/1200; /* remap MIDI velocity to attenuation */ if (vel) atten = env->atten + (-20/0.375*log(vel/127.0)); else atten = 0xff; if (atten<0x00) atten = 0x00; if (atten>0xff) atten = 0xff; /* update it in the envelope */ env->ifatn=env->filter+atten; /* modify pan with envelope's built-in pan */ if (pan<0x80) { pan_pos = (pan*env->pan)/0x80; } else { pan_pos = env->pan + (pan-0x80)*(256-env->pan)/0x80; } if (pan_pos<0x00) pan_pos=0x00; if (pan_pos>0xff) pan_pos=0xff; /* update pan in the envelope */ env->psst = (pan_pos<<24) + env->loopst; /* test exclusive class */ exclusive_class_info[voice] = (inst << 8) + env->exc; if (env->exc) { int chan; for (chan = 0; chan < 32; chan++) if ((chan != voice) && (exclusive_class_info[chan] == exclusive_class_info[voice])) emu8k_terminatesound (chan); } /* start the note playing */ emu8k_startsound(voice,env); } } } }