@ -52,29 +52,32 @@ class AudioEffectCompressor_F32 : public AudioStream_F32
//apply the desired gain...store the processed audio back into audio_block
//apply the desired gain...store the processed audio back into audio_block
arm_mult_f32 ( audio_block - > data , gain_block - > data , audio_block - > data , audio_block - > length ) ;
arm_mult_f32 ( audio_block - > data , gain_block - > data , audio_block - > data , audio_block - > length ) ;
/// transmit the block and release memory
//transmit the block and release memory
AudioStream_F32 : : transmit ( audio_block ) ;
AudioStream_F32 : : transmit ( audio_block ) ;
AudioStream_F32 : : release ( audio_block ) ;
AudioStream_F32 : : release ( audio_block ) ;
AudioStream_F32 : : release ( gain_block ) ;
AudioStream_F32 : : release ( gain_block ) ;
AudioStream_F32 : : release ( audio_level_dB_block ) ;
AudioStream_F32 : : release ( audio_level_dB_block ) ;
}
}
// Here's the method that estimates the level of the audio (in dB)
// It squares the signal and low-pass filters to get a time-averaged
// signal power. It then
void calcAudioLevel_dB ( audio_block_f32_t * wav_block , audio_block_f32_t * level_dB_block ) {
void calcAudioLevel_dB ( audio_block_f32_t * wav_block , audio_block_f32_t * level_dB_block ) {
// calculate the instantaneous signal power (square the signal)
// calculate the instantaneous signal power (square the signal)
audio_block_f32_t * wav_pow_block = AudioStream_F32 : : allocate_f32 ( ) ;
audio_block_f32_t * wav_pow_block = AudioStream_F32 : : allocate_f32 ( ) ;
arm_mult_f32 ( wav_block - > data , wav_block - > data , wav_pow_block - > data , wav_block - > length ) ;
arm_mult_f32 ( wav_block - > data , wav_block - > data , wav_pow_block - > data , wav_block - > length ) ;
//apply a smoothing filter to wav_pow_block and convert to dB
// low-pass filter and convert to dB
float c1 = level_lp_const ;
float c1 = level_lp_const , c2 = 1.0f - c1 ; //prepare constants
float c2 = 1.0f - c1 ;
for ( int i = 0 ; i < wav_pow_block - > length ; i + + ) {
for ( int i = 0 ; i < wav_pow_block - > length ; i + + ) {
//compute target gain (well, we're actualy calculating gain^2) assuming we want to copress
// first-order low-pass filter to get a running estimate of the average power
wav_pow_block - > data [ i ] = c1 * prev_level_lp_pow + c2 * wav_pow_block - > data [ i ] ;
wav_pow_block - > data [ i ] = c1 * prev_level_lp_pow + c2 * wav_pow_block - > data [ i ] ;
//save state for next time (and for next data block)
// save the state of the first-order low-pass filter
prev_level_lp_pow = wav_pow_block - > data [ i ] ;
prev_level_lp_pow = wav_pow_block - > data [ i ] ;
//convert to dB (but not yet multiplied by 10.0
//now convert the signal power to dB (but not yet multiplied by 10.0)
level_dB_block - > data [ i ] = log10f ( wav_pow_block - > data [ i ] ) ;
level_dB_block - > data [ i ] = log10f ( wav_pow_block - > data [ i ] ) ;
}
}
@ -89,9 +92,11 @@ class AudioEffectCompressor_F32 : public AudioStream_F32
return ; //output is passed through level_dB_block
return ; //output is passed through level_dB_block
}
}
//This method computes the desired gain from the compressor, given an estimate
//of the signal level (in dB)
void calcGain ( audio_block_f32_t * audio_level_dB_block , audio_block_f32_t * gain_block ) {
void calcGain ( audio_block_f32_t * audio_level_dB_block , audio_block_f32_t * gain_block ) {
//first, calculate the instantaneous target gain
//first, calculate the instantaneous target gain based on the compression ratio
audio_block_f32_t * inst_targ_gain_dB_block = AudioStream_F32 : : allocate_f32 ( ) ;
audio_block_f32_t * inst_targ_gain_dB_block = AudioStream_F32 : : allocate_f32 ( ) ;
calcInstantaneousTargetGain ( audio_level_dB_block , inst_targ_gain_dB_block ) ;
calcInstantaneousTargetGain ( audio_level_dB_block , inst_targ_gain_dB_block ) ;
@ -99,9 +104,9 @@ class AudioEffectCompressor_F32 : public AudioStream_F32
audio_block_f32_t * gain_dB_block = AudioStream_F32 : : allocate_f32 ( ) ;
audio_block_f32_t * gain_dB_block = AudioStream_F32 : : allocate_f32 ( ) ;
calcSmoothedGain_dB ( inst_targ_gain_dB_block , gain_dB_block ) ;
calcSmoothedGain_dB ( inst_targ_gain_dB_block , gain_dB_block ) ;
//finally, convert from dB to linear gain: gain = 10^(gain_dB/20)
//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
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 ] = powf ( 10.0f , gain_dB_block - > data [ i ] ) ; //10^(x)
for ( int i = 0 ; i < gain_dB_block - > length ; i + + ) gain_block - > data [ i ] = powf ( 10.0f , gain_dB_block - > data [ i ] ) ; //do the 10^(x)
//release memory and return
//release memory and return
AudioStream_F32 : : release ( gain_dB_block ) ;
AudioStream_F32 : : release ( gain_dB_block ) ;
@ -109,6 +114,8 @@ class AudioEffectCompressor_F32 : public AudioStream_F32
return ; //output is passed through gain_block
return ; //output is passed through gain_block
}
}
//Compute the instantaneous desired gain, including the compression ratio and
//threshold for where the comrpession kicks in
void calcInstantaneousTargetGain ( audio_block_f32_t * audio_level_dB_block , audio_block_f32_t * inst_targ_gain_dB_block ) {
void calcInstantaneousTargetGain ( audio_block_f32_t * audio_level_dB_block , audio_block_f32_t * inst_targ_gain_dB_block ) {
// how much are we above the compression threshold?
// how much are we above the compression threshold?
@ -140,6 +147,8 @@ class AudioEffectCompressor_F32 : public AudioStream_F32
return ; //output is passed through inst_targ_gain_dB_block
return ; //output is passed through inst_targ_gain_dB_block
}
}
//this method applies the "attack" and "release" constants to smooth the
//target gain level through time.
void calcSmoothedGain_dB ( audio_block_f32_t * inst_targ_gain_dB_block , audio_block_f32_t * gain_dB_block ) {
void calcSmoothedGain_dB ( audio_block_f32_t * inst_targ_gain_dB_block , audio_block_f32_t * gain_dB_block ) {
float32_t gain_dB ;
float32_t gain_dB ;
float32_t one_minus_attack_const = 1.0f - attack_const ;
float32_t one_minus_attack_const = 1.0f - attack_const ;