Line data Source code
1 : #include "audio/effects/dynamics/compressor.h"
2 :
3 : #include "audio/effects/core/effect_factory.h"
4 :
5 : namespace Amplitron {
6 :
7 2 : static EffectRegistrar<Compressor> reg("Compressor");
8 :
9 88 : Compressor::Compressor() {
10 286 : params_ = {
11 66 : {"Threshold", -20.0f, -60.0f, 0.0f, -20.0f, "dB",
12 22 : "Signal level at which compression begins. Signals above this level will be reduced in "
13 : "volume."},
14 22 : {"Ratio", 4.0f, 1.0f, 20.0f, 4.0f, ":1",
15 22 : "How strongly to reduce peaks that exceed the threshold. Higher values create a more "
16 : "squashed sound."},
17 22 : {"Attack", 5.0f, 0.1f, 50.0f, 5.0f, "ms",
18 22 : "How quickly the compressor reacts to peaks. Fast attack clamps down immediately, slow "
19 : "allows pick transients through."},
20 22 : {"Release", 100.0f, 10.0f, 500.0f, 100.0f, "ms",
21 22 : "How quickly the compressor stops reducing volume after the signal drops below "
22 : "threshold."},
23 22 : {"Makeup", 0.0f, 0.0f, 30.0f, 0.0f, "dB",
24 22 : "Gain boost applied after compression to compensate for the volume lost during peak "
25 : "reduction."},
26 286 : };
27 132 : }
28 :
29 36 : void Compressor::process(float* buffer, int num_samples) {
30 36 : if (!enabled_) return;
31 :
32 36 : float threshold_db = params_[0].value;
33 36 : float ratio = params_[1].value;
34 36 : float attack_ms = params_[2].value;
35 36 : float release_ms = params_[3].value;
36 36 : float makeup = db_to_linear(params_[4].value);
37 :
38 : // Parameter smoothing (anti-zipper) — keep short enough to reduce zipper noise
39 : // while limiting lag in fast attack/release settings.
40 36 : const float alpha = 1.0f - std::exp(-1.0f / (sample_rate_ * 0.002f)); // 2 ms
41 36 : smoothed_attack_ms_ += alpha * (attack_ms - smoothed_attack_ms_);
42 36 : smoothed_release_ms_ += alpha * (release_ms - smoothed_release_ms_);
43 :
44 36 : float attack_coeff = EnvelopeFollower::time_to_coeff(smoothed_attack_ms_, sample_rate_);
45 36 : float release_coeff = EnvelopeFollower::time_to_coeff(smoothed_release_ms_, sample_rate_);
46 :
47 35364 : for (int i = 0; i < num_samples; ++i) {
48 35328 : float envelope = env_.process_additive(buffer[i], attack_coeff, release_coeff);
49 :
50 35328 : float env_db = linear_to_db(envelope);
51 35328 : float gain_db = 0.0f;
52 35328 : if (env_db > threshold_db) {
53 33759 : gain_db = (threshold_db - env_db) * (1.0f - 1.0f / ratio);
54 11253 : }
55 :
56 35328 : float gain = db_to_linear(gain_db) * makeup;
57 35328 : buffer[i] *= gain;
58 11776 : }
59 12 : }
60 :
61 57 : void Compressor::reset() { env_.reset(); }
62 :
63 : } // namespace Amplitron
|