onPeriodicNotification() 在*某些*设备上有抖动
为什么 onPeriodicNotification() 的行为如此不稳定?
背景
我正在开发一个适用于 Android 的音频可视化工具,它使用 AudioRecord.read() (16 位单声道)从麦克风进行采样。我已经对 setPositionNotificationPeriod() 的采样率和帧周期进行了大量测试。最后我决定:
采样率: 8000
帧周期:采样率 * 41 / 1000 = 328
缓冲区大小: 5 * 采样率
我选择帧周期为 41 毫秒,因为我希望可视化工具每秒约 24 帧。
一开始我认为以这种速度绘制到画布会是一个问题,但在 DroidX 和 Nexus One 上进行测试后,我获得了惊人的性能。我可以将这些设备上的延迟降低到 20 毫秒,而不会出现缓冲区溢出,但其实没有必要。
当我开始在 Galaxy S 和 Nexus S 上进行测试后,我的性能就下降了。这看起来很奇怪,因为 Nexus S 的性能在很大程度上优于这两款设备。在消除绘图和计算问题后,我将计时调用放入 onPeriodicNotification() 中。我能够确认该问题是由于此回调以随意的时间间隔调用而导致的,我不明白为什么。
创建公平基准
作为一个公平的测试,我将所有音频处理和绘图都从循环中取出,这样我的应用程序所做的就是循环读取音频并在 onPeriodicNotification() 中记录数据。我将帧周期设置为 100 毫秒,并使用以下计时代码:
currentTime = SystemClock.elapsedRealtime();
Log.v(TAG, "time since last record update: " + (currentTime - lastTime));
lastTime = currentTime;
最后,我在每个设备上采样 5 分钟的数据。在 DroidX 上,我得到了我所期望的结果:
# 分: 3008
最低: 92
最大: 105
平均: 100
StdDev: 6.64
这看起来很合理,我愿意接受这一点。在 Galaxy S 上,我得到以下信息:
# 分: 3004
最小值:0!
最大: 274
平均: 100.05
StdDev: 126.30?!?
当 StdDev 为 126 时,这意味着后续的一组定时调用通常如下所示 [253, 0, 1, 258, 1, 0, 263] 。
结论与其他杂项数据
在执行这些测试时,我密切关注 CPU 使用情况。我的进程的 CPU 使用率徘徊在 2-3% 左右,需要处理大量开销。我注意到,如果我将通知之间的延迟增加到 250 毫秒左右,Galaxy S 就会开始按照我的预期运行(stddev 下降到 6-7 左右)。不幸的是,250 毫秒远不是音频可视化可用的延迟。
写完所有这些后,我忍不住觉得这更好地属于一些错误报告,但话又说回来,这是我们正在谈论的三星,我们知道他们有 没有互联网 android 错误报告存在 :(
非常感谢替代方案、见解和经验。
Why does onPeriodicNotification() behave so erratically?
Background
I'm working on an audio visualizer for Android that samples from the microphone using AudioRecord.read() (16-bit mono). I've done quite a bit of testing with sample rates and frame periods for setPositionNotificationPeriod(). In the end, I settled on:
Sample Rate: 8000
Frame Period: Sample Rate * 41 / 1000 = 328
Buffer Size: 5 * Sample Rate
The frame period is 41 ms which I chose because I want ~24 frames per second for my visualizer.
I thought that drawing to canvas at this rate would be a problem at first, but after testing on the DroidX and Nexus One, I was getting amazing performance. I can drop the latency to 20 ms on these devices without buffer-overruns but have no need to.
Once I started testing on the Galaxy S and Nexus S, my performance tanked. This seemed odd since the Nexus S outperforms both devices by a large degree. After eliminating drawing and calculations as being the problem, I put timing calls in onPeriodicNotification(). I was able to confirm that the issue is due to this callback being called at willy-nilly time intervals and I do not understand why.
Creating a Fair Benchmark
As a fair test, I took all of my audio processing and drawing out of the loop such that all my app does is read audio in a loop and log data in onPeriodicNotification(). I set the frame period to 100 ms and used the following timing code:
currentTime = SystemClock.elapsedRealtime();
Log.v(TAG, "time since last record update: " + (currentTime - lastTime));
lastTime = currentTime;
Finally, I sampled data for 5-minutes on each device. On the DroidX, I get about what I expect:
# Points: 3008
Min: 92
Max: 105
Avg: 100
StdDev: 6.64
This seems reasonable and I'm willing to live with this. On the Galaxy S, I get this:
# Points: 3004
Min: 0!
Max: 274
Avg: 100.05
StdDev: 126.30?!?
With a StdDev of 126, this means that a subsequent set of timing calls often looks like this [253, 0, 1, 258, 1, 0, 263].
Conclusion & other misc data
While performing these tests, I kept an eye on CPU usage. My process hovers around 2-3% CPU usage with plenty of overhead to work with. I notice that if I increase the latency between notifications to around 250 ms, the Galaxy S begins behaving as I would expect (the stddev drops to around 6-7). Unfortunately, 250 ms is far from being a usable latency for audio visualization.
After typing all this I can't help but feel this better belongs in some bug report, but then again this is Samsung we're talking about and we know they have no internet android bug reporting presence :(
Alternatives, insights and experience are greatly appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
最终,这似乎归结为音频驱动程序。我发现三星的音频实现会导致令人难以置信的高延迟,而摩托罗拉、HTC 和其他公司的延迟足够低,我没有注意到。
低延迟音频长期以来一直出现在错误列表上,所以这也许并不奇怪。如果您正在进行实时音频可视化,请准备好对三星设备感到失望:(
Ultimately this seems to come down to the audio driver. I've found that Samsung's audio implementation results in incredibly high latency whereas Motorola, HTC and others are sufficiently low enough that I don't notice.
Low latency audio has been on the bug list for a long time, so perhaps this isn't surprising. If you are doing realtime audio visualization, prepare to be disappointed on Samsung devices :(