5 #include "stereocompressor.h"
9 inline float compressor_knee(float x, float threshold, float inv_threshold, float inv_ratio_minus_one, float postgain)
11 assert(inv_ratio_minus_one <= 0.0f);
12 if (x > threshold && inv_ratio_minus_one < 0.0f) {
13 return postgain * pow(x * inv_threshold, inv_ratio_minus_one);
21 void StereoCompressor::process(float *buf, size_t num_samples, float threshold, float ratio,
22 float attack_time, float release_time, float makeup_gain)
24 float attack_increment = float(pow(2.0f, 1.0f / (attack_time * sample_rate + 1)));
25 if (attack_time == 0.0f) attack_increment = 100000; // For instant attack reaction.
27 const float release_increment = float(pow(2.0f, -1.0f / (release_time * sample_rate + 1)));
28 const float peak_increment = float(pow(2.0f, -1.0f / (0.003f * sample_rate + 1)));
30 float inv_ratio_minus_one = 1.0f / ratio - 1.0f;
31 if (ratio > 63) inv_ratio_minus_one = -1.0f; // Infinite ratio.
32 float inv_threshold = 1.0f / threshold;
34 float *left_ptr = buf;
35 float *right_ptr = buf + 1;
37 float peak_level = this->peak_level;
38 float compr_level = this->compr_level;
40 for (size_t i = 0; i < num_samples; ++i) {
41 if (fabs(*left_ptr) > peak_level) peak_level = float(fabs(*left_ptr));
42 if (fabs(*right_ptr) > peak_level) peak_level = float(fabs(*right_ptr));
44 if (peak_level > compr_level) {
45 compr_level = std::min(compr_level * attack_increment, peak_level);
47 compr_level = std::max(compr_level * release_increment, 0.0001f);
50 float scalefactor_with_gain = compressor_knee(compr_level, threshold, inv_threshold, inv_ratio_minus_one, makeup_gain);
52 *left_ptr *= scalefactor_with_gain;
55 *right_ptr *= scalefactor_with_gain;
58 peak_level = std::max(peak_level * peak_increment, 0.0001f);
61 // Store attenuation level for debug/visualization.
62 scalefactor = compressor_knee(compr_level, threshold, inv_threshold, inv_ratio_minus_one, 1.0f);
64 this->peak_level = peak_level;
65 this->compr_level = compr_level;