diff --git a/Tuner.pro b/Tuner.pro index 4a34d8d..cfbec22 100644 --- a/Tuner.pro +++ b/Tuner.pro @@ -1,13 +1,14 @@ QT += qml quick gui multimedia dbus TARGET = Tuner -CONFIG += c++11 +CONFIG += c++11 debug # PKGCONFIG += libpulse SOURCES += \ src/desktop.cpp \ src/Tuner.cpp \ + src/TunerWorker.cpp \ src/audio/LinearFilter.cpp \ src/audio/ZeroCross.cpp \ src/scale/Scale.cpp \ @@ -15,6 +16,7 @@ SOURCES += \ HEADERS += \ src/Tuner.hpp \ + src/TunerWorker.hpp \ src/audio/LinearFilter.hpp \ src/audio/ZeroCross.hpp \ src/scale/Scale.hpp \ diff --git a/harbour-sailtuner.pro b/harbour-sailtuner.pro index 41eadb2..457ada4 100644 --- a/harbour-sailtuner.pro +++ b/harbour-sailtuner.pro @@ -13,6 +13,7 @@ RESOURCES += \ SOURCES += \ src/sailfish.cpp \ src/Tuner.cpp \ + src/TunerWorker.cpp \ src/audio/LinearFilter.cpp \ src/audio/ZeroCross.cpp \ src/scale/Scale.cpp \ @@ -20,6 +21,7 @@ SOURCES += \ HEADERS += \ src/Tuner.hpp \ + src/TunerWorker.hpp \ src/audio/LinearFilter.hpp \ src/audio/ZeroCross.hpp \ src/scale/Scale.hpp \ diff --git a/src/Tuner.cpp b/src/Tuner.cpp index 4950420..440f0c1 100644 --- a/src/Tuner.cpp +++ b/src/Tuner.cpp @@ -19,229 +19,57 @@ #include #include +#include +#include #include -#include -#include #include -#include #include "Tuner.hpp" using namespace std; -// high 10hz / 16k -static double a10[] = { 1 , -2.99214602, 2.98432286, -0.99217678 }; -static double b10[] = { 0.99608071, -2.98824212, 2.98824212, -0.99608071 }; - -const char * Tuner::filename_record = NULL; - -// function to prevent screen blank - -static void blank_prevent(bool prevent) -{ - cerr << __func__ << endl; - QDBusConnection system = QDBusConnection::connectToBus(QDBusConnection::SystemBus, "system"); - QDBusInterface interface("com.nokia.mce", "/com/nokia/mce/request", "com.nokia.mce.request", system); - - if (prevent) { - interface.call(QLatin1String("req_display_blanking_pause")); - } else { - interface.call(QLatin1String("req_display_cancel_blanking_pause")); - } -} - Tuner::Tuner() { running = false; freq = deviation = 0; - note = octave = 0; + note = octave = 0; found = false; - count_found = count_not_found = 0; - nb_sample_running = 0; - note_found = octave_found = -1; + la = Scale::defaultLa; - if (filename_record) file_record.open(filename_record); - - high_filter = new LinearFilter(3, a10, b10); - - ZeroCross::Config cross_config({rate, defaultNbFrame, defaultFreqMin, defaultFreqMax}); - cross = new ZeroCross(cross_config); - - scale = new Scale(); + worker = new TunerWorker(); temperaments = new Temperaments(":/data"); + if (temperaments->SetTemperament(0)) { - scale->SetNotesFrequencies(temperaments->NotesFrequencies()); - } - else { - scale->ConstructEqualTemperament(); + worker->SetNotesFrequencies(temperaments->NotesFrequencies()); } - settings.setCodec("audio/PCM"); - settings.setChannelCount(1); - settings.setSampleRate(rate); + worker->moveToThread(&workerThread); - recorder = new QAudioRecorder(this); - recorder->setAudioInput("pulseaudio:"); - recorder->setAudioSettings(settings); + connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater); + connect(&workerThread, &QThread::started, worker, &TunerWorker::Entry); + connect(this, &Tuner::quit, worker, &TunerWorker::Quit, Qt::DirectConnection); - QUrl url = QString("/dev/null"); - recorder->setOutputLocation(url); + connect(this, &Tuner::start, worker, &TunerWorker::Start); + connect(this, &Tuner::stop, worker, &TunerWorker::Stop); + connect(this, &Tuner::setNotesFrequencies, worker, &TunerWorker::SetNotesFrequencies); + connect(this, &Tuner::setLa, worker, &TunerWorker::SetLa); - probe = new QAudioProbe(this); - connect(probe, SIGNAL(audioBufferProbed(QAudioBuffer)), this, SLOT(AudioCb(QAudioBuffer))); - probe->setSource(recorder); + connect(worker, &TunerWorker::resultFound, this, &Tuner::ResultFound); + connect(worker, &TunerWorker::resultNotFound, this, &Tuner::ResultNotFound); + + workerThread.start(); } Tuner::~Tuner() { - if (filename_record && file_record.is_open()) file_record.close(); - delete high_filter; - delete cross; - delete recorder; - delete probe; - delete scale; + quit(); +// workerThread.quit(); + workerThread.wait(10); delete temperaments; } -void Tuner::Start() -{ - cerr << __func__ << endl; - count_found = count_not_found = 0; - nb_sample_running = 0; - note_found = octave_found = -1; - ResetDeviation(); - blank_prevent(true); - high_filter->Clear(); - cross->Clear(); - recorder->record(); - running = true; - runningChanged(); -} - -void Tuner::Stop() -{ - cerr << __func__ << endl; - running = false; - recorder->stop(); - runningChanged(); - blank_prevent(false); -} - -void Tuner::ComputeFrame(int16_t v) -{ - v = (*high_filter)(v); - (*cross)(v); -} - -void Tuner::AudioCb(const QAudioBuffer &buffer) -{ - const int16_t *ptr = buffer.constData(); - const int nbFrame = buffer.sampleCount(); - AudioAnalyse(ptr, nbFrame); -} - -void Tuner::ResetDeviation() -{ - // reset deviation values - nb_deviation = 0; - deviation_start = 0; - deviation_sum = 0; -} - -void Tuner::UpdateDeviation(double d) -{ - if (nb_deviation == nbDeviationValues) { - deviation_sum -= deviation_values[deviation_start]; - deviation_start = (deviation_start + 1) % nbDeviationValues; - nb_deviation--; - } - deviation_values[(deviation_start + nb_deviation) % nbDeviationValues] = d; - nb_deviation++; - deviation_sum += d; -} - -void Tuner::SetFound(int n, int o, double d) -{ - if (n != note_found || o != octave_found) { - note_found = n; - octave_found = o; - count_found = 0; - SetNotFound(); - - ResetDeviation(); - UpdateDeviation(d); - } - 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(); - } - UpdateDeviation(d); - deviation = deviation_sum / nb_deviation; - deviationChanged(); - } - else { - UpdateDeviation(d); - } -} - -void Tuner::SetNotFound() -{ - if (count_not_found++ >= nbDefect) { - count_found = 0; - if (found) { - found = false; - ResetDeviation(); - foundChanged(); - } - } -} - -void Tuner::AudioAnalyse(const int16_t *ptr, int nb_frame) -{ - nb_sample_running += nb_frame; - - // record in file is needed - if (filename_record && file_record.is_open()) file_record.write((char*) ptr, nb_frame * sizeof(int16_t)); - - // compute every audio frame - while (nb_frame--) ComputeFrame(*ptr++); - - // update frequency - if (freq != cross->Freq()) { - freq = cross->Freq(); - freqChanged(); - } - - // find note, octave, deviation - if (freq) { - int n, o = 0; - double d = 0; - n = scale->FindNote(freq, o, d); - SetFound(n, o, d); - } - else { // no freq - SetNotFound(); - } - - // prevent screen blanking - if (nb_sample_running >= nbSamplePreventRunning && running) { - nb_sample_running = 0; - blank_prevent(true); - } -} - bool Tuner::GetRunning() { return running; @@ -251,8 +79,11 @@ void Tuner::SetRunning(bool r) { if (running == r) return; - if (r) Start(); - else Stop(); + running = r; + if (r) start(); + else stop(); + + runningChanged(); } double Tuner::GetFreq() @@ -275,16 +106,23 @@ int Tuner::GetOctave() return octave; } -const char* Tuner::GetNoteName() -{ - return scale->NoteName(note); -} - bool Tuner::GetFound() { return found; } +void Tuner::SetLa(double la) +{ + this->la = la; + setLa(la); + laChanged(); +} + +double Tuner::GetLa() +{ + return la; +} + unsigned int Tuner::GetTemperamentIndex() { return temperaments->GetCurrentIndex(); @@ -293,7 +131,7 @@ unsigned int Tuner::GetTemperamentIndex() void Tuner::SetTemperamentIndex(unsigned int idx) { if (temperaments->SetTemperament(idx)) { - scale->SetNotesFrequencies(temperaments->NotesFrequencies()); + setNotesFrequencies(temperaments->NotesFrequencies()); temperamentChanged(); } } @@ -303,35 +141,23 @@ QStringList Tuner::GetTemperamentList() const return temperaments->GetNames(); } -/// Set a filename to record raw audio stream - -void Tuner::set_record(const char *f) +void Tuner::ResultFound(int note, int octave, double deviation, double freq) { - filename_record = f; -} + this->note = note; + this->octave = octave; + this->deviation = deviation; + this->freq = freq; + resultChanged(); -/// analyse a file (static function) -void Tuner::analyse_file(const char *filename) -{ - cout << "analyse file " << filename << endl; - ifstream fin; - fin.open(filename); - - const int nb_frame = 1024; - Tuner *tuner = new Tuner(); - int16_t buffer[nb_frame]; - - while (1) { - fin.read((char*) buffer, sizeof(buffer)); - tuner->AudioAnalyse(buffer, sizeof(buffer) >> 1); - - cout << tuner->GetFreq() << " "; - if (tuner->GetFound()) - cout << tuner->GetNoteName() << " " << tuner->GetOctave() << " " << tuner->GetDeviation(); - cout << endl; - - if (fin.eof()) break; + if (!found) { + foundChanged(); + found = true; } - fin.close(); - delete tuner; +} + +void Tuner::ResultNotFound(double freq) +{ + this->freq = freq; + found = false; + foundChanged(); } diff --git a/src/Tuner.hpp b/src/Tuner.hpp index 1d0e9da..0df2fce 100644 --- a/src/Tuner.hpp +++ b/src/Tuner.hpp @@ -15,79 +15,37 @@ * */ -#include -#include +#ifndef _TUNER_HPP +#define _TUNER_HPP -#include - -#include "audio/LinearFilter.hpp" -#include "audio/ZeroCross.hpp" -#include "scale/Scale.hpp" +#include "TunerWorker.hpp" #include "scale/Temperaments.hpp" class Tuner : public QObject { Q_OBJECT Q_PROPERTY(bool running READ GetRunning WRITE SetRunning NOTIFY runningChanged) - Q_PROPERTY(double freq READ GetFreq NOTIFY freqChanged) - 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(double freq READ GetFreq NOTIFY resultChanged) + Q_PROPERTY(double deviation READ GetDeviation NOTIFY resultChanged) + Q_PROPERTY(int note READ GetNote NOTIFY resultChanged) + Q_PROPERTY(int octave READ GetOctave NOTIFY resultChanged) Q_PROPERTY(bool found READ GetFound NOTIFY foundChanged) - Q_PROPERTY(QString noteName READ GetNoteName NOTIFY noteNameChanged) Q_PROPERTY(int temperament_idx READ GetTemperamentIndex WRITE SetTemperamentIndex NOTIFY temperamentChanged) Q_PROPERTY(QStringList temperament_list READ GetTemperamentList) + Q_PROPERTY(double la READ GetLa WRITE SetLa NOTIFY laChanged) private: - QAudioRecorder *recorder; - QAudioEncoderSettings settings; - QAudioProbe *probe; - - LinearFilter *high_filter; - ZeroCross *cross; - Scale *scale; Temperaments *temperaments; - static const char *filename_record; - std::ofstream file_record; + TunerWorker *worker; + QThread workerThread; bool running, found; - double freq, deviation; - int note, octave, nb_sample_running; - int note_found, octave_found, count_found, count_not_found; - int nb_deviation, deviation_start; - double deviation_sum; - - 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; - /// number of deviation values for average - static const int nbDeviationValues = 8; - - double deviation_values[nbDeviationValues]; - - inline void ComputeFrame(int16_t v); - void SetFound(int note, int octave, double deviation); - void SetNotFound(); - void ResetDeviation(); - void UpdateDeviation(double d); - - private slots: - void AudioCb(const QAudioBuffer &buffer); + double freq, deviation, la; + int note, octave; public: Tuner(); ~Tuner(); - void Start(); - void Stop(); - - void AudioAnalyse(const int16_t *buffer, int size); - bool GetRunning(); void SetRunning(bool r); double GetFreq(); @@ -95,23 +53,29 @@ class Tuner : public QObject { int GetOctave(); double GetDeviation(); bool GetFound(); - const char* GetNoteName(); unsigned int GetTemperamentIndex(); void SetTemperamentIndex(unsigned int idx); QStringList GetTemperamentList() const; + double GetLa(); + void SetLa(double la); - /// analyse a file for debug - static void analyse_file(const char *filename); - /// write a file with raw audio - static void set_record(const char *filename_record); + public slots: + void ResultFound(int note, int octave, double deviation, double frequency); + void ResultNotFound(double freq); signals: void runningChanged(); - void freqChanged(); - void noteChanged(); - void noteNameChanged(); - void octaveChanged(); - void deviationChanged(); void foundChanged(); void temperamentChanged(); + void laChanged(); + void resultChanged(); + + // signals to worker + void quit(); + void start(); + void stop(); + void setNotesFrequencies(const double *freq); + void setLa(double la_freq); }; + +#endif diff --git a/src/TunerWorker.cpp b/src/TunerWorker.cpp new file mode 100644 index 0000000..330d6dc --- /dev/null +++ b/src/TunerWorker.cpp @@ -0,0 +1,297 @@ +/* Copyright 2016 (C) Louis-Joseph Fournier + * louisjoseph.fournier@gmail.com + * + * This file is part of SailTuner. + * + * SailTuner is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SailTuner is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include + +#include +#include + +#include "TunerWorker.hpp" + +using namespace std; + +// high 10hz / 16k +static double a10[] = { 1 , -2.99214602, 2.98432286, -0.99217678 }; +static double b10[] = { 0.99608071, -2.98824212, 2.98824212, -0.99608071 }; + +const char * TunerWorker::filename_record = NULL; + +/// function to prevent screen blank on Sailfish OS + +static void blank_prevent(bool prevent) +{ + cerr << __func__ << endl; + QDBusConnection system = QDBusConnection::connectToBus(QDBusConnection::SystemBus, "system"); + QDBusInterface interface("com.nokia.mce", "/com/nokia/mce/request", "com.nokia.mce.request", system); + + if (prevent) { + interface.call(QLatin1String("req_display_blanking_pause")); + } else { + interface.call(QLatin1String("req_display_cancel_blanking_pause")); + } +} + +TunerWorker::TunerWorker() : + high_filter(NULL), + cross(NULL), + scale(NULL), + running(false), + quit(false), + la_to_update(0), + freq_to_update(NULL) +{ + // part of reset + found = false; + count_found = count_not_found = 0; + nb_sample_running = 0; + note_found = octave_found = -1; + ResetDeviation(); +} + +TunerWorker::~TunerWorker() +{ + if (filename_record && file_record.is_open()) file_record.close(); + if (high_filter) delete high_filter; + if (cross) delete cross; + if (scale) delete scale; +} + +/// reset analyse values +void TunerWorker::Reset() +{ + found = false; + count_found = count_not_found = 0; + nb_sample_running = 0; + note_found = octave_found = -1; + ResetDeviation(); + blank_prevent(true); + high_filter->Clear(); + cross->Clear(); +} + +void TunerWorker::Start() +{ + cerr << __func__ << endl; + mutex.lock(); + running = true; + condition.wakeOne(); + mutex.unlock(); +} + +void TunerWorker::Stop() +{ + mutex.lock(); + running = false; + mutex.unlock(); +} + +void TunerWorker::Quit() +{ + mutex.lock(); + running = false; + quit = true; + condition.wakeOne(); + mutex.unlock(); +} + +void TunerWorker::SetNotesFrequencies(const double *notes_freq) +{ + mutex.lock(); + freq_to_update = notes_freq; + mutex.unlock(); +} + +void TunerWorker::SetLa(double la) +{ + mutex.lock(); + la_to_update = la; + mutex.unlock(); +} + +void TunerWorker::ComputeFrame(int16_t v) +{ + v = (*high_filter)(v); + (*cross)(v); +} + +void TunerWorker::ResetDeviation() +{ + // reset deviation values + nb_deviation = 0; + deviation_start = 0; + deviation_sum = 0; +} + +void TunerWorker::UpdateDeviation(double d) +{ + if (nb_deviation == nbDeviationValues) { + deviation_sum -= deviation_values[deviation_start]; + deviation_start = (deviation_start + 1) % nbDeviationValues; + nb_deviation--; + } + deviation_values[(deviation_start + nb_deviation) % nbDeviationValues] = d; + nb_deviation++; + deviation_sum += d; +} + +void TunerWorker::SetFound(int n, int o, double d) +{ + if (n != note_found || o != octave_found) { + note_found = n; + octave_found = o; + count_found = 0; + SetNotFound(); + + ResetDeviation(); + UpdateDeviation(d); + } + else if (count_found++ >= nbConfirm) { + found = true; + count_not_found = 0; + UpdateDeviation(d); + + resultFound(n, o, deviation_sum / nb_deviation, cross->Freq()); + } + else { + UpdateDeviation(d); + } +} + +void TunerWorker::SetNotFound() +{ + if (count_not_found++ >= nbDefect) { + count_found = 0; + if (found) { + found = false; + ResetDeviation(); + resultNotFound(cross->Freq()); + } + } +} + +void TunerWorker::AudioAnalyse(const int16_t *ptr, int nb_frame) +{ + nb_sample_running += nb_frame; + + // record in file is needed + if (filename_record && file_record.is_open()) file_record.write((char*) ptr, nb_frame * sizeof(int16_t)); + + // compute every audio frame + while (nb_frame--) ComputeFrame(*ptr++); + + // find note, octave, deviation + if (cross->Freq()) { + int n, o = 0; + double d = 0; + n = scale->FindNote(cross->Freq(), o, d); + SetFound(n, o, d); + } + else { // no freq + SetNotFound(); + } + + // prevent screen blanking + if (nb_sample_running >= nbSamplePreventRunning && running) { + nb_sample_running = 0; + blank_prevent(true); + } +} + + +void TunerWorker::Entry() +{ + // initialisations + if (filename_record) file_record.open(filename_record); + + high_filter = new LinearFilter(3, a10, b10); + + ZeroCross::Config cross_config({rate, defaultNbFrame, defaultFreqMin, defaultFreqMax}); + cross = new ZeroCross(cross_config); + + scale = new Scale(); + + while (1) { + // wait for running + mutex.lock(); + if (!running) { + blank_prevent(false); + while (!running && !quit) condition.wait(&mutex); + // reset operations on start + if (!quit) Reset(); + } + if (quit) { + mutex.unlock(); + break; + } + // update config + if (la_to_update) { + scale->SetLa(la_to_update); + la_to_update = 0; + } + if (freq_to_update) { + scale->SetNotesFrequencies(freq_to_update); + freq_to_update = NULL; + } + mutex.unlock(); + + std::cout << __func__ << " do job" << std::endl; + } +} + +/// Set a filename to record raw audio stream + +void TunerWorker::set_record(const char *f) +{ + filename_record = f; +} + +/// for analyse_file console logs +static void display_results(int note, int octave, double deviation, double frequency) +{ + cout << frequency << " " << Scale::NoteName(note) << " " << octave << " " << deviation << endl; +} + +static void display_no_results(double freq) +{ + cout << freq << endl; +} + +/// analyse a file (static function) +void TunerWorker::analyse_file(const char *filename) +{ + cout << "analyse file " << filename << endl; + ifstream fin; + fin.open(filename); + + const int nb_frame = 1024; + TunerWorker *tuner = new TunerWorker(); + int16_t buffer[nb_frame]; + + connect(tuner, &TunerWorker::resultFound, NULL, display_results); + connect(tuner, &TunerWorker::resultNotFound, NULL, display_no_results); + + while (1) { + fin.read((char*) buffer, sizeof(buffer)); + tuner->AudioAnalyse(buffer, sizeof(buffer) >> 1); +// cout << "." << endl; + + if (fin.eof()) break; + } + fin.close(); + delete tuner; +} diff --git a/src/TunerWorker.hpp b/src/TunerWorker.hpp new file mode 100644 index 0000000..384a054 --- /dev/null +++ b/src/TunerWorker.hpp @@ -0,0 +1,106 @@ +/* Copyright 2016 (C) Louis-Joseph Fournier + * louisjoseph.fournier@gmail.com + * + * This file is part of SailTuner. + * + * SailTuner is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SailTuner is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _TUNER_WORKER_HPP +#define _TUNER_WORKER_HPP + +#include +#include +#include +#include + +#include + +#include "audio/LinearFilter.hpp" +#include "audio/ZeroCross.hpp" +#include "scale/Scale.hpp" + +/** + * Worker class to work with audio datas + * + * Implements the pitch algorithm + * and note finding + */ +class TunerWorker : public QObject { + Q_OBJECT + + private: + 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; + /// number of deviation values for average + static const int nbDeviationValues = 8; + + static const char *filename_record; + + LinearFilter *high_filter; + ZeroCross *cross; + Scale *scale; + std::ofstream file_record; + + QMutex mutex; + QWaitCondition condition; + + bool running, found, quit; + int nb_sample_running; + int note_found, octave_found, count_found, count_not_found; + int nb_deviation, deviation_start; + double deviation_sum; + double deviation_values[nbDeviationValues]; + + // to update vars + double la_to_update; + const double *freq_to_update; + + inline void ComputeFrame(int16_t v); + void SetFound(int note, int octave, double deviation); + void SetNotFound(); + void Reset(); + void ResetDeviation(); + void UpdateDeviation(double d); + void AudioAnalyse(const int16_t *buffer, int size); + + public: + /// analyse a file for debug + static void analyse_file(const char *filename); + /// write a file with raw audio + static void set_record(const char *filename_record); + + /// constructor + TunerWorker(); + ~TunerWorker(); + + public slots: + void Start(); + void Stop(); + void SetNotesFrequencies(const double *notes_freq); + void SetLa(double la); + void Entry(); + void Quit(); + + signals: + void resultFound(int note, int octave, double deviation, double frequency); + void resultNotFound(double freq); +}; + +#endif diff --git a/src/desktop.cpp b/src/desktop.cpp index 499dada..1ce5ff4 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -27,7 +27,7 @@ Q_DECL_EXPORT int main(int argc, char* argv[]) { if (argc == 2) { - Tuner::analyse_file(argv[1]); + TunerWorker::analyse_file(argv[1]); return 0; } diff --git a/src/sailfish.cpp b/src/sailfish.cpp index 5048637..f0aea6b 100644 --- a/src/sailfish.cpp +++ b/src/sailfish.cpp @@ -45,7 +45,7 @@ class Main { Q_DECL_EXPORT int main(int argc, char* argv[]) { if (argc == 2) { - Tuner::analyse_file(argv[1]); + TunerWorker::analyse_file(argv[1]); return 0; } else if (argc == 3 && strcmp(argv[1], "record") == 0) { diff --git a/src/scale/Scale.cpp b/src/scale/Scale.cpp index 8f21389..3e788c3 100644 --- a/src/scale/Scale.cpp +++ b/src/scale/Scale.cpp @@ -36,6 +36,7 @@ const char * Scale::NoteName(int note) Scale::Scale() { actualLa = defaultLa; + freq_setted = false; } void Scale::updateScale() @@ -80,6 +81,10 @@ int Scale::findOctave(double &freq) int Scale::FindNote(double freq, int &octave, double &deviation) { assert (freq > 0); + if (!freq_setted) { + std::cerr << "Scale " << __func__ << ": notes not setted" << std::endl; + ConstructEqualTemperament(); + } int note = 0; octave = findOctave(freq); @@ -111,6 +116,7 @@ void Scale::ConstructEqualTemperament() noteFreq[i] = defaultLa * pow(2, (double) (i - la) / 12); //std::cerr << noteFreq[i] << std::endl; } + freq_setted = true; updateScale(); } @@ -121,6 +127,8 @@ double Scale::GetLa() void Scale::SetNotesFrequencies(const double freq[nbNote]) { + std::cout << __func__ << std::endl; + freq_setted = true; memcpy(noteFreq, freq, sizeof(double) * nbNote); updateScale(); } diff --git a/src/scale/Scale.hpp b/src/scale/Scale.hpp index f97834e..ba2c263 100644 --- a/src/scale/Scale.hpp +++ b/src/scale/Scale.hpp @@ -22,16 +22,18 @@ * Note recognition within a temperament */ class Scale { + public: + static const int defaultLa = 440; private: static const int nbNote = 12; static const int cmpOctave = 4; - static const int defaultLa = 440; static const char *noteNames[nbNote]; double noteFreq[nbNote], actualNoteFreq[nbNote]; double actualLa, actualFactor; double actualRange[2]; // freq range for default octave + bool freq_setted; /// update scale after temperament or default la change void updateScale(); diff --git a/src/scale/Temperaments.cpp b/src/scale/Temperaments.cpp index 1285fc2..6495772 100644 --- a/src/scale/Temperaments.cpp +++ b/src/scale/Temperaments.cpp @@ -69,7 +69,7 @@ void Temperaments::CheckFile(const QString & filename) } // add temperament name = line.left(offset); - qDebug() << " -> add temperament" << name; + //qDebug() << " -> add temperament" << name; list.push_back(temp_t{name, filename, f_pos}); } } diff --git a/src/scale/Temperaments.hpp b/src/scale/Temperaments.hpp index e2bb9ed..ba8aa7b 100644 --- a/src/scale/Temperaments.hpp +++ b/src/scale/Temperaments.hpp @@ -19,6 +19,7 @@ #define __TEMPERAMENTS_HPP #include +#include #include /**