We modify the Bluetooth stack to improve the sound on headphones without AAC, aptX and LDAC codecs

    Before reading this article, we recommend that you read the previous article: Audio via Bluetooth: as much as possible about profiles, codecs and devices / in English

    Some users of wireless headphones note low sound quality and a lack of high frequencies when using the standard SBC Bluetooth codec, which supports all audio devices. A frequent recommendation for better sound is to buy devices and headphones that support aptX and LDAC codecs. These codecs require licensing fees, so devices with their support are more expensive.

    It turns out that the low quality of SBC is due to the artificial limitations of Bluetooth stacks and headphone settings, and this restriction can be circumvented on any existing devices by software changes to a smartphone or computer.

    SBC Codec

    The SBC codec has many different parameters that are consistent during the connection setup phase. Among them:

    • Number and type of channels: Joint Stereo, Stereo, Dual Channel, Mono;
    • Number of frequency bands: 4 or 8;
    • The number of blocks in the package: 4, 8, 12, 16;
    • Quantization bit allocation algorithm: Loudness, SNR;
    • Maximum and minimum value of the pool of bits used in quantization (bitpool): usually, from 2 to 53.

    The decoding device must support any combination of these parameters. The encoder may not implement all.
    Existing Bluetooth stacks, as a rule, agree on the following profile: Joint Stereo, 8 bands, 16 blocks, Loudness, bitpool 2..53. This profile encodes 44.1 kHz audio with a bit rate of 328 kbps.
    The bitpool parameter directly affects the bitrate within a single profile: the higher it is, the higher the bitrate, and therefore the quality.
    However, the bitpool parameter is not tied to a specific profile; Other parameters also have an impact on the bit rate: the type of channels, the number of frequency bands, the number of blocks. You can increase the bitrate indirectly by negotiating non-standard profiles without changing the bitpool.

    $ bitrate = \ frac {8 \ times frame \ _length \ times sample \ _rate} {subbands \ times blocks} $

    SBC bitrate formula

    For example, Dual Channel mode encodes channels separately, using the entire bitpool for each channel. By forcing the device to use Dual Channel instead of Joint Stereo, we get an almost double bitrate with the same maximum bitpool value: 617 kbps.
    In my opinion, using a non-profile bitpool value at the approval stage is a flaw in the A2DP standard, which led to an artificial limitation of SBC quality. It would be wiser to negotiate bitrate, not bitpool.

    These fixed values, Bitpool and Bitrate, originate from a table with recommended values ​​for high-quality audio. But the recommendation is not a reason to be limited to these values.

    Bluetooth SBC Profile Table

    The A2DP v1.2 specification, which was active from 2007 to 2015, requires all decoding devices to work correctly with bitrates up to 512 kbps:

    The decoder of the SNK shall support all possible bitpool values ​​that do not result in excess of the maximum bit rate. This profile limits the available maximum bit rate to 320kb / s for mono, and 512kb / s for two-channel modes.

    There is no bitrate limit in the new version of the specification. It is assumed that modern headphones released after 2015 and supporting EDR can support bitrates up to ≈730 kbps.

    For some reason, the Linux Bluetooth stacks I tested (PulseAudio), Android, Blackberry, and macOS have artificial limitations on the maximum value of the bitpool parameter, which directly affects the maximum bitrate. But this is not the biggest problem, almost all headphones also limit the maximum bitpool value to 53.
    As I have already seen, most devices work fine on a modified Bluetooth stack with a bit rate of 551 kbit / s, without interruptions and crackle. But such a bitrate will never be negotiated under normal conditions, on ordinary Bluetooth stacks.

    Modifying the Bluetooth Stack

    Any Bluetooth stack that is compatible with the A2DP standard has support for Dual Channel mode, but it is not possible to activate it from the interface.

    Let's add a switch to the interface! I made patches for Android 8.1 and Android 9 that add full support for Dual Channel to the stack, add mode to the mode switching menu to the developer tools, and process SBC with Dual Channel support as if it were an additional codec like aptX, AAC or LDAC ( Android calls it HD Audio) by adding a checkmark to the settings of the Bluetooth device. Here's what it looks like:


    Patch for Android 9
    Patch for Android 8.1

    When the checkbox is activated, Bluetooth audio starts to be transmitted with a bit rate of 551 kbpsif the headphones support a connection at 3 Mbps, or 452 kbps if the headphones only support 2 Mbps.

    This patch is included in the following alternative firmware:
    • LineageOS
    • Resurrection remix
    • crDroid

    Where did 551 and 452 kbit / s come from?

    Bluetooth split-air technology is designed to efficiently transfer large fixed-size packets. Data is transmitted by slots, the largest number of slots sent in one transmission is 5. There are also transmission modes using 1 or 3 slots, but not 2 or 4. In 5 slots, you can transfer up to 679 bytes at a connection speed of 2 Mbps and up to 1021 bytes at a speed of 3 Mbps, and in 3 - 367 and 552 bytes, respectively.


    If we want to transfer less data than 679 or 1021 bytes, but more than 367 or 552 bytes, then the transfer will still take 5 slots, and the data will be transmitted in the same time, which reduces the transmission efficiency.


    SBC in Dual Channel mode, on 44100 Hz audio with Bitpool 38 parameters, 16 blocks per frame, 8 frequency ranges, encodes audio into frames of 164 bytes in size, with a bitrate of 452 kbps.
    Audio must be encapsulated in the L2CAP and AVDTP transfer protocols, which take 16 bytes from the audio payload.

    $ \ begin {align *} framelength & = 4 + \ frac {subbands \ times channels} {2} + \\ & \ begin {cases} \ frac {blocks \ times channels \ times bitpool} {8} & \ text { if mono or dual channel mode} \\ \ frac {subbands + blocks \ times bitpool} {8} & \ text {if joint stereo mode} \\ \ frac {blocks \ times bitpool} {8} & \ text {if stereo mode} \\ \ end {cases} \ end {align *} $

    Thus, in one Bluetooth transmission with 5 slots, it is possible to accommodate 4 audio frames:
    679 (EDR 2 mbit/s DH5) - 4 (L2CAP) - 12 (AVDTP/RTP) - 1 (заголовок SBC) - (164*4) = 6

    We put 11.7 ms of audio data into the sending packet, which will be transmitted in 3.75 ms, and we have 6 unused bytes in the package.
    If you slightly raise bitpool, 4 audio frames can no longer be packaged in one package. You will have to send 3 frames at a time, which reduces the transmission efficiency, reduces the amount of audio transmitted per packet, and will quickly lead to stuttering audio in poor radio conditions.

    In the same way, a bit rate of 551 kbit / s was selected for an EDR of 3 Mbps: with Bitpool 47, 16 blocks in a frame, 8 frequency ranges, the frame size is 200 bytes, with a bitrate of 551 kbit / s. 5 frames or 14.6 ms of music fits in one package.

    The algorithm for calculating all SBC parameters is quite complicated, you can easily get confused if you count manually, so I made an interactive calculator to help those interested: btcodecs.valdikss.org.ru/sbc-bitrate-calculator

    Why is all this necessary?

    Contrary to popular belief about the quality of the sound of the aptX codec, it may produce worse results on some files than SBC with a standard bit rate of 328 kbps.

    SBC dynamically allocates quantization bits for frequency bands, operating on a “bottom to top” basis. If the entire bitrate was used for the low and middle frequencies, the high frequencies will be “cut off” (there will be silence instead).
    aptX quantizes frequency bands with the same number of bits constantly, which is why it has a constant bitrate: 352 kbit / s for 44.1 kHz, 384 kbit / s for 48 kHz, and it cannot “transfer bits” to those frequencies most in need of them. Unlike SBC, aptX will not “cut” the frequencies, but will add quantization noise to them, reducing the dynamic range of the audio, and sometimes introduce characteristic crackles. SBC, on the other hand, “eats up the details” - discards the quietest areas.
    Compared to the SBC 328k, on average, aptX introduces less distortion to music with a wide frequency range, but sometimes it wins on music with a narrow frequency range and wide dynamic range.

    Consider a special case. Spectrogram for recording the piano:

    The main energy lies in the frequencies from 0 to 4 kHz, and lasts up to 10 kHz.
    The spectrogram of the file compressed in aptX looks like this: And it looks like SBC 328k. It can be seen that the SBC 328k periodically completely turned off the range above 16 kHz, and consumed all the available bitrate for ranges below this value. However, aptX introduced more distortion into the frequency spectrum heard by the human ear, which can be seen on the subtracted original spectrogram from the aptX spectrogram (the brighter, the more distortion): While the SBC 328k spoiled the signal in the range from 0 to 10 kHz less, and I cut the rest: the 485k SBC bitrate was enough to save the entire frequency range, without turning off the bands.





    SBC 485k on this composition is significantly ahead of aptX in the range of 0-15 kHz, and with a smaller but still noticeable difference of 15-22 kHz (the darker, the less distortion): Archive of the original audio, SBC and aptX . Switching to the high-bitrate SBC, you will get sound, often superior to aptX, on any headphones. On headphones that support a 3 Mbps EDR connection, a 551 Kbps bit rate produces sound comparable to aptX HD.

    Can I have more?

    The Android patch also has an option to further increase the bitrate for 2 Mbps EDR devices. You can increase the bitrate from 452 kbps to 595 kbps, at the cost of reducing transmission stability in complex radio conditions.
    Just set the variable persist.bluetooth.sbc_hd_higher_bitrate to 1:
    # setprop persist.bluetooth.sbc_hd_higher_bitrate 1

    The extreme bitrate patch has so far been accepted only in LineageOS 15.1, but not in 16.0.

    Device compatibility

    SBC Dual Channel is supported by almost all headphones, speakers and car head units. This is not surprising - the standard prescribes its support in any decoding devices. There are a small number of devices on which this mode causes problems, but these are single instances.
    More details on compatible devices can be found on w3bsit3-dns.com or xda-developers .

    Comparison of sound differences

    I made a web service encoding audio in SBC (as well as aptX and aptX HD) in real time, right in the browser. With it, you can compare the sound of various SBC profiles and other codecs, without actually transmitting audio via Bluetooth, on any wired headphones, speakers, and your favorite music, as well as change the encoding settings directly during audio playback.

    Contact Android Developers

    I wrote to many developers of the Google Bluetooth stack with a request to consider the inclusion of patches in the main Android branch - AOSP, but did not receive a single answer. My patches in the Gerrit patch system for Android also went unanswered by anyone involved.
    I would be glad if I was helped in connection with the developers from Google and the implementation of SBC HD in Android. The gerrit patch is already outdated (this is one of the early revisions), and I will update it if the developers are interested in my changes (it’s not easy for me to update it, I don’t have Android Q compatible devices).


    Users of smartphones with LineageOS, Resurrection Remix and crDroid firmware can be content with improved sound quality now, just activate the option in the settings of the Bluetooth device. Linux users can also get an increased SBC bitrate by installing a patch from Pali Rohár , which, among other things, adds support for aptX, aptX HD and FastStream codecs.

    Also popular now: