Bluetooth Stereo Audio (A2DP), Devices, Linux

      Kommentare deaktiviert für Bluetooth Stereo Audio (A2DP), Devices, Linux

General Introduction

Well, Bluetooth has always been a major source of joy, if you are into a kind of tech-SM 😉 It is very abstract and there are profiles and protocols for almost everything – and acronyms! Lots of acronyms, which can really make it hard to understand what is actually written in the spec documents.

I am currently looking at stereo audio over Bluetooth, which is called A2DP – Advanced Audio Distribution Profile. This again includes a bunch of sub protocols to actually do the work, like AVDTP (Audio/Video Distribution Transport Protocol) and GAVDP (Generic Audio/Video Distribution Profile). These are accompanied by AVRCP (Audio/Video Remote Control Profile), which is kind of the remote control protocol – play, pause etc.

Using AVDTP the source and the sink can negotiate a common set of parameters to use for the coming transmission, like which codecs are supported, which frequencies, how many channels, additional codec parameters and so on. Upon connection of a new A2DP device with a host the host will usually query the device about its capabilities (AVDTP Discover and AVDTP GetCapabilities) and choose the best match (AVDTP SetConfiguration).

Bluetooth was made for robustness and low power. Low power means low CPU power being necessary to speak to and drive a Bluetooth interface through its host controller interface (HCI) and low transmission power and short transmission frames over the air.

Audio signals are by their nature of medium bandwidth and have consist of an almost constant data stream, you do not want to have gaps in your playback. So in general a stereo audio stream is suitable for Bluetooth transmission, but it would not be optimal. So the Bluetooth special interest group (SIG – yet another acronym) specified different encodings of audio data for the stream, not the raw audio PCM – 16bit per sample, stereo, 44.1kHz would be 176,4 kbytes per second, which is quite a lot in terms of a constant data stream.

So the Bluetooth SIG came up with compressed audio streams. Since most common audio compression technologies, like MP3, AAC and thelike are patented, they created their own, Low Complexity Subband Coding (SBC). This is the mandatory codec for A2DP stereo devices. While SBC is pretty efficient and not really bad by default, it is not en-par with a good MP3 and in special not AAC encoding.

Bluetooth wouldn’t be Bluetooth if it would not allow different codecs, so optionally MPEG-1 Part 3/MPEG-2 Part 3 (MP2 and MP3), MPEG-2 Part 7/MPEG-4 Part 3 (AAC and HE-AAC), and ATRAC can also be supported but most devices do not do so. It is also extensible to support manufacturer-defined codecs, such as aptX which tries to alleviate the shortcomings of SBC. AptX was developed by Qualcom, is licensed (bought?) by Cambridge Silicon Radio (CSR, one of the largest Bluetooth chipset manufacturers) and is highly proprietary. There is no encoder available for it as open source or free software. So it is not not usable for me.

Linux, BlueZ and Stereo Audio over Bluetooth

The Linux Bluetooth stack BlueZ supports A2DP for quite some time now. The whole audio stuff is a little complex in Linux. There are hardware drivers that drive audio hardware, like a soundcard, this is the lowest end of the stack. Then there are applications that want to play or capture audio, in various formats. Traditionally these formats are PCM based, i.e. some kind of digitized waveforms, quantizing the wave by sampling its amplitude in constant intervals (sample rate) with a certain resolution (bits per sample). A stereo HiFi audio signal is usually sampled @44.1kHz with 16 bits per sample and two channels. The hardware can usually directly playback or capture such PCM streams.

Now imagine two applications that want to simultaneously play a sound, but there is only one hardware to play it. What can you do? And even worse, if those two sounds do not share the same audio format? Then a third instance is needed to mix the two sounds into one PCM stream that can then be sent to the hardware. In case of format differences the mixing instance can also resample the input source signals to match the output to the hardware sink.

So the common ground for all this audio stack is PCM samples. An audio player, like Audacious (an MP3 player), would read an MP3, OGG or otherwise compressed audio file, decode it into a PCM stream and sends it to the mixing and multiplexing instance, nowadays Pulse Audio. Pulse Audio will then mix this with other incoming audio signals and output it to one of the Pulse Audio sinks, which can be either the hardware soundcard or a – tata – Bluetooth A2DP sink.

Now we have a PCM signal which is supposed to be played back through Bluetooth A2DP. But A2DP does not support PCM directly so it must be re-encoded using a codec which is supported by the A2DP sink. The mandatory codec is SBC so in Linux all A2DP playback will get re-encoded by the SBC codec, then sent to the A2DP hardware, decoded there and then finally turned into an audio signal again. So MP3 to A2DP playback looks roughly like this:

MP3 decode -> PCM -> SBC encode -> SBC decode -> PCM -> DAC (digital to analogue converter)

This is not optimal. First of all SBC is not as good as MP3 or other more widely used codecs. Second, SBC, MP3, AAC, OGG and many others are not lossless, i.e. they loose quality compared to the original input signal. In the above scenario we loose quality twice, while encoding and decoding the MP3 and while encoding and decoding SBC. At least most of my digital music collection is already encoded in MP3 or OGG so it would make much more sense to directly send the MP3, AAC or OGG file to the A2DP sink?

But this is not yet possible in Linux…

Long Story’s Conclusion

Well, I own a bunch of Bluetooth A2DP devices and am wondering which codecs they might support, apart from SBC. The result is pretty disillusioning, almost all only support SBC, even the very nice Bose Soundlink Mini. But I have one device that supports at least AAC, hooray! So let’s play with this a little… stay tuned for more…