Line data Source code
1 : #pragma once
2 :
3 : // Algorithmic reverb for adding room and tail reflections.
4 : // Uses a Schroeder-style network: parallel feedback combs y_i[n]=x[n]+g_i*y_i[n-d_i]
5 : // build the decay tail, followed by all-pass filters that diffuse echoes while
6 : // keeping magnitude roughly flat.
7 :
8 : #include "audio/effects/core/effect.h"
9 :
10 : namespace Amplitron {
11 :
12 : class Reverb : public Effect {
13 : public:
14 : Reverb();
15 : void process(float* buffer, int num_samples) override;
16 : void process_stereo(float* left, float* right, int num_samples) override;
17 : void set_sample_rate(int sample_rate) override;
18 : void reset() override;
19 320 : const char* name() const override { return "Reverb"; }
20 3 : const char* type_id() const override { return "Reverb"; }
21 209 : std::vector<EffectParam>& params() override { return params_; }
22 3 : const std::vector<EffectParam>& params() const override { return params_; }
23 :
24 : private:
25 : std::vector<EffectParam> params_;
26 :
27 : // Schroeder reverb: 4 comb filters + 2 allpass filters
28 : static constexpr int NUM_COMBS = 4;
29 : static constexpr int NUM_ALLPASS = 2;
30 :
31 392 : struct CombFilter {
32 : std::vector<float> buffer;
33 392 : int write_pos = 0;
34 392 : float feedback = 0.0f;
35 392 : float lp_state = 0.0f;
36 392 : float damp = 0.5f;
37 : };
38 :
39 196 : struct AllpassFilter {
40 : std::vector<float> buffer;
41 196 : int write_pos = 0;
42 196 : float feedback = 0.5f;
43 : };
44 :
45 : std::array<CombFilter, NUM_COMBS> combs_;
46 : std::array<AllpassFilter, NUM_ALLPASS> allpasses_;
47 : // Right-channel filter banks — slightly longer delays for decorrelation
48 : std::array<CombFilter, NUM_COMBS> combs_r_;
49 : std::array<AllpassFilter, NUM_ALLPASS> allpasses_r_;
50 :
51 : void init_filters();
52 : };
53 :
54 : } // namespace Amplitron
|