From 06bca9b8946969bcefb66bd27bc7c10dc1df5467 Mon Sep 17 00:00:00 2001 From: jjceresa Date: Sun, 16 Dec 2018 07:57:51 +0100 Subject: [PATCH 1/3] Fix minor bug in lower_boundary_for_attenuation() - v variable is renamed min_val for clarity. - This fix a bug when calculating the possible minimun value (min_val) of a modulator. min_val should only be dependant of: - signs of mapped sources (ie bipolar [-1..+1] or unipolar [0..+1]) - sign of amount. - absolute value of amount. --- src/synth/fluid_voice.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/synth/fluid_voice.c b/src/synth/fluid_voice.c index 38b4bfe6..63bb88cf 100644 --- a/src/synth/fluid_voice.c +++ b/src/synth/fluid_voice.c @@ -1696,9 +1696,10 @@ int fluid_voice_get_velocity(const fluid_voice_t *voice) * A lower boundary for the attenuation (as in 'the minimum * attenuation of this voice, with volume pedals, modulators * etc. resulting in minimum attenuation, cannot fall below x cB) is - * calculated. This has to be called during fluid_voice_init, after + * calculated. This has to be called during fluid_voice_start, after * all modulators have been run on the voice once. Also, * voice->attenuation has to be initialized. + * (see fluid_voice_calculate_runtime_synthesis_parameters()) */ static fluid_real_t fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t *voice) @@ -1725,30 +1726,42 @@ fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t *voice) { fluid_real_t current_val = fluid_mod_get_value(mod, voice); - fluid_real_t v = fabs(mod->amount); + /* min_val is the possible minimum value for this modulator. + it depends of 3 things : + 1)the minimum values of src1,src2 (i.e -1 if mapping is bipolar + or 0 if mapping is unipolar). + 2)the sign of amount. + 3)absolute value of amount. - if((mod->src1 == FLUID_MOD_PITCHWHEEL) - || (mod->flags1 & FLUID_MOD_BIPOLAR) + When at least one source mapping is bipolar: + min_val is -|amount| regardless the sign of amount. + When both sources mapping are unipolar: + min_val is -|amount|, if amount is negative. + min_val is 0, if amount is positive + */ + fluid_real_t min_val = fabs(mod->amount); + + /* Can this modulator produce a negative contribution? */ + if((mod->flags1 & FLUID_MOD_BIPOLAR) || (mod->flags2 & FLUID_MOD_BIPOLAR) || (mod->amount < 0)) { - /* Can this modulator produce a negative contribution? */ - v *= -1.0; + min_val *= -1.0; /* min_val = - |amount|*/ } else { /* No negative value possible. But still, the minimum contribution is 0. */ - v = 0; + min_val = 0; } /* For example: * - current_val=100 * - min_val=-4000 - * - possible_att_reduction_cB += 4100 + * - possible reduction contribution of this modulator = current_val - min_val = 4100 */ - if(current_val > v) + if(current_val > min_val) { - possible_att_reduction_cB += (current_val - v); + possible_att_reduction_cB += (current_val - min_val); } } } From b659fd82a5037b2b0e49d7c2a59e86252fe16c39 Mon Sep 17 00:00:00 2001 From: jjceresa Date: Wed, 19 Dec 2018 18:12:09 +0100 Subject: [PATCH 2/3] Import modulator source src2 correctly. - When secondary source input (src2) is set to General Controller 'No Controller', output will be forced to +1.0 at synthesis time (see fluid_mod_get_value()). That means that this source will behave unipolar only. We need to force the unipolar flags to ensure the modulator will behave correctly later in fluid_voice_get_lower_boundary_for_attenuation(). --- src/sfloader/fluid_defsfont.c | 10 ++++++++++ src/synth/fluid_mod.c | 23 ++++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/sfloader/fluid_defsfont.c b/src/sfloader/fluid_defsfont.c index 1931d4ee..9a8f3245 100644 --- a/src/sfloader/fluid_defsfont.c +++ b/src/sfloader/fluid_defsfont.c @@ -1364,6 +1364,16 @@ fluid_zone_mod_import_sfont(fluid_mod_t **mod, SFZone *sfzone) * Deactivate the modulator by setting the amount to 0. */ mod_dest->amount = 0; } + /* Note: When secondary source input (src2) is set to General Controller 'No Controller', + output will be forced to +1.0 at synthesis time (see fluid_mod_get_value()). + That means that this source will behave unipolar only. We need to force the + unipolar flags to ensure the modulator will behave correctly later. + */ + if(((mod_dest->flags2 & FLUID_MOD_CC) == FLUID_MOD_GC) && + (mod_dest->src2 == FLUID_MOD_NONE)) + { + mod_dest->flags2 &= ~FLUID_MOD_BIPOLAR; + } /* *** Transform *** */ /* SF2.01 only uses the 'linear' transform (0). diff --git a/src/synth/fluid_mod.c b/src/synth/fluid_mod.c index 9a48ed45..db59642b 100644 --- a/src/synth/fluid_mod.c +++ b/src/synth/fluid_mod.c @@ -364,7 +364,22 @@ fluid_mod_transform_source_value(fluid_real_t val, unsigned char mod_flags, cons } /* - * fluid_mod_get_value + * fluid_mod_get_value. + * Computes and return modulator output following SF2.01 + * (See SoundFont Modulator Controller Model Chapter 9.5). + * + * Output = Transform(Amount * Map(primary source input) * Map(secondary source input)) + * + * Notes: + * 1)fluid_mod_get_value, ignores the Transform operator. The result is: + * + * Output = Amount * Map(primary source input) * Map(secondary source input) + * + * 2)When primary source input (src1) is set to General Controller 'No Controller', + * output is forced to 0. + * + * 3)When secondary source input (src2) is set to General Controller 'No Controller', + * output is forced to +1.0 */ fluid_real_t fluid_mod_get_value(fluid_mod_t *mod, fluid_voice_t *voice) @@ -418,6 +433,9 @@ fluid_mod_get_value(fluid_mod_t *mod, fluid_voice_t *voice) /* transform the input value */ v1 = fluid_mod_transform_source_value(v1, mod->flags1, range1); } + /* When primary source input (src1) is set to General Controller 'No Controller', + output is forced to 0.0 + */ else { return 0.0; @@ -437,6 +455,9 @@ fluid_mod_get_value(fluid_mod_t *mod, fluid_voice_t *voice) /* transform the second input value */ v2 = fluid_mod_transform_source_value(v2, mod->flags2, range2); } + /* When secondary source input (src2) is set to General Controller 'No Controller', + output is forced to +1.0 + */ else { v2 = 1.0f; From e8dd6ae3892d8aa8d524b46f38dda6227805cfa0 Mon Sep 17 00:00:00 2001 From: jjceresa Date: Fri, 21 Dec 2018 12:13:28 +0100 Subject: [PATCH 3/3] Import modulator source src1 correctly. - When primary source input (src1) is set to General Controller 'No Controller', output will be forced to 0.0 at synthesis time (see fluid_mod_get_value()). That means that the minimum value of the modulator will be always 0.0. We need to force amount value to 0 to ensure a correct evaluation of the minimum value later (see fluid_voice_get_lower_boundary_for_attenuation()). --- src/sfloader/fluid_defsfont.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/sfloader/fluid_defsfont.c b/src/sfloader/fluid_defsfont.c index 9a8f3245..b81aaca2 100644 --- a/src/sfloader/fluid_defsfont.c +++ b/src/sfloader/fluid_defsfont.c @@ -1354,7 +1354,20 @@ fluid_zone_mod_import_sfont(fluid_mod_t **mod, SFZone *sfzone) * Deactivate the modulator by setting the amount to 0. */ mod_dest->amount = 0; } - /* *** Dest *** */ + + /* Note: When primary source input (src1) is set to General Controller 'No Controller', + output will be forced to 0.0 at synthesis time (see fluid_mod_get_value()). + That means that the minimum value of the modulator will be always 0.0. + We need to force amount value to 0 to ensure a correct evaluation of the minimum + value later (see fluid_voice_get_lower_boundary_for_attenuation()). + */ + if(((mod_dest->flags1 & FLUID_MOD_CC) == FLUID_MOD_GC) && + (mod_dest->src1 == FLUID_MOD_NONE)) + { + mod_dest->amount = 0; + } + + /* *** Dest *** */ mod_dest->dest = mod_src->dest; /* index of controlled generator */ /* *** Amount source *** */ @@ -1367,7 +1380,8 @@ fluid_zone_mod_import_sfont(fluid_mod_t **mod, SFZone *sfzone) /* Note: When secondary source input (src2) is set to General Controller 'No Controller', output will be forced to +1.0 at synthesis time (see fluid_mod_get_value()). That means that this source will behave unipolar only. We need to force the - unipolar flags to ensure the modulator will behave correctly later. + unipolar flag to ensure to ensure a correct evaluation of the minimum + value later (see fluid_voice_get_lower_boundary_for_attenuation()). */ if(((mod_dest->flags2 & FLUID_MOD_CC) == FLUID_MOD_GC) && (mod_dest->src2 == FLUID_MOD_NONE))