LCOV - code coverage report
Current view: top level - src/audio/effects/delay_reverb - delay.cpp (source / functions) Coverage Total Hit
Test: merged.info Lines: 95.6 % 68 65
Test Date: 2026-06-07 15:51:50 Functions: 100.0 % 5 5

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

Generated by: LCOV version 2.0-1