Line data Source code
1 : #include "audio/effects/delay.h"
2 : #include "audio/effects/effect_factory.h"
3 :
4 : namespace Amplitron {
5 :
6 2 : static EffectRegistrar<Delay> reg("Delay");
7 :
8 164 : Delay::Delay() {
9 451 : params_ = {
10 123 : {"Time", 350.0f, 10.0f, 2000.0f, 350.0f, "ms", "Time interval between each echo. Sets the tempo of the delay repeats."},
11 41 : {"Feedback", 0.4f, 0.0f, 0.95f, 0.4f, "", "Amount of the delayed signal fed back into the input. Higher values create more repeats."},
12 41 : {"Tone", 0.7f, 0.0f, 1.0f, 0.7f, "", "High-frequency damping on the repeats. Lower values create darker, tape-like echoes."},
13 41 : {"Level", 0.5f, 0.0f, 1.0f, 0.5f, "", "Mix volume of the delay repeats added to your dry signal."},
14 451 : };
15 123 : set_sample_rate(DEFAULT_SAMPLE_RATE);
16 246 : }
17 :
18 264 : void Delay::set_sample_rate(int sample_rate) {
19 264 : Effect::set_sample_rate(sample_rate);
20 264 : max_delay_samples_ = static_cast<int>(sample_rate * 2.5f); // max 2.5s
21 264 : delay_buffer_.resize(max_delay_samples_, 0.0f);
22 264 : write_pos_ = 0;
23 264 : }
24 :
25 24 : void Delay::process(float* buffer, int num_samples) {
26 24 : if (!enabled_) return;
27 :
28 24 : const float alpha = 1.0f - std::exp(-1.0f / (sample_rate_ * 0.020f)); // 20 ms
29 24 : smoothed_time_ms_ += alpha * (params_[0].value - smoothed_time_ms_);
30 24 : smoothed_feedback_ += alpha * (params_[1].value - smoothed_feedback_);
31 24 : smoothed_tone_ += alpha * (params_[2].value - smoothed_tone_);
32 24 : smoothed_level_ += alpha * (params_[3].value - smoothed_level_);
33 :
34 24 : float time_ms = smoothed_time_ms_;
35 24 : float feedback = smoothed_feedback_;
36 24 : float tone = smoothed_tone_;
37 24 : float level = smoothed_level_;
38 :
39 24 : int delay_samples = static_cast<int>(time_ms * 0.001f * sample_rate_);
40 24 : delay_samples = std::min(delay_samples, max_delay_samples_ - 1);
41 24 : float lp_coeff = 0.1f + tone * 0.85f;
42 :
43 16920 : for (int i = 0; i < num_samples; ++i) {
44 16896 : float dry = buffer[i];
45 :
46 16896 : int read_pos = write_pos_ - delay_samples;
47 16896 : if (read_pos < 0) read_pos += max_delay_samples_;
48 :
49 16896 : float delayed = delay_buffer_[read_pos];
50 :
51 : // Tone filter on feedback path
52 16896 : float filtered = tone_lp_.lp(delayed, lp_coeff);
53 :
54 : // Write to delay buffer: input + filtered feedback
55 16896 : delay_buffer_[write_pos_] = buffer[i] + filtered * feedback;
56 :
57 16896 : write_pos_++;
58 16896 : if (write_pos_ >= max_delay_samples_) write_pos_ = 0;
59 :
60 16896 : buffer[i] = dry + delayed * level;
61 5632 : }
62 8 : }
63 :
64 144 : void Delay::reset() {
65 144 : std::fill(delay_buffer_.begin(), delay_buffer_.end(), 0.0f);
66 144 : write_pos_ = 0;
67 144 : tone_lp_.reset();
68 144 : }
69 :
70 3 : void Delay::set_transport_state(float bpm){
71 3 : if(bpm <= 0.0f || !std::isfinite(bpm)) return;
72 3 : if(bpm == last_bpm_) return;
73 3 : last_bpm_=bpm;
74 :
75 : //Quarter-note duration
76 3 : float quarter_note_ms = 60000.0f / bpm;
77 : //Check current knob
78 3 : float current_knob_time = params_[0].value;
79 : //Distance to nearest subdivisions
80 3 : float diff_quarter = std::fabs(current_knob_time - quarter_note_ms);
81 3 : float diff_eighth = std::fabs(current_knob_time - (quarter_note_ms * 0.5f));
82 3 : float diff_sixteenth = std::fabs(current_knob_time - (quarter_note_ms * 0.25f));
83 : //Check closest
84 3 : float target_time = quarter_note_ms; //default to 1/4 note
85 3 : if(diff_eighth < diff_quarter && diff_eighth < diff_sixteenth){
86 0 : target_time = quarter_note_ms * 0.5f; // 1/8 note
87 0 : }
88 3 : else if(diff_sixteenth < diff_quarter && diff_sixteenth < diff_eighth){
89 0 : target_time = quarter_note_ms * 0.25f; // 1/16 note
90 0 : }
91 :
92 : //Set knob
93 3 : params_[0].value = clamp(target_time, params_[0].min_val, params_[0].max_val);
94 1 : }
95 :
96 : } // namespace Amplitron
|