fluid-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[fluid-dev] Re: Fluidsynth voice stealing


From: Josh Green
Subject: [fluid-dev] Re: Fluidsynth voice stealing
Date: Thu, 13 Oct 2005 01:58:34 -0700

I'm CCing the FluidSynth devel list on this..

Admittedly I knew very little about the current voice stealing algorithm
in FluidSynth until now.  I looked over the changes you made and I agree
that something should be done about the voice age.

Here is an overview of the current rating system used in FluidSynth
(lowest rated voice gets killed).

- Percussion voice (drum channel) (+4000)
- In release stage and not percussion voice (-2000)
- Sustain pedal (-1000)
- Voice volume (+ 0 to 1000 for least to maximum volume envelope)
- Voice age (- note ID offset, i.e., number of notes played since)

So, it seems the voice age has the least affect on what voice gets
killed.  It seems kind of wrong to just use the note offset from the
latest note ID to the voice's note ID and many voices could have been
killed since then.  I think optimally an equation like this should be
used:
- (LastVoiceId - oldestVoiceId) * 1000

The problem with this is that the oldest voice ID isn't known until all
voices are iterated over and it would be nice not to have to iterate
over the voice list twice.

I still don't like it even then though, seems too indeterministic as to
which voice ends up getting stopped.  Perhaps making the weighted values
user configurable would help improve the situation (of course it would
be nice to be able to make the ranges non-linear).  Voice killing
statistics (counters for each criteria) would be nice too.

Another item for the ever growing list of things TODO.  Ahh the feeling
of being overwhelmed..  Cheers.

        Josh


On Sun, 2005-10-09 at 12:18 +0200, Norbert Schnell wrote:
> Hi Josh,
> 
> I detected a weird behavior of the fluid synth voice stealing, within  
> the fluidsynth~ implementation.
> 
> What happened is that voices which just started will be killed by an  
> even newer ongoing voice because they are detected as less prior than  
> older ones.
> 
> I fixed it for now with a change fluid_synth_free_voice_by_kill() of   
> in fluid_synth.c I post below.
> It doesn't kill a new born voice and uses the voice id to kill the  
> oldest voice, when everything is ongoing in the same moment.
> 
> Cheers
>    Norbert
> 
> fluid_voice_t*
> fluid_synth_free_voice_by_kill(fluid_synth_t* synth)
> {
>    int i;
>    fluid_real_t best_prio = 999999.;
>    fluid_real_t this_voice_prio;
>    unsigned int lowest_id = INT_MAX;
>    fluid_voice_t* voice;
>    int best_voice_index=-1;
>    int oldest_voice_index=-1;
> 
> /*   fluid_mutex_lock(synth->busy); /\* Don't interfere with the  
> audio thread *\/ */
> /*   fluid_mutex_unlock(synth->busy); */
> 
>    for (i = 0; i < synth->polyphony; i++) {
> 
>      voice = synth->voice[i];
> 
>      if(voice->id < lowest_id) {
>        lowest_id = voice->id;
>        oldest_voice_index = i;
>      }
> 
>      /* don't kill a just started voice (if its not anyway the  
> oldest) */
>      if(voice->ticks == 0)
>        continue;
> 


Shouldn't availability be checked before the above two statements?


>      /* 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.;
> 
>      /* Is this voice on the drum channel?
>       * Then it is very important.
>       * Also, forget about the released-note condition:
>       * Typically, drum notes are triggered only very briefly, they  
> run most
>       * of the time in release phase.
>       */
>      if (voice->chan == 9){
>        this_voice_prio += 4000;
> 
>      } else if (_RELEASED(voice)){
>        /* The key for this voice has been released. Consider it much  
> less important
>         * than a voice, which is still held.
>         */
>        this_voice_prio -= 2000.;
>      }
> 
>      if (_SUSTAINED(voice)){
>        /* The sustain pedal is held down on this channel.
>         * Consider it less important than non-sustained channels.
>         * This decision is somehow subjective. But usually the  
> sustain pedal
>         * is used to play 'more-voices-than-fingers', so it shouldn't  
> hurt
>         * if we kill one voice.
>         */
>        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 is a number between roughly 0 and 100.*/
>      this_voice_prio -= (synth->noteid - fluid_voice_get_id(voice));
> 
>      /* 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) {
>      if (oldest_voice_index < 0) {
>        return NULL;
>      } else {
>        best_voice_index = oldest_voice_index;
>      }
>    }
> 
>    voice = synth->voice[best_voice_index];
>    fluid_voice_off(voice);
> 
>    return voice;
> }
> 
> 

Attachment: signature.asc
Description: This is a digitally signed message part


reply via email to

[Prev in Thread] Current Thread [Next in Thread]