How to improve Bluetooth audio quality
#1
Hi all,

after almost losing my faith in humanity in a time when the mobile world is dominated by two [...], there still seems to be a glimmer of hope. MANY thanks to all who were involved in the development of the PinePhone, and especially to those who were engaged in the creation of the various Linux distributions. For me a dream has come true.

Mobian is so great! What I'm not satisfied with is Bluetooth A2DP audio performance. In the default configuration, the sound stutters and after some time the Bluetooth stack reduces the data rate -- hoping to deliver stutter-free audio. I don't expect true HiFi on the go, but I'm no fan of stuttering and compressy-rattling mids either.

After doing some research, I've found various ways to fix this:

1. Increase the priority of PulseAudio
2. Increase the buffer size of the encoder
3. Install other codec modues and increase minimum allowed bitpool

In detail:

1. Increase the priority of PulseAudio

Basically follow the instructions from here: https://wiki.ubuntuusers.de/PulseAudio/#...t-erhoehen

In /etc/pulse/daemon.conf, add:

Code:
high-priority = yes
rlimit-nice = 31
nice-level = -11
realtime-scheduling = ye
rlimit-rtprio = 9
realtime-priority = 9

In /etc/security/limits.conf, add:

Code:
mobian    -  nice  -11
mobian    -  rtprio  99

Reboot the PinePhone. The PulseAudio daemon should now run with a niceness of -11 (use the 'top' command to verify this).

2. Increase the buffer size of the encoder

Here's a script that increases the audio buffer. Connect the Bluetooth headphones, then run the script.

Code:
# based on https://askubuntu.com/a/1207648 and https://askubuntu.com/a/171165
BLUEZCARD=`pactl list cards short | egrep -o bluez.*[[:space:]]`
pactl set-port-latency-offset $BLUEZCARD headset-output 100000
sudo service bluetooth restart
pactl list | grep -Pzo '.*bluez_card(.*\n)*'

Steps 1 and 2 together should already dramatically reduce the stuttering.

3. Install other codec modues and increase minimum allowed bitpool

To get rid of the low data rates, follow the instructions here: https://github.com/EHfive/pulseaudio-modules-bt. This should also give you AptX support, but I have not tried this (don't have a compatible set). Some notes:

Install the required minimum packages:

Code:
sudo apt install libpulse-dev git cmake libdbus-1-dev libsbc-dev libavcodec-dev libltdl-dev libbluetooth-dev

Also install libpulse-dev, otherwise the backup of the original modules will fail. When running these commands, take them apart first. I mean, instead of directly executing

    MODDIR=`pkg-config --variable=modlibexecdir libpulse`

fist try to run

    pkg-config --variable=modlibexecdir libpulse

to see if that works.

Pull the sources and do the install mode "A. build for PulseAudio releases (e.g., v12.0, v12.2, etc.)". This worked for me.

Edit /etc/pulse/default.pa to configure everything.

In contrast to what's on the GitHub page, look for "discover", as there is already an entry for the module "module-bluetooth-disvover".

Code:
.ifexists module-bluetooth-discover.so
load-module module-bluetooth-discover a2dp_config="sbc_min_bp=53 sbc_max_bp=53"
.endif

Play around with the parameters "sbc_min_bp" and "sbc_max_bp". To test if the new module is working, set both values to e.g. 2. Then run

    pulseaudio -k; pulseaudio --start

Reconnect your headset and listen to some music. This setting should give a very low quality, but now you know it's working. Then try to find the highest possible values where the payback does not yet stutter. For me, around 36-38 seems to work (EDIT: 53, the maximum value, also works fine for me). If you're happy with the result, you can remove the "sbc_max_bp" option.

I haven't messed around with the other options. I would love to hear about experiences and settings.

