A cascaded first-order-allpass phaser. More...
#include <phaser_stages.hpp>
Public Types | |
| using | Wave = LfoWave |
| The LFO shape enum, forwarded verbatim. | |
Public Member Functions | |
| PhaserStagesT () | |
| A default instance is a Small Stone: 4 stages, 0.5 Hz triangle, 400 Hz centre, full depth, Color off, mix at the full-notch point, mono. | |
| void | prepare (double sample_rate) |
| Sets the sample rate and returns the instance to a fresh, silent state. | |
| void | reset () |
| Clears every stage's integrator, the feedback memories, and both LFO phases, so a render from here is bit-identical every time. | |
| void | set_stage_count (int n) |
| Active stage count. | |
| int | stage_count () const |
| void | set_rate_hz (double hz) |
| LFO rate in Hz. Forwarded to both channels' LFOs. | |
| double | rate_hz () const |
| void | set_depth (float depth01) |
| Sweep excursion, 0..1. | |
| double | depth () const |
| void | set_center_hz (double fc) |
| Allpass corner frequency at the LFO's midpoint. | |
| double | center_hz () const |
| void | set_feedback (float fb) |
| Feedback ("Color"), clamped to ±kFeedbackMax. | |
| double | feedback () const |
| void | set_mix (float mix01) |
| Dry/wet, 0..1. 0.5 is the full-notch point; 1.0 is a flat allpass. | |
| double | mix () const |
| void | set_stereo_spread (float cycles01) |
| Right-channel LFO lead in CYCLES, 0..0.5. | |
| double | stereo_spread () const |
| void | set_wave (Wave wave) |
| LFO shape, forwarded verbatim to both channels' LFOs. | |
| Wave | wave () const |
| void | set_stagger_ratio (double ratio) |
| Per-stage corner ratio; 1.0 (the default) means every stage shares one fc, which is the documented single-control-current topology. | |
| double | stagger_ratio () const |
| void | set_seed (std::uint32_t seed) |
| Seeds both LFOs identically, so the stochastic shapes stay a phase-shifted copy of each other rather than decorrelating. | |
| double | sweep_frequency_hz (int channel) const |
| The channel's current swept corner frequency in Hz, after clamping — the quantity the notch laws take as fc. | |
| void | process (const SampleType *in_l, const SampleType *in_r, SampleType *out_l, SampleType *out_r, int n_frames) |
| Stereo block process. | |
| void | process_mono (const SampleType *in, SampleType *out, int n_frames) |
| Mono block process, driving channel 0 only. | |
Static Public Member Functions | |
| static double | notch_frequency_analog_hz (int k, int stages, double fc_hz) |
| The cited analog-prototype notch law: f_k = fc · tan((2k−1)π/2N). | |
| static double | notch_frequency_hz (int k, int stages, double fc_hz, double sample_rate) |
| The exact notch law for the shipped TPT cascade: f_k = (fs/π)·arctan( tan(π·fc/fs) · tan((2k−1)π/2N) ). | |
| static constexpr int | notch_count (int stages) |
| How many notches an N-stage cascade produces. N/2, for even N. | |
| static constexpr double | worst_case_gain () |
| The worst-case output/input magnitude over all frequencies, mixes and feedback settings — the number Forge's registry row cites. | |
| static constexpr int | latency_samples () |
| Zero. The dry path is a wire and the TPT stages add no buffering. | |
Static Public Attributes | |
| static constexpr int | kMinStages = 4 |
| Fewest stages. | |
| static constexpr int | kMaxStages = 12 |
| Most stages. The DP/4's documented stage count, used as the anchor. | |
| static constexpr int | kStageCountDefault = 4 |
| Compact four-stage phaser class: two notches. | |
| static constexpr double | kFeedbackMax = 0.9 |
| Feedback magnitude ceiling. | |
| static constexpr double | kColorOffFeedback = 0.0 |
| The two documented "Color" switch positions, as preset points. | |
| static constexpr double | kColorOnFeedback = 0.65 |
| static constexpr double | kSweepRangeRatio = 1.0 |
| fc(t) = center · (1 + depth · kSweepRangeRatio · lfo(t)). | |
| static constexpr double | kSweepFloorHz = 20.0 |
| Sweep floor in Hz. | |
| static constexpr double | kSweepCeilingRatio = 0.45 |
| Sweep ceiling as a fraction of the sample rate. | |
| static constexpr double | kStaggerDefault = 1.0 |
| Per-stage corner ratio: stage i runs at fc · kStagger^i. | |
| static constexpr double | kStaggerMin = 0.85 |
| static constexpr double | kStaggerMax = 1.15 |
| static constexpr double | kMixDefault = 0.5 |
| The full-notch mix point. | |
| static constexpr double | kRateDefaultHz = 0.5 |
| Default LFO rate. | |
| static constexpr double | kPi = 3.14159265358979323846 |
| π, at the precision the notch laws need. | |
A cascaded first-order-allpass phaser.
Stereo, 4–12 stages, bounded feedback, LFO sweep with quadrature stereo spread.
| using pulp::signal::PhaserStagesT< SampleType >::Wave = LfoWave |
The LFO shape enum, forwarded verbatim.
There is deliberately no phaser-local copy of it.
|
inline |
A default instance is a Small Stone: 4 stages, 0.5 Hz triangle, 400 Hz centre, full depth, Color off, mix at the full-notch point, mono.
|
inline |
|
inline |
|
inline |
|
inlinestaticconstexpr |
Zero. The dry path is a wire and the TPT stages add no buffering.
|
inline |
|
inlinestaticconstexpr |
How many notches an N-stage cascade produces. N/2, for even N.
|
inlinestatic |
The cited analog-prototype notch law: f_k = fc · tan((2k−1)π/2N).
Exact for the continuous-time cascade, and the closed form that shows the notch pattern is a fixed ratio set around fc. It is an APPROXIMATION to what this code does — see the file doc block for where it breaks down, and prefer notch_frequency_hz for expectations.
|
inlinestatic |
The exact notch law for the shipped TPT cascade: f_k = (fs/π)·arctan( tan(π·fc/fs) · tan((2k−1)π/2N) ).
Always strictly below Nyquist, for any fc and any k ≤ stages/2, because arctan cannot reach π/2.
|
inline |
Sets the sample rate and returns the instance to a fresh, silent state.
Allocates nothing — every buffer here is a fixed-size member.
|
inline |
Stereo block process.
Safe in place: out_l/out_r may alias in_l/in_r, because each frame's input is read into a local before its output is written.
|
inline |
Mono block process, driving channel 0 only.
The right channel's LFO still advances — so switching a running instance to stereo does not jump its phase — but its cascade is not run, so the mono path costs half of what the stereo one does.
|
inline |
|
inline |
Clears every stage's integrator, the feedback memories, and both LFO phases, so a render from here is bit-identical every time.
|
inline |
Allpass corner frequency at the LFO's midpoint.
|
inline |
Sweep excursion, 0..1.
1.0 swings fc across [0, 2·center] before the floor and ceiling clamps apply.
|
inline |
Feedback ("Color"), clamped to ±kFeedbackMax.
Positive adds a resonant peak — see the doc block on what it does NOT do — and moves the nulls off the open-loop law. Negative flattens the whole response and is a catalog-only extension with no hardware precedent. Both signs obey the same gain bound.
|
inline |
Dry/wet, 0..1. 0.5 is the full-notch point; 1.0 is a flat allpass.
|
inline |
LFO rate in Hz. Forwarded to both channels' LFOs.
|
inline |
Seeds both LFOs identically, so the stochastic shapes stay a phase-shifted copy of each other rather than decorrelating.
A construction/preset choice, never automated (series law 2).
|
inline |
Active stage count.
Clamped into [4, 12] and then rounded DOWN to the nearest even value — 5 → 4, 7 → 6, 13 → 12 — because odd counts put the last odd-π crossing exactly at Nyquist where it is not a notch. The result is readable through stage_count(); nothing is silently ignored.
|
inline |
Per-stage corner ratio; 1.0 (the default) means every stage shares one fc, which is the documented single-control-current topology.
|
inline |
Right-channel LFO lead in CYCLES, 0..0.5.
0.25 is quadrature — the catalog's 90° default. 0 makes the two channels bit-identical.
|
inline |
LFO shape, forwarded verbatim to both channels' LFOs.
The catalog contract exposes triangle and sine. Direct C++ callers can pass the wider shared LfoWave enum; when they do, stereo spread remains literally a PHASE offset rather than a normalized-width macro. In particular, saw at 0.5 cycles is not an inversion (its discontinuity is phase-shifted), so its side/mid trajectory differs from triangle/sine.
|
inline |
|
inline |
|
inline |
|
inline |
The channel's current swept corner frequency in Hz, after clamping — the quantity the notch laws take as fc.
Exposed because it is what a host draws as a sweep readout, and what the stereo-spread and waveform-shape tests measure directly instead of trying to recover it from audio.
|
inline |
|
inlinestaticconstexpr |
The worst-case output/input magnitude over all frequencies, mixes and feedback settings — the number Forge's registry row cites.
Equality, not an estimate: see the derivation in the file doc block.
|
staticconstexpr |
The two documented "Color" switch positions, as preset points.
|
staticconstexpr |
|
staticconstexpr |
Feedback magnitude ceiling.
The worst-case-gain proof is 1/(1 − kFeedbackMax); widening this without redoing that proof is a stability change, not a range change.
|
staticconstexpr |
Most stages. The DP/4's documented stage count, used as the anchor.
|
staticconstexpr |
Fewest stages.
Below 4 the cascade produces a single notch and the effect reads as a phase shift rather than a sweep.
|
staticconstexpr |
The full-notch mix point.
|
staticconstexpr |
π, at the precision the notch laws need.
|
staticconstexpr |
Default LFO rate.
[design parameter] default 0.5 Hz, range 0.02 .. 10 Hz — the span a single vintage "Rate" pot covers, slow enough to read as a sweep and fast enough to reach the "jet" idiom.
|
staticconstexpr |
Compact four-stage phaser class: two notches.
|
staticconstexpr |
Per-stage corner ratio: stage i runs at fc · kStagger^i.
[design parameter] default 1.0 (off), range 0.85 .. 1.15. OFF by default and flagged as an original catalog extension: no public source documents a hardware phaser staggering its stages, so switching it on leaves the vintage-behaviour claim behind.
|
staticconstexpr |
|
staticconstexpr |
|
staticconstexpr |
Sweep ceiling as a fraction of the sample rate.
[design parameter] default 0.45, range 0.30 .. 0.49. The bilinear prewarp tan(π·fc/fs) diverges at Nyquist; 0.45 keeps the coefficient finite with margin.
|
staticconstexpr |
Sweep floor in Hz.
[design parameter] default 20, range 5 .. 50. The mapping above reaches 0 Hz at depth 100 %, where tan(π·fc/fs) is 0, the stage degenerates to a sign flip, and every notch collapses onto DC. Any floor below the bottom of hearing removes that degeneracy without being audible as a limit.
|
staticconstexpr |
fc(t) = center · (1 + depth · kSweepRangeRatio · lfo(t)).
[design parameter] default 1.0, fixed — it is what makes depth 100 % mean "sweep from DC to twice centre", which the presets assume.