Fx unit api (#673)

This PR addresses #669 point 2.1.
It proposes set/get API functions to change/read fx unit parameters.
The deprecated shell commands are updated. Now the commands line have 2 parameters:
- first parameter is the fx unit index.
- second parameter is the value to apply to the fx unit.
This commit is contained in:
jjceresa 2020-11-22 21:02:06 +01:00 committed by GitHub
parent 0c34b3d56c
commit c9b187bd85
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 1668 additions and 594 deletions

View File

@ -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?

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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

View File

@ -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);