Fix assert when reading or writing with non-power of 2 channels.

This commit is contained in:
Phil Burk 2016-05-18 21:41:01 -07:00
commit 110043f842
4 changed files with 121 additions and 119 deletions

View file

@ -33,13 +33,13 @@
*/ */
/* /*
* The text above constitutes the entire PortAudio license; however, * The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests: * the PortAudio community also makes the following non-binding requests:
* *
* Any person wishing to distribute modifications to the Software is * Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that * requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also * they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the * requested that these non-binding requests be included along with the
* license above. * license above.
*/ */
@ -51,7 +51,7 @@
/* #define SAMPLE_RATE (17932) // Test failure to open with this value. */ /* #define SAMPLE_RATE (17932) // Test failure to open with this value. */
#define SAMPLE_RATE (44100) #define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (1024) #define FRAMES_PER_BUFFER (1024)
#define NUM_CHANNELS (2) #define NUM_CHANNELS (6)
#define NUM_SECONDS (15) #define NUM_SECONDS (15)
/* #define DITHER_FLAG (paDitherOff) */ /* #define DITHER_FLAG (paDitherOff) */
#define DITHER_FLAG (0) /**/ #define DITHER_FLAG (0) /**/
@ -109,8 +109,8 @@ int main(void)
char *sampleBlock; char *sampleBlock;
int i; int i;
int numBytes; int numBytes;
printf("patest_read_write_wire.c\n"); fflush(stdout); printf("patest_read_write_wire.c\n"); fflush(stdout);
numBytes = FRAMES_PER_BUFFER * NUM_CHANNELS * SAMPLE_SIZE ; numBytes = FRAMES_PER_BUFFER * NUM_CHANNELS * SAMPLE_SIZE ;
@ -170,24 +170,6 @@ int main(void)
err = Pa_StopStream( stream ); err = Pa_StopStream( stream );
if( err != paNoError ) goto error; if( err != paNoError ) goto error;
CLEAR( sampleBlock );
/*
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Wire on. Interrupt to stop.\n"); fflush(stdout);
while( 1 )
{
err = Pa_WriteStream( stream, sampleBlock, FRAMES_PER_BUFFER );
if( err ) goto xrun;
err = Pa_ReadStream( stream, sampleBlock, FRAMES_PER_BUFFER );
if( err ) goto xrun;
}
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
Pa_CloseStream( stream );
*/
free( sampleBlock ); free( sampleBlock );
Pa_Terminate(); Pa_Terminate();

View file

@ -1921,14 +1921,13 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
/* /*
* If input and output devs are different or we are doing SR conversion, * If input and output devs are different or we are doing SR conversion,
* we also need a * we also need a ring buffer to store input data while waiting for
* ring buffer to store inpt data while waiting for output * output data.
* data.
*/ */
if( (stream->outputUnit && (stream->inputUnit != stream->outputUnit)) if( (stream->outputUnit && (stream->inputUnit != stream->outputUnit))
|| stream->inputSRConverter ) || stream->inputSRConverter )
{ {
/* May want the ringSize ot initial position in /* May want the ringSize or initial position in
ring buffer to depend somewhat on sample rate change */ ring buffer to depend somewhat on sample rate change */
void *data; void *data;
@ -1951,7 +1950,15 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
} }
/* now we can initialize the ring buffer */ /* now we can initialize the ring buffer */
PaUtil_InitializeRingBuffer( &stream->inputRingBuffer, szfl*inputParameters->channelCount, ringSize, data ) ; result = PaUtil_InitializeRingBuffer( &stream->inputRingBuffer, szfl*inputParameters->channelCount, ringSize, data );
if( result != 0 )
{
/* The only reason this should fail is if ringSize is not a power of 2, which we do not anticipate happening. */
result = paUnanticipatedHostError;
free(data);
goto error;
}
/* advance the read point a little, so we are reading from the /* advance the read point a little, so we are reading from the
middle of the buffer */ middle of the buffer */
if( stream->outputUnit ) if( stream->outputUnit )
@ -1973,12 +1980,11 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
stream->outputFramesPerBuffer, stream->outputFramesPerBuffer,
sampleRate ); sampleRate );
result = initializeBlioRingBuffers( &stream->blio, result = initializeBlioRingBuffers( &stream->blio,
inputParameters?inputParameters->sampleFormat:0 , inputParameters ? inputParameters->sampleFormat : 0,
outputParameters?outputParameters->sampleFormat:0 , outputParameters ? outputParameters->sampleFormat : 0,
MAX(stream->inputFramesPerBuffer,stream->outputFramesPerBuffer),
ringSize, ringSize,
inputParameters?inputChannelCount:0 , inputParameters ? inputChannelCount : 0,
outputParameters?outputChannelCount:0 ) ; outputParameters ? outputChannelCount : 0 ) ;
if( result != paNoError ) if( result != paNoError )
goto error; goto error;

