|
| | 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.
|
|
| 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 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.