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 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 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 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 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 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 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 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 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