Android AudioRecord缓冲区以有意义的值之前的0开头

时间:2019-02-19 10:05:28

标签: android audio audiorecord

我正在尝试使用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()方法之前,stateSTATE_INITIALIZED,而recordingStateRECORDSTATE_RECORDING,也是{{1} }方法会准确返回应该读取的帧数,因此在那里没有问题。

2 个答案:

答案 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