diff --git a/include/AudioJack.h b/include/AudioJack.h index 60adfc9a5..9bbb3bd48 100644 --- a/include/AudioJack.h +++ b/include/AudioJack.h @@ -37,7 +37,6 @@ #include #include #include -#include #include "AudioDevice.h" #include "AudioDeviceSetupWidget.h" @@ -108,7 +107,6 @@ private: bool m_active; bool m_stopped; - QMutex m_processingMutex; MidiJack *m_midiClient; QVector m_outputPorts; diff --git a/include/AudioPortAudio.h b/include/AudioPortAudio.h index 6a07aad47..e4f27c7e1 100644 --- a/include/AudioPortAudio.h +++ b/include/AudioPortAudio.h @@ -145,7 +145,6 @@ private: int m_outBufSize; bool m_stopped; - QSemaphore m_stopSemaphore; } ; diff --git a/include/AudioSoundIo.h b/include/AudioSoundIo.h index b0192a19e..f743ad676 100644 --- a/include/AudioSoundIo.h +++ b/include/AudioSoundIo.h @@ -109,6 +109,8 @@ private: fpp_t m_outBufFramesTotal; fpp_t m_outBufFrameIndex; + bool m_stopped; + int m_disconnectErr; void onBackendDisconnect(int err); diff --git a/include/fifo_buffer.h b/include/fifo_buffer.h index 39f9867fe..422b48df2 100644 --- a/include/fifo_buffer.h +++ b/include/fifo_buffer.h @@ -66,6 +66,12 @@ public: return( element ); } + void waitUntilRead() + { + m_writer_sem.acquire( m_size ); + m_writer_sem.release( m_size ); + } + bool available() { return( m_reader_sem.available() ); diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 830d7e6c8..d5baa0a85 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -640,7 +640,7 @@ void Mixer::storeAudioDevice() void Mixer::restoreAudioDevice() { - if( m_oldAudioDev != NULL ) + if( m_oldAudioDev && m_audioDev != m_oldAudioDev ) { stopProcessing(); delete m_audioDev; @@ -648,9 +648,9 @@ void Mixer::restoreAudioDevice() m_audioDev = m_oldAudioDev; emit sampleRateChanged(); - m_oldAudioDev = NULL; startProcessing(); } + m_oldAudioDev = NULL; } @@ -1127,7 +1127,9 @@ void Mixer::fifoWriter::run() write( buffer ); } + // Let audio backend stop processing write( NULL ); + m_fifo->waitUntilRead(); } diff --git a/src/core/audio/AudioJack.cpp b/src/core/audio/AudioJack.cpp index 4d730eed4..bca41356b 100644 --- a/src/core/audio/AudioJack.cpp +++ b/src/core/audio/AudioJack.cpp @@ -201,7 +201,6 @@ bool AudioJack::initJackClient() void AudioJack::startProcessing() { - QMutexLocker m( &m_processingMutex ); m_stopped = false; if( m_active || m_client == NULL ) @@ -254,7 +253,6 @@ void AudioJack::startProcessing() void AudioJack::stopProcessing() { - QMutexLocker m( &m_processingMutex ); m_stopped = true; } @@ -342,7 +340,6 @@ void AudioJack::renamePort( AudioPort * _port ) int AudioJack::processCallback( jack_nframes_t _nframes, void * _udata ) { - QMutexLocker m( &m_processingMutex ); // do midi processing first so that midi input can // add to the following sound processing @@ -406,6 +403,7 @@ int AudioJack::processCallback( jack_nframes_t _nframes, void * _udata ) m_framesDoneInCurBuf = 0; if( !m_framesToDoInCurBuf ) { + m_stopped = true; break; } } diff --git a/src/core/audio/AudioPortAudio.cpp b/src/core/audio/AudioPortAudio.cpp index b14c1e79d..6abb29453 100644 --- a/src/core/audio/AudioPortAudio.cpp +++ b/src/core/audio/AudioPortAudio.cpp @@ -57,8 +57,7 @@ AudioPortAudio::AudioPortAudio( bool & _success_ful, Mixer * _mixer ) : m_paStream( NULL ), m_wasPAInitError( false ), m_outBuf( new surroundSampleFrame[mixer()->framesPerPeriod()] ), - m_outBufPos( 0 ), - m_stopSemaphore( 1 ) + m_outBufPos( 0 ) { _success_ful = false; @@ -167,8 +166,6 @@ AudioPortAudio::AudioPortAudio( bool & _success_ful, Mixer * _mixer ) : printf( "Input device: '%s' backend: '%s'\n", Pa_GetDeviceInfo( inDevIdx )->name, Pa_GetHostApiInfo( Pa_GetDeviceInfo( inDevIdx )->hostApi )->name ); printf( "Output device: '%s' backend: '%s'\n", Pa_GetDeviceInfo( outDevIdx )->name, Pa_GetHostApiInfo( Pa_GetDeviceInfo( outDevIdx )->hostApi )->name ); - m_stopSemaphore.acquire(); - // TODO: debug Mixer::pushInputFrames() //m_supportsCapture = true; @@ -181,7 +178,6 @@ AudioPortAudio::AudioPortAudio( bool & _success_ful, Mixer * _mixer ) : AudioPortAudio::~AudioPortAudio() { stopProcessing(); - m_stopSemaphore.release(); if( !m_wasPAInitError ) { @@ -212,8 +208,7 @@ void AudioPortAudio::stopProcessing() { if( m_paStream && Pa_IsStreamActive( m_paStream ) ) { - m_stopSemaphore.acquire(); - + m_stopped = true; PaError err = Pa_StopStream( m_paStream ); if( err != paNoError ) @@ -283,7 +278,6 @@ int AudioPortAudio::process_callback( if( !frames ) { m_stopped = true; - m_stopSemaphore.release(); memset( _outputBuffer, 0, _framesPerBuffer * channels() * sizeof(float) ); return paComplete; diff --git a/src/core/audio/AudioPulseAudio.cpp b/src/core/audio/AudioPulseAudio.cpp index 23031b10c..20a106ed1 100644 --- a/src/core/audio/AudioPulseAudio.cpp +++ b/src/core/audio/AudioPulseAudio.cpp @@ -103,6 +103,7 @@ void AudioPulseAudio::startProcessing() void AudioPulseAudio::stopProcessing() { + m_quit = true; stopProcessingThread( this ); } diff --git a/src/core/audio/AudioSdl.cpp b/src/core/audio/AudioSdl.cpp index 2b810e913..f513916ba 100644 --- a/src/core/audio/AudioSdl.cpp +++ b/src/core/audio/AudioSdl.cpp @@ -168,6 +168,7 @@ void AudioSdl::sdlAudioCallback( Uint8 * _buf, int _len ) const fpp_t frames = getNextBuffer( m_outBuf ); if( !frames ) { + m_stopped = true; memset( _buf, 0, _len ); return; } diff --git a/src/core/audio/AudioSoundIo.cpp b/src/core/audio/AudioSoundIo.cpp index 46a0315e7..f6c624127 100644 --- a/src/core/audio/AudioSoundIo.cpp +++ b/src/core/audio/AudioSoundIo.cpp @@ -49,6 +49,7 @@ AudioSoundIo::AudioSoundIo( bool & outSuccessful, Mixer * _mixer ) : m_disconnectErr = 0; m_outBufFrameIndex = 0; m_outBufFramesTotal = 0; + m_stopped = true; m_soundio = soundio_create(); if (!m_soundio) @@ -210,15 +211,18 @@ void AudioSoundIo::startProcessing() m_outBuf = new surroundSampleFrame[m_outBufSize]; + m_stopped = false; int err; if ((err = soundio_outstream_start(m_outstream))) { + m_stopped = true; fprintf(stderr, "soundio unable to start stream: %s\n", soundio_strerror(err)); } } void AudioSoundIo::stopProcessing() { + m_stopped = true; if (m_outstream) { soundio_outstream_destroy(m_outstream); @@ -244,6 +248,7 @@ void AudioSoundIo::underflowCallback() void AudioSoundIo::writeCallback(int frameCountMin, int frameCountMax) { + if (m_stopped) {return;} const struct SoundIoChannelLayout *layout = &m_outstream->layout; SoundIoChannelArea *areas; int bytesPerSample = m_outstream->bytes_per_sample; @@ -265,11 +270,27 @@ void AudioSoundIo::writeCallback(int frameCountMin, int frameCountMax) if (!frameCount) break; + + if (m_stopped) + { + for (int channel = 0; channel < layout->channel_count; ++channel) + { + memset(areas[channel].ptr, 0, bytesPerSample * frameCount); + areas[channel].ptr += areas[channel].step * frameCount; + } + continue; + } + for (int frame = 0; frame < frameCount; frame += 1) { if (m_outBufFrameIndex >= m_outBufFramesTotal) { m_outBufFramesTotal = getNextBuffer(m_outBuf); + if (m_outBufFramesTotal == 0) + { + m_stopped = true; + break; + } m_outBufFrameIndex = 0; }