Monophonic and bad quality playback with Bluetooth headphones on iOS


#1

When I’m attaching my bluetooth headphones (Sony MDR-1000x, but tested with others, too), to either my iPhone 8+ running iOS 12.0.1 or my iPad (2018, 9.7in) iOS 11.3.1, I only get a monophonic connection if I run my JUCE app.
To make it reproducable, I tested this with JUCE’s AudioPlaybackDemo.

Here’s my log for:
a) iPad 2018 9.7in, iOS 11.3.1

JUCE v5.4.1
Creating iOS audio device
Updating hardware info
Lowest supported sample rate: 8000
Highest supported sample rate: 16000
Trying a sample rate of 9000, got 16000
Available sample rates: 8000 16000
Sample rate after detecting available sample rates: 16000
Available buffer sizes: 64 128 256 512 1024 2048 4096
Buffer size after detecting available buffer sizes: 256
Input channel configuration: {Number of hardware channels: 1, Hardware channel names: "MDR-1000X", Are channels available: yes, Active channel indices:}
Output channel configuration: {Number of hardware channels: 1, Hardware channel names: "MDR-1000X", Are channels available: yes, Active channel indices:}
Opening audio device: inputChannelsWanted: 11, outputChannelsWanted: 11, targetSampleRate: 16000, targetBufferSize: 256
Input channel configuration: {Number of hardware channels: 1, Hardware channel names: "MDR-1000X", Are channels available: yes, Active channel indices: 0}
Output channel configuration: {Number of hardware channels: 1, Hardware channel names: "MDR-1000X", Are channels available: yes, Active channel indices: 0}
handleRouteChange: Category change
Setting target sample rate: 16000
Actual sample rate: 16000
Setting target buffer size: 256
Actual buffer size: 256
Creating the audio unit
handleRouteChange: Category change
Internal buffer size: 4096
handleRouteChange: Category change
handleRouteChange: Category change
handleRouteChange: Category change

Here I can see, that JUCE thinks, that only one hardware channel seems to be available and no higher Sample rate is found than 16000 Hz.

b) iPhone 8+, iOS 12.0.1

