This page looks best with JavaScript enabled

Bluetooth Headphones on FreeBSD

 ·  πŸŽƒ kr0m

Bluetooth support on Unix systems has always been precarious, causing all kinds of problems. The only exception are mobile Android/IOS systems. In Linux, despite acting as the base of Android, the performance is terrible for some reason. In this article, we will see how to solve all these problems regardless of the operating system, as we will use a USB sound card that will transform the signal to BT.

First, let’s indicate the hardware we have so that there is no confusion:

We check the system’s sound cards, and when we connect the 1Mii, a new device, pcm8, appears:

cat /dev/sndstat

Installed devices:  
pcm0: <NVIDIA (0x0084) (HDMI/DP 8ch)> (play)  
pcm1: <NVIDIA (0x0084) (HDMI/DP 8ch)> (play)  
pcm2: <NVIDIA (0x0084) (HDMI/DP 8ch)> (play)  
pcm3: <NVIDIA (0x0084) (HDMI/DP 8ch)> (play)  
pcm4: <Realtek ALC1150 (Analog 5.1+HP/2.0)> (play/rec) default  
pcm5: <Realtek ALC1150 (Rear Digital)> (play)  
pcm6: <Realtek ALC1150 (Front Analog Mic)> (rec)  
pcm7: <USB audio> (rec)  
pcm8: <USB audio> (play/rec)  
No devices installed from userspace.

To change the sound card that the operating system should use, it is as simple as running:

sysctl hw.snd.default_unit=8

On the headphone side, we just need to pair it with the 1Mii as indicated in the user manual.

To make the sound card switching more agile, I have programmed a small script:

vi .scripts/audioSwap.sh

#!/usr/local/bin/bash

LAST_DEVICE=$(grep pcm /dev/sndstat | awk -F ":" '{print$1}' | awk -F "pcm" '{print$2}' | tail -n1)
#echo "LAST_DEVICE: $LAST_DEVICE"
for NEXT_DEVICE in $(grep pcm /dev/sndstat | awk -F ":" '{print$1}' | awk -F "pcm" '{print$2}'); do
    #echo "NEXT_DEVICE: $NEXT_DEVICE"
    CURRENT_DEVICE=$(grep default /dev/sndstat | awk -F ":" '{print$1}' | awk -F "pcm" '{print$2}')
    #echo "CURRENT_DEVICE: $CURRENT_DEVICE"
    if [ $NEXT_DEVICE -le $CURRENT_DEVICE ] && [ $NEXT_DEVICE -ne $LAST_DEVICE ]; then
        #echo "Continue"
        continue
    else
        if [ $CURRENT_DEVICE -eq $LAST_DEVICE ] && [ $NEXT_DEVICE -eq $LAST_DEVICE ]; then
            NEXT_DEVICE=0
            #echo "NEXT_DEVICE: $NEXT_DEVICE"
        fi
        DEVICE_NAME=$(grep pcm$NEXT_DEVICE /dev/sndstat | awk -F "<" '{print$2}' | awk -F ">" '{print$1}')
        sysctl hw.snd.default_unit=$NEXT_DEVICE
        if [ $? -eq 0 ]; then
            notify-send "Audio device changed: PCM$NEXT_DEVICE: $DEVICE_NAME"
            # Needed for Ubuntu jail
            killall pulseaudio
            break
        else
            notify-send "Error changing audio device, reverting"
            sysctl hw.snd.default_unit=$CURRENT_DEVICE
        fi
    fi
done

We assign the necessary permissions:

chmod 700 .scripts/audioSwap.sh

And I have modified the Awesome configuration to run the script with the “Mod + .” shortcut.

vi .config/awesome/rc.lua

-- {{{ Key bindings
globalkeys = awful.util.table.join(
    -- CUSTOM KEYBINDINGS:
    awful.key({modkey, }, ".", function () awful.util.spawn("/home/kr0m/.scripts/audioSwap.sh") end),

The only drawback is that applications have to be restarted to use the newly configured card. In Chrome, for example, you have to close the player tab and reopen it.

As for VoIP software, they work perfectly. We just need to switch the 1Mii to call mode and choose the correct device in the VoIP software. We must bear in mind that the BT bandwidth is very limited, so in order to receive and emit audio (call mode), the audio quality will be notably reduced. Remember to switch to playback mode when you finish the call to enjoy superior audio quality again.

NOTE: The firmware of my headphones must be buggy. When switching from audio to call mode, there is no problem, but when switching from call mode to audio, it is necessary to turn them off and on again to reconnect. If we don’t do this, there is no audio.

In systems like Android/IOS, apparently the sound quality does not decrease because they do some kind of multiplexing of audio transmission/reception so as not to have to switch to call mode. I leave here the link where they discuss it:

Bluetooth doesn’t have the bandwidth necessary to act as A2DP sink while also transmitting audio back to the pc. Android phones and iPhones switch "on the fly" so that it sounds good to both ends but the Linux implementation does not.

It is worth noting that in Mumble, it is no longer necessary to do anything described in this previous article , just choose the correct audio device, in my case default OSS.


Another software that works without problems is Discord. You just have to close the browser tab and reopen it after changing the sound card of the operating system.

If you liked the article, you can treat me to a RedBull here