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.