168efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com/*
268efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * $Id: pa_ringbuffer.c 1421 2009-11-18 16:09:05Z bjornroche $
368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * Portable Audio I/O Library
468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * Ring Buffer utility.
568efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com *
668efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * Author: Phil Burk, http://www.softsynth.com
768efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * modified for SMP safety on Mac OS X by Bjorn Roche
868efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * modified for SMP safety on Linux by Leland Lucius
968efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * also, allowed for const where possible
1068efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * modified for multiple-byte-sized data elements by Sven Fischer
1168efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com *
1268efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * Note that this is safe only for a single-thread reader and a
1368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * single-thread writer.
1468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com *
1568efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * This program uses the PortAudio Portable Audio Library.
1668efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * For more information see: http://www.portaudio.com
1768efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
1868efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com *
1968efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * Permission is hereby granted, free of charge, to any person obtaining
2068efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * a copy of this software and associated documentation files
2168efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * (the "Software"), to deal in the Software without restriction,
2268efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * including without limitation the rights to use, copy, modify, merge,
2368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * publish, distribute, sublicense, and/or sell copies of the Software,
2468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * and to permit persons to whom the Software is furnished to do so,
2568efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * subject to the following conditions:
2668efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com *
2768efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * The above copyright notice and this permission notice shall be
2868efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * included in all copies or substantial portions of the Software.
2968efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com *
3068efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
3168efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
3268efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
3368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
3468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
3568efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
3668efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3768efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com */
3868efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com
3968efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com/*
4068efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * The text above constitutes the entire PortAudio license; however,
4168efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * the PortAudio community also makes the following non-binding requests:
4268efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com *
4368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * Any person wishing to distribute modifications to the Software is
4468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * requested to send the modifications to the original developer so that
4568efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * they can be incorporated into the canonical version. It is also
4668efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * requested that these non-binding requests be included along with the
4768efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * license above.
4868efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com */
4968efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com
5068efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com/**
5168efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com @file
5268efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com @ingroup common_src
5368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com*/
5468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com
55811269df40fd8cd036b68cfe39bc04cacac0a698pbos@webrtc.org#include <math.h>
5668efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com#include <stdio.h>
5768efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com#include <stdlib.h>
5868efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com#include <string.h>
59811269df40fd8cd036b68cfe39bc04cacac0a698pbos@webrtc.org#include "webrtc/modules/audio_device/mac/portaudio/pa_memorybarrier.h"
60811269df40fd8cd036b68cfe39bc04cacac0a698pbos@webrtc.org#include "webrtc/modules/audio_device/mac/portaudio/pa_ringbuffer.h"
6168efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com
6268efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com/***************************************************************************
6368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * Initialize FIFO.
6468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com * elementCount must be power of 2, returns -1 if not.
6568efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com */
66e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.orgPaRingBufferSize PaUtil_InitializeRingBuffer(PaUtilRingBuffer* rbuf,
67e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org                                             PaRingBufferSize elementSizeBytes,
68e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org                                             PaRingBufferSize elementCount,
69e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org                                             void* dataPtr) {
7068efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    if( ((elementCount-1) & elementCount) != 0) return -1; /* Not Power of two. */
7168efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    rbuf->bufferSize = elementCount;
7268efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    rbuf->buffer = (char *)dataPtr;
7368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    PaUtil_FlushRingBuffer( rbuf );
7468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    rbuf->bigMask = (elementCount*2)-1;
7568efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    rbuf->smallMask = (elementCount)-1;
7668efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    rbuf->elementSizeBytes = elementSizeBytes;
7768efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    return 0;
7868efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com}
7968efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com
8068efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com/***************************************************************************
8168efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com** Return number of elements available for reading. */
82e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.orgPaRingBufferSize PaUtil_GetRingBufferReadAvailable( PaUtilRingBuffer *rbuf )
8368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com{
8468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    PaUtil_ReadMemoryBarrier();
8568efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    return ( (rbuf->writeIndex - rbuf->readIndex) & rbuf->bigMask );
8668efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com}
8768efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com/***************************************************************************
8868efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com** Return number of elements available for writing. */
89e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.orgPaRingBufferSize PaUtil_GetRingBufferWriteAvailable( PaUtilRingBuffer *rbuf )
9068efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com{
9168efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    /* Since we are calling PaUtil_GetRingBufferReadAvailable, we don't need an aditional MB */
9268efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    return ( rbuf->bufferSize - PaUtil_GetRingBufferReadAvailable(rbuf));
9368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com}
9468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com
9568efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com/***************************************************************************
9668efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com** Clear buffer. Should only be called when buffer is NOT being read. */
9768efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.comvoid PaUtil_FlushRingBuffer( PaUtilRingBuffer *rbuf )
9868efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com{
9968efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    rbuf->writeIndex = rbuf->readIndex = 0;
10068efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com}
10168efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com
10268efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com/***************************************************************************
10368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com** Get address of region(s) to which we can write data.
10468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com** If the region is contiguous, size2 will be zero.
10568efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com** If non-contiguous, size2 will be the size of second region.
10668efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com** Returns room available to be written or elementCount, whichever is smaller.
10768efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com*/
108e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.orgPaRingBufferSize PaUtil_GetRingBufferWriteRegions(PaUtilRingBuffer* rbuf,
109e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org                                                  PaRingBufferSize elementCount,
110e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org                                                  void** dataPtr1,
111e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org                                                  PaRingBufferSize* sizePtr1,
112e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org                                                  void** dataPtr2,
113e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org                                                  PaRingBufferSize* sizePtr2) {
114e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org    PaRingBufferSize   index;
115e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org    PaRingBufferSize   available = PaUtil_GetRingBufferWriteAvailable( rbuf );
11668efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    if( elementCount > available ) elementCount = available;
11768efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    /* Check to see if write is not contiguous. */
11868efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    index = rbuf->writeIndex & rbuf->smallMask;
11968efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    if( (index + elementCount) > rbuf->bufferSize )
12068efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    {
12168efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        /* Write data in two blocks that wrap the buffer. */
122e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org        PaRingBufferSize   firstHalf = rbuf->bufferSize - index;
12368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
12468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        *sizePtr1 = firstHalf;
12568efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        *dataPtr2 = &rbuf->buffer[0];
12668efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        *sizePtr2 = elementCount - firstHalf;
12768efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    }
12868efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    else
12968efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    {
13068efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
13168efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        *sizePtr1 = elementCount;
13268efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        *dataPtr2 = NULL;
13368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        *sizePtr2 = 0;
13468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    }
13568efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    return elementCount;
13668efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com}
13768efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com
13868efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com
13968efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com/***************************************************************************
14068efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com*/
141e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.orgPaRingBufferSize PaUtil_AdvanceRingBufferWriteIndex(
142e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org    PaUtilRingBuffer* rbuf,
143e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org    PaRingBufferSize elementCount) {
14468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    /* we need to ensure that previous writes are seen before we update the write index */
14568efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    PaUtil_WriteMemoryBarrier();
14668efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    return rbuf->writeIndex = (rbuf->writeIndex + elementCount) & rbuf->bigMask;
14768efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com}
14868efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com
14968efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com/***************************************************************************
15068efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com** Get address of region(s) from which we can read data.
15168efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com** If the region is contiguous, size2 will be zero.
15268efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com** If non-contiguous, size2 will be the size of second region.
15368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com** Returns room available to be written or elementCount, whichever is smaller.
15468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com*/
155e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.orgPaRingBufferSize PaUtil_GetRingBufferReadRegions(PaUtilRingBuffer* rbuf,
156e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org                                                 PaRingBufferSize elementCount,
157e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org                                                 void** dataPtr1,
158e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org                                                 PaRingBufferSize* sizePtr1,
159e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org                                                 void** dataPtr2,
160e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org                                                 PaRingBufferSize* sizePtr2) {
161e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org    PaRingBufferSize   index;
162e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org    PaRingBufferSize   available = PaUtil_GetRingBufferReadAvailable( rbuf );
16368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    if( elementCount > available ) elementCount = available;
16468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    /* Check to see if read is not contiguous. */
16568efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    index = rbuf->readIndex & rbuf->smallMask;
16668efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    if( (index + elementCount) > rbuf->bufferSize )
16768efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    {
16868efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        /* Write data in two blocks that wrap the buffer. */
169e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org        PaRingBufferSize firstHalf = rbuf->bufferSize - index;
17068efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
17168efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        *sizePtr1 = firstHalf;
17268efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        *dataPtr2 = &rbuf->buffer[0];
17368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        *sizePtr2 = elementCount - firstHalf;
17468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    }
17568efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    else
17668efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    {
17768efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
17868efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        *sizePtr1 = elementCount;
17968efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        *dataPtr2 = NULL;
18068efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        *sizePtr2 = 0;
18168efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    }
18268efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    return elementCount;
18368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com}
18468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com/***************************************************************************
18568efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com*/
186e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.orgPaRingBufferSize PaUtil_AdvanceRingBufferReadIndex(
187e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org    PaUtilRingBuffer* rbuf,
188e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org    PaRingBufferSize elementCount) {
18968efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    /* we need to ensure that previous writes are always seen before updating the index. */
19068efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    PaUtil_WriteMemoryBarrier();
19168efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    return rbuf->readIndex = (rbuf->readIndex + elementCount) & rbuf->bigMask;
19268efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com}
19368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com
19468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com/***************************************************************************
19568efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com** Return elements written. */
196e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.orgPaRingBufferSize PaUtil_WriteRingBuffer(PaUtilRingBuffer* rbuf,
197e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org                                        const void* data,
198e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org                                        PaRingBufferSize elementCount) {
199e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org    PaRingBufferSize size1, size2, numWritten;
20068efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    void *data1, *data2;
20168efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    numWritten = PaUtil_GetRingBufferWriteRegions( rbuf, elementCount, &data1, &size1, &data2, &size2 );
20268efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    if( size2 > 0 )
20368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    {
20468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com
20568efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        memcpy( data1, data, size1*rbuf->elementSizeBytes );
20668efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        data = ((char *)data) + size1*rbuf->elementSizeBytes;
20768efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        memcpy( data2, data, size2*rbuf->elementSizeBytes );
20868efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    }
20968efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    else
21068efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    {
21168efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        memcpy( data1, data, size1*rbuf->elementSizeBytes );
21268efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    }
21368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    PaUtil_AdvanceRingBufferWriteIndex( rbuf, numWritten );
21468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    return numWritten;
21568efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com}
21668efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com
21768efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com/***************************************************************************
21868efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com** Return elements read. */
219e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.orgPaRingBufferSize PaUtil_ReadRingBuffer(PaUtilRingBuffer* rbuf,
220e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org                                       void* data,
221e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org                                       PaRingBufferSize elementCount) {
222e728ee03ba093ddb9fa6fb803994969801a4f601pbos@webrtc.org    PaRingBufferSize size1, size2, numRead;
22368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    void *data1, *data2;
22468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    numRead = PaUtil_GetRingBufferReadRegions( rbuf, elementCount, &data1, &size1, &data2, &size2 );
22568efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    if( size2 > 0 )
22668efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    {
22768efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        memcpy( data, data1, size1*rbuf->elementSizeBytes );
22868efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        data = ((char *)data) + size1*rbuf->elementSizeBytes;
22968efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        memcpy( data, data2, size2*rbuf->elementSizeBytes );
23068efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    }
23168efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    else
23268efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    {
23368efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com        memcpy( data, data1, size1*rbuf->elementSizeBytes );
23468efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    }
23568efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    PaUtil_AdvanceRingBufferReadIndex( rbuf, numRead );
23668efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com    return numRead;
23768efa21abcae03939dd03ea6ec11fd6f510c8c47xians@google.com}
238