1 /*
2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 /*
12 * Provides a generic ring buffer that can be written to and read from with
13 * arbitrarily sized blocks. The AEC uses this for several different tasks.
14 */
15
16 #include <stdlib.h>
17 #include <string.h>
18 #include "ring_buffer.h"
19
20 typedef struct {
21 int readPos;
22 int writePos;
23 int size;
24 char rwWrap;
25 bufdata_t *data;
26 } buf_t;
27
28 enum {SAME_WRAP, DIFF_WRAP};
29
WebRtcApm_CreateBuffer(void ** bufInst,int size)30 int WebRtcApm_CreateBuffer(void **bufInst, int size)
31 {
32 buf_t *buf = NULL;
33
34 if (size < 0) {
35 return -1;
36 }
37
38 buf = malloc(sizeof(buf_t));
39 *bufInst = buf;
40 if (buf == NULL) {
41 return -1;
42 }
43
44 buf->data = malloc(size*sizeof(bufdata_t));
45 if (buf->data == NULL) {
46 free(buf);
47 buf = NULL;
48 return -1;
49 }
50
51 buf->size = size;
52 return 0;
53 }
54
WebRtcApm_InitBuffer(void * bufInst)55 int WebRtcApm_InitBuffer(void *bufInst)
56 {
57 buf_t *buf = (buf_t*)bufInst;
58
59 buf->readPos = 0;
60 buf->writePos = 0;
61 buf->rwWrap = SAME_WRAP;
62
63 // Initialize buffer to zeros
64 memset(buf->data, 0, sizeof(bufdata_t)*buf->size);
65
66 return 0;
67 }
68
WebRtcApm_FreeBuffer(void * bufInst)69 int WebRtcApm_FreeBuffer(void *bufInst)
70 {
71 buf_t *buf = (buf_t*)bufInst;
72
73 if (buf == NULL) {
74 return -1;
75 }
76
77 free(buf->data);
78 free(buf);
79
80 return 0;
81 }
82
WebRtcApm_ReadBuffer(void * bufInst,bufdata_t * data,int size)83 int WebRtcApm_ReadBuffer(void *bufInst, bufdata_t *data, int size)
84 {
85 buf_t *buf = (buf_t*)bufInst;
86 int n = 0, margin = 0;
87
88 if (size <= 0 || size > buf->size) {
89 return -1;
90 }
91
92 n = size;
93 if (buf->rwWrap == DIFF_WRAP) {
94 margin = buf->size - buf->readPos;
95 if (n > margin) {
96 buf->rwWrap = SAME_WRAP;
97 memcpy(data, buf->data + buf->readPos,
98 sizeof(bufdata_t)*margin);
99 buf->readPos = 0;
100 n = size - margin;
101 }
102 else {
103 memcpy(data, buf->data + buf->readPos,
104 sizeof(bufdata_t)*n);
105 buf->readPos += n;
106 return n;
107 }
108 }
109
110 if (buf->rwWrap == SAME_WRAP) {
111 margin = buf->writePos - buf->readPos;
112 if (margin > n)
113 margin = n;
114 memcpy(data + size - n, buf->data + buf->readPos,
115 sizeof(bufdata_t)*margin);
116 buf->readPos += margin;
117 n -= margin;
118 }
119
120 return size - n;
121 }
122
WebRtcApm_WriteBuffer(void * bufInst,const bufdata_t * data,int size)123 int WebRtcApm_WriteBuffer(void *bufInst, const bufdata_t *data, int size)
124 {
125 buf_t *buf = (buf_t*)bufInst;
126 int n = 0, margin = 0;
127
128 if (size < 0 || size > buf->size) {
129 return -1;
130 }
131
132 n = size;
133 if (buf->rwWrap == SAME_WRAP) {
134 margin = buf->size - buf->writePos;
135 if (n > margin) {
136 buf->rwWrap = DIFF_WRAP;
137 memcpy(buf->data + buf->writePos, data,
138 sizeof(bufdata_t)*margin);
139 buf->writePos = 0;
140 n = size - margin;
141 }
142 else {
143 memcpy(buf->data + buf->writePos, data,
144 sizeof(bufdata_t)*n);
145 buf->writePos += n;
146 return n;
147 }
148 }
149
150 if (buf->rwWrap == DIFF_WRAP) {
151 margin = buf->readPos - buf->writePos;
152 if (margin > n)
153 margin = n;
154 memcpy(buf->data + buf->writePos, data + size - n,
155 sizeof(bufdata_t)*margin);
156 buf->writePos += margin;
157 n -= margin;
158 }
159
160 return size - n;
161 }
162
WebRtcApm_FlushBuffer(void * bufInst,int size)163 int WebRtcApm_FlushBuffer(void *bufInst, int size)
164 {
165 buf_t *buf = (buf_t*)bufInst;
166 int n = 0, margin = 0;
167
168 if (size <= 0 || size > buf->size) {
169 return -1;
170 }
171
172 n = size;
173 if (buf->rwWrap == DIFF_WRAP) {
174 margin = buf->size - buf->readPos;
175 if (n > margin) {
176 buf->rwWrap = SAME_WRAP;
177 buf->readPos = 0;
178 n = size - margin;
179 }
180 else {
181 buf->readPos += n;
182 return n;
183 }
184 }
185
186 if (buf->rwWrap == SAME_WRAP) {
187 margin = buf->writePos - buf->readPos;
188 if (margin > n)
189 margin = n;
190 buf->readPos += margin;
191 n -= margin;
192 }
193
194 return size - n;
195 }
196
WebRtcApm_StuffBuffer(void * bufInst,int size)197 int WebRtcApm_StuffBuffer(void *bufInst, int size)
198 {
199 buf_t *buf = (buf_t*)bufInst;
200 int n = 0, margin = 0;
201
202 if (size <= 0 || size > buf->size) {
203 return -1;
204 }
205
206 n = size;
207 if (buf->rwWrap == SAME_WRAP) {
208 margin = buf->readPos;
209 if (n > margin) {
210 buf->rwWrap = DIFF_WRAP;
211 buf->readPos = buf->size - 1;
212 n -= margin + 1;
213 }
214 else {
215 buf->readPos -= n;
216 return n;
217 }
218 }
219
220 if (buf->rwWrap == DIFF_WRAP) {
221 margin = buf->readPos - buf->writePos;
222 if (margin > n)
223 margin = n;
224 buf->readPos -= margin;
225 n -= margin;
226 }
227
228 return size - n;
229 }
230
WebRtcApm_get_buffer_size(const void * bufInst)231 int WebRtcApm_get_buffer_size(const void *bufInst)
232 {
233 const buf_t *buf = (buf_t*)bufInst;
234
235 if (buf->rwWrap == SAME_WRAP)
236 return buf->writePos - buf->readPos;
237 else
238 return buf->size - buf->readPos + buf->writePos;
239 }
240