diff --git a/doc/recent_changes.txt b/doc/recent_changes.txt
index 725c2fa6..ba86d0a2 100644
--- a/doc/recent_changes.txt
+++ b/doc/recent_changes.txt
@@ -11,6 +11,7 @@
- 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()
+- Added getter and setter functions for individual effect groups
\section NewIn2_1_4 What's new in 2.1.4?
diff --git a/include/fluidsynth/synth.h b/include/fluidsynth/synth.h
index e4794319..b8d0b0ab 100644
--- a/include/fluidsynth/synth.h
+++ b/include/fluidsynth/synth.h
@@ -159,19 +159,31 @@ FLUIDSYNTH_API int fluid_synth_get_bank_offset(fluid_synth_t *synth, int sfont_i
*
* @{
*/
-FLUIDSYNTH_API int fluid_synth_set_reverb(fluid_synth_t *synth, double roomsize,
- double damping, double width, double level);
-FLUIDSYNTH_API int fluid_synth_set_reverb_roomsize(fluid_synth_t *synth, double roomsize);
-FLUIDSYNTH_API int fluid_synth_set_reverb_damp(fluid_synth_t *synth, double damping);
-FLUIDSYNTH_API int fluid_synth_set_reverb_width(fluid_synth_t *synth, double width);
-FLUIDSYNTH_API int fluid_synth_set_reverb_level(fluid_synth_t *synth, double level);
+FLUID_DEPRECATED FLUIDSYNTH_API void fluid_synth_set_reverb_on(fluid_synth_t *synth, int on);
+FLUIDSYNTH_API int fluid_synth_reverb_on(fluid_synth_t *synth, int fx_group, int on);
-FLUIDSYNTH_API void fluid_synth_set_reverb_on(fluid_synth_t *synth, int on);
-FLUIDSYNTH_API double fluid_synth_get_reverb_roomsize(fluid_synth_t *synth);
-FLUIDSYNTH_API double fluid_synth_get_reverb_damp(fluid_synth_t *synth);
-FLUIDSYNTH_API double fluid_synth_get_reverb_level(fluid_synth_t *synth);
-FLUIDSYNTH_API double fluid_synth_get_reverb_width(fluid_synth_t *synth);
-/* @} Reverb */
+FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_reverb(fluid_synth_t *synth, double roomsize,
+ double damping, double width, double level);
+FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_reverb_roomsize(fluid_synth_t *synth, double roomsize);
+FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_reverb_damp(fluid_synth_t *synth, double damping);
+FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_reverb_width(fluid_synth_t *synth, double width);
+FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_reverb_level(fluid_synth_t *synth, double level);
+
+FLUID_DEPRECATED FLUIDSYNTH_API double fluid_synth_get_reverb_roomsize(fluid_synth_t *synth);
+FLUID_DEPRECATED FLUIDSYNTH_API double fluid_synth_get_reverb_damp(fluid_synth_t *synth);
+FLUID_DEPRECATED FLUIDSYNTH_API double fluid_synth_get_reverb_level(fluid_synth_t *synth);
+FLUID_DEPRECATED FLUIDSYNTH_API double fluid_synth_get_reverb_width(fluid_synth_t *synth);
+
+FLUIDSYNTH_API int fluid_synth_set_reverb_group_roomsize(fluid_synth_t *synth, int fx_group, double roomsize);
+FLUIDSYNTH_API int fluid_synth_set_reverb_group_damp(fluid_synth_t *synth, int fx_group, double damping);
+FLUIDSYNTH_API int fluid_synth_set_reverb_group_width(fluid_synth_t *synth, int fx_group, double width);
+FLUIDSYNTH_API int fluid_synth_set_reverb_group_level(fluid_synth_t *synth, int fx_group, double level);
+
+FLUIDSYNTH_API int fluid_synth_get_reverb_group_roomsize(fluid_synth_t *synth, int fx_group, double *roomsize);
+FLUIDSYNTH_API int fluid_synth_get_reverb_group_damp(fluid_synth_t *synth, int fx_group, double *damping);
+FLUIDSYNTH_API int fluid_synth_get_reverb_group_width(fluid_synth_t *synth, int fx_group, double *width);
+FLUIDSYNTH_API int fluid_synth_get_reverb_group_level(fluid_synth_t *synth, int fx_group, double *level);
+ /* @} Reverb */
/**
@@ -192,22 +204,36 @@ enum fluid_chorus_mod
FLUID_CHORUS_MOD_TRIANGLE = 1 /**< Triangle wave chorus modulation */
};
-FLUIDSYNTH_API int fluid_synth_set_chorus(fluid_synth_t *synth, int nr, double level,
- double speed, double depth_ms, int type);
-FLUIDSYNTH_API int fluid_synth_set_chorus_nr(fluid_synth_t *synth, int nr);
-FLUIDSYNTH_API int fluid_synth_set_chorus_level(fluid_synth_t *synth, double level);
-FLUIDSYNTH_API int fluid_synth_set_chorus_speed(fluid_synth_t *synth, double speed);
-FLUIDSYNTH_API int fluid_synth_set_chorus_depth(fluid_synth_t *synth, double depth_ms);
-FLUIDSYNTH_API int fluid_synth_set_chorus_type(fluid_synth_t *synth, int type);
-FLUIDSYNTH_API void fluid_synth_set_chorus_on(fluid_synth_t *synth, int on);
-FLUIDSYNTH_API int fluid_synth_get_chorus_nr(fluid_synth_t *synth);
-FLUIDSYNTH_API double fluid_synth_get_chorus_level(fluid_synth_t *synth);
-FLUIDSYNTH_API double fluid_synth_get_chorus_speed(fluid_synth_t *synth);
-FLUIDSYNTH_API double fluid_synth_get_chorus_depth(fluid_synth_t *synth);
-FLUIDSYNTH_API int fluid_synth_get_chorus_type(fluid_synth_t *synth); /* see fluid_chorus_mod */
-/* @} Chrous */
+FLUID_DEPRECATED FLUIDSYNTH_API void fluid_synth_set_chorus_on(fluid_synth_t *synth, int on);
+FLUIDSYNTH_API int fluid_synth_chorus_on(fluid_synth_t *synth, int fx_group, int on);
+FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_chorus(fluid_synth_t *synth, int nr, double level,
+ double speed, double depth_ms, int type);
+FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_chorus_nr(fluid_synth_t *synth, int nr);
+FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_chorus_level(fluid_synth_t *synth, double level);
+FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_chorus_speed(fluid_synth_t *synth, double speed);
+FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_chorus_depth(fluid_synth_t *synth, double depth_ms);
+FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_chorus_type(fluid_synth_t *synth, int type);
+
+FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_get_chorus_nr(fluid_synth_t *synth);
+FLUID_DEPRECATED FLUIDSYNTH_API double fluid_synth_get_chorus_level(fluid_synth_t *synth);
+FLUID_DEPRECATED FLUIDSYNTH_API double fluid_synth_get_chorus_speed(fluid_synth_t *synth);
+FLUID_DEPRECATED FLUIDSYNTH_API double fluid_synth_get_chorus_depth(fluid_synth_t *synth);
+FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_get_chorus_type(fluid_synth_t *synth); /* see fluid_chorus_mod */
+
+FLUIDSYNTH_API int fluid_synth_set_chorus_group_nr(fluid_synth_t *synth, int fx_group, int nr);
+FLUIDSYNTH_API int fluid_synth_set_chorus_group_level(fluid_synth_t *synth, int fx_group, double level);
+FLUIDSYNTH_API int fluid_synth_set_chorus_group_speed(fluid_synth_t *synth, int fx_group, double speed);
+FLUIDSYNTH_API int fluid_synth_set_chorus_group_depth(fluid_synth_t *synth, int fx_group, double depth_ms);
+FLUIDSYNTH_API int fluid_synth_set_chorus_group_type(fluid_synth_t *synth, int fx_group, int type);
+
+FLUIDSYNTH_API int fluid_synth_get_chorus_group_nr(fluid_synth_t *synth, int fx_group, int *nr);
+FLUIDSYNTH_API int fluid_synth_get_chorus_group_level(fluid_synth_t *synth, int fx_group, double *level);
+FLUIDSYNTH_API int fluid_synth_get_chorus_group_speed(fluid_synth_t *synth, int fx_group, double *speed);
+FLUIDSYNTH_API int fluid_synth_get_chorus_group_depth(fluid_synth_t *synth, int fx_group, double *depth_ms);
+FLUIDSYNTH_API int fluid_synth_get_chorus_group_type(fluid_synth_t *synth, int fx_group, int *type);
+/* @} Chorus */
/**
* @defgroup synthesis_params Synthesis Parameters
diff --git a/src/bindings/fluid_cmd.c b/src/bindings/fluid_cmd.c
index 968f53dc..2776417d 100644
--- a/src/bindings/fluid_cmd.c
+++ b/src/bindings/fluid_cmd.c
@@ -192,48 +192,48 @@ static const fluid_cmd_t fluid_commands[] =
/* reverb commands */
{
"rev_preset", "reverb", fluid_handle_reverbpreset,
- "rev_preset num Load preset num into the reverb unit"
+ "rev_preset num Load preset num into all reverb unit"
},
{
"rev_setroomsize", "reverb", fluid_handle_reverbsetroomsize,
- "rev_setroomsize num Change reverb room size"
+ "rev_setroomsize [group] num Set room size of all or one reverb group to num"
},
{
"rev_setdamp", "reverb", fluid_handle_reverbsetdamp,
- "rev_setdamp num Change reverb damping"
+ "rev_setdamp [group] num Set damping of all or one reverb group to num"
},
{
"rev_setwidth", "reverb", fluid_handle_reverbsetwidth,
- "rev_setwidth num Change reverb width"
+ "rev_setwidth [group] num Set width of all or one reverb group to num"
},
{
"rev_setlevel", "reverb", fluid_handle_reverbsetlevel,
- "rev_setlevel num Change reverb level"
+ "rev_setlevel [group] num Set output level of all or one reverb group to num"
},
{
"reverb", "reverb", fluid_handle_reverb,
- "reverb [0|1|on|off] Turn the reverb on or off"
+ "reverb [0|1|on|off] Turn all reverb groups on or off"
},
/* chorus commands */
{
"cho_set_nr", "chorus", fluid_handle_chorusnr,
- "cho_set_nr n Use n delay lines (default 3)"
+ "cho_set_nr [group] n Set n delay lines (default 3) in all or one chorus group"
},
{
"cho_set_level", "chorus", fluid_handle_choruslevel,
- "cho_set_level num Set output level of each chorus line to num"
+ "cho_set_level [group] num Set output level of all or one chorus group to num"
},
{
"cho_set_speed", "chorus", fluid_handle_chorusspeed,
- "cho_set_speed num Set mod speed of chorus to num (Hz)"
+ "cho_set_speed [group] num Set mod speed of all or one chorus group to num (Hz)"
},
{
"cho_set_depth", "chorus", fluid_handle_chorusdepth,
- "cho_set_depth num Set chorus modulation depth to num (ms)"
+ "cho_set_depth [group] num Set modulation depth of all or one chorus group to num (ms)"
},
{
"chorus", "chorus", fluid_handle_chorus,
- "chorus [0|1|on|off] Turn the chorus on or off"
+ "chorus [0|1|on|off] Turn all chorus groups on or off"
},
{
"gain", "general", fluid_handle_gain,
@@ -623,13 +623,13 @@ fluid_get_userconf(char *buf, int len)
#if defined(WIN32)
home = getenv("USERPROFILE");
config_file = "\\fluidsynth.cfg";
-
+
#elif !defined(MACOS9)
home = getenv("HOME");
config_file = "/.fluidsynth";
-
+
#endif
-
+
if(home == NULL)
{
return NULL;
@@ -1096,275 +1096,365 @@ fluid_handle_reverbpreset(void *data, int ac, char **av, fluid_ostream_t out)
return FLUID_OK;
}
+/*
+ The function is useful for reverb and chorus commands which have
+ 1 or 2 parameters.
+ The function checks that there is 1 or 2 aguments.
+ When there is 2 parameters it checks the first argument that must be
+ an fx group index in the range[0..synth->effects_groups-1].
+
+ return the group index:
+ -1, when the command is for all fx groups.
+ 0 to synth->effects_groups-1, when the command is for this group index.
+ -2 if error.
+*/
+static int check_fx_group_idx(int ac, char **av, fluid_ostream_t out,
+ fluid_synth_t *synth, const char *name_cde)
+{
+ int fx_group; /* fx unit index */
+ int ngroups; /* count of fx groups */
+
+ /* One or 2 arguments allowed */
+ if(ac < 1 || ac > 2)
+ {
+ fluid_ostream_printf(out, "%s: needs 1 or 2 arguments\n", name_cde);
+ return -2;
+ }
+
+ /* check optionnal first argument which is a fx group index */
+ fx_group = -1;
+
+ if(ac > 1)
+ {
+ fx_group = atoi(av[0]); /* get fx group index */
+ ngroups = fluid_synth_count_effects_groups(synth);
+
+ if(!fluid_is_number(av[0]) || fx_group < 0 || fx_group >= ngroups)
+ {
+ fluid_ostream_printf(out, "%s: group index \"%s\" must be in range [%d..%d]\n",
+ name_cde, av[0], 0, ngroups - 1);
+ return -2;
+ }
+ }
+
+ return fx_group;
+}
+
+/* parameter value */
+struct value
+{
+ char *name;
+ double min;
+ double max;
+};
+
+/*
+ check 2 arguments for reverb commands : fx group index , value
+ - group index must be an integer in the range [-1..synth->effects_groups].
+ - value must be a double in the range [min..max]
+ @param param a pointer on a value to return the second value argument.
+ return the fx group index:
+ -1 when the command is for all fx group.
+ 0 to synth->effects_groups-1 when the command is for this group index.
+ -2 if error.
+*/
+static int check_fx_reverb_param(int ac, char **av, fluid_ostream_t out,
+ fluid_synth_t *synth, const char *name_cde,
+ const struct value *value,
+ fluid_real_t *param)
+{
+ /* get and check fx group index argument */
+ int fx_group = check_fx_group_idx(ac, av, out, synth, name_cde);
+
+ if(fx_group >= -1)
+ {
+ fluid_real_t val;
+
+ /* get and check value argument */
+ ac--;
+ val = atof(av[ac]);
+
+ if(!fluid_is_number(av[ac]) || val < value->min || val > value->max)
+ {
+ fluid_ostream_printf(out, "%s: %s \"%s\" must be in range [%f..%f]\n",
+ name_cde, value->name, av[ac], value->min, value->max);
+ return -2;
+ }
+
+ *param = val;
+ }
+
+ return fx_group;
+}
+
+/* Purpose:
+ * Response to fluid_handle_reverbsetxxxx commands
+ */
+static int
+fluid_handle_reverb_command(void *data, int ac, char **av, fluid_ostream_t out,
+ int param)
+{
+ int fx_group;
+
+ /* reverb commands name table */
+ static const char *name_cde[FLUID_REVERB_PARAM_LAST] =
+ {"rev_setroomsize", "rev_setdamp", "rev_setwidth", "rev_setlevel"};
+
+ /* name and min/max values table */
+ static struct value values[FLUID_REVERB_PARAM_LAST] =
+ {
+ {"room size"}, {"damp"}, {"width"}, {"level"}
+ };
+
+ FLUID_ENTRY_COMMAND(data);
+ fluid_real_t value;
+
+ fluid_settings_getnum_range(handler->synth->settings, "synth.reverb.room-size",
+ &values[FLUID_REVERB_ROOMSIZE].min,
+ &values[FLUID_REVERB_ROOMSIZE].max);
+
+ fluid_settings_getnum_range(handler->synth->settings, "synth.reverb.damp",
+ &values[FLUID_REVERB_DAMP].min,
+ &values[FLUID_REVERB_DAMP].max);
+
+
+ fluid_settings_getnum_range(handler->synth->settings, "synth.reverb.width",
+ &values[FLUID_REVERB_WIDTH].min,
+ &values[FLUID_REVERB_WIDTH].max);
+
+ fluid_settings_getnum_range(handler->synth->settings, "synth.reverb.level",
+ &values[FLUID_REVERB_LEVEL].min,
+ &values[FLUID_REVERB_LEVEL].max);
+
+ /* get and check command arguments */
+ fx_group = check_fx_reverb_param(ac, av, out, handler->synth,
+ name_cde[param], &values[param], &value);
+
+ if(fx_group >= -1)
+ {
+ /* run reverb function */
+ fluid_synth_reverb_set_param(handler->synth, fx_group, param, value);
+ return FLUID_OK;
+ }
+
+ return FLUID_FAILED;
+}
+
/* Purpose:
* Response to 'rev_setroomsize' command.
- * Load the new room size into the reverb unit. */
+ * Load the new room size into the reverb fx group.
+ * Example: rev_setroomzize 0 0.5
+ * load roomsize 0.5 in the reverb fx group at index 0
+ */
int
fluid_handle_reverbsetroomsize(void *data, int ac, char **av, fluid_ostream_t out)
{
- FLUID_ENTRY_COMMAND(data);
- fluid_real_t room_size;
-
- if(ac < 1)
- {
- fluid_ostream_printf(out, "rev_setroomsize: too few arguments.\n");
- return FLUID_FAILED;
- }
-
- fluid_ostream_printf(out, "rev_setroomsize is deprecated! Use 'set synth.reverb.room-size %s' instead.\n", av[0]);
-
- room_size = atof(av[0]);
-
- if(room_size < 0)
- {
- fluid_ostream_printf(out, "rev_setroomsize: Room size must be positive!\n");
- return FLUID_FAILED;
- }
-
- if(room_size > 1.0)
- {
- fluid_ostream_printf(out, "rev_setroomsize: Room size too big!\n");
- return FLUID_FAILED;
- }
-
- fluid_synth_set_reverb_roomsize(handler->synth, room_size);
- return FLUID_OK;
+ return fluid_handle_reverb_command(data, ac, av, out, FLUID_REVERB_ROOMSIZE);
}
/* Purpose:
* Response to 'rev_setdamp' command.
- * Load the new damp factor into the reverb unit. */
+ * Load the new damp factor into the reverb fx group.
+ * Example: rev_setdamp 1 0.5
+ * load damp 0.5 in the reverb fx group at index 1
+ */
int
fluid_handle_reverbsetdamp(void *data, int ac, char **av, fluid_ostream_t out)
{
- FLUID_ENTRY_COMMAND(data);
- fluid_real_t damp;
-
- if(ac < 1)
- {
- fluid_ostream_printf(out, "rev_setdamp: too few arguments.\n");
- return FLUID_FAILED;
- }
-
- fluid_ostream_printf(out, "rev_setdamp is deprecated! Use 'set synth.reverb.damp %s' instead.\n", av[0]);
-
- damp = atof(av[0]);
-
- if((damp < 0.0f) || (damp > 1))
- {
- fluid_ostream_printf(out, "rev_setdamp: damp must be between 0 and 1!\n");
- return FLUID_FAILED;
- }
-
- fluid_synth_set_reverb_damp(handler->synth, damp);
- return FLUID_OK;
+ return fluid_handle_reverb_command(data, ac, av, out, FLUID_REVERB_DAMP);
}
/* Purpose:
* Response to 'rev_setwidth' command.
- * Load the new width into the reverb unit. */
+ * Load the new width into the reverb fx group.
+ * Example: rev_setwidth 1 0.5
+ * load width 0.5 in the reverb fx group at index 1.
+ */
int
fluid_handle_reverbsetwidth(void *data, int ac, char **av, fluid_ostream_t out)
{
- FLUID_ENTRY_COMMAND(data);
- fluid_real_t width;
-
- if(ac < 1)
- {
- fluid_ostream_printf(out, "rev_setwidth: too few arguments.\n");
- return FLUID_FAILED;
- }
-
- fluid_ostream_printf(out, "rev_setroomsize is deprecated! Use 'set synth.reverb.width %s' instead.\n", av[0]);
-
- width = atof(av[0]);
-
- if((width < 0) || (width > 100))
- {
- fluid_ostream_printf(out, "rev_setroomsize: Too wide! (0..100)\n");
- return FLUID_FAILED;
- }
-
- fluid_synth_set_reverb_width(handler->synth, width);
- return FLUID_OK;
+ return fluid_handle_reverb_command(data, ac, av, out, FLUID_REVERB_WIDTH);
}
/* Purpose:
* Response to 'rev_setlevel' command.
- * Load the new level into the reverb unit. */
+ * Load the new level into the reverb fx group.
+ * Example: rev_setlevel 1 0.5
+ * load level 0.5 in the reverb fx group at index 1.
+ */
int
fluid_handle_reverbsetlevel(void *data, int ac, char **av, fluid_ostream_t out)
{
+ return fluid_handle_reverb_command(data, ac, av, out, FLUID_REVERB_LEVEL);
+}
+
+/* reverb/chorus on/off commands enum */
+enum rev_chor_on_cde
+{
+ REVERB_ON_CDE,
+ CHORUS_ON_CDE,
+ NBR_REV_CHOR_ON_CDE
+};
+
+/* Purpose:
+ * Set all reverb/chorus units on or off
+ */
+static int
+fluid_handle_reverb_chorus_on_command(void *data, int ac, char **av, fluid_ostream_t out,
+ enum rev_chor_on_cde cde)
+{
+ /* commands name table */
+ static const char *name_cde[NBR_REV_CHOR_ON_CDE] = {"reverb", "chorus"};
+ /* functions table */
+ static int (*onoff_func[NBR_REV_CHOR_ON_CDE])(fluid_synth_t *, int, int) =
+ {
+ fluid_synth_reverb_on, fluid_synth_chorus_on
+ };
+
FLUID_ENTRY_COMMAND(data);
- fluid_real_t level;
+ int onoff;
- if(ac < 1)
+ /* get and check fx group index argument */
+ int fx_group = check_fx_group_idx(ac, av, out, handler->synth, name_cde[cde]);
+
+ if(fx_group >= -1)
{
- fluid_ostream_printf(out, "rev_setlevel: too few arguments.\n");
- return FLUID_FAILED;
+ ac--;
+
+ /* check argument value */
+ if((FLUID_STRCMP(av[ac], "0") == 0) || (FLUID_STRCMP(av[ac], "off") == 0))
+ {
+ onoff = 0;
+ }
+ else if((FLUID_STRCMP(av[ac], "1") == 0) || (FLUID_STRCMP(av[ac], "on") == 0))
+ {
+ onoff = 1;
+ }
+ else
+ {
+ fluid_ostream_printf(out, "%s: invalid arguments %s [0|1|on|off]\n",
+ name_cde[cde], av[ac]);
+ return FLUID_FAILED;
+ }
+
+ /* run on/off function */
+ return onoff_func[cde](handler->synth, fx_group, onoff);
}
- fluid_ostream_printf(out, "rev_setlevel is deprecated! Use 'set synth.reverb.level %s' instead.\n", av[0]);
-
- level = atof(av[0]);
-
- if(fabs(level) > 30)
- {
- fluid_ostream_printf(out, "rev_setlevel: Value too high! (Value of 10 =+20 dB)\n");
- return FLUID_FAILED;
- }
-
- fluid_synth_set_reverb_level(handler->synth, level);
- return FLUID_OK;
+ return FLUID_FAILED;
}
/* Purpose:
- * Response to 'reverb' command.
- * Change the FLUID_REVERB flag in the synth */
+ * Set all reverb units on
+ */
int
fluid_handle_reverb(void *data, int ac, char **av, fluid_ostream_t out)
{
- FLUID_ENTRY_COMMAND(data);
-
- if(ac < 1)
- {
- fluid_ostream_printf(out, "reverb: too few arguments.\n");
- return FLUID_FAILED;
- }
-
- fluid_ostream_printf(out, "reverb is deprecated! Use 'set synth.reverb.active %s' instead.\n", av[0]);
-
- if((FLUID_STRCMP(av[0], "0") == 0) || (FLUID_STRCMP(av[0], "off") == 0))
- {
- fluid_synth_set_reverb_on(handler->synth, 0);
- }
- else if((FLUID_STRCMP(av[0], "1") == 0) || (FLUID_STRCMP(av[0], "on") == 0))
- {
- fluid_synth_set_reverb_on(handler->synth, 1);
- }
- else
- {
- fluid_ostream_printf(out, "reverb: invalid arguments %s [0|1|on|off]", av[0]);
- return FLUID_FAILED;
- }
-
- return FLUID_OK;
+ return fluid_handle_reverb_chorus_on_command(data, ac, av, out, REVERB_ON_CDE);
}
+/* Purpose:
+ * Response to fluid_handle_chorus_xxx commands
+ */
+static int
+fluid_handle_chorus_command(void *data, int ac, char **av, fluid_ostream_t out,
+ int param)
+{
+ /* chorus commands name table */
+ static const char *name_cde[FLUID_CHORUS_PARAM_LAST - 1] =
+ {"cho_set_nr", "cho_set_level", "cho_set_speed", "cho_set_depth"};
+
+ /* value name table */
+ static const char *name_value[FLUID_CHORUS_PARAM_LAST - 1] =
+ {"nr", "level", "speed", "depth"};
+
+ FLUID_ENTRY_COMMAND(data);
+
+ /* get and check index fx group index argument */
+ int fx_group = check_fx_group_idx(ac, av, out, handler->synth, name_cde[param]);
+
+ if(fx_group >= -1)
+ {
+ double value;
+ /* get and check value argument */
+ ac--;
+
+ if(!fluid_is_number(av[ac]))
+ {
+ fluid_ostream_printf(out, "%s: %s \"%s\" must be a number\n",
+ name_cde[param], name_value[param], av[ac]);
+ return FLUID_FAILED;
+ }
+
+ /* run chorus function */
+ if(param == FLUID_CHORUS_NR) /* commands with integer parameter */
+ {
+ value = (double)atoi(av[ac]);
+ }
+ else /* commands with float parameter */
+ {
+ value = atof(av[ac]);
+ }
+
+ fluid_synth_chorus_set_param(handler->synth, fx_group, param, value);
+ return FLUID_OK;
+ }
+
+ return FLUID_FAILED;
+}
/* Purpose:
- * Response to 'chorus_setnr' command */
+ * Response to 'cho_set_nr' command
+ * Load the new voice count into the chorus fx group.
+ * Example: cho_set_nr 1 3
+ * load 3 voices in the chorus fx group at index 1.
+ */
int
fluid_handle_chorusnr(void *data, int ac, char **av, fluid_ostream_t out)
{
- FLUID_ENTRY_COMMAND(data);
- int nr;
-
- if(ac < 1)
- {
- fluid_ostream_printf(out, "cho_set_nr: too few arguments.\n");
- return FLUID_FAILED;
- }
-
- fluid_ostream_printf(out, "cho_set_nr is deprecated! Use 'set synth.chorus.nr %s' instead.\n", av[0]);
-
- nr = atoi(av[0]);
- fluid_synth_set_chorus_nr(handler->synth, nr);
- return FLUID_OK;
+ return fluid_handle_chorus_command(data, ac, av, out, FLUID_CHORUS_NR);
}
/* Purpose:
- * Response to 'chorus_setlevel' command */
+ * Response to 'cho_setlevel' command
+ * Example: cho_set_level 1 3
+ * load level 3 in the chorus fx group at index 1.
+ */
int
fluid_handle_choruslevel(void *data, int ac, char **av, fluid_ostream_t out)
{
- FLUID_ENTRY_COMMAND(data);
- fluid_real_t level;
-
- if(ac < 1)
- {
- fluid_ostream_printf(out, "cho_set_level: too few arguments.\n");
- return FLUID_FAILED;
- }
-
- fluid_ostream_printf(out, "cho_set_level is deprecated! Use 'set synth.chorus.level %s' instead.\n", av[0]);
-
- level = atof(av[0]);
- fluid_synth_set_chorus_level(handler->synth, level);
- return FLUID_OK;
-
+ return fluid_handle_chorus_command(data, ac, av, out, FLUID_CHORUS_LEVEL);
}
/* Purpose:
- * Response to 'chorus_setspeed' command */
+ * Response to 'cho_setspeed' command
+ * Example: cho_set_speed 1 0.1
+ * load speed 0.1 in the chorus fx group at index 1.
+ */
int
fluid_handle_chorusspeed(void *data, int ac, char **av, fluid_ostream_t out)
{
- FLUID_ENTRY_COMMAND(data);
- fluid_real_t speed;
-
- if(ac < 1)
- {
- fluid_ostream_printf(out, "cho_set_speed: too few arguments.\n");
- return FLUID_FAILED;
- }
-
- fluid_ostream_printf(out, "cho_set_speed is deprecated! Use 'set synth.chorus.speed %s' instead.\n", av[0]);
-
- speed = atof(av[0]);
- fluid_synth_set_chorus_speed(handler->synth, speed);
- return FLUID_OK;
+ return fluid_handle_chorus_command(data, ac, av, out, FLUID_CHORUS_SPEED);
}
/* Purpose:
- * Response to 'chorus_setdepth' command */
+ * Response to 'cho_setdepth' command
+ * Example: cho_set_depth 1 0.3
+ * load depth 0.3 in the chorus fx group at index 1.
+ */
int
fluid_handle_chorusdepth(void *data, int ac, char **av, fluid_ostream_t out)
{
- FLUID_ENTRY_COMMAND(data);
- fluid_real_t depth;
-
- if(ac < 1)
- {
- fluid_ostream_printf(out, "cho_set_depth: too few arguments.\n");
- return FLUID_FAILED;
- }
-
- fluid_ostream_printf(out, "cho_set_depth is deprecated! Use 'set synth.chorus.depth %s' instead.\n", av[0]);
-
- depth = atof(av[0]);
- fluid_synth_set_chorus_depth(handler->synth, depth);
- return FLUID_OK;
+ return fluid_handle_chorus_command(data, ac, av, out, FLUID_CHORUS_DEPTH);
}
+/* Purpose:
+ * Set all chorus units on
+ */
int
fluid_handle_chorus(void *data, int ac, char **av, fluid_ostream_t out)
{
- FLUID_ENTRY_COMMAND(data);
-
- if(ac < 1)
- {
- fluid_ostream_printf(out, "chorus: too few arguments\n");
- return FLUID_FAILED;
- }
-
- fluid_ostream_printf(out, "chorus is deprecated! Use 'set synth.chorus.active %s' instead.\n", av[0]);
-
- if((FLUID_STRCMP(av[0], "0") == 0) || (FLUID_STRCMP(av[0], "off") == 0))
- {
- fluid_synth_set_chorus_on(handler->synth, 0);
- }
- else if((FLUID_STRCMP(av[0], "1") == 0) || (FLUID_STRCMP(av[0], "on") == 0))
- {
- fluid_synth_set_chorus_on(handler->synth, 1);
- }
- else
- {
- fluid_ostream_printf(out, "chorus: invalid arguments %s [0|1|on|off]", av[0]);
- return FLUID_FAILED;
- }
-
- return FLUID_OK;
+ return fluid_handle_reverb_chorus_on_command(data, ac, av, out, CHORUS_ON_CDE);
}
/* Purpose:
@@ -1880,7 +1970,7 @@ fluid_handle_set(void *data, int ac, char **av, fluid_ostream_t out)
{
fluid_ostream_printf(out, "set: Value out of range. Try 'info %s' for valid ranges\n", av[0]);
}
-
+
if(!fluid_settings_is_realtime(handler->synth->settings, av[0]))
{
fluid_ostream_printf(out, "Warning: '%s' is not a realtime setting, changes won't take effect.\n", av[0]);
@@ -2474,7 +2564,8 @@ int fluid_handle_router_par2(void *data, int ac, char **av, fluid_ostream_t out)
/** commands Poly/mono mode *************************************************/
-static const char *const mode_name[] = {
+static const char *const mode_name[] =
+{
"poly omni on (0)", "mono omni on (1)",
"poly omni off(2)", "mono omni off(3)"
};
@@ -2552,7 +2643,7 @@ static int get_channel_mode_num(char *name)
{
/* argument names for channel mode parameter (see resetbasicchannels and
setbasicchannels commands*/
- static const char * const name_channel_mode [FLUID_CHANNEL_MODE_LAST] =
+ static const char *const name_channel_mode [FLUID_CHANNEL_MODE_LAST] =
{"poly_omnion", "mono_omnion", "poly_omnioff", "mono_omnioff"};
int i;
diff --git a/src/rvoice/fluid_chorus.h b/src/rvoice/fluid_chorus.h
index affc777d..c6d247fa 100644
--- a/src/rvoice/fluid_chorus.h
+++ b/src/rvoice/fluid_chorus.h
@@ -27,14 +27,28 @@
typedef struct _fluid_chorus_t fluid_chorus_t;
+/* enum describing each chorus parameter */
+enum fluid_chorus_param
+{
+ FLUID_CHORUS_NR, /**< number of delay line */
+ FLUID_CHORUS_LEVEL, /**< output level */
+ FLUID_CHORUS_SPEED, /**< lfo frequency */
+ FLUID_CHORUS_DEPTH, /**< modulation depth */
+ FLUID_CHORUS_TYPE, /**< type of waveform */
+ FLUID_CHORUS_PARAM_LAST /* number of enum fluid_chorus_param */
+};
+
+/* return a bit flag from param: 2^param */
+#define FLUID_CHORPARAM_TO_SETFLAG(param) (1 << param)
+
/** Flags for fluid_chorus_set() */
typedef enum
{
- FLUID_CHORUS_SET_NR = 1 << 0,
- FLUID_CHORUS_SET_LEVEL = 1 << 1,
- FLUID_CHORUS_SET_SPEED = 1 << 2,
- FLUID_CHORUS_SET_DEPTH = 1 << 3,
- FLUID_CHORUS_SET_TYPE = 1 << 4,
+ FLUID_CHORUS_SET_NR = FLUID_CHORPARAM_TO_SETFLAG(FLUID_CHORUS_NR),
+ FLUID_CHORUS_SET_LEVEL = FLUID_CHORPARAM_TO_SETFLAG(FLUID_CHORUS_LEVEL),
+ FLUID_CHORUS_SET_SPEED = FLUID_CHORPARAM_TO_SETFLAG(FLUID_CHORUS_SPEED),
+ FLUID_CHORUS_SET_DEPTH = FLUID_CHORPARAM_TO_SETFLAG(FLUID_CHORUS_DEPTH),
+ FLUID_CHORUS_SET_TYPE = FLUID_CHORPARAM_TO_SETFLAG(FLUID_CHORUS_TYPE),
/** Value for fluid_chorus_set() which sets all chorus parameters. */
FLUID_CHORUS_SET_ALL = FLUID_CHORUS_SET_NR
diff --git a/src/rvoice/fluid_rev.h b/src/rvoice/fluid_rev.h
index 597467bb..35c9cf66 100644
--- a/src/rvoice/fluid_rev.h
+++ b/src/rvoice/fluid_rev.h
@@ -26,14 +26,26 @@
typedef struct _fluid_revmodel_t fluid_revmodel_t;
+/* enum describing each reverb parameter */
+enum fluid_reverb_param
+{
+ FLUID_REVERB_ROOMSIZE, /**< reverb time */
+ FLUID_REVERB_DAMP, /**< high frequency damping */
+ FLUID_REVERB_WIDTH, /**< stereo width */
+ FLUID_REVERB_LEVEL, /**< output level */
+ FLUID_REVERB_PARAM_LAST /* number of enum fluid_reverb_param */
+};
+
+/* return a bit flag from param: 2^param */
+#define FLUID_REVPARAM_TO_SETFLAG(param) (1 << param)
/** Flags for fluid_revmodel_set() */
typedef enum
{
- FLUID_REVMODEL_SET_ROOMSIZE = 1 << 0,
- FLUID_REVMODEL_SET_DAMPING = 1 << 1,
- FLUID_REVMODEL_SET_WIDTH = 1 << 2,
- FLUID_REVMODEL_SET_LEVEL = 1 << 3,
+ FLUID_REVMODEL_SET_ROOMSIZE = FLUID_REVPARAM_TO_SETFLAG(FLUID_REVERB_ROOMSIZE),
+ FLUID_REVMODEL_SET_DAMPING = FLUID_REVPARAM_TO_SETFLAG(FLUID_REVERB_DAMP),
+ FLUID_REVMODEL_SET_WIDTH = FLUID_REVPARAM_TO_SETFLAG(FLUID_REVERB_WIDTH),
+ FLUID_REVMODEL_SET_LEVEL = FLUID_REVPARAM_TO_SETFLAG(FLUID_REVERB_LEVEL),
/** Value for fluid_revmodel_set() which sets all reverb parameters. */
FLUID_REVMODEL_SET_ALL = FLUID_REVMODEL_SET_LEVEL
diff --git a/src/rvoice/fluid_rvoice_mixer.c b/src/rvoice/fluid_rvoice_mixer.c
index 1a3f685a..01b69671 100644
--- a/src/rvoice/fluid_rvoice_mixer.c
+++ b/src/rvoice/fluid_rvoice_mixer.c
@@ -77,7 +77,14 @@ typedef struct _fluid_mixer_fx_t fluid_mixer_fx_t;
struct _fluid_mixer_fx_t
{
fluid_revmodel_t *reverb; /**< Reverb unit */
+ /* reverb shadow parameters here will be returned if queried */
+ double reverb_param[FLUID_REVERB_PARAM_LAST];
+ int reverb_on; /* reverb on/off */
+
fluid_chorus_t *chorus; /**< Chorus unit */
+ /* chorus shadow parameters here will be returned if queried */
+ double chorus_param[FLUID_CHORUS_PARAM_LAST];
+ int chorus_on; /* chorus on/off */
};
struct _fluid_rvoice_mixer_t
@@ -128,6 +135,9 @@ fluid_rvoice_mixer_process_fx(fluid_rvoice_mixer_t *mixer, int current_blockcoun
int dry_count = mixer->buffers.buf_count; /* dry buffers count */
int mix_fx_to_out = mixer->mix_fx_to_out; /* get mix_fx_to_out mode */
int dry_idx = 0; /* dry buffer index */
+ int buf_idx; /* buffer index */
+ int samp_idx; /* sample index in buffer */
+ int sample_count; /* sample count to process */
void (*reverb_process_func)(fluid_revmodel_t *rev, const fluid_real_t *in, fluid_real_t *left_out, fluid_real_t *right_out);
void (*chorus_process_func)(fluid_chorus_t *chorus, const fluid_real_t *in, fluid_real_t *left_out, fluid_real_t *right_out);
@@ -166,9 +176,14 @@ fluid_rvoice_mixer_process_fx(fluid_rvoice_mixer_t *mixer, int current_blockcoun
{
for(f = 0; f < mixer->fx_units; f++)
{
- int buf_idx = f * fx_channels_per_unit + SYNTH_REVERB_CHANNEL;
- int samp_idx = buf_idx * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE;
- int sample_count = current_blockcount * FLUID_BUFSIZE;
+ if(!mixer->fx[f].reverb_on)
+ {
+ continue; /* this reverb unit is disabled */
+ }
+
+ buf_idx = f * fx_channels_per_unit + SYNTH_REVERB_CHANNEL;
+ samp_idx = buf_idx * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE;
+ sample_count = current_blockcount * FLUID_BUFSIZE;
/* in mix mode, map fx out_rev at index f to a dry buffer at index dry_idx */
if(mix_fx_to_out)
@@ -194,10 +209,15 @@ fluid_rvoice_mixer_process_fx(fluid_rvoice_mixer_t *mixer, int current_blockcoun
{
for(f = 0; f < mixer->fx_units; f++)
{
- int buf_idx = f * fx_channels_per_unit + SYNTH_CHORUS_CHANNEL;
- int samp_idx = buf_idx * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE;
- int sample_count = current_blockcount * FLUID_BUFSIZE;
-
+ if(!mixer->fx[f].chorus_on)
+ {
+ continue; /* this chorus unit is disabled */
+ }
+
+ buf_idx = f * fx_channels_per_unit + SYNTH_CHORUS_CHANNEL;
+ samp_idx = buf_idx * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE;
+ sample_count = current_blockcount * FLUID_BUFSIZE;
+
/* in mix mode, map fx out_ch at index f to a dry buffer at index dry_idx */
if(mix_fx_to_out)
{
@@ -260,18 +280,18 @@ fluid_mixer_buffers_prepare(fluid_mixer_buffers_t *buffers, fluid_real_t **outbu
for(i = 0; i < buffers->mixer->fx_units; i++)
{
int fx_idx = i * fx_channels_per_unit;
-
+
outbufs[offset + fx_idx + SYNTH_REVERB_CHANNEL] =
(with_reverb)
? &base_ptr[(fx_idx + SYNTH_REVERB_CHANNEL) * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT]
: NULL;
-
+
outbufs[offset + fx_idx + SYNTH_CHORUS_CHANNEL] =
(with_chorus)
? &base_ptr[(fx_idx + SYNTH_CHORUS_CHANNEL) * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT]
: NULL;
}
-
+
/* The output associated with a MIDI channel is wrapped around
* using the number of audio groups as modulo divider. This is
* typically the number of output channels on the 'sound card',
@@ -421,6 +441,7 @@ fluid_rvoice_buffers_mix(fluid_rvoice_buffers_t *buffers,
/* mixdown sample_count samples in the current buffer buf
Note, that this loop could be unrolled by FLUID_BUFSIZE elements */
#pragma omp simd aligned(dsp_buf,buf:FLUID_DEFAULT_ALIGNMENT)
+
for(dsp_i = 0; dsp_i < sample_count; dsp_i++)
{
// Index by blocks (not by samples) to let the compiler know that we always start accessing
@@ -449,20 +470,22 @@ fluid_mixer_buffers_render_one(fluid_mixer_buffers_t *buffers,
{
/* render one block in src_buf */
int s = fluid_rvoice_write(rvoice, &src_buf[FLUID_BUFSIZE * i]);
+
if(s == -1)
{
/* the voice is silent, mix back all the previously rendered sound */
fluid_rvoice_buffers_mix(&rvoice->buffers, src_buf, last_block_mixed,
- total_samples - (last_block_mixed*FLUID_BUFSIZE),
+ total_samples - (last_block_mixed * FLUID_BUFSIZE),
dest_bufs, dest_bufcount);
- last_block_mixed = i+1; /* future block start index to mix from */
+ last_block_mixed = i + 1; /* future block start index to mix from */
total_samples += FLUID_BUFSIZE; /* accumulate samples count rendered */
}
else
{
/* the voice wasn't quiet. Some samples have been rendered [0..FLUID_BUFSIZE] */
total_samples += s;
+
if(s < FLUID_BUFSIZE)
{
/* voice has finished */
@@ -473,7 +496,7 @@ fluid_mixer_buffers_render_one(fluid_mixer_buffers_t *buffers,
/* Now mix the remaining blocks from last_block_mixed to total_sample */
fluid_rvoice_buffers_mix(&rvoice->buffers, src_buf, last_block_mixed,
- total_samples - (last_block_mixed*FLUID_BUFSIZE),
+ total_samples - (last_block_mixed * FLUID_BUFSIZE),
dest_bufs, dest_bufcount);
if(total_samples < blockcount * FLUID_BUFSIZE)
@@ -692,6 +715,7 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_samplerate)
fluid_real_t samplerate = param[1].real; // because fluid_synth_update_mixer() puts real into arg2
int i;
+
for(i = 0; i < mixer->fx_units; i++)
{
if(mixer->fx[i].chorus)
@@ -751,6 +775,7 @@ new_fluid_rvoice_mixer(int buf_count, int fx_buf_count, int fx_units,
/* allocate the reverb module */
mixer->fx = FLUID_ARRAY(fluid_mixer_fx_t, fx_units);
+
if(mixer->fx == NULL)
{
FLUID_LOG(FLUID_ERR, "Out of memory");
@@ -819,7 +844,7 @@ fluid_mixer_buffers_free(fluid_mixer_buffers_t *buffers)
void delete_fluid_rvoice_mixer(fluid_rvoice_mixer_t *mixer)
{
int i;
-
+
fluid_return_if_fail(mixer != NULL);
#if ENABLE_MIXER_THREADS
@@ -848,7 +873,7 @@ void delete_fluid_rvoice_mixer(fluid_rvoice_mixer_t *mixer)
#endif
fluid_mixer_buffers_free(&mixer->buffers);
-
+
for(i = 0; i < mixer->fx_units; i++)
{
if(mixer->fx[i].reverb)
@@ -867,7 +892,6 @@ void delete_fluid_rvoice_mixer(fluid_rvoice_mixer_t *mixer)
FLUID_FREE(mixer);
}
-
#ifdef LADSPA
/**
* Set a LADSPS fx instance to be used by the mixer and assign the mixer buffers
@@ -911,6 +935,130 @@ void fluid_rvoice_mixer_set_ladspa(fluid_rvoice_mixer_t *mixer,
}
#endif
+/**
+ * set one or more reverb shadow parameters for one fx group.
+ * These parameters will be returned if queried.
+ * (see fluid_rvoice_mixer_reverb_get_param())
+ *
+ * @param mixer that contains all fx units.
+ * @param fx_group index of the fx group to which parameters must be set.
+ * must be in the range [-1..mixer->fx_units[. If -1 the changes are applied to
+ * all fx units.
+ * @param set Flags indicating which parameters should be set (#fluid_revmodel_set_t)
+ * @param values table of parameters values.
+ */
+void
+fluid_rvoice_mixer_set_reverb_full(const fluid_rvoice_mixer_t *mixer,
+ int fx_group, int set, const double values[])
+{
+ fluid_mixer_fx_t *fx = mixer->fx;
+ int nr_units = mixer->fx_units;
+
+ if(fx_group >= 0) /* apply parameters to this fx group only */
+ {
+ nr_units = fx_group + 1;
+ }
+ else /* apply parameters to all fx groups */
+ {
+ fx_group = 0;
+ }
+
+ for(; fx_group < nr_units; fx_group++)
+ {
+ int param;
+
+ for(param = 0; param < FLUID_REVERB_PARAM_LAST; param++)
+ {
+ if(set & FLUID_REVPARAM_TO_SETFLAG(param))
+ {
+ fx[fx_group].reverb_param[param] = values[param];
+ }
+ }
+ }
+}
+
+/**
+ * get one reverb shadow parameter for one fx group.
+ * (see fluid_rvoice_mixer_set_reverb_full())
+ *
+ * @param mixer that contains all fx group units.
+ * @param fx_group index of the fx group to get parameter from.
+ * must be in the range [0..mixer->fx_units[.
+ * @param enum indicating the parameter to get.
+ * FLUID_REVERB_ROOMSIZE, reverb room size value.
+ * FLUID_REVERB_DAMP, reverb damping value.
+ * FLUID_REVERB_WIDTH, reverb width value.
+ * FLUID_REVERB_LEVEL, reverb level value.
+ * @return value.
+ */
+double
+fluid_rvoice_mixer_reverb_get_param(const fluid_rvoice_mixer_t *mixer,
+ int fx_group, int param)
+{
+ return mixer->fx[fx_group].reverb_param[param];
+}
+
+/**
+ * set one or more chorus shadow parameters for one fx group.
+ * These parameters will be returned if queried.
+ * (see fluid_rvoice_mixer_chorus_get_param())
+ *
+ * @param mixer that contains all fx units.
+ * @param fx_group index of the fx group to which parameters must be set.
+ * must be in the range [-1..mixer->fx_units[. If -1 the changes are applied
+ * to all fx group.
+ * Keep in mind, that the needed CPU time is proportional to 'nr'.
+ * @param set Flags indicating which parameters to set (#fluid_chorus_set_t)
+ * @param values table of pararameters.
+ */
+void
+fluid_rvoice_mixer_set_chorus_full(const fluid_rvoice_mixer_t *mixer,
+ int fx_group, int set, const double values[])
+{
+ fluid_mixer_fx_t *fx = mixer->fx;
+ int nr_units = mixer->fx_units;
+
+ if(fx_group >= 0) /* apply parameters to this group fx only */
+ {
+ nr_units = fx_group + 1;
+ }
+ else /* apply parameters to all fx units*/
+ {
+ fx_group = 0;
+ }
+
+ for(; fx_group < nr_units; fx_group++)
+ {
+ int param;
+
+ for(param = 0; param < FLUID_CHORUS_PARAM_LAST; param++)
+ {
+ if(set & FLUID_CHORPARAM_TO_SETFLAG(param))
+ {
+ fx[fx_group].chorus_param[param] = values[param];
+ }
+ }
+ }
+}
+
+/**
+ * get one chorus shadow parameter for one fx group.
+ * (see fluid_rvoice_mixer_set_chorus_full())
+ *
+ * @param mixer that contains all fx groups units.
+ * @param fx_group index of the fx group to get parameter from.
+ * must be in the range [0..mixer->fx_units[.
+ * @param get Flags indicating which parameter to get (#fluid_chorus_set_t)
+ * @return the parameter value (0.0 is returned if error)
+ */
+double
+fluid_rvoice_mixer_chorus_get_param(const fluid_rvoice_mixer_t *mixer,
+ int fx_group, int param)
+{
+ return mixer->fx[fx_group].chorus_param[param];
+}
+
+/* @deprecated: use fluid_rvoice_mixer_reverb_enable instead */
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_reverb_enabled)
{
fluid_rvoice_mixer_t *mixer = obj;
@@ -919,6 +1067,43 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_reverb_enabled)
mixer->with_reverb = on;
}
+DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_reverb_enable)
+{
+ fluid_rvoice_mixer_t *mixer = obj;
+ int fx_group = param[0].i; /* reverb fx group index */
+ int on = param[1].i; /* on/off */
+
+ int nr_units = mixer->fx_units;
+
+ /* does on/off must be applied only to fx group at index fx_group ? */
+ if(fx_group >= 0)
+ {
+ mixer->fx[fx_group].reverb_on = on;
+ }
+ /* on/off must be applied to all fx groups */
+ else
+ {
+ for(fx_group = 0; fx_group < nr_units; fx_group++)
+ {
+ mixer->fx[fx_group].reverb_on = on;
+ }
+ }
+
+ /* set with_reverb if at least one reverb unit is on */
+ for(fx_group = 0; fx_group < nr_units; fx_group++)
+ {
+ on = mixer->fx[fx_group].reverb_on;
+
+ if(on)
+ {
+ break;
+ }
+ }
+
+ mixer->with_reverb = on;
+}
+
+/* @deprecated: use fluid_rvoice_mixer_chorus_enable instead */
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_chorus_enabled)
{
fluid_rvoice_mixer_t *mixer = obj;
@@ -926,6 +1111,42 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_chorus_enabled)
mixer->with_chorus = on;
}
+DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_chorus_enable)
+{
+ fluid_rvoice_mixer_t *mixer = obj;
+ int fx_group = param[0].i; /* chorus fx group index */
+ int on = param[1].i; /* on/off */
+
+ int nr_units = mixer->fx_units;
+
+ /* does on/off must be applied only to fx group at index fx_group ? */
+ if(fx_group >= 0)
+ {
+ mixer->fx[fx_group].chorus_on = on;
+ }
+ /* on/off must be applied to all fx groups */
+ else
+ {
+ for(fx_group = 0; fx_group < nr_units; fx_group++)
+ {
+ mixer->fx[fx_group].chorus_on = on;
+ }
+ }
+
+ /* set with_chorus if at least one chorus unit is on */
+ for(fx_group = 0; fx_group < nr_units; fx_group++)
+ {
+ on = mixer->fx[fx_group].chorus_on;
+
+ if(on)
+ {
+ break;
+ }
+ }
+
+ mixer->with_chorus = on;
+}
+
void fluid_rvoice_mixer_set_mix_fx(fluid_rvoice_mixer_t *mixer, int on)
{
mixer->mix_fx_to_out = on;
@@ -934,33 +1155,57 @@ void fluid_rvoice_mixer_set_mix_fx(fluid_rvoice_mixer_t *mixer, int on)
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_chorus_params)
{
fluid_rvoice_mixer_t *mixer = obj;
- int set = param[0].i;
- int nr = param[1].i;
- fluid_real_t level = param[2].real;
- fluid_real_t speed = param[3].real;
- fluid_real_t depth_ms = param[4].real;
- int type = param[5].i;
+ int i = param[0].i;
+ int set = param[1].i;
+ int nr = param[2].i;
+ fluid_real_t level = param[3].real;
+ fluid_real_t speed = param[4].real;
+ fluid_real_t depth_ms = param[5].real;
+ int type = param[6].i;
- int i;
- for(i = 0; i < mixer->fx_units; i++)
+ int nr_units = mixer->fx_units;
+
+ /* does parameters must be applied only to fx group i ? */
+ if(i >= 0)
{
- fluid_chorus_set(mixer->fx[i].chorus, set, nr, level, speed, depth_ms, type);
+ nr_units = i + 1;
+ }
+ else
+ {
+ i = 0; /* parameters must be applied to all fx groups */
+ }
+
+ while(i < nr_units)
+ {
+ fluid_chorus_set(mixer->fx[i++].chorus, set, nr, level, speed, depth_ms, type);
}
}
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_reverb_params)
{
fluid_rvoice_mixer_t *mixer = obj;
- int set = param[0].i;
- fluid_real_t roomsize = param[1].real;
- fluid_real_t damping = param[2].real;
- fluid_real_t width = param[3].real;
- fluid_real_t level = param[4].real;
+ int i = param[0].i; /* fx group index */
+ int set = param[1].i;
+ fluid_real_t roomsize = param[2].real;
+ fluid_real_t damping = param[3].real;
+ fluid_real_t width = param[4].real;
+ fluid_real_t level = param[5].real;
- int i;
- for(i = 0; i < mixer->fx_units; i++)
+ int nr_units = mixer->fx_units;
+
+ /* does parameters change should be applied only to fx group i ? */
+ if(i >= 0)
{
- fluid_revmodel_set(mixer->fx[i].reverb, set, roomsize, damping, width, level);
+ nr_units = i + 1; /* parameters change must be applied to fx groups i */
+ }
+ else
+ {
+ i = 0; /* parameters change must be applied to all fx groups */
+ }
+
+ while(i < nr_units)
+ {
+ fluid_revmodel_set(mixer->fx[i++].reverb, set, roomsize, damping, width, level);
}
}
@@ -968,6 +1213,7 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_reset_reverb)
{
fluid_rvoice_mixer_t *mixer = obj;
int i;
+
for(i = 0; i < mixer->fx_units; i++)
{
fluid_revmodel_reset(mixer->fx[i].reverb);
@@ -978,6 +1224,7 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_reset_chorus)
{
fluid_rvoice_mixer_t *mixer = obj;
int i;
+
for(i = 0; i < mixer->fx_units; i++)
{
fluid_chorus_reset(mixer->fx[i].chorus);
diff --git a/src/rvoice/fluid_rvoice_mixer.h b/src/rvoice/fluid_rvoice_mixer.h
index acc3fb02..63a456ce 100644
--- a/src/rvoice/fluid_rvoice_mixer.h
+++ b/src/rvoice/fluid_rvoice_mixer.h
@@ -43,12 +43,33 @@ fluid_rvoice_mixer_t *new_fluid_rvoice_mixer(int buf_count, int fx_buf_count, in
void delete_fluid_rvoice_mixer(fluid_rvoice_mixer_t *);
+void
+fluid_rvoice_mixer_set_reverb_full(const fluid_rvoice_mixer_t *mixer,
+ int fx_group, int set, const double values[]);
+
+double
+fluid_rvoice_mixer_reverb_get_param(const fluid_rvoice_mixer_t *mixer,
+ int fx_group, int param);
+void
+fluid_rvoice_mixer_set_chorus_full(const fluid_rvoice_mixer_t *mixer,
+ int fx_group, int set, const double values[]);
+double
+fluid_rvoice_mixer_chorus_get_param(const fluid_rvoice_mixer_t *mixer,
+ int fx_group, int param);
+
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_add_voice);
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_samplerate);
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_polyphony);
+
+/* @deprecated */
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_chorus_enabled);
+/* @deprecated */
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_reverb_enabled);
+
+DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_reverb_enable);
+DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_chorus_enable);
+
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_chorus_params);
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_reverb_params);
diff --git a/src/synth/fluid_synth.c b/src/synth/fluid_synth.c
index bf3ac21a..f45da2b7 100644
--- a/src/synth/fluid_synth.c
+++ b/src/synth/fluid_synth.c
@@ -78,6 +78,11 @@ static int fluid_synth_update_pitch_bend_LOCAL(fluid_synth_t *synth, int chan);
static int fluid_synth_update_pitch_wheel_sens_LOCAL(fluid_synth_t *synth, int chan);
static int fluid_synth_set_preset(fluid_synth_t *synth, int chan,
fluid_preset_t *preset);
+static int fluid_synth_reverb_get_param(fluid_synth_t *synth, int fx_group,
+ int param, double *value);
+static int fluid_synth_chorus_get_param(fluid_synth_t *synth, int fx_group,
+ int param, double *value);
+
static fluid_preset_t *
fluid_synth_get_preset(fluid_synth_t *synth, int sfontnum,
int banknum, int prognum);
@@ -926,44 +931,35 @@ new_fluid_synth(fluid_settings_t *settings)
fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_polyphony,
synth->polyphony, 0.0f);
- fluid_synth_set_reverb_on(synth, synth->with_reverb);
- fluid_synth_set_chorus_on(synth, synth->with_chorus);
+ fluid_synth_reverb_on(synth, -1, synth->with_reverb);
+ fluid_synth_chorus_on(synth, -1, synth->with_chorus);
synth->cur = FLUID_BUFSIZE;
synth->curmax = 0;
synth->dither_index = 0;
{
- double room, damp, width, level;
+ double values[FLUID_REVERB_PARAM_LAST];
- fluid_settings_getnum(settings, "synth.reverb.room-size", &room);
- fluid_settings_getnum(settings, "synth.reverb.damp", &damp);
- fluid_settings_getnum(settings, "synth.reverb.width", &width);
- fluid_settings_getnum(settings, "synth.reverb.level", &level);
+ fluid_settings_getnum(settings, "synth.reverb.room-size", &values[FLUID_REVERB_ROOMSIZE]);
+ fluid_settings_getnum(settings, "synth.reverb.damp", &values[FLUID_REVERB_DAMP]);
+ fluid_settings_getnum(settings, "synth.reverb.width", &values[FLUID_REVERB_WIDTH]);
+ fluid_settings_getnum(settings, "synth.reverb.level", &values[FLUID_REVERB_LEVEL]);
- fluid_synth_set_reverb_full(synth,
- FLUID_REVMODEL_SET_ALL,
- room,
- damp,
- width,
- level);
+ fluid_synth_set_reverb_full(synth, -1, FLUID_REVMODEL_SET_ALL, values);
}
{
- double level, speed, depth;
+ double values[FLUID_CHORUS_PARAM_LAST];
fluid_settings_getint(settings, "synth.chorus.nr", &i);
- fluid_settings_getnum(settings, "synth.chorus.level", &level);
- fluid_settings_getnum(settings, "synth.chorus.speed", &speed);
- fluid_settings_getnum(settings, "synth.chorus.depth", &depth);
+ values[FLUID_CHORUS_NR] = (double)i;
+ fluid_settings_getnum(settings, "synth.chorus.level", &values[FLUID_CHORUS_LEVEL]);
+ fluid_settings_getnum(settings, "synth.chorus.speed", &values[FLUID_CHORUS_SPEED]);
+ fluid_settings_getnum(settings, "synth.chorus.depth", &values[FLUID_CHORUS_DEPTH]);
+ values[FLUID_CHORUS_TYPE] = (double)FLUID_CHORUS_DEFAULT_TYPE;
- fluid_synth_set_chorus_full(synth,
- FLUID_CHORUS_SET_ALL,
- i,
- level,
- speed,
- depth,
- FLUID_CHORUS_DEFAULT_TYPE);
+ fluid_synth_set_chorus_full(synth, -1, FLUID_CHORUS_SET_ALL, values);
}
@@ -4649,31 +4645,31 @@ static void fluid_synth_handle_reverb_chorus_num(void *data, const char *name, d
if(FLUID_STRCMP(name, "synth.reverb.room-size") == 0)
{
- fluid_synth_set_reverb_roomsize(synth, value);
+ fluid_synth_reverb_set_param(synth, -1, FLUID_REVERB_ROOMSIZE, value);
}
else if(FLUID_STRCMP(name, "synth.reverb.damp") == 0)
{
- fluid_synth_set_reverb_damp(synth, value);
+ fluid_synth_reverb_set_param(synth, -1, FLUID_REVERB_DAMP, value);
}
else if(FLUID_STRCMP(name, "synth.reverb.width") == 0)
{
- fluid_synth_set_reverb_width(synth, value);
+ fluid_synth_reverb_set_param(synth, -1, FLUID_REVERB_WIDTH, value);
}
else if(FLUID_STRCMP(name, "synth.reverb.level") == 0)
{
- fluid_synth_set_reverb_level(synth, value);
+ fluid_synth_reverb_set_param(synth, -1, FLUID_REVERB_LEVEL, value);
}
else if(FLUID_STRCMP(name, "synth.chorus.depth") == 0)
{
- fluid_synth_set_chorus_depth(synth, value);
+ fluid_synth_chorus_set_param(synth, -1, FLUID_CHORUS_DEPTH, value);
}
else if(FLUID_STRCMP(name, "synth.chorus.speed") == 0)
{
- fluid_synth_set_chorus_speed(synth, value);
+ fluid_synth_chorus_set_param(synth, -1, FLUID_CHORUS_SPEED, value);
}
else if(FLUID_STRCMP(name, "synth.chorus.level") == 0)
{
- fluid_synth_set_chorus_level(synth, value);
+ fluid_synth_chorus_set_param(synth, -1, FLUID_CHORUS_LEVEL, value);
}
}
@@ -4687,15 +4683,15 @@ static void fluid_synth_handle_reverb_chorus_int(void *data, const char *name, i
if(FLUID_STRCMP(name, "synth.reverb.active") == 0)
{
- fluid_synth_set_reverb_on(synth, value);
+ fluid_synth_reverb_on(synth, -1, value);
}
else if(FLUID_STRCMP(name, "synth.chorus.active") == 0)
{
- fluid_synth_set_chorus_on(synth, value);
+ fluid_synth_chorus_on(synth, -1, value);
}
else if(FLUID_STRCMP(name, "synth.chorus.nr") == 0)
{
- fluid_synth_set_chorus_nr(synth, value);
+ fluid_synth_chorus_set_param(synth, -1, FLUID_CHORUS_NR, (double)value);
}
}
@@ -5464,13 +5460,13 @@ fluid_synth_get_voicelist(fluid_synth_t *synth, fluid_voice_t *buf[], int bufsiz
/**
* Enable or disable reverb effect.
* @param synth FluidSynth instance
- * @param on TRUE to enable reverb, FALSE to disable
+ * @param on TRUE to enable chorus, FALSE to disable
+ * @deprecated Use fluid_synth_reverb_on() instead.
*/
void
fluid_synth_set_reverb_on(fluid_synth_t *synth, int on)
{
fluid_return_if_fail(synth != NULL);
-
fluid_synth_api_enter(synth);
synth->with_reverb = (on != 0);
@@ -5479,6 +5475,44 @@ fluid_synth_set_reverb_on(fluid_synth_t *synth, int on)
fluid_synth_api_exit(synth);
}
+/**
+ * Enable or disable reverb on one fx group unit.
+ * @param synth FluidSynth instance
+ * @param fx_group Index of the fx group.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter common to all fx groups is fetched.
+ * @param on TRUE to enable reverb, FALSE to disable
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise
+ */
+int
+fluid_synth_reverb_on(fluid_synth_t *synth, int fx_group, int on)
+{
+ int ret;
+ fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
+ fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
+
+ fluid_synth_api_enter(synth);
+
+ if(fx_group < -1 || fx_group >= synth->effects_groups)
+ {
+ FLUID_API_RETURN(FLUID_FAILED);
+ }
+
+ if(fx_group < 0 )
+ {
+ synth->with_reverb = (on != 0);
+ }
+
+ param[0].i = fx_group;
+ param[1].i = on;
+ ret = fluid_rvoice_eventhandler_push(synth->eventhandler,
+ fluid_rvoice_mixer_reverb_enable,
+ synth->eventhandler->mixer,
+ param);
+
+ FLUID_API_RETURN(ret);
+}
+
/**
* Activate a reverb preset.
* @param synth FluidSynth instance
@@ -5490,19 +5524,23 @@ fluid_synth_set_reverb_on(fluid_synth_t *synth, int on)
int
fluid_synth_set_reverb_preset(fluid_synth_t *synth, unsigned int num)
{
+ double values[FLUID_REVERB_PARAM_LAST];
+
fluid_return_val_if_fail(
num < FLUID_N_ELEMENTS(revmodel_preset),
FLUID_FAILED
);
- fluid_synth_set_reverb(synth, revmodel_preset[num].roomsize,
- revmodel_preset[num].damp, revmodel_preset[num].width,
- revmodel_preset[num].level);
+ values[FLUID_REVERB_ROOMSIZE] = revmodel_preset[num].roomsize;
+ values[FLUID_REVERB_DAMP] = revmodel_preset[num].damp;
+ values[FLUID_REVERB_WIDTH] = revmodel_preset[num].width;
+ values[FLUID_REVERB_LEVEL] = revmodel_preset[num].level;
+ fluid_synth_set_reverb_full(synth, -1, FLUID_REVMODEL_SET_ALL, values);
return FLUID_OK;
}
/**
- * Set reverb parameters.
+ * Set reverb parameters to all groups.
*
* @param synth FluidSynth instance
* @param roomsize Reverb room size value (0.0-1.0)
@@ -5510,195 +5548,391 @@ fluid_synth_set_reverb_preset(fluid_synth_t *synth, unsigned int num)
* @param width Reverb width value (0.0-100.0)
* @param level Reverb level value (0.0-1.0)
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
- *
- * @note Not realtime safe and therefore should not be called from synthesis
- * context at the risk of stalling audio output.
+ * @deprecated Use the individual reverb setter functions in new code instead.
*/
int
fluid_synth_set_reverb(fluid_synth_t *synth, double roomsize, double damping,
double width, double level)
{
- return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_ALL,
- roomsize, damping, width, level);
+ double values[FLUID_REVERB_PARAM_LAST];
+
+ fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
+
+ values[FLUID_REVERB_ROOMSIZE] = roomsize;
+ values[FLUID_REVERB_DAMP] = damping;
+ values[FLUID_REVERB_WIDTH] = width;
+ values[FLUID_REVERB_LEVEL] = level;
+ return fluid_synth_set_reverb_full(synth, -1, FLUID_REVMODEL_SET_ALL, values);
}
/**
- * Set reverb roomsize.
+ * Set reverb roomsize of all groups.
*
* @param synth FluidSynth instance
* @param roomsize Reverb room size value (0.0-1.0)
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
+ * @deprecated Use fluid_synth_set_reverb_group_roomsize() in new code instead.
*/
int fluid_synth_set_reverb_roomsize(fluid_synth_t *synth, double roomsize)
{
- return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_ROOMSIZE, roomsize, 0, 0, 0);
+ return fluid_synth_reverb_set_param(synth, -1, FLUID_REVERB_ROOMSIZE, roomsize);
}
/**
- * Set reverb damping.
+ * Set reverb damping of all groups.
*
* @param synth FluidSynth instance
* @param damping Reverb damping value (0.0-1.0)
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
+ * @deprecated Use fluid_synth_set_reverb_group_damp() in new code instead.
*/
int fluid_synth_set_reverb_damp(fluid_synth_t *synth, double damping)
{
- return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_DAMPING, 0, damping, 0, 0);
+ return fluid_synth_reverb_set_param(synth, -1, FLUID_REVERB_DAMP, damping);
}
/**
- * Set reverb width.
+ * Set reverb width of all groups.
*
* @param synth FluidSynth instance
* @param width Reverb width value (0.0-100.0)
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
+ * @deprecated Use fluid_synth_set_reverb_group_width() in new code instead.
*/
int fluid_synth_set_reverb_width(fluid_synth_t *synth, double width)
{
- return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_WIDTH, 0, 0, width, 0);
+ return fluid_synth_reverb_set_param(synth, -1, FLUID_REVERB_WIDTH, width);
}
/**
- * Set reverb level.
+ * Set reverb level of all groups.
*
* @param synth FluidSynth instance
* @param level Reverb level value (0.0-1.0)
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
+ * @deprecated Use fluid_synth_set_reverb_group_level() in new code instead.
*/
int fluid_synth_set_reverb_level(fluid_synth_t *synth, double level)
{
- return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_LEVEL, 0, 0, 0, level);
+ return fluid_synth_reverb_set_param(synth, -1, FLUID_REVERB_LEVEL, level);
}
/**
- * Set one or more reverb parameters.
- *
- * @param synth FluidSynth instance
- * @param set Flags indicating which parameters should be set (#fluid_revmodel_set_t)
- * @param roomsize Reverb room size value (0.0-1.2)
- * @param damping Reverb damping value (0.0-1.0)
- * @param width Reverb width value (0.0-100.0)
- * @param level Reverb level value (0.0-1.0)
+ * Set reverb roomsize to one or all fx groups.
+ * @param synth FluidSynth instance.
+ * @param fx_group Index of the fx group.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter will be applied to all fx groups.
+ * @param roomsize roomsize value to set. Must be in the range indicated by
+ * synth.reverb.room-size setting.
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise
+ */
+int fluid_synth_set_reverb_group_roomsize(fluid_synth_t *synth, int fx_group,
+ double roomsize)
+{
+ return fluid_synth_reverb_set_param(synth, fx_group, FLUID_REVERB_ROOMSIZE, roomsize);
+}
+
+/**
+ * Set reverb damp to one or all fx groups.
+ * @param synth FluidSynth instance.
+ * @param fx_group Index of the fx group.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter will be applied to all fx groups.
+ * @param damping damping value to set. Must be in the range indicated by
+ * synth.reverb.damp setting.
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
+ */
+int fluid_synth_set_reverb_group_damp(fluid_synth_t *synth, int fx_group,
+ double damping)
+{
+ return fluid_synth_reverb_set_param(synth, fx_group, FLUID_REVERB_DAMP, damping);
+}
+
+/**
+ * Set reverb width to one or all fx groups.
+ * @param synth FluidSynth instance.
+ * @param fx_group Index of the fx group.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter will be applied to all fx groups.
+ * @param width width value to set. Must be in the range indicated by
+ * synth.reverb.width setting.
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
+ */
+int fluid_synth_set_reverb_group_width(fluid_synth_t *synth, int fx_group,
+ double width)
+{
+ return fluid_synth_reverb_set_param(synth, fx_group, FLUID_REVERB_WIDTH, width);
+}
+
+/**
+ * Set reverb level to one or all fx groups.
+ * @param synth FluidSynth instance.
+ * @param fx_group Index of the fx group.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter will be applied to all fx groups.
+ * @param level output level to set. Must be in the range indicated by
+ * synth.reverb.level setting.
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
+ */
+int fluid_synth_set_reverb_group_level(fluid_synth_t *synth, int fx_group,
+ double level)
+{
+ return fluid_synth_reverb_set_param(synth, fx_group, FLUID_REVERB_LEVEL, level);
+}
+
+/**
+ * Set one reverb parameter to one fx groups.
+ * @param synth FluidSynth instance.
+ * @param fx_group Index of the fx group.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter will be applied to all fx groups.
+ * @param enum indicating the parameter to set (#fluid_reverb_param).
+ * FLUID_REVERB_ROOMSIZE, roomsize Reverb room size value (0.0-1.0)
+ * FLUID_REVERB_DAMP, reverb damping value (0.0-1.0)
+ * FLUID_REVERB_WIDTH, reverb width value (0.0-100.0)
+ * FLUID_REVERB_LEVEL, reverb level value (0.0-1.0)
+ * @param value, parameter value
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
- *
- * @note Not realtime safe and therefore should not be called from synthesis
- * context at the risk of stalling audio output.
*/
int
-fluid_synth_set_reverb_full(fluid_synth_t *synth, int set, double roomsize,
- double damping, double width, double level)
+fluid_synth_reverb_set_param(fluid_synth_t *synth, int fx_group,
+ int param, double value)
{
int ret;
- fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
+ double values[FLUID_REVERB_PARAM_LAST] = {0.0};
+ static const char *name[FLUID_REVERB_PARAM_LAST] =
+ {
+ "synth.reverb.room-size", "synth.reverb.damp",
+ "synth.reverb.width", "synth.reverb.level"
+ };
+ double min; /* minimum value */
+ double max; /* maximum value */
+
+ /* check parameters */
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
- /* if non of the flags is set, fail */
- fluid_return_val_if_fail(set & FLUID_REVMODEL_SET_ALL, FLUID_FAILED);
-
- /* Synth shadow values are set here so that they will be returned if querried */
-
+ fluid_return_val_if_fail((param >= 0) && (param < FLUID_REVERB_PARAM_LAST), FLUID_FAILED);
fluid_synth_api_enter(synth);
- if(set & FLUID_REVMODEL_SET_ROOMSIZE)
+ if(fx_group < -1 || fx_group >= synth->effects_groups)
{
- synth->reverb_roomsize = roomsize;
+ FLUID_API_RETURN(FLUID_FAILED);
}
- if(set & FLUID_REVMODEL_SET_DAMPING)
- {
- synth->reverb_damping = damping;
- }
+ /* check if reverb value is in max min range */
+ fluid_settings_getnum_range(synth->settings, name[param], &min, &max);
+ fluid_return_val_if_fail( min <= value && value <= max, FLUID_FAILED);
- if(set & FLUID_REVMODEL_SET_WIDTH)
- {
- synth->reverb_width = width;
- }
-
- if(set & FLUID_REVMODEL_SET_LEVEL)
- {
- synth->reverb_level = level;
- }
-
- param[0].i = set;
- param[1].real = roomsize;
- param[2].real = damping;
- param[3].real = width;
- param[4].real = level;
- /* finally enqueue an rvoice event to the mixer to actual update reverb */
- ret = fluid_rvoice_eventhandler_push(synth->eventhandler,
- fluid_rvoice_mixer_set_reverb_params,
- synth->eventhandler->mixer,
- param);
+ /* set the value */
+ values[param] = value;
+ ret = fluid_synth_set_reverb_full(synth, fx_group, FLUID_REVPARAM_TO_SETFLAG(param), values);
FLUID_API_RETURN(ret);
}
+int
+fluid_synth_set_reverb_full(fluid_synth_t *synth, int fx_group, int set,
+ const double values[])
+{
+ fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
+
+ /* if non of the flags is set, fail */
+ fluid_return_val_if_fail(set & FLUID_REVMODEL_SET_ALL, FLUID_FAILED);
+
+ /* fx group shadow values are set here so that they will be returned if queried */
+ fluid_rvoice_mixer_set_reverb_full(synth->eventhandler->mixer, fx_group, set,
+ values);
+
+ /* Synth shadow values are set here so that they will be returned if queried */
+ if (fx_group < 0)
+ {
+ int i;
+ for(i = 0; i < FLUID_REVERB_PARAM_LAST; i++)
+ {
+ if(set & FLUID_REVPARAM_TO_SETFLAG(i))
+ {
+ synth->reverb_param[i] = values[i];
+ }
+ }
+ }
+
+ param[0].i = fx_group;
+ param[1].i = set;
+ param[2].real = values[FLUID_REVERB_ROOMSIZE];
+ param[3].real = values[FLUID_REVERB_DAMP];
+ param[4].real = values[FLUID_REVERB_WIDTH];
+ param[5].real = values[FLUID_REVERB_LEVEL];
+ /* finally enqueue an rvoice event to the mixer to actual update reverb */
+ return fluid_rvoice_eventhandler_push(synth->eventhandler,
+ fluid_rvoice_mixer_set_reverb_params,
+ synth->eventhandler->mixer,
+ param);
+}
+
/**
- * Get reverb room size.
+ * Get reverb room size of all fx groups.
* @param synth FluidSynth instance
* @return Reverb room size (0.0-1.2)
+ * @deprecated Use fluid_synth_get_reverb_group_roomsize() in new code instead.
*/
double
fluid_synth_get_reverb_roomsize(fluid_synth_t *synth)
{
- double result;
- fluid_return_val_if_fail(synth != NULL, 0.0);
- fluid_synth_api_enter(synth);
- result = synth->reverb_roomsize;
- FLUID_API_RETURN(result);
+ double roomsize = 0.0;
+ fluid_synth_reverb_get_param(synth, -1, FLUID_REVERB_ROOMSIZE, &roomsize);
+ return roomsize;
}
/**
- * Get reverb damping.
+ * Get reverb damping of all fx groups.
* @param synth FluidSynth instance
* @return Reverb damping value (0.0-1.0)
+ * @deprecated Use fluid_synth_get_reverb_group_damp() in new code instead.
*/
double
fluid_synth_get_reverb_damp(fluid_synth_t *synth)
{
- double result;
- fluid_return_val_if_fail(synth != NULL, 0.0);
- fluid_synth_api_enter(synth);
-
- result = synth->reverb_damping;
- FLUID_API_RETURN(result);
+ double damp = 0.0;
+ fluid_synth_reverb_get_param(synth, -1, FLUID_REVERB_DAMP, &damp);
+ return damp;
}
/**
- * Get reverb level.
+ * Get reverb level of all fx groups.
* @param synth FluidSynth instance
* @return Reverb level value (0.0-1.0)
+ * @deprecated Use fluid_synth_get_reverb_group_level() in new code instead.
*/
double
fluid_synth_get_reverb_level(fluid_synth_t *synth)
{
- double result;
- fluid_return_val_if_fail(synth != NULL, 0.0);
- fluid_synth_api_enter(synth);
-
- result = synth->reverb_level;
- FLUID_API_RETURN(result);
+ double level = 0.0;
+ fluid_synth_reverb_get_param(synth, -1, FLUID_REVERB_LEVEL, &level);
+ return level;
}
/**
- * Get reverb width.
+ * Get reverb width of all fx groups.
* @param synth FluidSynth instance
* @return Reverb width value (0.0-100.0)
+ * @deprecated Use fluid_synth_get_reverb_group_width() in new code instead.
*/
double
fluid_synth_get_reverb_width(fluid_synth_t *synth)
{
- double result;
- fluid_return_val_if_fail(synth != NULL, 0.0);
- fluid_synth_api_enter(synth);
-
- result = synth->reverb_width;
- FLUID_API_RETURN(result);
+ double width = 0.0;
+ fluid_synth_reverb_get_param(synth, -1, FLUID_REVERB_WIDTH, &width);
+ return width;
}
/**
- * Enable or disable chorus effect.
+ * get reverb roomsize of one or all groups.
+ * @param synth FluidSynth instance.
+ * @param fx_group Index of the fx group.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter common to all fx groups is fetched.
+ * @param roomsize valid pointer on the value to return.
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise
+ */
+int fluid_synth_get_reverb_group_roomsize(fluid_synth_t *synth, int fx_group,
+ double *roomsize)
+{
+ return fluid_synth_reverb_get_param(synth, fx_group, FLUID_REVERB_ROOMSIZE, roomsize);
+}
+
+/**
+ * get reverb damp of one or all groups.
+ * @param synth FluidSynth instance.
+ * @param fx_group Index of the fx group.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter common to all fx groups is fetched.
+ * @param damping valid pointer on the value to return.
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
+ */
+int fluid_synth_get_reverb_group_damp(fluid_synth_t *synth, int fx_group,
+ double *damping)
+{
+ return fluid_synth_reverb_get_param(synth, fx_group, FLUID_REVERB_DAMP, damping);
+}
+
+/**
+ * get reverb width of one or all groups
+ * @param synth FluidSynth instance.
+ * @param fx_group Index of the fx group.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter common to all fx groups is fetched.
+ * @param width valid pointer on the value to return.
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
+ */
+int fluid_synth_get_reverb_group_width(fluid_synth_t *synth, int fx_group,
+ double *width)
+{
+ return fluid_synth_reverb_get_param(synth, fx_group, FLUID_REVERB_WIDTH, width);
+}
+
+/**
+ * get reverb level of one or all groups.
+ * @param synth FluidSynth instance.
+ * @param fx_group Index of the fx group.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter common to all fx groups is fetched.
+ * @param level valid pointer on the value to return.
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
+ */
+int fluid_synth_get_reverb_group_level(fluid_synth_t *synth, int fx_group,
+ double *level)
+{
+ return fluid_synth_reverb_get_param(synth, fx_group, FLUID_REVERB_LEVEL, level);
+}
+
+
+/**
+ * Get one reverb parameter value of one fx groups.
+ * @param synth FluidSynth instance
+ * @param fx_group index of the fx group to get parameter value from.
+ * Must be in the range -1 to synth->effects_groups-1. If -1 get the
+ * parameter common to all fx groups.
+ * @param enum indicating the parameter to get (#fluid_reverb_param).
+ * FLUID_REVERB_ROOMSIZE, reverb room size value.
+ * FLUID_REVERB_DAMP, reverb damping value.
+ * FLUID_REVERB_WIDTH, reverb width value.
+ * FLUID_REVERB_LEVEL, reverb level value.
+ * @param value pointer on the value to return.
+ * @return FLUID_OK if success, FLUID_FAILED otherwise.
+ */
+static int fluid_synth_reverb_get_param(fluid_synth_t *synth, int fx_group,
+ int param, double *value)
+{
+ fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
+ fluid_return_val_if_fail((param >= 0) && (param < FLUID_REVERB_PARAM_LAST), FLUID_FAILED);
+ fluid_return_val_if_fail(value != NULL, FLUID_FAILED);
+ fluid_synth_api_enter(synth);
+
+ if(fx_group < -1 || fx_group >= synth->effects_groups)
+ {
+ FLUID_API_RETURN(FLUID_FAILED);
+ }
+
+ if (fx_group < 0)
+ {
+ /* return reverb param common to all fx groups */
+ *value = synth->reverb_param[param];
+ }
+ else
+ {
+ /* return reverb param of fx group at index fx_group */
+ *value = fluid_rvoice_mixer_reverb_get_param(synth->eventhandler->mixer,
+ fx_group, param);
+ }
+
+ FLUID_API_RETURN(FLUID_OK);
+}
+
+/**
+ * Enable or disable all chorus groups.
* @param synth FluidSynth instance
* @param on TRUE to enable chorus, FALSE to disable
+ * @deprecated Use fluid_synth_chorus_on() in new code instead.
*/
void
fluid_synth_set_chorus_on(fluid_synth_t *synth, int on)
@@ -5713,137 +5947,37 @@ fluid_synth_set_chorus_on(fluid_synth_t *synth, int on)
}
/**
- * Set chorus parameters.
- *
+ * Enable or disable chorus on one or all groups.
* @param synth FluidSynth instance
- * @param nr Chorus voice count (0-99, CPU time consumption proportional to
- * this value)
- * @param level Chorus level (0.0-10.0)
- * @param speed Chorus speed in Hz (0.1-5.0)
- * @param depth_ms Chorus depth (max value depends on synth sample-rate,
- * 0.0-21.0 is safe for sample-rate values up to 96KHz)
- * @param type Chorus waveform type (#fluid_chorus_mod)
- * @return #FLUID_OK on success, #FLUID_FAILED otherwise
- *
- * It should be turned on with fluid_synth_set_chorus_on().
- * Keep in mind, that the needed CPU time is proportional to 'nr'.
- */
-int fluid_synth_set_chorus(fluid_synth_t *synth, int nr, double level,
- double speed, double depth_ms, int type)
-{
- return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_ALL, nr, level, speed,
- depth_ms, type);
-}
-
-/**
- * Set the chorus voice count.
- *
- * @param synth FluidSynth instance
- * @param nr Chorus voice count (0-99, CPU time consumption proportional to
- * this value)
+ * @param fx_group Index of the fx group.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter common to all fx groups is fetched.
+ * @param on TRUE to enable chorus, FALSE to disable
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
*/
-int fluid_synth_set_chorus_nr(fluid_synth_t *synth, int nr)
-{
- return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_NR, nr, 0, 0, 0, 0);
-}
-
-/**
- * Set the chorus level.
- *
- * @param synth FluidSynth instance
- * @param level Chorus level (0.0-10.0)
- * @return #FLUID_OK on success, #FLUID_FAILED otherwise
- */
-int fluid_synth_set_chorus_level(fluid_synth_t *synth, double level)
-{
- return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_LEVEL, 0, level, 0, 0, 0);
-}
-
-/**
- * Set the chorus speed.
- *
- * @param synth FluidSynth instance
- * @param speed Chorus speed in Hz (0.1-5.0)
- * @return #FLUID_OK on success, #FLUID_FAILED otherwise
- */
-int fluid_synth_set_chorus_speed(fluid_synth_t *synth, double speed)
-{
- return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_SPEED, 0, 0, speed, 0, 0);
-}
-
-/**
- * Set the chorus depth.
- *
- * @param synth FluidSynth instance
- * @param depth_ms Chorus depth (max value depends on synth sample-rate,
- * 0.0-21.0 is safe for sample-rate values up to 96KHz)
- * @return #FLUID_OK on success, #FLUID_FAILED otherwise
- */
-int fluid_synth_set_chorus_depth(fluid_synth_t *synth, double depth_ms)
-{
- return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_DEPTH, 0, 0, 0, depth_ms, 0);
-}
-
-/**
- * Set the chorus type.
- *
- * @param synth FluidSynth instance
- * @param type Chorus waveform type (#fluid_chorus_mod)
- * @return #FLUID_OK on success, #FLUID_FAILED otherwise
- */
-int fluid_synth_set_chorus_type(fluid_synth_t *synth, int type)
-{
- return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_TYPE, 0, 0, 0, 0, type);
-}
-
int
-fluid_synth_set_chorus_full(fluid_synth_t *synth, int set, int nr, double level,
- double speed, double depth_ms, int type)
+fluid_synth_chorus_on(fluid_synth_t *synth, int fx_group, int on)
{
int ret;
- fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
-
+ fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
- /* if non of the flags is set, fail */
- fluid_return_val_if_fail(set & FLUID_CHORUS_SET_ALL, FLUID_FAILED);
- /* Synth shadow values are set here so that they will be returned if queried */
fluid_synth_api_enter(synth);
- if(set & FLUID_CHORUS_SET_NR)
+ if(fx_group < -1 || fx_group >= synth->effects_groups)
{
- synth->chorus_nr = nr;
+ FLUID_API_RETURN(FLUID_FAILED);
}
- if(set & FLUID_CHORUS_SET_LEVEL)
+ if(fx_group < 0 )
{
- synth->chorus_level = level;
+ synth->with_chorus = (on != 0);
}
- if(set & FLUID_CHORUS_SET_SPEED)
- {
- synth->chorus_speed = speed;
- }
-
- if(set & FLUID_CHORUS_SET_DEPTH)
- {
- synth->chorus_depth = depth_ms;
- }
-
- if(set & FLUID_CHORUS_SET_TYPE)
- {
- synth->chorus_type = type;
- }
-
- param[0].i = set;
- param[1].i = nr;
- param[2].real = level;
- param[3].real = speed;
- param[4].real = depth_ms;
- param[5].i = type;
+ param[0].i = fx_group;
+ param[1].i = on;
ret = fluid_rvoice_eventhandler_push(synth->eventhandler,
- fluid_rvoice_mixer_set_chorus_params,
+ fluid_rvoice_mixer_chorus_enable,
synth->eventhandler->mixer,
param);
@@ -5851,83 +5985,476 @@ fluid_synth_set_chorus_full(fluid_synth_t *synth, int set, int nr, double level,
}
/**
- * Get chorus voice number (delay line count) value.
+ * Set chorus parameters to all fx groups.
+ * Keep in mind, that the needed CPU time is proportional to 'nr'.
+ * @param synth FluidSynth instance
+ * @param nr Chorus voice count (0-99, CPU time consumption proportional to
+ * this value)
+ * @param level Chorus level (0.0-10.0)
+ * @param speed Chorus speed in Hz (0.1-5.0)
+ * @param depth_ms Chorus depth (max value depends on synth sample-rate,
+ * 0.0-21.0 is safe for sample-rate values up to 96KHz)
+ * @param type Chorus waveform type (#fluid_chorus_mod)
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise
+ * @deprecated Use the individual chorus setter functions in new code instead.
+ *
+ * Keep in mind, that the needed CPU time is proportional to 'nr'.
+ */
+int fluid_synth_set_chorus(fluid_synth_t *synth, int nr, double level,
+ double speed, double depth_ms, int type)
+{
+ double values[FLUID_CHORUS_PARAM_LAST];
+
+ fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
+
+ values[FLUID_CHORUS_NR] = nr;
+ values[FLUID_CHORUS_LEVEL] = level;
+ values[FLUID_CHORUS_SPEED] = speed;
+ values[FLUID_CHORUS_DEPTH] = depth_ms;
+ values[FLUID_CHORUS_TYPE] = type;
+ return fluid_synth_set_chorus_full(synth, -1, FLUID_CHORUS_SET_ALL, values);
+}
+
+/**
+ * Set the chorus voice count of all groups.
+ *
+ * @param synth FluidSynth instance
+ * @param nr Chorus voice count (0-99, CPU time consumption proportional to
+ * this value)
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise
+ * @deprecated Use fluid_synth_set_chorus_group_nr() in new code instead.
+ */
+int fluid_synth_set_chorus_nr(fluid_synth_t *synth, int nr)
+{
+ return fluid_synth_chorus_set_param(synth, -1, FLUID_CHORUS_NR, nr);
+}
+
+/**
+ * Set the chorus level of all groups.
+ *
+ * @param synth FluidSynth instance
+ * @param level Chorus level (0.0-10.0)
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise
+ * @deprecated Use fluid_synth_set_chorus_group_level() in new code instead.
+ */
+int fluid_synth_set_chorus_level(fluid_synth_t *synth, double level)
+{
+ return fluid_synth_chorus_set_param(synth, -1, FLUID_CHORUS_LEVEL, level);
+}
+
+/**
+ * Set the chorus speed of all groups.
+ *
+ * @param synth FluidSynth instance
+ * @param speed Chorus speed in Hz (0.1-5.0)
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise
+ * @deprecated Use fluid_synth_set_chorus_group_level() in new code instead.
+ */
+int fluid_synth_set_chorus_speed(fluid_synth_t *synth, double speed)
+{
+ return fluid_synth_chorus_set_param(synth, -1, FLUID_CHORUS_SPEED, speed);
+}
+
+/**
+ * Set the chorus depth of all groups.
+ *
+ * @param synth FluidSynth instance
+ * @param depth_ms Chorus depth (max value depends on synth sample-rate,
+ * 0.0-21.0 is safe for sample-rate values up to 96KHz)
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise
+ * @deprecated Use fluid_synth_set_chorus_group_depth() in new code instead.
+ */
+int fluid_synth_set_chorus_depth(fluid_synth_t *synth, double depth_ms)
+{
+ return fluid_synth_chorus_set_param(synth, -1, FLUID_CHORUS_DEPTH, depth_ms);
+}
+
+/**
+ * Set the chorus type of all groups.
+ *
+ * @param synth FluidSynth instance
+ * @param type Chorus waveform type (#fluid_chorus_mod)
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise
+ * @deprecated Use fluid_synth_set_chorus_group_type() in new code instead.
+ */
+int fluid_synth_set_chorus_type(fluid_synth_t *synth, int type)
+{
+ return fluid_synth_chorus_set_param(synth, -1, FLUID_CHORUS_TYPE, type);
+}
+
+/**
+ * Set chorus voice count nr to one or all chorus groups.
+ * @param synth FluidSynth instance.
+ * @param fx_group Index of the fx group.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter will be applied to all groups.
+ * @param nr Voice count to set. Must be in the range indicated by \setting{synth_chorus_nr}
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
+ */
+int
+fluid_synth_set_chorus_group_nr(fluid_synth_t *synth, int fx_group, int nr)
+{
+ return fluid_synth_chorus_set_param(synth, fx_group, FLUID_CHORUS_NR, (double)nr);
+}
+
+/**
+ * Set chorus output level to one or all chorus groups.
+ * @param synth FluidSynth instance.
+ * @param fx_group Index of the fx group.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter will be applied to all groups.
+ * @param level Output level to set. Must be in the range indicated by \setting{synth_chorus_level}
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
+ */
+int
+fluid_synth_set_chorus_group_level(fluid_synth_t *synth, int fx_group, double level)
+{
+ return fluid_synth_chorus_set_param(synth, fx_group, FLUID_CHORUS_LEVEL, level);
+}
+
+/**
+ * Set chorus lfo speed to one or all chorus groups.
+ * @param synth FluidSynth instance.
+ * @param fx_group Index of the fx group.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter will be applied to all groups.
+ * @param speed Lfo speed to set. Must be in the range indicated by \settings{synth_chorus_speed}
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
+ */
+int
+fluid_synth_set_chorus_group_speed(fluid_synth_t *synth, int fx_group, double speed)
+{
+ return fluid_synth_chorus_set_param(synth, fx_group, FLUID_CHORUS_SPEED, speed);
+}
+
+/**
+ * Set chorus lfo depth to one or all chorus groups.
+ * @param synth FluidSynth instance.
+ * @param fx_group Index of the fx group.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter will be applied to all groups.
+ * @depth_ms, lfo depth to set. Must be in the range indicated by synth.chorus.depth
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
+ */
+int
+fluid_synth_set_chorus_group_depth(fluid_synth_t *synth, int fx_group, double depth_ms)
+{
+ return fluid_synth_chorus_set_param(synth, fx_group, FLUID_CHORUS_DEPTH, depth_ms);
+}
+
+/**
+ * Set chorus lfo waveform type to one or all chorus groups.
+ * @param synth FluidSynth instance.
+ * @param fx_group Index of the fx group.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter will be applied to all groups.
+ * @param type Lfo waveform type to set. (#fluid_chorus_mod)
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
+ */
+int
+fluid_synth_set_chorus_group_type(fluid_synth_t *synth, int fx_group, int type)
+{
+ return fluid_synth_chorus_set_param(synth, fx_group, FLUID_CHORUS_TYPE, (double)type);
+}
+
+/**
+ * Set one chorus parameter to one fx groups.
+ * @param synth FluidSynth instance.
+ * @param fx_group Index of the fx group.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter will be applied to all groups.
+ * @param enum indicating the parameter to set (#fluid_chorus_param).
+ * FLUID_CHORUS_NR, chorus voice count (0-99, CPU time consumption proportional to
+ * this value).
+ * FLUID_CHORUS_LEVEL, chorus level (0.0-10.0).
+ * FLUID_CHORUS_SPEED, chorus speed in Hz (0.1-5.0).
+ * FLUID_CHORUS_DEPTH, chorus depth (max value depends on synth sample-rate,
+ * 0.0-21.0 is safe for sample-rate values up to 96KHz).
+ * FLUID_CHORUS_TYPE, chorus waveform type (#fluid_chorus_mod)
+ * @param value, parameter value
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
+ */
+int
+fluid_synth_chorus_set_param(fluid_synth_t *synth, int fx_group, int param,
+ double value)
+{
+ int ret;
+ double values[FLUID_CHORUS_PARAM_LAST] = {0.0};
+
+ /* setting name (except lfo waveform type) */
+ static const char *name[FLUID_CHORUS_PARAM_LAST-1] =
+ {
+ "synth.chorus.nr", "synth.chorus.level",
+ "synth.chorus.speed", "synth.chorus.depth"
+ };
+
+ /* check parameters */
+ fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
+ fluid_return_val_if_fail((param >= 0) && (param < FLUID_CHORUS_PARAM_LAST), FLUID_FAILED);
+ fluid_synth_api_enter(synth);
+
+ if(fx_group < -1 || fx_group >= synth->effects_groups)
+ {
+ FLUID_API_RETURN(FLUID_FAILED);
+ }
+
+ /* check if chorus value is in max min range */
+ if(param == FLUID_CHORUS_TYPE || param == FLUID_CHORUS_NR) /* integer value */
+ {
+ int min = FLUID_CHORUS_MOD_SINE;
+ int max = FLUID_CHORUS_MOD_TRIANGLE;
+ if(param == FLUID_CHORUS_NR)
+ {
+ fluid_settings_getint_range(synth->settings, name[param], &min, &max);
+ }
+ fluid_return_val_if_fail(min <= (int)value && (int)value <= max, FLUID_FAILED);
+ }
+ else /* float value */
+ {
+ double min;
+ double max;
+ fluid_settings_getnum_range(synth->settings, name[param], &min, &max);
+ fluid_return_val_if_fail(min <= value && value <= max, FLUID_FAILED);
+ }
+
+ /* set the value */
+ values[param] = value;
+ ret = fluid_synth_set_chorus_full(synth, fx_group,
+ FLUID_CHORPARAM_TO_SETFLAG(param), values);
+ FLUID_API_RETURN(ret);
+}
+
+int
+fluid_synth_set_chorus_full(fluid_synth_t *synth, int fx_group, int set,
+ const double values[])
+{
+ fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
+
+ /* if non of the flags is set, fail */
+ fluid_return_val_if_fail(set & FLUID_CHORUS_SET_ALL, FLUID_FAILED);
+
+ /* fx group shadow values are set here so that they will be returned if queried */
+ fluid_rvoice_mixer_set_chorus_full(synth->eventhandler->mixer, fx_group,
+ set, values);
+
+ /* Synth shadow values are set here so that they will be returned if queried */
+ if (fx_group < 0)
+ {
+ int i;
+ for(i = 0; i < FLUID_CHORUS_PARAM_LAST; i++)
+ {
+ if(set & FLUID_CHORPARAM_TO_SETFLAG(i))
+ {
+ synth->chorus_param[i] = values[i];
+ }
+ }
+ }
+
+ param[0].i = fx_group;
+ param[1].i = set;
+ param[2].i = (int)values[FLUID_CHORUS_NR];
+ param[3].real = values[FLUID_CHORUS_LEVEL];
+ param[4].real = values[FLUID_CHORUS_SPEED];
+ param[5].real = values[FLUID_CHORUS_DEPTH];
+ param[6].i = (int)values[FLUID_CHORUS_TYPE];
+ return fluid_rvoice_eventhandler_push(synth->eventhandler,
+ fluid_rvoice_mixer_set_chorus_params,
+ synth->eventhandler->mixer,
+ param);
+}
+
+/**
+ * Get chorus voice number (delay line count) value of all fx groups.
* @param synth FluidSynth instance
* @return Chorus voice count
+ * @deprecated Use fluid_synth_get_chorus_group_nr() in new code instead.
*/
int
fluid_synth_get_chorus_nr(fluid_synth_t *synth)
{
- int result;
- fluid_return_val_if_fail(synth != NULL, 0);
- fluid_synth_api_enter(synth);
-
- result = synth->chorus_nr;
- FLUID_API_RETURN(result);
+ double nr = 0.0;
+ fluid_synth_chorus_get_param(synth, -1, FLUID_CHORUS_NR, &nr);
+ return (int)nr;
}
/**
- * Get chorus level.
+ * Get chorus level of all fx groups.
* @param synth FluidSynth instance
* @return Chorus level value
+ * @deprecated Use fluid_synth_get_chorus_group_level() in new code instead.
*/
double
fluid_synth_get_chorus_level(fluid_synth_t *synth)
{
- double result;
- fluid_return_val_if_fail(synth != NULL, 0.0);
- fluid_synth_api_enter(synth);
-
- result = synth->chorus_level;
- FLUID_API_RETURN(result);
+ double level = 0.0;
+ fluid_synth_chorus_get_param(synth, -1, FLUID_CHORUS_LEVEL, &level);
+ return level;
}
/**
- * Get chorus speed in Hz.
+ * Get chorus speed in Hz of all fx groups.
* @param synth FluidSynth instance
* @return Chorus speed in Hz
+ * @deprecated Use fluid_synth_get_chorus_group_speed() in new code instead.
*/
double
fluid_synth_get_chorus_speed(fluid_synth_t *synth)
{
- double result;
- fluid_return_val_if_fail(synth != NULL, 0.0);
- fluid_synth_api_enter(synth);
-
- result = synth->chorus_speed;
- FLUID_API_RETURN(result);
+ double speed = 0.0;
+ fluid_synth_chorus_get_param(synth, -1, FLUID_CHORUS_SPEED, &speed);
+ return speed;
}
/**
- * Get chorus depth.
+ * Get chorus depth of all fx groups.
* @param synth FluidSynth instance
* @return Chorus depth
+ * @deprecated Use fluid_synth_get_chorus_group_depth() in new code instead.
*/
double
fluid_synth_get_chorus_depth(fluid_synth_t *synth)
{
- double result;
- fluid_return_val_if_fail(synth != NULL, 0.0);
- fluid_synth_api_enter(synth);
-
- result = synth->chorus_depth;
- FLUID_API_RETURN(result);
+ double depth = 0.0;
+ fluid_synth_chorus_get_param(synth, -1, FLUID_CHORUS_DEPTH, &depth);
+ return depth;
}
/**
- * Get chorus waveform type.
+ * Get chorus waveform type of all fx groups.
* @param synth FluidSynth instance
* @return Chorus waveform type (#fluid_chorus_mod)
+ * @deprecated Use fluid_synth_get_chorus_group_type() in new code instead.
*/
int
fluid_synth_get_chorus_type(fluid_synth_t *synth)
{
- int result;
- fluid_return_val_if_fail(synth != NULL, 0);
+ double type = 0.0;
+ fluid_synth_chorus_get_param(synth, -1, FLUID_CHORUS_TYPE, &type);
+ return (int)type;
+}
+
+/**
+ * Get chorus count nr of one or all fx groups.
+ * @param synth FluidSynth instance.
+ * @param fx_group Index of the fx group from which to fetch the chorus voice count.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter common to all fx groups is fetched.
+ * @param nr valid pointer on value to return.
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
+ */
+int
+fluid_synth_get_chorus_group_nr(fluid_synth_t *synth, int fx_group, int *nr)
+{
+ double num_nr = 0.0;
+ int status;
+ status = fluid_synth_chorus_get_param(synth, fx_group, FLUID_CHORUS_NR, &num_nr);
+ *nr = (int)num_nr;
+ return status;
+}
+
+/**
+ * Get chorus output level of one or all fx groups.
+ * @param synth FluidSynth instance.
+ * @param fx_group Index of the fx group from which chorus level to fetch.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter common to all fx groups is fetched.
+ * @param level valid pointer on value to return.
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
+ */
+int
+fluid_synth_get_chorus_group_level(fluid_synth_t *synth, int fx_group, double *level)
+{
+ return fluid_synth_chorus_get_param(synth, fx_group, FLUID_CHORUS_LEVEL, level);
+}
+
+/**
+ * Get chorus waveform lfo speed of one or all fx groups.
+ * @param synth FluidSynth instance.
+ * @param fx_group Index of the fx group from which lfo speed to fetch.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter common to all fx groups is fetched.
+ * @param speed valid pointer on value to return.
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
+ */
+int
+fluid_synth_get_chorus_group_speed(fluid_synth_t *synth, int fx_group, double *speed)
+{
+ return fluid_synth_chorus_get_param(synth, fx_group, FLUID_CHORUS_SPEED, speed);
+}
+
+/**
+ * Get chorus lfo depth of one or all fx groups.
+ * @param synth FluidSynth instance
+ * @param fx_group Index of the fx group from which lfo depth to fetch.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter common to all fx groups is fetched.
+ * @param depth valid pointer on value to return.
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise
+ */
+int
+fluid_synth_get_chorus_group_depth(fluid_synth_t *synth, int fx_group, double *depth_ms)
+{
+ return fluid_synth_chorus_get_param(synth, fx_group, FLUID_CHORUS_DEPTH, depth_ms);
+}
+
+/**
+ * Get chorus waveform type of one or all fx groups.
+ * @param synth FluidSynth instance
+ * @param fx_group Index of the fx group from which to fetch the waveform type.
+ * Must be in the range -1 to (fluid_synth_count_effects_groups()-1)
. If -1 the
+ * parameter common to all fx groups is fetched.
+ * @param type valid pointer on waveform type to return (#fluid_chorus_mod)
+ * @return #FLUID_OK on success, #FLUID_FAILED otherwise
+ */
+int
+fluid_synth_get_chorus_group_type(fluid_synth_t *synth, int fx_group, int *type)
+{
+ double num_type = 0.0;
+ int status;
+ status = fluid_synth_chorus_get_param(synth, fx_group, FLUID_CHORUS_TYPE, &num_type);
+ *type = (int)num_type;
+ return status;
+}
+
+/**
+ * Get chorus parameter value of one or all fx groups.
+ * @param synth FluidSynth instance
+ * @param fx_group index of the fx group
+ * @param enum indicating the parameter to get.
+ * FLUID_CHORUS_NR, chorus voice count.
+ * FLUID_CHORUS_LEVEL, chorus level.
+ * FLUID_CHORUS_SPEED, chorus speed.
+ * FLUID_CHORUS_DEPTH, chorus depth.
+ * FLUID_CHORUS_TYPE, chorus waveform type.
+ * @param value pointer on the value to return.
+ * @return FLUID_OK if success, FLUID_FAILED otherwise.
+ */
+static int fluid_synth_chorus_get_param(fluid_synth_t *synth, int fx_group,
+ int param, double *value)
+{
+ fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
+ fluid_return_val_if_fail((param >= 0) && (param < FLUID_CHORUS_PARAM_LAST), FLUID_FAILED);
+ fluid_return_val_if_fail(value != NULL, FLUID_FAILED);
fluid_synth_api_enter(synth);
- result = synth->chorus_type;
- FLUID_API_RETURN(result);
+ if(fx_group < -1 || fx_group >= synth->effects_groups)
+ {
+ FLUID_API_RETURN(FLUID_FAILED);
+ }
+
+ if (fx_group < 0)
+ {
+ /* return chorus param common to all fx groups */
+ *value = synth->chorus_param[param];
+ }
+ else
+ {
+ /* return chorus param of fx group at index group */
+ *value = fluid_rvoice_mixer_chorus_get_param(synth->eventhandler->mixer,
+ fx_group, param);
+ }
+
+ FLUID_API_RETURN(FLUID_OK);
}
/*
@@ -6082,6 +6609,8 @@ fluid_synth_count_effects_channels(fluid_synth_t *synth)
/**
* Get the total number of allocated effects units.
+ *
+ * This is the same number as initially provided by the setting \setting{synth_effects-groups}.
* @param synth FluidSynth instance
* @return Count of allocated effects units
*/
diff --git a/src/synth/fluid_synth.h b/src/synth/fluid_synth.h
index ab929b34..791ce074 100644
--- a/src/synth/fluid_synth.h
+++ b/src/synth/fluid_synth.h
@@ -138,16 +138,11 @@ struct _fluid_synth_t
int fromkey_portamento; /**< fromkey portamento */
fluid_rvoice_eventhandler_t *eventhandler;
- double reverb_roomsize; /**< Shadow of reverb roomsize */
- double reverb_damping; /**< Shadow of reverb damping */
- double reverb_width; /**< Shadow of reverb width */
- double reverb_level; /**< Shadow of reverb level */
+ /**< Shadow of reverb parameter: roomsize, damping, width, level */
+ double reverb_param[FLUID_REVERB_PARAM_LAST];
- int chorus_nr; /**< Shadow of chorus number */
- double chorus_level; /**< Shadow of chorus level */
- double chorus_speed; /**< Shadow of chorus speed */
- double chorus_depth; /**< Shadow of chorus depth */
- int chorus_type; /**< Shadow of chorus type */
+ /**< Shadow of chorus parameter: chorus number, level, speed, depth, type */
+ double chorus_param[FLUID_CHORUS_PARAM_LAST];
int cur; /**< the current sample in the audio buffers to be output */
int curmax; /**< current amount of samples present in the audio buffers */
@@ -219,12 +214,17 @@ void fluid_synth_dither_s16(int *dither_index, int len, const float *lin, const
int fluid_synth_reset_reverb(fluid_synth_t *synth);
int fluid_synth_set_reverb_preset(fluid_synth_t *synth, unsigned int num);
-int fluid_synth_set_reverb_full(fluid_synth_t *synth, int set, double roomsize,
- double damping, double width, double level);
+int fluid_synth_reverb_set_param(fluid_synth_t *synth, int fx_group,
+ int param,
+ double value);
+int fluid_synth_set_reverb_full(fluid_synth_t *synth, int fx_group, int set,
+ const double values[]);
int fluid_synth_reset_chorus(fluid_synth_t *synth);
-int fluid_synth_set_chorus_full(fluid_synth_t *synth, int set, int nr, double level,
- double speed, double depth_ms, int type);
+int fluid_synth_chorus_set_param(fluid_synth_t *synth, int fx_group,
+ int param, double value);
+int fluid_synth_set_chorus_full(fluid_synth_t *synth, int fx_group, int set,
+ const double values[]);
fluid_sample_timer_t *new_fluid_sample_timer(fluid_synth_t *synth, fluid_timer_callback_t callback, void *data);
void delete_fluid_sample_timer(fluid_synth_t *synth, fluid_sample_timer_t *timer);
diff --git a/src/utils/fluidsynth_priv.h b/src/utils/fluidsynth_priv.h
index 8d929c96..fe5bc507 100644
--- a/src/utils/fluidsynth_priv.h
+++ b/src/utils/fluidsynth_priv.h
@@ -98,7 +98,7 @@ typedef union _fluid_rvoice_param_t
int i;
fluid_real_t real;
} fluid_rvoice_param_t;
-enum { MAX_EVENT_PARAMS = 6 }; /**< Maximum number of #fluid_rvoice_param_t to be passed to an #fluid_rvoice_function_t */
+enum { MAX_EVENT_PARAMS = 7 }; /**< Maximum number of #fluid_rvoice_param_t to be passed to an #fluid_rvoice_function_t */
typedef void (*fluid_rvoice_function_t)(void *obj, const fluid_rvoice_param_t param[MAX_EVENT_PARAMS]);
/* Macro for declaring an rvoice event function (#fluid_rvoice_function_t). The functions may only access
diff --git a/test/test_synth_chorus_reverb.c b/test/test_synth_chorus_reverb.c
index 7c372d9b..14c7d716 100644
--- a/test/test_synth_chorus_reverb.c
+++ b/test/test_synth_chorus_reverb.c
@@ -2,18 +2,25 @@
#include "test.h"
#include "fluidsynth.h"
-// this test should make sure that sample rate changed are handled correctly
+// this test should make sure that effects change (reverb, chorus) are handled correctly
int main(void)
{
fluid_synth_t *synth;
fluid_settings_t *settings = new_fluid_settings();
- TEST_ASSERT(settings != NULL);
+ double value;
+ int int_value;
+ TEST_ASSERT(settings != NULL);
+ /* set 2 group of effects */
+ TEST_SUCCESS(fluid_settings_setint(settings, "synth.effects-groups", 2));
+
+ /* set values for all reverb group */
TEST_SUCCESS(fluid_settings_setnum(settings, "synth.reverb.room-size", 0.1));
TEST_SUCCESS(fluid_settings_setnum(settings, "synth.reverb.damp", 0.2));
TEST_SUCCESS(fluid_settings_setnum(settings, "synth.reverb.width", 0.3));
TEST_SUCCESS(fluid_settings_setnum(settings, "synth.reverb.level", 0.4));
+ /* set values for all chorus group */
TEST_SUCCESS(fluid_settings_setint(settings, "synth.chorus.nr", 99));
TEST_SUCCESS(fluid_settings_setnum(settings, "synth.chorus.level", 0.5));
TEST_SUCCESS(fluid_settings_setnum(settings, "synth.chorus.speed", 0.6));
@@ -22,18 +29,28 @@ int main(void)
synth = new_fluid_synth(settings);
TEST_ASSERT(synth != NULL);
- // check that the synth is initialized with the correct values
- TEST_ASSERT(fluid_synth_get_reverb_roomsize(synth) == 0.1);
- TEST_ASSERT(fluid_synth_get_reverb_damp(synth) == 0.2);
- TEST_ASSERT(fluid_synth_get_reverb_width(synth) == 0.3);
- TEST_ASSERT(fluid_synth_get_reverb_level(synth) == 0.4);
+ /*
+ check that the synth is initialized with the correct values (for all reverb group)
+ */
+ TEST_ASSERT(fluid_synth_get_reverb_group_roomsize(synth, -1, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.1);
+ TEST_ASSERT(fluid_synth_get_reverb_group_damp(synth, -1, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.2);
+ TEST_ASSERT(fluid_synth_get_reverb_group_width(synth, -1, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.3);
+ TEST_ASSERT(fluid_synth_get_reverb_group_level(synth, -1, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.4);
- TEST_ASSERT(fluid_synth_get_chorus_nr(synth) == 99);
- TEST_ASSERT(fluid_synth_get_chorus_level(synth) == 0.5);
- TEST_ASSERT(fluid_synth_get_chorus_speed(synth) == 0.6);
- TEST_ASSERT(fluid_synth_get_chorus_depth(synth) == 0.7);
+ TEST_ASSERT(fluid_synth_get_chorus_group_nr(synth, -1, &int_value) == FLUID_OK);
+ TEST_ASSERT(int_value == 99);
+ TEST_ASSERT(fluid_synth_get_chorus_group_level(synth, -1, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.5);
+ TEST_ASSERT(fluid_synth_get_chorus_group_speed(synth, -1, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.6);
+ TEST_ASSERT(fluid_synth_get_chorus_group_depth(synth, -1, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.7);
- // update the realtime settings afterward
+ // update the realtime settings for all reverb group and all chorus group afterward
TEST_SUCCESS(fluid_settings_setnum(settings, "synth.reverb.room-size", 0.11));
TEST_SUCCESS(fluid_settings_setnum(settings, "synth.reverb.damp", 0.22));
TEST_SUCCESS(fluid_settings_setnum(settings, "synth.reverb.width", 0.33));
@@ -45,15 +62,131 @@ int main(void)
TEST_SUCCESS(fluid_settings_setnum(settings, "synth.chorus.depth", 0.77));
// check that the realtime settings correctly update the values in the synth
- TEST_ASSERT(fluid_synth_get_reverb_roomsize(synth) == 0.11);
- TEST_ASSERT(fluid_synth_get_reverb_damp(synth) == 0.22);
- TEST_ASSERT(fluid_synth_get_reverb_width(synth) == 0.33);
- TEST_ASSERT(fluid_synth_get_reverb_level(synth) == 0.44);
+ TEST_ASSERT(fluid_synth_get_reverb_group_roomsize(synth, -1, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.11);
+ TEST_ASSERT(fluid_synth_get_reverb_group_damp(synth, -1, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.22);
+ TEST_ASSERT(fluid_synth_get_reverb_group_width(synth, -1, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.33);
+ TEST_ASSERT(fluid_synth_get_reverb_group_level(synth, -1, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.44);
- TEST_ASSERT(fluid_synth_get_chorus_nr(synth) == 11);
- TEST_ASSERT(fluid_synth_get_chorus_level(synth) == 0.55);
- TEST_ASSERT(fluid_synth_get_chorus_speed(synth) == 0.66);
- TEST_ASSERT(fluid_synth_get_chorus_depth(synth) == 0.77);
+ TEST_ASSERT(fluid_synth_get_chorus_group_nr(synth, -1, &int_value) == FLUID_OK);
+ TEST_ASSERT(int_value == 11);
+ TEST_ASSERT(fluid_synth_get_chorus_group_level(synth, -1, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.55);
+ TEST_ASSERT(fluid_synth_get_chorus_group_speed(synth, -1, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.66);
+ TEST_ASSERT(fluid_synth_get_chorus_group_depth(synth, -1, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.77);
+
+ /*
+ Set/get that the synth is initialized with the correct values for one group only
+ calling fx set/get API
+ */
+ // test reverb invalid parameters range
+ // room size valid range: 0.0..1.0
+ TEST_ASSERT(fluid_synth_set_reverb_group_roomsize(synth, 0, 1.1) == FLUID_FAILED);
+ TEST_ASSERT(fluid_synth_set_reverb_group_roomsize(synth, 0, -0.1) == FLUID_FAILED);
+
+ // damp valid range: 0.0..1.0
+ TEST_ASSERT(fluid_synth_set_reverb_group_damp(synth, 0, 1.1) == FLUID_FAILED);
+ TEST_ASSERT(fluid_synth_set_reverb_group_damp(synth, 0, -0.1) == FLUID_FAILED);
+
+ // width valid range: 0.0..100.0
+ TEST_ASSERT(fluid_synth_set_reverb_group_width(synth, 0, 100.1) == FLUID_FAILED);
+ TEST_ASSERT(fluid_synth_set_reverb_group_width(synth, 0, -0.1) == FLUID_FAILED);
+
+ // level valid range: 0.0..1.0
+ TEST_ASSERT(fluid_synth_set_reverb_group_level(synth, 0, 1.1) == FLUID_FAILED);
+ TEST_ASSERT(fluid_synth_set_reverb_group_level(synth, 0, -0.1) == FLUID_FAILED);
+
+ // test chorus invalid parameters range
+ // number of chorus block valid range: 0..99
+ TEST_ASSERT(fluid_synth_set_chorus_group_nr(synth, 1, 100) == FLUID_FAILED);
+ TEST_ASSERT(fluid_synth_set_chorus_group_nr(synth, 1, -1) == FLUID_FAILED);
+
+ // level valid range: 0..10
+ TEST_ASSERT(fluid_synth_set_chorus_group_level(synth, 0, 10.1) == FLUID_FAILED);
+ TEST_ASSERT(fluid_synth_set_chorus_group_level(synth, 0, -0.1) == FLUID_FAILED);
+
+ // lfo speed valid range: 0.1..5.0
+ TEST_ASSERT(fluid_synth_set_chorus_group_speed(synth, 0, 5.1) == FLUID_FAILED);
+ TEST_ASSERT(fluid_synth_set_chorus_group_speed(synth, 0, 0.09) == FLUID_FAILED);
+
+ // lfo depth valid range: 0..256
+ TEST_ASSERT(fluid_synth_set_chorus_group_depth(synth, 0, 256.1) == FLUID_FAILED);
+ TEST_ASSERT(fluid_synth_set_chorus_group_depth(synth, 0, -0.1) == FLUID_FAILED);
+
+ // lfo wafeform type valid range: 0..1
+ TEST_ASSERT(fluid_synth_set_chorus_group_type(synth, 0, 2) == FLUID_FAILED);
+ TEST_ASSERT(fluid_synth_set_chorus_group_type(synth, 0, -1) == FLUID_FAILED);
+
+ // set a value and check if we get the same value to reverb group 0
+ TEST_ASSERT(fluid_synth_set_reverb_group_roomsize(synth, 0, 0.1110) == FLUID_OK);
+ TEST_ASSERT(fluid_synth_set_reverb_group_damp(synth, 0, 0.2220) == FLUID_OK);
+ TEST_ASSERT(fluid_synth_set_reverb_group_width(synth, 0, 0.3330) == FLUID_OK);
+ TEST_ASSERT(fluid_synth_set_reverb_group_level(synth, 0, 0.4440) == FLUID_OK);
+
+ TEST_ASSERT(fluid_synth_get_reverb_group_roomsize(synth, 0, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.1110);
+ TEST_ASSERT(fluid_synth_get_reverb_group_damp(synth, 0, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.2220);
+ TEST_ASSERT(fluid_synth_get_reverb_group_width(synth, 0, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.3330);
+ TEST_ASSERT(fluid_synth_get_reverb_group_level(synth, 0, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.4440);
+
+ // set a value and check if we get the same value to reverb group 1
+ TEST_ASSERT(fluid_synth_set_reverb_group_roomsize(synth, 1, 0.1111) == FLUID_OK);
+ TEST_ASSERT(fluid_synth_set_reverb_group_damp(synth, 1, 0.2221) == FLUID_OK);
+ TEST_ASSERT(fluid_synth_set_reverb_group_width(synth, 1, 0.3331) == FLUID_OK);
+ TEST_ASSERT(fluid_synth_set_reverb_group_level(synth, 1, 0.4441) == FLUID_OK);
+
+ TEST_ASSERT(fluid_synth_get_reverb_group_roomsize(synth, 1, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.1111);
+ TEST_ASSERT(fluid_synth_get_reverb_group_damp(synth, 1, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.2221);
+ TEST_ASSERT(fluid_synth_get_reverb_group_width(synth, 1, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.3331);
+ TEST_ASSERT(fluid_synth_get_reverb_group_level(synth, 1, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.4441);
+
+ // set a value and check if we get the same value to chorus group 0
+ TEST_ASSERT(fluid_synth_set_chorus_group_nr(synth, 0, 20) == FLUID_OK);
+ TEST_ASSERT(fluid_synth_set_chorus_group_level(synth, 0, 0.5550) == FLUID_OK);
+ TEST_ASSERT(fluid_synth_set_chorus_group_speed(synth, 0, 0.6660) == FLUID_OK);
+ TEST_ASSERT(fluid_synth_set_chorus_group_depth(synth, 0, 0.7770) == FLUID_OK);
+ TEST_ASSERT(fluid_synth_set_chorus_group_type(synth, 0, 0) == FLUID_OK);
+
+ TEST_ASSERT(fluid_synth_get_chorus_group_nr(synth, 0, &int_value) == FLUID_OK);
+ TEST_ASSERT(int_value == 20);
+ TEST_ASSERT(fluid_synth_get_chorus_group_level(synth, 0, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.5550);
+ TEST_ASSERT(fluid_synth_get_chorus_group_speed(synth, 0, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.6660);
+ TEST_ASSERT(fluid_synth_get_chorus_group_depth(synth, 0, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.7770);
+ TEST_ASSERT(fluid_synth_get_chorus_group_type(synth, 0, &int_value) == FLUID_OK);
+ TEST_ASSERT(int_value == 0);
+
+ // set a value and check if we get the same value to chorus group 1
+ TEST_ASSERT(fluid_synth_set_chorus_group_nr(synth, 1, 21) == FLUID_OK);
+ TEST_ASSERT(fluid_synth_set_chorus_group_level(synth, 1, 0.5551) == FLUID_OK);
+ TEST_ASSERT(fluid_synth_set_chorus_group_speed(synth, 1, 0.6661) == FLUID_OK);
+ TEST_ASSERT(fluid_synth_set_chorus_group_depth(synth, 1, 0.7771) == FLUID_OK);
+ TEST_ASSERT(fluid_synth_set_chorus_group_type(synth, 1, 1) == FLUID_OK);
+
+ TEST_ASSERT(fluid_synth_get_chorus_group_nr(synth, 1, &int_value) == FLUID_OK);
+ TEST_ASSERT(int_value == 21);
+ TEST_ASSERT(fluid_synth_get_chorus_group_level(synth, 1, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.5551);
+ TEST_ASSERT(fluid_synth_get_chorus_group_speed(synth, 1, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.6661);
+ TEST_ASSERT(fluid_synth_get_chorus_group_depth(synth, 1, &value) == FLUID_OK);
+ TEST_ASSERT(value == 0.7771);
+ TEST_ASSERT(fluid_synth_get_chorus_group_type(synth, 1, &int_value) == FLUID_OK);
+ TEST_ASSERT(int_value == 1);
delete_fluid_synth(synth);
delete_fluid_settings(settings);