mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2024-11-10 15:01:40 +00:00
Avoid redundant dsp parameter updates upon modulation. (#461)
This commit is contained in:
parent
98e4046096
commit
36da011191
1 changed files with 47 additions and 55 deletions
|
@ -516,7 +516,6 @@ fluid_voice_calculate_gen_pitch(fluid_voice_t *voice)
|
||||||
voice->gen[GEN_PITCH].val = fluid_voice_calculate_pitch(voice, fluid_voice_get_actual_key(voice));
|
voice->gen[GEN_PITCH].val = fluid_voice_calculate_pitch(voice, fluid_voice_get_actual_key(voice));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fluid_voice_calculate_runtime_synthesis_parameters
|
* fluid_voice_calculate_runtime_synthesis_parameters
|
||||||
*
|
*
|
||||||
|
@ -1153,7 +1152,9 @@ fluid_voice_update_param(fluid_voice_t *voice, int gen)
|
||||||
* Recalculate voice parameters for a given control.
|
* Recalculate voice parameters for a given control.
|
||||||
* @param voice the synthesis voice
|
* @param voice the synthesis voice
|
||||||
* @param cc flag to distinguish between a continous control and a channel control (pitch bend, ...)
|
* @param cc flag to distinguish between a continous control and a channel control (pitch bend, ...)
|
||||||
* @param ctrl the control number
|
* @param ctrl the control number:
|
||||||
|
* when >=0, only modulators's destination having ctrl as source are updated.
|
||||||
|
* when -1, all modulators's destination are updated (regardless of ctrl).
|
||||||
*
|
*
|
||||||
* In this implementation, I want to make sure that all controllers
|
* In this implementation, I want to make sure that all controllers
|
||||||
* are event based: the parameter values of the DSP algorithm should
|
* are event based: the parameter values of the DSP algorithm should
|
||||||
|
@ -1163,36 +1164,56 @@ fluid_voice_update_param(fluid_voice_t *voice, int gen)
|
||||||
*
|
*
|
||||||
* The update is done in three steps:
|
* The update is done in three steps:
|
||||||
*
|
*
|
||||||
* - first, we look for all the modulators that have the changed
|
* - step 1: first, we look for all the modulators that have the changed
|
||||||
* controller as a source. This will yield a list of generators that
|
* controller as a source. This will yield a list of generators that
|
||||||
* will be changed because of the controller event.
|
* will be changed because of the controller event.
|
||||||
*
|
*
|
||||||
* - For every changed generator, calculate its new value. This is the
|
* - step 2: For every changed generator, calculate its new value. This is the
|
||||||
* sum of its original value plus the values of al the attached
|
* sum of its original value plus the values of all the attached modulators.
|
||||||
* modulators.
|
* The generator flag is set to indicate the parameters must be updated.
|
||||||
*
|
*
|
||||||
* - For every changed generator, convert its value to the correct
|
* - step 3: We need to avoid the risk to call 'fluid_voice_update_param' several
|
||||||
* unit of the corresponding DSP parameter
|
* times for the same generator if several modulators have that generator as
|
||||||
|
* destination. So every changed generators are updated only once
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* bit table for each generator being updated. The bits are packed in variables
|
||||||
|
Each variable have NBR_BIT_BY_VAR bits represented by NBR_BIT_BY_VAR_LN2.
|
||||||
|
The size of the table is the number of variables: SIZE_UPDATED_GEN.
|
||||||
|
|
||||||
|
Note: In this implementation NBR_BIT_BY_VAR_LN2 is set to 5 (convenient for 32 bits cpu)
|
||||||
|
but this could be set to 6 for 64 bits cpu.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NBR_BIT_BY_VAR_LN2 5 /* for 32 bits variables */
|
||||||
|
#define NBR_BIT_BY_VAR (1 << NBR_BIT_BY_VAR_LN2)
|
||||||
|
#define NBR_BIT_BY_VAR_ANDMASK (NBR_BIT_BY_VAR - 1)
|
||||||
|
#define SIZE_UPDATED_GEN_BIT ((GEN_LAST + NBR_BIT_BY_VAR_ANDMASK) / NBR_BIT_BY_VAR)
|
||||||
|
|
||||||
|
#define is_gen_updated(bit,gen) (bit[gen >> NBR_BIT_BY_VAR_LN2] & (1 << (gen & NBR_BIT_BY_VAR_ANDMASK)))
|
||||||
|
#define set_gen_updated(bit,gen) (bit[gen >> NBR_BIT_BY_VAR_LN2] |= (1 << (gen & NBR_BIT_BY_VAR_ANDMASK)))
|
||||||
|
|
||||||
int fluid_voice_modulate(fluid_voice_t *voice, int cc, int ctrl)
|
int fluid_voice_modulate(fluid_voice_t *voice, int cc, int ctrl)
|
||||||
{
|
{
|
||||||
int i, k;
|
int i, k;
|
||||||
fluid_mod_t *mod;
|
fluid_mod_t *mod;
|
||||||
int gen;
|
uint32_t gen;
|
||||||
fluid_real_t modval;
|
fluid_real_t modval;
|
||||||
|
|
||||||
|
/* registered bits table of updated generators */
|
||||||
|
uint32_t updated_gen_bit[SIZE_UPDATED_GEN_BIT] = {0};
|
||||||
|
|
||||||
/* printf("Chan=%d, CC=%d, Src=%d, Val=%d\n", voice->channel->channum, cc, ctrl, val); */
|
/* printf("Chan=%d, CC=%d, Src=%d, Val=%d\n", voice->channel->channum, cc, ctrl, val); */
|
||||||
|
|
||||||
for(i = 0; i < voice->mod_count; i++)
|
for(i = 0; i < voice->mod_count; i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
mod = &voice->mod[i];
|
mod = &voice->mod[i];
|
||||||
|
|
||||||
/* step 1: find all the modulators that have the changed controller
|
/* step 1: find all the modulators that have the changed controller
|
||||||
* as input source. */
|
as input source. When ctrl is -1 all modulators's destination
|
||||||
if(fluid_mod_has_source(mod, cc, ctrl))
|
are updated */
|
||||||
|
if(ctrl < 0 || fluid_mod_has_source(mod, cc, ctrl))
|
||||||
{
|
{
|
||||||
|
|
||||||
gen = fluid_mod_get_dest(mod);
|
gen = fluid_mod_get_dest(mod);
|
||||||
modval = 0.0;
|
modval = 0.0;
|
||||||
|
|
||||||
|
@ -1207,10 +1228,17 @@ int fluid_voice_modulate(fluid_voice_t *voice, int cc, int ctrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_gen_set_mod(&voice->gen[gen], modval);
|
fluid_gen_set_mod(&voice->gen[gen], modval);
|
||||||
|
/* set the bit that indicates this generator is updated */
|
||||||
|
set_gen_updated(updated_gen_bit, gen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* step 3: now that we have the new value of the generator,
|
/* step 3: now recalculate the parameter values that are derived from the
|
||||||
* recalculate the parameter values that are derived from the
|
generator */
|
||||||
* generator */
|
for(gen = 0; gen < GEN_LAST; gen++)
|
||||||
|
{
|
||||||
|
if (is_gen_updated(updated_gen_bit, gen))
|
||||||
|
{
|
||||||
fluid_voice_update_param(voice, gen);
|
fluid_voice_update_param(voice, gen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1222,47 +1250,11 @@ int fluid_voice_modulate(fluid_voice_t *voice, int cc, int ctrl)
|
||||||
* Update all the modulators. This function is called after a
|
* Update all the modulators. This function is called after a
|
||||||
* ALL_CTRL_OFF MIDI message has been received (CC 121).
|
* ALL_CTRL_OFF MIDI message has been received (CC 121).
|
||||||
*
|
*
|
||||||
|
* All destination of all modulators must be updated.
|
||||||
*/
|
*/
|
||||||
int fluid_voice_modulate_all(fluid_voice_t *voice)
|
int fluid_voice_modulate_all(fluid_voice_t *voice)
|
||||||
{
|
{
|
||||||
fluid_mod_t *mod;
|
return fluid_voice_modulate(voice, 0, -1);
|
||||||
int i, k, gen;
|
|
||||||
fluid_real_t modval;
|
|
||||||
|
|
||||||
/* Loop through all the modulators.
|
|
||||||
|
|
||||||
FIXME: we should loop through the set of generators instead of
|
|
||||||
the set of modulators. We risk to call 'fluid_voice_update_param'
|
|
||||||
several times for the same generator if several modulators have
|
|
||||||
that generator as destination. It's not an error, just a wast of
|
|
||||||
energy (think polution, global warming, unhappy musicians,
|
|
||||||
...) */
|
|
||||||
|
|
||||||
for(i = 0; i < voice->mod_count; i++)
|
|
||||||
{
|
|
||||||
|
|
||||||
mod = &voice->mod[i];
|
|
||||||
gen = fluid_mod_get_dest(mod);
|
|
||||||
modval = 0.0;
|
|
||||||
|
|
||||||
/* Accumulate the modulation values of all the modulators with
|
|
||||||
* destination generator 'gen' */
|
|
||||||
for(k = 0; k < voice->mod_count; k++)
|
|
||||||
{
|
|
||||||
if(fluid_mod_has_dest(&voice->mod[k], gen))
|
|
||||||
{
|
|
||||||
modval += fluid_mod_get_value(&voice->mod[k], voice);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fluid_gen_set_mod(&voice->gen[gen], modval);
|
|
||||||
|
|
||||||
/* Update the parameter values that are depend on the generator
|
|
||||||
* 'gen' */
|
|
||||||
fluid_voice_update_param(voice, gen);
|
|
||||||
}
|
|
||||||
|
|
||||||
return FLUID_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** legato update functions --------------------------------------------------*/
|
/** legato update functions --------------------------------------------------*/
|
||||||
|
|
Loading…
Reference in a new issue