Playing: prepare status and code

This commit is contained in:
Louis-Joseph Fournier 2016-01-09 23:33:19 +01:00
parent 17068c8c18
commit e8acf36c9b
5 changed files with 109 additions and 63 deletions

View file

@ -75,7 +75,7 @@ ApplicationWindow {
Tuner { Tuner {
id: tunerObject id: tunerObject
running: Qt.application.active && app.userRunning running: Qt.application.active && page.status == PageStatus.Active && app.userRunning
temperament_idx: Config.temperament_idx temperament_idx: Config.temperament_idx
la: Config.la la: Config.la
} }

View file

@ -57,6 +57,18 @@ Tuner::~Tuner()
workerThread.wait(100); workerThread.wait(100);
} }
bool Tuner::GetPlaying()
{
return playing;
}
void Tuner::SetPlaying(bool p)
{
if (p == playing) return;
playing = p;
emit playingChanged();
}
bool Tuner::GetRunning() bool Tuner::GetRunning()
{ {
return running; return running;

View file

@ -25,6 +25,7 @@
class Tuner : public QObject { class Tuner : public QObject {
Q_OBJECT Q_OBJECT
Q_PROPERTY(bool playing READ GetPlaying WRITE SetPlaying NOTIFY playingChanged)
Q_PROPERTY(bool running READ GetRunning WRITE SetRunning NOTIFY runningChanged) Q_PROPERTY(bool running READ GetRunning WRITE SetRunning NOTIFY runningChanged)
Q_PROPERTY(double freq READ GetFreq NOTIFY resultChanged) Q_PROPERTY(double freq READ GetFreq NOTIFY resultChanged)
Q_PROPERTY(double deviation READ GetDeviation NOTIFY resultChanged) Q_PROPERTY(double deviation READ GetDeviation NOTIFY resultChanged)
@ -41,7 +42,7 @@ class Tuner : public QObject {
PitchDetection::PitchResult result; PitchDetection::PitchResult result;
QStringList temperament_list; QStringList temperament_list;
bool running; bool running, playing;
double la; double la;
int temperament_idx; int temperament_idx;
@ -49,6 +50,8 @@ class Tuner : public QObject {
Tuner(); Tuner();
~Tuner(); ~Tuner();
bool GetPlaying();
void SetPlaying(bool p);
bool GetRunning(); bool GetRunning();
void SetRunning(bool r); void SetRunning(bool r);
double GetFreq(); double GetFreq();
@ -69,6 +72,7 @@ class Tuner : public QObject {
signals: signals:
// signals to UI // signals to UI
void playingChanged();
void runningChanged(); void runningChanged();
void foundChanged(); void foundChanged();
void laChanged(); void laChanged();

View file

@ -83,10 +83,19 @@ void TunerWorker::Stop()
mutex.unlock(); mutex.unlock();
} }
void TunerWorker::SetPlaying(bool p)
{
cerr << __func__ << " " << p << endl;
if (p == playing) return;
mutex.lock();
playing = p;
if (p) condition.wakeOne();
mutex.unlock();
}
void TunerWorker::Quit() void TunerWorker::Quit()
{ {
mutex.lock(); mutex.lock();
running = false;
quit = true; quit = true;
condition.wakeOne(); condition.wakeOne();
mutex.unlock(); mutex.unlock();
@ -112,7 +121,6 @@ void TunerWorker::Entry()
int nbSamplePreventBlanking = nbSecPreventBlanking * PitchDetection::rate; int nbSamplePreventBlanking = nbSecPreventBlanking * PitchDetection::rate;
int nb_sample_running = 0; int nb_sample_running = 0;
bool new_stream = true, waked;
int16_t *buffer = new int16_t[nbSampleBuffer]; int16_t *buffer = new int16_t[nbSampleBuffer];
@ -125,34 +133,43 @@ void TunerWorker::Entry()
emit temperamentListUpdated(pitchDetection->GetTemperamentList()); emit temperamentListUpdated(pitchDetection->GetTemperamentList());
// pulseaudio // pulseaudio
pa_simple *p_simple = NULL; pa_simple *p_record = NULL, *p_play = NULL;
pa_sample_spec p_spec; pa_sample_spec p_spec;
p_spec.format = PA_SAMPLE_S16NE; p_spec.format = PA_SAMPLE_S16NE;
p_spec.channels = 1; p_spec.channels = 1;
p_spec.rate = PitchDetection::rate; p_spec.rate = PitchDetection::rate;
// prevent lpm if running on startup
if (running || playing) blank_prevent(true);
while (1) { while (1) {
// free pulseaudio if not running
if (!running && p_record) {
pa_simple_free(p_record);
p_record = NULL;
}
if (!playing && p_play) {
pa_simple_free(p_play);
p_play = NULL;
}
// wait for running // wait for running
mutex.lock(); mutex.lock();
if (!running) { if (!running && !playing) {
blank_prevent(false); blank_prevent(false);
while (!running && !quit) { while (!running && !playing && !quit) {
waked = condition.wait(&mutex, p_simple ? stopPulseAfterMs : ULONG_MAX); condition.wait(&mutex);
if (!waked && p_simple) {
// stop pulseaudio after a delay if not running
pa_simple_free(p_simple);
p_simple = NULL;
}
} }
cerr << "wake-up" << endl; cerr << "wake-up" << endl;
// reset operations on start nb_sample_running = 0;
new_stream = true; if (!quit) blank_prevent(true);
} }
if (quit) { if (quit) {
mutex.unlock(); mutex.unlock();
break; break;
} }
// update config // update config
if (la_to_update) { if (la_to_update) {
pitchDetection->SetLa(la_to_update); pitchDetection->SetLa(la_to_update);
@ -164,52 +181,64 @@ void TunerWorker::Entry()
} }
mutex.unlock(); mutex.unlock();
if (!p_simple) { if (running ) {
// start pulseaudio if stopped // tuner detection running
p_simple = pa_simple_new(
NULL, if (!p_record) {
NAME, // start pulseaudio if stopped
PA_STREAM_RECORD, p_record = pa_simple_new(
NULL, NULL,
"Mic", NAME,
&p_spec, PA_STREAM_RECORD,
NULL, NULL,
NULL, "Tuner record",
NULL &p_spec,
); NULL,
} NULL,
else if (new_stream) { NULL
// flush pulseaudio if paused );
pa_simple_flush(p_simple, NULL); // reset detection
pitchDetection->Reset();
result.found = false;
emit resultUpdated(result);
}
// get audio data
int size = pa_simple_read(p_record, (void*) buffer, nbSampleBuffer << 1, NULL);
if (size < 0) {
cerr << "audio read failed " << size << endl;
continue;
}
//cerr << "read " << nb_sample_running << endl;
// record in file is needed
if (file) file->write((char*) buffer, nbSampleBuffer << 1);
pitchDetection->AudioAnalyse(buffer, nbSampleBuffer);
if (pitchDetection->GetResultUpdated(result)) {
if (result.found) cout << Scale::NoteName(result.note) << " " << result.frequency << endl;
emit resultUpdated(result);
}
} }
// if stream was stopped, reset analyse if (playing) {
if (new_stream) { // play
pitchDetection->Reset(); if (!p_play) {
blank_prevent(true); // start pulseaudio if stopped
nb_sample_running = 0; p_record = pa_simple_new(
new_stream = false; NULL,
// send a not-found result on restart NAME,
result.found = false; PA_STREAM_PLAYBACK,
emit resultUpdated(result); NULL,
} "Tuner playback",
&p_spec,
// get audio data NULL,
int size = pa_simple_read(p_simple, (void*) buffer, nbSampleBuffer << 1, NULL); NULL,
if (size < 0) { NULL
cerr << "audio read failed " << size << endl; );
continue; }
}
//cerr << "read " << nb_sample_running << endl;
// record in file is needed
if (file) file->write((char*) buffer, nbSampleBuffer << 1);
pitchDetection->AudioAnalyse(buffer, nbSampleBuffer);
if (pitchDetection->GetResultUpdated(result)) {
if (result.found) cout << Scale::NoteName(result.note) << " " << result.frequency << endl;
emit resultUpdated(result);
} }
// prevent screen blanking // prevent screen blanking
@ -220,7 +249,8 @@ void TunerWorker::Entry()
} }
} }
if (p_simple) pa_simple_free(p_simple); if (p_record) pa_simple_free(p_record);
if (p_play) pa_simple_free(p_play);
delete pitchDetection; delete pitchDetection;
delete buffer; delete buffer;
@ -229,6 +259,7 @@ void TunerWorker::Entry()
file->close(); file->close();
delete file; delete file;
} }
blank_prevent(false);
} }
/// Set a filename before instanciation to record raw audio stream /// Set a filename before instanciation to record raw audio stream

View file

@ -39,15 +39,13 @@ class TunerWorker : public QObject {
static const int nbSecPreventBlanking = 40; static const int nbSecPreventBlanking = 40;
/// nb of audio sample to read from pulseaudio at once /// nb of audio sample to read from pulseaudio at once
static const int nbSampleBuffer = 512; static const int nbSampleBuffer = 512;
/// stop pulseaudio after time if not running
static const int stopPulseAfterMs = 2000; // 2 sec
static const char *filename_record; static const char *filename_record;
QMutex mutex; QMutex mutex;
QWaitCondition condition; QWaitCondition condition;
bool running, quit; bool running, playing, quit;
// to update vars // to update vars
double la_to_update; double la_to_update;
@ -61,6 +59,7 @@ class TunerWorker : public QObject {
public slots: public slots:
void Start(); void Start();
void Stop(); void Stop();
void SetPlaying(bool p);
void SetTemperamentIndex(int idx); void SetTemperamentIndex(int idx);
void SetLa(double la); void SetLa(double la);
void Entry(); void Entry();