From 163877b76c3148e9ee2349817b63478a4a80c39b Mon Sep 17 00:00:00 2001 From: Chip Audette Date: Sun, 15 Jan 2017 08:50:35 -0500 Subject: [PATCH] Compressor: clarify and expand comments --- AudioEffectCompressor_F32.h | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/AudioEffectCompressor_F32.h b/AudioEffectCompressor_F32.h index 0e58cec..9c82a3e 100644 --- a/AudioEffectCompressor_F32.h +++ b/AudioEffectCompressor_F32.h @@ -37,7 +37,7 @@ class AudioEffectCompressor_F32 : public AudioStream_F32 //apply a high-pass filter to get rid of the DC offset if (use_HP_prefilter) arm_biquad_cascade_df1_f32(&hp_filt_struct, audio_block->data, audio_block->data, audio_block->length); - + //apply the pre-gain...a negative gain value will disable if (pre_gain > 0.0f) arm_scale_f32(audio_block->data, pre_gain, audio_block->data, audio_block->length); //use ARM DSP for speed! @@ -52,29 +52,32 @@ class AudioEffectCompressor_F32 : public AudioStream_F32 //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); - ///transmit the block and release memory + //transmit the block and release memory AudioStream_F32::transmit(audio_block); AudioStream_F32::release(audio_block); AudioStream_F32::release(gain_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) { - //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(); 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 - float c1 = level_lp_const; - float c2 = 1.0f - c1; + // low-pass filter and convert to dB + float c1 = level_lp_const, c2 = 1.0f - c1; //prepare constants 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]; + + // save the state of the first-order low-pass filter + prev_level_lp_pow = wav_pow_block->data[i]; - //save state for next time (and for next data block) - 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]); } @@ -89,9 +92,11 @@ class AudioEffectCompressor_F32 : public AudioStream_F32 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) { - //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(); 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(); 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 - 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 AudioStream_F32::release(gain_dB_block); @@ -109,6 +114,8 @@ class AudioEffectCompressor_F32 : public AudioStream_F32 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) { // 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 } + //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) { float32_t gain_dB; float32_t one_minus_attack_const = 1.0f - attack_const;