非 HTC 设备的 AudioRecord 问题
我在使用 AudioRecord 时遇到问题。
使用源自 splmeter 项目的部分代码的示例:
private static final int FREQUENCY = 8000;
private static final int CHANNEL = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private static final int ENCODING = AudioFormat.ENCODING_PCM_16BIT;
private int BUFFSIZE = 50;
private AudioRecord recordInstance = null;
...
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
recordInstance = new AudioRecord(MediaRecorder.AudioSource.MIC, FREQUENCY, CHANNEL, ENCODING, 8000);
recordInstance.startRecording();
short[] tempBuffer = new short[BUFFSIZE];
int retval = 0;
while (this.isRunning) {
for (int i = 0; i < BUFFSIZE - 1; i++) {
tempBuffer[i] = 0;
}
retval = recordInstance.read(tempBuffer, 0, BUFFSIZE);
... // process the data
}
适用于 HTC Dream和 HTC Magic 完美无任何日志警告/错误,但会导致模拟器和 Nexus One 设备出现问题。
在 Nexus 上,它根本不会返回有用的数据。我无法提供任何其他有用的信息,因为我正在让一位远程朋友进行测试。
在模拟器(Android 1.5、2.1 和 2.2)上,我从 AudioFlinger 和 AudioRecordThread 的缓冲区溢出中收到奇怪的错误。我的 UI 响应速度也大幅下降(尽管录制是在与 UI 不同的线程中进行的)。
我是否明显做错了什么?我需要对 Nexus One 硬件做任何特别的事情吗?
编辑
我已经部分解决了这个问题...... AudioRecord 的文档说:
public static int getMinBufferSize (int sampleRateInHz, int channelConfig, int audioFormat)
返回最小缓冲区大小 成功创建所需的 AudioRecord 对象的。注意 这个尺寸并不能保证平滑 在负载和更高的情况下录音 值应根据选择 的预期频率 AudioRecord 实例将被轮询 获取新数据。获取新数据。
所以我将缓冲区长度更改为
private static final int BUFFSIZE = AudioRecord.getMinBufferSize(FREQUENCY, CHANNEL, ENCODING);
现在模拟器运行良好。
但
硬件没有。虽然模拟器根据 8khz 从该调用返回值 640(每秒进行 12.5 次轮询),但 HTC 硬件返回 4096!这意味着大约每秒 2 次轮询和半秒的音频延迟! 此外,在 Nexus One 上的同一调用返回 8192!所以延迟了整整一秒!
我希望它就此结束,但是 Nexus One 仍然 不返回任何音频(我自己仍然没有音频,所以我无法从中获得正确的调试信息),即使HTC 设备和所有模拟器现在都可以工作(即使有些比其他模拟器更滞后)。
我在这里做错了什么吗?
I'm having troubles using AudioRecord.
An example using some of the code derived from the splmeter project:
private static final int FREQUENCY = 8000;
private static final int CHANNEL = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private static final int ENCODING = AudioFormat.ENCODING_PCM_16BIT;
private int BUFFSIZE = 50;
private AudioRecord recordInstance = null;
...
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
recordInstance = new AudioRecord(MediaRecorder.AudioSource.MIC, FREQUENCY, CHANNEL, ENCODING, 8000);
recordInstance.startRecording();
short[] tempBuffer = new short[BUFFSIZE];
int retval = 0;
while (this.isRunning) {
for (int i = 0; i < BUFFSIZE - 1; i++) {
tempBuffer[i] = 0;
}
retval = recordInstance.read(tempBuffer, 0, BUFFSIZE);
... // process the data
}
This works on the HTC Dream and the HTC Magic perfectly without any log warnings/errors, but causes problems on the emulators and Nexus One device.
On the Nexus one, it simply never returns useful data. I cannot provide any other useful information as I'm having a remote friend do the testing.
On the emulators (Android 1.5, 2.1 and 2.2), I get weird errors from the AudioFlinger and Buffer overflows with the AudioRecordThread. I also get a major slowdown in UI responsiveness (even though the recording takes place in a separate thread than the UI).
Is there something apparent that I'm doing incorrectly? Do I have to do anything special for the Nexus One hardware?
EDIT
I've partially solved the problem...
The Documentation for AudioRecord says:
public static int getMinBufferSize (int sampleRateInHz, int channelConfig, int audioFormat)
Returns the minimum buffer size
required for the successful creation
of an AudioRecord object. Note that
this size doesn't guarantee a smooth
recording under load, and higher
values should be chosen according to
the expected frequency at which the
AudioRecord instance will be polled
for new data.for new data.
So I changed the buffer length to
private static final int BUFFSIZE = AudioRecord.getMinBufferSize(FREQUENCY, CHANNEL, ENCODING);
And now the Emulators run well.
But
Hardware doesn't. While the emulators return a value of 640 from that call (giving 12.5 polls per second) based on 8khz, the HTC hardware returns 4096! Meaning roughly 2 polls per second and an audio delay of half a second!
Furthermore, that same call on the Nexus One returns 8192! So a full second delay!
I wish it ended at that, but the nexus one still doesn't return any audio (still don't have one myself, so I can't get proper debugging information from one), even though the HTC devices and all emulators now work (even if some are more laggy than others).
Am I doing something horribly wrong here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我解决了!
我(错误地)假设 AudioRecord 类的构造函数中使用的神奇数字 8000 是频率变量的重复项。它实际上应该是您将使用的缓冲区大小。
不幸的是,这不仅与 splmeter 的缓冲区长度(默认 320 - 我在第一个代码块中修改为 50)不同,而且 Nexus One 可接受的最小缓冲区大小是 8192,因此不得创建 AudioRecord 实例适当地。
因此,当我修改了缓冲区长度(来自 getMinBufferSize),用它替换了神奇的 8000,并将我的频率变量增加到建议的 44100 时,一切都在所有平台/模拟器上完美运行。
因此,如果您计划在修补之前使用 splmeter 代码库,请考虑这三件事。
老实说,splmeter 代码甚至不能在 HTC 设备上运行。我想这就是为什么我的开发设备被命名为 HTC Magic =P
I solved it!
I (wrongfully) assumed that the magic 8000 number used in the constructor of the AudioRecord class was a duplicate of the frequency variable. It's actually supposed to be the buffer size that you'll be using.
Unfortunately, not only is this different from the splmeter's buffer length (default 320 - which I modified to 50 in my first code block), but the minimum buffer size acceptable for the Nexus One is 8192, so the AudioRecord instance must not have been created properly.
So when I had my modified buffer length (from getMinBufferSize), replaced the magic 8000 with it, and increased my Frequency variable to the suggested 44100, everything works perfectly across all platforms/emulators.
So if you plan on using the splmeter code base before it gets patched, take these three things into account.
To be honest, the splmeter code shouldn't even work on the HTC devices. I guess that's why my dev device is named the HTC Magic =P