Home | History | Annotate | Download | only in utility
      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