diff --git a/qml/TunerScreen.qml b/qml/TunerScreen.qml index c02f963..066b236 100644 --- a/qml/TunerScreen.qml +++ b/qml/TunerScreen.qml @@ -25,7 +25,7 @@ Item { width: Math.min(parent.width, parent.height * 1.5) height: width / 2 - level: tuner.deviation * 100 + level: tuner.found ? tuner.deviation * 100 : -50 } ScaleToise { diff --git a/src/Tuner.cpp b/src/Tuner.cpp index 11bf8b6..aee436d 100644 --- a/src/Tuner.cpp +++ b/src/Tuner.cpp @@ -34,6 +34,8 @@ Tuner::Tuner() running = false; freq = deviation = 0; note = octave = 0; + found = false; + count_found = count_not_found = 0; high_filter = new LinearFilter(3, a10, b10); @@ -70,6 +72,7 @@ Tuner::~Tuner() void Tuner::Start() { cerr << __func__ << endl; + count_found = count_not_found = 0; nb_sample_running = 0; blank_prevent(true); high_filter->Clear(); @@ -101,6 +104,45 @@ void Tuner::AudioCb(const QAudioBuffer &buffer) AudioAnalyse(ptr, nbFrame); } +void Tuner::SetFound(int n, int o, double d) +{ + if (n != note_found) { + note_found = n; + count_found = 0; + SetNotFound(); + } + else if (count_found++ >= nbConfirm) { + count_not_found = 0; + if (!found) { + found = true; + foundChanged(); + } + if (note != n) { + note = n; + noteChanged(); + } + if (octave != o) { + octave = o; + octaveChanged(); + } + if (deviation != d) { + deviation = d; + deviationChanged(); + } + } +} + +void Tuner::SetNotFound() +{ + if (count_not_found++ >= nbDefect) { + count_found = 0; + if (found) { + found = false; + foundChanged(); + } + } +} + void Tuner::AudioAnalyse(const int16_t *ptr, int nb_frame) { nb_sample_running += nb_frame; @@ -112,12 +154,13 @@ void Tuner::AudioAnalyse(const int16_t *ptr, int nb_frame) freqChanged(); if (freq) { - note = scale->FindNote(freq, octave, deviation); - noteChanged(); - noteNameChanged(); - octaveChanged(); - deviationChanged(); - //std::cerr << note << " " << scale->NoteName(note) << std::endl; + int n, o; + double d; + n = scale->FindNote(freq, o, d); + SetFound(n, o, d); + } + else { // no freq + SetNotFound(); } } @@ -164,3 +207,8 @@ const char* Tuner::GetNoteName() { return scale->NoteName(note); } + +bool Tuner::GetFound() +{ + return found; +} diff --git a/src/Tuner.hpp b/src/Tuner.hpp index be6cdb4..e90333e 100644 --- a/src/Tuner.hpp +++ b/src/Tuner.hpp @@ -12,6 +12,7 @@ class Tuner : public QObject { Q_PROPERTY(double deviation READ GetDeviation NOTIFY deviationChanged) Q_PROPERTY(int note READ GetNote NOTIFY noteChanged) Q_PROPERTY(int octave READ GetOctave NOTIFY octaveChanged) + Q_PROPERTY(bool found READ GetFound NOTIFY foundChanged) Q_PROPERTY(QString noteName READ GetNoteName NOTIFY noteNameChanged) private: @@ -23,17 +24,25 @@ class Tuner : public QObject { ZeroCross *cross; Scale *scale; - bool running; + bool running, found; double freq, deviation; int note, octave, nb_sample_running; + int note_found, count_found, count_not_found; static const int rate = 16000; static const int defaultNbFrame = 1024; static const int defaultFreqMin = 50; static const int defaultFreqMax = 2000; static const int nbSamplePreventRunning = rate * 40; // 40 seconds + /// number of analyses to confirm a note + static const int nbConfirm = 3; + /// number of analyses to drop a note + static const int nbDefect = 20; + inline void ComputeFrame(int16_t v); + void SetFound(int note, int octave, double deviation); + void SetNotFound(); private slots: void AudioCb(const QAudioBuffer &buffer); @@ -53,6 +62,7 @@ class Tuner : public QObject { int GetNote(); int GetOctave(); double GetDeviation(); + bool GetFound(); const char* GetNoteName(); signals: @@ -62,4 +72,5 @@ class Tuner : public QObject { void noteNameChanged(); void octaveChanged(); void deviationChanged(); + void foundChanged(); };