All the best,
Sebastian
#2
Welcome.
1 of the best first posts I have ever seen (makes me want to go get a BT headset!), great to have you among us!
  • ROCKPro64 v2.1 2GB, 16Gb eMMC for rootfs, SX8200Pro 512GB NVMe for /home, HDMI video & sound, Bluetooth keyboard & mouse. Arch (5.14 kernel, Openbox desktop) for general purpose daily PC.
  • PinePhone BraveHeart now v1.2b 3/32Gb daily driver, dual boot via p-boot with Mobian/f2fs/Phosh on eMMC, Arch/ext4/Phosh on SDcard
  • PinePhone v1.2a 2G/16Gb that needs USB board replaced
#3
(07-23-2020, 12:18 PM)CyberSeb Wrote: Hi all,

What I'm not satisfied with is Bluetooth A2DP audio performance. In the default configuration, the sound stutters and after some time the Bluetooth stack reduces the data rate -- hoping to deliver stutter-free audio. I don't expect true HiFi on the go, but I'm no fan of stuttering and compressy-rattling mids either.
Really interesting, I'll give it a try, at least the first two points. I am no fan of bluetooth audio. I only own a bluetooth headset since three months and audio quality is less than satisfactory using raspbian, or debian. That is background hammering noise when no sound, low music or only voice is being played.
I tested the bluetooth headset with mobian because of your post. I played some music from the SD card using lolipop and stuttering only happened once with no user interaction.
I agree that with user interaction stuttering happens quite frequently. I didn't experience any sound distortion on the mid freqs. I could live with it. Not with the background hammering noise though. : (
I'll test it again after applying your two first points.
Thank you for sharing this.
#4
Feedback:
I tried the first two points.
On the first point I wonder if the line: mobian - rtprio 99  should be mobian - rtprio 9?
On the second point, the script fails on the second command with the message "failure.no such entity"
After the third command the headset is not connected 
anymore and must be connected again manually.

If I try afterwards to play some music and then open the calculator and enter a number quickly, stuttering happens, so obviously only the first point is not enough.
#5
Hi all!

@dukla2000: Many thanks for the warm welcome! :-)

@fernando_c_m: Thanks for trying it out. If the script fails at this point, then the headset is not yet registered by PulseAudio. It takes a few seconds (2-5?). Try rerunning the command (the one that start with "BLUEZCARD= ...") again. And yes, the headset gets disconnected after running the command. You only have to run it once. "rtprio 99" is from the site linked above. It's an upper range limit, so that should be fine.

I have some news for you, after fiddling around for a few days. Here's fix no. 4:

4. Disable WiFi / Bluetooth Coexistence

WiFi and Bluetooth operate on the same 2.4GHz frequency range, and this can cause issues. I noticed stuttering when I was logged into the PinePhone via SSH. Disabling the coexistence mode seems to help. Here's what I did (steps to replicate):

1. Run "lsmod", which prints out a list of all loaded kernel modules. We're looking for "8723cs", which is the WiFi (and Bluetooth?) module.

2. Run "sudo modinfo 8723cs | grep co-existence", which prints out the module's options for the co-exitence setting. You should get:

Code:
parm:          rtw_btcoex_enable:BT co-existence on/off, 0:off, 1:on, 2:by efuse (int)


3. Run "cat /sys/module/8723cs/parameters/rtw_btcoex_enable", this will print out the current setting, which should be 2.

To disable the coexistence, do the following:

4. Create the file "/etc/modprobe.d/8723cs-opt.conf" with the following content: "options 8723cs rtw_btcoex_enable=0" (without quotation marks).

5. Reboot the PinePhone. After running the cat command (step 3) again, you should get 0.

I am by no means an expert in this area, so I would be grateful if someone could comment on it. But this has improved the link quality dramatically for me, and I can now revise option 3 from above:

3. Install other codec modues and increase minimum allowed bitpool (update)

I'm now using the setting 

Code:
load-module module-bluetooth-discover a2dp_config="sbc_freq=44k sbc_cmode=joint_stereo sbc_min_bp=46 sbc_max_bp=46"

