mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2025-04-22 23:50:53 +00:00
defsfont: Avoid memory allocation on program change
This memory allocation can be avoided by preallocating one preset per midi channel (every midi channel only has one current preset).
This commit is contained in:
parent
36e8257065
commit
822ffbb4ab
3 changed files with 56 additions and 6 deletions
|
@ -118,17 +118,23 @@ fluid_sample_t* fluid_defsfont_get_sample(fluid_defsfont_t* sfont, char *s)
|
|||
fluid_preset_t*
|
||||
fluid_defsfont_sfont_get_preset(fluid_sfont_t* sfont, unsigned int bank, unsigned int prenum)
|
||||
{
|
||||
fluid_preset_t* preset;
|
||||
fluid_preset_t* preset = NULL;
|
||||
fluid_defpreset_t* defpreset;
|
||||
fluid_defsfont_t* defsfont = sfont->data;
|
||||
|
||||
defpreset = fluid_defsfont_get_preset((fluid_defsfont_t*) sfont->data, bank, prenum);
|
||||
defpreset = fluid_defsfont_get_preset(defsfont, bank, prenum);
|
||||
|
||||
if (defpreset == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
preset = FLUID_NEW(fluid_preset_t);
|
||||
if (preset == NULL) {
|
||||
if (defsfont->preset_stack_size > 0) {
|
||||
defsfont->preset_stack_size--;
|
||||
preset = defsfont->preset_stack[defsfont->preset_stack_size];
|
||||
}
|
||||
if (!preset)
|
||||
preset = FLUID_NEW(fluid_preset_t);
|
||||
if (!preset) {
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -164,9 +170,15 @@ int fluid_defsfont_sfont_iteration_next(fluid_sfont_t* sfont, fluid_preset_t* pr
|
|||
|
||||
int fluid_defpreset_preset_delete(fluid_preset_t* preset)
|
||||
{
|
||||
FLUID_FREE(preset);
|
||||
fluid_defpreset_t* defpreset = preset ? preset->data : NULL;
|
||||
fluid_defsfont_t* sfont = defpreset ? defpreset->sfont : NULL;
|
||||
|
||||
/* TODO: free modulators */
|
||||
if (sfont && sfont->preset_stack_size < sfont->preset_stack_capacity) {
|
||||
sfont->preset_stack[sfont->preset_stack_size] = preset;
|
||||
sfont->preset_stack_size++;
|
||||
}
|
||||
else
|
||||
FLUID_FREE(preset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -429,6 +441,7 @@ static int fluid_cached_sampledata_unload(const short *sampledata)
|
|||
fluid_defsfont_t* new_fluid_defsfont(fluid_settings_t* settings)
|
||||
{
|
||||
fluid_defsfont_t* sfont;
|
||||
int i;
|
||||
|
||||
sfont = FLUID_NEW(fluid_defsfont_t);
|
||||
if (sfont == NULL) {
|
||||
|
@ -444,6 +457,29 @@ fluid_defsfont_t* new_fluid_defsfont(fluid_settings_t* settings)
|
|||
sfont->preset = NULL;
|
||||
fluid_settings_getint(settings, "synth.lock-memory", &sfont->mlock);
|
||||
|
||||
/* Initialise preset cache, so we don't have to call malloc on program changes.
|
||||
Usually, we have at most one preset per channel plus one temporarily used,
|
||||
so optimise for that case. */
|
||||
fluid_settings_getint(settings, "synth.midi-channels", &sfont->preset_stack_capacity);
|
||||
sfont->preset_stack_capacity++;
|
||||
sfont->preset_stack_size = 0;
|
||||
sfont->preset_stack = FLUID_ARRAY(fluid_preset_t*, sfont->preset_stack_capacity);
|
||||
if (!sfont->preset_stack) {
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
FLUID_FREE(sfont);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < sfont->preset_stack_capacity; i++) {
|
||||
sfont->preset_stack[i] = FLUID_NEW(fluid_preset_t);
|
||||
if (!sfont->preset_stack[i]) {
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
delete_fluid_defsfont(sfont);
|
||||
return NULL;
|
||||
}
|
||||
sfont->preset_stack_size++;
|
||||
}
|
||||
|
||||
return sfont;
|
||||
}
|
||||
|
||||
|
@ -480,6 +516,10 @@ int delete_fluid_defsfont(fluid_defsfont_t* sfont)
|
|||
fluid_cached_sampledata_unload(sfont->sampledata);
|
||||
}
|
||||
|
||||
while (sfont->preset_stack_size > 0)
|
||||
FLUID_FREE(sfont->preset_stack[--sfont->preset_stack_size]);
|
||||
FLUID_FREE(sfont->preset_stack);
|
||||
|
||||
preset = sfont->preset;
|
||||
while (preset != NULL) {
|
||||
sfont->preset = preset->next;
|
||||
|
|
|
@ -409,6 +409,10 @@ struct _fluid_defsfont_t
|
|||
|
||||
fluid_preset_t iter_preset; /* preset interface used in the iteration */
|
||||
fluid_defpreset_t* iter_cur; /* the current preset in the iteration */
|
||||
|
||||
fluid_preset_t** preset_stack; /* List of presets that are available to use */
|
||||
int preset_stack_capacity; /* Length of preset_stack array */
|
||||
int preset_stack_size; /* Current number of items in the stack */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -806,6 +806,12 @@ delete_fluid_synth(fluid_synth_t* synth)
|
|||
}
|
||||
}
|
||||
|
||||
/* also unset all presets for clean SoundFont unload */
|
||||
if (synth->channel != NULL)
|
||||
for (i = 0; i < synth->midi_channels; i++)
|
||||
if (synth->channel[i] != NULL)
|
||||
fluid_channel_set_preset(synth->channel[i], NULL);
|
||||
|
||||
if (synth->eventhandler)
|
||||
delete_fluid_rvoice_eventhandler(synth->eventhandler);
|
||||
|
||||
|
|
Loading…
Reference in a new issue