更新:Android 中的这个错误在 4.2.2 和 5.01 之前的某个地方得到了修复。在 5.01 中,回调的工作方式与文档中所说的完全一样。
read
由于开发人员的一些短视,它看起来正在阻塞。
基本上,当录音机被初始化时,它会分配一种环形缓冲区,当它被告知时.start()
,它开始录制到该缓冲区。
然后当.read()
被调用时,它最多读取缓冲区大小的一半(或请求的大小,以较小者为准)并返回。
如果它要读取 1000 个样本而只有 900 个可用,则必须再等待 100 个样本才能返回。但是,如果有超过 1000 个样本,它会立即读取这些样本,然后立即返回。
理想情况下,它们要么提供非阻塞读取,以便返回任何可用的内容,要么提供一种方法来了解完整读取的数据何时可用,以便可以执行非阻塞读取。
我不认为他们支持第一个。他们似乎试图通过使用设置周期回调方法来支持第二个,但到目前为止,我无法在正确的时间获得该回调来进行快速的非阻塞读取。
我已经克隆了本机 C++ 源代码的完整源代码(8.5G 字节),并且我试图通过所有层来跟踪该功能,以了解它应该如何工作。
非阻塞的技巧.read(0)
是仅在准备好完整读取的样本时才读取。但是确定该条件何时为真是我尚未弄清楚的。
参考资料:这是 .read() 的 java 代码,它调用原生 C++ 函数:
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.4_r1/android/media/AudioRecord.java#AudioRecord.read%28java.nio.ByteBuffer% 2美分%29
上面的 read() 方法调用位于以下位置的本机native_read_in_direct_buffer()
:
http://pdroid.googlecode.com/svn/android-2.3.4_r1/trunk/frameworks/base/core/jni/android_media_AudioRecord.cpp
哪个调用或指向android_media_AudioRecord_readInByteArray()
哪个依次调用AudioRecord.read()
(frameworks/base/media/libmedia/frameworks/base/media/libmedia/AudioRecord.cpp
据我所知),看起来在这个函数中有一个 do/while 循环,它基本上阻塞,直到读取所需的字节数(或缓冲区大小的一半,以较小者为准。)
我试图让回调正常运行,但它们似乎只在 read() 必须等待音频缓冲区被填充才能返回时才回调——所以有什么意义。
我的下一个目标是尝试追踪通知回调源代码,这样我就可以准确猜测应该做什么以及何时执行。