Browse Source

Version 2.1.1

tags/2.1.1
Gary Scavone Stephen Sinclair 12 years ago
parent
commit
45906f9f72
3 changed files with 89 additions and 74 deletions
  1. +69
    -66
      RtAudio.cpp
  2. +16
    -8
      doc/doxygen/tutorial.txt
  3. +4
    -0
      doc/release.txt

+ 69
- 66
RtAudio.cpp View File

@@ -37,6 +37,7 @@
*/ */
/************************************************************************/ /************************************************************************/


// RtAudio: Version 2.1.1, 24 October 2002


#include "RtAudio.h" #include "RtAudio.h"
#include <vector> #include <vector>
@@ -1261,44 +1262,10 @@ void RtAudio :: callbackEvent( int streamId, DEVICE_ID deviceId, void *inData, v


MUTEX_LOCK(&stream->mutex); 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; i<stream->nDeviceChannels[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; RTAUDIO_CALLBACK callback = (RTAUDIO_CALLBACK) info->callback;
info->stopStream = callback(stream->userBuffer, stream->bufferSize, info->userData); 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; i<stream->nDeviceChannels[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] ) ) if ( !info->usingCallback && (stream->mode != DUPLEX || deviceId == info->device[1] ) )
info->blockTick = false; info->blockTick = false;


@@ -4130,41 +4131,17 @@ void RtAudio :: callbackEvent(int streamId, int bufferIndex, void *inData, void
} }


MUTEX_LOCK(&stream->mutex); 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; i<stream->nDeviceChannels[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 ) { if ( info->usingCallback ) {
RTAUDIO_CALLBACK callback = (RTAUDIO_CALLBACK) info->callback; RTAUDIO_CALLBACK callback = (RTAUDIO_CALLBACK) info->callback;
if ( callback(stream->userBuffer, stream->bufferSize, info->userData) ) if ( callback(stream->userBuffer, stream->bufferSize, info->userData) )
info->stopStream = true; 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 ) { if ( stream->mode == OUTPUT || stream->mode == DUPLEX ) {


bufferBytes = stream->bufferSize * formatBytes(stream->deviceFormat[0]); 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; i<stream->nDeviceChannels[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 ) if ( !info->usingCallback )
info->blockTick = false; info->blockTick = false;




+ 16
- 8
doc/doxygen/tutorial.txt View File

@@ -41,7 +41,7 @@ The RtAudio API provides both blocking (synchronous) and callback (asyncronous)


\section download Download \section download Download


Latest Release (7 October 2002): <A href="http://www-ccrma.stanford.edu/~gary/rtaudio/release/rtaudio-2.1.tar.gz">Version 2.1 (165 kB tar/gzipped)</A>
Latest Release (24 October 2002): <A href="http://www-ccrma.stanford.edu/~gary/rtaudio/release/rtaudio-2.1.1.tar.gz">Version 2.1.1 (165 kB tar/gzipped)</A>




\section start Getting Started \section start Getting Started
@@ -467,7 +467,7 @@ In this example, the stream was opened for recording with a non-zero <I>inputCha


\section duplex Duplex Mode \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 \code
// duplex.cpp // duplex.cpp
@@ -476,9 +476,18 @@ Finally, it is easy to use RtAudio for simultaneous audio input/output, or duple
#include "RtAudio.h" #include "RtAudio.h"


// Pass-through function. // 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; i<buffer_size; i++) {
// Do for two channels.
*my_buffer++ *= 0.5;
*my_buffer++ *= 0.5;
}

return 0; return 0;
} }


@@ -490,7 +499,6 @@ int main()
int n_buffers = 4; // number of internal buffers used by device int n_buffers = 4; // number of internal buffers used by device
int device = 0; // 0 indicates the default or first available device int device = 0; // 0 indicates the default or first available device
int stream; // our stream identifier int stream; // our stream identifier
double data[2];
char input; char input;
RtAudio *audio; RtAudio *audio;


@@ -506,7 +514,7 @@ int main()


try { try {
// Set the stream callback function // Set the stream callback function
audio->setStreamCallback(stream, &pass, NULL);
audio->setStreamCallback(stream, &scale, NULL);


// Start the stream // Start the stream
audio->startStream(stream); audio->startStream(stream);
@@ -537,7 +545,7 @@ int main()


When an RtAudio stream is running in duplex mode (nonzero input <I>AND</I> 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. When an RtAudio stream is running in duplex mode (nonzero input <I>AND</I> 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 <I>explicitly</I> control the calling order of the callback functions. 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 <I>explicitly</I> 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
<TD>CoreAudio</TD> <TD>CoreAudio</TD>
<TD>__MACOSX_CORE__</TD> <TD>__MACOSX_CORE__</TD>
<TD><TT>pthread, stdc++, CoreAudio</TT></TD> <TD><TT>pthread, stdc++, CoreAudio</TT></TD>
<TD><TT>cc -Wall -D__MACOSX_CORE__ -o probe probe.cpp RtAudio.cpp -framework CoreAudio -lstdc++ -lpthread</TT></TD>
<TD><TT>CC -Wall -D__MACOSX_CORE__ -o probe probe.cpp RtAudio.cpp -framework CoreAudio -lstdc++ -lpthread</TT></TD>
</TR> </TR>
<TR> <TR>
<TD>Irix</TD> <TD>Irix</TD>


+ 4
- 0
doc/release.txt View File

@@ -2,6 +2,10 @@ RtAudio - a C++ class which provides a common API for realtime audio input/outpu


By Gary P. Scavone, 2002. 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) v2.1: (7 October 2002)
- added Mac OS X CoreAudio support - added Mac OS X CoreAudio support
- added Windows ASIO support - added Windows ASIO support


Loading…
Cancel
Save