Add function API fluid_synth_mixer_set_mapping()

- Add fluid_synth_mixer_set_mapping() in fluid_synth.c.
- Add setter function fluid_rvoice_mixer_set_fx_out_mapping() in
  fluid_rvoice_mixer.c.
- Add command sechanmapout in fluid_cmd.c.
This commit is contained in:
jjceresa 2020-09-08 05:15:54 +02:00
parent ac62a8a41c
commit 0fa451f46b
6 changed files with 254 additions and 0 deletions

View file

@ -393,6 +393,10 @@ FLUIDSYNTH_API int fluid_synth_get_breath_mode(fluid_synth_t *synth,
FLUIDSYNTH_API int fluid_synth_mixer_get_mapping(fluid_synth_t *synth,
int chan, int *out_from_chan, int *fx_from_chan,
int *out_from_fx);
FLUIDSYNTH_API int fluid_synth_mixer_set_mapping(fluid_synth_t *synth,
int chan_to_out, int out_from_chan,
int chan_to_fx, int fx_from_chan,
int chanfx_to_out, int out_from_fx);
#ifdef __cplusplus
}

View file

@ -194,6 +194,10 @@ static const fluid_cmd_t fluid_commands[] =
"chanmap", "mixer", fluid_handle_chanmap,
"chanmap [chan1 chan2..] Print mapping of all or some MIDI channels"
},
{
"setchanmapout", "mixer", fluid_handle_setchanmapout,
"setchanmapout chan0 out0 [chan1 out1..] Set mapping MIDI channel to dry output"
},
/* reverb commands */
{
"rev_preset", "reverb", fluid_handle_reverbpreset,
@ -3410,6 +3414,92 @@ int fluid_handle_chanmap(void *data, int ac, char **av,
return 0;
}
/* type of MIDI channel mapping */
enum channel_mapping_type
{
MAP_CHAN_TO_OUT, /* mapping between MIDI channel and dry output index */
MAP_CHAN_TO_FX, /* mappping between MIDI channel and fx input index */
MAP_CHANFX_TO_OUT, /* mapping between FX output and dry output index */
NBR_MAPPING_TYPE
};
/*-----------------------------------------------------------------------------
Set a mapping to a MIDI channel
@param map_type type of mapping to set (see channel_mapping_type enum)
(MAP_CHAN_TO_OUT) Any MIDI channels mapped to any audio dry buffers:
setchanmapout chan0 out0 [chan1 out1 .. ..]
(MAP_CHAN_TO_FX) Any MIDI channel mapped to any fx unit input:
setchanmapfx chan0 fx0 [chan1 fx1 .. ..]
(MAP_CHANFX_TO_OUT) Any unit fx output mapped to any audio dry buffers:
setchanfxmapout chanfx0 out0 [chanfx1 out1 .. ..]
*/
static int fluid_setchanmap(void *data, int ac, char **av,
fluid_ostream_t out, int map_type)
{
static const char *name_cde[NBR_MAPPING_TYPE] =
{"setchanmapout", "setchanmapfx", "setchanfxmapout"};
static const char *too_few_arg_chan_map_msg[NBR_MAPPING_TYPE] =
{
"too few argument, chan out [chan out]...\n",
"too few argument, chan fx [chan fx]...\n",
"too few argument, chanfx out [chanfx out]...\n"
};
FLUID_ENTRY_COMMAND(data);
fluid_synth_t *synth = handler->synth;
int i, n ;
/* checks channels arguments by group of 2: chan1 val1 chan2 val1 .. ..*/
if(check_channels_group_arguments(ac, av, 2, out, name_cde[map_type],
too_few_arg_chan_map_msg[map_type]) < 0)
{
return -1;
}
n = ac / 2; /* number of groups information */
for(i = 0; i < n; i++)
{
struct
{
int chan;
int val;
}chan_val[NBR_MAPPING_TYPE] ={-1,0,-1,0,-1,0}; /* set all chan parameter to -1*/
int chan, val, result;
chan_val[map_type].chan = chan = atoi(av[(i * 2)]);
chan_val[map_type].val = val = atoi(av[(i * 2) + 1]);
/* set mapping */
result = fluid_synth_mixer_set_mapping(synth,
chan_val[MAP_CHAN_TO_OUT].chan,
chan_val[MAP_CHAN_TO_OUT].val,
chan_val[MAP_CHAN_TO_FX].chan,
chan_val[MAP_CHAN_TO_FX].val,
chan_val[MAP_CHANFX_TO_OUT].chan,
chan_val[MAP_CHAN_TO_OUT].val);
if(result == FLUID_FAILED)
{
fluid_ostream_printf(out, "%s: channel %3d, map to %3d, %s",
name_cde[map_type], chan, val, invalid_arg_msg);
}
}
return 0;
}
/*-----------------------------------------------------------------------------
setchanmapout chan0 out0 [chan1 out1 .. ..]
Set a mapping between a MIDI channel and a dry output index
*/
int fluid_handle_setchanmapout(void *data, int ac, char **av,
fluid_ostream_t out)
{
return fluid_setchanmap(data, ac, av, out, MAP_CHAN_TO_OUT);
}
#ifdef LADSPA
#define CHECK_LADSPA_ENABLED(_fx, _out) \

View file

@ -104,6 +104,7 @@ int fluid_handle_setbreathmode(void *data, int ac, char **av, fluid_ostream_t ou
int fluid_handle_sleep(void *data, int ac, char **av, fluid_ostream_t out);
int fluid_handle_chanmap(void *data, int ac, char **av,fluid_ostream_t out);
int fluid_handle_setchanmapout(void *data, int ac, char **av, fluid_ostream_t out);
#ifdef LADSPA
int fluid_handle_ladspa_effect(void *data, int ac, char **av, fluid_ostream_t out);

View file

@ -828,6 +828,46 @@ fluid_rvoice_mixer_get_fx_out_mapping(fluid_rvoice_mixer_t *mixer, int fxunit_id
return mixer->fx[fxunit_idx].to_out;
}
/*
Set internal mapping from a fx unit output to a dry buffer index.
*/
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_fx_set_mapping)
{
fluid_mixer_fx_t *fx = obj; /* array of fx unit */
int fxunit_idx = param[0].i; /* fx unit index */
int out_from_fx = param[1].i; /* index of dry output buffer*/
fx[fxunit_idx].mapping_to_out = out_from_fx;
}
/**
* Set mapping beetwen fx unit and audio dry output at index out_from_fx.
* @param mixer.
* @fxunit_idx, index of fx unit to which out_from_fx must be mapped.
* @out_from_fx, dry output index to map to fx unit.
*/
void fluid_rvoice_mixer_set_fx_out_mapping(fluid_rvoice_mixer_t *mixer,
int fxunit_idx, int out_from_fx)
{
fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
/* get fx unit */
fluid_mixer_fx_t *fx = mixer->fx;
/*
- First set shadow out_from_fx value here so that it will be returned
if queried.
- Then set the mapping value through the ring buffer.
*/
fx[fxunit_idx].to_out = out_from_fx; /* shadow value */
/* Set the mapping through the ring buffer. */
param[0].i = fxunit_idx; /* fx unit index */
param[1].i = out_from_fx; /* dry output index */
fluid_rvoice_eventhandler_push(mixer->eventhandler,
fluid_rvoice_mixer_fx_set_mapping,
fx, param);
}
static void
fluid_mixer_buffers_free(fluid_mixer_buffers_t *buffers)
{

View file

@ -42,6 +42,8 @@ fluid_rvoice_mixer_t *new_fluid_rvoice_mixer(int buf_count, int fx_buf_count, in
fluid_rvoice_eventhandler_t *, int, int);
int
fluid_rvoice_mixer_get_fx_out_mapping(fluid_rvoice_mixer_t *mixer, int fxunit_idx);
void fluid_rvoice_mixer_set_fx_out_mapping(fluid_rvoice_mixer_t *mixer,
int fxunit_idx, int out_from_fx);
void delete_fluid_rvoice_mixer(fluid_rvoice_mixer_t *);

View file

@ -7481,3 +7481,120 @@ fluid_synth_mixer_get_mapping(fluid_synth_t *synth,
FLUID_API_RETURN(FLUID_OK);
}
/**
* Set mixer MIDI channel mapping to audio buffers.
* These mapping allows:
* (1) Any MIDI channels mapped to any audio dry buffers.
* (2) Any MIDI channel mapped to any fx unit input .
* (3) Any unit fx output mapped to any audio dry buffers.
*
* The function allows the setting of mapping (1) or/and(2) or/and (3)
* simultaneously or not:
* 1)Mapping between MIDI channel chan_to_out and audio dry output at
* index out_from_chan. If chan_to_out is -1 this mapping is ignored,
* otherwise the mapping is done with the following special case:
* if out_from_chan is -1, this disable dry audio for this MIDI channel.
* This allows playing only fx (with dry muted temporarily).
*
* @param synth FluidSynth instance.
* @param chan_to_out, MIDI channel to which out_from_chan must be mapped.
* Must be in the range (-1 to MIDI channel count-1).
* @param out_from_chan, audio output index to map to chan_to_out.
* Must be in the range (-1 to synth->audio_groups-1).
*
* 2)Mapping between MIDI channel chan_to_fx and fx unit input at
* index fx_from_chan. If chan_to_fx is -1 this mapping is ignored,
* otherwise the mapping is done with the following special case:
* if fx_from_chan is -1, this disable fx audio for this MIDI channel.
* This allows playing only dry (with fx muted temporarily).
*
* @param chan_to_fx, MIDI channel to which fx_from_chan must be mapped.
* Must be in the range (-1 to MIDI channel count-1).
* @param fx_from_chan, fx unit input index to map to chan_to_fx.
* Must be in the range (-1 to synth->effects_groups-1).
*
* 3)Mapping beetwen fx unit output (which is mapped to chanfx_to_out) and
* audio dry output at index index out_from_fx. If chanfx_to_out is -1,
* this mapping is ignored.
*
* @param chanfx_to_out, indicates the fx unit (which is actually mapped
* to chanfx_to_out) whose output must be mapped with out_from_fx.
* Must be in the range (-1 to MIDI channel count-1).
* @param out_from_fx, audio output index that must be mapped to fx unit output
* (which is actually mapped to chanfx_to_out).
* Must be in the range (0 to synth->audio_groups-1).
*
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
*/
int
fluid_synth_mixer_set_mapping(fluid_synth_t *synth,
int chan_to_out, int out_from_chan,
int chan_to_fx, int fx_from_chan,
int chanfx_to_out, int out_from_fx)
{
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
fluid_synth_api_enter(synth);
/* Map chan_to_out and audio dry output if queried */
if(chan_to_out >= 0)
{
/* check chan_to_out and out_from_chan */
if((chan_to_out >= synth->midi_channels)
||(out_from_chan >= synth->audio_groups))
{
FLUID_API_RETURN(FLUID_FAILED);
}
/* Mapping between MIDI channel chan_to_out and audio dry output
at index out_from_chan.
*/
synth->channel[chan_to_out]->mapping_to_out = out_from_chan;
}
/* Map chan_to_fx and fx input index if queried */
if(chan_to_fx >= 0)
{
/* check chan_to_fx and fx_from_chan */
if((chan_to_fx >= synth->midi_channels)
||(fx_from_chan >= synth->effects_groups))
{
FLUID_API_RETURN(FLUID_FAILED);
}
/* Mapping between MIDI channel chan_to_fx and fx input
at index fx_from_chan.
*/
synth->channel[chan_to_fx]->mapping_to_fx = fx_from_chan;
}
/* Map fx unit output and audio dry output if queried */
if(chanfx_to_out >= 0)
{
int fxunit_idx; /* fx input which is actually mapped to chanfx_to_out*/
/* check chanfx_to_out and out_from_fx */
if((chanfx_to_out >= synth->midi_channels)
||(out_from_fx >= synth->audio_groups))
{
FLUID_API_RETURN(FLUID_FAILED);
}
/* get fx unit actually mapped to chanfx_fx_to out */
fxunit_idx = synth->channel[chanfx_to_out]->mapping_to_fx;
/* check if any fx unit has been mapped to chanfx_to_out */
if (fxunit_idx < 0)
{
FLUID_API_RETURN(FLUID_FAILED);
}
/* Mapping beetwen fx unit output and audio dry output
at index index out_from_fx.
*/
fluid_rvoice_mixer_set_fx_out_mapping(synth->eventhandler->mixer,
fxunit_idx, out_from_fx);
}
FLUID_API_RETURN(FLUID_OK);
}