diff options
Diffstat (limited to 'src/modules/audio_processing/utility/ring_buffer.c')
-rw-r--r-- | src/modules/audio_processing/utility/ring_buffer.c | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/src/modules/audio_processing/utility/ring_buffer.c b/src/modules/audio_processing/utility/ring_buffer.c new file mode 100644 index 0000000000..ea2e3544be --- /dev/null +++ b/src/modules/audio_processing/utility/ring_buffer.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +/* + * Provides a generic ring buffer that can be written to and read from with + * arbitrarily sized blocks. The AEC uses this for several different tasks. + */ + +#include <stdlib.h> +#include <string.h> +#include "ring_buffer.h" + +typedef struct { + int readPos; + int writePos; + int size; + char rwWrap; + bufdata_t *data; +} buf_t; + +enum {SAME_WRAP, DIFF_WRAP}; + +int WebRtcApm_CreateBuffer(void **bufInst, int size) +{ + buf_t *buf = NULL; + + if (size < 0) { + return -1; + } + + buf = malloc(sizeof(buf_t)); + *bufInst = buf; + if (buf == NULL) { + return -1; + } + + buf->data = malloc(size*sizeof(bufdata_t)); + if (buf->data == NULL) { + free(buf); + buf = NULL; + return -1; + } + + buf->size = size; + return 0; +} + +int WebRtcApm_InitBuffer(void *bufInst) +{ + buf_t *buf = (buf_t*)bufInst; + + buf->readPos = 0; + buf->writePos = 0; + buf->rwWrap = SAME_WRAP; + + // Initialize buffer to zeros + memset(buf->data, 0, sizeof(bufdata_t)*buf->size); + + return 0; +} + +int WebRtcApm_FreeBuffer(void *bufInst) +{ + buf_t *buf = (buf_t*)bufInst; + + if (buf == NULL) { + return -1; + } + + free(buf->data); + free(buf); + + return 0; +} + +int WebRtcApm_ReadBuffer(void *bufInst, bufdata_t *data, int size) +{ + buf_t *buf = (buf_t*)bufInst; + int n = 0, margin = 0; + + if (size <= 0 || size > buf->size) { + return -1; + } + + n = size; + if (buf->rwWrap == DIFF_WRAP) { + margin = buf->size - buf->readPos; + if (n > margin) { + buf->rwWrap = SAME_WRAP; + memcpy(data, buf->data + buf->readPos, + sizeof(bufdata_t)*margin); + buf->readPos = 0; + n = size - margin; + } + else { + memcpy(data, buf->data + buf->readPos, + sizeof(bufdata_t)*n); + buf->readPos += n; + return n; + } + } + + if (buf->rwWrap == SAME_WRAP) { + margin = buf->writePos - buf->readPos; + if (margin > n) + margin = n; + memcpy(data + size - n, buf->data + buf->readPos, + sizeof(bufdata_t)*margin); + buf->readPos += margin; + n -= margin; + } + + return size - n; +} + +int WebRtcApm_WriteBuffer(void *bufInst, const bufdata_t *data, int size) +{ + buf_t *buf = (buf_t*)bufInst; + int n = 0, margin = 0; + + if (size < 0 || size > buf->size) { + return -1; + } + + n = size; + if (buf->rwWrap == SAME_WRAP) { + margin = buf->size - buf->writePos; + if (n > margin) { + buf->rwWrap = DIFF_WRAP; + memcpy(buf->data + buf->writePos, data, + sizeof(bufdata_t)*margin); + buf->writePos = 0; + n = size - margin; + } + else { + memcpy(buf->data + buf->writePos, data, + sizeof(bufdata_t)*n); + buf->writePos += n; + return n; + } + } + + if (buf->rwWrap == DIFF_WRAP) { + margin = buf->readPos - buf->writePos; + if (margin > n) + margin = n; + memcpy(buf->data + buf->writePos, data + size - n, + sizeof(bufdata_t)*margin); + buf->writePos += margin; + n -= margin; + } + + return size - n; +} + +int WebRtcApm_FlushBuffer(void *bufInst, int size) +{ + buf_t *buf = (buf_t*)bufInst; + int n = 0, margin = 0; + + if (size <= 0 || size > buf->size) { + return -1; + } + + n = size; + if (buf->rwWrap == DIFF_WRAP) { + margin = buf->size - buf->readPos; + if (n > margin) { + buf->rwWrap = SAME_WRAP; + buf->readPos = 0; + n = size - margin; + } + else { + buf->readPos += n; + return n; + } + } + + if (buf->rwWrap == SAME_WRAP) { + margin = buf->writePos - buf->readPos; + if (margin > n) + margin = n; + buf->readPos += margin; + n -= margin; + } + + return size - n; +} + +int WebRtcApm_StuffBuffer(void *bufInst, int size) +{ + buf_t *buf = (buf_t*)bufInst; + int n = 0, margin = 0; + + if (size <= 0 || size > buf->size) { + return -1; + } + + n = size; + if (buf->rwWrap == SAME_WRAP) { + margin = buf->readPos; + if (n > margin) { + buf->rwWrap = DIFF_WRAP; + buf->readPos = buf->size - 1; + n -= margin + 1; + } + else { + buf->readPos -= n; + return n; + } + } + + if (buf->rwWrap == DIFF_WRAP) { + margin = buf->readPos - buf->writePos; + if (margin > n) + margin = n; + buf->readPos -= margin; + n -= margin; + } + + return size - n; +} + +int WebRtcApm_get_buffer_size(const void *bufInst) +{ + const buf_t *buf = (buf_t*)bufInst; + + if (buf->rwWrap == SAME_WRAP) + return buf->writePos - buf->readPos; + else + return buf->size - buf->readPos + buf->writePos; +} |