Hola
A raíz de estar trabajando en un reproductor MP3 con una memoria USB y un PIC24 necesité de una librería para implementar un buffer circular. En ese buffer se iba volcando el contenido del archivo MP3 y al mismo tiempo el códec VS1053B lo iba consumiendo. Lo conveniente era mantenerlo lleno para que la reproducción de audio no se entrecortara.
Estuve buscando la librería en línea y encontré la de
Jarno Elonen en su página web:
Ring buffer streaming in general - how to implementhttp://elonen.iki.fi/code/misc-notes/ringbuffer/Sólo que está hecha en C++ y se controla como un objeto. Con varias modificaciones puede funcionar en C sencillo y opera correctamente. Con este buffer me fue posible leer datos desde la memoria USB a 320kbps sin pérdida de bytes.
Si no conocen los buffers circulares, acá hay una excelente guía al respecto.
http://en.wikipedia.org/wiki/Ring_bufferCreo que es muy fácil de usar. La dejo adjunta.
Espero que les llegue a servir.
//Origen de la librería
//1997-06-19, Jarno Elonen <elonen<at>iki.fi> | URN:NBN:fi-fe20031153
//http://elonen.iki.fi/code/misc-notes/ringbuffer/
//Modificada a C sencillo por MigSantiago
//Prototipos de funciones
void Create_Ring_Buffer(BYTE* buffer, unsigned int buffer_size);
unsigned int Data_In( BYTE* data, unsigned int len );
unsigned int Data_Out( BYTE* outData, unsigned int len );
unsigned int SkipData( unsigned int len );
unsigned int Free_Space();
unsigned int Buffered_Bytes();
void Update_State();
//Variables internas
unsigned char *m_load_ptr, *m_consume_ptr;
unsigned char *m_buff_end;
unsigned char *m_buff;
int m_max_load, m_max_consume, m_data_in_buffer;
//Funciones públicas
void Create_Ring_Buffer( BYTE* buffer, unsigned int buffer_size )
{
m_buff = (unsigned char*)buffer;
m_buff_end = m_buff + buffer_size;
m_load_ptr = m_consume_ptr = m_buff;
m_max_load = buffer_size;
m_max_consume = m_data_in_buffer = 0;
Update_State();
}
// Try to add data to the buffer. After the call,
// 'len' contains the amount of bytes actually copied.
unsigned int Data_In( BYTE* data, unsigned int len )
{
if ( len > (unsigned int)m_max_load )
len = (unsigned int)m_max_load;
memcpy( m_load_ptr, data, len );
m_load_ptr += len;
m_data_in_buffer += len;
Update_State();
return len;
}
// Request 'len' bytes from the buffer. After the call,
// 'len' contains the amount of bytes actually copied.
unsigned int Data_Out( BYTE* outData, unsigned int len )
{
if ( len > (unsigned int)m_max_consume )
len = (unsigned int)m_max_consume;
memcpy( outData, m_consume_ptr, len );
m_consume_ptr += len;
m_data_in_buffer -= len;
Update_State();
return len;
}
// Tries to skip len bytes. After the call,
// 'len' contains the realized skip.
unsigned int SkipData( unsigned int len )
{
int i;
int skip;
unsigned int requestedSkip = len;
for (i=0; i<2; ++i ) // This may wrap so try it twice
{
skip = (int)len;
if ( skip > m_max_consume )
skip = m_max_consume;
m_consume_ptr += skip;
m_data_in_buffer -= skip;
len -= skip;
Update_State();
}
len = requestedSkip - len;
return len;
}
// The amount of data the buffer can currently receive on one Data_In() call.
unsigned int Free_Space() { return (unsigned int)m_max_load; }
// The total amount of data in the buffer. Note that it may not be continuous: you may need
// two successive calls to Get_Data() to get it all.
unsigned int Buffered_Bytes() { return (unsigned int)m_data_in_buffer; }
//Funciones privadas
void Update_State()
{
if (m_consume_ptr == m_buff_end) m_consume_ptr = m_buff;
if (m_load_ptr == m_buff_end) m_load_ptr = m_buff;
if (m_load_ptr == m_consume_ptr)
{
if ( m_data_in_buffer > 0 )
{
m_max_load = 0;
m_max_consume = m_buff_end - m_consume_ptr;
}
else
{
m_max_load = m_buff_end - m_load_ptr;
m_max_consume = 0;
}
}
else if ( m_load_ptr > m_consume_ptr )
{
m_max_load = m_buff_end - m_load_ptr;
m_max_consume = m_load_ptr - m_consume_ptr;
}
else
{
m_max_load = m_consume_ptr - m_load_ptr;
m_max_consume = m_buff_end - m_consume_ptr;
}
}