15class Mutable :
public Base {
16 constexpr static size_t kBufferSize = 32768;
21 ~Mutable()
override =
default;
23 void process(std::span<int32_t> in, std::span<StereoSample> output)
override {
42 FxEngine::ConstructTopology(engine_,
44 &ap1, &ap2, &ap3, &ap4,
45 &dap1a, &dap1b, &del1,
46 &dap2a, &dap2b, &del2,
49 const float kap = diffusion_;
50 const float klp = lp_;
51 const float krt = reverb_time_;
53 float lp_1 = lp_decay_1_;
54 float lp_2 = lp_decay_2_;
56 for (
size_t frame = 0; frame < in.size(); frame++) {
66 const float input_sample = in[frame] /
static_cast<float>(std::numeric_limits<int32_t>::max());
81 dap1a.Process(c, -kap);
82 dap1b.Process(c, kap);
85 wet = wet - dsp::OnePole(hp_r_, wet, hp_cutoff_);
86 wet = dsp::OnePole(lp_r_, wet, lp_cutoff_);
88 auto output_right = dsp::toQ31Saturating(wet *
kOutputGain);
93 dap2a.Process(c, -kap);
94 dap2b.Process(c, kap);
97 wet = wet - dsp::OnePole(hp_l_, wet, hp_cutoff_);
98 wet = dsp::OnePole(lp_l_, wet, lp_cutoff_);
100 auto output_left = dsp::toQ31Saturating(wet *
kOutputGain);
103 s.l += multiply_32x32_rshift32_rounded(output_left, getPanLeft());
104 s.r += multiply_32x32_rshift32_rounded(output_right, getPanRight());
111 inline void Clear() { engine_.Clear(); }
117 static constexpr float kReverbTimeMin = 0.01f;
118 static constexpr float kReverbTimeMax = 0.98f;
119 static constexpr float kWidthMin = 0.1f;
120 static constexpr float kWidthMax = 0.9f;
124 static constexpr float kLpMax = 1.f;
127 void setRoomSize(
float value)
override {
128 reverb_time_ = util::map(value, 0.f, 1.f, kReverbTimeMin, kReverbTimeMax);
130 [[nodiscard]]
float getRoomSize()
const override {
131 return util::map(reverb_time_, kReverbTimeMin, kReverbTimeMax, 0.f, 1.f);
138 const float damping = std::clamp(std::log2((value * 50.f) + 1.f) / 5.7f, 0.f, 1.f);
139 lp_ = util::map(1.f - damping, 0.f, 1.f,
kLpMin, kLpMax);
141 [[nodiscard]]
float getDamping()
const override {
return lp_val_; }
143 void setWidth(
float value)
override { diffusion_ = util::map(value, 0.f, 1.f, kWidthMin, kWidthMax); }
144 [[nodiscard]]
float getWidth()
const override {
return util::map(diffusion_, kWidthMin, kWidthMax, 0.f, 1.f); };
146 void setHPF(
float f)
override {
148 hp_cutoff_ = calcFilterCutoff<FilterType::HighPass>(f);
151 [[nodiscard]]
float getHPF()
const override {
return hp_cutoff_val_; }
153 void setLPF(
float f)
override {
155 lp_cutoff_ = calcFilterCutoff<FilterType::LowPass>(f);
158 [[nodiscard]]
float getLPF()
const override {
return lp_cutoff_val_; }
161 static constexpr float sample_rate = kSampleRate;
163 std::array<float, kBufferSize> buffer_{};
164 FxEngine engine_{buffer_, {0.5f / sample_rate, 0.3f / sample_rate}};
167 float reverb_time_ = 0.665f;
170 float diffusion_ = 0.625f;
177 float lp_decay_1_{0};
178 float lp_decay_2_{0};
181 float hp_cutoff_val_{0.f};
183 float hp_cutoff_{calcFilterCutoff<FilterType::HighPass>(0)};
188 float lp_cutoff_val_{0.f};
190 float lp_cutoff_{calcFilterCutoff<FilterType::LowPass>(0)};
Definition fx_engine.hpp:98