Skip to content

Commit

Permalink
Temporarily apply FluidSynth upstream patches
Browse files Browse the repository at this point in the history
Apply fixes for FluidSynth/fluidsynth#727 via
patch until a new version is released.

This should clear up some memory leaks related to SoundFont unloading.
  • Loading branch information
dwhinham committed Jan 2, 2021
1 parent bc13fad commit f060199
Show file tree
Hide file tree
Showing 3 changed files with 207 additions and 2 deletions.
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ $(MT32EMUBUILDDIR)/.done: $(CIRCLESTDLIBHOME)/.done
fluidsynth: $(FLUIDSYNTHBUILDDIR)/.done

$(FLUIDSYNTHBUILDDIR)/.done: $(CIRCLESTDLIBHOME)/.done
@patch -N -p1 -r - -d $(FLUIDSYNTHHOME) < patches/fluidsynth-2.1.5-circle.patch
@patch -N -p1 --no-backup-if-mismatch -r - -d $(FLUIDSYNTHHOME) < patches/fluidsynth-2.1.5-circle.patch
@patch -N -p1 --no-backup-if-mismatch -r - -d $(FLUIDSYNTHHOME) < patches/fluidsynth-2.1.5-fix-727-1.patch
@patch -N -p1 --no-backup-if-mismatch -r - -d $(FLUIDSYNTHHOME) < patches/fluidsynth-2.1.5-fix-727-2.patch

@export CFLAGS="$(CFLAGS_FOR_TARGET)"
@cmake -B $(FLUIDSYNTHBUILDDIR) \
Expand Down Expand Up @@ -119,7 +121,9 @@ veryclean: clean
@patch -R -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.2-sd-sysconfig.patch
@patch -R -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.2-sd-high-speed.patch
@patch -R -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.2-i2s-slave.patch
@patch -R -N -p1 -r - -d $(FLUIDSYNTHHOME) < patches/fluidsynth-2.1.5-circle.patch
@patch -R -N -p1 --no-backup-if-mismatch -r - -d $(FLUIDSYNTHHOME) < patches/fluidsynth-2.1.5-fix-727-2.patch
@patch -R -N -p1 --no-backup-if-mismatch -r - -d $(FLUIDSYNTHHOME) < patches/fluidsynth-2.1.5-fix-727-1.patch
@patch -R -N -p1 --no-backup-if-mismatch -r - -d $(FLUIDSYNTHHOME) < patches/fluidsynth-2.1.5-circle.patch

# Clean circle-stdlib
@$(MAKE) -C $(CIRCLESTDLIBHOME) mrproper
Expand Down
133 changes: 133 additions & 0 deletions patches/fluidsynth-2.1.5-fix-727-1.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
From a4ac56502fec5f0c20a60187d965c94ba1dc81c2 Mon Sep 17 00:00:00 2001
From: jjceresa <[email protected]>
Date: Wed, 30 Dec 2020 07:24:40 +0100
Subject: [PATCH] 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.
---
src/synth/fluid_synth.c | 21 ++++++++++++++++++++-
src/synth/fluid_voice.c | 27 +++++++++++++++++++--------
2 files changed, 39 insertions(+), 9 deletions(-)

diff --git a/src/synth/fluid_synth.c b/src/synth/fluid_synth.c
index 6c10094c7..389aff5ff 100644
--- a/src/synth/fluid_synth.c
+++ b/src/synth/fluid_synth.c
@@ -1005,7 +1005,6 @@ delete_fluid_synth(fluid_synth_t *synth)
fluid_return_if_fail(synth != NULL);

