I have a setup as follows, testing on an iPhone 5s with iOS 10.3, both in and out of debug.
- An
AVAudioRecorder
firesrecord(forDuration: 5.0)
- A
CADisplayLink
watches the levels of the recorder (the recorder ismeteringEnabled
), synchronizing an animation, and keeping track ofrecorder.currentTime
(but the problem can be reproduced by minimally keeping track of time in the display link) - The reports of
recorder.currentTime
consistently reach values > 5 (often 5.2 to 5.5). The results are essentially consistent with the values ofrecorder.deviceTime
andCFAbsoluteTimeGetCurrent
- I initialize an
AVAudioPlayer
and verify that the sound asset does have a duration of precisely 5.0 seconds.
From my understanding, the recorder's currentTime
is measured in seconds, and resets to 0.0 when recorder.isRecording reverts to false, which happens immediately when the recorder stops (this is consistent with what i see in audioRecorderDidFinishRecording
)... so observing with a CADisplayLink
should produce currentTime values strictly less than 5.0?
The question is: what could be going wrong here? The recorder is stopping as it should after exactly 5 seconds, but internally it thinks it recorded for more than 5 seconds? I'm listening to all my recordings and they sound fine.
I'm not sure if it's relevant, but my AVAudioSession
is of type AVAudioSessionCategoryPlayAndRecord
, and my audio settings are as follows (all of these excepting sample rate are necessary for later analysis):
audioSettings = [
AVFormatIDKey: Int(kAudioFormatLinearPCM),
AVSampleRateKey: 44100,
AVNumberOfChannelsKey: 2,
AVLinearPCMIsBigEndianKey: 0,
AVLinearPCMIsFloatKey: 0,
AVLinearPCMBitDepthKey: 16,
AVLinearPCMIsNonInterleaved: 0
]
I already tried fiddling with all of these and didn't see any change behavior.
The CADisplayLink
is added from the main thread via
recorderDisplayLink?.add(to: RunLoop.current, forMode: RunLoopMode.commonModes)
The only similar question I can find on stack exchange is this, but the question is underspecified and the answer unhelpful (for me at least).
At first I thought maybe the issue is with overloading the main queue, so that somehow the recorder's sense of time becomes bloated (which I think
would still constitute bad behavior), but after disabling the animation (and also experimenting with a Timer instead of a CADisplayLink), the problem persists!!! Perhaps it is still a threading problem, but I don't see why that would be the case. And if i do need to multi-thread, I could use some help both with understanding and implementing :)
Any ideas appreciated.