~ubuntu-branches/ubuntu/trusty/sflphone/trusty

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/third_party/portaudio/src/common/pa_ringbuffer.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (4.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20140128182336-jrsv0k9u6cawc068
Tags: 1.3.0-1
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * $Id: pa_ringbuffer.c 1421 2009-11-18 16:09:05Z bjornroche $
3
 
 * Portable Audio I/O Library
4
 
 * Ring Buffer utility.
5
 
 *
6
 
 * Author: Phil Burk, http://www.softsynth.com
7
 
 * modified for SMP safety on Mac OS X by Bjorn Roche
8
 
 * modified for SMP safety on Linux by Leland Lucius
9
 
 * also, allowed for const where possible
10
 
 * modified for multiple-byte-sized data elements by Sven Fischer
11
 
 *
12
 
 * Note that this is safe only for a single-thread reader and a
13
 
 * single-thread writer.
14
 
 *
15
 
 * This program uses the PortAudio Portable Audio Library.
16
 
 * For more information see: http://www.portaudio.com
17
 
 * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
18
 
 *
19
 
 * Permission is hereby granted, free of charge, to any person obtaining
20
 
 * a copy of this software and associated documentation files
21
 
 * (the "Software"), to deal in the Software without restriction,
22
 
 * including without limitation the rights to use, copy, modify, merge,
23
 
 * publish, distribute, sublicense, and/or sell copies of the Software,
24
 
 * and to permit persons to whom the Software is furnished to do so,
25
 
 * subject to the following conditions:
26
 
 *
27
 
 * The above copyright notice and this permission notice shall be
28
 
 * included in all copies or substantial portions of the Software.
29
 
 *
30
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
31
 
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
32
 
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
33
 
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
34
 
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
35
 
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
36
 
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37
 
 */
38
 
 
39
 
/*
40
 
 * The text above constitutes the entire PortAudio license; however,
41
 
 * the PortAudio community also makes the following non-binding requests:
42
 
 *
43
 
 * Any person wishing to distribute modifications to the Software is
44
 
 * requested to send the modifications to the original developer so that
45
 
 * they can be incorporated into the canonical version. It is also
46
 
 * requested that these non-binding requests be included along with the
47
 
 * license above.
48
 
 */
49
 
 
50
 
/**
51
 
 @file
52
 
 @ingroup common_src
53
 
*/
54
 
 
55
 
#include <stdio.h>
56
 
#include <stdlib.h>
57
 
#include <math.h>
58
 
#include "pa_ringbuffer.h"
59
 
#include <string.h>
60
 
#include "pa_memorybarrier.h"
61
 
 
62
 
/***************************************************************************
63
 
 * Initialize FIFO.
64
 
 * elementCount must be power of 2, returns -1 if not.
65
 
 */
66
 
ring_buffer_size_t PaUtil_InitializeRingBuffer( PaUtilRingBuffer *rbuf, ring_buffer_size_t elementSizeBytes, ring_buffer_size_t elementCount, void *dataPtr )
67
 
{
68
 
    if( ((elementCount-1) & elementCount) != 0) return -1; /* Not Power of two. */
69
 
    rbuf->bufferSize = elementCount;
70
 
    rbuf->buffer = (char *)dataPtr;
71
 
    PaUtil_FlushRingBuffer( rbuf );
72
 
    rbuf->bigMask = (elementCount*2)-1;
73
 
    rbuf->smallMask = (elementCount)-1;
74
 
    rbuf->elementSizeBytes = elementSizeBytes;
75
 
    return 0;
76
 
}
77
 
 
78
 
/***************************************************************************
79
 
** Return number of elements available for reading. */
80
 
ring_buffer_size_t PaUtil_GetRingBufferReadAvailable( PaUtilRingBuffer *rbuf )
81
 
{
82
 
    PaUtil_ReadMemoryBarrier();
83
 
    return ( (rbuf->writeIndex - rbuf->readIndex) & rbuf->bigMask );
84
 
}
85
 
/***************************************************************************
86
 
** Return number of elements available for writing. */
87
 
ring_buffer_size_t PaUtil_GetRingBufferWriteAvailable( PaUtilRingBuffer *rbuf )
88
 
{
89
 
    /* Since we are calling PaUtil_GetRingBufferReadAvailable, we don't need an aditional MB */
90
 
    return ( rbuf->bufferSize - PaUtil_GetRingBufferReadAvailable(rbuf));
91
 
}
92
 
 
93
 
/***************************************************************************
94
 
** Clear buffer. Should only be called when buffer is NOT being read. */
95
 
void PaUtil_FlushRingBuffer( PaUtilRingBuffer *rbuf )
96
 
{
97
 
    rbuf->writeIndex = rbuf->readIndex = 0;
98
 
}
99
 
 
100
 
/***************************************************************************
101
 
** Get address of region(s) to which we can write data.
102
 
** If the region is contiguous, size2 will be zero.
103
 
** If non-contiguous, size2 will be the size of second region.
104
 
** Returns room available to be written or elementCount, whichever is smaller.
105
 
*/
106
 
ring_buffer_size_t PaUtil_GetRingBufferWriteRegions( PaUtilRingBuffer *rbuf, ring_buffer_size_t elementCount,
107
 
                                       void **dataPtr1, ring_buffer_size_t *sizePtr1,
108
 
                                       void **dataPtr2, ring_buffer_size_t *sizePtr2 )
109
 
{
110
 
    ring_buffer_size_t   index;
111
 
    ring_buffer_size_t   available = PaUtil_GetRingBufferWriteAvailable( rbuf );
112
 
    if( elementCount > available ) elementCount = available;
113
 
    /* Check to see if write is not contiguous. */
114
 
    index = rbuf->writeIndex & rbuf->smallMask;
115
 
    if( (index + elementCount) > rbuf->bufferSize )
116
 
    {
117
 
        /* Write data in two blocks that wrap the buffer. */
118
 
        ring_buffer_size_t   firstHalf = rbuf->bufferSize - index;
119
 
        *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
120
 
        *sizePtr1 = firstHalf;
121
 
        *dataPtr2 = &rbuf->buffer[0];
122
 
        *sizePtr2 = elementCount - firstHalf;
123
 
    }
124
 
    else
125
 
    {
126
 
        *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
127
 
        *sizePtr1 = elementCount;
128
 
        *dataPtr2 = NULL;
129
 
        *sizePtr2 = 0;
130
 
    }
131
 
    return elementCount;
132
 
}
133
 
 
134
 
 
135
 
/***************************************************************************
136
 
*/
137
 
ring_buffer_size_t PaUtil_AdvanceRingBufferWriteIndex( PaUtilRingBuffer *rbuf, ring_buffer_size_t elementCount )
138
 
{
139
 
    /* we need to ensure that previous writes are seen before we update the write index */
140
 
    PaUtil_WriteMemoryBarrier();
141
 
    return rbuf->writeIndex = (rbuf->writeIndex + elementCount) & rbuf->bigMask;
142
 
}
143
 
 
144
 
/***************************************************************************
145
 
** Get address of region(s) from which we can read data.
146
 
** If the region is contiguous, size2 will be zero.
147
 
** If non-contiguous, size2 will be the size of second region.
148
 
** Returns room available to be written or elementCount, whichever is smaller.
149
 
*/
150
 
ring_buffer_size_t PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, ring_buffer_size_t elementCount,
151
 
                                void **dataPtr1, ring_buffer_size_t *sizePtr1,
152
 
                                void **dataPtr2, ring_buffer_size_t *sizePtr2 )
