我正在尝试使用AudioRecord记录大约500帧,但似乎AudioRecord的缓冲区最初在捕获有意义的值之前被部分填充为0。
为了获得实际值,我必须使用数组读取初始的10000帧。
AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
44100,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
2*44100);
audioRecord.startRecording();
audioRecord.read(new short[10000], 0, 10000); // have to include this to remove redundant values
audioRecord.read(audio, 0, 500);
audioRecord.stop();
如果我省略第三行,我将得到500个零。这个解决方案不是很好,我需要知道我做错了什么。另外,请务必注意,在调用read()
方法之前,state
是STATE_INITIALIZED
,而recordingState
是RECORDSTATE_RECORDING
,也是{{1} }方法会准确返回应该读取的帧数,因此在那里没有问题。
答案 0 :(得分:1)
您正确使用了AudioRecord
。问题似乎是麦克风上有一些AGC。如您所见,从缓冲区读出的值在最初的几毫秒内逐渐变大。这很可能是硬件AGC,可能是制造商添加的,用于在每次新录制开始时抑制尖锐的“裂纹”。
顺便说一句:我有一个带有AGC的旧RAZR,它是如此具有攻击性,如果您将手指靠近麦克风,它将沉默一整秒钟,然后慢慢淡入。
解决此问题的一种方法是长期保留AudioRecord
记录。然后,当您决定需要抓取500帧时,它已经被“预热”,并且值应该是满量程的。
编辑
我只是对其进行了单元测试,并且如果您忽略了足够快的读出速度,看来AudioRecord
不会覆盖其内部缓冲区中的数据。或者,至少,目前尚不清楚该数据到底发生了什么。因此,需要更复杂的解决方案。
在这种情况下,您似乎必须确保缓冲区永远不会溢出。这意味着以足够快的速率调用read()
。根据您的体系结构,您可能会发现最简单的为此目的专用线程。
如果您在每次读取中仅使用500帧缓冲区,那么当时间到了时,您可以获取该缓冲区的副本,这将很接近麦克风中“最新可能”流式传输的数据。假设您已经足够快地阅读,以至于下次阅读将被阻止。
我之所以说“合理接近”,是因为如果我没记错的话,音频数据会以大小为getMinBufferSize()/2
的块放置在缓冲区中,这也是OnRecordPositionUpdateListener
分辨率的极限。因此,您将接近尾声,但是很难确切知道距离多近。
答案 1 :(得分:0)
缓冲区本身的初始值或重新采样可能导致缓冲区中的初始零。查看相关文章:
1. Android AudioRecord Initialization delay
2. AudioRecord returns some empty data after start