A zap: a phase-distortion percussion voice. More...
#include <zap.hpp>
Public Member Functions | |
| ZapVoice () | |
| void | set_tune_hz (double hz) |
| void | set_pitch_sweep_octaves (double octaves) |
| Depth and time constant of the pitch drop, in octaves. | |
| void | set_pitch_sweep_ms (double ms) |
| void | set_decay_ms (double ms) |
| How long the note lasts, as a T60. | |
| void | set_shape (PhaseDistortionShape shape) |
| void | set_distortion (double amount) |
| Distortion depth at the start of the hit, and how quickly it collapses. | |
| void | set_distortion_ms (double ms) |
| void | set_resonant_depth (double multiples) |
| Highest carrier multiple the resonant shapes reach. | |
| void | set_detune_cents (double cents) |
| Detune of the second oscillator, in cents. | |
| void | set_ring (double amount) |
| Depth of a ring modulation applied to the pair, and its ratio to the tuning. | |
| void | set_ring_ratio (double ratio) |
| LowpassGate & | gate () |
| OutputStage & | output () |
| const OutputStage & | output () const |
| OutputStage * | output_stage () noexcept override |
| The terminal saturation and degradation stage, at the generic voice boundary. | |
| int | latency_samples () const noexcept override |
| Fixed host-rate delay introduced by this voice's selected output quality. | |
| OutputOversampling | output_oversampling () const noexcept override |
| Output quality at the generic voice boundary. | |
| void | set_output_oversampling (OutputOversampling factor) override |
| void | prepare (double sample_rate) |
| Fixes the sample rate and clears all state. | |
| void | reset () |
| Silences the voice immediately, without a fade. | |
| void | note_on (float velocity) |
| Starts a hit. velocity is in [0, 1]; values outside are clamped. | |
| void | choke (float fade_ms=4.0f) |
| Fades the voice out over fade_ms and then silences it. | |
| bool | is_active () const |
| Whether the voice still has something to render. | |
| VoiceState | state () const |
| float | velocity () const |
| double | sample_rate () const |
| const OutputStage * | output_stage () const noexcept |
| void | set_velocity_response (const VelocityResponse &r) |
| const VelocityResponse & | velocity_response () const |
| void | process (float *out, int num_samples) |
| Adds num_samples of this voice's output into out. | |
| void | process_stereo (float *left, float *right, int num_samples) |
| Adds a stereo rendering to left and right. | |
Protected Member Functions | |
| void | on_prepare (double sample_rate) override |
| Sizes buffers and fixes coefficients. | |
| void | on_reset () override |
| Clears every piece of state the voice carries, so is_active() becomes false and the next render starts from silence. | |
| void | on_note_on (float velocity) override |
| Starts a hit at the given velocity, already clamped to [0, 1]. | |
| bool | on_is_active () const override |
| void | render_add (float *out, int num_samples) override |
| Adds the voice's output into out. Must add, never assign. | |
| virtual void | render_add_stereo (float *left, float *right, int num_samples) |
| Optional stereo realization. | |
A zap: a phase-distortion percussion voice.
The sound this voice is named for is the one phase distortion is uniquely good at. Two envelopes run at once and they are doing different things: the pitch drops, as in any electronic drum, and the distortion amount drops independently, which sweeps the apparent resonant peak down through the spectrum. Because the peak is produced by reading a cosine at a swept multiple of the phase rather than by a filter, it can be swept faster and further than any filter would stay stable through — which is exactly why the resulting sound has no equivalent in a subtractive voice.
Decoupling the two is the point. Tying the distortion sweep to the pitch sweep gives an ordinary filtered drop; letting the distortion collapse while the pitch is still falling is what produces the zap.
Two oscillators, the second detuned, because a single phase-distortion oscillator is a very pure sound and the beating between two is most of what gives the voice weight.
Lineage: Casio's phase-distortion patent, US 4,658,691 (expired), implemented from the published description. See pulp::signal::PhaseDistortionOscT.
RT contract: prepare() allocates nothing; every other method, including note_on and process, allocates nothing and takes no locks.
|
inline |
|
inlineinherited |
Fades the voice out over fade_ms and then silences it.
Used by choke groups; a shorter fade is more abrupt but never clicks the way an instant cut does.
|
inline |
|
inlineinherited |
Whether the voice still has something to render.
A kit uses this to skip voices entirely rather than summing silence.
|
inlineoverridevirtualnoexcept |
Fixed host-rate delay introduced by this voice's selected output quality.
Generic registry consumers can report it without recovering the concrete voice type.
Reimplemented from pulp::signal::drum::Voice.
|
inlineinherited |
Starts a hit. velocity is in [0, 1]; values outside are clamped.
|
inlineoverrideprotectedvirtual |
Implements pulp::signal::drum::Voice.
|
inlineoverrideprotectedvirtual |
Starts a hit at the given velocity, already clamped to [0, 1].
Implements pulp::signal::drum::Voice.
|
inlineoverrideprotectedvirtual |
Sizes buffers and fixes coefficients.
The only hook allowed to allocate.
Implements pulp::signal::drum::Voice.
|
inlineoverrideprotectedvirtual |
Clears every piece of state the voice carries, so is_active() becomes false and the next render starts from silence.
Implements pulp::signal::drum::Voice.
|
inline |
|
inline |
|
inlineoverridevirtualnoexcept |
Output quality at the generic voice boundary.
Kits use this surface to keep every registered path on one latency contract.
Reimplemented from pulp::signal::drum::Voice.
|
inlinenoexceptinherited |
|
inlineoverridevirtualnoexcept |
The terminal saturation and degradation stage, at the generic voice boundary.
A registry consumer reaches it without recovering the concrete voice type, so adding an engine cannot desynchronise a downcast from the engine it was selected for. A voice that ends without one returns nullptr.
Reimplemented from pulp::signal::drum::Voice.
|
inlineinherited |
Fixes the sample rate and clears all state.
The only method a derived voice may allocate in.
|
inlineinherited |
Adds num_samples of this voice's output into out.
|
inlineinherited |
Adds a stereo rendering to left and right.
Voices that do not provide a stereo realization are placed in the centre with half their mono signal in each channel, so summing the two channels reproduces process() exactly. A stereo-capable voice may override render_add_stereo, but the shared choke fade remains here.
|
inlineoverrideprotectedvirtual |
Adds the voice's output into out. Must add, never assign.
Implements pulp::signal::drum::Voice.
|
inlineprotectedvirtualinherited |
Optional stereo realization.
The default is centre-panned and preserves exact mono-sum equivalence.
Reimplemented in pulp::signal::drum::ClapVoice.
|
inlineinherited |
Silences the voice immediately, without a fade.
For transport stops and buffer-size changes, where a click cannot be heard because nothing is playing either side of it.
|
inlineinherited |
|
inline |
How long the note lasts, as a T60.
|
inline |
Detune of the second oscillator, in cents.
|
inline |
Distortion depth at the start of the hit, and how quickly it collapses.
This envelope is deliberately independent of the pitch sweep.
|
inline |
|
inlineoverridevirtual |
Reimplemented from pulp::signal::drum::Voice.
|
inline |
|
inline |
Depth and time constant of the pitch drop, in octaves.
|
inline |
Highest carrier multiple the resonant shapes reach.
|
inline |
Depth of a ring modulation applied to the pair, and its ratio to the tuning.
Ring modulation of an already-swept pair is what takes the voice from a zap toward a clang.
|
inline |
|
inline |
|
inline |
|
inlineinherited |
|
inlineinherited |
|
inlineinherited |
|
inlineinherited |