From 45906f9f72aaf6578431e68a06a0cdb0bf6ccec8 Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Wed, 9 Oct 2013 23:45:50 +0200 Subject: [PATCH] Version 2.1.1 --- RtAudio.cpp | 135 ++++++++++++++++++++------------------- doc/doxygen/tutorial.txt | 24 ++++--- doc/release.txt | 4 ++ 3 files changed, 89 insertions(+), 74 deletions(-) diff --git a/RtAudio.cpp b/RtAudio.cpp index 4a51baf..8e44ba2 100644 --- a/RtAudio.cpp +++ b/RtAudio.cpp @@ -37,6 +37,7 @@ */ /************************************************************************/ +// RtAudio: Version 2.1.1, 24 October 2002 #include "RtAudio.h" #include @@ -1261,44 +1262,10 @@ void RtAudio :: callbackEvent( int streamId, DEVICE_ID deviceId, void *inData, v MUTEX_LOCK(&stream->mutex); - if ( stream->mode == INPUT || ( stream->mode == DUPLEX && deviceId == info->device[1] ) ) { - - if (stream->doConvertBuffer[1]) { - - if ( stream->deInterleave[1] ) { - stream->deviceBuffer = (char *) stream->callbackInfo.buffers; - int bufferBytes = inBufferList->mBuffers[stream->handle[1]].mDataByteSize; - for ( int i=0; inDeviceChannels[1]; i++ ) { - memcpy(&stream->deviceBuffer[i*bufferBytes], - inBufferList->mBuffers[stream->handle[1]+i].mData, bufferBytes ); - } - } - else - stream->deviceBuffer = (char *) inBufferList->mBuffers[stream->handle[1]].mData; - - if ( stream->doByteSwap[1] ) - byteSwapBuffer(stream->deviceBuffer, - stream->bufferSize * stream->nDeviceChannels[1], - stream->deviceFormat[1]); - convertStreamBuffer(stream, INPUT); - - } - else { - memcpy(stream->userBuffer, - inBufferList->mBuffers[stream->handle[1]].mData, - inBufferList->mBuffers[stream->handle[1]].mDataByteSize ); - - if (stream->doByteSwap[1]) - byteSwapBuffer(stream->userBuffer, - stream->bufferSize * stream->nUserChannels[1], - stream->userFormat); - } - } - - // Don't invoke the user callback if duplex mode, the input/output - // devices are different, and this function is called for the output - // device. - if ( info->usingCallback && (stream->mode != DUPLEX || deviceId == info->device[1] ) ) { + // Invoke user callback first, to get fresh output data. Don't + // invoke the user callback if duplex mode, the input/output devices + // are different, and this function is called for the input device. + if ( info->usingCallback && (stream->mode != DUPLEX || deviceId == info->device[0] ) ) { RTAUDIO_CALLBACK callback = (RTAUDIO_CALLBACK) info->callback; info->stopStream = callback(stream->userBuffer, stream->bufferSize, info->userData); } @@ -1339,6 +1306,40 @@ void RtAudio :: callbackEvent( int streamId, DEVICE_ID deviceId, void *inData, v } } + if ( stream->mode == INPUT || ( stream->mode == DUPLEX && deviceId == info->device[1] ) ) { + + if (stream->doConvertBuffer[1]) { + + if ( stream->deInterleave[1] ) { + stream->deviceBuffer = (char *) stream->callbackInfo.buffers; + int bufferBytes = inBufferList->mBuffers[stream->handle[1]].mDataByteSize; + for ( int i=0; inDeviceChannels[1]; i++ ) { + memcpy(&stream->deviceBuffer[i*bufferBytes], + inBufferList->mBuffers[stream->handle[1]+i].mData, bufferBytes ); + } + } + else + stream->deviceBuffer = (char *) inBufferList->mBuffers[stream->handle[1]].mData; + + if ( stream->doByteSwap[1] ) + byteSwapBuffer(stream->deviceBuffer, + stream->bufferSize * stream->nDeviceChannels[1], + stream->deviceFormat[1]); + convertStreamBuffer(stream, INPUT); + + } + else { + memcpy(stream->userBuffer, + inBufferList->mBuffers[stream->handle[1]].mData, + inBufferList->mBuffers[stream->handle[1]].mDataByteSize ); + + if (stream->doByteSwap[1]) + byteSwapBuffer(stream->userBuffer, + stream->bufferSize * stream->nUserChannels[1], + stream->userFormat); + } + } + if ( !info->usingCallback && (stream->mode != DUPLEX || deviceId == info->device[1] ) ) info->blockTick = false; @@ -4130,41 +4131,17 @@ void RtAudio :: callbackEvent(int streamId, int bufferIndex, void *inData, void } MUTEX_LOCK(&stream->mutex); - int nChannels = stream->nDeviceChannels[0] + stream->nDeviceChannels[1]; - int bufferBytes; - ASIOBufferInfo *bufferInfos = (ASIOBufferInfo *) info->buffers; - if ( stream->mode == INPUT || stream->mode == DUPLEX ) { - - bufferBytes = stream->bufferSize * formatBytes(stream->deviceFormat[1]); - if (stream->doConvertBuffer[1]) { - - // Always interleave ASIO input data. - for ( int i=0; inDeviceChannels[1]; i++, bufferInfos++ ) - memcpy(&stream->deviceBuffer[i*bufferBytes], bufferInfos->buffers[bufferIndex], bufferBytes ); - - if ( stream->doByteSwap[1] ) - byteSwapBuffer(stream->deviceBuffer, - stream->bufferSize * stream->nDeviceChannels[1], - stream->deviceFormat[1]); - convertStreamBuffer(stream, INPUT); - - } - else { // single channel only - memcpy(stream->userBuffer, bufferInfos->buffers[bufferIndex], bufferBytes ); - - if (stream->doByteSwap[1]) - byteSwapBuffer(stream->userBuffer, - stream->bufferSize * stream->nUserChannels[1], - stream->userFormat); - } - } + // Invoke user callback first, to get fresh output data. if ( info->usingCallback ) { RTAUDIO_CALLBACK callback = (RTAUDIO_CALLBACK) info->callback; if ( callback(stream->userBuffer, stream->bufferSize, info->userData) ) info->stopStream = true; } + int nChannels = stream->nDeviceChannels[0] + stream->nDeviceChannels[1]; + int bufferBytes; + ASIOBufferInfo *bufferInfos = (ASIOBufferInfo *) info->buffers; if ( stream->mode == OUTPUT || stream->mode == DUPLEX ) { bufferBytes = stream->bufferSize * formatBytes(stream->deviceFormat[0]); @@ -4193,6 +4170,32 @@ void RtAudio :: callbackEvent(int streamId, int bufferIndex, void *inData, void } } + if ( stream->mode == INPUT || stream->mode == DUPLEX ) { + + bufferBytes = stream->bufferSize * formatBytes(stream->deviceFormat[1]); + if (stream->doConvertBuffer[1]) { + + // Always interleave ASIO input data. + for ( int i=0; inDeviceChannels[1]; i++, bufferInfos++ ) + memcpy(&stream->deviceBuffer[i*bufferBytes], bufferInfos->buffers[bufferIndex], bufferBytes ); + + if ( stream->doByteSwap[1] ) + byteSwapBuffer(stream->deviceBuffer, + stream->bufferSize * stream->nDeviceChannels[1], + stream->deviceFormat[1]); + convertStreamBuffer(stream, INPUT); + + } + else { // single channel only + memcpy(stream->userBuffer, bufferInfos->buffers[bufferIndex], bufferBytes ); + + if (stream->doByteSwap[1]) + byteSwapBuffer(stream->userBuffer, + stream->bufferSize * stream->nUserChannels[1], + stream->userFormat); + } + } + if ( !info->usingCallback ) info->blockTick = false; diff --git a/doc/doxygen/tutorial.txt b/doc/doxygen/tutorial.txt index db703ac..49bd4ad 100644 --- a/doc/doxygen/tutorial.txt +++ b/doc/doxygen/tutorial.txt @@ -41,7 +41,7 @@ The RtAudio API provides both blocking (synchronous) and callback (asyncronous) \section download Download -Latest Release (7 October 2002): Version 2.1 (165 kB tar/gzipped) +Latest Release (24 October 2002): Version 2.1.1 (165 kB tar/gzipped) \section start Getting Started @@ -467,7 +467,7 @@ In this example, the stream was opened for recording with a non-zero inputCha \section duplex Duplex Mode -Finally, it is easy to use RtAudio for simultaneous audio input/output, or duplex operation. In this example, we use a callback function and pass our recorded data directly through for playback. +Finally, it is easy to use RtAudio for simultaneous audio input/output, or duplex operation. In this example, we use a callback function and simply scale the input data before sending it back to the output. \code // duplex.cpp @@ -476,9 +476,18 @@ Finally, it is easy to use RtAudio for simultaneous audio input/output, or duple #include "RtAudio.h" // Pass-through function. -int pass(char *buffer, int buffer_size, void *) +int scale(char *buffer, int buffer_size, void *) { - // Surprise!! We do nothing to pass the data through. + // Note: do nothing here for pass through. + double *my_buffer = (double *) buffer; + + // Scale input data for output. + for (int i=0; isetStreamCallback(stream, &pass, NULL); + audio->setStreamCallback(stream, &scale, NULL); // Start the stream audio->startStream(stream); @@ -537,7 +545,7 @@ int main() When an RtAudio stream is running in duplex mode (nonzero input AND output channels), the audio write (playback) operation always occurs before the audio read (record) operation. This sequence allows the use of a single buffer to store both output and input data. -As we see with this example, the write-read sequence of operations does not preclude the use of RtAudio in situations where input data is first processed and then output through a duplex stream. When the stream buffer is first allocated, it is initialized with zeros, which produces no audible result when output to the device. In this example, anything recorded by the audio stream input will be played out during the next round of audio processing. +As we see with this example, the write-read sequence of operations does not preclude the use of RtAudio in situations where input data is first processed and then output through a duplex stream. When the stream buffer is first allocated, it is initialized with zeros, which produces no audible result when output to the device. In this example, anything recorded by the audio stream input will be scaled and played out during the next round of audio processing. Note that duplex operation can also be achieved by opening one output stream and one input stream using the same or different devices. However, there may be timing problems when attempting to use two different devices, due to possible device clock variations, unless a common external "sync" is provided. This becomes even more difficult to achieve using two separate callback streams because it is not possible to explicitly control the calling order of the callback functions. @@ -594,7 +602,7 @@ In order to compile RtAudio for a specific OS and audio API, it is necessary to CoreAudio __MACOSX_CORE__ pthread, stdc++, CoreAudio - cc -Wall -D__MACOSX_CORE__ -o probe probe.cpp RtAudio.cpp -framework CoreAudio -lstdc++ -lpthread + CC -Wall -D__MACOSX_CORE__ -o probe probe.cpp RtAudio.cpp -framework CoreAudio -lstdc++ -lpthread Irix diff --git a/doc/release.txt b/doc/release.txt index d388256..bcd3867 100644 --- a/doc/release.txt +++ b/doc/release.txt @@ -2,6 +2,10 @@ RtAudio - a C++ class which provides a common API for realtime audio input/outpu By Gary P. Scavone, 2002. +v2.1.1: (24 October 2002) +- bug fix in duplex for Mac OS X and Windows ASIO code +- duplex example change in tutorial + v2.1: (7 October 2002) - added Mac OS X CoreAudio support - added Windows ASIO support