mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2025-01-19 07:50:49 +00:00
Add public API to pin and unpin presets to the sample cache (#698)
Following the discussion about an API to pin and unpin preset samples in the sample cache here: https://lists.nongnu.org/archive/html/fluid-dev/2020-10/msg00016.html Short explanation of the change: Only the default loader currently supports dynamic sample loading, so I thought it might be a good idea to keep the changes for this feature mostly contained in the default loader as well. I've added two new preset notify flags (FLUID_PRESET_PIN and FLUID_PRESET_UNPIN) that are handled by the preset->notify callback and trigger the loading and possibly unloading of the samples.
This commit is contained in:
parent
58ccd6d53e
commit
109c41c355
11 changed files with 399 additions and 5 deletions
|
@ -80,6 +80,7 @@ What is FluidSynth?
|
|||
- The sequencer's queue no longer blocks the synthesizer thread, due to being busy arranging its events internally.
|
||||
- Events that share the same tick was given a new, documented order, see fluid_sequencer_send_at().
|
||||
- The sequencer's scale can now be used for arbitrary tempo changes. Previously, the scale of the sequencer was limited to 1000. The only limitation now is >0.
|
||||
- The dynamic-sample-loader has learned support to pin samples, see fluid_synth_pin_preset() and fluid_synth_unpin_preset()
|
||||
|
||||
\section NewIn2_1_4 What's new in 2.1.4?
|
||||
|
||||
|
|
|
@ -68,7 +68,9 @@ enum
|
|||
{
|
||||
FLUID_PRESET_SELECTED, /**< Preset selected notify */
|
||||
FLUID_PRESET_UNSELECTED, /**< Preset unselected notify */
|
||||
FLUID_SAMPLE_DONE /**< Sample no longer needed notify */
|
||||
FLUID_SAMPLE_DONE, /**< Sample no longer needed notify */
|
||||
FLUID_PRESET_PIN, /**< Request to pin preset samples to cache */
|
||||
FLUID_PRESET_UNPIN /**< Request to unpin preset samples from cache */
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -84,6 +84,15 @@ FLUIDSYNTH_API int fluid_synth_system_reset(fluid_synth_t *synth);
|
|||
FLUIDSYNTH_API int fluid_synth_all_notes_off(fluid_synth_t *synth, int chan);
|
||||
FLUIDSYNTH_API int fluid_synth_all_sounds_off(fluid_synth_t *synth, int chan);
|
||||
|
||||
|
||||
/* Dynamic sample loading */
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_synth_pin_preset(fluid_synth_t *synth, int sfont_id, int bank_num, int preset_num);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_synth_unpin_preset(fluid_synth_t *synth, int sfont_id, int bank_num, int preset_num);
|
||||
|
||||
/**
|
||||
* The midi channel type used by fluid_synth_set_channel_type()
|
||||
*/
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#define EMU_ATTENUATION_FACTOR (0.4f)
|
||||
|
||||
/* Dynamic sample loading functions */
|
||||
static int pin_preset_samples(fluid_defsfont_t *defsfont, fluid_preset_t *preset);
|
||||
static int unpin_preset_samples(fluid_defsfont_t *defsfont, fluid_preset_t *preset);
|
||||
static int load_preset_samples(fluid_defsfont_t *defsfont, fluid_preset_t *preset);
|
||||
static int unload_preset_samples(fluid_defsfont_t *defsfont, fluid_preset_t *preset);
|
||||
static void unload_sample(fluid_sample_t *sample);
|
||||
|
@ -228,6 +230,17 @@ int delete_fluid_defsfont(fluid_defsfont_t *defsfont)
|
|||
|
||||
fluid_return_val_if_fail(defsfont != NULL, FLUID_OK);
|
||||
|
||||
/* If we use dynamic sample loading, make sure we unpin any
|
||||
* pinned presets before removing this soundfont */
|
||||
if(defsfont->dynamic_samples)
|
||||
{
|
||||
for(list = defsfont->preset; list; list = fluid_list_next(list))
|
||||
{
|
||||
preset = (fluid_preset_t *)fluid_list_get(list);
|
||||
unpin_preset_samples(defsfont, preset);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that no samples are currently used */
|
||||
for(list = defsfont->sample; list; list = fluid_list_next(list))
|
||||
{
|
||||
|
@ -637,6 +650,7 @@ new_fluid_defpreset(void)
|
|||
defpreset->num = 0;
|
||||
defpreset->global_zone = NULL;
|
||||
defpreset->zone = NULL;
|
||||
defpreset->pinned = FALSE;
|
||||
return defpreset;
|
||||
}
|
||||
|
||||
|
@ -2003,15 +2017,74 @@ static int dynamic_samples_preset_notify(fluid_preset_t *preset, int reason, int
|
|||
{
|
||||
FLUID_LOG(FLUID_DBG, "Selected preset '%s' on channel %d", fluid_preset_get_name(preset), chan);
|
||||
defsfont = fluid_sfont_get_data(preset->sfont);
|
||||
load_preset_samples(defsfont, preset);
|
||||
return load_preset_samples(defsfont, preset);
|
||||
}
|
||||
else if(reason == FLUID_PRESET_UNSELECTED)
|
||||
|
||||
if(reason == FLUID_PRESET_UNSELECTED)
|
||||
{
|
||||
FLUID_LOG(FLUID_DBG, "Deselected preset '%s' from channel %d", fluid_preset_get_name(preset), chan);
|
||||
defsfont = fluid_sfont_get_data(preset->sfont);
|
||||
unload_preset_samples(defsfont, preset);
|
||||
return unload_preset_samples(defsfont, preset);
|
||||
}
|
||||
|
||||
if(reason == FLUID_PRESET_PIN)
|
||||
{
|
||||
defsfont = fluid_sfont_get_data(preset->sfont);
|
||||
return pin_preset_samples(defsfont, preset);
|
||||
}
|
||||
|
||||
if(reason == FLUID_PRESET_UNPIN)
|
||||
{
|
||||
defsfont = fluid_sfont_get_data(preset->sfont);
|
||||
return unpin_preset_samples(defsfont, preset);
|
||||
}
|
||||
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
|
||||
static int pin_preset_samples(fluid_defsfont_t *defsfont, fluid_preset_t *preset)
|
||||
{
|
||||
fluid_defpreset_t *defpreset;
|
||||
|
||||
defpreset = fluid_preset_get_data(preset);
|
||||
if (defpreset->pinned)
|
||||
{
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
FLUID_LOG(FLUID_DBG, "Pinning preset '%s'", fluid_preset_get_name(preset));
|
||||
|
||||
if(load_preset_samples(defsfont, preset) == FLUID_FAILED)
|
||||
{
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
defpreset->pinned = TRUE;
|
||||
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
|
||||
static int unpin_preset_samples(fluid_defsfont_t *defsfont, fluid_preset_t *preset)
|
||||
{
|
||||
fluid_defpreset_t *defpreset;
|
||||
|
||||
defpreset = fluid_preset_get_data(preset);
|
||||
if (!defpreset->pinned)
|
||||
{
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
FLUID_LOG(FLUID_DBG, "Unpinning preset '%s'", fluid_preset_get_name(preset));
|
||||
|
||||
if(unload_preset_samples(defsfont, preset) == FLUID_FAILED)
|
||||
{
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
defpreset->pinned = FALSE;
|
||||
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -148,6 +148,7 @@ struct _fluid_defpreset_t
|
|||
unsigned int num; /* the preset number */
|
||||
fluid_preset_zone_t *global_zone; /* the global zone of the preset */
|
||||
fluid_preset_zone_t *zone; /* the chained list of preset zones */
|
||||
int pinned; /* preset samples pinned to sample cache? */
|
||||
};
|
||||
|
||||
fluid_defpreset_t *new_fluid_defpreset(void);
|
||||
|
|
|
@ -290,3 +290,22 @@ static int fluid_get_file_modification_time(char *filename, time_t *modification
|
|||
*modification_time = buf.st_mtime;
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Only used for tests */
|
||||
int fluid_samplecache_count_entries(void)
|
||||
{
|
||||
fluid_list_t *entry;
|
||||
int count = 0;
|
||||
|
||||
fluid_mutex_lock(samplecache_mutex);
|
||||
|
||||
for(entry = samplecache_list; entry != NULL; entry = fluid_list_next(entry))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
fluid_mutex_unlock(samplecache_mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -31,4 +31,7 @@ int fluid_samplecache_load(SFData *sf,
|
|||
|
||||
int fluid_samplecache_unload(const short *sample_data);
|
||||
|
||||
/* Only used for tests */
|
||||
int fluid_samplecache_count_entries(void);
|
||||
|
||||
#endif /* _FLUID_SAMPLECACHE_H */
|
||||
|
|
|
@ -45,7 +45,7 @@ int fluid_sample_sanitize_loop(fluid_sample_t *sample, unsigned int max_end);
|
|||
(*(_preset)->noteon)(_preset,_synth,_ch,_key,_vel)
|
||||
|
||||
#define fluid_preset_notify(_preset,_reason,_chan) \
|
||||
{ if ((_preset) && (_preset)->notify) { (*(_preset)->notify)(_preset,_reason,_chan); }}
|
||||
( ((_preset) && (_preset)->notify) ? (*(_preset)->notify)(_preset,_reason,_chan) : FLUID_OK )
|
||||
|
||||
|
||||
#define fluid_sample_incr_ref(_sample) { (_sample)->refcount++; }
|
||||
|
|
|
@ -3018,6 +3018,97 @@ fluid_synth_program_select(fluid_synth_t *synth, int chan, int sfont_id,
|
|||
FLUID_API_RETURN(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pins all samples of the given preset.
|
||||
*
|
||||
* This function will attempt to pin all samples of the given preset and
|
||||
* load them into memory, if they are currently unloaded. "To pin" in this
|
||||
* context means preventing them from being unloaded by an upcoming channel
|
||||
* prog change.
|
||||
*
|
||||
* @note This function is only useful if <code>synth.dynamic-sample-loading</code> is enabled.
|
||||
* By default, dynamic-sample-loading is disabled and all samples are kept in memory.
|
||||
* Furthermore, this is only useful for presets which support dynamic-sample-loading (currently,
|
||||
* only preset loaded with the default soundfont loader do).
|
||||
* @param synth FluidSynth instance
|
||||
* @param sfont_id ID of a loaded SoundFont
|
||||
* @param bank_num MIDI bank number
|
||||
* @param preset_num MIDI program number
|
||||
* @return #FLUID_OK if the preset was found, pinned and loaded
|
||||
* into memory successfully. #FLUID_FAILED otherwise. Note that #FLUID_OK
|
||||
* is returned, even if <code>synth.dynamic-sample-loading</code> is disabled or
|
||||
* the preset doesn't support dynamic-sample-loading.
|
||||
* @since 2.2.0
|
||||
*/
|
||||
int
|
||||
fluid_synth_pin_preset(fluid_synth_t *synth, int sfont_id, int bank_num, int preset_num)
|
||||
{
|
||||
int ret;
|
||||
fluid_preset_t *preset;
|
||||
|
||||
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
|
||||
fluid_return_val_if_fail(bank_num >= 0, FLUID_FAILED);
|
||||
fluid_return_val_if_fail(preset_num >= 0, FLUID_FAILED);
|
||||
|
||||
fluid_synth_api_enter(synth);
|
||||
|
||||
preset = fluid_synth_get_preset(synth, sfont_id, bank_num, preset_num);
|
||||
|
||||
if(preset == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR,
|
||||
"There is no preset with bank number %d and preset number %d in SoundFont %d",
|
||||
bank_num, preset_num, sfont_id);
|
||||
FLUID_API_RETURN(FLUID_FAILED);
|
||||
}
|
||||
|
||||
ret = fluid_preset_notify(preset, FLUID_PRESET_PIN, -1); // channel unused for pinning messages
|
||||
|
||||
FLUID_API_RETURN(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpin all samples of the given preset.
|
||||
*
|
||||
* This function undoes the effect of fluid_synth_pin_preset(). If the preset is
|
||||
* not currently used, its samples will be unloaded.
|
||||
*
|
||||
* @note Only useful for presets loaded with the default soundfont loader and
|
||||
* only if <code>synth.dynamic-sample-loading</code> is enabled.
|
||||
* @param synth FluidSynth instance
|
||||
* @param sfont_id ID of a loaded SoundFont
|
||||
* @param bank_num MIDI bank number
|
||||
* @param preset_num MIDI program number
|
||||
* @return #FLUID_OK if preset was found, #FLUID_FAILED otherwise
|
||||
* @since 2.2.0
|
||||
*/
|
||||
int
|
||||
fluid_synth_unpin_preset(fluid_synth_t *synth, int sfont_id, int bank_num, int preset_num)
|
||||
{
|
||||
int ret;
|
||||
fluid_preset_t *preset;
|
||||
|
||||
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
|
||||
fluid_return_val_if_fail(bank_num >= 0, FLUID_FAILED);
|
||||
fluid_return_val_if_fail(preset_num >= 0, FLUID_FAILED);
|
||||
|
||||
fluid_synth_api_enter(synth);
|
||||
|
||||
preset = fluid_synth_get_preset(synth, sfont_id, bank_num, preset_num);
|
||||
|
||||
if(preset == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR,
|
||||
"There is no preset with bank number %d and preset number %d in SoundFont %d",
|
||||
bank_num, preset_num, sfont_id);
|
||||
FLUID_API_RETURN(FLUID_FAILED);
|
||||
}
|
||||
|
||||
ret = fluid_preset_notify(preset, FLUID_PRESET_UNPIN, -1); // channel unused for pinning messages
|
||||
|
||||
FLUID_API_RETURN(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select an instrument on a MIDI channel by SoundFont name, bank and program numbers.
|
||||
* @param synth FluidSynth instance
|
||||
|
|
|
@ -11,6 +11,7 @@ ADD_FLUID_TEST(test_sample_cache)
|
|||
ADD_FLUID_TEST(test_sfont_loading)
|
||||
ADD_FLUID_TEST(test_sample_rate_change)
|
||||
ADD_FLUID_TEST(test_preset_sample_loading)
|
||||
ADD_FLUID_TEST(test_preset_pinning)
|
||||
ADD_FLUID_TEST(test_bug_635)
|
||||
ADD_FLUID_TEST(test_pointer_alignment)
|
||||
ADD_FLUID_TEST(test_seqbind_unregister)
|
||||
|
|
194
test/test_preset_pinning.c
Normal file
194
test/test_preset_pinning.c
Normal file
|
@ -0,0 +1,194 @@
|
|||
#include "test.h"
|
||||
#include "fluidsynth.h"
|
||||
#include "sfloader/fluid_sfont.h"
|
||||
#include "sfloader/fluid_defsfont.h"
|
||||
#include "sfloader/fluid_samplecache.h"
|
||||
#include "utils/fluid_sys.h"
|
||||
#include "utils/fluid_list.h"
|
||||
|
||||
static int count_loaded_samples(fluid_synth_t *synth, int sfont_id);
|
||||
|
||||
|
||||
/* Test the preset pinning and unpinning feature */
|
||||
int main(void)
|
||||
{
|
||||
int id;
|
||||
fluid_synth_t *synth;
|
||||
fluid_sfont_t *sfont;
|
||||
fluid_defsfont_t *defsfont;
|
||||
|
||||
/* Setup */
|
||||
fluid_settings_t *settings = new_fluid_settings();
|
||||
|
||||
|
||||
/* Test that pinning and unpinning has no effect and throws no errors
|
||||
* when dynamic-sample-loading is disabled */
|
||||
fluid_settings_setint(settings, "synth.dynamic-sample-loading", 0);
|
||||
synth = new_fluid_synth(settings);
|
||||
id = fluid_synth_sfload(synth, TEST_SOUNDFONT, 0);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 123);
|
||||
TEST_ASSERT(fluid_samplecache_count_entries() == 1);
|
||||
|
||||
/* Attempt to pin and unpin an exising preset should succeed (but have no effect) */
|
||||
TEST_ASSERT(fluid_synth_pin_preset(synth, id, 0, 42) == FLUID_OK);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 123);
|
||||
|
||||
TEST_ASSERT(fluid_synth_unpin_preset(synth, id, 0, 42) == FLUID_OK);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 123);
|
||||
|
||||
/* Attempt to pin and unpin a non-existant preset should fail */
|
||||
TEST_ASSERT(fluid_synth_pin_preset(synth, id, 42, 42) == FLUID_FAILED);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 123);
|
||||
|
||||
TEST_ASSERT(fluid_synth_unpin_preset(synth, id, 42, 42) == FLUID_FAILED);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 123);
|
||||
|
||||
delete_fluid_synth(synth);
|
||||
|
||||
|
||||
/* Test pinning and unpinning with dyamic-sample loading enabled */
|
||||
fluid_settings_setint(settings, "synth.dynamic-sample-loading", 1);
|
||||
synth = new_fluid_synth(settings);
|
||||
id = fluid_synth_sfload(synth, TEST_SOUNDFONT, 0);
|
||||
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 0);
|
||||
TEST_ASSERT(fluid_samplecache_count_entries() == 0);
|
||||
|
||||
|
||||
/* For the following tests, preset 42 (Lead Synth 2) consists of 4 samples,
|
||||
* preset 40 (Aluminum Plate) consists of 1 sample */
|
||||
|
||||
/* Simple pin and unpin */
|
||||
TEST_ASSERT(fluid_synth_pin_preset(synth, id, 0, 42) == FLUID_OK);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 4);
|
||||
TEST_ASSERT(fluid_samplecache_count_entries() == 4);
|
||||
|
||||
TEST_ASSERT(fluid_synth_unpin_preset(synth, id, 0, 42) == FLUID_OK);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 0);
|
||||
TEST_ASSERT(fluid_samplecache_count_entries() == 0);
|
||||
|
||||
|
||||
/* Pinning and unpinning twice should have exactly the same effect */
|
||||
TEST_ASSERT(fluid_synth_pin_preset(synth, id, 0, 42) == FLUID_OK);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 4);
|
||||
TEST_ASSERT(fluid_samplecache_count_entries() == 4);
|
||||
|
||||
TEST_ASSERT(fluid_synth_pin_preset(synth, id, 0, 42) == FLUID_OK);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 4);
|
||||
TEST_ASSERT(fluid_samplecache_count_entries() == 4);
|
||||
|
||||
TEST_ASSERT(fluid_synth_unpin_preset(synth, id, 0, 42) == FLUID_OK);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 0);
|
||||
TEST_ASSERT(fluid_samplecache_count_entries() == 0);
|
||||
|
||||
TEST_ASSERT(fluid_synth_unpin_preset(synth, id, 0, 42) == FLUID_OK);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 0);
|
||||
TEST_ASSERT(fluid_samplecache_count_entries() == 0);
|
||||
|
||||
|
||||
/* Pin a single preset, select both presets, unselect both, ensure the pinned
|
||||
* is still in memory and gone after unpinning */
|
||||
TEST_ASSERT(fluid_synth_pin_preset(synth, id, 0, 42) == FLUID_OK);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 4);
|
||||
TEST_ASSERT(fluid_samplecache_count_entries() == 4);
|
||||
|
||||
TEST_ASSERT(fluid_synth_program_select(synth, 0, id, 0, 42) == FLUID_OK);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 4);
|
||||
TEST_ASSERT(fluid_samplecache_count_entries() == 4);
|
||||
|
||||
TEST_ASSERT(fluid_synth_program_select(synth, 1, id, 0, 40) == FLUID_OK);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 5);
|
||||
TEST_ASSERT(fluid_samplecache_count_entries() == 5);
|
||||
|
||||
TEST_ASSERT(fluid_synth_unset_program(synth, 0) == FLUID_OK);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 5);
|
||||
TEST_ASSERT(fluid_samplecache_count_entries() == 5);
|
||||
|
||||
TEST_ASSERT(fluid_synth_unset_program(synth, 1) == FLUID_OK);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 4);
|
||||
TEST_ASSERT(fluid_samplecache_count_entries() == 4);
|
||||
|
||||
TEST_ASSERT(fluid_synth_unpin_preset(synth, id, 0, 42) == FLUID_OK);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 0);
|
||||
TEST_ASSERT(fluid_samplecache_count_entries() == 0);
|
||||
|
||||
|
||||
/* Unpinning an unpinned and selected preset should not remove it from memory */
|
||||
TEST_ASSERT(fluid_synth_program_select(synth, 0, id, 0, 42) == FLUID_OK);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 4);
|
||||
TEST_ASSERT(fluid_samplecache_count_entries() == 4);
|
||||
|
||||
TEST_ASSERT(fluid_synth_unpin_preset(synth, id, 0, 42) == FLUID_OK);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 4);
|
||||
TEST_ASSERT(fluid_samplecache_count_entries() == 4);
|
||||
|
||||
TEST_ASSERT(fluid_synth_unset_program(synth, 0) == FLUID_OK);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 0);
|
||||
TEST_ASSERT(fluid_samplecache_count_entries() == 0);
|
||||
|
||||
|
||||
/* Test unload of soundfont with pinned sample automatically unpins
|
||||
* the sample and removes all samples from cache */
|
||||
TEST_ASSERT(fluid_synth_pin_preset(synth, id, 0, 42) == FLUID_OK);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 4);
|
||||
TEST_ASSERT(fluid_samplecache_count_entries() == 4);
|
||||
|
||||
TEST_ASSERT(fluid_synth_sfunload(synth, id, 0) == FLUID_OK);
|
||||
TEST_ASSERT(fluid_samplecache_count_entries() == 0);
|
||||
|
||||
|
||||
/* Ensure that failures during load of preset results in an
|
||||
* error returned by pinning function */
|
||||
id = fluid_synth_sfload(synth, TEST_SOUNDFONT, 0);
|
||||
// hack the soundfont filename so the next load won't find the file anymore
|
||||
sfont = fluid_synth_get_sfont_by_id(synth, id);
|
||||
defsfont = fluid_sfont_get_data(sfont);
|
||||
defsfont->filename[0]++;
|
||||
|
||||
TEST_ASSERT(fluid_synth_pin_preset(synth, id, 0, 42) == FLUID_FAILED);
|
||||
|
||||
defsfont->filename[0]--;
|
||||
TEST_ASSERT(fluid_synth_sfunload(synth, id, 0) == FLUID_OK);
|
||||
|
||||
|
||||
/* Test that deleting the synth with a pinned preset also leaves no
|
||||
* samples in cache */
|
||||
id = fluid_synth_sfload(synth, TEST_SOUNDFONT, 0);
|
||||
|
||||
TEST_ASSERT(fluid_synth_pin_preset(synth, id, 0, 42) == FLUID_OK);
|
||||
TEST_ASSERT(count_loaded_samples(synth, id) == 4);
|
||||
TEST_ASSERT(fluid_samplecache_count_entries() == 4);
|
||||
|
||||
delete_fluid_synth(synth);
|
||||
|
||||
TEST_ASSERT(fluid_samplecache_count_entries() == 0);
|
||||
|
||||
|
||||
/* Tear down */
|
||||
delete_fluid_settings(settings);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int count_loaded_samples(fluid_synth_t *synth, int sfont_id)
|
||||
{
|
||||
fluid_list_t *list;
|
||||
int count = 0;
|
||||
|
||||
fluid_sfont_t *sfont = fluid_synth_get_sfont_by_id(synth, sfont_id);
|
||||
fluid_defsfont_t *defsfont = fluid_sfont_get_data(sfont);
|
||||
|
||||
for(list = defsfont->sample; list; list = fluid_list_next(list))
|
||||
{
|
||||
fluid_sample_t *sample = fluid_list_get(list);
|
||||
|
||||
if(sample->data != NULL)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
FLUID_LOG(FLUID_INFO, "Loaded samples on sfont %d: %d\n", sfont_id, count);
|
||||
return count;
|
||||
}
|
Loading…
Reference in a new issue