Fix assert when reading or writing with non-power of 2 channels.
This commit is contained in:
parent
21d185f815
commit
110043f842
4 changed files with 121 additions and 119 deletions
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 );
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue