Additive Synthesis, Vocoding, and Modular Sequencing¶
This guide covers the authoring pieces for additive voices, a channel vocoder,
and clocked modular control. They compose inside a Processor; use a
SignalGraph only when users can change the routing itself at run time.
Additive bank¶
AdditiveBank renders up to the prepared partial capacity with a voice table,
inharmonicity, spectral tilt, two morphable spectral envelopes, attack/release,
detuned doublets, pitch glide, and deterministic retrigger phase.
#include <pulp/signal/additive_bank.hpp>
pulp::signal::AdditiveBank bank;
bank.prepare(sample_rate, 128);
bank.set_partial_count(32);
bank.set_fundamental_hz(110.0);
bank.set_spectral_tilt_db_oct(-3.0);
bank.set_attack_ms(8.0);
bank.set_release_ms(400.0);
bank.retrigger();
bank.process(output, num_frames); // replaces output
SpectralEnvelope::gain_db_at() and AdditiveBank::envelope_db_at() expose the
configured and realized curves respectively. Use them for plots and tests.
Vocoder¶
Vocoder owns the analysis and synthesis banks, envelope followers, internal or
external carrier, unvoiced/sibilance path, formant shift/freeze, trim, and
dry/wet mix. process(modulator, carrier, out_dry) returns the wet sample and
writes the DC-blocked dry sample used by its mix contract. Band inspection
methods expose the exact filters and gains used by the renderer.
Modular sequencing¶
| Type | Header | Purpose |
|---|---|---|
StageSeq |
<pulp/signal/stage_sequencer.hpp> |
Per-stage pitch, pulses, gate modes, slide, skip, and direction |
CartesianWalk |
<pulp/signal/cartesian_walk.hpp> |
Independently clocked X/Y grid walk with cell CV and gate |
Rungler |
<pulp/signal/rungler.hpp> |
Shift-register feedback pattern and DAC output |
QuantizeScale |
<pulp/signal/scale_quantizer.hpp> |
EDO or scale-mask voltage quantization with hysteresis |
ProbGate |
<pulp/signal/probability_gate.hpp> |
One seeded draw per trigger edge |
GateLogic |
<pulp/signal/gate_logic.hpp> |
Boolean or thresholded level-domain gate operations |
All event processors distinguish continuous level from edge events. Compute an
edge once, then pass that boolean to every consumer that should observe the same
event; do not let several processors independently reinterpret one noisy clock.
apply_reset_edge() performs the documented live reset, while reset() returns
the whole object to deterministic initial state.
See the modulation toolkit for clock, trigger, envelope, VCA, and routing primitives. The complete advanced DSP API lists every method on the types above.