#ifndef CUBEB_RING_ARRAY_H
#define CUBEB_RING_ARRAY_H
#include "cubeb_utils.h"
typedef struct {
AudioBuffer * buffer_array;
unsigned int tail;
unsigned int count;
unsigned int capacity;
} ring_array;
static int
single_audiobuffer_init(AudioBuffer * buffer,
uint32_t bytesPerFrame,
uint32_t channelsPerFrame,
uint32_t frames)
{
assert(buffer);
assert(bytesPerFrame > 0 && channelsPerFrame && frames > 0);
size_t size = bytesPerFrame * frames;
buffer->mData = operator new(size);
if (buffer->mData == NULL) {
return CUBEB_ERROR;
}
PodZero(static_cast<char*>(buffer->mData), size);
buffer->mNumberChannels = channelsPerFrame;
buffer->mDataByteSize = size;
return CUBEB_OK;
}
int
ring_array_init(ring_array * ra,
uint32_t capacity,
uint32_t bytesPerFrame,
uint32_t channelsPerFrame,
uint32_t framesPerBuffer)
{
assert(ra);
if (capacity == 0 || bytesPerFrame == 0 ||
channelsPerFrame == 0 || framesPerBuffer == 0) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
ra->capacity = capacity;
ra->tail = 0;
ra->count = 0;
ra->buffer_array = new AudioBuffer[ra->capacity];
PodZero(ra->buffer_array, ra->capacity);
if (ra->buffer_array == NULL) {
return CUBEB_ERROR;
}
for (unsigned int i = 0; i < ra->capacity; ++i) {
if (single_audiobuffer_init(&ra->buffer_array[i],
bytesPerFrame,
channelsPerFrame,
framesPerBuffer) != CUBEB_OK) {
return CUBEB_ERROR;
}
}
return CUBEB_OK;
}
void
ring_array_destroy(ring_array * ra)
{
assert(ra);
if (ra->buffer_array == NULL){
return;
}
for (unsigned int i = 0; i < ra->capacity; ++i) {
if (ra->buffer_array[i].mData) {
operator delete(ra->buffer_array[i].mData);
}
}
delete [] ra->buffer_array;
}
AudioBuffer *
ring_array_get_free_buffer(ring_array * ra)
{
assert(ra && ra->buffer_array);
assert(ra->buffer_array[0].mData != NULL);
if (ra->count == ra->capacity) {
return NULL;
}
assert(ra->count == 0 || (ra->tail + ra->count) % ra->capacity != ra->tail);
AudioBuffer * ret = &ra->buffer_array[(ra->tail + ra->count) % ra->capacity];
++ra->count;
assert(ra->count <= ra->capacity);
return ret;
}
AudioBuffer *
ring_array_get_data_buffer(ring_array * ra)
{
assert(ra && ra->buffer_array);
assert(ra->buffer_array[0].mData != NULL);
if (ra->count == 0) {
return NULL;
}
AudioBuffer * ret = &ra->buffer_array[ra->tail];
ra->tail = (ra->tail + 1) % ra->capacity;
assert(ra->tail < ra->capacity);
assert(ra->count > 0);
--ra->count;
return ret;
}
AudioBuffer *
ring_array_get_dummy_buffer(ring_array * ra)
{
assert(ra && ra->buffer_array);
assert(ra->capacity > 0);
if (ra->count > 0) {
return NULL;
}
return &ra->buffer_array[0];
}
#endif