fluid_profiling_print();
-
/* turn off all voices, needed to unload SoundFont data */
if(synth->voice != NULL)
{
@@ -1018,6 +1017,12 @@ delete_fluid_synth(fluid_synth_t *synth)
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_overflow_rvoice_finished(voice);

@@ -4228,7 +4233,21 @@ fluid_synth_check_finished_voices(fluid_synth_t *synth)
}
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]);
+
+ /* 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;
}
}
diff --git a/src/synth/fluid_voice.c b/src/synth/fluid_voice.c
index 90f945582..cc5d3d79d 100644
--- a/src/synth/fluid_voice.c
+++ b/src/synth/fluid_voice.c
@@ -321,12 +321,13 @@ fluid_voice_init(fluid_voice_t *voice, fluid_sample_t *sample,
voice->has_noteoff = 0;
UPDATE_RVOICE0(fluid_rvoice_reset);

- /* Increment the reference count of the sample to prevent the
- unloading of the soundfont while this voice is playing,
- once for us and once for the rvoice. */
+ /*
+ We increment the reference count of the sample to indicate that this
+ 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_rvoice_eventhandler_push_ptr(voice->eventhandler, fluid_rvoice_set_sample, voice->rvoice, sample);
- fluid_sample_incr_ref(sample);
voice->sample = sample;

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)
{
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);
}

@@ -1439,17 +1448,19 @@ fluid_voice_stop(fluid_voice_t *voice)

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)
{
fluid_voice_sample_unref(&voice->rvoice->dsp.sample);
}

+ voice->sample = NULL;
+
voice->status = FLUID_VOICE_OFF;
voice->has_noteoff = 1;

- /* Decrement the reference count of the sample. */
- fluid_voice_sample_unref(&voice->sample);
-
/* Decrement voice count */
voice->channel->synth->active_voice_count--;
}
68 changes: 68 additions & 0 deletions patches/fluidsynth-2.1.5-fix-727-2.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
From 56ddeea098d51dc67994c29430b43fd506ec706d Mon Sep 17 00:00:00 2001
From: jjceresa <[email protected]>
Date: Thu, 31 Dec 2020 14:29:32 +0100
Subject: [PATCH] delete_fluid_synth() may not unload soundfonts still used by
rvoices

---
src/synth/fluid_voice.c | 11 ++++-------
src/synth/fluid_voice.h | 3 ++-
2 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/src/synth/fluid_voice.c b/src/synth/fluid_voice.c
index cc5d3d79d..503f0f67a 100644
--- a/src/synth/fluid_voice.c
+++ b/src/synth/fluid_voice.c
@@ -174,6 +174,7 @@ static void fluid_voice_swap_rvoice(fluid_voice_t *voice)
voice->can_access_rvoice = voice->can_access_overflow_rvoice;
voice->overflow_rvoice = rtemp;
voice->can_access_overflow_rvoice = ctemp;
+ voice->overflow_sample = voice->sample;
}

static void fluid_voice_initialize_rvoice(fluid_voice_t *voice, fluid_real_t output_rate)
@@ -242,6 +243,7 @@ new_fluid_voice(fluid_rvoice_eventhandler_t *handler, fluid_real_t output_rate)
voice->eventhandler = handler;
voice->channel = NULL;
voice->sample = NULL;
+ voice->overflow_sample = NULL;
voice->output_rate = output_rate;

/* Initialize both the rvoice and overflow_rvoice */
@@ -1420,7 +1422,7 @@ void fluid_voice_overflow_rvoice_finished(fluid_voice_t *voice)

/* 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_sample);
}

/*
@@ -1451,12 +1453,7 @@ fluid_voice_stop(fluid_voice_t *voice)
/* Decrement the reference count of the sample, to indicate
that this sample isn't owned by the rvoice anymore.
*/
- if(voice->can_access_rvoice)
- {
- fluid_voice_sample_unref(&voice->rvoice->dsp.sample);
- }
-
- voice->sample = NULL;
+ fluid_voice_sample_unref(&voice->sample);

voice->status = FLUID_VOICE_OFF;
voice->has_noteoff = 1;
diff --git a/src/synth/fluid_voice.h b/src/synth/fluid_voice.h
index 599a0e28a..4ce6c2b7a 100644
--- a/src/synth/fluid_voice.h
+++ b/src/synth/fluid_voice.h
@@ -71,7 +71,8 @@ struct _fluid_voice_t
fluid_channel_t *channel;
fluid_rvoice_eventhandler_t *eventhandler;
fluid_zone_range_t *zone_range; /* instrument zone range*/
- fluid_sample_t *sample; /* Pointer to sample (dupe in rvoice) */
+ fluid_sample_t *sample; /* Pointer to sample (dupe in rvoice) */
+ fluid_sample_t *overflow_sample; /* Pointer to sample (dupe in overflow_rvoice) */

unsigned int start_time;
int mod_count;

0 comments on commit f060199

Please sign in to comment.