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

问题描述 投票:1回答:1

我正在尝试使用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_INITIALIZEDrecordingStateRECORDSTATE_RECORDINGread()方法也正确地返回它们应该读取的帧数,因此没有问题。

android audio audiorecord
1个回答
1
投票

您正确使用AudioRecord。问题似乎是麦克风上的一些AGC;正如您所观察到的,从缓冲区读出的值在前几毫秒内逐渐变大。这可能是硬件AGC,也许是制造商添加的,以便在每次新录制开始时抑制尖锐的“破解”。

顺便说一句:我有一个旧AGZ的RAZR非常具有侵略性,如果你用手指靠近麦克风,它会沉默一整秒,然后慢慢淡入。

这个问题的一个解决方案就是长期留下AudioRecord录音。然后,当你决定需要抓住你的500帧时,它已经“热身”,并且值应该是满量程的。

编辑

我只对它进行了单元测试,如果你忽略了足够快地读出它,那么AudioRecord似乎不会覆盖其内部缓冲区中的数据。或者,至少,目前还不清楚该数据到底发生了什么。因此,需要一个更复杂的解决方案。

在这种情况下,看起来你必须确保缓冲区永不溢出。这意味着以足够快的速度调用read()。根据您的体系结构,您可能会发现最简单的方法是为此目的专门设置一个线程。

如果您只是在每次读取时使用500帧缓冲区,那么当时机到来时,您可以只获取该缓冲区的副本,这将合理地接近来自麦克风的“最新可能”数据流。这假设您已经足够快速地阅读,以便您的下一次阅读将被阻止。

我说“合理接近”,因为音频数据以getMinBufferSize()/2大小的块放在缓冲区中,如果我没记错的话,这也是OnRecordPositionUpdateListener分辨率的限制。所以,你将会接近尾声,但很难确切地知道它有多接近。

© www.soinside.com 2019 - 2024. All rights reserved.