|
| | KickVoice () |
| void | set_body (KickBody body) |
| KickBody | body () const |
| void | set_tune_hz (double hz) |
| | Fundamental of the body, in Hz.
|
| void | set_body_decay_ms (double ms) |
| | How long the body rings, as a T60 in milliseconds.
|
| void | set_pitch_sweep_octaves (double octaves) |
| | Depth of the downward pitch sweep, in octaves, and how quickly it settles.
|
| void | set_pitch_sweep_ms (double ms) |
| void | set_click_level (double level) |
| | Level of the attack click, and the corner of the one-pole that tones it.
|
| void | set_click_tone_hz (double hz) |
| void | set_click_decay_ms (double ms) |
| void | set_noise_level (double level) |
| | Level and decay of the noise layer.
|
| void | set_noise_decay_ms (double ms) |
| void | set_noise_color (NoiseColor color) |
| void | set_sub_level (double level) |
| | Level of the sub layer, a sine an octave below the body gated by the body's own envelope.
|
| OutputStage & | output () |
| | The saturation and degradation stage the voice ends with.
|
| 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 | set_oscillator_triangle (bool triangle) |
| | Triangle instead of sine.
|
| void | set_fm_amount (double amount) |
| | Phase-modulation depth and the modulator's frequency ratio.
|
| void | set_fm_ratio (double ratio) |
| void | set_circuit_components (const BridgedTComponents &c) |
| | Component values of the bridged-T network.
|
| void | set_circuit_feedback (double gain) |
| | Regeneration around the network, 0 to 1.
|
| void | set_circuit_attack_ms (double ms) |
| | How long the attack shunt grounds the transistor's collector after a trigger.
|
| void | set_circuit_pulse_ms (double ms) |
| | Width of the trigger pulse into the pulse shaper, in milliseconds.
|
| void | set_circuit_drive (double amount) |
| | How hard the trigger drives the network, 0 to 1.
|
| void | set_circuit_sigh (bool enabled) |
| | Disconnect the leakage path that produces the pitch sigh.
|
| void | set_circuit_hit_life (HitLifeMode mode) |
| | Select whether circuit retriggers restart, vary their excitation, or preserve the network memory.
|
| HitLifeMode | circuit_hit_life () const |
| 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.
|
|
| 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 kick drum.
The layers are the ones every electronic kick has had since the 1970s: a body that carries the pitch, a click that carries the attack, a noise layer that carries the air the beater moves, and an optional sub an octave down for systems that reproduce it. What distinguishes one machine's kick from another's is almost entirely how the body is made, which is what KickBody selects.
Velocity reaches timbre through VelocityResponse: harder hits bend the pitch further and brighten the click, which is what a beater striking a head harder actually does. The default response has both enabled, so a caller gets a velocity-sensitive kick without configuring one.
RT contract: prepare() allocates nothing; every other method, including note_on and process, allocates nothing and takes no locks.
| void pulp::signal::drum::KickVoice::set_circuit_drive |
( |
double | amount | ) |
|
|
inline |
How hard the trigger drives the network, 0 to 1.
Unlike most drive controls this one is not a taste control layered on top of a working circuit – it moves the network through the only range in which it behaves at all, so the control is mapped across that window rather than across an arbitrary one.
At 0 the ring only just pushes the transistor past its conduction knee, so the pitch drop is at its weakest. Below that window the drop stops happening entirely, which is why 0 is the floor. At 1 the op-amp is approaching its supply rail, so the ring begins to flatten into a square. Both ends are audible character rather than faults, and they are reachable on purpose: clamping the range to the middle would remove the two sounds the circuit is most recognisable for.
| void pulp::signal::drum::KickVoice::set_circuit_feedback |
( |
double | gain | ) |
|
|
inline |
Regeneration around the network, 0 to 1.
This is the 808's decay control: the loop replaces some of what the network dissipates each cycle, so more feedback is a longer ring rather than a louder one.
The control is normalised rather than being the raw loop gain, because the raw gain has a hard ceiling: past about 0.87 the loop replaces more than the network loses and the drum becomes an oscillator that never stops. 1 here maps to just under that, which is a very long ring and still a drum. The real instrument's decay pot has an end stop for the same reason.
| void pulp::signal::drum::KickVoice::set_pitch_sweep_octaves |
( |
double | octaves | ) |
|
|
inline |
Depth of the downward pitch sweep, in octaves, and how quickly it settles.
These apply to the oscillator body only. The resonant body is struck at a fixed frequency, and the circuit body produces its sweep from the network; both ignore these. The velocity bend is carried on the same term, so it too reaches the oscillator body alone – which is why the Forge catalog declares neither control on the other bodies.
Octaves rather than a linear multiplier, so the sweep composes additively with the velocity bend, which is also in octaves. A depth quoted in the multiplier form converts as octaves = log2(1 + amount).