in /etc/pulse/default.pa, which works just fine and is acceptable in terms of sound quality (compression). From https://btcodecs.valdikss.org.ru/codec-compatibility/ (which was linked at: https://github.com/EHfive/pulseaudio-modules-bt), and by searching for the first digits of my headsets' MAC address, my headset should support a maximum bitpool of 53 and dual channel SBC. But that's not working without stuttering. 36-38 is too low, sounds very compressed to my ears.

Audio is sometimes still choppy for me, especially if the phone is doing other work. I also do not yet fully understand if WiFi is still an issue and if cellular is also. But in general it's now very usable with my tweaks. The "Lollypop" player is the best I've come across!  Heart

Best, Sebastian
#6
Hi, the fourth point certainly is worth trying as it could be the source of my background hammering noise.
I found the issue on the second point: the port should be headset-output instead of headphones-output.
By the way, the stuttering was gone after applying points 1 and 2.
Only I managed to crash lollypop just by entering numbers quickly on the calculator, and afterwards a high pitch continuous noise is heard on the headset. : )
Restarting bluetooth solves this.
#7
Hi @fernando_c_m,

oh thanks for your feedback. I don't know how this error has crept in! I've fixed the original post.

Here's an updated version of bluetooth.sh:

Code:
#!/bin/bash
# Note: Bluetooth headset must be connect when running this script.

# Enable auto connection of the bluetooth device (add "load-module module-switch-on-connect" to /etc/pulse/default.pa first):
MACADDR=`pactl list cards | grep -o -E '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}'`
bluetoothctl trust $MACADDR

# Increase latency:
BLUEZCARD=`pactl list cards short | egrep -o bluez.*[[:space:]]`
SNDDEVICE=`pactl list | grep '\-output:' | head -n1 | cut -d ":" -f1 | xargs`
pactl set-port-latency-offset $BLUEZCARD $SNDDEVICE 100000

# Restart bluetooth:
sudo service bluetooth restart

# Reconnect:
bluetoothctl connect $MACADDR

# Show current settings:
pactl list | grep -Pzo '.*bluez_card(.*\n)*'

Notice that the script now tries to reconnect the bluetooth device after restarting the bluetooth service. It also tries to setup an automatic bluetooth reconnection (you need to edit /etc/pulse/default.pa first, see script).

This sort of works, but is not perfect! Sometimes there is a loud hum after reconnecting, this has happend with both of my bluetooth headsets. Using delays in the script could potentially help.

What I haven't figured out yet is how to get the buttons on the headsets working. According to https://wiki.archlinux.org/index.php/Blu...a_controls, this should work with "mpris-proxy". The tool recognizes the bluetooth connections and the players (I've tried Lollypop and Rhythmbox), but it does not work.

Cheers,
Sebastian


Possibly Related Threads…
Thread Author Replies Views Last Post
  podcast shuts down after 10 minutes or perhaps bluetooth motox6 10 1,005 09-17-2021, 11:37 AM
Last Post: ragreenburg
  Is there a better audio / podcast player? motox6 15 4,108 08-24-2021, 04:08 PM
Last Post: ragreenburg
  phone call using built it app will not go to bluetooth motox6 3 535 06-28-2021, 11:03 AM
Last Post: wibble
  Jerky wifi and bluetooth motox6 0 322 06-22-2021, 12:50 AM
Last Post: motox6
  audio quality on phone Rainer 0 326 05-28-2021, 09:25 AM
Last Post: Rainer
Information Bluetooth DIsconnect Problems? RTP 3 1,606 05-20-2021, 09:28 AM
Last Post: Emichel2020
  Bluetooth audio stalling (maybe the whole phone) motox6 1 433 05-18-2021, 10:15 AM
Last Post: wibble
  Any trick to fix terrible audio? daniel 2 788 02-18-2021, 06:29 PM
Last Post: natasha
  Audio over USB 3x5co 1 746 01-05-2021, 06:21 PM
Last Post: wibble
  Keep phone awake when audio is playing 3x5co 2 1,005 12-27-2020, 11:25 PM
Last Post: 3x5co

Forum Jump:


Users browsing this thread: 1 Guest(s)