Line data Source code
1 : #include "audio/effects/distortion/distortion.h"
2 :
3 : #include "audio/effects/core/effect_factory.h"
4 :
5 : namespace Amplitron {
6 :
7 2 : static EffectRegistrar<Distortion> reg("Distortion");
8 :
9 120 : Distortion::Distortion() {
10 270 : params_ = {
11 90 : {"Drive", 2.0f, 1.0f, 20.0f, 2.0f, "x",
12 30 : "Amount of input gain slamming into the hard clippers. Creates aggressive, dense harmonic "
13 : "distortion."},
14 30 : {"Tone", 0.6f, 0.0f, 1.0f, 0.6f, "",
15 30 : "Low-pass filter cutoff to tame the fizzy high-end generated by hard clipping."},
16 30 : {"Level", 0.5f, 0.0f, 1.0f, 0.5f, "",
17 30 : "Master output volume of the pedal. Useful to match volume with the pedal bypassed."},
18 270 : };
19 120 : drive_smoothed_ = params_[0].value;
20 90 : tone_smoothed_ = params_[1].value;
21 90 : level_smoothed_ = params_[2].value;
22 210 : }
23 :
24 60 : void Distortion::process(float* buffer, int num_samples) {
25 60 : if (!enabled_) return;
26 :
27 24 : const float mix = mix_.load(std::memory_order_relaxed);
28 :
29 : // One-pole smoothing: advance states toward raw param targets each block
30 24 : const float alpha = 1.0f - std::exp(-1.0f / (sample_rate_ * 0.010f)); // 10 ms
31 24 : drive_smoothed_ += alpha * (params_[0].value - drive_smoothed_);
32 24 : tone_smoothed_ += alpha * (params_[1].value - tone_smoothed_);
33 24 : level_smoothed_ += alpha * (params_[2].value - level_smoothed_);
34 :
35 24 : float drive = drive_smoothed_;
36 24 : float tone = tone_smoothed_;
37 24 : float level = level_smoothed_;
38 :
39 : // Tone control: simple one-pole LP filter coefficient
40 24 : float lp_coeff = 0.1f + tone * 0.8f;
41 :
42 6168 : for (int i = 0; i < num_samples; ++i) {
43 6144 : float dry = buffer[i];
44 :
45 : // Apply drive gain
46 6144 : float x = buffer[i] * drive;
47 :
48 : // Soft path (tube-like via tanh + soft clip)
49 6144 : float x_soft = soft_clip(fast_tanh(x) * 1.5f);
50 :
51 : // Hard path (hard clip at unity)
52 6144 : float x_hard = hard_clip(x, 1.0f);
53 :
54 : // Blend: more drive → more hard clipping
55 4096 : float hard_amount =
56 6144 : (drive - params_[0].min_val) / (params_[0].max_val - params_[0].min_val);
57 6144 : x = x_soft * (1.0f - hard_amount) + x_hard * hard_amount;
58 :
59 : // Tone filter (one-pole LP)
60 6144 : x = tone_lp_.lp(x, lp_coeff);
61 :
62 : // Output level
63 6144 : x *= level;
64 :
65 : // Wet/dry mix
66 6144 : buffer[i] = dry * (1.0f - mix) + x * mix;
67 2048 : }
68 20 : }
69 :
70 90 : void Distortion::reset() { tone_lp_.reset(); }
71 :
72 : } // namespace Amplitron
|