git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@968 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Michael Jerris 2006-03-30 01:37:57 +00:00
parent 0232f398c7
commit df1f3209d9
4 changed files with 696 additions and 696 deletions

View File

@ -55,10 +55,10 @@
/************************************************************************/ /************************************************************************/
/******** Prototypes ****************************************************/ /******** Prototypes ****************************************************/
/************************************************************************/ /************************************************************************/
static int blockingIOCallback(void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, static int blockingIOCallback(void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer,
PaTimestamp outTime, void *userData); PaTimestamp outTime, void *userData);
static PaError PABLIO_InitFIFO(RingBuffer * rbuf, long numFrames, long bytesPerFrame); static PaError PABLIO_InitFIFO(RingBuffer * rbuf, long numFrames, long bytesPerFrame);
static PaError PABLIO_TermFIFO(RingBuffer * rbuf); static PaError PABLIO_TermFIFO(RingBuffer * rbuf);
/************************************************************************/ /************************************************************************/
/******** Functions *****************************************************/ /******** Functions *****************************************************/
@ -67,52 +67,52 @@
/* Called from PortAudio. /* Called from PortAudio.
* Read and write data only if there is room in FIFOs. * Read and write data only if there is room in FIFOs.
*/ */
static int blockingIOCallback(void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, static int blockingIOCallback(void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer,
PaTimestamp outTime, void *userData) PaTimestamp outTime, void *userData)
{ {
PABLIO_Stream * data = (PABLIO_Stream *) userData; PABLIO_Stream * data = (PABLIO_Stream *) userData;
long numBytes = data->bytesPerFrame * framesPerBuffer; long numBytes = data->bytesPerFrame * framesPerBuffer;
(void) outTime; (void) outTime;
/* This may get called with NULL inputBuffer during initial setup. */ /* This may get called with NULL inputBuffer during initial setup. */
if (inputBuffer != NULL) if (inputBuffer != NULL)
{ {
RingBuffer_Write(&data->inFIFO, inputBuffer, numBytes); RingBuffer_Write(&data->inFIFO, inputBuffer, numBytes);
} }
if (outputBuffer != NULL) if (outputBuffer != NULL)
{ {
int i; int i;
int numRead = RingBuffer_Read(&data->outFIFO, outputBuffer, numBytes); int numRead = RingBuffer_Read(&data->outFIFO, outputBuffer, numBytes);
/* Zero out remainder of buffer if we run out of data. */ /* Zero out remainder of buffer if we run out of data. */
for (i = numRead; i < numBytes; i++) for (i = numRead; i < numBytes; i++)
{ {
((char *) outputBuffer)[i] = 0; ((char *) outputBuffer)[i] = 0;
} } } }
return 0; return 0;
} }
/* Allocate buffer. */ /* Allocate buffer. */
static PaError PABLIO_InitFIFO(RingBuffer * rbuf, long numFrames, long bytesPerFrame) static PaError PABLIO_InitFIFO(RingBuffer * rbuf, long numFrames, long bytesPerFrame)
{ {
long numBytes = numFrames * bytesPerFrame; long numBytes = numFrames * bytesPerFrame;
char *buffer = (char *) malloc(numBytes); char *buffer = (char *) malloc(numBytes);
if (buffer == NULL) if (buffer == NULL)
return paInsufficientMemory; return paInsufficientMemory;
memset(buffer, 0, numBytes); memset(buffer, 0, numBytes);
return (PaError) RingBuffer_Init(rbuf, numBytes, buffer); return (PaError) RingBuffer_Init(rbuf, numBytes, buffer);
} }
/* Free buffer. */ /* Free buffer. */
static PaError PABLIO_TermFIFO(RingBuffer * rbuf) static PaError PABLIO_TermFIFO(RingBuffer * rbuf)
{ {
if (rbuf->buffer) if (rbuf->buffer)
free(rbuf->buffer); free(rbuf->buffer);
rbuf->buffer = NULL; rbuf->buffer = NULL;
return paNoError; return paNoError;
} }
/************************************************************ /************************************************************
@ -121,19 +121,19 @@ static PaError PABLIO_TermFIFO(RingBuffer * rbuf)
*/ */
long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames) long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames)
{ {
long bytesWritten; long bytesWritten;
char *p = (char *) data; char *p = (char *) data;
long numBytes = aStream->bytesPerFrame * numFrames; long numBytes = aStream->bytesPerFrame * numFrames;
while (numBytes > 0) while (numBytes > 0)
{ {
bytesWritten = RingBuffer_Write(&aStream->outFIFO, p, numBytes); bytesWritten = RingBuffer_Write(&aStream->outFIFO, p, numBytes);
numBytes -= bytesWritten; numBytes -= bytesWritten;
p += bytesWritten; p += bytesWritten;
if (numBytes > 0) if (numBytes > 0)
Pa_Sleep(10); Pa_Sleep(10);
} }
return numFrames; return numFrames;
} }
/************************************************************ /************************************************************
@ -142,19 +142,19 @@ long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames)
*/ */
long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames) long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames)
{ {
long bytesRead; long bytesRead;
char *p = (char *) data; char *p = (char *) data;
long numBytes = aStream->bytesPerFrame * numFrames; long numBytes = aStream->bytesPerFrame * numFrames;
while (numBytes > 0) while (numBytes > 0)
{ {
bytesRead = RingBuffer_Read(&aStream->inFIFO, p, numBytes); bytesRead = RingBuffer_Read(&aStream->inFIFO, p, numBytes);
numBytes -= bytesRead; numBytes -= bytesRead;
p += bytesRead; p += bytesRead;
if (numBytes > 0) if (numBytes > 0)
Pa_Sleep(10); Pa_Sleep(10);
} }
return numFrames; return numFrames;
} }
/************************************************************ /************************************************************
@ -163,9 +163,9 @@ long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames)
*/ */
long GetAudioStreamWriteable(PABLIO_Stream * aStream) long GetAudioStreamWriteable(PABLIO_Stream * aStream)
{ {
int bytesEmpty = RingBuffer_GetWriteAvailable(&aStream->outFIFO); int bytesEmpty = RingBuffer_GetWriteAvailable(&aStream->outFIFO);
return bytesEmpty / aStream->bytesPerFrame; return bytesEmpty / aStream->bytesPerFrame;
} }
/************************************************************ /************************************************************
@ -174,24 +174,24 @@ long GetAudioStreamWriteable(PABLIO_Stream * aStream)
*/ */
long GetAudioStreamReadable(PABLIO_Stream * aStream) long GetAudioStreamReadable(PABLIO_Stream * aStream)
{ {
int bytesFull = RingBuffer_GetReadAvailable(&aStream->inFIFO); int bytesFull = RingBuffer_GetReadAvailable(&aStream->inFIFO);
return bytesFull / aStream->bytesPerFrame; return bytesFull / aStream->bytesPerFrame;
} }
/************************************************************/ /************************************************************/
static unsigned long RoundUpToNextPowerOf2(unsigned long n) static unsigned long RoundUpToNextPowerOf2(unsigned long n)
{ {
long numBits = 0; long numBits = 0;
if (((n - 1) & n) == 0) if (((n - 1) & n) == 0)
return n; /* Already Power of two. */ return n; /* Already Power of two. */
while (n > 0) while (n > 0)
{ {
n = n >> 1; n = n >> 1;
numBits++; numBits++;
} }
return (1 << numBits); return (1 << numBits);
} }
/************************************************************ /************************************************************
@ -202,132 +202,132 @@ static unsigned long RoundUpToNextPowerOf2(unsigned long n)
* PABLIO_READ, PABLIO_WRITE, or PABLIO_READ_WRITE, * PABLIO_READ, PABLIO_WRITE, or PABLIO_READ_WRITE,
* and either PABLIO_MONO or PABLIO_STEREO * and either PABLIO_MONO or PABLIO_STEREO
*/ */
PaError OpenAudioStream(PABLIO_Stream ** rwblPtr, double sampleRate, PaSampleFormat format, long flags, int indev, PaError OpenAudioStream(PABLIO_Stream ** rwblPtr, double sampleRate, PaSampleFormat format, long flags, int indev,
int outdev) int outdev)
{ {
long bytesPerSample; long bytesPerSample;
long doRead = 0; long doRead = 0;
long doWrite = 0; long doWrite = 0;
PaError err; PaError err;
PABLIO_Stream * aStream; PABLIO_Stream * aStream;
long minNumBuffers; long minNumBuffers;
long numFrames; long numFrames;
/* Allocate PABLIO_Stream structure for caller. */ /* Allocate PABLIO_Stream structure for caller. */
aStream = (PABLIO_Stream *) malloc(sizeof(PABLIO_Stream)); aStream = (PABLIO_Stream *) malloc(sizeof(PABLIO_Stream));
if (aStream == NULL) if (aStream == NULL)
return paInsufficientMemory; return paInsufficientMemory;
memset(aStream, 0, sizeof(PABLIO_Stream)); memset(aStream, 0, sizeof(PABLIO_Stream));
/* Determine size of a sample. */ /* Determine size of a sample. */
bytesPerSample = Pa_GetSampleSize(format); bytesPerSample = Pa_GetSampleSize(format);
if (bytesPerSample < 0) if (bytesPerSample < 0)
{ {
err = (PaError) bytesPerSample; err = (PaError) bytesPerSample;
goto error; goto error;
} }
aStream->samplesPerFrame = ((flags & PABLIO_MONO) != 0) ? 1 : 2; aStream->samplesPerFrame = ((flags & PABLIO_MONO) != 0) ? 1 : 2;
aStream->bytesPerFrame = bytesPerSample * aStream->samplesPerFrame; aStream->bytesPerFrame = bytesPerSample * aStream->samplesPerFrame;
/* Initialize PortAudio */ /* Initialize PortAudio */
err = Pa_Initialize(); err = Pa_Initialize();
if (err != paNoError) if (err != paNoError)
goto error; goto error;
/* Warning: numFrames must be larger than amount of data processed per interrupt /* Warning: numFrames must be larger than amount of data processed per interrupt
* inside PA to prevent glitches. Just to be safe, adjust size upwards. * inside PA to prevent glitches. Just to be safe, adjust size upwards.
*/ */
minNumBuffers = 2 * Pa_GetMinNumBuffers(FRAMES_PER_BUFFER, sampleRate); minNumBuffers = 2 * Pa_GetMinNumBuffers(FRAMES_PER_BUFFER, sampleRate);
numFrames = minNumBuffers * FRAMES_PER_BUFFER; numFrames = minNumBuffers * FRAMES_PER_BUFFER;
/* The PortAudio callback runs in a high priority thread. But PABLIO /* The PortAudio callback runs in a high priority thread. But PABLIO
* runs in a normal foreground thread. So we may have much worse * runs in a normal foreground thread. So we may have much worse
* latency in PABLIO. So adjust latency to a safe level. * latency in PABLIO. So adjust latency to a safe level.
*/ */
{ {
const int safeLatencyMSec = 200; const int safeLatencyMSec = 200;
int minLatencyMSec = (int) ((1000 * numFrames) / sampleRate); int minLatencyMSec = (int) ((1000 * numFrames) / sampleRate);
if (minLatencyMSec < safeLatencyMSec) if (minLatencyMSec < safeLatencyMSec)
{ {
numFrames = (int) ((safeLatencyMSec * sampleRate) / 1000); numFrames = (int) ((safeLatencyMSec * sampleRate) / 1000);
} }
} numFrames = RoundUpToNextPowerOf2(numFrames); } numFrames = RoundUpToNextPowerOf2(numFrames);
/* Initialize Ring Buffers */ /* Initialize Ring Buffers */
doRead = ((flags & PABLIO_READ) != 0); doRead = ((flags & PABLIO_READ) != 0);
doWrite = ((flags & PABLIO_WRITE) != 0); doWrite = ((flags & PABLIO_WRITE) != 0);
if (doRead) if (doRead)
{ {
err = PABLIO_InitFIFO(&aStream->inFIFO, numFrames, aStream->bytesPerFrame); err = PABLIO_InitFIFO(&aStream->inFIFO, numFrames, aStream->bytesPerFrame);
if (err != paNoError) if (err != paNoError)
goto error; goto error;
} }
if (doWrite) if (doWrite)
{ {
long numBytes; long numBytes;
err = PABLIO_InitFIFO(&aStream->outFIFO, numFrames, aStream->bytesPerFrame); err = PABLIO_InitFIFO(&aStream->outFIFO, numFrames, aStream->bytesPerFrame);
if (err != paNoError) if (err != paNoError)
goto error; goto error;
/* Make Write FIFO appear full initially. */ /* Make Write FIFO appear full initially. */
numBytes = RingBuffer_GetWriteAvailable(&aStream->outFIFO); numBytes = RingBuffer_GetWriteAvailable(&aStream->outFIFO);
RingBuffer_AdvanceWriteIndex(&aStream->outFIFO, numBytes); RingBuffer_AdvanceWriteIndex(&aStream->outFIFO, numBytes);
} }
/* Open a PortAudio stream that we will use to communicate with the underlying /* Open a PortAudio stream that we will use to communicate with the underlying
* audio drivers. */ * audio drivers. */
err = Pa_OpenStream( &aStream->stream, err = Pa_OpenStream(&aStream->stream,
(doRead ? (indev > -1) ? indev : Pa_GetDefaultInputDeviceID() : paNoDevice), (doRead ? (indev > -1) ? indev : Pa_GetDefaultInputDeviceID() : paNoDevice),
(doRead ? aStream->samplesPerFrame : 0), format, NULL, (doRead ? aStream->samplesPerFrame : 0), format, NULL,
(doWrite ? (outdev > -1) ? outdev : Pa_GetDefaultOutputDeviceID() : paNoDevice), (doWrite ? (outdev > -1) ? outdev : Pa_GetDefaultOutputDeviceID() : paNoDevice),
(doWrite ? aStream->samplesPerFrame : 0), format, NULL, sampleRate, FRAMES_PER_BUFFER, (doWrite ? aStream->samplesPerFrame : 0), format, NULL, sampleRate, FRAMES_PER_BUFFER,
minNumBuffers, paClipOff, minNumBuffers, paClipOff,
/* we won't output out of range samples so don't bother clipping them */ /* we won't output out of range samples so don't bother clipping them */
blockingIOCallback, aStream); blockingIOCallback, aStream);
if (err != paNoError) if (err != paNoError)
goto error; goto error;
err = Pa_StartStream(aStream->stream); err = Pa_StartStream(aStream->stream);
if (err != paNoError) if (err != paNoError)
goto error; goto error;
*rwblPtr = aStream; *rwblPtr = aStream;
return paNoError; return paNoError;
error: CloseAudioStream(aStream); error:CloseAudioStream(aStream);
*rwblPtr = NULL; *rwblPtr = NULL;
return err; return err;
} }
/************************************************************/ /************************************************************/
PaError CloseAudioStream(PABLIO_Stream * aStream) PaError CloseAudioStream(PABLIO_Stream * aStream)
{ {
PaError err = paNoError; PaError err = paNoError;
int bytesEmpty; int bytesEmpty;
int byteSize = aStream->outFIFO.bufferSize; int byteSize = aStream->outFIFO.bufferSize;
if (aStream->stream != NULL) /* Make sure stream was opened. PLB021214 */ if (aStream->stream != NULL) /* Make sure stream was opened. PLB021214 */
{ {
/* If we are writing data, make sure we play everything written. */ /* If we are writing data, make sure we play everything written. */
if (byteSize > 0) if (byteSize > 0)
{ {
int timeOutMSec = 2000; int timeOutMSec = 2000;
bytesEmpty = RingBuffer_GetWriteAvailable(&aStream->outFIFO); bytesEmpty = RingBuffer_GetWriteAvailable(&aStream->outFIFO);
while ((bytesEmpty < byteSize) && (timeOutMSec > 0)) while ((bytesEmpty < byteSize) && (timeOutMSec > 0))
{ {
Pa_Sleep(20); Pa_Sleep(20);
timeOutMSec -= 20; timeOutMSec -= 20;
bytesEmpty = RingBuffer_GetWriteAvailable(&aStream->outFIFO); bytesEmpty = RingBuffer_GetWriteAvailable(&aStream->outFIFO);
} }
} }
err = Pa_StopStream(aStream->stream); err = Pa_StopStream(aStream->stream);
if (err != paNoError) if (err != paNoError)
goto error; goto error;
err = Pa_CloseStream(aStream->stream); err = Pa_CloseStream(aStream->stream);
} }
error: Pa_Terminate(); error:Pa_Terminate();
PABLIO_TermFIFO(&aStream->inFIFO); PABLIO_TermFIFO(&aStream->inFIFO);
PABLIO_TermFIFO(&aStream->outFIFO); PABLIO_TermFIFO(&aStream->outFIFO);
free(aStream); free(aStream);
return err; return err;
} }

