diff --git a/include/fluidsynth/synth.h b/include/fluidsynth/synth.h index 12cba85f..57212315 100644 --- a/include/fluidsynth/synth.h +++ b/include/fluidsynth/synth.h @@ -275,6 +275,19 @@ FLUIDSYNTH_API double fluid_synth_get_cpu_load(fluid_synth_t* synth); FLUIDSYNTH_API char* fluid_synth_error(fluid_synth_t* synth); +/* Default modulators */ + +/** + * Enum used with fluid_synth_add_default_mod() to specify how to handle duplicate modulators. + */ +enum fluid_synth_add_mod { + FLUID_SYNTH_OVERWRITE, /**< Overwrite any existing matching modulator */ + FLUID_SYNTH_ADD, /**< Add (sum) modulator amounts */ +}; + +FLUIDSYNTH_API int fluid_synth_add_default_mod(fluid_synth_t* synth, fluid_mod_t* mod, int mode); + + /* * Synthesizer plugin * diff --git a/src/synth/fluid_synth.c b/src/synth/fluid_synth.c index e1e1d813..0d9f355b 100644 --- a/src/synth/fluid_synth.c +++ b/src/synth/fluid_synth.c @@ -692,6 +692,21 @@ new_fluid_synth(fluid_settings_t *settings) if (synth->eventhandler == NULL) goto error_recovery; + /* Setup the list of default modulators. + * Needs to happen after eventhandler has been set up, as fluid_synth_enter_api is called in the process */ + synth->default_mod = NULL; + fluid_synth_add_default_mod(synth, &default_vel2att_mod, FLUID_SYNTH_ADD); + fluid_synth_add_default_mod(synth, &default_vel2filter_mod, FLUID_SYNTH_ADD); + fluid_synth_add_default_mod(synth, &default_at2viblfo_mod, FLUID_SYNTH_ADD); + fluid_synth_add_default_mod(synth, &default_mod2viblfo_mod, FLUID_SYNTH_ADD); + fluid_synth_add_default_mod(synth, &default_att_mod, FLUID_SYNTH_ADD); + fluid_synth_add_default_mod(synth, &default_pan_mod, FLUID_SYNTH_ADD); + fluid_synth_add_default_mod(synth, &default_expr_mod, FLUID_SYNTH_ADD); + fluid_synth_add_default_mod(synth, &default_reverb_mod, FLUID_SYNTH_ADD); + fluid_synth_add_default_mod(synth, &default_chorus_mod, FLUID_SYNTH_ADD); + fluid_synth_add_default_mod(synth, &default_pitch_bend_mod, FLUID_SYNTH_ADD); + + #ifdef LADSPA /* Create and initialize the Fx unit.*/ fluid_settings_getint(settings, "synth.ladspa.active", &with_ladspa); @@ -811,6 +826,8 @@ delete_fluid_synth(fluid_synth_t* synth) fluid_list_t *list; fluid_sfont_info_t* sfont_info; fluid_sfloader_t* loader; + fluid_mod_t* default_mod; + fluid_mod_t* mod; if (synth == NULL) { return FLUID_OK; @@ -918,6 +935,14 @@ delete_fluid_synth(fluid_synth_t* synth) } #endif + /* delete all default modulators */ + default_mod = synth->default_mod; + while (default_mod != NULL) { + mod = default_mod; + default_mod = mod->next; + fluid_mod_delete(mod); + } + fluid_rec_mutex_destroy(synth->mutex); FLUID_FREE(synth); @@ -1079,6 +1104,58 @@ fluid_synth_damp_voices_by_sostenuto_LOCAL(fluid_synth_t* synth, int chan) return FLUID_OK; } +/** + * Adds the specified modulator \c mod as default modulator to the synth. If \c mod is new it + * will be used by any subsequently created voice. If an amount of an existing modulator is + * changed by \c mod it will take effect for any subsequently created voice. + * @param synth FluidSynth instance + * @param mod Modulator info (values copied, passed in object can be freed again immediately) + * @param mode Determines how to handle an existing identical modulator (#fluid_synth_add_mod) + * @return FLUID_OK on success, FLUID_FAILED otherwise + */ +int +fluid_synth_add_default_mod(fluid_synth_t* synth, fluid_mod_t* mod, int mode) +{ + fluid_mod_t* default_mod; + fluid_mod_t* last_mod = NULL; + fluid_mod_t* new_mod; + + fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); + fluid_return_val_if_fail (mod != NULL, FLUID_FAILED); + fluid_synth_api_enter(synth); + + default_mod = synth->default_mod; + + while (default_mod != NULL) { + if (fluid_mod_test_identity(default_mod, mod)) { + if (mode == FLUID_SYNTH_ADD) + default_mod->amount += mod->amount; + else if (mode == FLUID_SYNTH_OVERWRITE) + default_mod->amount = mod->amount; + else + FLUID_API_RETURN(FLUID_FAILED); + FLUID_API_RETURN(FLUID_OK); + } + last_mod = default_mod; + default_mod = default_mod->next; + } + + /* Add a new modulator (no existing modulator to add / overwrite). */ + new_mod = fluid_mod_new(); + if (new_mod == NULL) + FLUID_API_RETURN(FLUID_FAILED); + + fluid_mod_clone(new_mod, mod); + new_mod->next = NULL; + + if (last_mod == NULL) + synth->default_mod = new_mod; + else + last_mod->next = new_mod; + + FLUID_API_RETURN(FLUID_OK); +} + /** * Send a MIDI controller event on a MIDI channel. @@ -3142,6 +3219,7 @@ fluid_synth_alloc_voice(fluid_synth_t* synth, fluid_sample_t* sample, int chan, int i, k; fluid_voice_t* voice = NULL; fluid_channel_t* channel = NULL; + fluid_mod_t* default_mod; unsigned int ticks; fluid_return_val_if_fail (sample != NULL, NULL); @@ -3194,16 +3272,11 @@ fluid_synth_alloc_voice(fluid_synth_t* synth, fluid_sample_t* sample, int chan, } /* add the default modulators to the synthesis process. */ - fluid_voice_add_mod(voice, &default_vel2att_mod, FLUID_VOICE_DEFAULT); /* SF2.01 $8.4.1 */ - fluid_voice_add_mod(voice, &default_vel2filter_mod, FLUID_VOICE_DEFAULT); /* SF2.01 $8.4.2 */ - fluid_voice_add_mod(voice, &default_at2viblfo_mod, FLUID_VOICE_DEFAULT); /* SF2.01 $8.4.3 */ - fluid_voice_add_mod(voice, &default_mod2viblfo_mod, FLUID_VOICE_DEFAULT); /* SF2.01 $8.4.4 */ - fluid_voice_add_mod(voice, &default_att_mod, FLUID_VOICE_DEFAULT); /* SF2.01 $8.4.5 */ - fluid_voice_add_mod(voice, &default_pan_mod, FLUID_VOICE_DEFAULT); /* SF2.01 $8.4.6 */ - fluid_voice_add_mod(voice, &default_expr_mod, FLUID_VOICE_DEFAULT); /* SF2.01 $8.4.7 */ - fluid_voice_add_mod(voice, &default_reverb_mod, FLUID_VOICE_DEFAULT); /* SF2.01 $8.4.8 */ - fluid_voice_add_mod(voice, &default_chorus_mod, FLUID_VOICE_DEFAULT); /* SF2.01 $8.4.9 */ - fluid_voice_add_mod(voice, &default_pitch_bend_mod, FLUID_VOICE_DEFAULT); /* SF2.01 $8.4.10 */ + default_mod = synth->default_mod; + while (default_mod != NULL) { + fluid_voice_add_mod(voice, default_mod, FLUID_VOICE_DEFAULT); + default_mod = default_mod->next; + } FLUID_API_RETURN(voice); } diff --git a/src/synth/fluid_synth.h b/src/synth/fluid_synth.h index 7280d78e..476b006b 100644 --- a/src/synth/fluid_synth.h +++ b/src/synth/fluid_synth.h @@ -167,6 +167,8 @@ struct _fluid_synth_t int cores; /**< Number of CPU cores (1 by default) */ + fluid_mod_t* default_mod; /**< the (dynamic) list of default modulators */ + #ifdef LADSPA fluid_LADSPA_FxUnit_t* LADSPA_FxUnit; /**< Effects unit for LADSPA support */ #endif