Line data Source code
1 : #pragma once
2 :
3 : // Cascaded all-pass phaser with LFO modulation.
4 : // Each all-pass stage has near-unity magnitude and phase shift A(z); mixing
5 : // dry + wet creates notches where phase cancellation occurs. The LFO modulates
6 : // the all-pass coefficient so notch frequencies sweep over time.
7 :
8 : #include "audio/effects/effect.h"
9 : #include <array>
10 :
11 : namespace Amplitron {
12 :
13 : /**
14 : * Phaser effect — cascaded 1st-order all-pass filters with LFO modulation.
15 : * Supports 4, 6, 8, or 12 stages (classic MXR Phase 90 to studio phasers).
16 : */
17 6 : class Phaser : public Effect {
18 : public:
19 : Phaser();
20 : void process(float* buffer, int num_samples) override;
21 : void process_stereo(float* left, float* right, int num_samples) override;
22 : void set_sample_rate(int sample_rate) override;
23 : void reset() override;
24 65 : const char* name() const override { return "Phaser"; }
25 3 : const char* type_id() const override { return "Phaser"; }
26 97 : std::vector<EffectParam>& params() override { return params_; }
27 :
28 : private:
29 : std::vector<EffectParam> params_;
30 :
31 : float lfo_phase_ = 0.0f;
32 : float feedback_state_ = 0.0f;
33 : float feedback_state_r_ = 0.0f; // right-channel APF feedback
34 :
35 : static constexpr int MAX_STAGES = 12;
36 : std::array<float, MAX_STAGES> apf_xprev_{};
37 : std::array<float, MAX_STAGES> apf_yprev_{};
38 : // Right-channel APF state — LFO is 180° out of phase for stereo sweep
39 : std::array<float, MAX_STAGES> apf_xprev_r_{};
40 : std::array<float, MAX_STAGES> apf_yprev_r_{};
41 : };
42 :
43 : } // namespace Amplitron
|