View File

@ -45,39 +45,39 @@
*/ */
long RingBuffer_Init(RingBuffer * rbuf, long numBytes, void *dataPtr) long RingBuffer_Init(RingBuffer * rbuf, long numBytes, void *dataPtr)
{ {
if (((numBytes - 1) & numBytes) != 0) if (((numBytes - 1) & numBytes) != 0)
return -1; /* Not Power of two. */ return -1; /* Not Power of two. */
rbuf->bufferSize = numBytes; rbuf->bufferSize = numBytes;
rbuf->buffer = (char *) dataPtr; rbuf->buffer = (char *) dataPtr;
RingBuffer_Flush(rbuf); RingBuffer_Flush(rbuf);
rbuf->bigMask = (numBytes * 2) - 1; rbuf->bigMask = (numBytes * 2) - 1;
rbuf->smallMask = (numBytes) - 1; rbuf->smallMask = (numBytes) - 1;
return 0; return 0;
} }
/*************************************************************************** /***************************************************************************
** Return number of bytes available for reading. */ ** Return number of bytes available for reading. */
long RingBuffer_GetReadAvailable(RingBuffer * rbuf) long RingBuffer_GetReadAvailable(RingBuffer * rbuf)
{ {
return ((rbuf->writeIndex - rbuf->readIndex) & rbuf->bigMask); return ((rbuf->writeIndex - rbuf->readIndex) & rbuf->bigMask);
} }
/*************************************************************************** /***************************************************************************
** Return number of bytes available for writing. */ ** Return number of bytes available for writing. */
long RingBuffer_GetWriteAvailable(RingBuffer * rbuf) long RingBuffer_GetWriteAvailable(RingBuffer * rbuf)
{ {
return (rbuf->bufferSize - RingBuffer_GetReadAvailable(rbuf)); return (rbuf->bufferSize - RingBuffer_GetReadAvailable(rbuf));
} }
/*************************************************************************** /***************************************************************************
** Clear buffer. Should only be called when buffer is NOT being read. */ ** Clear buffer. Should only be called when buffer is NOT being read. */
void RingBuffer_Flush(RingBuffer * rbuf) void RingBuffer_Flush(RingBuffer * rbuf)
{ {
rbuf->writeIndex = rbuf->readIndex = 0; rbuf->writeIndex = rbuf->readIndex = 0;
} }
/*************************************************************************** /***************************************************************************
** Get address of region(s) to which we can write data. ** Get address of region(s) to which we can write data.
@ -85,44 +85,44 @@ void RingBuffer_Flush(RingBuffer * rbuf)
** If non-contiguous, size2 will be the size of second region. ** If non-contiguous, size2 will be the size of second region.
** Returns room available to be written or numBytes, whichever is smaller. ** Returns room available to be written or numBytes, whichever is smaller.
*/ */
long RingBuffer_GetWriteRegions(RingBuffer * rbuf, long numBytes, void **dataPtr1, long *sizePtr1, void **dataPtr2, long RingBuffer_GetWriteRegions(RingBuffer * rbuf, long numBytes, void **dataPtr1, long *sizePtr1, void **dataPtr2,
long *sizePtr2) long *sizePtr2)
{ {
long index; long index;
long available = RingBuffer_GetWriteAvailable(rbuf); long available = RingBuffer_GetWriteAvailable(rbuf);
if (numBytes > available) if (numBytes > available)
numBytes = available; numBytes = available;
/* Check to see if write is not contiguous. */ /* Check to see if write is not contiguous. */
index = rbuf->writeIndex & rbuf->smallMask; index = rbuf->writeIndex & rbuf->smallMask;
if ((index + numBytes) > rbuf->bufferSize) if ((index + numBytes) > rbuf->bufferSize)
{ {
/* Write data in two blocks that wrap the buffer. */ /* Write data in two blocks that wrap the buffer. */
long firstHalf = rbuf->bufferSize - index; long firstHalf = rbuf->bufferSize - index;
*dataPtr1 = &rbuf->buffer[index]; *dataPtr1 = &rbuf->buffer[index];
*sizePtr1 = firstHalf; *sizePtr1 = firstHalf;
*dataPtr2 = &rbuf->buffer[0]; *dataPtr2 = &rbuf->buffer[0];
*sizePtr2 = numBytes - firstHalf; *sizePtr2 = numBytes - firstHalf;
} }
else else
{ {
*dataPtr1 = &rbuf->buffer[index]; *dataPtr1 = &rbuf->buffer[index];
*sizePtr1 = numBytes; *sizePtr1 = numBytes;
*dataPtr2 = NULL; *dataPtr2 = NULL;
*sizePtr2 = 0; *sizePtr2 = 0;
} }
return numBytes; return numBytes;
} }
/*************************************************************************** /***************************************************************************
*/ */
long RingBuffer_AdvanceWriteIndex(RingBuffer * rbuf, long numBytes) long RingBuffer_AdvanceWriteIndex(RingBuffer * rbuf, long numBytes)
{ {
return rbuf->writeIndex = (rbuf->writeIndex + numBytes) & rbuf->bigMask; return rbuf->writeIndex = (rbuf->writeIndex + numBytes) & rbuf->bigMask;
} }
/*************************************************************************** /***************************************************************************
@ -131,89 +131,89 @@ long RingBuffer_AdvanceWriteIndex(RingBuffer * rbuf, long numBytes)
** If non-contiguous, size2 will be the size of second region. ** If non-contiguous, size2 will be the size of second region.
** Returns room available to be written or numBytes, whichever is smaller. ** Returns room available to be written or numBytes, whichever is smaller.
*/ */
long RingBuffer_GetReadRegions(RingBuffer * rbuf, long numBytes, void **dataPtr1, long *sizePtr1, void **dataPtr2, long RingBuffer_GetReadRegions(RingBuffer * rbuf, long numBytes, void **dataPtr1, long *sizePtr1, void **dataPtr2,
long *sizePtr2) long *sizePtr2)
{ {
long index; long index;
long available = RingBuffer_GetReadAvailable(rbuf); long available = RingBuffer_GetReadAvailable(rbuf);
if (numBytes > available) if (numBytes > available)
numBytes = available; numBytes = available;
/* Check to see if read is not contiguous. */ /* Check to see if read is not contiguous. */
index = rbuf->readIndex & rbuf->smallMask; index = rbuf->readIndex & rbuf->smallMask;
if ((index + numBytes) > rbuf->bufferSize) if ((index + numBytes) > rbuf->bufferSize)
{ {
/* Write data in two blocks that wrap the buffer. */ /* Write data in two blocks that wrap the buffer. */
long firstHalf = rbuf->bufferSize - index; long firstHalf = rbuf->bufferSize - index;
*dataPtr1 = &rbuf->buffer[index]; *dataPtr1 = &rbuf->buffer[index];
*sizePtr1 = firstHalf; *sizePtr1 = firstHalf;
*dataPtr2 = &rbuf->buffer[0]; *dataPtr2 = &rbuf->buffer[0];
*sizePtr2 = numBytes - firstHalf; *sizePtr2 = numBytes - firstHalf;
} }
else else
{ {
*dataPtr1 = &rbuf->buffer[index]; *dataPtr1 = &rbuf->buffer[index];
*sizePtr1 = numBytes; *sizePtr1 = numBytes;
*dataPtr2 = NULL; *dataPtr2 = NULL;
*sizePtr2 = 0; *sizePtr2 = 0;
} }
return numBytes; return numBytes;
} }
/*************************************************************************** /***************************************************************************
*/ */
long RingBuffer_AdvanceReadIndex(RingBuffer * rbuf, long numBytes) long RingBuffer_AdvanceReadIndex(RingBuffer * rbuf, long numBytes)
{ {
return rbuf->readIndex = (rbuf->readIndex + numBytes) & rbuf->bigMask; return rbuf->readIndex = (rbuf->readIndex + numBytes) & rbuf->bigMask;
} }
/*************************************************************************** /***************************************************************************
** Return bytes written. */ ** Return bytes written. */
long RingBuffer_Write(RingBuffer * rbuf, void *data, long numBytes) long RingBuffer_Write(RingBuffer * rbuf, void *data, long numBytes)
{ {
long size1, size2, numWritten; long size1, size2, numWritten;
void *data1, *data2; void *data1, *data2;
numWritten = RingBuffer_GetWriteRegions(rbuf, numBytes, &data1, &size1, &data2, &size2); numWritten = RingBuffer_GetWriteRegions(rbuf, numBytes, &data1, &size1, &data2, &size2);
if (size2 > 0) if (size2 > 0)
{ {
memcpy(data1, data, size1); memcpy(data1, data, size1);
data = ((char *) data) + size1; data = ((char *) data) + size1;
memcpy(data2, data, size2); memcpy(data2, data, size2);
} }
else else
{ {
memcpy(data1, data, size1); memcpy(data1, data, size1);
} }
RingBuffer_AdvanceWriteIndex(rbuf, numWritten); RingBuffer_AdvanceWriteIndex(rbuf, numWritten);
return numWritten; return numWritten;
} }
/*************************************************************************** /***************************************************************************
** Return bytes read. */ ** Return bytes read. */
long RingBuffer_Read(RingBuffer * rbuf, void *data, long numBytes) long RingBuffer_Read(RingBuffer * rbuf, void *data, long numBytes)
{ {
long size1, size2, numRead; long size1, size2, numRead;
void *data1, *data2; void *data1, *data2;
numRead = RingBuffer_GetReadRegions(rbuf, numBytes, &data1, &size1, &data2, &size2); numRead = RingBuffer_GetReadRegions(rbuf, numBytes, &data1, &size1, &data2, &size2);
if (size2 > 0) if (size2 > 0)
{ {
memcpy(data, data1, size1); memcpy(data, data1, size1);
data = ((char *) data) + size1; data = ((char *) data) + size1;
memcpy(data, data2, size2); memcpy(data, data2, size2);
} }
else else
{ {
memcpy(data, data1, size1); memcpy(data, data1, size1);
} }
RingBuffer_AdvanceReadIndex(rbuf, numRead); RingBuffer_AdvanceReadIndex(rbuf, numRead);
return numRead; return numRead;
} }