Add support for C99 math functions, if available (#545)

This commit is contained in:
Carlo Bramini 2019-07-07 11:02:31 +02:00 committed by Tom M
parent 2be598b8e9
commit a02f1379d8
8 changed files with 158 additions and 49 deletions

View File

@ -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 )

View File

@ -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 */

View File

@ -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

View File

@ -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,7 +757,7 @@ 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] *
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:
@ -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] *
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);

View File

@ -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);
}

View File

@ -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:

View File

@ -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);
}
/*

View File

@ -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