From 0921ccc4c08f53fe4e5b20824589a37dbce0e579 Mon Sep 17 00:00:00 2001 From: jjceresa <32781294+jjceresa@users.noreply.github.com> Date: Fri, 15 Jun 2018 18:42:15 +0200 Subject: [PATCH] introducing FLUID_PEAK_ATTENUATION macro. (#397) avoids hard-coding the magic 96 dB everywhere in the code --- src/rvoice/fluid_rvoice.c | 7 ++++--- src/rvoice/fluid_rvoice.h | 1 - src/synth/fluid_synth.c | 12 ++++++------ src/utils/fluid_conv.c | 2 +- src/utils/fluid_conv.h | 31 +++++++++++++++++++++++++++++++ 5 files changed, 42 insertions(+), 11 deletions(-) diff --git a/src/rvoice/fluid_rvoice.c b/src/rvoice/fluid_rvoice.c index 436dda7e..fa67f281 100644 --- a/src/rvoice/fluid_rvoice.c +++ b/src/rvoice/fluid_rvoice.c @@ -51,7 +51,7 @@ fluid_rvoice_calc_amp(fluid_rvoice_t* voice) fluid_real_t amp_max; target_amp = fluid_cb2amp (voice->dsp.attenuation) - * fluid_cb2amp (960.0f * (1.0f - fluid_adsr_env_get_val(&voice->envlfo.volenv)) + * fluid_cb2amp (FLUID_PEAK_ATTENUATION * (1.0f - fluid_adsr_env_get_val(&voice->envlfo.volenv)) + fluid_lfo_get_val(&voice->envlfo.modlfo) * -voice->envlfo.modlfo_to_vol); /* We turn off a voice, if the volume has dropped low enough. */ @@ -507,7 +507,7 @@ fluid_rvoice_noteoff_LOCAL(fluid_rvoice_t* voice, unsigned int min_ticks) if (fluid_adsr_env_get_val(&voice->envlfo.volenv) > 0){ fluid_real_t lfo = fluid_lfo_get_val(&voice->envlfo.modlfo) * -voice->envlfo.modlfo_to_vol; fluid_real_t amp = fluid_adsr_env_get_val(&voice->envlfo.volenv) * fluid_cb2amp(lfo); - fluid_real_t env_value = - ((-200 * log (amp) / log (10.0) - lfo) / 960.0 - 1); + fluid_real_t env_value = - ((-200 * log (amp) / log (10.0) - lfo) / FLUID_PEAK_ATTENUATION - 1); fluid_clip (env_value, 0.0, 1.0); fluid_adsr_env_set_val(&voice->envlfo.volenv, env_value); } @@ -569,7 +569,8 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_multi_retrigger_attack) volenv_val to achieve equivalent amplitude during the attack phase for seamless volume transition. */ fluid_real_t amp_cb, env_value; - amp_cb = 960.0f * (1.0f - fluid_adsr_env_get_val(&voice->envlfo.volenv)); + amp_cb = FLUID_PEAK_ATTENUATION * + (1.0f - fluid_adsr_env_get_val(&voice->envlfo.volenv)); env_value = fluid_cb2amp(amp_cb); /* a bit of optimization */ fluid_clip (env_value, 0.0, 1.0); fluid_adsr_env_set_val(&voice->envlfo.volenv, env_value); diff --git a/src/rvoice/fluid_rvoice.h b/src/rvoice/fluid_rvoice.h index b36e75ec..2b81646a 100644 --- a/src/rvoice/fluid_rvoice.h +++ b/src/rvoice/fluid_rvoice.h @@ -41,7 +41,6 @@ typedef struct _fluid_rvoice_t fluid_rvoice_t; */ #define FLUID_NOISE_FLOOR 2.e-7 - enum fluid_loop { FLUID_UNLOOPED = 0, FLUID_LOOP_DURING_RELEASE = 1, diff --git a/src/synth/fluid_synth.c b/src/synth/fluid_synth.c index 03173465..523645ec 100644 --- a/src/synth/fluid_synth.c +++ b/src/synth/fluid_synth.c @@ -305,7 +305,7 @@ fluid_synth_init(void) ); fluid_mod_set_source2(&custom_breath2att_mod, 0, 0); /* No 2nd source */ fluid_mod_set_dest(&custom_breath2att_mod, GEN_ATTENUATION); /* Target: Initial attenuation */ - fluid_mod_set_amount(&custom_breath2att_mod, 960.0); /* Modulation amount: 960 */ + fluid_mod_set_amount(&custom_breath2att_mod, FLUID_PEAK_ATTENUATION); /* Modulation amount: 960 */ /* SF2.01 page 53 section 8.4.1: MIDI Note-On Velocity to Initial Attenuation */ fluid_mod_set_source1(&default_vel2att_mod, /* The modulator we are programming here */ @@ -317,7 +317,7 @@ fluid_synth_init(void) ); fluid_mod_set_source2(&default_vel2att_mod, 0, 0); /* No 2nd source */ fluid_mod_set_dest(&default_vel2att_mod, GEN_ATTENUATION); /* Target: Initial attenuation */ - fluid_mod_set_amount(&default_vel2att_mod, 960.0); /* Modulation amount: 960 */ + fluid_mod_set_amount(&default_vel2att_mod, FLUID_PEAK_ATTENUATION); /* Modulation amount: 960 */ @@ -381,7 +381,7 @@ fluid_synth_init(void) ); fluid_mod_set_source2(&default_att_mod, 0, 0); /* No second source */ fluid_mod_set_dest(&default_att_mod, GEN_ATTENUATION); /* Target: Initial attenuation */ - fluid_mod_set_amount(&default_att_mod, 960.0); /* Amount: 960 */ + fluid_mod_set_amount(&default_att_mod, FLUID_PEAK_ATTENUATION); /* Amount: 960 */ @@ -409,7 +409,7 @@ fluid_synth_init(void) ); fluid_mod_set_source2(&default_expr_mod, 0, 0); /* No second source */ fluid_mod_set_dest(&default_expr_mod, GEN_ATTENUATION); /* Target: Initial attenuation */ - fluid_mod_set_amount(&default_expr_mod, 960.0); /* Amount: 960 */ + fluid_mod_set_amount(&default_expr_mod, FLUID_PEAK_ATTENUATION); /* Amount: 960 */ @@ -464,9 +464,9 @@ fluid_synth_init(void) | FLUID_MOD_POSITIVE /* D=0 */ ); fluid_mod_set_source2(&custom_balance_mod, 0, 0); - fluid_mod_set_dest(&custom_balance_mod, GEN_CUSTOM_BALANCE); /* Destination: stereo balance */ + fluid_mod_set_dest(&custom_balance_mod, GEN_CUSTOM_BALANCE); /* Destination: stereo balance */ /* Amount: 96 dB of attenuation (on the opposite channel) */ - fluid_mod_set_amount(&custom_balance_mod, 960.0); + fluid_mod_set_amount(&custom_balance_mod, FLUID_PEAK_ATTENUATION); /* Amount: 960 */ } static FLUID_INLINE unsigned int fluid_synth_get_ticks(fluid_synth_t* synth) diff --git a/src/utils/fluid_conv.c b/src/utils/fluid_conv.c index 40942bdf..fbf61da6 100644 --- a/src/utils/fluid_conv.c +++ b/src/utils/fluid_conv.c @@ -71,7 +71,7 @@ fluid_conversion_config(void) implemented according to the pictures on SF2.01 page 73. */ for (i = 1; i < FLUID_VEL_CB_SIZE - 1; i++) { - x = -20.0 / 96.0 * log((i * i) / (fluid_real_t)((FLUID_VEL_CB_SIZE-1) * (FLUID_VEL_CB_SIZE-1))) / M_LN10; + x = (-200.0 / FLUID_PEAK_ATTENUATION) * log((i * i) / (fluid_real_t)((FLUID_VEL_CB_SIZE-1) * (FLUID_VEL_CB_SIZE-1))) / M_LN10; fluid_convex_tab[i] = (fluid_real_t) (1.0 - x); fluid_concave_tab[(FLUID_VEL_CB_SIZE-1) - i] = (fluid_real_t) x; } diff --git a/src/utils/fluid_conv.h b/src/utils/fluid_conv.h index 9e4553fd..6049cfd3 100644 --- a/src/utils/fluid_conv.h +++ b/src/utils/fluid_conv.h @@ -23,6 +23,37 @@ #include "fluidsynth_priv.h" +/* + Attenuation range in centibels. + Attenuation range is the dynamic range of the volume envelope generator + from 0 to the end of attack segment. + fluidsynth is a 24 bit synth, it could (should??) be 144 dB of attenuation. + However the spec makes no distinction between 16 or 24 bit synths, so use + 96 dB here. + + Note about usefulness of 24 bits: + 1)Even fluidsynth is a 24 bit synth, this format is only relevant if + the sample format coming from the soundfont is 24 bits and the audio sample format + choosen by the application (audio.sample.format) is not 16 bits. + + 2)When the sample soundfont is 16 bits, the internal 24 bits number have + 16 bits msb and lsb to 0. Consequently, at the DAC output, the dynamic range of + this 24 bit sample is reduced to the the dynamic of a 16 bits sample (ie 90 db) + even if this sample is produced by the audio driver using an audio sample format + compatible for a 24 bit DAC. + + 3)When the audio sample format settings is 16 bits (audio.sample.format), the + audio driver will make use of a 16 bit DAC, and the dynamic will be reduced to 96 dB + even if the initial sample comes from a 24 bits soundfont. + + In both cases (2) or (3), the real dynamic range is only 96 dB. + + Other consideration for FLUID_NOISE_FLOOR related to case (1),(2,3): + - for case (1), FLUID_NOISE_FLOOR should be the noise floor for 24 bits (i.e -138 dB). + - for case (2) or (3), FLUID_NOISE_FLOOR should be the noise floor for 16 bits (i.e -90 dB). + */ +#define FLUID_PEAK_ATTENUATION 960.0f + void fluid_conversion_config(void); fluid_real_t fluid_ct2hz_real(fluid_real_t cents);