diff --git a/include/fluidsynth/mod.h b/include/fluidsynth/mod.h index a0965d000..c303b214c 100644 --- a/include/fluidsynth/mod.h +++ b/include/fluidsynth/mod.h @@ -57,6 +57,15 @@ enum fluid_mod_flags FLUID_MOD_SIN = 0x80, /**< Custom non-standard sinus mapping function */ }; +/** + * Transform types for the SoundFont2 modulators. + */ +enum fluid_mod_transforms +{ + FLUID_MOD_LINEAR_TRANSFORM = 0, /* **< Linear: directly add the computed value to summing node */ + FLUID_MOD_ABS_VALUE = 2 /* **< Absolute value: add abs of the computed value */ +}; + /** * General controller (if #FLUID_MOD_GC in flags). This * corresponds to SoundFont 2.04 PDF section 8.2.1 @@ -83,6 +92,7 @@ FLUIDSYNTH_API void fluid_mod_set_source1(fluid_mod_t *mod, int src, int flags); FLUIDSYNTH_API void fluid_mod_set_source2(fluid_mod_t *mod, int src, int flags); FLUIDSYNTH_API void fluid_mod_set_dest(fluid_mod_t *mod, int dst); FLUIDSYNTH_API void fluid_mod_set_amount(fluid_mod_t *mod, double amount); +FLUIDSYNTH_API void fluid_mod_set_transform(fluid_mod_t *mod, int type); FLUIDSYNTH_API int fluid_mod_get_source1(const fluid_mod_t *mod); FLUIDSYNTH_API int fluid_mod_get_flags1(const fluid_mod_t *mod); @@ -90,6 +100,7 @@ FLUIDSYNTH_API int fluid_mod_get_source2(const fluid_mod_t *mod); FLUIDSYNTH_API int fluid_mod_get_flags2(const fluid_mod_t *mod); FLUIDSYNTH_API int fluid_mod_get_dest(const fluid_mod_t *mod); FLUIDSYNTH_API double fluid_mod_get_amount(const fluid_mod_t *mod); +FLUIDSYNTH_API int fluid_mod_get_transform(fluid_mod_t *mod); FLUIDSYNTH_API int fluid_mod_test_identity(const fluid_mod_t *mod1, const fluid_mod_t *mod2); FLUIDSYNTH_API int fluid_mod_has_source(const fluid_mod_t *mod, int cc, int ctrl); diff --git a/src/sfloader/fluid_defsfont.c b/src/sfloader/fluid_defsfont.c index 91ce38dfb..55e9677f6 100644 --- a/src/sfloader/fluid_defsfont.c +++ b/src/sfloader/fluid_defsfont.c @@ -1648,8 +1648,20 @@ fluid_zone_mod_import_sfont(char *zone_name, fluid_mod_t **mod, SFZone *sfzone) mod_dest->flags2 &= ~FLUID_MOD_BIPOLAR; } - /* *** Transform Type *** */ - mod_dest->trans = mod_src->trans; + /** + * *** Transform Type *** + * Only 2 types of transform are defined in the sf2 specification. + */ + if(mod_src->trans != FLUID_MOD_LINEAR_TRANSFORM && mod_src->trans != FLUID_MOD_ABS_VALUE) + { + /* disable the modulator as the transform is invalid */ + mod_dest->amount = 0; + mod_dest->trans = FLUID_MOD_LINEAR_TRANSFORM; + } + else + { + mod_dest->trans = mod_src->trans; + } /* Store the new modulator in the zone The order of modulators * will make a difference, at least in an instrument context: The diff --git a/src/synth/fluid_mod.c b/src/synth/fluid_mod.c index 3df5d085e..1868c9f0a 100644 --- a/src/synth/fluid_mod.c +++ b/src/synth/fluid_mod.c @@ -98,6 +98,24 @@ fluid_mod_set_amount(fluid_mod_t *mod, double amount) mod->amount = (double) amount; } +/** + * Set the transform type of a modulator. + * + * @param mod The modulator instance + * @param type Transform type + */ +void +fluid_mod_set_transform(fluid_mod_t *mod, int type) +{ + unsigned char flag = (unsigned char) type; + if(flag != FLUID_MOD_LINEAR_TRANSFORM && flag != FLUID_MOD_ABS_VALUE) + { + /* invalid transform */ + return; + } + mod->trans = flag; +} + /** * Get the primary source value from a modulator. * @@ -170,6 +188,18 @@ fluid_mod_get_amount(const fluid_mod_t *mod) return (double) mod->amount; } +/** + * Get the transform type of a modulator. + * + * @param mod The modulator instance + * @return Transform type + */ +int +fluid_mod_get_transform(fluid_mod_t *mod) +{ + return (int) mod->trans; +} + /* * retrieves the initial value from the given source of the modulator */ @@ -474,10 +504,11 @@ fluid_mod_get_value(fluid_mod_t *mod, fluid_voice_t *voice) /* it indeed is as simple as that: */ final_value = (fluid_real_t) mod->amount * v1 * v2; - /* check for absolute value transform*/ - if(mod->trans == 2) + + /* check for absolute value transform */ + if(mod->trans == FLUID_MOD_ABS_VALUE) { - final_value = fabs(final_value); + final_value = FLUID_FABS(final_value); } return final_value; } @@ -497,7 +528,8 @@ new_fluid_mod(void) FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } - + // for the sake of backward compatibility + mod->trans = FLUID_MOD_LINEAR_TRANSFORM; return mod; }