对于频繁读写的字节流缓存,环形字节流可以重复使用空闲的内存,原理类似于环形队列。代码参考speex,代码已经经过测试使用。
/**
* @file circular_buffer.h
* @brief
*
* 循环字节流缓存,能够自动增加缓存,参考speex
*
* @author yswang
* @version 1.0
* @date 2012年6月18日
*
* @see
*
* @par 版本记录:
* <table border=1>
* <tr> <th>版本 <th>日期 <th>作者 <th>备注 </tr>
* <tr> <td>1.0 <td>2012年6月18日 <td>yswang <td>创建 </tr>
* </table>
*/
#ifndef _CIRCULAR_BUFFER_H_
#define _CIRCULAR_BUFFER_H_
#ifdef ___cplusplus
extern "C" {
#endif
struct circular_buffer_;
typedef struct circular_buffer_ circular_buffer;
circular_buffer *circular_buffer_init(int size);
void circular_buffer_destroy(circular_buffer *st);
int circular_buffer_write(circular_buffer *st, void *data, int len);
int circular_buffer_writezeros(circular_buffer *st, int len);
int circular_buffer_read(circular_buffer *st, void *data, int len);
int circular_buffer_get_available(circular_buffer *st);
int circular_buffer_resize(circular_buffer *st, int len);
#ifdef ___cplusplus
}
#endif
#endif // _CIRCULAR_BUFFER_H_
/**
* @file circular_buffer.cpp
* @brief
*
*
*
* @author yswang
* @version 1.0
* @date 2012年6月18日
*
* @see
*
* @par 版本记录:
* <table border=1>
* <tr> <th>版本 <th>日期 <th>作者 <th>备注 </tr>
* <tr> <td>1.0 <td>2012年6月18日 <td>yswang <td>创建 </tr>
* </table>
*/
#include <stdlib.h>
#include "circular_buffer.h"
#define dsound_alloc(size) \
calloc(size, 1); \
#define dsound_realloc(ptr, size) \
realloc(ptr, size); \
#define dsound_free(ptr) \
free(ptr); \
#define DSOUND_COPY(dst, src, n) (memcpy((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) ))
#define DSOUND_MOVE(dst, src, n) (memmove((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) ))
#define DSOUND_MEMSET(dst, c, n) (memset((dst), (c), (n)*sizeof(*(dst))))
//////////////////////////////////////////////////////////////////////////
struct circular_buffer_
{
char *data;
int size; // 内存大小
int read_ptr; // 读指针
int write_ptr; // 写指针
int available; // 可读字节数(实际字节 write_ptr - read_ptr )
};
//////////////////////////////////////////////////////////////////////////
circular_buffer * circular_buffer_init(int size)
{
circular_buffer * st = dsound_alloc(sizeof(circular_buffer));
st->data = dsound_alloc(size);
st->size = size;
st->read_ptr = 0;
st->write_ptr = 0;
st->available = 0;
return st;
}
void circular_buffer_destroy(circular_buffer *st)
{
dsound_free(st->data);
dsound_free(st);
}
int circular_buffer_write(circular_buffer *st, void * _data, int len)
{
int end, end1; // 写后的位置
int newlen;
char * data = _data;
if (len > st->size - st->available) // 大于剩余的空间(剩余空间不足,重新分配)
{
newlen = st->available + len;
newlen *= 2; // 2倍空间,预留
circular_buffer_resize(st, newlen);
}
end = st->write_ptr + len;
end1 = end;
if (end1 > st->size)
end1 = st->size;
DSOUND_COPY(st->data + st->write_ptr, data, end1 - st->write_ptr);
if (end > st->size)
{
end -= st->size;
DSOUND_COPY(st->data, data + end1 - st->write_ptr, end);
}
st->available += len;
st->write_ptr += len;
if (st->write_ptr > st->size) // 保证指针在有效范围内
st->write_ptr -= st->size;
return len;
}
int circular_buffer_read(circular_buffer *st, void * _data, int len)
{
int end, end1; // 读取后的位置
char * data = _data;
if (len > st->available) // 读取有效的直接
{
//DSOUND_MEMSET(data + st->available, 0, st->size - st->available);
len = st->available;
}
end = st->read_ptr + len;
end1 = end;
/*
* ||-------------|----------------------||
* &######################&
* read_ptr end1
* ####&#####&
* end write_ptr
**/
if (end1 > st->size)
end1 = st->size;
DSOUND_COPY(data, st->data + st->read_ptr, end1 - st->read_ptr);
if (end > st->size)
{
end -= st->size;
DSOUND_COPY(data + end1 - st->read_ptr, st->data, end);
}
st->available -= len;
st->read_ptr += len;
if (st->read_ptr > st->size) // 保证指针在有效范围内
st->read_ptr -= st->size;
return len;
}
int circular_buffer_get_available(circular_buffer *st)
{
return st->available;
}
int circular_buffer_resize(circular_buffer *st, int len)
{
int end, end1;
char * data;
int oldlen = st->size;
data = dsound_alloc(len);
if (!data)
return -1;
// 拷贝内存
end = st->read_ptr + st->available;
end1 = end;
if (end1 > st->size)
end1 = st->size;
DSOUND_COPY(data, st->data + st->read_ptr, end1 - st->read_ptr);
if (end > st->size)
{
end -= st->size;
DSOUND_COPY(data + end1 - st->read_ptr, st->data, end);
}
// 更新状态
free(st->data);
st->data = data;
st->size = len;
st->read_ptr = 0;
st->write_ptr = st->available;
return 0;
}