iOS 12.0.1 iPhone 8+
JUCE v5.4.1
2018-12-06 17:49:34.016793+0100 AudioPlaybackDemo[611:110775] +[CATransaction synchronize] called within transaction
Creating iOS audio device
Updating hardware info
Lowest supported sample rate: 8000
Highest supported sample rate: 16000
Trying a sample rate of 9000, got 16000
2018-12-06 17:49:34.091988+0100 AudioPlaybackDemo[611:110827] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothA2DPOutput)
2018-12-06 17:49:34.092264+0100 AudioPlaybackDemo[611:110827] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothHFP)
2018-12-06 17:49:34.092355+0100 AudioPlaybackDemo[611:110827] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothHFP)
Available sample rates: 8000 16000
Sample rate after detecting available sample rates: 16000
Available buffer sizes: 64 128 256 512 1024 2048 4096
Buffer size after detecting available buffer sizes: 256
2018-12-06 17:49:34.100768+0100 AudioPlaybackDemo[611:110775] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothHFP)
2018-12-06 17:49:34.100811+0100 AudioPlaybackDemo[611:110775] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothHFP)
Input channel configuration: {Number of hardware channels: 1, Hardware channel names: "MDR-1000X", Are channels available: yes, Active channel indices:}
2018-12-06 17:49:34.102859+0100 AudioPlaybackDemo[611:110775] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothHFP)
2018-12-06 17:49:34.102889+0100 AudioPlaybackDemo[611:110775] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothHFP)
Output channel configuration: {Number of hardware channels: 1, Hardware channel names: "MDR-1000X", Are channels available: yes, Active channel indices:}
Opening audio device: inputChannelsWanted: 11, outputChannelsWanted: 11, targetSampleRate: 16000, targetBufferSize: 256
2018-12-06 17:49:51.556093+0100 AudioPlaybackDemo[611:110827] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothHFP)
2018-12-06 17:49:51.556503+0100 AudioPlaybackDemo[611:110827] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothHFP)
handleRouteChange: Category change
2018-12-06 17:49:51.557572+0100 AudioPlaybackDemo[611:110827] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothA2DPOutput)
2018-12-06 17:49:51.557763+0100 AudioPlaybackDemo[611:110775] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothHFP)
2018-12-06 17:49:51.557987+0100 AudioPlaybackDemo[611:110775] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothHFP)
Input channel configuration: {Number of hardware channels: 1, Hardware channel names: "MDR-1000X", Are channels available: yes, Active channel indices: 0}
2018-12-06 17:49:51.561552+0100 AudioPlaybackDemo[611:110775] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothHFP)
2018-12-06 17:49:51.561732+0100 AudioPlaybackDemo[611:110775] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothHFP)
Output channel configuration: {Number of hardware channels: 1, Hardware channel names: "MDR-1000X", Are channels available: yes, Active channel indices: 0}
2018-12-06 17:50:04.703434+0100 AudioPlaybackDemo[611:110827] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothA2DPOutput)
handleRouteChange: Category change
2018-12-06 17:50:04.704149+0100 AudioPlaybackDemo[611:110827] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothHFP)
2018-12-06 17:50:04.704430+0100 AudioPlaybackDemo[611:110827] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothHFP)
2018-12-06 17:50:04.835810+0100 AudioPlaybackDemo[611:110827] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothHFP)
2018-12-06 17:50:04.836097+0100 AudioPlaybackDemo[611:110827] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothHFP)
handleRouteChange: Category change
2018-12-06 17:50:04.836429+0100 AudioPlaybackDemo[611:110827] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port Empfänger (type: Receiver)
2018-12-06 17:50:04.836836+0100 AudioPlaybackDemo[611:110827] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port Empfänger (type: Receiver)
handleRouteChange: Category change
2018-12-06 17:50:04.836948+0100 AudioPlaybackDemo[611:110827] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothHFP)
2018-12-06 17:50:04.837010+0100 AudioPlaybackDemo[611:110827] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothHFP)
Setting target sample rate: 16000
Actual sample rate: 16000
Setting target buffer size: 256
Actual buffer size: 256
2018-12-06 17:50:04.850994+0100 AudioPlaybackDemo[611:110775] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothHFP)
2018-12-06 17:50:04.851039+0100 AudioPlaybackDemo[611:110775] [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields: Unknown selected data source for Port MDR-1000X (type: BluetoothHFP)
Creating the audio unit
Internal buffer size: 4096
2018-12-06 17:50:31.627967+0100 AudioPlaybackDemo[611:110775] [MC] System group container for systemgroup.com.apple.configurationprofiles path is /private/var/containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles
2018-12-06 17:50:31.628153+0100 AudioPlaybackDemo[611:110775] [MC] Reading from public effective user settings.
2018-12-06 17:50:32.066394+0100 AudioPlaybackDemo[611:110775] Unbalanced calls to begin/end appearance transitions for <JuceUIViewController: 0x108b025f0>.

In iOS 12 there are these errors in AVAudioSessionPortImpl.mm.
The right type: BluetoothA2DPOutput is recognised, but with only one channel and a poor sample rate of 16000 Hz, too.

ROLI’s Noise app doesn’t seem to have the problem.
@ed95 Maybe you have a hint for me for getting JUCE AudioPlaybackDemo working like Noise. Thank you for any help!


#2

Can you try changing line 280 of juce_ios_Audio.cpp to:

if (category == AVAudioSessionCategoryPlayAndRecord)
    options |= (AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionAllowBluetooth | AVAudioSessionCategoryOptionAllowBluetoothA2DP);

and see if you get a higher sample rate.

How are you testing this? I can’t see any options in the app to display or change the current sample rate.


#3

Hi Ed, sorry for the delay. I could test it today with the change:
iPad 2018 9.7in, iOS 11.3.1 (i couldn’t test it with 12 because I accidentally updated to 12.1.1 and can’t compile at the moment)

JUCE v5.4.1
Creating iOS audio device
Updating hardware info
Lowest supported sample rate: 8000
Highest supported sample rate: 16000
Trying a sample rate of 9000, got 16000
Available sample rates: 8000 16000
Sample rate after detecting available sample rates: 16000
Available buffer sizes: 64 128 256 512 1024 2048 4096
Buffer size after detecting available buffer sizes: 256
Input channel configuration: {Number of hardware channels: 1, Hardware channel names: "MDR-1000X", Are channels available: yes, Active channel indices:}
Output channel configuration: {Number of hardware channels: 1, Hardware channel names: "MDR-1000X", Are channels available: yes, Active channel indices:}
Opening audio device: inputChannelsWanted: 11, outputChannelsWanted: 11, targetSampleRate: 16000, targetBufferSize: 256
handleRouteChange: Category change
Input channel configuration: {Number of hardware channels: 1, Hardware channel names: "MDR-1000X", Are channels available: yes, Active channel indices: 0}
Output channel configuration: {Number of hardware channels: 1, Hardware channel names: "MDR-1000X", Are channels available: yes, Active channel indices: 0}
handleRouteChange: Category change
Setting target sample rate: 16000
Actual sample rate: 16000
Setting target buffer size: 256
Actual buffer size: 256
handleRouteChange: Category change
Creating the audio unit
handleRouteChange: Category change
handleRouteChange: Category change
Internal buffer size: 4096
2018-12-13 09:29:16.335302+0100 AudioPlaybackDemo[1899:6221019] [MC] System group container for systemgroup.com.apple.configurationprofiles path is /private/var/containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles
2018-12-13 09:29:16.335950+0100 AudioPlaybackDemo[1899:6221019] [MC] Reading from public effective user settings.
2018-12-13 09:29:16.343059+0100 AudioPlaybackDemo[1899:6221019] Unbalanced calls to begin/end appearance transitions for <_UIWaitingForRemoteViewContainerViewController: 0x109e27a00>.

In this case nothing is changing (as you see), I only get monophonic playback with 16kHz.

Getting back to ROLI’s Noise app:
Of course I can’t see the internal samplerate / buffersize used, but my ears tell me, that I get a high fidelity sound with my headphones, which is definitively not mono and >16kHz.


#4

OK, I’ve made a couple of changes to the iOS audio device here -

This will ensure that the best sample rate will be chosen for the bluetooth headphones, but it depends on what input is selected as the OS ties you to a lower sample rate when you are using the BT headphones input (e.g. if they have a mic attached). You’ll need to either deselect the headphones input in the AudioDeviceSelectorComponent or change how the device manager is initialised in the AudioPlaybackDemo:

audioDeviceManager.initialise (0, 2, nullptr, true, {}, nullptr);

As this demo only outputs audio, you don’t need to request any input channels and then you will get the best sample rate available for your headphones and stereo output.


#5

@ed95 Great, thank you. I’ll try it on Monday.


#6

@ed95 It works much better now, thank you!