Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
pulp::signal::drum::FmDrumVoice Class Reference

A two-operator FM percussion voice. More...

#include <fm.hpp>

Public Member Functions

 FmDrumVoice ()
void set_tune_hz (double hz)
 Carrier frequency, in Hz.
void set_ratio (double ratio)
 Modulator frequency as a ratio of the carrier.
void set_index (double index)
 Modulation index at the strike, and how fast it collapses.
void set_index_ms (double ms)
void set_decay_ms (double ms)
 How long the note lasts, as a T60.
void set_pitch_sweep_octaves (double octaves)
 Pitch envelope depth in octaves and its time constant.
void set_pitch_sweep_ms (double ms)
void set_feedback (double amount)
 Modulator self-feedback, 0 to 1.
void set_carrier_wave (int wave)
 The 26 shared phase-readable waves and each operator's decaying Casio-family phase warp.
void set_modulator_wave (int wave)
void set_carrier_warp (double amount)
void set_modulator_warp (double amount)
void set_carrier_warp_ms (double ms)
void set_modulator_warp_ms (double ms)
void set_lfo_rate_hz (double hz)
 Delayed, faded pitch LFO.
void set_lfo_depth_octaves (double octaves)
void set_lfo_delay_ms (double ms)
void set_lfo_fade_ms (double ms)
void set_hard_sync (bool sync)
 Reset the modulator phase whenever the carrier wraps.
void set_transient (int index)
 Select one of the shared 24 procedural strike recipes.
void set_noise_level (double level)
void set_noise_decay_ms (double ms)
void set_noise_color (NoiseColor color)
void set_cutoff_hz (double hz)
 A bandpass on the output, for picking one formant out of the sidebands.
void set_resonance (double q)
void set_bandpass (bool bandpass)
void set_click_level (double level)
void set_click_cutoff_hz (double hz)
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.

Detailed Description

A two-operator FM percussion voice.

Frequency modulation earns its place in a drum kit for one reason: the sidebands it produces are spaced by the modulator's frequency, so setting a non-integer ratio puts partials at frequencies that belong to no harmonic series. That is inharmonicity generated rather than filtered, and it is why two operators can produce a bell, a clank or a metallic tom that a filtered oscillator cannot reach at any setting.

The ratio decides where the partials land — integer ratios stay harmonic, ratios near a simple fraction beat, and irrational-ish ratios clang. The index decides how many there are, and because it is enveloped separately from amplitude the spectrum collapses while the note is still sounding. The shared 26-wave table and per-operator warp envelopes broaden the strike vocabulary without changing those FM fundamentals.

The modulator feeds back into itself through a one-sample delay. As that feedback rises the modulator's own waveform moves continuously from a sine toward a saw and then into noise, which is a cheap and controllable way to reach a noise-like strike without a separate noise source.

Lineage: Chowning, "The Synthesis of Complex Audio Spectra by Means of Frequency Modulation", JAES 21(7), 1973. Implemented from the published technique.

RT contract: prepare() allocates nothing; every other method, including note_on and process, allocates nothing and takes no locks.

Constructor & Destructor Documentation

◆ FmDrumVoice()

pulp::signal::drum::FmDrumVoice::FmDrumVoice ( )
inline

Member Function Documentation

◆ choke()

void pulp::signal::drum::Voice::choke ( float fade_ms = 4.0f)
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.

◆ is_active()

bool pulp::signal::drum::Voice::is_active ( ) const
inlineinherited

Whether the voice still has something to render.

A kit uses this to skip voices entirely rather than summing silence.

◆ latency_samples()

int pulp::signal::drum::FmDrumVoice::latency_samples ( ) const
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.

◆ note_on()

void pulp::signal::drum::Voice::note_on ( float velocity)
inlineinherited

Starts a hit. velocity is in [0, 1]; values outside are clamped.

◆ on_is_active()

bool pulp::signal::drum::FmDrumVoice::on_is_active ( ) const
inlineoverrideprotectedvirtual

