Vital
Loading...
Searching...
No Matches
dirty_filter.cpp
Go to the documentation of this file.
1#include "dirty_filter.h"
2#include "futils.h"
3
4namespace vital {
5
10 hardReset();
11 }
12
17 void DirtyFilter::reset(poly_mask reset_mask) {
18 pre_stage1_.reset(reset_mask);
19 pre_stage2_.reset(reset_mask);
20 stage1_.reset(reset_mask);
21 stage2_.reset(reset_mask);
22 stage3_.reset(reset_mask);
23 stage4_.reset(reset_mask);
24 }
25
34 coefficient_ = 0.1f;
35 resonance_ = 0.0f;
36 drive_ = 0.0f;
37 drive_boost_ = 0.0f;
38 drive_blend_ = 0.0f;
39 drive_mult_ = 0.0f;
40 low_pass_amount_ = 0.0f;
41 band_pass_amount_ = 0.0f;
42 high_pass_amount_ = 0.0f;
43 }
44
52 void DirtyFilter::process(int num_samples) {
54
55 // Cache current parameter values
56 poly_float current_resonance = resonance_;
57 poly_float current_drive = drive_;
58 poly_float current_drive_boost = drive_boost_;
59 poly_float current_drive_blend = drive_blend_;
60 poly_float current_drive_mult = drive_mult_;
61 poly_float current_low = low_pass_amount_;
62 poly_float current_band = band_pass_amount_;
63 poly_float current_high = high_pass_amount_;
64
65 // Load user settings and setup the filter
68
69 // Check for voice-specific resets
70 poly_mask reset_mask = getResetMask(kReset);
71 if (reset_mask.anyMask()) {
72 reset(reset_mask);
73
74 // Reload parameters for those voices
75 current_resonance = utils::maskLoad(current_resonance, resonance_, reset_mask);
76 current_drive = utils::maskLoad(current_drive, drive_, reset_mask);
77 current_drive_boost = utils::maskLoad(current_drive_boost, drive_boost_, reset_mask);
78 current_drive_blend = utils::maskLoad(current_drive_blend, drive_blend_, reset_mask);
79 current_drive_mult = utils::maskLoad(current_drive_mult, drive_mult_, reset_mask);
80 current_low = utils::maskLoad(current_low, low_pass_amount_, reset_mask);
81 current_band = utils::maskLoad(current_band, band_pass_amount_, reset_mask);
82 current_high = utils::maskLoad(current_high, high_pass_amount_, reset_mask);
83 }
84
85 // Dispatch processing based on the filter style
86 if (filter_state_.style == k12Db) {
87 process12(num_samples,
88 current_resonance,
89 current_drive,
90 current_drive_boost,
91 current_drive_blend,
92 current_low,
93 current_band,
94 current_high);
95 }
97 processDual(num_samples,
98 current_resonance,
99 current_drive,
100 current_drive_boost,
101 current_drive_blend,
102 current_drive_mult,
103 current_low,
104 current_high);
105 }
106 else {
107 process24(num_samples,
108 current_resonance,
109 current_drive,
110 current_drive_boost,
111 current_drive_blend,
112 current_low,
113 current_band,
114 current_high);
115 }
116 }
117
129 void DirtyFilter::process12(int num_samples,
130 poly_float current_resonance,
131 poly_float current_drive,
132 poly_float current_drive_boost,
133 poly_float current_drive_blend,
134 poly_float current_low,
135 poly_float current_band,
136 poly_float current_high) {
137 const poly_float* audio_in = input(kAudio)->source->buffer;
138 poly_float* audio_out = output()->buffer;
139
140 // Calculate parameter smoothing increments
141 mono_float tick_increment = 1.0f / num_samples;
142 poly_float delta_resonance = (resonance_ - current_resonance) * tick_increment;
143 poly_float delta_drive = (drive_ - current_drive) * tick_increment;
144 poly_float delta_drive_boost = (drive_boost_ - current_drive_boost) * tick_increment;
145 poly_float delta_drive_blend = (drive_blend_ - current_drive_blend) * tick_increment;
146 poly_float delta_low = (low_pass_amount_ - current_low) * tick_increment;
147 poly_float delta_band = (band_pass_amount_ - current_band) * tick_increment;
148 poly_float delta_high = (high_pass_amount_ - current_high) * tick_increment;
149
150 // Retrieve coefficient lookup and MIDI-based cutoff data
151 const CoefficientLookup* coefficient_lookup = getCoefficientLookup();
152 const poly_float* midi_cutoff_buffer = filter_state_.midi_cutoff_buffer;
153 poly_float base_midi = midi_cutoff_buffer[num_samples - 1];
154 poly_float base_frequency =
155 utils::midiNoteToFrequency(base_midi) * (1.0f / getSampleRate());
156
157 // Process each sample
158 for (int i = 0; i < num_samples; ++i) {
159 current_drive_boost += delta_drive_boost;
160 current_resonance += delta_resonance;
161
162 // Compute dynamic cutoff frequency
163 poly_float midi_delta = midi_cutoff_buffer[i] - base_midi;
164 poly_float frequency =
165 utils::min(base_frequency * futils::midiOffsetToRatio(midi_delta), 1.0f);
166 poly_float coefficient = coefficient_lookup->cubicLookup(frequency);
167
168 // Compute resonance
169 poly_float coefficient_squared = coefficient * coefficient;
170 poly_float coefficient2 = coefficient * 2.0f;
171 poly_float resonance_in = utils::clamp(tuneResonance(current_resonance, coefficient2), 0.0f, 1.0f);
172 poly_float resonance = utils::interpolate(kMinResonance, kMaxResonance, resonance_in) + current_drive_boost;
173 poly_float resonance_squared = resonance * resonance;
174
175 // Set up normalizing factors
176 poly_float normalizer = poly_float(kSaturationBoost) / (resonance_squared + 1.0f);
177 poly_float compute = -resonance * (coefficient - coefficient_squared) + 1.0f;
178 poly_float feed_mult = poly_float(1.0f) / (compute * (coefficient + 1.0f));
179
180 // Smooth drive parameter
181 current_drive += delta_drive;
182 current_drive_blend += delta_drive_blend;
183 poly_float scaled_drive = utils::max(poly_float(kMinDrive), current_drive)
184 / (resonance_squared * 0.5f + 1.0f);
185 poly_float drive = utils::interpolate(current_drive, scaled_drive, current_drive_blend);
186
187 // Smooth pass amounts
188 current_low += delta_low;
189 current_band += delta_band;
190 current_high += delta_high;
191
192 // Process single sample
193 audio_out[i] = tick(audio_in[i],
194 coefficient,
195 resonance,
196 drive,
197 feed_mult,
198 normalizer,
199 current_low,
200 current_band,
201 current_high);
202 }
203 }
204
216 void DirtyFilter::process24(int num_samples,
217 poly_float current_resonance,
218 poly_float current_drive,
219 poly_float current_drive_boost,
220 poly_float current_drive_blend,
221 poly_float current_low,
222 poly_float current_band,
223 poly_float current_high) {
224 const poly_float* audio_in = input(kAudio)->source->buffer;
225 poly_float* audio_out = output()->buffer;
226
227 // Calculate parameter smoothing increments
228 mono_float tick_increment = 1.0f / num_samples;
229 poly_float delta_resonance = (resonance_ - current_resonance) * tick_increment;
230 poly_float delta_drive = (drive_ - current_drive) * tick_increment;
231 poly_float delta_drive_boost = (drive_boost_ - current_drive_boost) * tick_increment;
232 poly_float delta_drive_blend = (drive_blend_ - current_drive_blend) * tick_increment;
233 poly_float delta_low = (low_pass_amount_ - current_low) * tick_increment;
234 poly_float delta_band = (band_pass_amount_ - current_band) * tick_increment;
235 poly_float delta_high = (high_pass_amount_ - current_high) * tick_increment;
236
237 // Retrieve coefficient lookup and MIDI-based cutoff data
238 const CoefficientLookup* coefficient_lookup = getCoefficientLookup();
239 const poly_float* midi_cutoff_buffer = filter_state_.midi_cutoff_buffer;
240 poly_float base_midi = midi_cutoff_buffer[num_samples - 1];
241 poly_float base_frequency =
242 utils::midiNoteToFrequency(base_midi) * (1.0f / getSampleRate());
243
244 // Process each sample
245 for (int i = 0; i < num_samples; ++i) {
246 current_drive_boost += delta_drive_boost;
247 current_resonance += delta_resonance;
248
249 // Compute dynamic cutoff frequency
250 poly_float midi_delta = midi_cutoff_buffer[i] - base_midi;
251 poly_float frequency =
252 utils::min(base_frequency * futils::midiOffsetToRatio(midi_delta), 1.0f);
253 poly_float coefficient = coefficient_lookup->cubicLookup(frequency);
254
255 // Compute resonance
256 poly_float coefficient_squared = coefficient * coefficient;
257 poly_float coefficient2 = coefficient * 2.0f;
258 poly_float resonance_in = utils::clamp(tuneResonance(current_resonance, coefficient2), 0.0f, 1.0f);
259 poly_float resonance = utils::interpolate(kMinResonance, kMaxResonance, resonance_in) + current_drive_boost;
260 poly_float resonance_squared = resonance * resonance;
261
262 // Compute normalization factors
263 poly_float normalizer = poly_float(kSaturationBoost) / (resonance_squared + 1.0f);
264 poly_float coefficient_diff = coefficient_squared - coefficient;
265 poly_float compute = resonance * coefficient_diff + 1.0f;
266 poly_float feed_mult = poly_float(1.0f) / (compute * (coefficient + 1.0f));
267 poly_float pre_feedback = coefficient2 - coefficient_squared - 1.0f;
268 poly_float pre_normalizer = poly_float(1.0f) / (coefficient_diff * kFlatResonance + 1.0f);
269
270 // Smooth drive parameter
271 current_drive += delta_drive;
272 current_drive_blend += delta_drive_blend;
273 poly_float scaled_drive = utils::max(poly_float(kMinDrive), current_drive)
274 / (resonance_squared * 0.5f + 1.0f);
275 poly_float drive = utils::interpolate(current_drive, scaled_drive, current_drive_blend);
276
277 // Smooth pass amounts
278 current_low += delta_low;
279 current_band += delta_band;
280 current_high += delta_high;
281
282 // Tick through the 24 dB filter process
283 audio_out[i] = tick24(audio_in[i],
284 coefficient,
285 resonance,
286 drive,
287 feed_mult,
288 normalizer,
289 pre_feedback,
290 pre_normalizer,
291 current_low,
292 current_band,
293 current_high);
294 }
295 }
296
308 void DirtyFilter::processDual(int num_samples,
309 poly_float current_resonance,
310 poly_float current_drive,
311 poly_float current_drive_boost,
312 poly_float current_drive_blend,
313 poly_float current_drive_mult,
314 poly_float current_low,
315 poly_float current_high) {
316 const poly_float* audio_in = input(kAudio)->source->buffer;
317 poly_float* audio_out = output()->buffer;
318
319 // Calculate parameter smoothing increments
320 mono_float tick_increment = 1.0f / num_samples;
321 poly_float delta_resonance = (resonance_ - current_resonance) * tick_increment;
322 poly_float delta_drive = (drive_ - current_drive) * tick_increment;
323 poly_float delta_drive_boost = (drive_boost_ - current_drive_boost) * tick_increment;
324 poly_float delta_drive_blend = (drive_blend_ - current_drive_blend) * tick_increment;
325 poly_float delta_drive_mult = (drive_mult_ - current_drive_mult) * tick_increment;
326 poly_float delta_low = (low_pass_amount_ - current_low) * tick_increment;
327 poly_float delta_high = (high_pass_amount_ - current_high) * tick_increment;
328
329 // Retrieve coefficient lookup and MIDI-based cutoff data
330 const CoefficientLookup* coefficient_lookup = getCoefficientLookup();
331 const poly_float* midi_cutoff_buffer = filter_state_.midi_cutoff_buffer;
332 poly_float base_midi = midi_cutoff_buffer[num_samples - 1];
333 poly_float base_frequency =
334 utils::midiNoteToFrequency(base_midi) * (1.0f / getSampleRate());
335
336 // Process each sample
337 for (int i = 0; i < num_samples; ++i) {
338 current_drive_boost += delta_drive_boost;
339 current_resonance += delta_resonance;
340
341 // Compute dynamic cutoff frequency
342 poly_float midi_delta = midi_cutoff_buffer[i] - base_midi;
343 poly_float frequency =
344 utils::min(base_frequency * futils::midiOffsetToRatio(midi_delta), 1.0f);
345 poly_float coefficient = coefficient_lookup->cubicLookup(frequency);
346
347 // Compute resonance
348 poly_float coefficient_squared = coefficient * coefficient;
349 poly_float coefficient2 = coefficient * 2.0f;
350 poly_float resonance_in = utils::clamp(tuneResonance(current_resonance, coefficient2), 0.0f, 1.0f);
351 poly_float resonance = utils::interpolate(kMinResonance, kMaxResonance, resonance_in) + current_drive_boost;
352 poly_float resonance_squared = resonance * resonance;
353
354 // Normalization factors
355 poly_float normalizer = poly_float(kSaturationBoost) / (resonance_squared + 1.0f);
356 poly_float coefficient_diff = coefficient_squared - coefficient;
357 poly_float compute = resonance * coefficient_diff + 1.0f;
358 poly_float feed_mult = poly_float(1.0f) / (compute * (coefficient + 1.0f));
359 poly_float pre_feedback = coefficient2 - coefficient_squared - 1.0f;
360 poly_float pre_normalizer = poly_float(1.0f) / (coefficient_diff * kFlatResonance + 1.0f);
361
362 // Smooth drive parameters
363 current_drive += delta_drive;
364 current_drive_blend += delta_drive_blend;
365 current_drive_mult += delta_drive_mult;
366 poly_float scaled_drive = utils::max(poly_float(kMinDrive), current_drive)
367 / (resonance_squared * 0.5f + 1.0f);
368 poly_float drive = utils::interpolate(current_drive, scaled_drive * current_drive_mult, current_drive_blend);
369
370 // Smooth pass amounts
371 current_low += delta_low;
372 current_high += delta_high;
373
374 // Tick through the dual filter process
375 audio_out[i] = tickDual(audio_in[i],
376 coefficient,
377 resonance,
378 drive,
379 feed_mult,
380 normalizer,
381 pre_feedback,
382 pre_normalizer,
383 current_low,
384 current_high);
385 }
386 }
387
396 void DirtyFilter::setupFilter(const FilterState& filter_state) {
397 static constexpr float kMaxMidi = 150.0f;
398 // Clamp cutoff to a maximum MIDI note
399 poly_float cutoff = utils::clamp(filter_state.midi_cutoff, 0.0f, kMaxMidi);
400 // Convert to frequency, then normalize by sample rate
401 poly_float base_frequency = utils::midiNoteToFrequency(cutoff) * (1.0f / getSampleRate());
402 coefficient_ = getCoefficientLookup()->cubicLookup(base_frequency);
403
404 // Compute base resonance and drive
405 resonance_ = utils::sqrt(utils::clamp(filter_state.resonance_percent, 0.0f, 1.0f));
406 drive_ = (filter_state.drive - 1.0f) * 2.0f + 1.0f;
407 drive_boost_ = filter_state.drive_percent * kDriveResonanceBoost;
408
409 // Default drive blending and multiplier
410 drive_blend_ = 1.0f;
411 drive_mult_ = 1.0f;
412
413 // Set up blend for pass-band amounts
414 poly_float blend = utils::clamp(filter_state.pass_blend - 1.0f, -1.0f, 1.0f);
415 if (filter_state.style == kDualNotchBand) {
416 // Specialized blending for dual-notch style
417 poly_float t = blend * 0.5f + 0.5f;
418 drive_blend_ = poly_float::min(-blend + 1.0f, 1.0f);
419 drive_mult_ = -t + 2.0f;
420
421 low_pass_amount_ = t;
422 band_pass_amount_ = 0.0f;
423 high_pass_amount_ = 1.0f;
424 }
425 else if (filter_state.style == kNotchPassSwap) {
426 // Another specialized blending mode
427 drive_blend_ = poly_float::abs(blend);
428 low_pass_amount_ = utils::min(-blend + 1.0f, 1.0f);
429 band_pass_amount_ = 0.0f;
430 high_pass_amount_ = utils::min(blend + 1.0f, 1.0f);
431 }
432 else if (filter_state.style == kBandPeakNotch) {
433 // Band/Peak/Notch style filter blending
434 drive_blend_ = poly_float::min(-blend + 1.0f, 1.0f);
435 poly_float drive_inv_t = -drive_blend_ + 1.0f;
436 poly_float mult = utils::sqrt((drive_inv_t * drive_inv_t) * 0.5f + 0.5f);
437 poly_float peak_band_value = -utils::max(-blend, 0.0f);
438 low_pass_amount_ = mult * (peak_band_value + 1.0f);
439 band_pass_amount_ = mult * (peak_band_value - blend + 1.0f) * 2.0f;
440 high_pass_amount_ = low_pass_amount_;
441 }
442 else {
443 // Default or standard blending
444 band_pass_amount_ = utils::sqrt(-blend * blend + 1.0f);
445 poly_mask blend_mask = poly_float::lessThan(blend, 0.0f);
446 low_pass_amount_ = (-blend) & blend_mask;
447 high_pass_amount_ = blend & ~blend_mask;
448 }
449 }
450
467 poly_float coefficient,
469 poly_float drive,
470 poly_float feed_mult,
471 poly_float normalizer,
472 poly_float pre_feedback_mult,
473 poly_float pre_normalizer,
474 poly_float low,
475 poly_float band,
476 poly_float high) {
477 // Pre-stage feedback and processing
478 poly_float mult_stage2 = -coefficient + 1.0f;
479 poly_float feedback = pre_feedback_mult * pre_stage1_.getNextSatState()
480 + mult_stage2 * pre_stage2_.getNextSatState();
481
482 feedback *= kFlatResonance;
483 poly_float stage1_input = (audio_in - feedback) * pre_normalizer;
484
485 // Two one-pole stages for preliminary filtering
486 poly_float stage1_out = pre_stage1_.tickBasic(stage1_input, coefficient);
487 poly_float stage2_out = pre_stage2_.tickBasic(stage1_out, coefficient);
488
489 poly_float band_pass = stage1_out - stage2_out;
490 poly_float high_pass = stage1_input - stage1_out - band_pass;
491 // Mix the pre-output based on user’s low/band/high settings
492 poly_float pre_out = band * band_pass + high * high_pass + low * stage2_out;
493
494 // Process using the main shared function
495 return tick(pre_out, coefficient, resonance, drive, feed_mult, normalizer, low, band, high);
496 }
497
513 poly_float coefficient,
515 poly_float drive,
516 poly_float feed_mult,
517 poly_float normalizer,
518 poly_float pre_feedback_mult,
519 poly_float pre_normalizer,
520 poly_float low,
521 poly_float high) {
522 // Similar pre-stage approach as 24 dB
523 poly_float mult_stage2 = -coefficient + 1.0f;
524 poly_float feedback = pre_feedback_mult * pre_stage1_.getNextSatState()
525 + mult_stage2 * pre_stage2_.getNextSatState();
526
527 feedback *= kFlatResonance;
528 poly_float stage1_input = (audio_in - feedback) * pre_normalizer;
529
530 // Pre-stage filtering
531 poly_float stage1_out = pre_stage1_.tickBasic(stage1_input, coefficient);
532 poly_float stage2_out = pre_stage2_.tickBasic(stage1_out, coefficient);
533
534 poly_float band_pass = stage1_out - stage2_out;
535 poly_float high_pass = stage1_input - stage1_out - band_pass;
536
537 // For the dual style, mix differently
538 poly_float pre_out = low * high_pass + high * stage2_out;
539
540 // Pass on to main tick
541 return tick(pre_out, coefficient, resonance, drive, feed_mult, normalizer, low, 0.0f, high);
542 }
543
558 poly_float coefficient,
560 poly_float drive,
561 poly_float feed_mult,
562 poly_float normalizer,
563 poly_float low,
564 poly_float band,
565 poly_float high) {
566 // Normalize and pass through first stages
567 poly_float stage1_in = normalizer * audio_in;
568 poly_float stage1_out = stage1_.tickBasic(stage1_in, coefficient);
569 poly_float stage2_out = stage2_.tickBasic(stage1_out, coefficient);
570
571 // Compute band-pass and high-pass from the two-pole difference
572 poly_float band_pass = stage1_out - stage2_out;
573 poly_float high_pass = stage1_in - stage1_out - band_pass;
574 // Combine outputs according to user-defined pass amounts
575 poly_float pass_output =
576 utils::mulAdd(utils::mulAdd(low * stage2_out, band, band_pass), high, high_pass);
577
578 // Feedback from final stage
579 poly_float feedback = stage4_.getNextSatState() +
580 utils::mulAdd(pass_output, coefficient, pass_output - stage3_.getNextSatState());
581
582 // Drive plus resonance feedback
583 poly_float loop_input =
584 futils::tanh(utils::mulAdd(drive * pass_output, resonance, feed_mult * feedback));
585
586 // Last two stages with quickTanh saturations
587 poly_float stage3_out = stage3_.tick(loop_input, coefficient);
588
589 poly_float stage4_in = loop_input - stage3_out;
590 stage4_.tick(stage4_in, coefficient);
591
592 // Return processed audio, scaled back by the saturation factor
593 return loop_input * (1.0f / kSaturationBoost);
594 }
595
596} // namespace vital
A nonlinear filter that produces a "dirty" and saturated sound, ideal for adding character to the sig...
Definition dirty_filter.h:30
void process24(int num_samples, poly_float current_resonance, poly_float current_drive, poly_float current_drive_boost, poly_float current_drive_blend, poly_float current_low, poly_float current_band, poly_float current_high)
Processes the filter in 24 dB/oct mode.
Definition dirty_filter.cpp:216
force_inline poly_float tick(poly_float audio_in, poly_float coefficient, poly_float resonance, poly_float drive, poly_float feed_mult, poly_float normalizer, poly_float low, poly_float band, poly_float high)
Processes a single sample in 12 dB mode or as a part of other modes' chains.
Definition dirty_filter.cpp:557
static constexpr mono_float kMaxResonance
Maximum resonance factor.
Definition dirty_filter.h:35
force_inline poly_float tuneResonance(poly_float resonance, poly_float coefficient)
Tunes the resonance based on the filter coefficient.
Definition dirty_filter.h:58
static constexpr mono_float kSaturationBoost
Scaling factor applied during saturation.
Definition dirty_filter.h:37
void reset(poly_mask reset_mask) override
Resets the filter state for specific voices.
Definition dirty_filter.cpp:17
static constexpr mono_float kMinDrive
Minimum drive value.
Definition dirty_filter.h:46
static constexpr mono_float kMinResonance
Minimum resonance factor.
Definition dirty_filter.h:33
void setupFilter(const FilterState &filter_state) override
Sets up the filter's internal state (cutoff, resonance, drive, blend) from the given FilterState.
Definition dirty_filter.cpp:396
static constexpr mono_float kDriveResonanceBoost
Additional resonance boost when drive is applied.
Definition dirty_filter.h:41
static constexpr mono_float kFlatResonance
Flat resonance factor used internally.
Definition dirty_filter.h:49
force_inline poly_float tickDual(poly_float audio_in, poly_float coefficient, poly_float resonance, poly_float drive, poly_float feed_mult, poly_float normalizer, poly_float pre_feedback_mult, poly_float pre_normalizer, poly_float low, poly_float high)
Processes a single sample in dual mode.
Definition dirty_filter.cpp:512
void processDual(int num_samples, poly_float current_resonance, poly_float current_drive, poly_float current_drive_boost, poly_float current_drive_blend, poly_float current_drive_mult, poly_float current_low, poly_float current_high)
Processes the filter in dual (e.g., dual-notch band) mode.
Definition dirty_filter.cpp:308
force_inline poly_float tick24(poly_float audio_in, poly_float coefficient, poly_float resonance, poly_float drive, poly_float feed_mult, poly_float normalizer, poly_float pre_feedback_mult, poly_float pre_normalizer, poly_float low, poly_float band, poly_float high)
Processes a single sample in 24 dB mode with nonlinearities and drive.
Definition dirty_filter.cpp:466
virtual void process(int num_samples) override
Processes a block of audio samples.
Definition dirty_filter.cpp:52
void hardReset() override
Hard resets the filter, clearing all internal states.
Definition dirty_filter.cpp:32
void process12(int num_samples, poly_float current_resonance, poly_float current_drive, poly_float current_drive_boost, poly_float current_drive_blend, poly_float current_low, poly_float current_band, poly_float current_high)
Processes the filter in 12 dB/oct mode.
Definition dirty_filter.cpp:129
DirtyFilter()
Constructs a DirtyFilter with default parameters.
Definition dirty_filter.cpp:9
A one-dimensional lookup table for a given function with a specified resolution.
Definition lookup_table.h:31
force_inline poly_float cubicLookup(poly_float value) const
Performs a cubic interpolation lookup on the precomputed data.
Definition lookup_table.h:61
force_inline void reset(poly_mask reset_mask)
Resets the filter state for the voices indicated by a mask.
Definition one_pole_filter.h:36
force_inline poly_float getNextSatState()
Gets the next saturated filter state value.
Definition one_pole_filter.h:113
force_inline poly_float tick(poly_float audio_in, poly_float coefficient)
Processes a single sample, applying the saturation function at each step.
Definition one_pole_filter.h:73
force_inline poly_float tickBasic(poly_float audio_in, poly_float coefficient)
Processes a single sample in a basic (non-saturating) manner.
Definition one_pole_filter.h:56
Base class for all signal-processing units in Vital.
Definition processor.h:212
force_inline Input * input(unsigned int index=0) const
Retrieves the Input pointer at a given index.
Definition processor.h:587
force_inline int getSampleRate() const
Retrieves the current (effective) sample rate.
Definition processor.h:326
bool inputMatchesBufferSize(int input=0)
Checks whether the buffer size of a particular input matches the size needed by this Processor.
Definition processor.cpp:42
force_inline poly_mask getResetMask(int input_index) const
Retrieves a mask indicating which voices triggered a note-on event. Compares the input's trigger_valu...
Definition processor.h:360
force_inline Output * output(unsigned int index=0) const
Retrieves the Output pointer at a given index.
Definition processor.h:616
Holds the parameters necessary to configure a SynthFilter at runtime.
Definition synth_filter.h:92
void loadSettings(Processor *processor)
Loads state from a Processor’s input signals (MIDI cutoff, drive, style, etc.).
Definition synth_filter.cpp:30
const poly_float * midi_cutoff_buffer
Pointer to the buffer storing per-sample MIDI cutoff.
Definition synth_filter.h:111
poly_float drive_percent
Normalized drive parameter in [0..1].
Definition synth_filter.h:114
poly_float pass_blend
Blend parameter in [0..2], controlling pass type.
Definition synth_filter.h:117
poly_float drive
Drive in linear magnitude.
Definition synth_filter.h:113
int style
Filter style enum (e.g., k12Db, k24Db)
Definition synth_filter.h:116
poly_float midi_cutoff
MIDI note-based cutoff value.
Definition synth_filter.h:110
poly_float resonance_percent
Resonance parameter in [0..1].
Definition synth_filter.h:112
@ kReset
Reset signal.
Definition synth_filter.h:56
@ kAudio
Audio input index.
Definition synth_filter.h:55
FilterState filter_state_
Internal storage of the most recent FilterState, used by derived filters.
Definition synth_filter.h:151
static const CoefficientLookup * getCoefficientLookup()
Retrieves a pointer to the static coefficient lookup table.
Definition synth_filter.h:48
@ kBandPeakNotch
Definition synth_filter.h:79
@ kNotchPassSwap
Definition synth_filter.h:77
@ k12Db
Definition synth_filter.h:75
@ kDualNotchBand
Definition synth_filter.h:78
#define VITAL_ASSERT(x)
Definition common.h:11
#define force_inline
Definition common.h:23
cr::Value resonance
Resonance factor for this formant.
Definition formant_filter.cpp:18
Contains faster but less accurate versions of utility math functions, such as exponential,...
const poly_mask kFullMask
A mask covering all lanes of a poly_float vector.
Definition synth_constants.h:257
force_inline poly_float midiOffsetToRatio(poly_float note_offset)
Converts a MIDI note offset to a frequency ratio.
Definition futils.h:184
force_inline poly_float tanh(poly_float value)
Approximates tanh function using a complex polynomial.
Definition futils.h:347
force_inline poly_float clamp(poly_float value, mono_float min, mono_float max)
Clamps each lane of a vector to [min, max].
Definition poly_utils.h:306
force_inline poly_float mulAdd(poly_float a, poly_float b, poly_float c)
Performs a fused multiply-add on SIMD data: (a * b) + c.
Definition poly_utils.h:61
force_inline poly_float min(poly_float left, poly_float right)
Returns the minimum of two poly_floats lane-by-lane.
Definition poly_utils.h:334
force_inline poly_float max(poly_float left, poly_float right)
Returns the maximum of two poly_floats lane-by-lane.
Definition poly_utils.h:327
force_inline poly_float maskLoad(poly_float zero_value, poly_float one_value, poly_mask reset_mask)
Selects between two values (zero_value or one_value) based on a mask in each lane.
Definition poly_utils.h:351
force_inline poly_float midiNoteToFrequency(poly_float value)
Converts a MIDI note to a frequency (vectorized).
Definition poly_utils.h:123
force_inline poly_float sqrt(poly_float value)
Computes the square root of each element in a poly_float.
Definition poly_utils.h:169
force_inline poly_float interpolate(poly_float from, poly_float to, mono_float t)
Performs a linear interpolation between two poly_floats using a scalar t in [0..1].
Definition poly_utils.h:182
Contains classes and functions used within the Vital synthesizer framework.
float mono_float
Definition common.h:33
const Output * source
The output from which this input reads samples.
Definition processor.h:134
poly_float * buffer
Pointer to the output buffer.
Definition processor.h:110
Represents a vector of floating-point values using SIMD instructions.
Definition poly_values.h:600
static force_inline poly_mask vector_call lessThan(poly_float one, poly_float two)
Definition poly_values.h:1105
static force_inline simd_type vector_call min(simd_type one, simd_type two)
Returns the element-wise minimum of two SIMD float registers.
Definition poly_values.h:920
static force_inline simd_type vector_call abs(simd_type value)
Computes the absolute value of each element in the SIMD float register.
Definition poly_values.h:935
Represents a vector of integer values using SIMD instructions.
Definition poly_values.h:56
static force_inline uint32_t vector_call anyMask(simd_type value)
Returns a bitmask that indicates which bytes/elements in the register are non-zero.
Definition poly_values.h:352