View file

@ -108,14 +108,16 @@ static size_t computeSampleSizeFromFormatPow2( PaSampleFormat format )
* *
*/ */
/* This should be called with the relevant info when initializing a stream for /**
callback. */ * This should be called with the relevant info when initializing a stream for callback.
*
* @param ringBufferSizeInFrames must be a power of 2
*/
PaError initializeBlioRingBuffers( PaError initializeBlioRingBuffers(
PaMacBlio *blio, PaMacBlio *blio,
PaSampleFormat inputSampleFormat, PaSampleFormat inputSampleFormat,
PaSampleFormat outputSampleFormat, PaSampleFormat outputSampleFormat,
size_t framesPerBuffer, long ringBufferSizeInFrames,
long ringBufferSize,
int inChan, int inChan,
int outChan ) int outChan )
{ {
@ -126,20 +128,19 @@ PaError initializeBlioRingBuffers(
/* zeroify things */ /* zeroify things */
bzero( blio, sizeof( PaMacBlio ) ); bzero( blio, sizeof( PaMacBlio ) );
/* this is redundant, but the buffers are used to check /* this is redundant, but the buffers are used to check
if the bufffers have been initialized, so we do it explicitly. */ if the buffers have been initialized, so we do it explicitly. */
blio->inputRingBuffer.buffer = NULL; blio->inputRingBuffer.buffer = NULL;
blio->outputRingBuffer.buffer = NULL; blio->outputRingBuffer.buffer = NULL;
/* initialize simple data */ /* initialize simple data */
blio->ringBufferFrames = ringBufferSize; blio->ringBufferFrames = ringBufferSizeInFrames;
blio->inputSampleFormat = inputSampleFormat; blio->inputSampleFormat = inputSampleFormat;
blio->inputSampleSizeActual = computeSampleSizeFromFormat(inputSampleFormat); blio->inputSampleSizeActual = computeSampleSizeFromFormat(inputSampleFormat);
blio->inputSampleSizePow2 = computeSampleSizeFromFormatPow2(inputSampleFormat); blio->inputSampleSizePow2 = computeSampleSizeFromFormatPow2(inputSampleFormat); // FIXME: WHY?
blio->outputSampleFormat = outputSampleFormat; blio->outputSampleFormat = outputSampleFormat;
blio->outputSampleSizeActual = computeSampleSizeFromFormat(outputSampleFormat); blio->outputSampleSizeActual = computeSampleSizeFromFormat(outputSampleFormat);
blio->outputSampleSizePow2 = computeSampleSizeFromFormatPow2(outputSampleFormat); blio->outputSampleSizePow2 = computeSampleSizeFromFormatPow2(outputSampleFormat);
blio->framesPerBuffer = framesPerBuffer;
blio->inChan = inChan; blio->inChan = inChan;
blio->outChan = outChan; blio->outChan = outChan;
blio->statusFlags = 0; blio->statusFlags = 0;
@ -163,7 +164,7 @@ PaError initializeBlioRingBuffers(
result = UNIX_ERR( pthread_cond_init( &(blio->outputCond), NULL ) ); result = UNIX_ERR( pthread_cond_init( &(blio->outputCond), NULL ) );
#endif #endif
if( inChan ) { if( inChan ) {
data = calloc( ringBufferSize, blio->inputSampleSizePow2*inChan ); data = calloc( ringBufferSizeInFrames, blio->inputSampleSizePow2 * inChan );
if( !data ) if( !data )
{ {
result = paInsufficientMemory; result = paInsufficientMemory;
@ -172,12 +173,13 @@ PaError initializeBlioRingBuffers(
err = PaUtil_InitializeRingBuffer( err = PaUtil_InitializeRingBuffer(
&blio->inputRingBuffer, &blio->inputRingBuffer,
1, ringBufferSize*blio->inputSampleSizePow2*inChan, blio->inputSampleSizePow2 * inChan,
ringBufferSizeInFrames,
data ); data );
assert( !err ); assert( !err );
} }
if( outChan ) { if( outChan ) {
data = calloc( ringBufferSize, blio->outputSampleSizePow2*outChan ); data = calloc( ringBufferSizeInFrames, blio->outputSampleSizePow2 * outChan );
if( !data ) if( !data )
{ {
result = paInsufficientMemory; result = paInsufficientMemory;
@ -186,7 +188,8 @@ PaError initializeBlioRingBuffers(
err = PaUtil_InitializeRingBuffer( err = PaUtil_InitializeRingBuffer(
&blio->outputRingBuffer, &blio->outputRingBuffer,
1, ringBufferSize*blio->outputSampleSizePow2*outChan, blio->outputSampleSizePow2 * outChan,
ringBufferSizeInFrames,
data ); data );
assert( !err ); assert( !err );
} }
@ -266,12 +269,11 @@ PaError resetBlioRingBuffers( PaMacBlio *blio )
#endif #endif
blio->statusFlags = 0; blio->statusFlags = 0;
if( blio->outputRingBuffer.buffer ) { if( blio->outputRingBuffer.buffer ) {
PaUtil_FlushRingBuffer( &blio->outputRingBuffer ); PaUtil_FlushRingBuffer( &blio->outputRingBuffer );
bzero( blio->outputRingBuffer.buffer, /* Fill the buffer with zeros. */
blio->outputRingBuffer.bufferSize ); bzero( blio->outputRingBuffer.buffer,
/* Advance buffer */ blio->outputRingBuffer.bufferSize * blio->outputRingBuffer.elementSizeBytes );
PaUtil_AdvanceRingBufferWriteIndex( &blio->outputRingBuffer, blio->ringBufferFrames*blio->outputSampleSizeActual*blio->outChan ); PaUtil_AdvanceRingBufferWriteIndex( &blio->outputRingBuffer, blio->ringBufferFrames );
//PaUtil_AdvanceRingBufferWriteIndex( &blio->outputRingBuffer, blio->outputRingBuffer.bufferSize );
/* Update isOutputFull. */ /* Update isOutputFull. */
#ifdef PA_MAC__BLIO_MUTEX #ifdef PA_MAC__BLIO_MUTEX
@ -280,16 +282,14 @@ PaError resetBlioRingBuffers( PaMacBlio *blio )
goto error; goto error;
#endif #endif
/* /*
printf( "------%d\n" , blio->framesPerBuffer );
printf( "------%d\n" , blio->outChan ); printf( "------%d\n" , blio->outChan );
printf( "------%d\n" , blio->outputSampleSize ); printf( "------%d\n" , blio->outputSampleSize );
printf( "------%d\n" , blio->framesPerBuffer*blio->outChan*blio->outputSampleSize );
*/ */
} }
if( blio->inputRingBuffer.buffer ) { if( blio->inputRingBuffer.buffer ) {
PaUtil_FlushRingBuffer( &blio->inputRingBuffer ); PaUtil_FlushRingBuffer( &blio->inputRingBuffer );
bzero( blio->inputRingBuffer.buffer, bzero( blio->inputRingBuffer.buffer,
blio->inputRingBuffer.bufferSize ); blio->inputRingBuffer.bufferSize * blio->inputRingBuffer.elementSizeBytes );
/* Update isInputEmpty. */ /* Update isInputEmpty. */
#ifdef PA_MAC__BLIO_MUTEX #ifdef PA_MAC__BLIO_MUTEX
result = blioSetIsInputEmpty( blio, true ); result = blioSetIsInputEmpty( blio, true );
@ -344,30 +344,32 @@ int BlioCallback( const void *input, void *output, unsigned long frameCount,
void *userData ) void *userData )
{ {
PaMacBlio *blio = (PaMacBlio*)userData; PaMacBlio *blio = (PaMacBlio*)userData;
long avail; ring_buffer_size_t framesAvailable;
long toRead; ring_buffer_size_t framesToTransfer;
long toWrite; ring_buffer_size_t framesTransferred;
long read;
long written;
/* set flags returned by OS: */ /* set flags returned by OS: */
OSAtomicOr32( statusFlags, &blio->statusFlags ) ; OSAtomicOr32( statusFlags, &blio->statusFlags ) ;
/* --- Handle Input Buffer --- */ /* --- Handle Input Buffer --- */
if( blio->inChan ) { if( blio->inChan ) {
avail = PaUtil_GetRingBufferWriteAvailable( &blio->inputRingBuffer ); framesAvailable = PaUtil_GetRingBufferWriteAvailable( &blio->inputRingBuffer );
/* check for underflow */ /* check for underflow */
if( avail < frameCount * blio->inputSampleSizeActual * blio->inChan ) if( framesAvailable < frameCount )
{ {
OSAtomicOr32( paInputOverflow, &blio->statusFlags ); OSAtomicOr32( paInputOverflow, &blio->statusFlags );
framesToTransfer = framesAvailable;
}
else
{
framesToTransfer = (ring_buffer_size_t)frameCount;
} }
toRead = MIN( avail, frameCount * blio->inputSampleSizeActual * blio->inChan );
/* copy the data */ /* Copy the data from the audio input to the application ring buffer. */
/*printf( "reading %d\n", toRead );*/ /*printf( "reading %d\n", toRead );*/
read = PaUtil_WriteRingBuffer( &blio->inputRingBuffer, input, toRead ); framesTransferred = PaUtil_WriteRingBuffer( &blio->inputRingBuffer, input, framesToTransfer );
assert( toRead == read ); assert( framesToTransfer == framesTransferred );
#ifdef PA_MAC__BLIO_MUTEX #ifdef PA_MAC__BLIO_MUTEX
/* Priority inversion. See notes below. */ /* Priority inversion. See notes below. */
blioSetIsInputEmpty( blio, false ); blioSetIsInputEmpty( blio, false );
@ -377,21 +379,31 @@ int BlioCallback( const void *input, void *output, unsigned long frameCount,
/* --- Handle Output Buffer --- */ /* --- Handle Output Buffer --- */
if( blio->outChan ) { if( blio->outChan ) {
avail = PaUtil_GetRingBufferReadAvailable( &blio->outputRingBuffer ); framesAvailable = PaUtil_GetRingBufferReadAvailable( &blio->outputRingBuffer );
/* check for underflow */ /* check for underflow */
if( avail < frameCount * blio->outputSampleSizeActual * blio->outChan ) if( framesAvailable < frameCount )
OSAtomicOr32( paOutputUnderflow, &blio->statusFlags ); {
/* zero out the end of the output buffer that we do not have data for */
framesToTransfer = framesAvailable;
toWrite = MIN( avail, frameCount * blio->outputSampleSizeActual * blio->outChan ); size_t bytesPerFrame = blio->outputSampleSizeActual * blio->outChan;
size_t offsetInBytes = framesToTransfer * bytesPerFrame;
size_t countInBytes = (frameCount - framesToTransfer) * bytesPerFrame;
bzero( ((char *)output) + offsetInBytes, countInBytes );
OSAtomicOr32( paOutputUnderflow, &blio->statusFlags );
framesToTransfer = framesAvailable;
}
else
{
framesToTransfer = (ring_buffer_size_t)frameCount;
}
if( toWrite != frameCount * blio->outputSampleSizeActual * blio->outChan )
bzero( ((char *)output)+toWrite,
frameCount * blio->outputSampleSizeActual * blio->outChan - toWrite );
/* copy the data */ /* copy the data */
/*printf( "writing %d\n", toWrite );*/ /*printf( "writing %d\n", toWrite );*/
written = PaUtil_ReadRingBuffer( &blio->outputRingBuffer, output, toWrite ); framesTransferred = PaUtil_ReadRingBuffer( &blio->outputRingBuffer, output, framesToTransfer );
assert( toWrite == written ); assert( framesToTransfer == framesTransferred );
#ifdef PA_MAC__BLIO_MUTEX #ifdef PA_MAC__BLIO_MUTEX
/* We have a priority inversion here. However, we will only have to /* We have a priority inversion here. However, we will only have to
wait if this was true and is now false, which means we've got wait if this was true and is now false, which means we've got
@ -406,24 +418,25 @@ int BlioCallback( const void *input, void *output, unsigned long frameCount,
PaError ReadStream( PaStream* stream, PaError ReadStream( PaStream* stream,
void *buffer, void *buffer,
unsigned long frames ) unsigned long framesRequested )
{ {
PaMacBlio *blio = & ((PaMacCoreStream*)stream) -> blio; PaMacBlio *blio = & ((PaMacCoreStream*)stream) -> blio;
char *cbuf = (char *) buffer; char *cbuf = (char *) buffer;
PaError ret = paNoError; PaError ret = paNoError;
VVDBUG(("ReadStream()\n")); VVDBUG(("ReadStream()\n"));
while( frames > 0 ) { while( framesRequested > 0 ) {
long avail; ring_buffer_size_t framesAvailable;
long toRead; ring_buffer_size_t framesToTransfer;
ring_buffer_size_t framesTransferred;
do { do {
avail = PaUtil_GetRingBufferReadAvailable( &blio->inputRingBuffer ); framesAvailable = PaUtil_GetRingBufferReadAvailable( &blio->inputRingBuffer );
/* /*
printf( "Read Buffer is %%%g full: %ld of %ld.\n", printf( "Read Buffer is %%%g full: %ld of %ld.\n",
100 * (float)avail / (float) blio->inputRingBuffer.bufferSize, 100 * (float)avail / (float) blio->inputRingBuffer.bufferSize,
avail, blio->inputRingBuffer.bufferSize ); framesAvailable, blio->inputRingBuffer.bufferSize );
*/ */
if( avail == 0 ) { if( framesAvailable == 0 ) {
#ifdef PA_MAC_BLIO_MUTEX #ifdef PA_MAC_BLIO_MUTEX
/**block when empty*/ /**block when empty*/
ret = UNIX_ERR( pthread_mutex_lock( &blio->inputMutex ) ); ret = UNIX_ERR( pthread_mutex_lock( &blio->inputMutex ) );
@ -441,14 +454,13 @@ PaError ReadStream( PaStream* stream,
Pa_Sleep( PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL ); Pa_Sleep( PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL );
#endif #endif
} }
} while( avail == 0 ); } while( framesAvailable == 0 );
toRead = MIN( avail, frames * blio->inputSampleSizeActual * blio->inChan ); framesToTransfer = MIN( framesAvailable, framesRequested );
toRead -= toRead % blio->inputSampleSizeActual * blio->inChan ; PaUtil_ReadRingBuffer( &blio->inputRingBuffer, (void *)cbuf, framesToTransfer );
PaUtil_ReadRingBuffer( &blio->inputRingBuffer, (void *)cbuf, toRead ); cbuf += framesToTransfer * blio->inputSampleSizeActual * blio->inChan;
cbuf += toRead; framesRequested -= framesToTransfer;
frames -= toRead / ( blio->inputSampleSizeActual * blio->inChan );
if( toRead == avail ) { if( framesToTransfer == framesAvailable ) {
#ifdef PA_MAC_BLIO_MUTEX #ifdef PA_MAC_BLIO_MUTEX
/* we just emptied the buffer, so we need to mark it as empty. */ /* we just emptied the buffer, so we need to mark it as empty. */
ret = blioSetIsInputEmpty( blio, true ); ret = blioSetIsInputEmpty( blio, true );
@ -457,8 +469,10 @@ PaError ReadStream( PaStream* stream,
/* of course, in the meantime, the callback may have put some sats /* of course, in the meantime, the callback may have put some sats
in, so in, so
so check for that, too, to avoid a race condition. */ so check for that, too, to avoid a race condition. */
/* FIXME - this does not seem to fix any race condition. */
if( PaUtil_GetRingBufferReadAvailable( &blio->inputRingBuffer ) ) { if( PaUtil_GetRingBufferReadAvailable( &blio->inputRingBuffer ) ) {
blioSetIsInputEmpty( blio, false ); blioSetIsInputEmpty( blio, false );
/* FIXME - why check? ret has not been set? */
if( ret ) if( ret )
return ret; return ret;
} }
@ -468,6 +482,7 @@ PaError ReadStream( PaStream* stream,
/* Report either paNoError or paInputOverflowed. */ /* Report either paNoError or paInputOverflowed. */
/* may also want to report other errors, but this is non-standard. */ /* may also want to report other errors, but this is non-standard. */
/* FIXME should not clobber ret, use if(blio->statusFlags & paInputOverflow) */
ret = blio->statusFlags & paInputOverflow; ret = blio->statusFlags & paInputOverflow;
/* report underflow only once: */ /* report underflow only once: */
@ -482,25 +497,27 @@ PaError ReadStream( PaStream* stream,
PaError WriteStream( PaStream* stream, PaError WriteStream( PaStream* stream,
const void *buffer, const void *buffer,
unsigned long frames ) unsigned long framesRequested )
{ {
PaMacBlio *blio = & ((PaMacCoreStream*)stream) -> blio; PaMacBlio *blio = & ((PaMacCoreStream*)stream) -> blio;
char *cbuf = (char *) buffer; char *cbuf = (char *) buffer;
PaError ret = paNoError; PaError ret = paNoError;
VVDBUG(("WriteStream()\n")); VVDBUG(("WriteStream()\n"));
while( frames > 0 ) { while( framesRequested > 0 ) {
long avail = 0; ring_buffer_size_t framesAvailable;
long toWrite; ring_buffer_size_t framesToTransfer;
ring_buffer_size_t framesTransferred;
do { do {
avail = PaUtil_GetRingBufferWriteAvailable( &blio->outputRingBuffer ); framesAvailable = PaUtil_GetRingBufferWriteAvailable( &blio->outputRingBuffer );
/* /*
printf( "Write Buffer is %%%g full: %ld of %ld.\n", printf( "Write Buffer is %%%g full: %ld of %ld.\n",
100 - 100 * (float)avail / (float) blio->outputRingBuffer.bufferSize, 100 - 100 * (float)avail / (float) blio->outputRingBuffer.bufferSize,
avail, blio->outputRingBuffer.bufferSize ); framesAvailable, blio->outputRingBuffer.bufferSize );
*/ */
if( avail == 0 ) { if( framesAvailable == 0 ) {
#ifdef PA_MAC_BLIO_MUTEX #ifdef PA_MAC_BLIO_MUTEX
/*block while full*/ /*block while full*/
ret = UNIX_ERR( pthread_mutex_lock( &blio->outputMutex ) ); ret = UNIX_ERR( pthread_mutex_lock( &blio->outputMutex ) );
@ -518,16 +535,15 @@ PaError WriteStream( PaStream* stream,
Pa_Sleep( PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL ); Pa_Sleep( PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL );
#endif #endif
} }
} while( avail == 0 ); } while( framesAvailable == 0 );
toWrite = MIN( avail, frames * blio->outputSampleSizeActual * blio->outChan ); framesToTransfer = MIN( framesAvailable, framesRequested );
toWrite -= toWrite % blio->outputSampleSizeActual * blio->outChan ; PaUtil_WriteRingBuffer( &blio->outputRingBuffer, (void *)cbuf, framesToTransfer );
PaUtil_WriteRingBuffer( &blio->outputRingBuffer, (void *)cbuf, toWrite ); cbuf += framesToTransfer * blio->outputSampleSizeActual * blio->outChan;
cbuf += toWrite; framesRequested -= framesToTransfer;
frames -= toWrite / ( blio->outputSampleSizeActual * blio->outChan );
#ifdef PA_MAC_BLIO_MUTEX #ifdef PA_MAC_BLIO_MUTEX
if( toWrite == avail ) { if( framesToTransfer == framesAvailable ) {
/* we just filled up the buffer, so we need to mark it as filled. */ /* we just filled up the buffer, so we need to mark it as filled. */
ret = blioSetIsOutputFull( blio, true ); ret = blioSetIsOutputFull( blio, true );
if( ret ) if( ret )
@ -536,6 +552,7 @@ PaError WriteStream( PaStream* stream,
so check for that, too, to avoid a race condition. */ so check for that, too, to avoid a race condition. */
if( PaUtil_GetRingBufferWriteAvailable( &blio->outputRingBuffer ) ) { if( PaUtil_GetRingBufferWriteAvailable( &blio->outputRingBuffer ) ) {
blioSetIsOutputFull( blio, false ); blioSetIsOutputFull( blio, false );
/* FIXME remove or review this code, does not fix race, ret not set! */
if( ret ) if( ret )
return ret; return ret;
} }
@ -545,6 +562,7 @@ PaError WriteStream( PaStream* stream,
/* Report either paNoError or paOutputUnderflowed. */ /* Report either paNoError or paOutputUnderflowed. */
/* may also want to report other errors, but this is non-standard. */ /* may also want to report other errors, but this is non-standard. */
/* FIXME should not clobber ret, use if(blio->statusFlags & paInputOverflow) */
ret = blio->statusFlags & paOutputUnderflow; ret = blio->statusFlags & paOutputUnderflow;
/* report underflow only once: */ /* report underflow only once: */
@ -562,11 +580,12 @@ PaError WriteStream( PaStream* stream,
void waitUntilBlioWriteBufferIsFlushed( PaMacBlio *blio ) void waitUntilBlioWriteBufferIsFlushed( PaMacBlio *blio )
{ {
if( blio->outputRingBuffer.buffer ) { if( blio->outputRingBuffer.buffer ) {
long avail = PaUtil_GetRingBufferWriteAvailable( &blio->outputRingBuffer ); /* FIXME loop until PaUtil_GetRingBufferReadAvailable==0 */
while( avail != blio->outputRingBuffer.bufferSize ) { ring_buffer_size_t framesAvailable = PaUtil_GetRingBufferWriteAvailable( &blio->outputRingBuffer );
if( avail == 0 ) while( framesAvailable != blio->outputRingBuffer.bufferSize ) {
if( framesAvailable == 0 )
Pa_Sleep( PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL ); Pa_Sleep( PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL );
avail = PaUtil_GetRingBufferWriteAvailable( &blio->outputRingBuffer ); framesAvailable = PaUtil_GetRingBufferWriteAvailable( &blio->outputRingBuffer );
} }
} }
} }
@ -577,8 +596,7 @@ signed long GetStreamReadAvailable( PaStream* stream )
PaMacBlio *blio = & ((PaMacCoreStream*)stream) -> blio; PaMacBlio *blio = & ((PaMacCoreStream*)stream) -> blio;
VVDBUG(("GetStreamReadAvailable()\n")); VVDBUG(("GetStreamReadAvailable()\n"));
return PaUtil_GetRingBufferReadAvailable( &blio->inputRingBuffer ) return PaUtil_GetRingBufferReadAvailable( &blio->inputRingBuffer );
/ ( blio->inputSampleSizeActual * blio->inChan );
} }
@ -587,7 +605,6 @@ signed long GetStreamWriteAvailable( PaStream* stream )
PaMacBlio *blio = & ((PaMacCoreStream*)stream) -> blio; PaMacBlio *blio = & ((PaMacCoreStream*)stream) -> blio;
VVDBUG(("GetStreamWriteAvailable()\n")); VVDBUG(("GetStreamWriteAvailable()\n"));
return PaUtil_GetRingBufferWriteAvailable( &blio->outputRingBuffer ) return PaUtil_GetRingBufferWriteAvailable( &blio->outputRingBuffer );
/ ( blio->outputSampleSizeActual * blio->outChan );
} }

View file

@ -64,7 +64,7 @@
#include "pa_mac_core_utilities.h" #include "pa_mac_core_utilities.h"
/* /*
* Number of miliseconds to busy wait whil waiting for data in blocking calls. * Number of milliseconds to busy wait while waiting for data in blocking calls.
*/ */
#define PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL (5) #define PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL (5)
/* /*
@ -79,7 +79,7 @@
typedef struct { typedef struct {
PaUtilRingBuffer inputRingBuffer; PaUtilRingBuffer inputRingBuffer;
PaUtilRingBuffer outputRingBuffer; PaUtilRingBuffer outputRingBuffer;
size_t ringBufferFrames; ring_buffer_size_t ringBufferFrames;
PaSampleFormat inputSampleFormat; PaSampleFormat inputSampleFormat;
size_t inputSampleSizeActual; size_t inputSampleSizeActual;
size_t inputSampleSizePow2; size_t inputSampleSizePow2;
@ -87,8 +87,6 @@ typedef struct {
size_t outputSampleSizeActual; size_t outputSampleSizeActual;
size_t outputSampleSizePow2; size_t outputSampleSizePow2;
size_t framesPerBuffer;
int inChan; int inChan;
int outChan; int outChan;
@ -117,8 +115,7 @@ PaError initializeBlioRingBuffers(
PaMacBlio *blio, PaMacBlio *blio,
PaSampleFormat inputSampleFormat, PaSampleFormat inputSampleFormat,
PaSampleFormat outputSampleFormat, PaSampleFormat outputSampleFormat,
size_t framesPerBuffer, long ringBufferSizeInFrames,
long ringBufferSize,
int inChan, int inChan,
int outChan ); int outChan );
PaError destroyBlioRingBuffers( PaMacBlio *blio ); PaError destroyBlioRingBuffers( PaMacBlio *blio );