File record is done by worker, and details

This commit is contained in:
Louis-Joseph Fournier 2016-01-05 14:17:16 +01:00
parent cd9ded443e
commit e3a3d25cbd
7 changed files with 213 additions and 32 deletions

View file

@ -40,6 +40,8 @@ Item {
property color led_green: "green" property color led_green: "green"
property color led_red: "red" property color led_red: "red"
opacity: tuner.running ? 1 : 0.8
property bool dev_is_ok: Math.abs(tuner.deviation) <= deviation_ok property bool dev_is_ok: Math.abs(tuner.deviation) <= deviation_ok
Led { Led {

168
src/' Normal file
View file

@ -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 <QDBusConnection>
#include <QDBusInterface>
#include <iostream>
#include <fstream>
#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;
}

View file

@ -26,8 +26,6 @@ using namespace std;
static double a10[] = { 1 , -2.99214602, 2.98432286, -0.99217678 }; static double a10[] = { 1 , -2.99214602, 2.98432286, -0.99217678 };
static double b10[] = { 0.99608071, -2.98824212, 2.98824212, -0.99608071 }; static double b10[] = { 0.99608071, -2.98824212, 2.98824212, -0.99608071 };
const char * PitchDetection::filename_record = NULL;
/// Pitch detection result methods /// Pitch detection result methods
PitchDetection::PitchResult::PitchResult() : PitchDetection::PitchResult::PitchResult() :
@ -52,8 +50,6 @@ void PitchDetection::PitchResult::Set(int n, int o, double d, double f)
PitchDetection::PitchDetection() PitchDetection::PitchDetection()
{ {
if (filename_record) file_record.open(filename_record);
high_filter = new LinearFilter<int16_t>(3, a10, b10); high_filter = new LinearFilter<int16_t>(3, a10, b10);
ZeroCross<int16_t>::Config cross_config({rate, defaultNbFrame, defaultFreqMin, defaultFreqMax}); ZeroCross<int16_t>::Config cross_config({rate, defaultNbFrame, defaultFreqMin, defaultFreqMax});
@ -74,7 +70,6 @@ PitchDetection::PitchDetection()
PitchDetection::~PitchDetection() PitchDetection::~PitchDetection()
{ {
if (filename_record && file_record.is_open()) file_record.close();
delete high_filter; delete high_filter;
delete cross; delete cross;
delete scale; delete scale;
@ -169,9 +164,6 @@ void PitchDetection::SetTemperament(int idx)
void PitchDetection::AudioAnalyse(const int16_t *ptr, int nb_frame) 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 // compute every audio frame
while (nb_frame--) ComputeFrame(*ptr++); while (nb_frame--) ComputeFrame(*ptr++);
@ -200,13 +192,6 @@ QStringList PitchDetection::GetTemperamentList() const
return temperaments->GetNames(); 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 /// for analyse_file console logs
static void display_results(const PitchDetection::PitchResult &res) static void display_results(const PitchDetection::PitchResult &res)
{ {

View file

@ -18,8 +18,6 @@
#ifndef _PITCH_DETECTION_HPP #ifndef _PITCH_DETECTION_HPP
#define _PITCH_DETECTION_HPP #define _PITCH_DETECTION_HPP
#include <fstream>
#include "audio/LinearFilter.hpp" #include "audio/LinearFilter.hpp"
#include "audio/ZeroCross.hpp" #include "audio/ZeroCross.hpp"
#include "scale/Scale.hpp" #include "scale/Scale.hpp"
@ -45,12 +43,12 @@ class PitchDetection {
void Set(int n, int o, double d, double f); void Set(int n, int o, double d, double f);
}; };
private:
static const int rate = 16000; static const int rate = 16000;
private:
static const int defaultNbFrame = 1024; static const int defaultNbFrame = 1024;
static const int defaultFreqMin = 50; static const int defaultFreqMin = 50;
static const int defaultFreqMax = 2000; static const int defaultFreqMax = 2000;
static const int nbSamplePreventRunning = rate * 40; // 40 seconds
/// number of analyses to confirm a note /// number of analyses to confirm a note
static const int nbConfirm = 3; static const int nbConfirm = 3;
/// number of analyses to drop a note /// number of analyses to drop a note
@ -58,13 +56,10 @@ class PitchDetection {
/// number of deviation values for average /// number of deviation values for average
static const int nbDeviationValues = 8; static const int nbDeviationValues = 8;
static const char *filename_record;
LinearFilter<int16_t> *high_filter; LinearFilter<int16_t> *high_filter;
ZeroCross<int16_t> *cross; ZeroCross<int16_t> *cross;
Scale *scale; Scale *scale;
Temperaments *temperaments; Temperaments *temperaments;
std::ofstream file_record;
PitchResult result; PitchResult result;
bool updated; bool updated;
@ -100,8 +95,6 @@ class PitchDetection {
/// analyse a file for debug /// analyse a file for debug
static void analyse_file(const char *filename); static void analyse_file(const char *filename);
/// write a file with raw audio
static void set_record(const char *filename_record);
}; };
#endif #endif

View file

@ -19,11 +19,16 @@
#include <QDBusInterface> #include <QDBusInterface>
#include <iostream> #include <iostream>
#include <fstream>
#include "TunerWorker.hpp" #include "TunerWorker.hpp"
using namespace std; using namespace std;
/// file name to record audio
const char * TunerWorker::filename_record = NULL;
/// function to prevent screen blank on Sailfish OS /// function to prevent screen blank on Sailfish OS
static void blank_prevent(bool prevent) static void blank_prevent(bool prevent)
@ -49,7 +54,6 @@ TunerWorker::TunerWorker() :
TunerWorker::~TunerWorker() TunerWorker::~TunerWorker()
{ {
if (pitchDetection) delete pitchDetection;
} }
void TunerWorker::Start() void TunerWorker::Start()
@ -96,7 +100,13 @@ void TunerWorker::Entry()
{ {
cerr << __func__ << endl; 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()); emit temperamentListUpdated(pitchDetection->GetTemperamentList());
while (1) { while (1) {
@ -107,7 +117,10 @@ void TunerWorker::Entry()
while (!running && !quit) condition.wait(&mutex); while (!running && !quit) condition.wait(&mutex);
cerr << "wake-up" << endl; cerr << "wake-up" << endl;
// reset operations on start // reset operations on start
if (!quit) pitchDetection->Reset(); if (!quit) {
pitchDetection->Reset();
nb_sample_running = 0;
}
} }
if (quit) { if (quit) {
mutex.unlock(); mutex.unlock();
@ -124,9 +137,19 @@ void TunerWorker::Entry()
} }
mutex.unlock(); 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; std::cout << __func__ << " do job" << std::endl;
} }
delete pitchDetection;
if (file) {
file->close();
delete file;
}
cerr << __func__ << " quit" << endl; cerr << __func__ << " quit" << endl;
/* /*
// prevent screen blanking // 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;
}

View file

@ -35,13 +35,13 @@ class TunerWorker : public QObject {
Q_OBJECT Q_OBJECT
private: private:
static const int nbSecPreventRunning = 40;
static const char *filename_record;
QMutex mutex; QMutex mutex;
QWaitCondition condition; QWaitCondition condition;
PitchDetection *pitchDetection;
bool running, quit; bool running, quit;
int nb_sample_running;
// to update vars // to update vars
double la_to_update; double la_to_update;
@ -60,6 +60,9 @@ class TunerWorker : public QObject {
void Entry(); void Entry();
void Quit(); void Quit();
/// write a file with raw audio
static void set_record(const char *filename_record);
signals: signals:
void resultUpdated(const PitchDetection::PitchResult &result); void resultUpdated(const PitchDetection::PitchResult &result);
void temperamentListUpdated(const QStringList &list); void temperamentListUpdated(const QStringList &list);

View file

@ -45,11 +45,11 @@ class Main {
Q_DECL_EXPORT int main(int argc, char* argv[]) Q_DECL_EXPORT int main(int argc, char* argv[])
{ {
if (argc == 2) { if (argc == 2) {
TunerWorker::analyse_file(argv[1]); PitchDetection::analyse_file(argv[1]);
return 0; return 0;
} }
else if (argc == 3 && strcmp(argv[1], "record") == 0) { else if (argc == 3 && strcmp(argv[1], "record") == 0) {
Tuner::set_record(argv[2]); TunerWorker::set_record(argv[2]);
} }
qmlRegisterType<Tuner>("harbour.sailtuner.tuner", 1, 0, "Tuner"); qmlRegisterType<Tuner>("harbour.sailtuner.tuner", 1, 0, "Tuner");