diff --git a/src/TunerWorker.cpp b/src/TunerWorker.cpp index 5998e02..7f3419f 100644 --- a/src/TunerWorker.cpp +++ b/src/TunerWorker.cpp @@ -55,6 +55,7 @@ static void blank_prevent(bool prevent) } TunerWorker::TunerWorker() : + play_stop_counter(0), running(false), playing(false), quit(false), @@ -92,8 +93,15 @@ void TunerWorker::SetPlaying(bool p) cerr << __func__ << " " << p << endl; if (p == playing) return; mutex.lock(); - playing = p; - if (p) condition.wakeOne(); + if (p) { + playing = p; + play_stop_counter = 0; + condition.wakeOne(); + } + else { + // stop after a frame + play_stop_counter = 1; + } mutex.unlock(); } @@ -167,21 +175,27 @@ void TunerWorker::Entry() while (1) { mutex.lock(); + // stop playing after a frame + if (play_stop_counter >= 2) playing = false; + // 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; + p_record = nullptr; } + // free playing after a delay of inactivity to avoid clac // wait for running if (!running && !playing) { blank_prevent(false); + bool waked; while (!running && !playing && !quit) { - condition.wait(&mutex); + waked = condition.wait(&mutex, p_play ? 1000000 : ULONG_MAX); + // free playing now + if (!waked && p_play) { + pa_simple_free(p_play); + p_play = nullptr; + } } cerr << "wake-up" << endl; nb_sample_running = 0; @@ -277,11 +291,15 @@ void TunerWorker::Entry() player->SetFreq(pitchDetection->GetNoteFreq(result.note, result.octave)); } - player->WriteAudio(buffer, nbSampleBuffer); + const int stop_counter = play_stop_counter; + + player->WriteAudio(buffer, nbSampleBuffer, stop_counter > 0); if (pa_simple_write(p_play, buffer, nbSampleBuffer << 1, nullptr) < 0) { cerr << "audio write failed" << endl; } - //else cout << "audio written" << endl; + + if (stop_counter) play_stop_counter = stop_counter + 1; + } // playing // prevent screen blanking diff --git a/src/TunerWorker.hpp b/src/TunerWorker.hpp index c3abf35..1dd920f 100644 --- a/src/TunerWorker.hpp +++ b/src/TunerWorker.hpp @@ -45,6 +45,7 @@ class TunerWorker : public QObject { QMutex mutex; QWaitCondition condition; + int play_stop_counter; bool running, playing, quit; // to update vars diff --git a/src/audio/FreqPlayer.cpp b/src/audio/FreqPlayer.cpp index 4701319..7e8a917 100644 --- a/src/audio/FreqPlayer.cpp +++ b/src/audio/FreqPlayer.cpp @@ -35,6 +35,7 @@ template FreqPlayer::FreqPlayer(int _rate): template void FreqPlayer::Reset() { n_frame = 0; + last_frame = 0; if (k_update != -1) { k = k_update; k_update = -1; @@ -62,21 +63,7 @@ template<> double FreqPlayer::max() { return 1; } template double FreqPlayer::radius() { - double ret = (double) (n_frame++) * k; - - /* to update frequency factor, wait current radius to go to beginning - * in interval [0, 2PI] - */ - if (k_update != -1) { - double a = fmod(ret, M_PI * 1); - double b = fmod(n_frame * k, M_PI * 2); - if (b < a) { // next frame go back to beginning of circle - n_frame = 0; - k = k_update; - k_update = -1; - } - } - return ret; + return (double) (n_frame++) * k; } template sample_t FreqPlayer::AudioFrame() @@ -90,9 +77,34 @@ template sample_t FreqPlayer::AudioFrame() } } -template void FreqPlayer::WriteAudio(sample_t *out, int nb_frame) +template void FreqPlayer::WriteAudio(sample_t *out, int nb_frame, bool stop) { - while (nb_frame--) *out++ = AudioFrame(); + sample_t v; + const bool to_update = (k_update != -1) || stop; + + while (nb_frame--) { + v = AudioFrame(); + if (to_update && (v >= 0 && last_frame < 0)) { + // zero cross. update now. + if (k_update != -1) { + // update frequency + n_frame = 0; + k = k_update; + k_update = -1; + v = AudioFrame(); + } + else if (stop) { + std::cerr << "stop audio" << std::endl; + // finish with 0s + *out++ = 0; + while (nb_frame--) *out++ = 0; + last_frame = 0; + return; + } + } + *out++ = v; + last_frame = v; + } } // instanciation for int16 diff --git a/src/audio/FreqPlayer.hpp b/src/audio/FreqPlayer.hpp index 6062287..7fecb28 100644 --- a/src/audio/FreqPlayer.hpp +++ b/src/audio/FreqPlayer.hpp @@ -42,6 +42,8 @@ template class FreqPlayer { WAVEFORM waveform; /// pre computed factor double k, k_update; + // last frame written + sample_t last_frame; /// return k computed double K() const; @@ -59,7 +61,7 @@ template class FreqPlayer { /// get next audio frame inline sample_t AudioFrame(); /// write audio buffer - void WriteAudio(sample_t *out, int nb_frame); + void WriteAudio(sample_t *out, int nb_frame, bool stop = false); /// set current frequency void SetFreq(double freq); /// set current volume