/* * hexter_instance_damp_voices * * advance all sustained voices to the release phase (note that this does not * clear the sustain controller.) */ void hexter_instance_damp_voices(hexter_instance_t* instance) { int i; dx7_voice_t* voice; for (i = 0; i < instance->max_voices; i++) { voice = instance->voice[i]; if (_SUSTAINED(voice)) { /* this assumes the caller has cleared the sustain controller */ dx7_voice_release_note(instance, voice); } } }
/* * hexter_instance_all_notes_off * * put all notes into the released state */ void hexter_instance_all_notes_off(hexter_instance_t* instance) { int i; dx7_voice_t *voice; /* reset the sustain controller */ instance->cc[MIDI_CTL_SUSTAIN] = 0; for (i = 0; i < instance->max_voices; i++) { voice = instance->voice[i]; if (_ON(voice) || _SUSTAINED(voice)) { dx7_voice_release_note(instance, voice); } } }
/* * nekobee_synth_all_notes_off * * put all notes into the released state */ void nekobee_synth_all_notes_off(nekobee_synth_t* synth) { int i; nekobee_voice_t *voice; /* reset the sustain controller */ synth->cc[MIDI_CTL_SUSTAIN] = 0; for (i = 0; i < synth->voices; i++) { //voice = synth->voice[i]; voice = synth->voice; if (_ON(voice) || _SUSTAINED(voice)) { nekobee_voice_release_note(synth, voice); } } }
/* * hexter_synth_alloc_voice */ static dx7_voice_t * hexter_synth_alloc_voice(hexter_instance_t* instance, unsigned char key) { int i; dx7_voice_t* voice; /* If there is another voice on the same key, advance it * to the release phase. Note that a DX7 doesn't do this, * but we do it here to keep our CPU usage low. */ for (i = 0; i < instance->max_voices; i++) { voice = instance->voice[i]; if (voice->key == key && (_ON(voice) || _SUSTAINED(voice))) { dx7_voice_release_note(instance, voice); } } voice = NULL; if (instance->current_voices < instance->max_voices) { /* check if there's an available voice */ for (i = 0; i < instance->max_voices; i++) { if (_AVAILABLE(instance->voice[i])) { voice = instance->voice[i]; break; } } /* if not, then stop a running voice. */ if (voice == NULL) { voice = hexter_synth_free_voice_by_kill(instance); } } else { /* at instance polyphony limit */ voice = hexter_synth_free_voice_by_kill(instance); } if (voice == NULL) { DEBUG_MESSAGE(DB_NOTE, " hexter_synth_alloc_voice: failed to allocate a voice (key=%d)\n", key); return NULL; } DEBUG_MESSAGE(DB_NOTE, " hexter_synth_alloc_voice: key %d voice %p\n", key, voice); return voice; }
/* * hexter_synth_free_voice_by_kill * * selects a voice for killing. the selection algorithm is a refinement * of the algorithm previously in fluid_synth_alloc_voice. */ static dx7_voice_t* hexter_synth_free_voice_by_kill(hexter_instance_t *instance) { int i; int best_prio = 10001; int this_voice_prio; dx7_voice_t *voice; int best_voice_index = -1; for (i = 0; i < instance->max_voices; i++) { voice = instance->voice[i]; /* safeguard against an available voice. */ if (_AVAILABLE(voice)) return voice; /* Determine, how 'important' a voice is. * Start with an arbitrary number */ this_voice_prio = 10000; if (_RELEASED(voice)) { /* This voice is in the release phase. Consider it much less * important than a voice which is still held. */ this_voice_prio -= 2000; } else if (_SUSTAINED(voice)) { /* The sustain pedal is held down, and this voice is still "on" * because of this even though it has received a note off. * Consider it less important than voices which have not yet * received a note off. This decision is somewhat subjective, but * usually the sustain pedal is used to play 'more-voices-than- * fingers', and if so, it won't hurt as much to kill one of those * voices. */ this_voice_prio -= 1000; }; /* We are not enthusiastic about releasing voices, which have just been * started. Otherwise hitting a chord may result in killing notes * belonging to that very same chord. So subtract the age of the voice * from the priority - an older voice is just a little bit less * important than a younger voice. */ this_voice_prio -= (instance->note_id - voice->note_id); /* -FIX- not yet implemented: * /= take a rough estimate of loudness into account. Louder voices are more important. =/ * if (voice->volenv_section != FLUID_VOICE_ENVATTACK){ * this_voice_prio += voice->volenv_val*1000.; * }; */ /* check if this voice has less priority than the previous candidate. */ if (this_voice_prio < best_prio) best_voice_index = i, best_prio = this_voice_prio; } if (best_voice_index < 0) return NULL; voice = instance->voice[best_voice_index]; DEBUG_MESSAGE(DB_NOTE, " hexter_synth_free_voice_by_kill: no available voices, killing voice %d note id %d\n", best_voice_index, voice->note_id); dx7_voice_off(voice); return voice; }