一个特殊需求的环形Buffer设计

22 篇文章 1 订阅
14 篇文章 0 订阅

最近有一个特别坑人的需求,厂家平板提供了一个回声消除接口,但每次只能读固定大小的字节数,但我们的编码器每次读取的自己数和这个大小不一样,于是就萌生了一种做一个buffer来临时存储声音数据,然后编码器再去读取,这样不管厂家每次读多少个自己,codec这边也可以控制读取的字节数了。

首先映入眼帘的肯定首选环形buffer

我先定义一个writeIndex 一个 readIndex,和一个当前buffer已经放入数据的大小 size,重点就在于判断何时可写入数据,何时又可以读出数据。

可写入必须要buffer里面有足够多的剩余空间,比如我每次厂家接口只能得到512byte ,那么buffer里面必须有>=512的空间,这样才能往buffer里面push ,get的时候因为codec每次都是读取320个byte,那么必须确保当前buffer里面有>=320个byte的内容,最后就是读写到头的时候需要回到开头这个就比较简单了,以下贴出代码,帮助那些需要写这种特殊环形buffer的同学们:

/*
 * Author: Vincent Luo
 * Date : 20150409
 * Description: 用于声音数据的缓冲,put 每次是512 ,get 每次是320,保证数据的同步
 * 
 */
public class RoundQueue {
	private final static String TAG = "RoundQueue";
	private final int PUT = 512;
	private final int GET = 320;
	private int readIndex = 0;
	private int writeIndex = 0;
	private static final int MAX_SIZE = 512*100;
	private byte[] voiceData = new byte[MAX_SIZE];
	private int size = 0;//current data size
	private boolean isFull(){
		return (MAX_SIZE - size < PUT)?true:false;
	}
	private boolean isEmpty(){
		return size < GET?true:false;
	}
    public synchronized boolean putVoiceData(byte[] data){
    	if(!isFull()){
    		System.arraycopy(data, 0, voiceData, writeIndex, data.length);
        	writeIndex = (writeIndex + PUT) % MAX_SIZE;  
        	size+=PUT;
        	return true;
    	}else{
    		Log.e(TAG,"Buffer is not enough readIndex = " + readIndex + ",writeIndex = " + writeIndex);
    	}
    	return false;
    }
    public synchronized boolean getVoiceData(byte[] data){
    	if(!isEmpty()){
    		System.arraycopy(voiceData, readIndex, data, 0, data.length);
    		readIndex = (readIndex + GET) % MAX_SIZE;  
        	size-=GET;
        	return true;
    	}else{
    		Log.e(TAG,"Buffer is empty readIndex = " + readIndex + ",writeIndex = " + writeIndex);
    	}
    	return false;
    }
    public synchronized void clear(){
    	size = readIndex = writeIndex = 0;
    }
	
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
下面是一个简单的环形缓冲区实现,使用C语言编写: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { char *data; int head; int tail; int size; } CircularBuffer; CircularBuffer* createCircularBuffer(int size) { CircularBuffer *buffer = (CircularBuffer*)malloc(sizeof(CircularBuffer)); buffer->data = (char*)malloc(sizeof(char) * size); buffer->head = 0; buffer->tail = 0; buffer->size = size; return buffer; } void destroyCircularBuffer(CircularBuffer *buffer) { free(buffer->data); free(buffer); } int isEmpty(CircularBuffer *buffer) { return buffer->head == buffer->tail; } int isFull(CircularBuffer *buffer) { return (buffer->tail + 1) % buffer->size == buffer->head; } int write(CircularBuffer *buffer, char *data, int len) { if (isFull(buffer)) { return 0; } int i; for (i=0; i<len; i++) { buffer->data[buffer->tail] = data[i]; buffer->tail = (buffer->tail + 1) % buffer->size; } return len; } int read(CircularBuffer *buffer, char *data, int len) { if (isEmpty(buffer)) { return 0; } int i; for (i=0; i<len; i++) { data[i] = buffer->data[buffer->head]; buffer->head = (buffer->head + 1) % buffer->size; if (buffer->head == buffer->tail) { break; } } return i; } int main() { CircularBuffer *buffer = createCircularBuffer(10); char *data1 = "hello"; char *data2 = "world"; char *data3 = "this is a test"; write(buffer, data1, strlen(data1)); write(buffer, data2, strlen(data2)); write(buffer, data3, strlen(data3)); char read_data[20]; int len = read(buffer, read_data, 20); read_data[len] = '\0'; printf("%s\n", read_data); destroyCircularBuffer(buffer); return 0; } ``` 这个实现中,我们使用一个结构体来表示环形缓冲区,其中包括一个指针、头和尾指针、缓冲区大小等信息。为了实现环形缓冲区,我们使用了取模运算来计算下一个指针的位置。在 `write` 函数中,我们将数据写入缓冲区的尾部;在 `read` 函数中,我们从缓冲区的头部读取数据。在 `main` 函数中,我们展示了如何使用这个环形缓冲区来写入和读取数据。 需要注意的是,在使用环形缓冲区时需要考虑读写指针的同步问题,避免数据的丢失或覆盖。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值