Add synth.lock-memory option (possibility to avoid mlock)

Closes ticket #111. Sometimes, e g in a fast-render scenario
or other scenarios where low latency is not important, you can
turn off mlock to reduce memory pressure (and thus allow the soundfont
to swap to disk).
This commit is contained in:
David Henningsson 2012-12-08 06:25:21 +00:00
parent 5f3568deee
commit 5b2e24a762
4 changed files with 54 additions and 39 deletions

View file

@ -599,7 +599,8 @@ int main(int argc, char** argv)
midi_in = 0; midi_in = 0;
interactive = 0; interactive = 0;
with_server = 0; with_server = 0;
fluid_settings_setstr(settings, "player.timing-source", "sample"); fluid_settings_setstr(settings, "player.timing-source", "sample");
fluid_settings_setint(settings, "synth.lock-memory", 0);
fluid_settings_setint(settings, "synth.parallel-render", 1); /* TODO: Fast_render should not need this, but currently do */ fluid_settings_setint(settings, "synth.parallel-render", 1); /* TODO: Fast_render should not need this, but currently do */
} }

View file

@ -31,7 +31,7 @@
* SFONT LOADER * SFONT LOADER
*/ */
fluid_sfloader_t* new_fluid_defsfloader() fluid_sfloader_t* new_fluid_defsfloader(fluid_settings_t* settings)
{ {
fluid_sfloader_t* loader; fluid_sfloader_t* loader;
@ -41,7 +41,7 @@ fluid_sfloader_t* new_fluid_defsfloader()
return NULL; return NULL;
} }
loader->data = NULL; loader->data = settings;
loader->free = delete_fluid_defsfloader; loader->free = delete_fluid_defsfloader;
loader->load = fluid_defsfloader_load; loader->load = fluid_defsfloader_load;
@ -61,7 +61,7 @@ fluid_sfont_t* fluid_defsfloader_load(fluid_sfloader_t* loader, const char* file
fluid_defsfont_t* defsfont; fluid_defsfont_t* defsfont;
fluid_sfont_t* sfont; fluid_sfont_t* sfont;
defsfont = new_fluid_defsfont(); defsfont = new_fluid_defsfont(loader->data);
if (defsfont == NULL) { if (defsfont == NULL) {
return NULL; return NULL;
@ -200,12 +200,13 @@ int fluid_defpreset_preset_noteon(fluid_preset_t* preset, fluid_synth_t* synth,
* CACHED SAMPLEDATA LOADER * CACHED SAMPLEDATA LOADER
*/ */
typedef struct _fluid_cached_sampledata_t{ typedef struct _fluid_cached_sampledata_t {
struct _fluid_cached_sampledata_t *next; struct _fluid_cached_sampledata_t *next;
char* filename; char* filename;
time_t modification_time; time_t modification_time;
int num_references; int num_references;
int mlock;
const short* sampledata; const short* sampledata;
unsigned int samplesize; unsigned int samplesize;
@ -231,7 +232,8 @@ static int fluid_get_file_modification_time(char *filename, time_t *modification
#endif #endif
} }
static int fluid_cached_sampledata_load(char *filename, unsigned int samplepos, unsigned int samplesize, short **sampledata) static int fluid_cached_sampledata_load(char *filename, unsigned int samplepos,
unsigned int samplesize, short **sampledata, int try_mlock)
{ {
fluid_file fd = NULL; fluid_file fd = NULL;
short *loaded_sampledata = NULL; short *loaded_sampledata = NULL;
@ -245,25 +247,27 @@ static int fluid_cached_sampledata_load(char *filename, unsigned int samplepos,
modification_time = 0; modification_time = 0;
} }
cached_sampledata = all_cached_sampledata; for (cached_sampledata = all_cached_sampledata; cached_sampledata; cached_sampledata = cached_sampledata->next) {
while (cached_sampledata != NULL) { if (strcmp(filename, cached_sampledata->filename))
if (!strcmp(filename, cached_sampledata->filename)) { continue;
if (cached_sampledata->modification_time != modification_time)
if (cached_sampledata->modification_time == modification_time) { continue;
if (cached_sampledata->samplesize != samplesize) {
if (cached_sampledata->samplesize != samplesize) { FLUID_LOG(FLUID_ERR, "Cached size of soundfont doesn't match actual size of soundfont (cached: %u. actual: %u)",
FLUID_LOG(FLUID_ERR, "Cached size of soundfont doesn't match actual size of soundfont (cached: %u. actual: %u)", cached_sampledata->samplesize, samplesize);
cached_sampledata->samplesize,samplesize); continue;
} else {
cached_sampledata->num_references++;
loaded_sampledata = (short*) cached_sampledata->sampledata;
goto success_exit;
}
}
} }
cached_sampledata = cached_sampledata->next; if (try_mlock && !cached_sampledata->mlock) {
if (fluid_mlock(*sampledata, samplesize) != 0)
FLUID_LOG(FLUID_WARN, "Failed to pin the sample data to RAM; swapping is possible.");
else
cached_sampledata->mlock = try_mlock;
}
cached_sampledata->num_references++;
loaded_sampledata = (short*) cached_sampledata->sampledata;
goto success_exit;
} }
fd = FLUID_FOPEN(filename, "rb"); fd = FLUID_FOPEN(filename, "rb");
@ -291,10 +295,21 @@ static int fluid_cached_sampledata_load(char *filename, unsigned int samplepos,
FLUID_FCLOSE(fd); FLUID_FCLOSE(fd);
fd = NULL; fd = NULL;
cached_sampledata = (fluid_cached_sampledata_t*) FLUID_MALLOC(sizeof(fluid_cached_sampledata_t));
if (cached_sampledata == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory.");
goto error_exit;
}
/* Lock the memory to disable paging. It's okay if this fails. It /* Lock the memory to disable paging. It's okay if this fails. It
probably means that the user doesn't have to required permission. */ probably means that the user doesn't have to required permission. */
if (fluid_mlock(*sampledata, samplesize) != 0) { cached_sampledata->mlock = 0;
FLUID_LOG(FLUID_WARN, "Failed to pin the sample data to RAM; swapping is possible."); if (try_mlock) {
if (fluid_mlock(*sampledata, samplesize) != 0)
FLUID_LOG(FLUID_WARN, "Failed to pin the sample data to RAM; swapping is possible.");
else
cached_sampledata->mlock = try_mlock;
} }
/* If this machine is big endian, the sample have to byte swapped */ /* If this machine is big endian, the sample have to byte swapped */
@ -312,12 +327,6 @@ static int fluid_cached_sampledata_load(char *filename, unsigned int samplepos,
} }
} }
cached_sampledata = (fluid_cached_sampledata_t*) FLUID_MALLOC(sizeof(fluid_cached_sampledata_t));
if (cached_sampledata == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory.");
goto error_exit;
}
cached_sampledata->filename = (char*) FLUID_MALLOC(strlen(filename) + 1); cached_sampledata->filename = (char*) FLUID_MALLOC(strlen(filename) + 1);
if (cached_sampledata->filename == NULL) { if (cached_sampledata->filename == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory."); FLUID_LOG(FLUID_ERR, "Out of memory.");
@ -373,7 +382,8 @@ static int fluid_cached_sampledata_unload(const short *sampledata)
cached_sampledata->num_references--; cached_sampledata->num_references--;
if (cached_sampledata->num_references == 0) { if (cached_sampledata->num_references == 0) {
fluid_munlock(cached_sampledata->sampledata, cached_sampledata->samplesize); if (cached_sampledata->mlock)
fluid_munlock(cached_sampledata->sampledata, cached_sampledata->samplesize);
FLUID_FREE((short*) cached_sampledata->sampledata); FLUID_FREE((short*) cached_sampledata->sampledata);
FLUID_FREE(cached_sampledata->filename); FLUID_FREE(cached_sampledata->filename);
@ -416,7 +426,7 @@ static int fluid_cached_sampledata_unload(const short *sampledata)
/* /*
* new_fluid_defsfont * new_fluid_defsfont
*/ */
fluid_defsfont_t* new_fluid_defsfont() fluid_defsfont_t* new_fluid_defsfont(fluid_settings_t* settings)
{ {
fluid_defsfont_t* sfont; fluid_defsfont_t* sfont;
@ -432,6 +442,7 @@ fluid_defsfont_t* new_fluid_defsfont()
sfont->sample = NULL; sfont->sample = NULL;
sfont->sampledata = NULL; sfont->sampledata = NULL;
sfont->preset = NULL; sfont->preset = NULL;
fluid_settings_getint(settings, "synth.lock-memory", &sfont->mlock);
return sfont; return sfont;
} }
@ -616,7 +627,8 @@ int fluid_defsfont_add_preset(fluid_defsfont_t* sfont, fluid_defpreset_t* preset
int int
fluid_defsfont_load_sampledata(fluid_defsfont_t* sfont) fluid_defsfont_load_sampledata(fluid_defsfont_t* sfont)
{ {
return fluid_cached_sampledata_load(sfont->filename, sfont->samplepos, sfont->samplesize, &sfont->sampledata); return fluid_cached_sampledata_load(sfont->filename, sfont->samplepos,
sfont->samplesize, &sfont->sampledata, sfont->mlock);
} }
/* /*

View file

@ -375,7 +375,7 @@ typedef struct _fluid_inst_zone_t fluid_inst_zone_t;
*/ */
fluid_sfloader_t* new_fluid_defsfloader(void); fluid_sfloader_t* new_fluid_defsfloader(fluid_settings_t* settings);
int delete_fluid_defsfloader(fluid_sfloader_t* loader); int delete_fluid_defsfloader(fluid_sfloader_t* loader);
fluid_sfont_t* fluid_defsfloader_load(fluid_sfloader_t* loader, const char* filename); fluid_sfont_t* fluid_defsfloader_load(fluid_sfloader_t* loader, const char* filename);
@ -405,13 +405,14 @@ struct _fluid_defsfont_t
short* sampledata; /* the sample data, loaded in ram */ short* sampledata; /* the sample data, loaded in ram */
fluid_list_t* sample; /* the samples in this soundfont */ fluid_list_t* sample; /* the samples in this soundfont */
fluid_defpreset_t* preset; /* the presets of this soundfont */ fluid_defpreset_t* preset; /* the presets of this soundfont */
int mlock; /* Should we try memlock (avoid swapping)? */
fluid_preset_t iter_preset; /* preset interface used in the iteration */ fluid_preset_t iter_preset; /* preset interface used in the iteration */
fluid_defpreset_t* iter_cur; /* the current preset in the iteration */ fluid_defpreset_t* iter_cur; /* the current preset in the iteration */
}; };
fluid_defsfont_t* new_fluid_defsfont(void); fluid_defsfont_t* new_fluid_defsfont(fluid_settings_t* settings);
int delete_fluid_defsfont(fluid_defsfont_t* sfont); int delete_fluid_defsfont(fluid_defsfont_t* sfont);
int fluid_defsfont_load(fluid_defsfont_t* sfont, const char* file); int fluid_defsfont_load(fluid_defsfont_t* sfont, const char* file);
char* fluid_defsfont_get_name(fluid_defsfont_t* sfont); char* fluid_defsfont_get_name(fluid_defsfont_t* sfont);

View file

@ -27,6 +27,7 @@
#include "fluid_settings.h" #include "fluid_settings.h"
#include "fluid_sfont.h" #include "fluid_sfont.h"
#include "fluid_hash.h" #include "fluid_hash.h"
#include "fluid_defsfont.h"
#ifdef TRAP_ON_FPE #ifdef TRAP_ON_FPE
#define _GNU_SOURCE #define _GNU_SOURCE
@ -110,8 +111,6 @@ static void fluid_synth_set_gen_LOCAL (fluid_synth_t* synth, int chan,
static void fluid_synth_stop_LOCAL (fluid_synth_t *synth, unsigned int id); static void fluid_synth_stop_LOCAL (fluid_synth_t *synth, unsigned int id);
fluid_sfloader_t* new_fluid_defsfloader(void);
/*************************************************************** /***************************************************************
* *
@ -186,6 +185,8 @@ void fluid_synth_settings(fluid_settings_t* settings)
FLUID_HINT_TOGGLED, NULL, NULL); FLUID_HINT_TOGGLED, NULL, NULL);
fluid_settings_register_int(settings, "synth.ladspa.active", 0, 0, 1, fluid_settings_register_int(settings, "synth.ladspa.active", 0, 0, 1,
FLUID_HINT_TOGGLED, NULL, NULL); FLUID_HINT_TOGGLED, NULL, NULL);
fluid_settings_register_int(settings, "synth.lock-memory", 1, 0, 1,
FLUID_HINT_TOGGLED, NULL, NULL);
fluid_settings_register_str(settings, "midi.portname", "", 0, NULL, NULL); fluid_settings_register_str(settings, "midi.portname", "", 0, NULL, NULL);
fluid_settings_register_int(settings, "synth.polyphony", fluid_settings_register_int(settings, "synth.polyphony",
@ -676,7 +677,7 @@ new_fluid_synth(fluid_settings_t *settings)
#endif #endif
/* allocate and add the default sfont loader */ /* allocate and add the default sfont loader */
loader = new_fluid_defsfloader(); loader = new_fluid_defsfloader(settings);
if (loader == NULL) { if (loader == NULL) {
FLUID_LOG(FLUID_WARN, "Failed to create the default SoundFont loader"); FLUID_LOG(FLUID_WARN, "Failed to create the default SoundFont loader");