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