public int read(byte [] audioData,int offsetInBytes,int sizeInBytes)。
此方法从音频硬件读取音频数据,以便录制到缓冲区中。
其参数是: audioData记录的音频数据写入的数组。 audioIn中的offsetInBytes索引,从中写入数据以字节为单位表示。 sizeInBytes请求的字节数。
它返回 如果对象未正确初始化,则读取的字节数或ERROR_INVALID_OPERATION;如果参数未解析为有效数据和索引,则为ERROR_BAD_VALUE。字节数不会超过sizeInBytes。
我在我的代码中编写了这个方法,如下所示: int num; byte [] buf = new byte [160]; num = record.read(buf,0,160);
问题是即使数据不可用,它总是返回160(即要读取的请求字节)不小于160。有什么问题?帮我。 提前谢谢。
答案 0 :(得分:13)
更新:Android中的这个错误在4.2.2之后和5.01之前得到了修复。在5.01上,回调的工作方式与文档所说的完全相同。
由于开发人员的一些短视,read
似乎正在阻塞。
基本上,当初始化录音机时,它会分配一种环形缓冲区,当它被告知.start()
时,它会开始录制到该缓冲区。
然后当调用.read()
时,它会读取缓冲区大小的一半(或请求的大小,以较小者为准)并返回。
如果它想要读取1000个样本并且只有900个样本可用,则必须等待100个样本才能返回。但是,如果有超过1000个样本,它会立即读取这些样本,然后立即返回。
理想情况下,它们要么提供非阻塞读取,以便返回任何可用的内容,要么提供一种方法来了解何时可以获得完整读取的数据,从而可以执行非阻塞读取。
我认为他们不支持第一个。他们似乎试图通过使用设置周期回调方法来支持第二种方法,但到目前为止,我无法在正确的时间进行回调以进行快速非阻塞读取。
我已经克隆了本机C ++源代码的完整源代码(8.5G字节),并且我试图通过所有层来跟踪功能,看看它应该如何工作。
非阻塞.read(0)
的技巧是只有在准备好完整读取的样本时才会读取。但确定何时该条件为真是我尚未弄清楚的。
参考文献: 这是.read()的java代码,它调用本机C ++函数:
上面的read()方法调用了以下内容中的本地native_read_in_direct_buffer()
:
调用或指向android_media_AudioRecord_readInByteArray()
,而AudioRecord.read()
又调用frameworks/base/media/libmedia/frameworks/base/media/libmedia/AudioRecord.cpp
中的{{1}}(尽我所知),看起来在这个函数中有一个do / while循环基本上阻塞,直到读取了所需的字节数(或缓冲区大小的一半,以较小者为准)。
我试图让回调运行得很好但是它们似乎只在read()必须等待音频缓冲区被填充才能返回之前回调 - 所以重点是什么。
我的下一个目标是尝试追踪通知回调源代码,以便我可以准确猜测应该做什么以及何时做什么。
答案 1 :(得分:8)
read
是一种阻止方法。只有在读取了您要读取的字节数,或者流已关闭,或者流表明没有更多数据可用时(例如读取文件时),它才会返回。
AudioRecord是一个连续的流,“没有更多数据可用”的情况从未适用。