95 static constexpr std::array<PresetData, 8>
presets{{
118 r.bend_octaves = 1.5f;
119 r.brightness_octaves = 1.0f;
122 click_.set_level(0.35);
123 click_.set_cutoff_hz(5000.0);
124 click_.set_decay_ms(2.0);
128 void set_tune_hz(
double hz) { tune_hz_ = std::clamp(hz, 30.0, 1200.0); }
134 void set_bend_ms(
double ms) { bend_ms_ = std::clamp(ms, 0.5, 500.0); }
137 void set_decay_ms(
double ms) { decay_ms_ = std::clamp(ms, 10.0, 4000.0); }
148 noise_resonance_ = std::clamp(amount, 0.0, 1.0);
160 if (profile != ladder_math_profile_) noise_filter_.reset();
161 ladder_math_profile_ = profile;
166 return ladder_math_profile_;
176 const auto it = std::find_if(
178 [preset](
const PresetData& data) { return data.id == preset; });
179 if (it ==
presets.end())
return;
206 return output_.latency_samples();
209 return output_.oversampling();
212 output_.set_oversampling(factor);
221 noise_filter_.set_sample_rate(
static_cast<float>(
sample_rate));
222 click_hp_.prepare(
static_cast<float>(
sample_rate));
238 noise_filter_.reset();
247 output_.reset_nonlinear_state();
250 velocity_gain_ = response.gain(
velocity);
254 applied_bend_ = bend_octaves_ + response.bend(
velocity);
255 brightness_ = response.brightness_scale(
velocity);
261 bend_env_.set_attack_ms(0.0);
262 bend_env_.set_decay_time_constant_ms(bend_ms_);
265 amp_env_.set_attack_ms(0.5);
266 amp_env_.set_decay_t60_ms(decay_ms_);
269 click_.trigger(brightness_);
271 noise_filter_.set_frequency(
static_cast<float>(
272 std::min(noise_cutoff_hz_ * brightness_, 0.45 *
sample_rate())));
273 noise_filter_.set_resonance(
static_cast<float>(noise_resonance_));
277 return amp_env_.is_active() || click_.is_active() || body_lofi_.has_tail() ||
278 noise_lofi_.has_tail() || output_.has_tail();
283 render_add_profiled<true>(out, num_samples);
285 render_add_profiled<false>(out, num_samples);
289 template <
bool RealtimeEfficient>
290 void render_add_profiled(
float* out,
int num_samples) {
291 const double oscillator_mix = 1.0 - noise_balance_;
293 for (
int i = 0;
i < num_samples; ++
i) {
296 const double bend = bend_env_.
process();
297 const double amplitude = amp_env_.
process();
300 if (oscillator_mix > 0.0) {
301 const double f = std::min(tune_hz_ * std::exp2(applied_bend_ * bend),
304 if (phase_ >= 1.0) phase_ -= std::floor(phase_);
306 ? 2.0 * std::fabs(2.0 * phase_ - 1.0) - 1.0
307 : std::sin(2.0 * 3.14159265358979323846 * phase_));
313 body =
static_cast<double>(body_lofi_.
process(
static_cast<float>(body)));
316 if (noise_balance_ > 0.0) {
317 hiss = noise_balance_ *
318 static_cast<double>(RealtimeEfficient
322 hiss =
static_cast<double>(noise_lofi_.
process(
static_cast<float>(hiss)));
324 const double beater =
328 const double mixed = (body + hiss) * amplitude + beater;
329 out[
i] +=
static_cast<float>(
330 output_.
process(
static_cast<float>(mixed)) * velocity_gain_);
334 double tune_hz_ = 120.0;
335 double bend_octaves_ = 1.0;
336 double bend_ms_ = 30.0;
337 double decay_ms_ = 500.0;
339 double noise_balance_ = 0.15;
340 double noise_cutoff_hz_ = 1500.0;
341 double noise_resonance_ = 0.3;
354 double velocity_gain_ = 1.0;
355 double applied_bend_ = 1.0;
356 double brightness_ = 1.0;
SampleType process()
Next envelope sample in [0, peak].
Definition decay_envelope.hpp:125
SampleType process_reference(SampleType input)
Process one sample with exact std::tanh stages.
Definition ladder_filter.hpp:40
SampleType process_realtime_efficient(SampleType input)
Process one sample with the Padé FastMath::tanh stages.
Definition ladder_filter.hpp:45
SampleType process(SampleType input)
Definition lofi_chain.hpp:300
SampleType process()
Next sample, normalised so every colour has approximately the same RMS.
Definition noise_source.hpp:111
SampleType white()
Raw uniform white sample in [-1, 1), bypassing the colour filter and the normalisation.
Definition noise_source.hpp:123
SampleType process_highpass(SampleType input)
Process and return the highpass output.
Definition tpt_filter.hpp:78
double process(double noise)
Next sample. noise is a raw white sample from the voice's generator.
Definition layers.hpp:85
SampleType process(SampleType input)
Definition output_stage.hpp:204
void set_noise_resonance(double amount)
Definition tom.hpp:147
LadderMathProfile ladder_math_profile() const noexcept
Definition tom.hpp:165
void on_prepare(double sample_rate) override
Sizes buffers and fixes coefficients.
Definition tom.hpp:216
const LofiChain & body_lofi() const
Definition tom.hpp:198
const LofiChain & noise_lofi() const
Definition tom.hpp:200
OutputOversampling output_oversampling() const noexcept override
Output quality at the generic voice boundary.
Definition tom.hpp:208
void set_noise_cutoff_hz(double hz)
Corner and resonance of the four-pole lowpass the noise runs through.
Definition tom.hpp:146
void set_tune_hz(double hz)
Pitch the body settles at, in Hz.
Definition tom.hpp:128
void set_click_level(double level)
The beater.
Definition tom.hpp:171
void set_noise_balance(double amount)
Balance between the oscillator (0) and the filtered noise (1).
Definition tom.hpp:142
bool set_ladder_math_profile(LadderMathProfile profile) noexcept
Selects the noise ladder's saturation curve between hits.
Definition tom.hpp:155
void set_click_cutoff_hz(double hz)
Definition tom.hpp:172
void set_bend_ms(double ms)
Definition tom.hpp:134
OutputStage & output()
Definition tom.hpp:202
Wave
Body waveform.
Definition tom.hpp:65
@ sine
Definition tom.hpp:65
@ triangle
Definition tom.hpp:65
TomVoice()
Definition tom.hpp:114
int latency_samples() const noexcept override
Fixed host-rate delay introduced by this voice's selected output quality.
Definition tom.hpp:205
bool on_is_active() const override
Definition tom.hpp:276
void on_reset() override
Clears every piece of state the voice carries, so is_active() becomes false and the next render start...
Definition tom.hpp:228
void set_decay_ms(double ms)
How long the note rings, as a T60. Unrelated to the bend.
Definition tom.hpp:137
static constexpr std::array< PresetData, 8 > presets
Original Pulp-authored voicings of this one SDS-V-family topology.
Definition tom.hpp:95
void render_add(float *out, int num_samples) override
Adds the voice's output into out. Must add, never assign.
Definition tom.hpp:281
void set_wave(Wave wave)
Definition tom.hpp:139
void set_bend_octaves(double octaves)
Depth of the downward dive in octaves, and how quickly it lands.
Definition tom.hpp:133
LofiChain & noise_lofi()
Definition tom.hpp:199
void apply_preset(Preset preset)
Definition tom.hpp:175
OutputStage * output_stage() noexcept override
The terminal saturation and degradation stage, at the generic voice boundary.
Definition tom.hpp:204
void set_output_oversampling(OutputOversampling factor) override
Definition tom.hpp:211
void set_noise_color(NoiseColor color)
Definition tom.hpp:151
void set_click_decay_ms(double ms)
Definition tom.hpp:173
void on_note_on(float velocity) override
Starts a hit at the given velocity, already clamped to [0, 1].
Definition tom.hpp:246
LofiChain & body_lofi()
Independent degradation for the two halves of the drum.
Definition tom.hpp:197
const OutputStage & output() const
Definition tom.hpp:203
Preset
Definition tom.hpp:67
@ mid_tom
Definition tom.hpp:70
@ generic_tom
Definition tom.hpp:68
@ hi_tom
Definition tom.hpp:71
@ snary
Definition tom.hpp:73
@ zap
Definition tom.hpp:74
@ cosmic
Definition tom.hpp:75
@ low_tom
Definition tom.hpp:69
@ bass
Definition tom.hpp:72
LadderMathProfile
The noise ladder's saturator, chosen per voice.
Definition tom.hpp:56
@ realtime_efficient
Definition tom.hpp:58
@ reference
Definition tom.hpp:57
bool is_active() const
Whether the voice still has something to render.
Definition voice.hpp:97
double sample_rate() const
Definition voice.hpp:105
void set_velocity_response(const VelocityResponse &r)
Definition voice.hpp:129
float velocity() const
Definition voice.hpp:104
const VelocityResponse & velocity_response() const
Definition voice.hpp:130
OutputOversampling
Realtime quality choices for the shared drum output nonlinearity.
Definition output_stage.hpp:20
OutputStageT< float > OutputStage
Definition output_stage.hpp:384
LofiChainT< float > LofiChain
Definition lofi_chain.hpp:328
TptFilterT< float > TptFilter
Definition tpt_filter.hpp:172
LadderFilterT< float > LadderFilter
Definition ladder_filter.hpp:127
@ i
Definition formant_filter_bank.hpp:20
NoiseColor
Spectral tilt of a NoiseSourceT, named by the usual colour convention.
Definition noise_source.hpp:17
DecayEnvelopeT< double > DecayEnvelope64
Definition decay_envelope.hpp:201
NoiseSourceT< float > NoiseSource
Definition noise_source.hpp:279
double noise_resonance
Definition tom.hpp:88
double bend_octaves
Definition tom.hpp:82
double decay_ms
Definition tom.hpp:84
double tune_hz
Definition tom.hpp:81
double click_level
Definition tom.hpp:89
double bend_ms
Definition tom.hpp:83
double noise_cutoff_hz
Definition tom.hpp:87
std::string_view name
Definition tom.hpp:80
Preset id
Definition tom.hpp:79
Wave wave
Definition tom.hpp:85
double noise_balance
Definition tom.hpp:86
How hard a hit changes the sound, beyond changing how loud it is.
Definition velocity.hpp:33
First-order topology-preserving transform (TPT) filter.