198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/* Copyright (C) 2007 Jean-Marc Valin 298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project File: buffer.c 498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project This is a very simple ring buffer implementation. It is not thread-safe 598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project so you need to do your own locking. 698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project Redistribution and use in source and binary forms, with or without 898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project modification, are permitted provided that the following conditions are 998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project met: 1098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 1198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 1. Redistributions of source code must retain the above copyright notice, 1298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project this list of conditions and the following disclaimer. 1398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 1498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 2. Redistributions in binary form must reproduce the above copyright 1598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project notice, this list of conditions and the following disclaimer in the 1698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project documentation and/or other materials provided with the distribution. 1798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 1898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 3. The name of the author may not be used to endorse or promote products 1998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project derived from this software without specific prior written permission. 2098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 2198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 2598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 3098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project POSSIBILITY OF SUCH DAMAGE. 3298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project*/ 3398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 3498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef HAVE_CONFIG_H 3598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "config.h" 3698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif 3798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 3898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 3998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "os_support.h" 4098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "arch.h" 4198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include <speex/speex_buffer.h> 4298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 4398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstruct SpeexBuffer_ { 4498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project char *data; 4598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int size; 4698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int read_ptr; 4798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int write_ptr; 4898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int available; 4998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}; 5098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 5198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT SpeexBuffer *speex_buffer_init(int size) 5298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 5398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project SpeexBuffer *st = speex_alloc(sizeof(SpeexBuffer)); 5498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->data = speex_alloc(size); 5598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->size = size; 5698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->read_ptr = 0; 5798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->write_ptr = 0; 5898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->available = 0; 5998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return st; 6098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 6198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 6298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT void speex_buffer_destroy(SpeexBuffer *st) 6398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 6498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project speex_free(st->data); 6598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project speex_free(st); 6698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 6798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 6898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT int speex_buffer_write(SpeexBuffer *st, void *_data, int len) 6998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 7098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int end; 7198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int end1; 7298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project char *data = _data; 7398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (len > st->size) 7498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 7598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project data += len-st->size; 7698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project len = st->size; 7798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 7898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project end = st->write_ptr + len; 7998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project end1 = end; 8098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (end1 > st->size) 8198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project end1 = st->size; 8298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project SPEEX_COPY(st->data + st->write_ptr, data, end1 - st->write_ptr); 8398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (end > st->size) 8498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 8598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project end -= st->size; 8698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project SPEEX_COPY(st->data, data+end1 - st->write_ptr, end); 8798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 8898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->available += len; 8998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (st->available > st->size) 9098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 9198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->available = st->size; 9298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->read_ptr = st->write_ptr; 9398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 9498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->write_ptr += len; 9598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (st->write_ptr > st->size) 9698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->write_ptr -= st->size; 9798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return len; 9898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 9998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 10098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT int speex_buffer_writezeros(SpeexBuffer *st, int len) 10198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 10298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* This is almost the same as for speex_buffer_write() but using 10398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project SPEEX_MEMSET() instead of SPEEX_COPY(). Update accordingly. */ 10498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int end; 10598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int end1; 10698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (len > st->size) 10798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 10898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project len = st->size; 10998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 11098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project end = st->write_ptr + len; 11198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project end1 = end; 11298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (end1 > st->size) 11398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project end1 = st->size; 11498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project SPEEX_MEMSET(st->data + st->write_ptr, 0, end1 - st->write_ptr); 11598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (end > st->size) 11698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 11798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project end -= st->size; 11898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project SPEEX_MEMSET(st->data, 0, end); 11998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 12098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->available += len; 12198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (st->available > st->size) 12298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 12398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->available = st->size; 12498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->read_ptr = st->write_ptr; 12598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 12698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->write_ptr += len; 12798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (st->write_ptr > st->size) 12898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->write_ptr -= st->size; 12998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return len; 13098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 13198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 13298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT int speex_buffer_read(SpeexBuffer *st, void *_data, int len) 13398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 13498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int end, end1; 13598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project char *data = _data; 13698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (len > st->available) 13798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 13898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project SPEEX_MEMSET(data+st->available, 0, st->size-st->available); 13998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project len = st->available; 14098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 14198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project end = st->read_ptr + len; 14298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project end1 = end; 14398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (end1 > st->size) 14498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project end1 = st->size; 14598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project SPEEX_COPY(data, st->data + st->read_ptr, end1 - st->read_ptr); 14698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 14798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (end > st->size) 14898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 14998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project end -= st->size; 15098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project SPEEX_COPY(data+end1 - st->read_ptr, st->data, end); 15198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 15298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->available -= len; 15398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->read_ptr += len; 15498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (st->read_ptr > st->size) 15598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->read_ptr -= st->size; 15698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return len; 15798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 15898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 15998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT int speex_buffer_get_available(SpeexBuffer *st) 16098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 16198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return st->available; 16298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 16398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 16498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT int speex_buffer_resize(SpeexBuffer *st, int len) 16598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{ 16698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int old_len = st->size; 16798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (len > old_len) 16898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project { 16998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->data = speex_realloc(st->data, len); 17098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* FIXME: move data/pointers properly for growing the buffer */ 17198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } else { 17298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* FIXME: move data/pointers properly for shrinking the buffer */ 17398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project st->data = speex_realloc(st->data, len); 17498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 17598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return len; 17698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 177