📄 pa_process.c
字号:
*streamCallbackResult = bp->streamCallback( userInput, userOutput,
bp->framesPerUserBuffer, bp->timeInfo,
bp->callbackStatusFlags, bp->userData );
if( *streamCallbackResult == paAbort )
{
/* if the callback returned paAbort, we disregard its output */
}
else
{
bp->timeInfo->outputBufferDacTime += bp->framesPerUserBuffer * bp->samplePeriod;
bp->framesInTempOutputBuffer = bp->framesPerUserBuffer;
}
}
if( bp->framesInTempOutputBuffer > 0 )
{
/* convert frameCount frames from user buffer to host buffer */
frameCount = PA_MIN_( bp->framesInTempOutputBuffer, framesToGo );
if( bp->userOutputIsInterleaved )
{
srcBytePtr = ((unsigned char*)bp->tempOutputBuffer) +
bp->bytesPerUserOutputSample * bp->outputChannelCount *
(bp->framesPerUserBuffer - bp->framesInTempOutputBuffer);
srcSampleStrideSamples = bp->outputChannelCount;
srcChannelStrideBytes = bp->bytesPerUserOutputSample;
}
else /* user output is not interleaved */
{
srcBytePtr = ((unsigned char*)bp->tempOutputBuffer) +
bp->bytesPerUserOutputSample *
(bp->framesPerUserBuffer - bp->framesInTempOutputBuffer);
srcSampleStrideSamples = 1;
srcChannelStrideBytes = bp->framesPerUserBuffer * 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;
}
bp->framesInTempOutputBuffer -= frameCount;
}
else
{
/* no more user data is available because the callback has returned
paComplete or paAbort. Fill the remainder of the host buffer
with zeros.
*/
frameCount = framesToGo;
for( i=0; i<bp->outputChannelCount; ++i )
{
bp->outputZeroer( hostOutputChannels[i].data,
hostOutputChannels[i].stride,
frameCount );
/* advance dest ptr for next iteration */
hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) +
frameCount * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample;
}
}
framesProcessed += frameCount;
framesToGo -= frameCount;
}while( framesToGo > 0 );
return framesProcessed;
}
/* CopyTempOutputBuffersToHostOutputBuffers is called from AdaptingProcess to copy frames from
tempOutputBuffer to hostOutputChannels. This includes data conversion
and interleaving.
*/
static void CopyTempOutputBuffersToHostOutputBuffers( PaUtilBufferProcessor *bp)
{
unsigned long maxFramesToCopy;
PaUtilChannelDescriptor *hostOutputChannels;
unsigned int frameCount;
unsigned char *srcBytePtr;
unsigned int srcSampleStrideSamples; /* stride from one sample to the next within a channel, in samples */
unsigned int srcChannelStrideBytes; /* stride from one channel to the next, in bytes */
unsigned int i;
/* copy frames from user to host output buffers */
while( bp->framesInTempOutputBuffer > 0 &&
((bp->hostOutputFrameCount[0] + bp->hostOutputFrameCount[1]) > 0) )
{
maxFramesToCopy = bp->framesInTempOutputBuffer;
/* select the output buffer set (1st or 2nd) */
if( bp->hostOutputFrameCount[0] > 0 )
{
hostOutputChannels = bp->hostOutputChannels[0];
frameCount = PA_MIN_( bp->hostOutputFrameCount[0], maxFramesToCopy );
}
else
{
hostOutputChannels = bp->hostOutputChannels[1];
frameCount = PA_MIN_( bp->hostOutputFrameCount[1], maxFramesToCopy );
}
if( bp->userOutputIsInterleaved )
{
srcBytePtr = ((unsigned char*)bp->tempOutputBuffer) +
bp->bytesPerUserOutputSample * bp->outputChannelCount *
(bp->framesPerUserBuffer - bp->framesInTempOutputBuffer);
srcSampleStrideSamples = bp->outputChannelCount;
srcChannelStrideBytes = bp->bytesPerUserOutputSample;
}
else /* user output is not interleaved */
{
srcBytePtr = ((unsigned char*)bp->tempOutputBuffer) +
bp->bytesPerUserOutputSample *
(bp->framesPerUserBuffer - bp->framesInTempOutputBuffer);
srcSampleStrideSamples = 1;
srcChannelStrideBytes = bp->framesPerUserBuffer * 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( bp->hostOutputFrameCount[0] > 0 )
bp->hostOutputFrameCount[0] -= frameCount;
else
bp->hostOutputFrameCount[1] -= frameCount;
bp->framesInTempOutputBuffer -= frameCount;
}
}
/*
AdaptingProcess is a full duplex adapting buffer processor. It converts
data from the temporary output buffer into the host output buffers, then
from the host input buffers into the temporary input buffers. Calling the
streamCallback when necessary.
When processPartialUserBuffers is 0, all available input data will be
consumed and all available output space will be filled. When
processPartialUserBuffers is non-zero, as many full user buffers
as possible will be processed, but partial buffers will not be consumed.
*/
static unsigned long AdaptingProcess( PaUtilBufferProcessor *bp,
int *streamCallbackResult, int processPartialUserBuffers )
{
void *userInput, *userOutput;
unsigned long framesProcessed = 0;
unsigned long framesAvailable;
unsigned long endProcessingMinFrameCount;
unsigned long maxFramesToCopy;
PaUtilChannelDescriptor *hostInputChannels, *hostOutputChannels;
unsigned int frameCount;
unsigned char *destBytePtr;
unsigned int destSampleStrideSamples; /* stride from one sample to the next within a channel, in samples */
unsigned int destChannelStrideBytes; /* stride from one channel to the next, in bytes */
unsigned int i, j;
framesAvailable = bp->hostInputFrameCount[0] + bp->hostInputFrameCount[1];/* this is assumed to be the same as the output buffer's frame count */
if( processPartialUserBuffers )
endProcessingMinFrameCount = 0;
else
endProcessingMinFrameCount = (bp->framesPerUserBuffer - 1);
/* Fill host output with remaining frames in user output (tempOutputBuffer) */
CopyTempOutputBuffersToHostOutputBuffers( bp );
while( framesAvailable > endProcessingMinFrameCount )
{
if( bp->framesInTempOutputBuffer == 0 && *streamCallbackResult != paContinue )
{
/* the callback will not be called any more, so zero what remains
of the host output buffers */
for( i=0; i<2; ++i )
{
frameCount = bp->hostOutputFrameCount[i];
if( frameCount > 0 )
{
hostOutputChannels = bp->hostOutputChannels[i];
for( j=0; j<bp->outputChannelCount; ++j )
{
bp->outputZeroer( hostOutputChannels[j].data,
hostOutputChannels[j].stride,
frameCount );
/* advance dest ptr for next iteration */
hostOutputChannels[j].data = ((unsigned char*)hostOutputChannels[j].data) +
frameCount * hostOutputChannels[j].stride * bp->bytesPerHostOutputSample;
}
bp->hostOutputFrameCount[i] = 0;
}
}
}
/* copy frames from host to user input buffers */
while( bp->framesInTempInputBuffer < bp->framesPerUserBuffer &&
((bp->hostInputFrameCount[0] + bp->hostInputFrameCount[1]) > 0) )
{
maxFramesToCopy = bp->framesPerUserBuffer - bp->framesInTempInputBuffer;
/* select the input buffer set (1st or 2nd) */
if( bp->hostInputFrameCount[0] > 0 )
{
hostInputChannels = bp->hostInputChannels[0];
frameCount = PA_MIN_( bp->hostInputFrameCount[0], maxFramesToCopy );
}
else
{
hostInputChannels = bp->hostInputChannels[1];
frameCount = PA_MIN_( bp->hostInputFrameCount[1], maxFramesToCopy );
}
/* configure conversion destination pointers */
if( bp->userInputIsInterleaved )
{
destBytePtr = ((unsigned char*)bp->tempInputBuffer) +
bp->bytesPerUserInputSample * bp->inputChannelCount *
bp->framesInTempInputBuffer;
destSampleStrideSamples = bp->inputChannelCount;
destChannelStrideBytes = bp->bytesPerUserInputSample;
}
else /* user input is not interleaved */
{
destBytePtr = ((unsigned char*)bp->tempInputBuffer) +
bp->bytesPerUserInputSample * bp->framesInTempInputBuffer;
destSampleStrideSamples = 1;
destChannelStrideBytes = bp->framesPerUserBuffer * bp->bytesPerUserInputSample;
}
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;
}
if( bp->hostInputFrameCount[0] > 0 )
bp->hostInputFrameCount[0] -= frameCount;
else
bp->hostInputFrameCount[1] -= frameCount;
bp->framesInTempInputBuffer += frameCount;
/* update framesAvailable and framesProcessed based on input consumed
unless something is very wrong this will also correspond to the
amount of output generated */
framesAvailable -= frameCount;
framesProcessed += frameCount;
}
/* call streamCallback */
if( bp->framesInTempInputBuffer == bp->framesPerUserBuffer &&
bp->framesInTempOutputBuffer == 0 )
{
if( *streamCallbackResult == paContinue )
{
/* setup userInput */
if( bp->userInputIsInterleaved )
{
userInput = bp->tempInputBuffer;
}
else /* user input is not interleaved */
{
for( i = 0; i < bp->inputChannelCount; ++i )
{
bp->tempInputBufferPtrs[i] = ((unsigned char*)bp->tempInputBuffer) +
i * bp->framesPerUserBuffer * bp->bytesPerUserInputSample;
}
userInput = bp->tempInputBufferPtrs;
}
/* setup userOutput */
if( bp->userOutputIsInterleaved )
{
userOutput = bp->tempOutputBuffer;
}
else /* user output is not interleaved */
{
for( i = 0; i < bp->outputChannelCount; ++i )
{
bp->tempOutputBufferPtrs[i] = ((unsigned char*)bp->tempOutputBuffer) +
i * bp->framesPerUserBuffer * bp->bytesPerUserOutputSample;
}
userOutput = bp->tempOutputBufferPtrs;
}
/* call streamCallback */
*streamCallbackResult = bp->streamCallback( userInput, userOutput,
bp->framesPerUserBuffer, bp->timeInfo,
bp->callbackStatusFlags, bp->userData );
bp->timeInfo->inputBufferAdcTime += bp->framesPerUserBuffer * bp->samplePeriod;
bp->timeInfo->outputBufferDacTime += bp->framesPerUserBuffer * bp->samplePeriod;
bp->framesInTempInputBuffer = 0;
if( *streamCallbackResult == paAbort )
bp->framesInTempOutputBuffer = 0;
else
bp->framesInTempOutputBuffer = bp->framesPerUserBuffer;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -