环形字符流缓存代码

对于频繁读写的字节流缓存,环形字节流可以重复使用空闲的内存,原理类似于环形队列。代码参考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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值