My fingernails are bitten down to the bone, but I'm making some partial progress figuring out what's going on. That doesn't mean I wouldn't still be interested in help, though!
On 24 Apr '08, at 9:40 AM, I wrote: (1) How do I tell when an under-run occurs?
It seems to happen "really soon" after my buffer callback is called with the last in-use buffer. I.e. if I keep track of the count of the number of buffers that have been queued but not yet returned, when that number hits zero.
...except that if I can immediately queue another buffer before returning from the callback, there is no under-run and no drop-outs. That's why I said "really soon after". It's only if I queue the next buffer sometime after the callback returns that there'll be audible drop-outs. (2) After an under-run, what value do I pass in for the inTimeStamp when scheduling the buffer, to indicate "Right Now"? Again, I thought the value of AudioQueueGetCurrentTime would work for this, but it doesn't, because it drifts apart from the actual sample count and it resets to zero when the audio hardware reconfigures.
I've figured out the drift. The answer is that (a) AudioQueueGetCurrentTime does not use the queue's sample rate for its mSampleTime; instead it uses the output device's sample rate. (b) On the Mac Mini where the sample-times were drifting apart, the output device is for some reason running at 48khz, not 44.1. No idea why, and I can't find any UI for configuring this; does it just vary from one Mac model to the next?
The solution is to get the queue's kAudioQueueDeviceProperty_SampleRate, and then multiply the current sample time by the queue rate divided by the device rate.
(It is unfortunately impossible to use a host-time to schedule playback of a buffer, because the queue only pays attention to mSampleTime in the inTimeStamp; it ignores mHostTime, even if the flags are set to indicate that mSampleTime isn't valid.)
Anyway, by doing that, after an underrun I can compute the appropriate timestamp for queueing the next buffer to make it start "right now".
...except if there's been a "discontinuity", like plugging in headphones. That causes the current sample time to reset to zero, actually to a negative number, and I can't use it any more as a time-base for computing the sample time to schedule the buffer.
In other words, I seem to have duct-taped things together into good enough shape for an alpha version of my app, but I certainly can't ship this way, otherwise headphones + network glitches = no more audio, oops.
Clinging to my last shreds of sanity, I remain
—Jens |