Skip to content

Commit

Permalink
Add configuration file support
Browse files Browse the repository at this point in the history
The following settings for fluidsynth (all non realtime - so no GUI) can be
configured in ini-formatted $HOME/.config/fluidsynth-dssi/fluidsynth-dssi.conf:

* audio/realtime-prio: realtime priority for threads.
* synth/maxchannels: Maximum channels supported by fluidsynth-dssi
* parallel-threads: Number of parallel threads used for sound rendering

Signed-off-by: Andreas Müller <schnitzeltony@gmail.com>
  • Loading branch information
schnitzeltony committed Nov 20, 2017
1 parent 5246c06 commit bad09c6
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 19 deletions.
87 changes: 71 additions & 16 deletions src/fluidsynth-dssi.c
Expand Up @@ -36,6 +36,7 @@
#include <stdarg.h>
#include <pthread.h>

#include <glib.h>
#include <ladspa.h>
#include <dssi.h>

Expand All @@ -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)
Expand Down Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -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;
}

Expand All @@ -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");
Expand All @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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));
Expand Down
13 changes: 10 additions & 3 deletions src/fluidsynth-dssi.h
Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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];
};
Expand Down

0 comments on commit bad09c6

Please sign in to comment.