File record is done by worker, and details
This commit is contained in:
parent
cd9ded443e
commit
e3a3d25cbd
7 changed files with 213 additions and 32 deletions
|
@ -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 {
|
||||
|
|
168
src/'
Normal file
168
src/'
Normal 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;
|
||||
}
|
||||
|
|
@ -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<int16_t>(3, a10, b10);
|
||||
|
||||
ZeroCross<int16_t>::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)
|
||||
{
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
#ifndef _PITCH_DETECTION_HPP
|
||||
#define _PITCH_DETECTION_HPP
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#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<int16_t> *high_filter;
|
||||
ZeroCross<int16_t> *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
|
||||
|
|
|
@ -19,11 +19,16 @@
|
|||
#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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<Tuner>("harbour.sailtuner.tuner", 1, 0, "Tuner");
|
||||
|
|
Loading…
Reference in a new issue