1*28e138c6SAndroid Build Coastguard Worker /* Copyright (C) 2007 Jean-Marc Valin
2*28e138c6SAndroid Build Coastguard Worker
3*28e138c6SAndroid Build Coastguard Worker File: buffer.c
4*28e138c6SAndroid Build Coastguard Worker This is a very simple ring buffer implementation. It is not thread-safe
5*28e138c6SAndroid Build Coastguard Worker so you need to do your own locking.
6*28e138c6SAndroid Build Coastguard Worker
7*28e138c6SAndroid Build Coastguard Worker Redistribution and use in source and binary forms, with or without
8*28e138c6SAndroid Build Coastguard Worker modification, are permitted provided that the following conditions are
9*28e138c6SAndroid Build Coastguard Worker met:
10*28e138c6SAndroid Build Coastguard Worker
11*28e138c6SAndroid Build Coastguard Worker 1. Redistributions of source code must retain the above copyright notice,
12*28e138c6SAndroid Build Coastguard Worker this list of conditions and the following disclaimer.
13*28e138c6SAndroid Build Coastguard Worker
14*28e138c6SAndroid Build Coastguard Worker 2. Redistributions in binary form must reproduce the above copyright
15*28e138c6SAndroid Build Coastguard Worker notice, this list of conditions and the following disclaimer in the
16*28e138c6SAndroid Build Coastguard Worker documentation and/or other materials provided with the distribution.
17*28e138c6SAndroid Build Coastguard Worker
18*28e138c6SAndroid Build Coastguard Worker 3. The name of the author may not be used to endorse or promote products
19*28e138c6SAndroid Build Coastguard Worker derived from this software without specific prior written permission.
20*28e138c6SAndroid Build Coastguard Worker
21*28e138c6SAndroid Build Coastguard Worker THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22*28e138c6SAndroid Build Coastguard Worker IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23*28e138c6SAndroid Build Coastguard Worker OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24*28e138c6SAndroid Build Coastguard Worker DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25*28e138c6SAndroid Build Coastguard Worker INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26*28e138c6SAndroid Build Coastguard Worker (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27*28e138c6SAndroid Build Coastguard Worker SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28*28e138c6SAndroid Build Coastguard Worker HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29*28e138c6SAndroid Build Coastguard Worker STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30*28e138c6SAndroid Build Coastguard Worker ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31*28e138c6SAndroid Build Coastguard Worker POSSIBILITY OF SUCH DAMAGE.
32*28e138c6SAndroid Build Coastguard Worker */
33*28e138c6SAndroid Build Coastguard Worker
34*28e138c6SAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
35*28e138c6SAndroid Build Coastguard Worker #include "config.h"
36*28e138c6SAndroid Build Coastguard Worker #endif
37*28e138c6SAndroid Build Coastguard Worker
38*28e138c6SAndroid Build Coastguard Worker
39*28e138c6SAndroid Build Coastguard Worker #include "os_support.h"
40*28e138c6SAndroid Build Coastguard Worker #include "arch.h"
41*28e138c6SAndroid Build Coastguard Worker #include "speex/speex_buffer.h"
42*28e138c6SAndroid Build Coastguard Worker
43*28e138c6SAndroid Build Coastguard Worker struct SpeexBuffer_ {
44*28e138c6SAndroid Build Coastguard Worker char *data;
45*28e138c6SAndroid Build Coastguard Worker int size;
46*28e138c6SAndroid Build Coastguard Worker int read_ptr;
47*28e138c6SAndroid Build Coastguard Worker int write_ptr;
48*28e138c6SAndroid Build Coastguard Worker int available;
49*28e138c6SAndroid Build Coastguard Worker };
50*28e138c6SAndroid Build Coastguard Worker
speex_buffer_init(int size)51*28e138c6SAndroid Build Coastguard Worker EXPORT SpeexBuffer *speex_buffer_init(int size)
52*28e138c6SAndroid Build Coastguard Worker {
53*28e138c6SAndroid Build Coastguard Worker SpeexBuffer *st = speex_alloc(sizeof(SpeexBuffer));
54*28e138c6SAndroid Build Coastguard Worker st->data = speex_alloc(size);
55*28e138c6SAndroid Build Coastguard Worker st->size = size;
56*28e138c6SAndroid Build Coastguard Worker st->read_ptr = 0;
57*28e138c6SAndroid Build Coastguard Worker st->write_ptr = 0;
58*28e138c6SAndroid Build Coastguard Worker st->available = 0;
59*28e138c6SAndroid Build Coastguard Worker return st;
60*28e138c6SAndroid Build Coastguard Worker }
61*28e138c6SAndroid Build Coastguard Worker
speex_buffer_destroy(SpeexBuffer * st)62*28e138c6SAndroid Build Coastguard Worker EXPORT void speex_buffer_destroy(SpeexBuffer *st)
63*28e138c6SAndroid Build Coastguard Worker {
64*28e138c6SAndroid Build Coastguard Worker speex_free(st->data);
65*28e138c6SAndroid Build Coastguard Worker speex_free(st);
66*28e138c6SAndroid Build Coastguard Worker }
67*28e138c6SAndroid Build Coastguard Worker
speex_buffer_write(SpeexBuffer * st,void * _data,int len)68*28e138c6SAndroid Build Coastguard Worker EXPORT int speex_buffer_write(SpeexBuffer *st, void *_data, int len)
69*28e138c6SAndroid Build Coastguard Worker {
70*28e138c6SAndroid Build Coastguard Worker int end;
71*28e138c6SAndroid Build Coastguard Worker int end1;
72*28e138c6SAndroid Build Coastguard Worker char *data = _data;
73*28e138c6SAndroid Build Coastguard Worker if (len > st->size)
74*28e138c6SAndroid Build Coastguard Worker {
75*28e138c6SAndroid Build Coastguard Worker data += len-st->size;
76*28e138c6SAndroid Build Coastguard Worker len = st->size;
77*28e138c6SAndroid Build Coastguard Worker }
78*28e138c6SAndroid Build Coastguard Worker end = st->write_ptr + len;
79*28e138c6SAndroid Build Coastguard Worker end1 = end;
80*28e138c6SAndroid Build Coastguard Worker if (end1 > st->size)
81*28e138c6SAndroid Build Coastguard Worker end1 = st->size;
82*28e138c6SAndroid Build Coastguard Worker SPEEX_COPY(st->data + st->write_ptr, data, end1 - st->write_ptr);
83*28e138c6SAndroid Build Coastguard Worker if (end > st->size)
84*28e138c6SAndroid Build Coastguard Worker {
85*28e138c6SAndroid Build Coastguard Worker end -= st->size;
86*28e138c6SAndroid Build Coastguard Worker SPEEX_COPY(st->data, data+end1 - st->write_ptr, end);
87*28e138c6SAndroid Build Coastguard Worker }
88*28e138c6SAndroid Build Coastguard Worker st->available += len;
89*28e138c6SAndroid Build Coastguard Worker if (st->available > st->size)
90*28e138c6SAndroid Build Coastguard Worker {
91*28e138c6SAndroid Build Coastguard Worker st->available = st->size;
92*28e138c6SAndroid Build Coastguard Worker st->read_ptr = st->write_ptr;
93*28e138c6SAndroid Build Coastguard Worker }
94*28e138c6SAndroid Build Coastguard Worker st->write_ptr += len;
95*28e138c6SAndroid Build Coastguard Worker if (st->write_ptr > st->size)
96*28e138c6SAndroid Build Coastguard Worker st->write_ptr -= st->size;
97*28e138c6SAndroid Build Coastguard Worker return len;
98*28e138c6SAndroid Build Coastguard Worker }
99*28e138c6SAndroid Build Coastguard Worker
speex_buffer_writezeros(SpeexBuffer * st,int len)100*28e138c6SAndroid Build Coastguard Worker EXPORT int speex_buffer_writezeros(SpeexBuffer *st, int len)
101*28e138c6SAndroid Build Coastguard Worker {
102*28e138c6SAndroid Build Coastguard Worker /* This is almost the same as for speex_buffer_write() but using
103*28e138c6SAndroid Build Coastguard Worker SPEEX_MEMSET() instead of SPEEX_COPY(). Update accordingly. */
104*28e138c6SAndroid Build Coastguard Worker int end;
105*28e138c6SAndroid Build Coastguard Worker int end1;
106*28e138c6SAndroid Build Coastguard Worker if (len > st->size)
107*28e138c6SAndroid Build Coastguard Worker {
108*28e138c6SAndroid Build Coastguard Worker len = st->size;
109*28e138c6SAndroid Build Coastguard Worker }
110*28e138c6SAndroid Build Coastguard Worker end = st->write_ptr + len;
111*28e138c6SAndroid Build Coastguard Worker end1 = end;
112*28e138c6SAndroid Build Coastguard Worker if (end1 > st->size)
113*28e138c6SAndroid Build Coastguard Worker end1 = st->size;
114*28e138c6SAndroid Build Coastguard Worker SPEEX_MEMSET(st->data + st->write_ptr, 0, end1 - st->write_ptr);
115*28e138c6SAndroid Build Coastguard Worker if (end > st->size)
116*28e138c6SAndroid Build Coastguard Worker {
117*28e138c6SAndroid Build Coastguard Worker end -= st->size;
118*28e138c6SAndroid Build Coastguard Worker SPEEX_MEMSET(st->data, 0, end);
119*28e138c6SAndroid Build Coastguard Worker }
120*28e138c6SAndroid Build Coastguard Worker st->available += len;
121*28e138c6SAndroid Build Coastguard Worker if (st->available > st->size)
122*28e138c6SAndroid Build Coastguard Worker {
123*28e138c6SAndroid Build Coastguard Worker st->available = st->size;
124*28e138c6SAndroid Build Coastguard Worker st->read_ptr = st->write_ptr;
125*28e138c6SAndroid Build Coastguard Worker }
126*28e138c6SAndroid Build Coastguard Worker st->write_ptr += len;
127*28e138c6SAndroid Build Coastguard Worker if (st->write_ptr > st->size)
128*28e138c6SAndroid Build Coastguard Worker st->write_ptr -= st->size;
129*28e138c6SAndroid Build Coastguard Worker return len;
130*28e138c6SAndroid Build Coastguard Worker }
131*28e138c6SAndroid Build Coastguard Worker
speex_buffer_read(SpeexBuffer * st,void * _data,int len)132*28e138c6SAndroid Build Coastguard Worker EXPORT int speex_buffer_read(SpeexBuffer *st, void *_data, int len)
133*28e138c6SAndroid Build Coastguard Worker {
134*28e138c6SAndroid Build Coastguard Worker int end, end1;
135*28e138c6SAndroid Build Coastguard Worker char *data = _data;
136*28e138c6SAndroid Build Coastguard Worker if (len > st->available)
137*28e138c6SAndroid Build Coastguard Worker {
138*28e138c6SAndroid Build Coastguard Worker SPEEX_MEMSET(data+st->available, 0, len - st->available);
139*28e138c6SAndroid Build Coastguard Worker len = st->available;
140*28e138c6SAndroid Build Coastguard Worker }
141*28e138c6SAndroid Build Coastguard Worker end = st->read_ptr + len;
142*28e138c6SAndroid Build Coastguard Worker end1 = end;
143*28e138c6SAndroid Build Coastguard Worker if (end1 > st->size)
144*28e138c6SAndroid Build Coastguard Worker end1 = st->size;
145*28e138c6SAndroid Build Coastguard Worker SPEEX_COPY(data, st->data + st->read_ptr, end1 - st->read_ptr);
146*28e138c6SAndroid Build Coastguard Worker
147*28e138c6SAndroid Build Coastguard Worker if (end > st->size)
148*28e138c6SAndroid Build Coastguard Worker {
149*28e138c6SAndroid Build Coastguard Worker end -= st->size;
150*28e138c6SAndroid Build Coastguard Worker SPEEX_COPY(data+end1 - st->read_ptr, st->data, end);
151*28e138c6SAndroid Build Coastguard Worker }
152*28e138c6SAndroid Build Coastguard Worker st->available -= len;
153*28e138c6SAndroid Build Coastguard Worker st->read_ptr += len;
154*28e138c6SAndroid Build Coastguard Worker if (st->read_ptr > st->size)
155*28e138c6SAndroid Build Coastguard Worker st->read_ptr -= st->size;
156*28e138c6SAndroid Build Coastguard Worker return len;
157*28e138c6SAndroid Build Coastguard Worker }
158*28e138c6SAndroid Build Coastguard Worker
speex_buffer_get_available(SpeexBuffer * st)159*28e138c6SAndroid Build Coastguard Worker EXPORT int speex_buffer_get_available(SpeexBuffer *st)
160*28e138c6SAndroid Build Coastguard Worker {
161*28e138c6SAndroid Build Coastguard Worker return st->available;
162*28e138c6SAndroid Build Coastguard Worker }
163*28e138c6SAndroid Build Coastguard Worker
speex_buffer_resize(SpeexBuffer * st,int len)164*28e138c6SAndroid Build Coastguard Worker EXPORT int speex_buffer_resize(SpeexBuffer *st, int len)
165*28e138c6SAndroid Build Coastguard Worker {
166*28e138c6SAndroid Build Coastguard Worker int old_len = st->size;
167*28e138c6SAndroid Build Coastguard Worker if (len > old_len)
168*28e138c6SAndroid Build Coastguard Worker {
169*28e138c6SAndroid Build Coastguard Worker st->data = speex_realloc(st->data, len);
170*28e138c6SAndroid Build Coastguard Worker /* FIXME: move data/pointers properly for growing the buffer */
171*28e138c6SAndroid Build Coastguard Worker } else {
172*28e138c6SAndroid Build Coastguard Worker /* FIXME: move data/pointers properly for shrinking the buffer */
173*28e138c6SAndroid Build Coastguard Worker st->data = speex_realloc(st->data, len);
174*28e138c6SAndroid Build Coastguard Worker }
175*28e138c6SAndroid Build Coastguard Worker return len;
176*28e138c6SAndroid Build Coastguard Worker }
177