diff --git a/src/fluidsynth-dssi.c b/src/fluidsynth-dssi.c index 0b1c50b..0f61adf 100644 --- a/src/fluidsynth-dssi.c +++ b/src/fluidsynth-dssi.c @@ -36,6 +36,7 @@ #include #include +#include #include #include @@ -52,6 +53,12 @@ static DSSI_Descriptor *fsd_DSSI_descriptor = NULL; static fsd_synth_t fsd_synth; +static fsd_settings_t fsd_settings; + +static LADSPA_Data **l_outputs = NULL; +static LADSPA_Data **r_outputs = NULL; + + struct fsd_port_descriptor fsd_port_description[FSD_PORTS_COUNT] = { #define PD_OUT (LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO) #define PD_IN (LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL) @@ -95,7 +102,7 @@ fsd_all_voices_off(void) { int i; - for (i = 0; i < FSD_CHANNEL_COUNT; i++) { + for (i = 0; i < fsd_settings.channel_count; i++) { fsd_chan_all_voices_off(i); } } @@ -276,10 +283,14 @@ static LADSPA_Handle fsd_instantiate(const LADSPA_Descriptor *descriptor, unsigned long sample_rate) { fsd_instance_t *instance; - int i; - - /* refuse another instantiation if we've reached out limit */ - if (fsd_synth.instance_count == FSD_CHANNEL_COUNT) { + int i, configval; + gchar *configdirname, *configfilename; + GKeyFile *key_file; + + /* fsd_settings.channel_count unset on forst call */ + if (fsd_synth.instance_count != 0 && + /* refuse another instantiation if we've reached out limit */ + fsd_synth.instance_count == fsd_settings.channel_count) { return NULL; } @@ -292,11 +303,54 @@ fsd_instantiate(const LADSPA_Descriptor *descriptor, unsigned long sample_rate) return NULL; } + /* configfile settings defaults */ + fsd_settings.channel_count = FSD_CHANNEL_COUNT_DEFAULT; + fluid_settings_getint(fsd_synth.fluid_settings, "audio.realtime-prio", &fsd_settings.realtime_prio); + fluid_settings_getint(fsd_synth.fluid_settings, "synth.cpu-cores", &fsd_settings.thread_count); + + configdirname = g_build_filename(g_get_user_config_dir(), "fluidsynth-dssi", NULL); + configfilename = g_build_filename(configdirname, "fluidsynth-dssi.conf", NULL); + key_file = g_key_file_new(); + /* No config file yet: create one with defaults */ + if (!g_key_file_load_from_file( + key_file, + configfilename, + G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, + NULL)) { + g_key_file_set_integer(key_file, "audio", "realtime-prio", fsd_settings.realtime_prio); + g_key_file_set_integer(key_file, "synth", "maxchannels", fsd_settings.channel_count); + g_key_file_set_integer(key_file, "synth", "parallel-threads", fsd_settings.thread_count); + g_mkdir_with_parents(configdirname, 0700); + g_key_file_save_to_file(key_file, configfilename, NULL); + /* config file available: get settings */ + } else { + configval = g_key_file_get_integer(key_file, "audio", "realtime-prio", NULL); + if (configval > 0) + fsd_settings.realtime_prio = configval; + configval = g_key_file_get_integer(key_file, "synth", "maxchannels", NULL); + if (configval > 0) + fsd_settings.channel_count = configval; + configval = g_key_file_get_integer(key_file, "synth", "parallel-threads", NULL); + if (configval > 0) + fsd_settings.thread_count = configval; + } + + g_key_file_free(key_file); + g_free(configfilename); + g_free(configdirname); + + /* setup buffers from persitant settings */ + fsd_synth.channel_map = (fsd_instance_t **)calloc(fsd_settings.channel_count, sizeof(fsd_instance_t *)); + l_outputs = (LADSPA_Data **) calloc(fsd_settings.channel_count, sizeof(LADSPA_Data *)); + r_outputs = (LADSPA_Data **) calloc(fsd_settings.channel_count, sizeof(LADSPA_Data *)); + /* set appropriate settings here */ fluid_settings_setnum(fsd_synth.fluid_settings, "synth.sample-rate", sample_rate); - fluid_settings_setint(fsd_synth.fluid_settings, "synth.midi-channels", FSD_CHANNEL_COUNT); - fluid_settings_setint(fsd_synth.fluid_settings, "synth.audio-channels", FSD_CHANNEL_COUNT); - fluid_settings_setint(fsd_synth.fluid_settings, "synth.audio-groups", FSD_CHANNEL_COUNT); + fluid_settings_setint(fsd_synth.fluid_settings, "synth.midi-channels", fsd_settings.channel_count); + fluid_settings_setint(fsd_synth.fluid_settings, "synth.audio-channels", fsd_settings.channel_count); + fluid_settings_setint(fsd_synth.fluid_settings, "synth.audio-groups", fsd_settings.channel_count); + fluid_settings_setint(fsd_synth.fluid_settings, "audio.realtime-prio", fsd_settings.realtime_prio); + fluid_settings_setint(fsd_synth.fluid_settings, "synth.cpu-cores", fsd_settings.thread_count); fsd_synth.polyphony = FSD_MAX_POLYPHONY; fluid_settings_setint(fsd_synth.fluid_settings, "synth.polyphony", fsd_synth.polyphony); fluid_settings_setstr(fsd_synth.fluid_settings, "synth.reverb.active", "no"); @@ -323,7 +377,7 @@ fsd_instantiate(const LADSPA_Descriptor *descriptor, unsigned long sample_rate) return NULL; } /* find a free channel */ - for (i = 0; i < FSD_CHANNEL_COUNT; i++) { + for (i = 0; i < fsd_settings.channel_count; i++) { if (fsd_synth.channel_map[i] == NULL) { fsd_synth.channel_map[i] = instance; instance->channel = i; @@ -439,6 +493,12 @@ fsd_cleanup(LADSPA_Handle handle) delete_fluid_settings(fsd_synth.fluid_settings); fsd_synth.fluid_synth = NULL; fsd_synth.fluid_settings = NULL; + free(fsd_synth.channel_map); + fsd_synth.channel_map = NULL; + free(l_outputs); + l_outputs = NULL; + free(r_outputs); + r_outputs = NULL; } free(instance); } @@ -777,8 +837,6 @@ fsd_run_multiple_synths(unsigned long instance_count, LADSPA_Handle *handles, fsd_instance_t **instances = (fsd_instance_t **)handles; unsigned long samples_done = 0; unsigned long event_index[instance_count]; - static LADSPA_Data *l_outputs[FSD_CHANNEL_COUNT]; - static LADSPA_Data *r_outputs[FSD_CHANNEL_COUNT]; unsigned long this_pending_event_tick; unsigned long next_pending_event_tick; int i; @@ -799,7 +857,7 @@ fsd_run_multiple_synths(unsigned long instance_count, LADSPA_Handle *handles, instances[i]->pending_preset_change = -1; } } - for (i = 0; i < FSD_CHANNEL_COUNT; i++) { + for (i = 0; i < fsd_settings.channel_count; i++) { l_outputs[i] = fsd_synth.bit_bucket; r_outputs[i] = fsd_synth.bit_bucket; } @@ -835,7 +893,7 @@ fsd_run_multiple_synths(unsigned long instance_count, LADSPA_Handle *handles, if (burst_size > FSD_MAX_BURST_SIZE) burst_size = FSD_MAX_BURST_SIZE; - for (i = 0; i < FSD_CHANNEL_COUNT; i++) { + for (i = 0; i < fsd_settings.channel_count; i++) { if (fsd_synth.channel_map[i]) { fsd_instance_t *instance = fsd_synth.channel_map[i]; l_outputs[instance->channel] = instance->output_l + samples_done; @@ -906,9 +964,6 @@ void _init() pthread_mutex_init(&fsd_synth.mutex, NULL); fsd_synth.mutex_grab_failed = 0; fsd_synth.soundfonts = NULL; - for (i = 0; i < FSD_CHANNEL_COUNT; i++) { - fsd_synth.channel_map[i] = NULL; - } fsd_LADSPA_descriptor = (LADSPA_Descriptor *) malloc(sizeof(LADSPA_Descriptor)); diff --git a/src/fluidsynth-dssi.h b/src/fluidsynth-dssi.h index 4a3dd23..81786a3 100644 --- a/src/fluidsynth-dssi.h +++ b/src/fluidsynth-dssi.h @@ -47,13 +47,13 @@ #define FSD_MAX_CHANNELS 255 /* FluidSynth's virtual channel limit (n.b. NO_CHANNEL in fluid_voice.h) */ -/* FSD_CHANNEL_COUNT is the number of channels FluidSynth-DSSI tells +/* FSD_CHANNEL_COUNT_DEFAULT is the number of channels FluidSynth-DSSI tells * libfluidsynth to create at startup. It can be up to FSD_MAX_CHANNELS, * but be aware that for each channel, libfluidsynth will zero and copy out * two buffers every process cycle, so it's best to set FSD_CHANNEL_COUNT * to no more than the maximum number of simultaneous FluidSynth-DSSI * instances you'll need. */ -#define FSD_CHANNEL_COUNT 32 +#define FSD_CHANNEL_COUNT_DEFAULT 32 /* -FIX- These should be in a header file shared with FluidSynth-DSSI_gtk.c: */ #define FSD_MAX_POLYPHONY 256 @@ -75,10 +75,17 @@ struct fsd_port_descriptor { LADSPA_Data upper_bound; }; +typedef struct _fsd_settings_t fsd_settings_t; typedef struct _fsd_instance_t fsd_instance_t; typedef struct _fsd_sfont_t fsd_sfont_t; typedef struct _fsd_synth_t fsd_synth_t; +struct _fsd_settings_t { + int channel_count; + int thread_count; + int realtime_prio; +}; + struct _fsd_instance_t { int channel; int pending_preset_change; @@ -106,7 +113,7 @@ struct _fsd_synth_t { fsd_sfont_t *soundfonts; float gain; int polyphony; - fsd_instance_t *channel_map[FSD_CHANNEL_COUNT]; + fsd_instance_t **channel_map; LADSPA_Data bit_bucket[FSD_MAX_BURST_SIZE]; LADSPA_Data *fx_buckets[2]; };