From 1c289f924e981857b5a413ff39651bd7af777121 Mon Sep 17 00:00:00 2001 From: dmitrykos Date: Sat, 10 Jul 2010 17:41:25 +0000 Subject: [PATCH] optimized PA processor for case when host and user buffer match by type and size, now host buffer pointer will be passed to user space directly, additional copying of audio input/output data is thus avoided. asio: apply paNonInterleaved flag on host formats for callback mode (required for processor compatibility). --- src/common/pa_process.c | 187 ++++++++++++++++++++++++----------- src/common/pa_process.h | 4 + src/hostapi/asio/pa_asio.cpp | 4 +- 3 files changed, 137 insertions(+), 58 deletions(-) diff --git a/src/common/pa_process.c b/src/common/pa_process.c index 568c774..01a9ee2 100644 --- a/src/common/pa_process.c +++ b/src/common/pa_process.c @@ -263,7 +263,10 @@ PaError PaUtil_InitializeBufferProcessor( PaUtilBufferProcessor* bp, bp->inputZeroer = PaUtil_SelectZeroer( hostInputSampleFormat ); bp->userInputIsInterleaved = (userInputSampleFormat & paNonInterleaved)?0:1; + + bp->hostInputIsInterleaved = (hostInputSampleFormat & paNonInterleaved)?0:1; + bp->userInputSampleFormatIsEqualToHost = ((userInputSampleFormat & ~paNonInterleaved) == (hostInputSampleFormat & ~paNonInterleaved)); tempInputBufferSize = bp->framesPerTempBuffer * bp->bytesPerUserInputSample * inputChannelCount; @@ -331,6 +334,10 @@ PaError PaUtil_InitializeBufferProcessor( PaUtilBufferProcessor* bp, bp->userOutputIsInterleaved = (userOutputSampleFormat & paNonInterleaved)?0:1; + bp->hostOutputIsInterleaved = (hostOutputSampleFormat & paNonInterleaved)?0:1; + + bp->userOutputSampleFormatIsEqualToHost = ((userOutputSampleFormat & ~paNonInterleaved) == (hostOutputSampleFormat & ~paNonInterleaved)); + tempOutputBufferSize = bp->framesPerTempBuffer * bp->bytesPerUserOutputSample * outputChannelCount; @@ -495,6 +502,7 @@ void PaUtil_SetInterleavedInputChannels( PaUtilBufferProcessor* bp, assert( firstChannel < bp->inputChannelCount ); assert( firstChannel + channelCount <= bp->inputChannelCount ); + assert( bp->hostInputIsInterleaved ); for( i=0; i< channelCount; ++i ) { @@ -509,6 +517,7 @@ void PaUtil_SetNonInterleavedInputChannel( PaUtilBufferProcessor* bp, unsigned int channel, void *data ) { assert( channel < bp->inputChannelCount ); + assert( !bp->hostInputIsInterleaved ); bp->hostInputChannels[0][channel].data = data; bp->hostInputChannels[0][channel].stride = 1; @@ -544,6 +553,7 @@ void PaUtil_Set2ndInterleavedInputChannels( PaUtilBufferProcessor* bp, assert( firstChannel < bp->inputChannelCount ); assert( firstChannel + channelCount <= bp->inputChannelCount ); + assert( bp->hostInputIsInterleaved ); for( i=0; i< channelCount; ++i ) { @@ -558,6 +568,7 @@ void PaUtil_Set2ndNonInterleavedInputChannel( PaUtilBufferProcessor* bp, unsigned int channel, void *data ) { assert( channel < bp->inputChannelCount ); + assert( !bp->hostInputIsInterleaved ); bp->hostInputChannels[1][channel].data = data; bp->hostInputChannels[1][channel].stride = 1; @@ -605,6 +616,7 @@ void PaUtil_SetInterleavedOutputChannels( PaUtilBufferProcessor* bp, assert( firstChannel < bp->outputChannelCount ); assert( firstChannel + channelCount <= bp->outputChannelCount ); + assert( bp->hostOutputIsInterleaved ); for( i=0; i< channelCount; ++i ) { @@ -618,6 +630,7 @@ void PaUtil_SetNonInterleavedOutputChannel( PaUtilBufferProcessor* bp, unsigned int channel, void *data ) { assert( channel < bp->outputChannelCount ); + assert( !bp->hostOutputIsInterleaved ); PaUtil_SetOutputChannel( bp, channel, data, 1 ); } @@ -653,6 +666,7 @@ void PaUtil_Set2ndInterleavedOutputChannels( PaUtilBufferProcessor* bp, assert( firstChannel < bp->outputChannelCount ); assert( firstChannel + channelCount <= bp->outputChannelCount ); + assert( bp->hostOutputIsInterleaved ); for( i=0; i< channelCount; ++i ) { @@ -666,6 +680,7 @@ void PaUtil_Set2ndNonInterleavedOutputChannel( PaUtilBufferProcessor* bp, unsigned int channel, void *data ) { assert( channel < bp->outputChannelCount ); + assert( !bp->hostOutputIsInterleaved ); PaUtil_Set2ndOutputChannel( bp, channel, data, 1 ); } @@ -722,6 +737,8 @@ static unsigned long NonAdaptingProcess( PaUtilBufferProcessor *bp, unsigned long frameCount; unsigned long framesToGo = framesToProcess; unsigned long framesProcessed = 0; + int skipOutputConvert = 0; + int skipInputConvert = 0; if( *streamCallbackResult == paContinue ) @@ -738,18 +755,25 @@ static unsigned long NonAdaptingProcess( PaUtilBufferProcessor *bp, } else /* there are input channels */ { - /* - could use more elaborate logic here and sometimes process - buffers in-place. - */ - + destBytePtr = (unsigned char *)bp->tempInputBuffer; if( bp->userInputIsInterleaved ) { destSampleStrideSamples = bp->inputChannelCount; destChannelStrideBytes = bp->bytesPerUserInputSample; - userInput = bp->tempInputBuffer; + + /* process host buffer directly, or use temp buffer if formats differ or host buffer non-interleaved */ + if( bp->userInputSampleFormatIsEqualToHost && bp->hostInputIsInterleaved ) + { + userInput = hostInputChannels[0].data; + destBytePtr = (unsigned char *)hostInputChannels[0].data; + skipInputConvert = 1; + } + else + { + userInput = bp->tempInputBuffer; + } } else /* user input is not interleaved */ { @@ -757,10 +781,21 @@ static unsigned long NonAdaptingProcess( PaUtilBufferProcessor *bp, destChannelStrideBytes = frameCount * bp->bytesPerUserInputSample; /* setup non-interleaved ptrs */ - for( i=0; iinputChannelCount; ++i ) + if( bp->userInputSampleFormatIsEqualToHost && !bp->hostInputIsInterleaved ) { - bp->tempInputBufferPtrs[i] = ((unsigned char*)bp->tempInputBuffer) + - i * bp->bytesPerUserInputSample * frameCount; + for( i=0; iinputChannelCount; ++i ) + { + bp->tempInputBufferPtrs[i] = hostInputChannels[i].data; + } + skipInputConvert = 1; + } + else + { + for( i=0; iinputChannelCount; ++i ) + { + bp->tempInputBufferPtrs[i] = ((unsigned char*)bp->tempInputBuffer) + + i * bp->bytesPerUserInputSample * frameCount; + } } userInput = bp->tempInputBufferPtrs; @@ -778,19 +813,31 @@ static unsigned long NonAdaptingProcess( PaUtilBufferProcessor *bp, } } else - { - for( i=0; iinputChannelCount; ++i ) + { + if( skipInputConvert ) { - bp->inputConverter( destBytePtr, destSampleStrideSamples, - hostInputChannels[i].data, - hostInputChannels[i].stride, - frameCount, &bp->ditherGenerator ); - - destBytePtr += destChannelStrideBytes; /* skip to next destination channel */ - - /* advance src ptr for next iteration */ - hostInputChannels[i].data = ((unsigned char*)hostInputChannels[i].data) + - frameCount * hostInputChannels[i].stride * bp->bytesPerHostInputSample; + for( i=0; iinputChannelCount; ++i ) + { + /* advance src ptr for next iteration */ + hostInputChannels[i].data = ((unsigned char*)hostInputChannels[i].data) + + frameCount * hostInputChannels[i].stride * bp->bytesPerHostInputSample; + } + } + else + { + for( i=0; iinputChannelCount; ++i ) + { + bp->inputConverter( destBytePtr, destSampleStrideSamples, + hostInputChannels[i].data, + hostInputChannels[i].stride, + frameCount, &bp->ditherGenerator ); + + destBytePtr += destChannelStrideBytes; /* skip to next destination channel */ + + /* advance src ptr for next iteration */ + hostInputChannels[i].data = ((unsigned char*)hostInputChannels[i].data) + + frameCount * hostInputChannels[i].stride * bp->bytesPerHostInputSample; + } } } } @@ -805,14 +852,34 @@ static unsigned long NonAdaptingProcess( PaUtilBufferProcessor *bp, { if( bp->userOutputIsInterleaved ) { - userOutput = bp->tempOutputBuffer; + /* process host buffer directly, or use temp buffer if formats differ or host buffer non-interleaved */ + if( bp->userOutputSampleFormatIsEqualToHost && bp->hostOutputIsInterleaved ) + { + userOutput = hostOutputChannels[0].data; + skipOutputConvert = 1; + } + else + { + userOutput = bp->tempOutputBuffer; + } } else /* user output is not interleaved */ { - for( i = 0; i < bp->outputChannelCount; ++i ) + if( bp->userOutputSampleFormatIsEqualToHost && !bp->hostOutputIsInterleaved ) { - bp->tempOutputBufferPtrs[i] = ((unsigned char*)bp->tempOutputBuffer) + - i * bp->bytesPerUserOutputSample * frameCount; + for( i=0; ioutputChannelCount; ++i ) + { + bp->tempOutputBufferPtrs[i] = hostOutputChannels[i].data; + } + skipOutputConvert = 1; + } + else + { + for( i=0; ioutputChannelCount; ++i ) + { + bp->tempOutputBufferPtrs[i] = ((unsigned char*)bp->tempOutputBuffer) + + i * bp->bytesPerUserOutputSample * frameCount; + } } userOutput = bp->tempOutputBufferPtrs; @@ -836,37 +903,45 @@ static unsigned long NonAdaptingProcess( PaUtilBufferProcessor *bp, if( bp->outputChannelCount != 0 && bp->hostOutputChannels[0][0].data ) { - /* - could use more elaborate logic here and sometimes process - buffers in-place. - */ - - srcBytePtr = (unsigned char *)bp->tempOutputBuffer; - - if( bp->userOutputIsInterleaved ) - { - srcSampleStrideSamples = bp->outputChannelCount; - srcChannelStrideBytes = bp->bytesPerUserOutputSample; - } - else /* user output is not interleaved */ - { - srcSampleStrideSamples = 1; - srcChannelStrideBytes = frameCount * bp->bytesPerUserOutputSample; - } - - for( i=0; ioutputChannelCount; ++i ) - { - bp->outputConverter( hostOutputChannels[i].data, - hostOutputChannels[i].stride, - srcBytePtr, srcSampleStrideSamples, - frameCount, &bp->ditherGenerator ); - - srcBytePtr += srcChannelStrideBytes; /* skip to next source channel */ - - /* advance dest ptr for next iteration */ - hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) + - frameCount * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample; - } + if( skipOutputConvert ) + { + for( i=0; ioutputChannelCount; ++i ) + { + /* advance dest ptr for next iteration */ + hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) + + frameCount * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample; + } + } + else + { + + srcBytePtr = (unsigned char *)bp->tempOutputBuffer; + + if( bp->userOutputIsInterleaved ) + { + srcSampleStrideSamples = bp->outputChannelCount; + srcChannelStrideBytes = bp->bytesPerUserOutputSample; + } + else /* user output is not interleaved */ + { + srcSampleStrideSamples = 1; + srcChannelStrideBytes = frameCount * bp->bytesPerUserOutputSample; + } + + for( i=0; ioutputChannelCount; ++i ) + { + bp->outputConverter( hostOutputChannels[i].data, + hostOutputChannels[i].stride, + srcBytePtr, srcSampleStrideSamples, + frameCount, &bp->ditherGenerator ); + + srcBytePtr += srcChannelStrideBytes; /* skip to next source channel */ + + /* advance dest ptr for next iteration */ + hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) + + frameCount * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample; + } + } } framesProcessed += frameCount; diff --git a/src/common/pa_process.h b/src/common/pa_process.h index 9aef25e..eb44749 100644 --- a/src/common/pa_process.h +++ b/src/common/pa_process.h @@ -256,6 +256,8 @@ typedef struct { PaUtilHostBufferSizeMode hostBufferSizeMode; int useNonAdaptingProcess; + int userOutputSampleFormatIsEqualToHost; + int userInputSampleFormatIsEqualToHost; unsigned long framesPerTempBuffer; unsigned int inputChannelCount; @@ -287,12 +289,14 @@ typedef struct { PaStreamCallbackFlags callbackStatusFlags; + int hostInputIsInterleaved; unsigned long hostInputFrameCount[2]; PaUtilChannelDescriptor *hostInputChannels[2]; /**< pointers to arrays of channel descriptors. pointers are NULL for half-duplex output processing. hostInputChannels[i].data is NULL when the caller calls PaUtil_SetNoInput() */ + int hostOutputIsInterleaved; unsigned long hostOutputFrameCount[2]; PaUtilChannelDescriptor *hostOutputChannels[2]; /**< pointers to arrays of channel descriptors. pointers are NULL for half-duplex input processing. diff --git a/src/hostapi/asio/pa_asio.cpp b/src/hostapi/asio/pa_asio.cpp index 01096cf..009fbfa 100644 --- a/src/hostapi/asio/pa_asio.cpp +++ b/src/hostapi/asio/pa_asio.cpp @@ -2528,8 +2528,8 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, else /* Using callback interface... */ { result = PaUtil_InitializeBufferProcessor( &stream->bufferProcessor, - inputChannelCount, inputSampleFormat, hostInputSampleFormat, - outputChannelCount, outputSampleFormat, hostOutputSampleFormat, + inputChannelCount, inputSampleFormat, (hostInputSampleFormat | paNonInterleaved), + outputChannelCount, outputSampleFormat, (hostOutputSampleFormat | paNonInterleaved), sampleRate, streamFlags, framesPerBuffer, framesPerHostBuffer, paUtilFixedHostBufferSize, streamCallback, userData ); -- 2.43.0