diff --git a/qml/TunerScreen.qml b/qml/TunerScreen.qml index d1f553a..fd88b6c 100644 --- a/qml/TunerScreen.qml +++ b/qml/TunerScreen.qml @@ -40,6 +40,8 @@ Item { property color led_green: "green" property color led_red: "red" + opacity: tuner.running ? 1 : 0.8 + property bool dev_is_ok: Math.abs(tuner.deviation) <= deviation_ok Led { diff --git a/src/' b/src/' new file mode 100644 index 0000000..0abbd7e --- /dev/null +++ b/src/' @@ -0,0 +1,168 @@ +/* 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; + +/// file name to record audio + +const char * TunerWorker::filename_record = NULL; + +/// function to prevent screen blank on Sailfish OS + +static void blank_prevent(bool prevent) +{ + cerr << __func__ << " " << prevent << 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() : + running(false), + quit(false), + la_to_update(0), + temperament_to_update(-1) +{ +} + +TunerWorker::~TunerWorker() +{ +} + +void TunerWorker::Start() +{ + cerr << __func__ << endl; + mutex.lock(); + running = true; + condition.wakeOne(); + mutex.unlock(); +} + +void TunerWorker::Stop() +{ + cerr << __func__ << endl; + mutex.lock(); + running = false; + mutex.unlock(); +} + +void TunerWorker::Quit() +{ + mutex.lock(); + running = false; + quit = true; + condition.wakeOne(); + mutex.unlock(); +} + +void TunerWorker::SetLa(double la) +{ + mutex.lock(); + la_to_update = la; + mutex.unlock(); +} + +void TunerWorker::SetTemperamentIndex(int idx) +{ + mutex.lock(); + temperament_to_update = idx; + mutex.unlock(); +} + +void TunerWorker::Entry() +{ + cerr << __func__ << endl; + + int nbSamplePreventRunning = nbSecPreventRunning * PitchDetection::rate; + int nb_sample_running = 0; + + ofstream *file = NULL; + if (filename_record) file = new ofstream(filename_record); + + PitchDetection *pitchDetection = new PitchDetection(); + emit temperamentListUpdated(pitchDetection->GetTemperamentList()); + + while (1) { + // wait for running + mutex.lock(); + if (!running) { + blank_prevent(false); + while (!running && !quit) condition.wait(&mutex); + cerr << "wake-up" << endl; + // reset operations on start + if (!quit) { + pitchDetection->Reset(); + nb_sample_running = 0; + } + } + if (quit) { + mutex.unlock(); + break; + } + // update config + if (la_to_update) { + pitchDetection->SetLa(la_to_update); + la_to_update = 0; + } + if (temperament_to_update != -1) { + pitchDetection->SetTemperament(temperament_to_update); + temperament_to_update = -1; + } + mutex.unlock(); + + // record in file is needed + //if (file) file_record.write((char*) ptr, nb_frame * sizeof(int16_t)); + + std::cout << __func__ << " do job" << std::endl; + } + + delete pitchDetection; + + if (file) { + file->close(); + delete file; + } + + cerr << __func__ << " quit" << endl; +/* + // prevent screen blanking + if (nb_sample_running >= nbSamplePreventRunning && running) { + nb_sample_running = 0; + blank_prevent(true); + }*/ +} + +/// Set a filename to record raw audio stream + +void TunerWorker::set_record(const char *f) +{ + filename_record = f; +} + diff --git a/src/PitchDetection.cpp b/src/PitchDetection.cpp index 3d3d643..5fb8494 100644 --- a/src/PitchDetection.cpp +++ b/src/PitchDetection.cpp @@ -26,8 +26,6 @@ using namespace std; static double a10[] = { 1 , -2.99214602, 2.98432286, -0.99217678 }; static double b10[] = { 0.99608071, -2.98824212, 2.98824212, -0.99608071 }; -const char * PitchDetection::filename_record = NULL; - /// Pitch detection result methods PitchDetection::PitchResult::PitchResult() : @@ -52,8 +50,6 @@ void PitchDetection::PitchResult::Set(int n, int o, double d, double f) PitchDetection::PitchDetection() { - if (filename_record) file_record.open(filename_record); - high_filter = new LinearFilter(3, a10, b10); ZeroCross::Config cross_config({rate, defaultNbFrame, defaultFreqMin, defaultFreqMax}); @@ -74,7 +70,6 @@ PitchDetection::PitchDetection() PitchDetection::~PitchDetection() { - if (filename_record && file_record.is_open()) file_record.close(); delete high_filter; delete cross; delete scale; @@ -169,9 +164,6 @@ void PitchDetection::SetTemperament(int idx) void PitchDetection::AudioAnalyse(const int16_t *ptr, int 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++); @@ -200,13 +192,6 @@ QStringList PitchDetection::GetTemperamentList() const return temperaments->GetNames(); } -/// Set a filename to record raw audio stream - -void PitchDetection::set_record(const char *f) -{ - filename_record = f; -} - /// for analyse_file console logs static void display_results(const PitchDetection::PitchResult &res) { diff --git a/src/PitchDetection.hpp b/src/PitchDetection.hpp index 21568b4..f2818d6 100644 --- a/src/PitchDetection.hpp +++ b/src/PitchDetection.hpp @@ -18,8 +18,6 @@ #ifndef _PITCH_DETECTION_HPP #define _PITCH_DETECTION_HPP -#include - #include "audio/LinearFilter.hpp" #include "audio/ZeroCross.hpp" #include "scale/Scale.hpp" @@ -45,12 +43,12 @@ class PitchDetection { void Set(int n, int o, double d, double f); }; - private: static const int rate = 16000; + + private: 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 @@ -58,13 +56,10 @@ class PitchDetection { /// number of deviation values for average static const int nbDeviationValues = 8; - static const char *filename_record; - LinearFilter *high_filter; ZeroCross *cross; Scale *scale; Temperaments *temperaments; - std::ofstream file_record; PitchResult result; bool updated; @@ -100,8 +95,6 @@ class PitchDetection { /// 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); }; #endif diff --git a/src/TunerWorker.cpp b/src/TunerWorker.cpp index ce3cb39..8ba181f 100644 --- a/src/TunerWorker.cpp +++ b/src/TunerWorker.cpp @@ -19,11 +19,16 @@ #include #include +#include #include "TunerWorker.hpp" using namespace std; +/// file name to record audio + +const char * TunerWorker::filename_record = NULL; + /// function to prevent screen blank on Sailfish OS static void blank_prevent(bool prevent) @@ -49,7 +54,6 @@ TunerWorker::TunerWorker() : TunerWorker::~TunerWorker() { - if (pitchDetection) delete pitchDetection; } void TunerWorker::Start() @@ -96,7 +100,13 @@ void TunerWorker::Entry() { cerr << __func__ << endl; - pitchDetection = new PitchDetection(); + int nbSamplePreventRunning = nbSecPreventRunning * PitchDetection::rate; + int nb_sample_running = 0; + + ofstream *file = NULL; + if (filename_record) file = new ofstream(filename_record); + + PitchDetection *pitchDetection = new PitchDetection(); emit temperamentListUpdated(pitchDetection->GetTemperamentList()); while (1) { @@ -107,7 +117,10 @@ void TunerWorker::Entry() while (!running && !quit) condition.wait(&mutex); cerr << "wake-up" << endl; // reset operations on start - if (!quit) pitchDetection->Reset(); + if (!quit) { + pitchDetection->Reset(); + nb_sample_running = 0; + } } if (quit) { mutex.unlock(); @@ -124,9 +137,19 @@ void TunerWorker::Entry() } mutex.unlock(); + // record in file is needed + //if (file) file->write((char*) ptr, nb_frame * sizeof(int16_t)); + std::cout << __func__ << " do job" << std::endl; } + delete pitchDetection; + + if (file) { + file->close(); + delete file; + } + cerr << __func__ << " quit" << endl; /* // prevent screen blanking @@ -136,3 +159,10 @@ void TunerWorker::Entry() }*/ } +/// Set a filename before instanciation to record raw audio stream + +void TunerWorker::set_record(const char *f) +{ + filename_record = f; +} + diff --git a/src/TunerWorker.hpp b/src/TunerWorker.hpp index 3cfe150..ccb555a 100644 --- a/src/TunerWorker.hpp +++ b/src/TunerWorker.hpp @@ -35,13 +35,13 @@ class TunerWorker : public QObject { Q_OBJECT private: + static const int nbSecPreventRunning = 40; + static const char *filename_record; + QMutex mutex; QWaitCondition condition; - PitchDetection *pitchDetection; - bool running, quit; - int nb_sample_running; // to update vars double la_to_update; @@ -60,6 +60,9 @@ class TunerWorker : public QObject { void Entry(); void Quit(); + /// write a file with raw audio + static void set_record(const char *filename_record); + signals: void resultUpdated(const PitchDetection::PitchResult &result); void temperamentListUpdated(const QStringList &list); diff --git a/src/sailfish.cpp b/src/sailfish.cpp index f0aea6b..768464f 100644 --- a/src/sailfish.cpp +++ b/src/sailfish.cpp @@ -45,11 +45,11 @@ class Main { Q_DECL_EXPORT int main(int argc, char* argv[]) { if (argc == 2) { - TunerWorker::analyse_file(argv[1]); + PitchDetection::analyse_file(argv[1]); return 0; } else if (argc == 3 && strcmp(argv[1], "record") == 0) { - Tuner::set_record(argv[2]); + TunerWorker::set_record(argv[2]); } qmlRegisterType("harbour.sailtuner.tuner", 1, 0, "Tuner");