◆ on_note_on()

void pulp::signal::drum::FmDrumVoice::on_note_on ( float velocity)
inlineoverrideprotectedvirtual

Starts a hit at the given velocity, already clamped to [0, 1].

Implements pulp::signal::drum::Voice.

◆ on_prepare()

void pulp::signal::drum::FmDrumVoice::on_prepare ( double sample_rate)
inlineoverrideprotectedvirtual

Sizes buffers and fixes coefficients.

The only hook allowed to allocate.

Implements pulp::signal::drum::Voice.

◆ on_reset()

void pulp::signal::drum::FmDrumVoice::on_reset ( )
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.

◆ output() [1/2]

OutputStage & pulp::signal::drum::FmDrumVoice::output ( )
inline

◆ output() [2/2]

const OutputStage & pulp::signal::drum::FmDrumVoice::output ( ) const
inline

◆ output_oversampling()

OutputOversampling pulp::signal::drum::FmDrumVoice::output_oversampling ( ) const
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.

◆ output_stage() [1/2]

OutputStage * pulp::signal::drum::FmDrumVoice::output_stage ( )
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.

◆ output_stage() [2/2]

const OutputStage * pulp::signal::drum::Voice::output_stage ( ) const
inlinenoexceptinherited

◆ prepare()

void pulp::signal::drum::Voice::prepare ( double sample_rate)
inlineinherited

Fixes the sample rate and clears all state.

The only method a derived voice may allocate in.

◆ process()

void pulp::signal::drum::Voice::process ( float * out,
int num_samples )
inlineinherited

Adds num_samples of this voice's output into out.

◆ process_stereo()

void pulp::signal::drum::Voice::process_stereo ( float * left,
float * right,
int num_samples )
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.

◆ render_add()

void pulp::signal::drum::FmDrumVoice::render_add ( float * out,
int num_samples )
inlineoverrideprotectedvirtual

Adds the voice's output into out. Must add, never assign.

Implements pulp::signal::drum::Voice.

◆ render_add_stereo()

virtual void pulp::signal::drum::Voice::render_add_stereo ( float * left,
float * right,
int num_samples )
inlineprotectedvirtualinherited

Optional stereo realization.

The default is centre-panned and preserves exact mono-sum equivalence.

Reimplemented in pulp::signal::drum::ClapVoice.

◆ reset()

void pulp::signal::drum::Voice::reset ( )
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.

◆ sample_rate()

double pulp::signal::drum::Voice::sample_rate ( ) const
inlineinherited

◆ set_bandpass()

void pulp::signal::drum::FmDrumVoice::set_bandpass ( bool bandpass)
inline

◆ set_carrier_warp()

void pulp::signal::drum::FmDrumVoice::set_carrier_warp ( double amount)
inline

◆ set_carrier_warp_ms()

void pulp::signal::drum::FmDrumVoice::set_carrier_warp_ms ( double ms)
inline

◆ set_carrier_wave()

void pulp::signal::drum::FmDrumVoice::set_carrier_wave ( int wave)
inline

The 26 shared phase-readable waves and each operator's decaying Casio-family phase warp.

◆ set_click_cutoff_hz()

void pulp::signal::drum::FmDrumVoice::set_click_cutoff_hz ( double hz)
inline

◆ set_click_level()

void pulp::signal::drum::FmDrumVoice::set_click_level ( double level)
inline

◆ set_cutoff_hz()

void pulp::signal::drum::FmDrumVoice::set_cutoff_hz ( double hz)
inline

A bandpass on the output, for picking one formant out of the sidebands.

◆ set_decay_ms()

void pulp::signal::drum::FmDrumVoice::set_decay_ms ( double ms)
inline

How long the note lasts, as a T60.

◆ set_feedback()

void pulp::signal::drum::FmDrumVoice::set_feedback ( double amount)
inline

Modulator self-feedback, 0 to 1.

