mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2024-11-10 06:51:54 +00:00
SoundFonts cannot be unloaded if polyphony is ever exceeded
If polyphony is exceeded and FluidSynth has to allocate a voice by calling fluid_synth_free_voice_by_kill_LOCAL(), two problems occur: 1)The value returned by fluid_synth_get_active_voice_count() never returns back to 0. 2)SoundFont samples are not unref'd properly, and therefore if an attempt is made to unload the SoundFont, the deferred unload timer is started, and fluid_synth_sfunload_callback() unsuccessfully tries to unload the SoundFont forever. These 2 issues are fixed by this commit.
This commit is contained in:
parent
5c1cfe6a5f
commit
0d38823527
2 changed files with 39 additions and 8 deletions
|
@ -1067,6 +1067,12 @@ delete_fluid_synth(fluid_synth_t *synth)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* WARNING: A this point we must ensure that the reference counter
|
||||||
|
of any soundfont sample owned by any rvoice belonging to the voice
|
||||||
|
are correctly decremented. This is the contrary part to
|
||||||
|
to fluid_voice_init() where the sample's reference counter is
|
||||||
|
incremented.
|
||||||
|
*/
|
||||||
fluid_voice_unlock_rvoice(voice);
|
fluid_voice_unlock_rvoice(voice);
|
||||||
fluid_voice_overflow_rvoice_finished(voice);
|
fluid_voice_overflow_rvoice_finished(voice);
|
||||||
|
|
||||||
|
@ -4289,7 +4295,21 @@ fluid_synth_check_finished_voices(fluid_synth_t *synth)
|
||||||
}
|
}
|
||||||
else if(synth->voice[j]->overflow_rvoice == fv)
|
else if(synth->voice[j]->overflow_rvoice == fv)
|
||||||
{
|
{
|
||||||
|
/* Unlock the overflow_rvoice of the voice.
|
||||||
|
Decrement the reference count of the sample owned by this
|
||||||
|
rvoice.
|
||||||
|
*/
|
||||||
fluid_voice_overflow_rvoice_finished(synth->voice[j]);
|
fluid_voice_overflow_rvoice_finished(synth->voice[j]);
|
||||||
|
|
||||||
|
/* Decrement synth active voice count. Must not be incorporated
|
||||||
|
in fluid_voice_overflow_rvoice_finished() because
|
||||||
|
fluid_voice_overflow_rvoice_finished() is called also
|
||||||
|
at synth destruction and in this case the variable should be
|
||||||
|
accessed via voice->channel->synth->active_voice_count.
|
||||||
|
And for certain voices which are not playing, the field
|
||||||
|
voice->channel is NULL.
|
||||||
|
*/
|
||||||
|
synth->active_voice_count--;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -321,12 +321,13 @@ fluid_voice_init(fluid_voice_t *voice, fluid_sample_t *sample,
|
||||||
voice->has_noteoff = 0;
|
voice->has_noteoff = 0;
|
||||||
UPDATE_RVOICE0(fluid_rvoice_reset);
|
UPDATE_RVOICE0(fluid_rvoice_reset);
|
||||||
|
|
||||||
/* Increment the reference count of the sample to prevent the
|
/*
|
||||||
unloading of the soundfont while this voice is playing,
|
We increment the reference count of the sample to indicate that this
|
||||||
once for us and once for the rvoice. */
|
sample is about to be owned by the rvoice. This will prevent the
|
||||||
|
unloading of the soundfont while this rvoice is playing.
|
||||||
|
*/
|
||||||
fluid_sample_incr_ref(sample);
|
fluid_sample_incr_ref(sample);
|
||||||
fluid_rvoice_eventhandler_push_ptr(voice->eventhandler, fluid_rvoice_set_sample, voice->rvoice, sample);
|
fluid_rvoice_eventhandler_push_ptr(voice->eventhandler, fluid_rvoice_set_sample, voice->rvoice, sample);
|
||||||
fluid_sample_incr_ref(sample);
|
|
||||||
voice->sample = sample;
|
voice->sample = sample;
|
||||||
|
|
||||||
i = fluid_channel_get_interp_method(channel);
|
i = fluid_channel_get_interp_method(channel);
|
||||||
|
@ -1406,11 +1407,19 @@ fluid_voice_kill_excl(fluid_voice_t *voice)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called by fluid_synth when the overflow rvoice can be reclaimed.
|
* Unlock the overflow rvoice of the voice.
|
||||||
|
* Decrement the reference count of the sample owned by this rvoice.
|
||||||
|
*
|
||||||
|
* Called by fluid_synth when the overflow rvoice has finished by itself.
|
||||||
|
* Must be called also explicitly at synth destruction to ensure that
|
||||||
|
* the soundfont be unloaded successfully.
|
||||||
*/
|
*/
|
||||||
void fluid_voice_overflow_rvoice_finished(fluid_voice_t *voice)
|
void fluid_voice_overflow_rvoice_finished(fluid_voice_t *voice)
|
||||||
{
|
{
|
||||||
voice->can_access_overflow_rvoice = 1;
|
voice->can_access_overflow_rvoice = 1;
|
||||||
|
|
||||||
|
/* Decrement the reference count of the sample to indicate
|
||||||
|
that this sample isn't owned by the rvoice anymore */
|
||||||
fluid_voice_sample_unref(&voice->overflow_rvoice->dsp.sample);
|
fluid_voice_sample_unref(&voice->overflow_rvoice->dsp.sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1439,17 +1448,19 @@ fluid_voice_stop(fluid_voice_t *voice)
|
||||||
|
|
||||||
voice->chan = NO_CHANNEL;
|
voice->chan = NO_CHANNEL;
|
||||||
|
|
||||||
|
/* Decrement the reference count of the sample, to indicate
|
||||||
|
that this sample isn't owned by the rvoice anymore.
|
||||||
|
*/
|
||||||
if(voice->can_access_rvoice)
|
if(voice->can_access_rvoice)
|
||||||
{
|
{
|
||||||
fluid_voice_sample_unref(&voice->rvoice->dsp.sample);
|
fluid_voice_sample_unref(&voice->rvoice->dsp.sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
voice->sample = NULL;
|
||||||
|
|
||||||
voice->status = FLUID_VOICE_OFF;
|
voice->status = FLUID_VOICE_OFF;
|
||||||
voice->has_noteoff = 1;
|
voice->has_noteoff = 1;
|
||||||
|
|
||||||
/* Decrement the reference count of the sample. */
|
|
||||||
fluid_voice_sample_unref(&voice->sample);
|
|
||||||
|
|
||||||
/* Decrement voice count */
|
/* Decrement voice count */
|
||||||
voice->channel->synth->active_voice_count--;
|
voice->channel->synth->active_voice_count--;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue