LCOV - code coverage report
Current view: top level - src/audio/effects/utility - tuner.h (source / functions) Coverage Total Hit
Test: merged.info Lines: 75.0 % 4 3
Test Date: 2026-06-07 15:51:50 Functions: 75.0 % 4 3

            Line data    Source code
       1              : #pragma once
       2              : 
       3              : // Chromatic tuner based on pitch detection from the input signal.
       4              : // Uses the YIN difference d(tau)=sum_j(x[j]-x[j+tau])^2 and cumulative mean
       5              : // normalized difference to estimate period tau; frequency is Fs/tau and cents
       6              : // error is 1200*log2(freq / nearest_note_freq).
       7              : 
       8              : #include <atomic>
       9              : #include <vector>
      10              : 
      11              : #include "audio/effects/core/effect.h"
      12              : 
      13              : namespace Amplitron {
      14              : 
      15              : class TunerPedal : public Effect {
      16              :    public:
      17              :     TunerPedal();
      18              :     void process(float* buffer, int num_samples) override;
      19              :     void set_sample_rate(int sample_rate) override;
      20              :     void reset() override;
      21           29 :     const char* name() const override { return "Tuner"; }
      22            3 :     const char* type_id() const override { return "Tuner"; }
      23           94 :     std::vector<EffectParam>& params() override { return params_; }
      24            0 :     const std::vector<EffectParam>& params() const override { return params_; }
      25              : 
      26              :     // Tuner detection results (audio thread writes, UI thread reads)
      27              :     std::atomic<float> detected_freq{0.0f};
      28              :     std::atomic<float> detected_cents{0.0f};
      29              :     std::atomic<int> detected_note{-1};  // 0=C, 1=C#, 2=D, ... 11=B
      30              :     std::atomic<int> detected_octave{-1};
      31              :     std::atomic<bool> signal_detected{false};
      32              : 
      33              :     static const char* note_name(int note_index);
      34              : 
      35              :    private:
      36              :     std::vector<EffectParam> params_;
      37              : 
      38              :     // YIN pitch detection buffer
      39              :     // 4096 samples at 48kHz gives ~85ms window, ample headroom for E2 (82.41Hz, period ~582
      40              :     // samples)
      41              :     static constexpr int YIN_BUFFER_SIZE = 4096;
      42              :     std::vector<float> yin_buffer_;
      43              :     int yin_write_pos_ = 0;
      44              :     bool yin_buffer_full_ = false;
      45              : 
      46              :     // YIN internals
      47              :     float yin_detect_pitch(float a4_ref);
      48              :     void freq_to_note(float freq, float a4_ref);
      49              : 
      50              :     // Preallocated work buffers for yin_detect_pitch() (avoids RT heap allocs)
      51              :     std::vector<float> yin_buf_;  // linearized circular buffer (YIN_BUFFER_SIZE)
      52              :     std::vector<float> yin_d_;    // cumulative mean normalized difference (YIN_BUFFER_SIZE/2)
      53              : 
      54              :     // Update rate control (~15 updates/sec)
      55              :     int samples_since_update_ = 0;
      56              :     int update_interval_ = 0;
      57              :     void recalc_update_interval();
      58              : };
      59              : 
      60              : }  // namespace Amplitron
        

Generated by: LCOV version 2.0-1