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.
Code Block 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)
Code Block 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?
Thank you