bryan wade / Mbed 2 deprecated usb_sound_effects

Dependencies:   C12832_lcd MMA7660 USBDevice mbed

buffer.cpp

Committer:
bw
Date:
2014-03-27
Revision:
2:9429f84ea165
Parent:
0:bbf6cf0eab95

File content as of revision 2:9429f84ea165:

/*******************************************************************************
 * Implements FIFO buffer for glitch-free audio playback.
 * Bryan Wade
 * 27 MAR 2014
 ******************************************************************************/
#include "buffer.h"
#include "string.h"

struct buffer_t { // Implementation of opaque type.
    int16_t *base;
    int16_t *head;
    int16_t *tail;
    size_t len;
};

/*
 * Create a buffer object given a ptr and size of available RAM.
 * @return Ptr to the new buffer.
 */
buffer_t *Buffer_Create(void *ram, size_t size)
{
    buffer_t *buffer = (buffer_t *)malloc(sizeof(buffer_t));
    if (buffer) {
        buffer->base = (int16_t *)ram;
        buffer->len = size / sizeof(int16_t);
        memset(ram, 0, size);
        buffer->head = buffer->tail = buffer->base;
    }
    return buffer;
}

/*
 * Read a single sample from the buffer.
 * @return True if successful (no underflow).
 */
bool Buffer_Read(buffer_t *buffer, int16_t *pDataOut)
{
    if (buffer->head == buffer->tail)
        return false;

    *pDataOut = *buffer->tail;

    if (++buffer->tail >= buffer->base + buffer->len) {
        buffer->tail = buffer->base;
    }

    return true;
}

/*
 * Write a single sample to the buffer.
 */
void Buffer_Write(buffer_t *buffer, int16_t dataIn)
{
    if (Buffer_GetLevel(buffer) >= buffer->len - 1)
        return;
    
    *buffer->head = dataIn;

    if (++buffer->head >= buffer->base + buffer->len)
        buffer->head = buffer->base;
}

/*
 * Write a block of data to the buffer.
 */
void Buffer_WriteBlock(buffer_t *buffer, const int16_t *pDataIn, uint32_t length)
{
    int i;
    for (i = 0; i < length; i++) {
        Buffer_Write(buffer, pDataIn[i]);
    }
}

/*
 * Get buffer level
 */
int32_t Buffer_GetLevel(buffer_t *buffer) 
{
    __disable_irq(); /* Begin critical section */
    
    int32_t level = (buffer->head >= buffer->tail) ?
                    buffer->head - buffer->tail :
                    buffer->len + buffer->head - buffer->tail;
                    
    __enable_irq(); /* End critical section */
    
    return level;
}