Index: src/iiwu_synth.c =================================================================== RCS file: /cvsroot/iiwusynth/iiwusynth/src/iiwu_synth.c,v retrieving revision 1.42 diff -u -r1.42 iiwu_synth.c --- src/iiwu_synth.c 14 Jun 2002 05:48:40 -0000 1.42 +++ src/iiwu_synth.c 13 Jul 2002 14:13:37 -0000 @@ -1224,6 +1224,59 @@ return 0; } +/* + * iiwu_synth_free_voice_by_kill + * + * selects a voice for killing. the selection algorithm is a refinement + * of the algorithm previously in iiwu_synth_alloc_voice. + */ +iiwu_voice_t* +iiwu_synth_free_voice_by_kill (iiwu_synth_t* synth) +{ + int i, k; + iiwu_real_t min_prio, prio; + iiwu_voice_t* voice; + + k = -1; + min_prio = 50.; + + for (i = 0; i < synth->nvoice; i++) { + + voice = synth->voice[i]; + + /* safeguard against an available voice. */ + if (_AVAILABLE(voice)) + return voice; + + /* assign basic priority class based on voice state. */ + if (_RELEASED(voice)) + prio = 20.; + else if (_SUSTAINED(voice)) + prio = 10.; + else + prio = 0.; + + /* the later the voice's stage in the envelope section the less + * priority it has. */ + prio += 7. - voice->volenv_section; + + /* take a rough estimate of loudness into account. */ + if (voice->volenv_section != IIWU_VOICE_ENVATTACK) + prio += voice->volenv_val; + + /* check if this voice has less priority than the previous candidate. */ + if (prio < min_prio) + k = i, + min_prio = prio; + } + + if (k < 0) + return NULL; + + voice = synth->voice[k]; + iiwu_voice_off (voice); + return voice; +} /* * iiwu_synth_alloc_voice @@ -1245,45 +1298,7 @@ } } - /* No synthesis process available: steal one according to channel - priorities */ - if (voice == NULL) { - - for (k = 0; k < IIWU_NUM_CHANNELS; k++) { - - /* We steal a voice according to the priorities of the - channels. (DLS specifications) */ - ch = chan_priority[k]; - - /* first, try to find a key that's been released */ - for (i = 0; i < synth->nvoice; i++) { - if ((synth->voice[i]->chan == ch) && _RELEASED(synth->voice[i])) { - iiwu_voice_off(synth->voice[i]); - voice = synth->voice[i]; - break; - } - } - - /* second, try to find a key that's been sustained */ - for (i = 0; i < synth->nvoice; i++) { - if ((synth->voice[i]->chan == ch) && _SUSTAINED(synth->voice[i])) { - iiwu_voice_off(synth->voice[i]); - voice = synth->voice[i]; - break; - } - } - - /* third, go for any key on this channel */ - if (voice == NULL) { - for (i = 0; i < synth->nvoice; i++) { - if (synth->voice[i]->chan == ch) { - iiwu_voice_off(synth->voice[i]); - voice = synth->voice[i]; - } - } - } - } - } + voice = iiwu_synth_free_voice_by_kill (synth); if (voice == NULL) { IIWU_LOG(IIWU_WARN, "Max polyphony reached (chan=%d,key=%d)", chan, key);