How to get notified for sample rate change in AVAudioSession ?

Hi all,


I got some crashes in an app for quite some time, and I finally understood why. My app uses AVAudioSession for audio input and output with real-time interaction, and also uses the Google pod youtube-ios-player-helper to display YouTube videos. The problem is that the youtube player, on which I have very little control, modifies my AudioSession, and especially changes the current sample rate, resulting in some serious buffer issues in my audio code.


My question is the following :

Is there any way to get notified when the sampleRate of the audio session is changed?


I did some research, tried a few a few things, none worked. More precisely :

- The sampleRate property of AVAudioSession is not key value observable.

- A change of sample rate does not trigger any call to the handle route notification or the media services reset notification.


Any idea how to get notified when the sample rate of the audio session is changed?

The sample rate of the audio session is a key information for an audio app. If it can be changed by other components, there should be a way to get notified in order to be able to take it into account!


Thanks,

Best,


Thomas

Replies

We have an open feature request to add KVO support for the sample rate property of AVAudioSession. It would help if you filed another request even though it is a duplicate. The number of developer requests for specific features are really important and are always taken into account when trying to prioritize features for future versions of the OS.


So, not knowing how clients are expected to work with the youtube-ios-player-helper, it's hard to comment on what their expected behavior is or why they need to change the hardware sample rate. Maybe something you can ask google support?


Couple of quick things -- you mention using AVAudioSession for input and output -- I'm going to guess you mean you have an AVAudioSession configured for PlayAndRecordCategory but since AVAudioSession itself doesn't provide any audio data specific APIs you may also be using the RemoteIO?


If this is the case, you should be able to add a property listeners which will allow you to get notifications when the hardware sample rate is changed. I've done this before by adding a kAudioUnitProperty_StreamFormat listener via AudioUnitAddPropertyListener on the RemoteIO, which is called whenever the hardware sample rate is successfully changed.


The other thought is to make sure you're not running into some version of the 48k speaker hardware issue discussed here.

Hi,


Thanks for the answer.

Yes, as you guessed it, I use the standard pattern with the RemoteIO and an input callback on the element 0. We're also in touch with Google, as the youtube-ios-player-helper is very basic and not really for integration in a complex audio app.


We're aware of the issue with the 6S, but I'm not sure I understood everything. In the case of a RemoteIO set at 44100Hz, where does the conversion take place? Can we specify exactly what we want for input and output format with the following AudioUnitSetProperty on kAudioUnitProperty_StreamFormat? Are we ensured that it will allways be respected?


About the sample rate observation, we started investigating the property listener on the RemoteIO's stream format property a few minutes before we read your answer. But we have strange indications, with the 4 sample rates (input/output of elements 0 and 1) being different sometimes. This raises two questions I couldn't answer yet:

Q1. In the remoteIO, can the sample rate of the input of one element be different of the sample rate of the output of the same elements? In other word, can the RemoteIO itself take care of sample rate conversion? If not, why do sometime the stream formats are different on input and output of elements 0 and 1?

Q2. Can the sample rate of the input (element 1) be different from the one of the output (element 0)? We're facing strange behaviours (I'm working on a way to describe this clearly) when we start an app with a prefered sample rate at 44100Hz and then plug a sound card with only inputs running exclusively at 48000Hz.


Thank you theanalogkid for your attention and your allways relevant and usefull answers 🙂


Thomas

There are a number of WWDC session video's discussing AVAudioSession and I/O on iOS going back as much as 6 years which are still very useful to check out. One of them from 2012 called Audio Session and Multiroute Audio in iOS has a nice discussion of the "Anatomy of an I/O Unit". I've found this session really helps folks with Scopes, Elements and formats via some nice block diagrams. This illustration from our documentation isn't quite as nice, but should help.


I'll attempt to convey the same information below.


Element (Bus) 0 is App Output, think of 0 as the letter O for Output.

Element (Bus) 1 is App Input, think of 1 as the letter I for Input.


Output Element, 0:

The Input Scope of Element 0 allows you to set the Client Format - this is the format of the data you supply to the output unit for rendering.

The Output Scope of Element 0 is the Virtual Output Format or Hardware Format - format conversion will happen from client format to HW format as required.


Input Element, 1:

The Output Scope of Element 1 allows you to set the Client Format - this is the format of the data you will receive when you pull on the input.

The Input Scope of Element 1 is the Virtual Input Format or Hardware Format - format conversion will occur from HW format to client format as required.


In this illustration, the blue color represents the Hardware Format and the peach color represents Client Format.


When you set the AVAudioSession preferred sample rate, it affects both the input and output hardware sample rate. It's recommended that you always check the sampleRate property to confirm the hardware sample rate you've asked for if this is important to you. Don't assume and use the returned property value to directly configure your client formats sample rate.


The format you set for the app is the client format and this format may be different between input and output since it represents the format of the data the application wants to work with.