From a02f1379d8dfda01acc6e5a4924973479329fd68 Mon Sep 17 00:00:00 2001 From: Carlo Bramini <30959007+carlo-bramini@users.noreply.github.com> Date: Sun, 7 Jul 2019 11:02:31 +0200 Subject: [PATCH] Add support for C99 math functions, if available (#545) --- CMakeLists.txt | 38 ++++++++++++++++++ src/config.cmake | 18 +++++++++ src/rvoice/fluid_iir_filter.c | 16 ++++---- src/rvoice/fluid_rev.c | 36 +++++++++-------- src/rvoice/fluid_rvoice.c | 2 +- src/synth/fluid_mod.c | 12 +++--- src/utils/fluid_conv.c | 12 +++--- src/utils/fluidsynth_priv.h | 73 +++++++++++++++++++++++++++++------ 8 files changed, 158 insertions(+), 49 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a2b8a63..76da64b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -666,6 +666,44 @@ endif() set(TEST_SOUNDFONT "${CMAKE_SOURCE_DIR}/sf2/VintageDreamsWaves-v2.sf2") set(TEST_SOUNDFONT_SF3 "${CMAKE_SOURCE_DIR}/sf2/VintageDreamsWaves-v2.sf3") +# Check for C99 float math + +unset ( HAVE_SINF CACHE ) +CHECK_FUNCTION_EXISTS ( "sinf" HAVE_SINF ) +if ( HAVE_SINF ) + set ( HAVE_SINF 1 ) +endif ( HAVE_SINF ) + +unset ( HAVE_COSF CACHE ) +CHECK_FUNCTION_EXISTS ( "cosf" HAVE_COSF ) +if ( HAVE_COSF ) + set ( HAVE_COSF 1 ) +endif ( HAVE_COSF ) + +unset ( HAVE_FABSF CACHE ) +CHECK_FUNCTION_EXISTS ( "fabsf" HAVE_FABSF ) +if ( HAVE_FABSF ) + set ( HAVE_FABSF 1 ) +endif ( HAVE_FABSF ) + +unset ( HAVE_POWF CACHE ) +CHECK_FUNCTION_EXISTS ( "powf" HAVE_POWF ) +if ( HAVE_POWF ) + set ( HAVE_POWF 1 ) +endif ( HAVE_POWF ) + +unset ( HAVE_SQRTF CACHE ) +CHECK_FUNCTION_EXISTS ( "sqrtf" HAVE_SQRTF ) +if ( HAVE_SQRTF ) + set ( HAVE_SQRTF 1 ) +endif ( HAVE_SQRTF ) + +unset ( HAVE_LOGF CACHE ) +CHECK_FUNCTION_EXISTS ( "logf" HAVE_LOGF ) +if ( HAVE_LOGF ) + set ( HAVE_LOGF 1 ) +endif ( HAVE_LOGF ) + # General configuration file configure_file ( ${CMAKE_SOURCE_DIR}/src/config.cmake ${CMAKE_BINARY_DIR}/config.h ) diff --git a/src/config.cmake b/src/config.cmake index 055d25d6..50b5bf12 100644 --- a/src/config.cmake +++ b/src/config.cmake @@ -251,4 +251,22 @@ #cmakedefine inline @INLINE_KEYWORD@ #endif +/* Define to 1 if you have the sinf() function. */ +#cmakedefine HAVE_SINF @HAVE_SINF@ + +/* Define to 1 if you have the cosf() function. */ +#cmakedefine HAVE_COSF @HAVE_COSF@ + +/* Define to 1 if you have the fabsf() function. */ +#cmakedefine HAVE_FABSF @HAVE_FABSF@ + +/* Define to 1 if you have the powf() function. */ +#cmakedefine HAVE_POWF @HAVE_POWF@ + +/* Define to 1 if you have the sqrtf() function. */ +#cmakedefine HAVE_SQRTF @HAVE_SQRTF@ + +/* Define to 1 if you have the logf() function. */ +#cmakedefine HAVE_LOGF @HAVE_LOGF@ + #endif /* CONFIG_H */ diff --git a/src/rvoice/fluid_iir_filter.c b/src/rvoice/fluid_iir_filter.c index 7cadb7d1..0be192f1 100644 --- a/src/rvoice/fluid_iir_filter.c +++ b/src/rvoice/fluid_iir_filter.c @@ -73,7 +73,7 @@ fluid_iir_filter_apply(fluid_iir_filter_t *iir_filter, /* filter (implement the voice filter according to SoundFont standard) */ /* Check for denormal number (too close to zero). */ - if(fabs(dsp_hist1) < 1e-20f) + if(FLUID_FABS(dsp_hist1) < 1e-20f) { dsp_hist1 = 0.0f; /* FIXME JMG - Is this even needed? */ } @@ -109,7 +109,7 @@ fluid_iir_filter_apply(fluid_iir_filter_t *iir_filter, dsp_b1 += dsp_b1_incr; /* Compensate history to avoid the filter going havoc with large frequency changes */ - if(iir_filter->compensate_incr && fabs(dsp_b02) > 0.001f) + if(iir_filter->compensate_incr && FLUID_FABS(dsp_b02) > 0.001f) { fluid_real_t compensate = old_b02 / dsp_b02; dsp_hist1 *= compensate; @@ -205,7 +205,7 @@ static fluid_real_t fluid_iir_filter_q_from_dB(fluid_real_t q_dB) /* The 'sound font' Q is defined in dB. The filter needs a linear q. Convert. */ - return pow(10.0f, q_dB / 20.0f); + return FLUID_POW(10.0f, q_dB / 20.0f); } DECLARE_FLUID_RVOICE_FUNCTION(fluid_iir_filter_set_q) @@ -247,7 +247,7 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_iir_filter_set_q) * (numerator of the filter equation). This gain factor depends * only on Q, so this is the right place to calculate it. */ - iir_filter->filter_gain /= sqrt(q); + iir_filter->filter_gain /= FLUID_SQRT(q); } /* The synthesis loop will have to recalculate the filter coefficients. */ @@ -277,8 +277,8 @@ fluid_iir_filter_calculate_coefficients(fluid_iir_filter_t *iir_filter, fluid_real_t omega = (fluid_real_t)(2.0 * M_PI) * (iir_filter->last_fres / output_rate); - fluid_real_t sin_coeff = (fluid_real_t) sin(omega); - fluid_real_t cos_coeff = (fluid_real_t) cos(omega); + fluid_real_t sin_coeff = FLUID_SIN(omega); + fluid_real_t cos_coeff = FLUID_COS(omega); fluid_real_t alpha_coeff = sin_coeff / (2.0f * iir_filter->q_lin); fluid_real_t a0_inv = 1.0f / (1.0f + alpha_coeff); @@ -352,7 +352,7 @@ fluid_iir_filter_calculate_coefficients(fluid_iir_filter_t *iir_filter, iir_filter->b02_incr = (b02_temp - iir_filter->b02) / transition_samples; iir_filter->b1_incr = (b1_temp - iir_filter->b1) / transition_samples; - if(fabs(iir_filter->b02) > 0.0001f) + if(FLUID_FABS(iir_filter->b02) > 0.0001f) { fluid_real_t quota = b02_temp / iir_filter->b02; iir_filter->compensate_incr = quota < 0.5f || quota > 2.f; @@ -399,7 +399,7 @@ void fluid_iir_filter_calc(fluid_iir_filter_t *iir_filter, } /* if filter enabled and there is a significant frequency change.. */ - if(iir_filter->type != FLUID_IIR_DISABLED && fabs(fres - iir_filter->last_fres) > 0.01f) + if(iir_filter->type != FLUID_IIR_DISABLED && FLUID_FABS(fres - iir_filter->last_fres) > 0.01f) { /* The filter coefficients have to be recalculated (filter * parameters have changed). Recalculation for various reasons is diff --git a/src/rvoice/fluid_rev.c b/src/rvoice/fluid_rev.c index 4bb84ac2..1d90b3ab 100644 --- a/src/rvoice/fluid_rev.c +++ b/src/rvoice/fluid_rev.c @@ -431,12 +431,16 @@ typedef struct static void set_mod_frequency(sinus_modulator *mod, float freq, float sample_rate, float phase) { - fluid_real_t w = 2 * M_PI * freq / sample_rate; /* intial angle */ + fluid_real_t w = 2 * FLUID_M_PI * freq / sample_rate; /* intial angle */ + fluid_real_t a; - mod->a1 = 2 * cos(w); - mod->buffer2 = sin(2 * M_PI * phase / 360 - w); /* y(n-1) = sin(-intial angle) */ - mod->buffer1 = sin(2 * M_PI * phase / 360); /* y(n) = sin(initial phase) */ - mod->reset_buffer2 = sin(M_PI / 2.0 - w); /* reset value for PI/2 */ + mod->a1 = 2 * FLUID_COS(w); + + a = (2 * FLUID_M_PI / 360) * phase; + + mod->buffer2 = FLUID_SIN(a - w); /* y(n-1) = sin(-intial angle) */ + mod->buffer1 = FLUID_SIN(a); /* y(n) = sin(initial phase) */ + mod->reset_buffer2 = FLUID_SIN(FLUID_M_PI / 2 - w); /* reset value for PI/2 */ } /*----------------------------------------------------------------------------- @@ -753,8 +757,8 @@ static void update_rev_time_damping(fluid_late *late, ------------------------------------------*/ dc_rev_time = GET_DC_REV_TIME(roomsize); /* computes gi_tmp from dc_rev_time using relation E2 */ - gi_tmp = (fluid_real_t) pow(10.f, -3 * delay_length[NBR_DELAYS - 1] * - sample_period / dc_rev_time); /* E2 */ + gi_tmp = FLUID_POW(10, -3 * delay_length[NBR_DELAYS - 1] * + sample_period / dc_rev_time); /* E2 */ #else /* roomsize parameters have the same response that Freeverb, that is: * - roomsize (0 to 1) controls concave reverb time (0.7 to 10 s). @@ -766,14 +770,14 @@ static void update_rev_time_damping(fluid_late *late, fluid_real_t gi_min, gi_max; /* values gi_min et gi_max are computed using E2 for the line with maximum delay */ - gi_max = (fluid_real_t)pow(10.f, -3 * delay_length[NBR_DELAYS - 1] * + gi_max = FLUID_POW(10, -3 * delay_length[NBR_DELAYS - 1] * sample_period / MAX_DC_REV_TIME); /* E2 */ - gi_min = (fluid_real_t)pow(10.f, -3 * delay_length[NBR_DELAYS - 1] * + gi_min = FLUID_POW(10, -3 * delay_length[NBR_DELAYS - 1] * sample_period / MIN_DC_REV_TIME); /* E2 */ /* gi = f(roomsize, gi_max, gi_min) */ gi_tmp = gi_min + roomsize * (gi_max - gi_min); /* Computes T60DC from gi using inverse of relation E2.*/ - dc_rev_time = -3 * M_LN10 * delay_length[NBR_DELAYS - 1] * sample_period / log(gi_tmp); + dc_rev_time = -3 * FLUID_M_LN10 * delay_length[NBR_DELAYS - 1] * sample_period / FLUID_LOGF(gi_tmp); } #endif /* ROOMSIZE_RESPONSE_LINEAR */ /*-------------------------------------------- @@ -784,9 +788,9 @@ static void update_rev_time_damping(fluid_late *late, ai_tmp = 1.0f * damp; /* Preserve the square of R */ - alpha2 = 1.f / (1.f - ai_tmp / ((20.f / 80.f) * log(gi_tmp))); + alpha2 = 1.f / (1.f - ai_tmp / ((20.f / 80.f) * FLUID_LOGF(gi_tmp))); - alpha = sqrt(alpha2); /* R */ + alpha = FLUID_SQRT(alpha2); /* R */ } /* updates tone corrector coefficients b1,b2 from alpha */ @@ -806,12 +810,12 @@ static void update_rev_time_damping(fluid_late *late, for(i = 0; i < NBR_DELAYS; i++) { /* iir low pass filter gain */ - fluid_real_t gi = (fluid_real_t)pow(10.f, -3 * delay_length[i] * - sample_period / dc_rev_time); + fluid_real_t gi = FLUID_POW(10, -3 * delay_length[i] * + sample_period / dc_rev_time); /* iir low pass filter feedback gain */ - fluid_real_t ai = (fluid_real_t)((20.f / 80.f) * log(gi) * - (1.f - 1.f / alpha2)); + fluid_real_t ai = (20.f / 80.f) * FLUID_LOGF(gi) * (1.f - 1.f / alpha2); + /* b0 = gi * (1 - ai), a1 = - ai */ set_fdn_delay_lpf(&late->mod_delay_lines[i].dl.damping, gi * (1.f - ai), -ai); diff --git a/src/rvoice/fluid_rvoice.c b/src/rvoice/fluid_rvoice.c index c9530da4..76e55792 100644 --- a/src/rvoice/fluid_rvoice.c +++ b/src/rvoice/fluid_rvoice.c @@ -599,7 +599,7 @@ fluid_rvoice_noteoff_LOCAL(fluid_rvoice_t *voice, unsigned int min_ticks) { 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.f / M_LN10) * log(amp) - lfo) / FLUID_PEAK_ATTENUATION - 1); + fluid_real_t env_value = - (((-200.f / FLUID_M_LN10) * FLUID_LOGF(amp) - lfo) / FLUID_PEAK_ATTENUATION - 1); fluid_clip(env_value, 0.0f, 1.0f); fluid_adsr_env_set_val(&voice->envlfo.volenv, env_value); } diff --git a/src/synth/fluid_mod.c b/src/synth/fluid_mod.c index eede618a..47547b5b 100644 --- a/src/synth/fluid_mod.c +++ b/src/synth/fluid_mod.c @@ -334,21 +334,21 @@ fluid_mod_transform_source_value(fluid_real_t val, unsigned char mod_flags, cons * is close enough. */ case FLUID_MOD_SIN | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE: /* custom sin(x) */ - val = sin((M_PI / 2.0f * 0.87f) * val_norm); + val = FLUID_SIN((FLUID_M_PI / 2.0f * 0.87f) * val_norm); break; case FLUID_MOD_SIN | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE: /* custom */ - val = sin((M_PI / 2.0f * 0.87f) * (1.0f - val_norm)); + val = FLUID_SIN((FLUID_M_PI / 2.0f * 0.87f) * (1.0f - val_norm)); break; case FLUID_MOD_SIN | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE: /* custom */ - val = (val_norm > 0.5f) ? sin(M_PI * (val_norm - 0.5f)) - : -sin(M_PI * (0.5f - val_norm)); + val = (val_norm > 0.5f) ? FLUID_SIN(FLUID_M_PI * (val_norm - 0.5f)) + : -FLUID_SIN(FLUID_M_PI * (0.5f - val_norm)); break; case FLUID_MOD_SIN | FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE: /* custom */ - val = (val_norm > 0.5f) ? -sin(M_PI * (val_norm - 0.5f)) - : sin(M_PI * (0.5f - val_norm)); + val = (val_norm > 0.5f) ? -FLUID_SIN(FLUID_M_PI * (val_norm - 0.5f)) + : FLUID_SIN(FLUID_M_PI * (0.5f - val_norm)); break; default: diff --git a/src/utils/fluid_conv.c b/src/utils/fluid_conv.c index bea1fcc6..a2ba770b 100644 --- a/src/utils/fluid_conv.c +++ b/src/utils/fluid_conv.c @@ -160,7 +160,7 @@ fluid_tc2sec_delay(fluid_real_t tc) tc = (fluid_real_t) 5000.0f; } - return (fluid_real_t) pow(2.f, tc / 1200.f); + return FLUID_POW(2.f, tc / 1200.f); } /* @@ -188,7 +188,7 @@ fluid_tc2sec_attack(fluid_real_t tc) tc = (fluid_real_t) 8000.f; }; - return (fluid_real_t) pow(2.f, tc / 1200.f); + return FLUID_POW(2.f, tc / 1200.f); } /* @@ -198,7 +198,7 @@ fluid_real_t fluid_tc2sec(fluid_real_t tc) { /* No range checking here! */ - return (fluid_real_t) pow(2.f, tc / 1200.f); + return FLUID_POW(2.f, tc / 1200.f); } /* @@ -226,7 +226,7 @@ fluid_tc2sec_release(fluid_real_t tc) tc = (fluid_real_t) 8000.f; }; - return (fluid_real_t) pow(2.f, tc / 1200.f); + return FLUID_POW(2.f, tc / 1200.f); } /* @@ -238,13 +238,13 @@ fluid_tc2sec_release(fluid_real_t tc) * fluid_hz2ct(fluid_real_t f) { - return (fluid_real_t)(6900 + (1200 / M_LN2) * log(f / 440.0)); + return 6900.f + (1200.f / FLUID_M_LN2) * FLUID_LOGF(f / 440.0f)); } */ fluid_real_t fluid_act2hz(fluid_real_t c) { - return (fluid_real_t)(8.176f * pow(2.f, c / 1200.f)); + return 8.176f * FLUID_POW(2.f, c / 1200.f); } /* diff --git a/src/utils/fluidsynth_priv.h b/src/utils/fluidsynth_priv.h index c8a59908..659aa53a 100644 --- a/src/utils/fluidsynth_priv.h +++ b/src/utils/fluidsynth_priv.h @@ -126,19 +126,80 @@ typedef void (*fluid_rvoice_function_t)(void *obj, const fluid_rvoice_param_t pa * SYSTEM INTERFACE */ +/* Math constants */ +#ifndef M_PI +#define M_PI 3.1415926535897932384626433832795 +#endif + +#ifndef M_LN2 +#define M_LN2 0.69314718055994530941723212145818 +#endif + +#ifndef M_LN10 +#define M_LN10 2.3025850929940456840179914546844 +#endif + +#define FLUID_M_PI ((fluid_real_t)M_PI) +#define FLUID_M_LN2 ((fluid_real_t)M_LN2) +#define FLUID_M_LN10 ((fluid_real_t)M_LN10) + +/* Math functions */ +#if defined WITH_FLOAT && defined HAVE_SINF +#define FLUID_SIN sinf +#else +#define FLUID_SIN (fluid_real_t)sin +#endif + +#if defined WITH_FLOAT && defined HAVE_COSF +#define FLUID_COS cosf +#else +#define FLUID_COS (fluid_real_t)cos +#endif + +#if defined WITH_FLOAT && defined HAVE_FABSF +#define FLUID_FABS fabsf +#else +#define FLUID_FABS (fluid_real_t)fabs +#endif + +#if defined WITH_FLOAT && defined HAVE_POWF +#define FLUID_POW powf +#else +#define FLUID_POW (fluid_real_t)pow +#endif + +#if defined WITH_FLOAT && defined HAVE_SQRTF +#define FLUID_SQRT sqrtf +#else +#define FLUID_SQRT (fluid_real_t)sqrt +#endif + +#if defined WITH_FLOAT && defined HAVE_LOGF +#define FLUID_LOGF logf +#else +#define FLUID_LOGF (fluid_real_t)log +#endif + +/* Memory allocation */ #define FLUID_MALLOC(_n) malloc(_n) #define FLUID_REALLOC(_p,_n) realloc(_p,_n) #define FLUID_NEW(_t) (_t*)malloc(sizeof(_t)) #define FLUID_ARRAY_ALIGNED(_t,_n,_a) (_t*)malloc((_n)*sizeof(_t) + ((unsigned int)_a - 1u)) #define FLUID_ARRAY(_t,_n) FLUID_ARRAY_ALIGNED(_t,_n,1u) #define FLUID_FREE(_p) free(_p) + +/* File access */ #define FLUID_FOPEN(_f,_m) fopen(_f,_m) #define FLUID_FCLOSE(_f) fclose(_f) #define FLUID_FREAD(_p,_s,_n,_f) fread(_p,_s,_n,_f) #define FLUID_FSEEK(_f,_n,_set) fseek(_f,_n,_set) #define FLUID_FTELL(_f) ftell(_f) + +/* Memory functions */ #define FLUID_MEMCPY(_dst,_src,_n) memcpy(_dst,_src,_n) #define FLUID_MEMSET(_s,_c,_n) memset(_s,_c,_n) + +/* String functions */ #define FLUID_STRLEN(_s) strlen(_s) #define FLUID_STRCMP(_s,_t) strcmp(_s,_t) #define FLUID_STRNCMP(_s,_t,_n) strncmp(_s,_t,_n) @@ -212,18 +273,6 @@ do { strncpy(_dst,_src,_n); \ #define FLUID_LOG fluid_log #endif -#ifndef M_PI -#define M_PI 3.1415926535897932384626433832795 -#endif - -#ifndef M_LN2 -#define M_LN2 0.69314718055994530941723212145818 -#endif - -#ifndef M_LN10 -#define M_LN10 2.3025850929940456840179914546844 -#endif - #ifdef DEBUG #define FLUID_ASSERT(a) g_assert(a) #else