Hi, I am building a realtime drum practise tool which listens to the players' practice and provides visual feedback on their accuracy.
I use AVAudioSourceNode and AVAudioSinkNode for playing audio and for listening to player practise. Precious timing is the most important part of our app. To optimise audio latency I set PreferredIOBufferDuration to 64/48000sec (~1.33ms). My preferences work fine with builtin or wired audio devices. In these cases we can easily estimate the actual audio latency.
However we would like to support Apple airPods (or other bluetooth earbuds) as well, but it seems to be impossible to predict the actual audio latency.
let bufferSize: UInt32 = 64
let sampleRate: Double = 48000
let bufferDuration = TimeInterval(Double(bufferSize) / sampleRate)
try? session.setCategory(AVAudioSession.Category.playAndRecord, options: [.defaultToSpeaker, .mixWithOthers, .allowBluetoothA2DP])
try? session.setPreferredSampleRate(Double(sampleRate))
try? session.setPreferredIOBufferDuration(bufferDuration)
try? session.setActive(true, options: .notifyOthersOnDeactivation)
I use iPhone 12 mini and airPods 2 for testing.
(Input always have to be the phone's builtin mic)
let input = session.inputLatency // 2.438ms
let output = session.outputLatency // 160.667ms
let buffer = session.ioBufferDuration // 1.333ms
let estimated = input + output + buffer * 2 // 165.771
session.outputLatency returns ca 160ms for my airPods.
With the basic calculation above I can estimate a latency of 165.771ms, but when I measure the actual latency (time difference between heard and played sound ) I get significantly different values.
If I connect my airPods and start playing immediately, the actual measured latency is ca 215-220ms at first, but it is continuously decreasing over time. After about 20-30mins of measuring the actual latency is around 155-160ms (just like the value that the session returns).
However if I am using my airPods for a while before I start the measurement, the actual latency starts from ca 180ms (and decreasing over time the same way). On older iOS devices these differences are even larger.
It feels like bluetooth connection needs to "warm up" or something.
My questions would be: Is there any way to have a relatively constant audio latency with bluetooth devices?
I thought maybe it depends on the actual bandwidth but I couldn't find anything on this topic. Can bandwidth change over time? Can I control it?
I guess airPods support AAC codec. Is there any way to force them to use SBC? Does SBC codec work with lower latency?
What is the best audioengine setting to support bluetooth devices with the lowest latency?
Any other suggestion?
Thank you