#pragma once #include #include #include #include #include "Config.h" struct DetectedNote { float frequency; float magnitude; uint8_t noteNumber; // MIDI note number for easy identification uint32_t startTime; // When the note was first detected uint32_t lastSeenTime; // Last time this note was detected }; class NoteDetector { public: NoteDetector(); void analyzeSamples(const int16_t* samples, size_t sampleCount); const std::vector& getDetectedNotes() const { return detectedNotes; } const double* getSpectrum() const { return vReal; } void beginCalibration(); void endCalibration(); bool isCalibrating() const { return calibrationMode; } // Threshold adjustment methods void adjustThreshold(float delta); float getCurrentThreshold() const { return dynamicThreshold; } private: arduinoFFT FFT; double vReal[Config::FFT_SIZE]; double vImag[Config::FFT_SIZE]; std::vector detectedNotes; std::deque peakMagnitudeHistory; // For calibration bool calibrationMode; uint32_t calibrationStartTime; float dynamicThreshold; uint8_t freqToNoteNumber(float frequency) const; bool isNoteFrequency(float frequency) const; bool isHarmonic(float freq1, float freq2, float tolerance) const; void findPeaks(); void updateNoteTimings(); void calculateDynamicThreshold(); };