153a5a1b3Sopenharmony_ci/* Copyright (C) 2007 Jean-Marc Valin 253a5a1b3Sopenharmony_ci 353a5a1b3Sopenharmony_ci File: buffer.c 453a5a1b3Sopenharmony_ci This is a very simple ring buffer implementation. It is not thread-safe 553a5a1b3Sopenharmony_ci so you need to do your own locking. 653a5a1b3Sopenharmony_ci 753a5a1b3Sopenharmony_ci Redistribution and use in source and binary forms, with or without 853a5a1b3Sopenharmony_ci modification, are permitted provided that the following conditions are 953a5a1b3Sopenharmony_ci met: 1053a5a1b3Sopenharmony_ci 1153a5a1b3Sopenharmony_ci 1. Redistributions of source code must retain the above copyright notice, 1253a5a1b3Sopenharmony_ci this list of conditions and the following disclaimer. 1353a5a1b3Sopenharmony_ci 1453a5a1b3Sopenharmony_ci 2. Redistributions in binary form must reproduce the above copyright 1553a5a1b3Sopenharmony_ci notice, this list of conditions and the following disclaimer in the 1653a5a1b3Sopenharmony_ci documentation and/or other materials provided with the distribution. 1753a5a1b3Sopenharmony_ci 1853a5a1b3Sopenharmony_ci 3. The name of the author may not be used to endorse or promote products 1953a5a1b3Sopenharmony_ci derived from this software without specific prior written permission. 2053a5a1b3Sopenharmony_ci 2153a5a1b3Sopenharmony_ci THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2253a5a1b3Sopenharmony_ci IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2353a5a1b3Sopenharmony_ci OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2453a5a1b3Sopenharmony_ci DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 2553a5a1b3Sopenharmony_ci INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2653a5a1b3Sopenharmony_ci (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2753a5a1b3Sopenharmony_ci SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2853a5a1b3Sopenharmony_ci HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2953a5a1b3Sopenharmony_ci STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 3053a5a1b3Sopenharmony_ci ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3153a5a1b3Sopenharmony_ci POSSIBILITY OF SUCH DAMAGE. 3253a5a1b3Sopenharmony_ci*/ 3353a5a1b3Sopenharmony_ci 3453a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H 3553a5a1b3Sopenharmony_ci#include "config.h" 3653a5a1b3Sopenharmony_ci#endif 3753a5a1b3Sopenharmony_ci 3853a5a1b3Sopenharmony_ci 3953a5a1b3Sopenharmony_ci#include "os_support.h" 4053a5a1b3Sopenharmony_ci#include "arch.h" 4153a5a1b3Sopenharmony_ci#include "speex/speex_buffer.h" 4253a5a1b3Sopenharmony_ci 4353a5a1b3Sopenharmony_cistruct SpeexBuffer_ { 4453a5a1b3Sopenharmony_ci char *data; 4553a5a1b3Sopenharmony_ci int size; 4653a5a1b3Sopenharmony_ci int read_ptr; 4753a5a1b3Sopenharmony_ci int write_ptr; 4853a5a1b3Sopenharmony_ci int available; 4953a5a1b3Sopenharmony_ci}; 5053a5a1b3Sopenharmony_ci 5153a5a1b3Sopenharmony_ciEXPORT SpeexBuffer *speex_buffer_init(int size) 5253a5a1b3Sopenharmony_ci{ 5353a5a1b3Sopenharmony_ci SpeexBuffer *st = speex_alloc(sizeof(SpeexBuffer)); 5453a5a1b3Sopenharmony_ci st->data = speex_alloc(size); 5553a5a1b3Sopenharmony_ci st->size = size; 5653a5a1b3Sopenharmony_ci st->read_ptr = 0; 5753a5a1b3Sopenharmony_ci st->write_ptr = 0; 5853a5a1b3Sopenharmony_ci st->available = 0; 5953a5a1b3Sopenharmony_ci return st; 6053a5a1b3Sopenharmony_ci} 6153a5a1b3Sopenharmony_ci 6253a5a1b3Sopenharmony_ciEXPORT void speex_buffer_destroy(SpeexBuffer *st) 6353a5a1b3Sopenharmony_ci{ 6453a5a1b3Sopenharmony_ci speex_free(st->data); 6553a5a1b3Sopenharmony_ci speex_free(st); 6653a5a1b3Sopenharmony_ci} 6753a5a1b3Sopenharmony_ci 6853a5a1b3Sopenharmony_ciEXPORT int speex_buffer_write(SpeexBuffer *st, void *_data, int len) 6953a5a1b3Sopenharmony_ci{ 7053a5a1b3Sopenharmony_ci int end; 7153a5a1b3Sopenharmony_ci int end1; 7253a5a1b3Sopenharmony_ci char *data = _data; 7353a5a1b3Sopenharmony_ci if (len > st->size) 7453a5a1b3Sopenharmony_ci { 7553a5a1b3Sopenharmony_ci data += len-st->size; 7653a5a1b3Sopenharmony_ci len = st->size; 7753a5a1b3Sopenharmony_ci } 7853a5a1b3Sopenharmony_ci end = st->write_ptr + len; 7953a5a1b3Sopenharmony_ci end1 = end; 8053a5a1b3Sopenharmony_ci if (end1 > st->size) 8153a5a1b3Sopenharmony_ci end1 = st->size; 8253a5a1b3Sopenharmony_ci SPEEX_COPY(st->data + st->write_ptr, data, end1 - st->write_ptr); 8353a5a1b3Sopenharmony_ci if (end > st->size) 8453a5a1b3Sopenharmony_ci { 8553a5a1b3Sopenharmony_ci end -= st->size; 8653a5a1b3Sopenharmony_ci SPEEX_COPY(st->data, data+end1 - st->write_ptr, end); 8753a5a1b3Sopenharmony_ci } 8853a5a1b3Sopenharmony_ci st->available += len; 8953a5a1b3Sopenharmony_ci if (st->available > st->size) 9053a5a1b3Sopenharmony_ci { 9153a5a1b3Sopenharmony_ci st->available = st->size; 9253a5a1b3Sopenharmony_ci st->read_ptr = st->write_ptr; 9353a5a1b3Sopenharmony_ci } 9453a5a1b3Sopenharmony_ci st->write_ptr += len; 9553a5a1b3Sopenharmony_ci if (st->write_ptr > st->size) 9653a5a1b3Sopenharmony_ci st->write_ptr -= st->size; 9753a5a1b3Sopenharmony_ci return len; 9853a5a1b3Sopenharmony_ci} 9953a5a1b3Sopenharmony_ci 10053a5a1b3Sopenharmony_ciEXPORT int speex_buffer_writezeros(SpeexBuffer *st, int len) 10153a5a1b3Sopenharmony_ci{ 10253a5a1b3Sopenharmony_ci /* This is almost the same as for speex_buffer_write() but using 10353a5a1b3Sopenharmony_ci SPEEX_MEMSET() instead of SPEEX_COPY(). Update accordingly. */ 10453a5a1b3Sopenharmony_ci int end; 10553a5a1b3Sopenharmony_ci int end1; 10653a5a1b3Sopenharmony_ci if (len > st->size) 10753a5a1b3Sopenharmony_ci { 10853a5a1b3Sopenharmony_ci len = st->size; 10953a5a1b3Sopenharmony_ci } 11053a5a1b3Sopenharmony_ci end = st->write_ptr + len; 11153a5a1b3Sopenharmony_ci end1 = end; 11253a5a1b3Sopenharmony_ci if (end1 > st->size) 11353a5a1b3Sopenharmony_ci end1 = st->size; 11453a5a1b3Sopenharmony_ci SPEEX_MEMSET(st->data + st->write_ptr, 0, end1 - st->write_ptr); 11553a5a1b3Sopenharmony_ci if (end > st->size) 11653a5a1b3Sopenharmony_ci { 11753a5a1b3Sopenharmony_ci end -= st->size; 11853a5a1b3Sopenharmony_ci SPEEX_MEMSET(st->data, 0, end); 11953a5a1b3Sopenharmony_ci } 12053a5a1b3Sopenharmony_ci st->available += len; 12153a5a1b3Sopenharmony_ci if (st->available > st->size) 12253a5a1b3Sopenharmony_ci { 12353a5a1b3Sopenharmony_ci st->available = st->size; 12453a5a1b3Sopenharmony_ci st->read_ptr = st->write_ptr; 12553a5a1b3Sopenharmony_ci } 12653a5a1b3Sopenharmony_ci st->write_ptr += len; 12753a5a1b3Sopenharmony_ci if (st->write_ptr > st->size) 12853a5a1b3Sopenharmony_ci st->write_ptr -= st->size; 12953a5a1b3Sopenharmony_ci return len; 13053a5a1b3Sopenharmony_ci} 13153a5a1b3Sopenharmony_ci 13253a5a1b3Sopenharmony_ciEXPORT int speex_buffer_read(SpeexBuffer *st, void *_data, int len) 13353a5a1b3Sopenharmony_ci{ 13453a5a1b3Sopenharmony_ci int end, end1; 13553a5a1b3Sopenharmony_ci char *data = _data; 13653a5a1b3Sopenharmony_ci if (len > st->available) 13753a5a1b3Sopenharmony_ci { 13853a5a1b3Sopenharmony_ci SPEEX_MEMSET(data+st->available, 0, len - st->available); 13953a5a1b3Sopenharmony_ci len = st->available; 14053a5a1b3Sopenharmony_ci } 14153a5a1b3Sopenharmony_ci end = st->read_ptr + len; 14253a5a1b3Sopenharmony_ci end1 = end; 14353a5a1b3Sopenharmony_ci if (end1 > st->size) 14453a5a1b3Sopenharmony_ci end1 = st->size; 14553a5a1b3Sopenharmony_ci SPEEX_COPY(data, st->data + st->read_ptr, end1 - st->read_ptr); 14653a5a1b3Sopenharmony_ci 14753a5a1b3Sopenharmony_ci if (end > st->size) 14853a5a1b3Sopenharmony_ci { 14953a5a1b3Sopenharmony_ci end -= st->size; 15053a5a1b3Sopenharmony_ci SPEEX_COPY(data+end1 - st->read_ptr, st->data, end); 15153a5a1b3Sopenharmony_ci } 15253a5a1b3Sopenharmony_ci st->available -= len; 15353a5a1b3Sopenharmony_ci st->read_ptr += len; 15453a5a1b3Sopenharmony_ci if (st->read_ptr > st->size) 15553a5a1b3Sopenharmony_ci st->read_ptr -= st->size; 15653a5a1b3Sopenharmony_ci return len; 15753a5a1b3Sopenharmony_ci} 15853a5a1b3Sopenharmony_ci 15953a5a1b3Sopenharmony_ciEXPORT int speex_buffer_get_available(SpeexBuffer *st) 16053a5a1b3Sopenharmony_ci{ 16153a5a1b3Sopenharmony_ci return st->available; 16253a5a1b3Sopenharmony_ci} 16353a5a1b3Sopenharmony_ci 16453a5a1b3Sopenharmony_ciEXPORT int speex_buffer_resize(SpeexBuffer *st, int len) 16553a5a1b3Sopenharmony_ci{ 16653a5a1b3Sopenharmony_ci int old_len = st->size; 16753a5a1b3Sopenharmony_ci if (len > old_len) 16853a5a1b3Sopenharmony_ci { 16953a5a1b3Sopenharmony_ci st->data = speex_realloc(st->data, len); 17053a5a1b3Sopenharmony_ci /* FIXME: move data/pointers properly for growing the buffer */ 17153a5a1b3Sopenharmony_ci } else { 17253a5a1b3Sopenharmony_ci /* FIXME: move data/pointers properly for shrinking the buffer */ 17353a5a1b3Sopenharmony_ci st->data = speex_realloc(st->data, len); 17453a5a1b3Sopenharmony_ci } 17553a5a1b3Sopenharmony_ci return len; 17653a5a1b3Sopenharmony_ci} 177