|
|
|
@ -16,47 +16,6 @@ |
|
|
|
|
#include <arm_math.h> //ARM DSP extensions. https://www.keil.com/pack/doc/CMSIS/DSP/html/index.html |
|
|
|
|
#include <AudioStream_F32.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// //// Accelerate the powf(10.0,x) function???
|
|
|
|
|
//#define POW10_FUNC(x) powf(10.0f,x) //standard, but slower
|
|
|
|
|
#define POW10_FUNC(x) expf(2.302585092994f*x) //faster: exp(log(10.0f)*x)
|
|
|
|
|
|
|
|
|
|
// //// Accelerate the log10f(x) function?
|
|
|
|
|
//#define LOG10_FUNC(x) log10f(x) //standard, but slower
|
|
|
|
|
#define LOG10_FUNC(x) log2f_approx(x)*0.3010299956639812f; //faster: log2(x)/log2(10)
|
|
|
|
|
|
|
|
|
|
//https://community.arm.com/tools/f/discussions/4292/cmsis-dsp-new-functionality-proposal/22621#22621
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
|
** Fast approximation to the log2() function. It uses a two step |
|
|
|
|
** process. First, it decomposes the floating-point number into |
|
|
|
|
** a fractional component F and an exponent E. The fraction component |
|
|
|
|
** is used in a polynomial approximation and then the exponent added |
|
|
|
|
** to the result. A 3rd order polynomial is used and the result |
|
|
|
|
** when computing db20() is accurate to 7.984884e-003 dB. |
|
|
|
|
** ------------------------------------------------------------------- */ |
|
|
|
|
float log2f_approx_coeff[4] = {1.23149591368684f, -4.11852516267426f, 6.02197014179219f, -3.13396450166353f}; |
|
|
|
|
float log2f_approx(float X) { |
|
|
|
|
float *C = &log2f_approx_coeff[0]; |
|
|
|
|
float Y; |
|
|
|
|
float F; |
|
|
|
|
int E; |
|
|
|
|
|
|
|
|
|
// This is the approximation to log2()
|
|
|
|
|
F = frexpf(fabsf(X), &E); |
|
|
|
|
// Y = C[0]*F*F*F + C[1]*F*F + C[2]*F + C[3] + E;
|
|
|
|
|
Y = *C++; |
|
|
|
|
Y *= F; |
|
|
|
|
Y += (*C++); |
|
|
|
|
Y *= F; |
|
|
|
|
Y += (*C++); |
|
|
|
|
Y *= F; |
|
|
|
|
Y += (*C++); |
|
|
|
|
Y += E; |
|
|
|
|
|
|
|
|
|
return(Y); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AudioEffectCompressor_F32 : public AudioStream_F32 |
|
|
|
|
{ |
|
|
|
|
public: |
|
|
|
@ -119,7 +78,7 @@ class AudioEffectCompressor_F32 : public AudioStream_F32 |
|
|
|
|
prev_level_lp_pow = wav_pow_block->data[i];
|
|
|
|
|
|
|
|
|
|
//now convert the signal power to dB (but not yet multiplied by 10.0)
|
|
|
|
|
level_dB_block->data[i] = LOG10_FUNC(wav_pow_block->data[i]); |
|
|
|
|
level_dB_block->data[i] = log10f_approx(wav_pow_block->data[i]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//limit the amount that the state of the smoothing filter can go toward negative infinity
|
|
|
|
@ -147,7 +106,7 @@ class AudioEffectCompressor_F32 : public AudioStream_F32 |
|
|
|
|
|
|
|
|
|
//finally, convert from dB to linear gain: gain = 10^(gain_dB/20); (ie this takes care of the sqrt, too!)
|
|
|
|
|
arm_scale_f32(gain_dB_block->data, 1.0f/20.0f, gain_dB_block->data, gain_dB_block->length); //divide by 20
|
|
|
|
|
for (int i = 0; i < gain_dB_block->length; i++) gain_block->data[i] = POW10_FUNC(gain_dB_block->data[i]); //do the 10^(x)
|
|
|
|
|
for (int i = 0; i < gain_dB_block->length; i++) gain_block->data[i] = pow10f(gain_dB_block->data[i]); //do the 10^(x)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//release memory and return
|
|
|
|
@ -254,13 +213,13 @@ class AudioEffectCompressor_F32 : public AudioStream_F32 |
|
|
|
|
void enableHPFilter(boolean flag) { use_HP_prefilter = flag; }; |
|
|
|
|
|
|
|
|
|
//methods to return information about this module
|
|
|
|
|
float32_t getPreGain_dB(void) { return 20.0 * log10f(pre_gain); } |
|
|
|
|
float32_t getPreGain_dB(void) { return 20.0 * log10f_approx(pre_gain); } |
|
|
|
|
float32_t getAttack_sec(void) { return attack_sec; } |
|
|
|
|
float32_t getRelease_sec(void) { return release_sec; } |
|
|
|
|
float32_t getLevelTimeConst_sec(void) { return level_lp_sec; } |
|
|
|
|
float32_t getThresh_dBFS(void) { return thresh_dBFS; } |
|
|
|
|
float32_t getCompressionRatio(void) { return comp_ratio; } |
|
|
|
|
float32_t getCurrentLevel_dBFS(void) { return 10.0* log10f(prev_level_lp_pow); } |
|
|
|
|
float32_t getCurrentLevel_dBFS(void) { return 10.0* log10f_approx(prev_level_lp_pow); } |
|
|
|
|
float32_t getCurrentGain_dB(void) { return prev_gain_dB; } |
|
|
|
|
|
|
|
|
|
void setHPFilterCoeff_N2IIR_Matlab(float32_t b[], float32_t a[]){ |
|
|
|
@ -297,7 +256,7 @@ class AudioEffectCompressor_F32 : public AudioStream_F32 |
|
|
|
|
float32_t comp_ratio_const, thresh_pow_FS_wCR; //used in calcGain(); set in updateThresholdAndCompRatioConstants()
|
|
|
|
|
void updateThresholdAndCompRatioConstants(void) { |
|
|
|
|
comp_ratio_const = 1.0f-(1.0f / comp_ratio); |
|
|
|
|
thresh_pow_FS_wCR = powf(thresh_pow_FS, comp_ratio_const); //powf() is much faster than pow()
|
|
|
|
|
thresh_pow_FS_wCR = powf(thresh_pow_FS, comp_ratio_const);
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//settings
|
|
|
|
@ -312,6 +271,55 @@ class AudioEffectCompressor_F32 : public AudioStream_F32 |
|
|
|
|
float32_t pre_gain = -1.0; //gain to apply before the compression. negative value disables
|
|
|
|
|
boolean use_HP_prefilter; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Accelerate the powf(10.0,x) function
|
|
|
|
|
static float32_t pow10f(float x) { |
|
|
|
|
//return powf(10.0f,x) //standard, but slower
|
|
|
|
|
return expf(2.302585092994f*x); //faster: exp(log(10.0f)*x)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Accelerate the log10f(x) function?
|
|
|
|
|
static float32_t log10f_approx(float x) { |
|
|
|
|
//return log10f(x); //standard, but slower
|
|
|
|
|
return log2f_approx(x)*0.3010299956639812f; //faster: log2(x)/log2(10)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
|
** Fast approximation to the log2() function. It uses a two step |
|
|
|
|
** process. First, it decomposes the floating-point number into |
|
|
|
|
** a fractional component F and an exponent E. The fraction component |
|
|
|
|
** is used in a polynomial approximation and then the exponent added |
|
|
|
|
** to the result. A 3rd order polynomial is used and the result |
|
|
|
|
** when computing db20() is accurate to 7.984884e-003 dB. |
|
|
|
|
** ------------------------------------------------------------------- */ |
|
|
|
|
//https://community.arm.com/tools/f/discussions/4292/cmsis-dsp-new-functionality-proposal/22621#22621
|
|
|
|
|
//float log2f_approx_coeff[4] = {1.23149591368684f, -4.11852516267426f, 6.02197014179219f, -3.13396450166353f};
|
|
|
|
|
static float log2f_approx(float X) { |
|
|
|
|
//float *C = &log2f_approx_coeff[0];
|
|
|
|
|
float Y; |
|
|
|
|
float F; |
|
|
|
|
int E; |
|
|
|
|
|
|
|
|
|
// This is the approximation to log2()
|
|
|
|
|
F = frexpf(fabsf(X), &E); |
|
|
|
|
// Y = C[0]*F*F*F + C[1]*F*F + C[2]*F + C[3] + E;
|
|
|
|
|
//Y = *C++;
|
|
|
|
|
Y = 1.23149591368684f; |
|
|
|
|
Y *= F; |
|
|
|
|
//Y += (*C++);
|
|
|
|
|
Y += -4.11852516267426f; |
|
|
|
|
Y *= F; |
|
|
|
|
//Y += (*C++);
|
|
|
|
|
Y += 6.02197014179219f; |
|
|
|
|
Y *= F; |
|
|
|
|
//Y += (*C++);
|
|
|
|
|
Y += -3.13396450166353f; |
|
|
|
|
Y += E; |
|
|
|
|
|
|
|
|
|
return(Y); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|