]> Repos - portaudio/commitdiff
optimized PA processor for case when host and user buffer match by type and size...
authordmitrykos <dmitrykos@0f58301d-fd10-0410-b4af-bbb618454e57>
Sat, 10 Jul 2010 17:41:25 +0000 (17:41 +0000)
committerdmitrykos <dmitrykos@0f58301d-fd10-0410-b4af-bbb618454e57>
Sat, 10 Jul 2010 17:41:25 +0000 (17:41 +0000)
asio: apply paNonInterleaved flag on host formats for callback mode (required for processor compatibility).

src/common/pa_process.c
src/common/pa_process.h
src/hostapi/asio/pa_asio.cpp

index 568c774abdbe5c73dbe862ee433e56250f400b6d..01a9ee29ea2292dc5b8d13d6382efa8d5aed0287 100644 (file)
@@ -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; i<bp->inputChannelCount; ++i )
+                    if( bp->userInputSampleFormatIsEqualToHost && !bp->hostInputIsInterleaved )
                     {
-                        bp->tempInputBufferPtrs[i] = ((unsigned char*)bp->tempInputBuffer) +
-                            i * bp->bytesPerUserInputSample * frameCount;
+                        for( i=0; i<bp->inputChannelCount; ++i )
+                        {
+                            bp->tempInputBufferPtrs[i] = hostInputChannels[i].data;
+                        }
+                        skipInputConvert = 1;
+                    }
+                    else
+                    {
+                        for( i=0; i<bp->inputChannelCount; ++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; i<bp->inputChannelCount; ++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; i<bp->inputChannelCount; ++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; i<bp->inputChannelCount; ++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; i<bp->outputChannelCount; ++i )
+                        {
+                            bp->tempOutputBufferPtrs[i] = hostOutputChannels[i].data;
+                        }
+                        skipOutputConvert = 1;
+                    }
+                    else
+                    {
+                        for( i=0; i<bp->outputChannelCount; ++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; i<bp->outputChannelCount; ++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; i<bp->outputChannelCount; ++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; i<bp->outputChannelCount; ++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;
index 9aef25e0d4e842f377a03e6b6ab66be1f29399ae..eb44749ff83d2c8cdc8b442789fcf6e2f12efc61 100644 (file)
@@ -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.
index 01096cffae584f0793321fafb4765030245b12a9..009fbfaa38a4baafb1c391894ecc375676f15f6a 100644 (file)
@@ -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 );