Playing: prepare status and code
This commit is contained in:
parent
17068c8c18
commit
e8acf36c9b
5 changed files with 109 additions and 63 deletions
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in a new issue