From a38df79293e937e1cdb8b99b20c615894aa73859 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Wed, 21 Sep 2016 15:46:30 -0700 Subject: [PATCH] pa_mac_core_blocking: Fix timeout. Change alignment of comment. --- include/portaudio.h | 6 ++-- src/hostapi/coreaudio/pa_mac_core.c | 2 +- src/hostapi/coreaudio/pa_mac_core_blocking.c | 29 +++++++++++++------- src/hostapi/coreaudio/pa_mac_core_blocking.h | 3 +- test/patest_write_stop_hang_illegal.c | 5 ++-- 5 files changed, 28 insertions(+), 17 deletions(-) diff --git a/include/portaudio.h b/include/portaudio.h index 42e4d6d..e3b9914 100644 --- a/include/portaudio.h +++ b/include/portaudio.h @@ -1149,9 +1149,9 @@ PaError Pa_ReadStream( PaStream* stream, will want to match this parameter to the framesPerBuffer parameter used when opening the stream. - @return On success PaNoError will be returned, - or paOutputUnderflowed if additional output data was inserted after the - previous call and before this call. + @return On success PaNoError will be returned, or paOutputUnderflowed if + additional output data was inserted after the previous call and before this + call. */ PaError Pa_WriteStream( PaStream* stream, const void *buffer, diff --git a/src/hostapi/coreaudio/pa_mac_core.c b/src/hostapi/coreaudio/pa_mac_core.c index 896ee64..beb6bae 100644 --- a/src/hostapi/coreaudio/pa_mac_core.c +++ b/src/hostapi/coreaudio/pa_mac_core.c @@ -2790,7 +2790,7 @@ static PaError StopStream( PaStream *s ) stream->state = STOPPING; VDBUG( ("Waiting for BLIO.\n") ); - paErr = waitUntilBlioWriteBufferIsEmpty( &stream->blio, stream->sampleRate ); + paErr = waitUntilBlioWriteBufferIsEmpty( &stream->blio, stream->sampleRate, stream->outputFramesPerBuffer ); VDBUG( ( "waitUntilBlioWriteBufferIsEmpty returned %d\n", paErr ) ); return FinishStoppingStream( stream ); diff --git a/src/hostapi/coreaudio/pa_mac_core_blocking.c b/src/hostapi/coreaudio/pa_mac_core_blocking.c index 959b765..149d82c 100644 --- a/src/hostapi/coreaudio/pa_mac_core_blocking.c +++ b/src/hostapi/coreaudio/pa_mac_core_blocking.c @@ -587,27 +587,36 @@ PaError WriteStream( PaStream* stream, /* * Wait until the data in the buffer has finished playing. */ -PaError waitUntilBlioWriteBufferIsEmpty( PaMacBlio *blio, double sampleRate ) +PaError waitUntilBlioWriteBufferIsEmpty( PaMacBlio *blio, double sampleRate, + size_t framesPerBuffer ) { PaError result = paNoError; if( blio->outputRingBuffer.buffer ) { - int timeout = 5; // don't wait forever - ring_buffer_size_t framesInBuffer = PaUtil_GetRingBufferReadAvailable( &blio->outputRingBuffer ); - while( framesInBuffer > 0 && timeout-- > 0 ) { - long msecEstimated = 1 + (long)( 1000.0 * framesInBuffer / sampleRate); - VDBUG(( "waitUntilBlioWriteBufferIsFlushed: framesInBuffer = %d, msecEstimated = %ld\n", framesInBuffer, msecEstimated )); - Pa_Sleep( msecEstimated ); - framesInBuffer = PaUtil_GetRingBufferReadAvailable( &blio->outputRingBuffer ); + ring_buffer_size_t framesLeft = PaUtil_GetRingBufferReadAvailable( &blio->outputRingBuffer ); + + /* Calculate when we should give up waiting. To be safe wait for two extra periods. */ + PaTime now = PaUtil_GetTime(); + PaTime startTime = now; + PaTime timeoutTime = startTime + (framesLeft + (2 * framesPerBuffer)) / sampleRate; + + long msecPerBuffer = 1 + (long)( 1000.0 * framesPerBuffer / sampleRate); + while( framesLeft > 0 && now < timeoutTime ) { + VDBUG(( "waitUntilBlioWriteBufferIsFlushed: framesLeft = %d, framesPerBuffer = %ld\n", + framesLeft, framesPerBuffer )); + Pa_Sleep( msecPerBuffer ); + framesLeft = PaUtil_GetRingBufferReadAvailable( &blio->outputRingBuffer ); + now = PaUtil_GetTime(); } - if( framesInBuffer > 0 ) + + if( framesLeft > 0 ) { + VDBUG(( "waitUntilBlioWriteBufferIsFlushed: TIMED OUT - framesLeft = %d\n", framesLeft )); result = paTimedOut; } } return result; } - signed long GetStreamReadAvailable( PaStream* stream ) { PaMacBlio *blio = & ((PaMacCoreStream*)stream) -> blio; diff --git a/src/hostapi/coreaudio/pa_mac_core_blocking.h b/src/hostapi/coreaudio/pa_mac_core_blocking.h index 8a9707b..c994f09 100644 --- a/src/hostapi/coreaudio/pa_mac_core_blocking.h +++ b/src/hostapi/coreaudio/pa_mac_core_blocking.h @@ -128,6 +128,7 @@ int BlioCallback( PaStreamCallbackFlags statusFlags, void *userData ); -PaError waitUntilBlioWriteBufferIsEmpty( PaMacBlio *blio, double sampleRate ); +PaError waitUntilBlioWriteBufferIsEmpty( PaMacBlio *blio, double sampleRate, + size_t framesPerBuffer ); #endif /*PA_MAC_CORE_BLOCKING_H_*/ diff --git a/test/patest_write_stop_hang_illegal.c b/test/patest_write_stop_hang_illegal.c index 35f73a0..71e17de 100644 --- a/test/patest_write_stop_hang_illegal.c +++ b/test/patest_write_stop_hang_illegal.c @@ -50,7 +50,7 @@ #include "portaudio.h" #define SAMPLE_RATE (44100) -#define FRAMES_PER_BUFFER (4096) +#define FRAMES_PER_BUFFER (2048) static float s_buffer[FRAMES_PER_BUFFER][2]; /* stereo output buffer */ @@ -75,10 +75,11 @@ void *stop_thread_proc(void *arg) PaTime time; for (int i = 0; i < 20; i++) { + /* ILLEGAL unsynchronised call to PA, see comment above */ time = Pa_GetStreamTime( stream ); printf("Stream time = %f\n", time); fflush(stdout); - Pa_Sleep(100); + usleep(100 * 1000); } printf("Call Pa_StopStream()\n"); fflush(stdout); -- 2.43.0