From c43f4da408969b599a9a77999204dd3adee72767 Mon Sep 17 00:00:00 2001 From: "Tom M." Date: Thu, 31 Oct 2024 14:29:17 +0100 Subject: [PATCH] Fix bugs in modulator handling (#1392) --- src/sfloader/fluid_defsfont.c | 23 ------------- src/synth/fluid_mod.c | 64 ++++++++++------------------------- src/synth/fluid_voice.c | 2 +- 3 files changed, 18 insertions(+), 71 deletions(-) diff --git a/src/sfloader/fluid_defsfont.c b/src/sfloader/fluid_defsfont.c index 75660c5c5..b601621e2 100644 --- a/src/sfloader/fluid_defsfont.c +++ b/src/sfloader/fluid_defsfont.c @@ -1616,18 +1616,6 @@ fluid_zone_mod_import_sfont(char *zone_name, fluid_mod_t **mod, SFZone *sfzone) /* This shouldn't happen - unknown type! * Deactivate the modulator by setting the amount to 0. */ mod_dest->amount = 0; - } - - /* 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 *** */ @@ -1639,17 +1627,6 @@ fluid_zone_mod_import_sfont(char *zone_name, fluid_mod_t **mod, SFZone *sfzone) /* This shouldn't happen - unknown type! * 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 flag 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)) - { - mod_dest->flags2 &= ~FLUID_MOD_BIPOLAR; } /** diff --git a/src/synth/fluid_mod.c b/src/synth/fluid_mod.c index ee1632074..c82a2790f 100644 --- a/src/synth/fluid_mod.c +++ b/src/synth/fluid_mod.c @@ -219,7 +219,7 @@ fluid_mod_get_source_value(const unsigned char mod_src, if(mod_src == PORTAMENTO_CTRL) { - // an invalid portamento fromkey should be treated as 0 when it's actually used for moulating + // an invalid portamento fromkey should be treated as 0 when it's actually used for modulating if(!fluid_channel_is_valid_note(val)) { val = 0; @@ -396,23 +396,17 @@ fluid_mod_transform_source_value(fluid_real_t val, unsigned char mod_flags, cons * * Output = Transform(Amount * Map(primary source input) * Map(secondary source input)) * - * Notes: - * 1)fluid_mod_get_value, ignores the Transform operator. The result is: + * Note: + * 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) { extern fluid_mod_t default_vel2filter_mod; - fluid_real_t v1 = 0.0, v2 = 1.0; + fluid_real_t v1, v2; fluid_real_t final_value; /* The wording of the default modulators refers to a range of 127/128. * And the table in section 9.5.3 suggests, that this mapping should be applied @@ -451,56 +445,32 @@ fluid_mod_get_value(fluid_mod_t *mod, fluid_voice_t *voice) * */ if(fluid_mod_test_identity(mod, &default_vel2filter_mod)) { -// S. Christian Collins' mod, to stop forcing velocity based filtering /* if (voice->vel < 64){ return (fluid_real_t) mod->amount / 2.0; } else { return (fluid_real_t) mod->amount * (127 - voice->vel) / 127; } + return (fluid_real_t) mod->amount / 2.0; */ - return 0; // (fluid_real_t) mod->amount / 2.0; + // S. Christian Collins' mod, to stop forcing velocity based filtering + return 0; } -// end S. Christian Collins' mod - - /* get the initial value of the first source */ - if(mod->src1 > 0) - { - v1 = fluid_mod_get_source_value(mod->src1, mod->flags1, &range1, 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; - } + /* Get the initial value of the first source. + * + * Even if the src is FLUID_MOD_NONE, the value has to be transformed, see #1389 + */ + v1 = fluid_mod_get_source_value(mod->src1, mod->flags1, &range1, voice); - /* no need to go further */ - if(v1 == 0.0f) - { - return 0.0f; - } + /* transform the input value */ + v1 = fluid_mod_transform_source_value(v1, mod->flags1, range1); /* get the second input source */ - if(mod->src2 > 0) - { - v2 = fluid_mod_get_source_value(mod->src2, mod->flags2, &range2, voice); + v2 = fluid_mod_get_source_value(mod->src2, mod->flags2, &range2, 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; - } + /* transform the second input value */ + v2 = fluid_mod_transform_source_value(v2, mod->flags2, range2); /* it indeed is as simple as that: */ final_value = (fluid_real_t) mod->amount * v1 * v2; diff --git a/src/synth/fluid_voice.c b/src/synth/fluid_voice.c index 1acd55032..f975ef50c 100644 --- a/src/synth/fluid_voice.c +++ b/src/synth/fluid_voice.c @@ -1791,7 +1791,7 @@ fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t *voice) 3)absolute value of amount. When at least one source mapping is bipolar: - min_val is -|amount| regardless the sign of amount. + 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