Line data Source code
1 : #include "audio/effects/equalizer.h"
2 : #include "audio/effects/effect_factory.h"
3 :
4 : namespace Amplitron {
5 :
6 2 : static EffectRegistrar<Equalizer> reg("Equalizer");
7 :
8 96 : Equalizer::Equalizer() {
9 264 : params_ = {
10 72 : {"Bass", 0.0f, -12.0f, 12.0f, 0.0f, "dB", "Low shelf filter (200Hz). Boosts or cuts the heavy low-end thud and body of the tone."},
11 24 : {"Mid", 0.0f, -12.0f, 12.0f, 0.0f, "dB", "Bell filter (800Hz). Boosts for leads that cut through a mix, cuts for a hollow metal rhythm tone."},
12 24 : {"Treble", 0.0f, -12.0f, 12.0f, 0.0f, "dB", "High shelf filter (3kHz). Adjusts the bite, pick attack, and overall brightness."},
13 24 : {"Presence", 0.0f, -12.0f, 12.0f, 0.0f, "dB", "Ultra-high frequency contour. Adds 'air' and glassiness to the very top end."},
14 264 : };
15 72 : set_sample_rate(DEFAULT_SAMPLE_RATE);
16 144 : }
17 :
18 135 : void Equalizer::set_sample_rate(int sample_rate) {
19 135 : Effect::set_sample_rate(sample_rate);
20 : // Snap smoothing states and force recomputation
21 135 : bass_state_ = params_[0].value;
22 135 : mid_state_ = params_[1].value;
23 135 : treble_state_ = params_[2].value;
24 135 : presence_state_ = params_.size() > 3 ? params_[3].value : 0.0f;
25 135 : cached_bass_ = -999.0f;
26 135 : cached_mid_ = -999.0f;
27 135 : cached_treble_ = -999.0f;
28 135 : cached_presence_ = -999.0f;
29 135 : recompute_coefficients_if_dirty();
30 135 : }
31 :
32 159 : void Equalizer::recompute_coefficients_if_dirty() {
33 159 : float bass = bass_state_;
34 159 : float mid = mid_state_;
35 159 : float treble = treble_state_;
36 159 : float presence = presence_state_;
37 :
38 167 : if (bass != cached_bass_ || mid != cached_mid_ ||
39 24 : treble != cached_treble_ || presence != cached_presence_) {
40 135 : low_shelf_.set_low_shelf(200.0f, bass, 0.7f, sample_rate_);
41 135 : mid_peak_.set_peaking(800.0f, mid, 1.0f, sample_rate_);
42 135 : high_shelf_.set_high_shelf(3000.0f, treble + presence, 0.7f, sample_rate_);
43 135 : cached_bass_ = bass;
44 135 : cached_mid_ = mid;
45 135 : cached_treble_ = treble;
46 135 : cached_presence_ = presence;
47 45 : }
48 159 : }
49 :
50 24 : void Equalizer::process(float* buffer, int num_samples) {
51 24 : if (!enabled_) return;
52 :
53 : // One-pole smoothing: advance states toward raw param targets each block
54 24 : const float alpha = 1.0f - std::exp(-1.0f / (sample_rate_ * 0.010f)); // 10 ms
55 24 : bass_state_ += alpha * (params_[0].value - bass_state_);
56 24 : mid_state_ += alpha * (params_[1].value - mid_state_);
57 24 : treble_state_ += alpha * (params_[2].value - treble_state_);
58 24 : presence_state_ += alpha * ((params_.size() > 3 ? params_[3].value : 0.0f) - presence_state_);
59 :
60 24 : recompute_coefficients_if_dirty();
61 :
62 6168 : for (int i = 0; i < num_samples; ++i) {
63 6144 : float x = buffer[i];
64 6144 : x = low_shelf_.process(x);
65 6144 : x = mid_peak_.process(x);
66 6144 : x = high_shelf_.process(x);
67 6144 : buffer[i] = x;
68 2048 : }
69 8 : }
70 :
71 63 : void Equalizer::reset() {
72 63 : low_shelf_.reset();
73 63 : mid_peak_.reset();
74 63 : high_shelf_.reset();
75 63 : }
76 :
77 : } // namespace Amplitron
|