Android使用AudioRecord采集声音时声音播放很快解决方案

最近公司要做回音消除相关的项目,首先要求对目前公司所有的测试机进行一次摸底测试,过程就是利用Android录音API——AudioRecord从手机麦克风采集音频数据测试声压,然后在PC上用音频原始数据播放工具播放。在写这个demo的时候,开始的时候以为很简单,测试MM测试过几次采样率为8000Hz数据也OK,不过在测试采样率为16000Hz时把我的版本打回了,原因是采集到的音频保存之后,有明显的失真,具体现象就是播放速度很快,好像要把所以声音一口气播放完似的。开始以为很简单,分分钟搞定的问题,结果测试了一天时间才搞定,所以把解决方法保存下来,也算是提醒自己小问题,大道理

首先,我把常规的边采集边保存文件的代码贴出来

mAudioRecord.startRecording();
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(mAudioFile)));
while (mAudioRecord.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) {
	int number = mAudioRecord.read(mAudioRecordData, 0,mAudioRecordData.length);
	for (int i = 0; i < number; i++) {
	dos.writeShort(mAudioRecordData[i]);//写文件操作
	}
	if (AudioRecord.ERROR_BAD_VALUE != number
			&& AudioRecord.ERROR != number) {
		Log.d("TAG", String.valueOf(number));
								}
	}
	dos.flush();
	dos.close();

上面这段代码是AudioRecord把采集到的数据放入到short[]类型缓冲区mAudioRecordData中,然后利用DataOutputStream把缓冲区的数据写入指定的文件中。

OK,下面我们来看看这段代码中对边采集边写入文件可能带来的风险进行一下分析:

1.我们可以看到每次采样存入缓冲区的数据长度是number,然后是利用for循环将short[]类型缓冲区中的数据逐个写入文件的,这里就产生了一个疑问:这种方式的文件写入,可行吗?这种写入方案应该是不被鼓励使用的,为什么?因为执行代码和写入文件比较耗时,在写入文件时如果缓冲区的数据还没有写完,而新的采集数据又填入到了缓冲区,那么上一次采集到的数据就有可能有一部分被覆盖掉。

2.有的同学可能会想,既然你用short[]保存数据,我为什么不能用byte[]保存呢,用byte[]保存之后,可以用DataOutputStream.write(byte[] data,int offset,int index)一次写入所有数据啊?这种方式当然是可以的,但是你忽略了I/O同样也是耗时操作的问题,把整个缓冲区一次写入文件也是需要时间的。问题有回归到1中提到的后来采集到的数据覆盖掉了上一次采集到的数据。


如上图所示,当2阶段的时间小于3阶段时间时,缓冲区的数据肯定会被后来的数据覆盖的,本人初步的猜想可能跟手机性能有关,有可能手机性能越突出,2阶段的耗时越小。如果有大神对AudioRecord音频采集这块比较熟悉,麻烦不吝指教。


所以说,针对上面出现的这种缓冲区数据被覆盖的情况,我的处理方案如下:

第一,写文件操作另起线程操作;

第二,在写文件时启用双缓冲区,双缓冲区交替写入文件。例如有两个缓冲区a和b,当从a中写文件时,b等待接收采集到的数据。下一次从b中写文件时,a等待采集到的数据。

做到这两点基本可以保证边采集边保存文件的数据无恙了。


最后,还有个问题,与各位大神讨论一下,希望有大神能给出解决方案,就是结束采集的时候,有没有一种可能:I/O通道已经关闭,但是AudioRecord在stop之前又采集到了一组数据,这个是不是说保存的时候丢失了一部分数据,当然这个应该不会影响播放,但是对专业的音频开发人员做数据分析会有影响的。目前我的处理方案是:AudioRecord stop,然后是500ms后执行关闭I/O通道操作。


好了整个过程看起来描述的还算比较清楚,就不上传代码了,毕竟只要思想不滑坡,办法总比困难多。哈哈……共勉之!

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值