From 42998e668cb29b922ef92ed0d4c9217660d23201 Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Sun, 2 Mar 2025 10:19:26 +0100 Subject: [PATCH] the good old simple compressor --- lib/filters.c | 153 +++++++------------------------------------------- lib/filters.h | 30 +--------- src/fm95.c | 7 +-- 3 files changed, 26 insertions(+), 164 deletions(-) diff --git a/lib/filters.c b/lib/filters.c index 87ca21a..22287bf 100644 --- a/lib/filters.c +++ b/lib/filters.c @@ -121,144 +121,31 @@ float voltage_to_power_db(float linear) { return 10.0f * log10f(fmaxf(linear, 1e-10f)); // Avoid log(0) } -static float compute_gain_reduction(float input_db, float threshold, float ratio, float knee) { - float gain_reduction = 0.0f; - - if (knee > 0.0f && input_db > (threshold - knee / 2.0f) && input_db < (threshold + knee / 2.0f)) { - float knee_range = input_db - (threshold - knee / 2.0f); - float knee_factor = knee_range * knee_range / (2.0f * knee); - gain_reduction = (ratio - 1.0f) * knee_factor / ratio; - } else if (input_db > threshold) { - gain_reduction = (threshold - input_db) * (1.0f - 1.0f / ratio); - } - - return gain_reduction; -} - -void init_compressor(Compressor *compressor, float threshold, float ratio, float knee, - float makeup_gain, float attack, float release, float rmsTime, float sample_rate) { - compressor->threshold = threshold; - compressor->ratio = ratio; - compressor->knee = knee; - compressor->makeup_gain = makeup_gain; +void init_compressor(Compressor *compressor, float attack, float release) { compressor->attack = attack; compressor->release = release; - compressor->sample_rate = sample_rate; - compressor->gainReduction = 0.0f; - compressor->rmsEnv = 0.0f; - compressor->rmsTime = rmsTime; + compressor->max = 0.0f; } float peak_compress(Compressor *compressor, float sample) { - float input_level_db = voltage_to_voltage_db(fabsf(sample)); - - float desired_gain_reduction = compute_gain_reduction(input_level_db, - compressor->threshold, - compressor->ratio, - compressor->knee); - - float attack_coef = expf(-1.0f / (compressor->sample_rate * compressor->attack)); - float release_coef = expf(-1.0f / (compressor->sample_rate * compressor->release)); - - float coef = (fabsf(desired_gain_reduction) > fabsf(compressor->gainReduction)) ? attack_coef : release_coef; - - compressor->gainReduction = desired_gain_reduction + coef * (compressor->gainReduction - desired_gain_reduction); - - float gain = voltage_db_to_voltage(compressor->gainReduction + compressor->makeup_gain); - - return sample * gain; + float sample_abs = fabsf(sample); + if(sample_abs > compressor->max) { + compressor->max += (sample_abs - compressor->max) / * compressor->attack; + } else { + compressor->max *= compressor->release; + } + return sample/(compressor->max+0.01); } -float rms_compress(Compressor *compressor, float sample) { - float rms_coef = expf(-1.0f / (compressor->sample_rate * compressor->rmsTime)); - float squared_input = sample * sample; - - compressor->rmsEnv = squared_input + rms_coef * (compressor->rmsEnv - squared_input); - - float input_level_db = voltage_to_voltage_db(sqrtf(fmaxf(compressor->rmsEnv, 1e-9f))); - - float desired_gain_reduction = compute_gain_reduction(input_level_db, - compressor->threshold, - compressor->ratio, - compressor->knee); - - float attack_coef = expf(-1.0f / (compressor->sample_rate * compressor->attack)); - float release_coef = expf(-1.0f / (compressor->sample_rate * compressor->release)); - - float coef = (fabsf(desired_gain_reduction) > fabsf(compressor->gainReduction)) ? attack_coef : release_coef; - - compressor->gainReduction = desired_gain_reduction + coef * (compressor->gainReduction - desired_gain_reduction); - - float gain = voltage_db_to_voltage(compressor->gainReduction + compressor->makeup_gain); - - return sample * gain; +float peak_compress_stereo(Compressor *compressor, float l, float r, float *output_r) { + float l_abs = fabsf(l); + float r_abs = fabsf(r); + float max = (l_abs > r_abs) ? l_abs : r_abs; + if(max > compressor->max) { + compressor->max += (max - compressor->max) / compressor->attack; + } else { + compressor->max *= compressor->release; + } + *output_r = r/(compressor->max+0.01); + return l/(compressor->max+0.01); } - -void init_compressor_stereo(StereoCompressor *compressor, float threshold, float ratio, - float knee, float makeup_gain, float attack, float release, - float rmsTime, float sample_rate) { - compressor->threshold = threshold; - compressor->ratio = ratio; - compressor->knee = knee; - compressor->makeup_gain = makeup_gain; - compressor->attack = attack; - compressor->release = release; - compressor->sample_rate = sample_rate; - compressor->gainReduction = 0.0f; - compressor->rmsEnv = 0.0f; - compressor->rmsEnv2 = 0.0f; - compressor->rmsTime = rmsTime; -} - -float peak_compress_stereo(StereoCompressor *compressor, float l, float r, float *output_r) { - float max_level = fmaxf(fabsf(l), fabsf(r)); - - float input_level_db = voltage_to_voltage_db(max_level); - - float desired_gain_reduction = compute_gain_reduction(input_level_db, - compressor->threshold, - compressor->ratio, - compressor->knee); - - float attack_coef = expf(-1.0f / (compressor->sample_rate * compressor->attack)); - float release_coef = expf(-1.0f / (compressor->sample_rate * compressor->release)); - - float coef = (fabsf(desired_gain_reduction) > fabsf(compressor->gainReduction)) ? attack_coef : release_coef; - - compressor->gainReduction = desired_gain_reduction + coef * (compressor->gainReduction - desired_gain_reduction); - - float gain = voltage_db_to_voltage(compressor->gainReduction + compressor->makeup_gain); - - *output_r = r * gain; - return l * gain; -} - -float rms_compress_stereo(StereoCompressor *compressor, float l, float r, float *output_r) { - float rms_coef = expf(-1.0f / (compressor->sample_rate * compressor->rmsTime)); - float squared_input1 = l * l; - float squared_input2 = r * r; - - compressor->rmsEnv = squared_input1 + rms_coef * (compressor->rmsEnv - squared_input1); - compressor->rmsEnv2 = squared_input2 + rms_coef * (compressor->rmsEnv2 - squared_input2); - - float max_rms = fmaxf(compressor->rmsEnv, compressor->rmsEnv2); - - float input_level_db = voltage_to_voltage_db(sqrtf(fmaxf(max_rms, 1e-9f))); - - float desired_gain_reduction = compute_gain_reduction(input_level_db, - compressor->threshold, - compressor->ratio, - compressor->knee); - - float attack_coef = expf(-1.0f / (compressor->sample_rate * compressor->attack)); - float release_coef = expf(-1.0f / (compressor->sample_rate * compressor->release)); - - float coef = (fabsf(desired_gain_reduction) > fabsf(compressor->gainReduction)) ? attack_coef : release_coef; - - compressor->gainReduction = desired_gain_reduction + coef * (compressor->gainReduction - desired_gain_reduction); - - float gain = voltage_db_to_voltage(compressor->gainReduction + compressor->makeup_gain); - - *output_r = r * gain; - return l * gain; -} \ No newline at end of file diff --git a/lib/filters.h b/lib/filters.h index 5f67fbc..6a69db7 100644 --- a/lib/filters.h +++ b/lib/filters.h @@ -32,34 +32,10 @@ float voltage_to_voltage_db(float linear); float voltage_to_power_db(float linear); typedef struct { - float threshold; - float ratio; - float knee; - float makeup_gain; float attack; float release; - float sample_rate; - float gainReduction; - float rmsEnv; - float rmsTime; + float max; } Compressor; -void init_compressor(Compressor *compressor, float threshold, float ratio, float knee, float makeup_gain, float attack, float release, float rmsTime, float sample_rate); +void init_compressor(Compressor *compressor, float attack, float release); float peak_compress(Compressor *compressor, float sample); -float rms_compress(Compressor *compressor, float sample); - -typedef struct { - float threshold; - float ratio; - float knee; - float makeup_gain; - float attack; - float release; - float sample_rate; - float gainReduction; - float rmsEnv; - float rmsEnv2; - float rmsTime; -} StereoCompressor; -void init_compressor_stereo(StereoCompressor *compressor, float threshold, float ratio, float knee, float makeup_gain, float attack, float release, float rmsTime, float sample_rate); -float peak_compress_stereo(StereoCompressor *compressor, float l, float r, float *output_r); -float rms_compress_stereo(StereoCompressor *compressor, float l, float r, float *output_r); +float peak_compress_stereo(Compressor *compressor, float l, float r, float *output_r); diff --git a/src/fm95.c b/src/fm95.c index 4a7e49b..b89018b 100644 --- a/src/fm95.c +++ b/src/fm95.c @@ -375,9 +375,8 @@ int main(int argc, char **argv) { init_lpf(&lpf_l, LPF_CUTOFF, 1.25f, SAMPLE_RATE); init_lpf(&lpf_r, LPF_CUTOFF, 1.25f, SAMPLE_RATE); - StereoCompressor comp; - // THRESH RATIO KNE MAKE ATT REL RMS - init_compressor_stereo(&comp, -24.0f, 4.0f, 2.0f, 24.0f, 0.025f, 0.4f, 0.04f, SAMPLE_RATE); + Compressor comp; + init_compressor(&comp, 0.9995f, 0.8f); // #endregion signal(SIGINT, stop); @@ -419,7 +418,7 @@ int main(int argc, char **argv) { float current_sca_in = sca_in[i]; float ready_r; - float ready_l = rms_compress_stereo(&comp, l_in, r_in, &ready_r); + float ready_l = peak_compress_stereo(&comp, l_in, r_in, &ready_r); ready_l = apply_frequency_filter(&lpf_l, l_in); ready_r = apply_frequency_filter(&lpf_r, r_in); ready_l = apply_preemphasis(&preemp_l, ready_l)*4;