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 {
id: tunerObject
running: Qt.application.active && app.userRunning
running: Qt.application.active && page.status == PageStatus.Active && app.userRunning
temperament_idx: Config.temperament_idx
la: Config.la
}

View file

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

View file

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

View file

@ -83,10 +83,19 @@ void TunerWorker::Stop()
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()
{
mutex.lock();
running = false;
quit = true;
condition.wakeOne();
mutex.unlock();
@ -112,7 +121,6 @@ void TunerWorker::Entry()
int nbSamplePreventBlanking = nbSecPreventBlanking * PitchDetection::rate;
int nb_sample_running = 0;
bool new_stream = true, waked;
int16_t *buffer = new int16_t[nbSampleBuffer];
@ -125,34 +133,43 @@ void TunerWorker::Entry()
emit temperamentListUpdated(pitchDetection->GetTemperamentList());
// pulseaudio
pa_simple *p_simple = NULL;
pa_simple *p_record = NULL, *p_play = NULL;
pa_sample_spec p_spec;
p_spec.format = PA_SAMPLE_S16NE;
p_spec.channels = 1;
p_spec.rate = PitchDetection::rate;
// prevent lpm if running on startup
if (running || playing) blank_prevent(true);
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
mutex.lock();
if (!running) {
if (!running && !playing) {
blank_prevent(false);
while (!running && !quit) {
waked = condition.wait(&mutex, p_simple ? stopPulseAfterMs : ULONG_MAX);
if (!waked && p_simple) {
// stop pulseaudio after a delay if not running
pa_simple_free(p_simple);
p_simple = NULL;
}
while (!running && !playing && !quit) {
condition.wait(&mutex);
}
cerr << "wake-up" << endl;
// reset operations on start
new_stream = true;
nb_sample_running = 0;
if (!quit) blank_prevent(true);
}
if (quit) {
mutex.unlock();
break;
}
// update config
if (la_to_update) {
pitchDetection->SetLa(la_to_update);
@ -164,38 +181,30 @@ void TunerWorker::Entry()
}
mutex.unlock();
if (!p_simple) {
if (running ) {
// tuner detection running
if (!p_record) {
// start pulseaudio if stopped
p_simple = pa_simple_new(
p_record = pa_simple_new(
NULL,
NAME,
PA_STREAM_RECORD,
NULL,
"Mic",
"Tuner record",
&p_spec,
NULL,
NULL,
NULL
);
}
else if (new_stream) {
// flush pulseaudio if paused
pa_simple_flush(p_simple, NULL);
}
// if stream was stopped, reset analyse
if (new_stream) {
// reset detection
pitchDetection->Reset();
blank_prevent(true);
nb_sample_running = 0;
new_stream = false;
// send a not-found result on restart
result.found = false;
emit resultUpdated(result);
}
// get audio data
int size = pa_simple_read(p_simple, (void*) buffer, nbSampleBuffer << 1, NULL);
int size = pa_simple_read(p_record, (void*) buffer, nbSampleBuffer << 1, NULL);
if (size < 0) {
cerr << "audio read failed " << size << endl;
continue;
@ -212,6 +221,26 @@ void TunerWorker::Entry()
emit resultUpdated(result);
}
}
if (playing) {
// play
if (!p_play) {
// start pulseaudio if stopped
p_record = pa_simple_new(
NULL,
NAME,
PA_STREAM_PLAYBACK,
NULL,
"Tuner playback",
&p_spec,
NULL,
NULL,
NULL
);
}
}
// prevent screen blanking
nb_sample_running += nbSampleBuffer;
if (nb_sample_running >= nbSamplePreventBlanking && running) {
@ -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 buffer;
@ -229,6 +259,7 @@ void TunerWorker::Entry()
file->close();
delete file;
}
blank_prevent(false);
}
/// 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;
/// nb of audio sample to read from pulseaudio at once
static const int nbSampleBuffer = 512;
/// stop pulseaudio after time if not running
static const int stopPulseAfterMs = 2000; // 2 sec
static const char *filename_record;
QMutex mutex;
QWaitCondition condition;
bool running, quit;
bool running, playing, quit;
// to update vars
double la_to_update;
@ -61,6 +59,7 @@ class TunerWorker : public QObject {
public slots:
void Start();
void Stop();
void SetPlaying(bool p);
void SetTemperamentIndex(int idx);
void SetLa(double la);
void Entry();