Moves the modulator from a sine toward a saw and then into noise.

◆ set_hard_sync()

void pulp::signal::drum::FmDrumVoice::set_hard_sync ( bool sync)
inline

Reset the modulator phase whenever the carrier wraps.

◆ set_index()

void pulp::signal::drum::FmDrumVoice::set_index ( double index)
inline

Modulation index at the strike, and how fast it collapses.

The index envelope is deliberately separate from the amplitude envelope.

◆ set_index_ms()

void pulp::signal::drum::FmDrumVoice::set_index_ms ( double ms)
inline

◆ set_lfo_delay_ms()

void pulp::signal::drum::FmDrumVoice::set_lfo_delay_ms ( double ms)
inline

◆ set_lfo_depth_octaves()

void pulp::signal::drum::FmDrumVoice::set_lfo_depth_octaves ( double octaves)
inline

◆ set_lfo_fade_ms()

void pulp::signal::drum::FmDrumVoice::set_lfo_fade_ms ( double ms)
inline

◆ set_lfo_rate_hz()

void pulp::signal::drum::FmDrumVoice::set_lfo_rate_hz ( double hz)
inline

Delayed, faded pitch LFO.

Delay and fade are independent so vibrato can enter after the strike without stepping on.

◆ set_modulator_warp()

void pulp::signal::drum::FmDrumVoice::set_modulator_warp ( double amount)
inline

◆ set_modulator_warp_ms()

void pulp::signal::drum::FmDrumVoice::set_modulator_warp_ms ( double ms)
inline

◆ set_modulator_wave()

void pulp::signal::drum::FmDrumVoice::set_modulator_wave ( int wave)
inline

◆ set_noise_color()

void pulp::signal::drum::FmDrumVoice::set_noise_color ( NoiseColor color)
inline

◆ set_noise_decay_ms()

void pulp::signal::drum::FmDrumVoice::set_noise_decay_ms ( double ms)
inline

◆ set_noise_level()

void pulp::signal::drum::FmDrumVoice::set_noise_level ( double level)
inline

◆ set_output_oversampling()

void pulp::signal::drum::FmDrumVoice::set_output_oversampling ( OutputOversampling factor)
inlineoverridevirtual

Reimplemented from pulp::signal::drum::Voice.

◆ set_pitch_sweep_ms()

void pulp::signal::drum::FmDrumVoice::set_pitch_sweep_ms ( double ms)
inline

◆ set_pitch_sweep_octaves()

void pulp::signal::drum::FmDrumVoice::set_pitch_sweep_octaves ( double octaves)
inline

Pitch envelope depth in octaves and its time constant.

◆ set_ratio()

void pulp::signal::drum::FmDrumVoice::set_ratio ( double ratio)
inline

Modulator frequency as a ratio of the carrier.

Integer ratios keep the result harmonic; everything else is where the metal lives.

◆ set_resonance()

void pulp::signal::drum::FmDrumVoice::set_resonance ( double q)
inline

◆ set_transient()

void pulp::signal::drum::FmDrumVoice::set_transient ( int index)
inline

Select one of the shared 24 procedural strike recipes.

-1 leaves the manually configured click/noise controls in place.

◆ set_tune_hz()

void pulp::signal::drum::FmDrumVoice::set_tune_hz ( double hz)
inline

Carrier frequency, in Hz.

◆ set_velocity_response()

void pulp::signal::drum::Voice::set_velocity_response ( const VelocityResponse & r)
inlineinherited

◆ state()

VoiceState pulp::signal::drum::Voice::state ( ) const
inlineinherited

◆ velocity()

float pulp::signal::drum::Voice::velocity ( ) const
inlineinherited

◆ velocity_response()

const VelocityResponse & pulp::signal::drum::Voice::velocity_response ( ) const
inlineinherited

The documentation for this class was generated from the following file:
  • /home/runner/work/pulp/pulp/core/signal/include/pulp/signal/drum/fm.hpp