153
 
{
154
 
    ring_buffer_size_t   index;
155
 
    ring_buffer_size_t   available = PaUtil_GetRingBufferReadAvailable( rbuf );
156
 
    if( elementCount > available ) elementCount = available;
157
 
    /* Check to see if read is not contiguous. */
158
 
    index = rbuf->readIndex & rbuf->smallMask;
159
 
    if( (index + elementCount) > rbuf->bufferSize )
160
 
    {
161
 
        /* Write data in two blocks that wrap the buffer. */
162
 
        ring_buffer_size_t firstHalf = rbuf->bufferSize - index;
163
 
        *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
164
 
        *sizePtr1 = firstHalf;
165
 
        *dataPtr2 = &rbuf->buffer[0];
166
 
        *sizePtr2 = elementCount - firstHalf;
167
 
    }
168
 
    else
169
 
    {
170
 
        *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
171
 
        *sizePtr1 = elementCount;
172
 
        *dataPtr2 = NULL;
173
 
        *sizePtr2 = 0;
174
 
    }
175
 
    return elementCount;
176
 
}
177
 
/***************************************************************************
178
 
*/
179
 
ring_buffer_size_t PaUtil_AdvanceRingBufferReadIndex( PaUtilRingBuffer *rbuf, ring_buffer_size_t elementCount )
180
 
{
181
 
    /* we need to ensure that previous writes are always seen before updating the index. */
182
 
    PaUtil_WriteMemoryBarrier();
183
 
    return rbuf->readIndex = (rbuf->readIndex + elementCount) & rbuf->bigMask;
184
 
}
185
 
 
186
 
/***************************************************************************
187
 
** Return elements written. */
188
 
ring_buffer_size_t PaUtil_WriteRingBuffer( PaUtilRingBuffer *rbuf, const void *data, ring_buffer_size_t elementCount )
189
 
{
190
 
    ring_buffer_size_t size1, size2, numWritten;
191
 
    void *data1, *data2;
192
 
    numWritten = PaUtil_GetRingBufferWriteRegions( rbuf, elementCount, &data1, &size1, &data2, &size2 );
193
 
    if( size2 > 0 )
194
 
    {
195
 
 
196
 
        memcpy( data1, data, size1*rbuf->elementSizeBytes );
197
 
        data = ((char *)data) + size1*rbuf->elementSizeBytes;
198
 
        memcpy( data2, data, size2*rbuf->elementSizeBytes );
199
 
    }
200
 
    else
201
 
    {
202
 
        memcpy( data1, data, size1*rbuf->elementSizeBytes );
203
 
    }
204
 
    PaUtil_AdvanceRingBufferWriteIndex( rbuf, numWritten );
205
 
    return numWritten;
206
 
}
207
 
 
208
 
/***************************************************************************
209
 
** Return elements read. */
210
 
ring_buffer_size_t PaUtil_ReadRingBuffer( PaUtilRingBuffer *rbuf, void *data, ring_buffer_size_t elementCount )
211
 
{
212
 
    ring_buffer_size_t size1, size2, numRead;
213
 
    void *data1, *data2;
214
 
    numRead = PaUtil_GetRingBufferReadRegions( rbuf, elementCount, &data1, &size1, &data2, &size2 );
215
 
    if( size2 > 0 )
216
 
    {
217
 
        memcpy( data, data1, size1*rbuf->elementSizeBytes );
218
 
        data = ((char *)data) + size1*rbuf->elementSizeBytes;
219
 
        memcpy( data, data2, size2*rbuf->elementSizeBytes );
220
 
    }
221
 
    else
222
 
    {
223
 
        memcpy( data, data1, size1*rbuf->elementSizeBytes );
224
 
    }
225
 
    PaUtil_AdvanceRingBufferReadIndex( rbuf, numRead );
226
 
    return numRead;
227
 
}