Diffusion audio multicanal 5.1 et bluetooth

J’envoie régulièrement l’audio de mon ordinateur portable Thinkpad vers ma barre de son en bluetooth. Alors que celle-ci dispose de toutes les fonctionnalités audio surround, dolby, DTX, 5.1, etc, ça me désole d’envoyer simplement en stéréo alors que je pourrais faire mieux.

D’où mes recherches pour pouvoir envoyer un son plus qualitatif. Au fil de mes recherches je découvre qu’il existe principalement 2 technologies de diffusion audio bluetooth:

  • L’A2DP (Advanced Audio Distribution Profile) est celle qu’on retrouve sur tous les périphériques bluetooth actuels. Elle permet une sortie audio stéréo (qu’on retrouve sous le terme sink). Elle utilise en natif le codec audio SBC qui fournit une qualité audio juste acceptable (références ici et ). Aussi d’autres codecs ont fait leur apparition, SBC XQ qui est une version améliorée de SBC, mais également LDAC, Aptx, AAC ou LC3. Cette page, celle là et cette dernière page expliquent très bien les subtilités qui peuvent exister entre eux. Cette technologie est associée à AVRCP (Audio Video Remote Control Profile) qui permet de gérer les commandes.
  • LE Audio associé au Bluetooth Low Energy (BLE) est un mode basse consommation qui utilise le codec LC3 qui à terme devrait équiper tous les périphériques bluetooth. Ce mode permettra la diffusion vers plusieurs périphériques bluetooth et de pouvoir utiliser la diffusion multicanal 5.1 contrairement aux autres codecs précédemment cités qui sont limités au mono et au stéréo.

Or en connectant ma barre de son « Abri de jardin » (je sais, c’est bizarre…) avec blueman, je me rends compte que je n’ai accès qu’au codec standard SBC et à sa version améliorée SBC XQ. Pas moyen d’avoir un codec plus qualitatif.

Ni une, ni deux, je me lance dans l’installation du serveur audio pipewire car pulseaudio installé de base sur ma Mageia 9 ne gère que l’A2DP et ne gère pas le LE Audio.

Je bascule sous pipewire fourni sur mon système avec l’outil pa-switcher et je constate aucune évolution avec blueman et j’ai toujours les mêmes codecs, je choisis d’installer la dernière version de pipewire à partir des sources. Avant cela, j’ai installé les codecs supplémentaires. Tout d’abord LC3 qu’on récupérera ici. On tape ensuite les commandes suivantes:

tar xvfz liblc3-1.1.1.tar.gz
cd liblc3-1.1.1
meson setup build
cd build

et en tant que root

meson install

On passe à Aptx qu’on récupère sur ce site. On tape ensuite les commandes

tar xvfz libfreeaptx-0.1.1.tar.gz
libfreeaptx-0.1.1
make

Et en tant que root

make install

J’ai installé par ailleurs les packages suivants bluez-devel, sbc, lib64sbc-devel, lib64mysofa-devel et lib64ldac-devel. Pour pipewire, on le récupère sur ce site. On tape les commandes :

tar xvfj pipewire-1.2.6.tar.bz2
pipewire-1.2.6
./autogen.sh --prefix=/usr/local

Et voilà le résultat

pipewire 1.2.6

    systemd conf data                       : YES
    libsystemd                              : YES
    logind                                  : YES
    libselinux                              : NO
    intl support                            : YES
    pipewire-alsa                           : YES
    OpenSSL (for raop-sink)                 : YES
    lilv (for lv2 plugins)                  : NO
    ffado                                   : NO
    RLIMITs                                 : with limits.d file affecting matching PAM users
    PAM defaults                            : without limits.d file affecting all PAM users (not needed with modern systemd or kernel)
    Documentation                           : NO
    Man pages                               : NO

  Misc dependencies
    dbus (Bluetooth, rt, portal, pw-reserve): YES
    SDL2 (video examples)                   : YES
    opus (Bluetooth, RTP)                   : YES
    readline (for pw-cli)                   : YES
    X11 (x11-bell)                          : YES
    libcanberra (x11-bell)                  : NO
    GLib-2.0 (Flatpak support)              : YES
    GIO (GSettings)                         : YES
    WebRTC Echo Canceling < 1.0             : NO
    GLib-2.0 (Snap support)                 : YES
    Gio-2.0 (Snap support)                  : YES
    Apparmor (Snap support)                 : NO
    Snapd-glib (Snap support)               : NO
    Vulkan                                  : NO

  pw-cat/pw-play/pw-dump/filter-chain
    sndfile                                 : YES

  filter-chain
    libmysofa                               : YES

  Streaming between daemons
    libpulse                                : YES
    Avahi DNS-SD (Zeroconf)                 : NO
    Opus with custom modes for NetJack2     : YES
    ROC                                     : NO

  Backend
    libusb (Bluetooth quirks)               : YES
    gstreamer-device-provider               : YES
    gstreamer DMA_DRM support               : NO
    JACK2                                   : NO
    ALSA                                    : YES
    Bluetooth audio                         : YES
    libcamera                               : NO
    Compress-Offload                        : YES
    Udev                                    : YES
    V4L2 kernel header                      : YES
    V4L2 enabled                            : YES

  GStreamer modules
    glib-2.0                                : YES
    gobject-2.0                             : YES
    gmodule-2.0                             : YES
    gio-2.0                                 : YES
    gio-unix-2.0                            : YES
    gstreamer-1.0                           : YES
    gstreamer-base-1.0                      : YES
    gstreamer-video-1.0                     : YES
    gstreamer-audio-1.0                     : YES
    gstreamer-allocators-1.0                : YES

  Bluetooth audio codecs
    SBC                                     : YES
    LDAC                                    : YES
    LDAC ABR                                : YES
    aptX                                    : YES
    AAC                                     : YES
    LC3plus                                 : NO
    Opus                                    : YES
    LC3                                     : YES

  Bluetooth backends
    ModemManager                            : NO

  Optional programs
    find (for header testing)               : YES
    valgrind (test setup)                   : YES

  Session managers
    Build media-session                     : NO
    Build wireplumber                       : YES
    Default session-manager                 : wireplumber

  pw-cat/pw-play/pw-dump tool
    Build pw-cat tool                       : YES
    Build pw-cat with FFmpeg integration    : NO

  Optional Modules
    jack-tunnel                             : NO
    ffado-driver                            : NO
    rt                                      : with RTKit
    portal                                  : YES
    pulse-tunnel                            : YES
    zeroconf-discover                       : NO
    raop-discover (needs Avahi)             : NO
    snapcast-discover (needs Avahi)         : NO
    raop-sink (requires OpenSSL)            : YES
    roc-sink                                : NO
    roc-source                              : NO
    x11-bell                                : NO
    avb                                     : YES

  Functional test programs
    openal-info                             : NO
    pactl                                   : YES

  Subprojects
    lua                                     : YES (from wireplumber)
    wireplumber                             : YES

  User defined options
    prefix                                  : /usr/local

J’avoue que je n’ai pas trouvé les sources de LC3plus, mais peu importe avec les autres codecs c’est déjà largement suffisant pour continuer. On tape ensuite make puis en tant que root make install. L’installation se fait sous /usr/local, ce qui évite d’écraser l’installation système. On stoppe déjà les processus pipewire système en tapant :

systemctl --user stop pipewire
systemctl --user stop pipewire.socket
systemctl --user stop pipewire-pulse
systemctl --user stop pipewire-pulse.socket

Et on lance maintenant les commandes ci-dessous, chacune dans un terminal distinct :

/usr/local/bin/pipewire
/usr/local/bin/pipewire-pulse
/usr/local/bin/wireplumber -c /usr/local/share/wireplumber/wireplumber.conf

Et voilà le résultat pour la dernière commande


déc. 22 12:12:57 cilaos.kervao.fr bluetoothd[857]: Endpoint registered: sender=:1.197 path=/MediaEndpoint/A2DPSource/ldac
déc. 22 12:12:57 cilaos.kervao.fr bluetoothd[857]: Endpoint registered: sender=:1.197 path=/MediaEndpoint/A2DPSink/aptx_hd
déc. 22 12:12:57 cilaos.kervao.fr bluetoothd[857]: Endpoint registered: sender=:1.197 path=/MediaEndpoint/A2DPSource/aptx_hd
déc. 22 12:12:57 cilaos.kervao.fr bluetoothd[857]: Endpoint registered: sender=:1.197 path=/MediaEndpoint/A2DPSink/aptx
déc. 22 12:12:57 cilaos.kervao.fr bluetoothd[857]: Endpoint registered: sender=:1.197 path=/MediaEndpoint/A2DPSource/aptx
déc. 22 12:12:57 cilaos.kervao.fr bluetoothd[857]: Endpoint registered: sender=:1.197 path=/MediaEndpoint/A2DPSink/aac
déc. 22 12:12:57 cilaos.kervao.fr bluetoothd[857]: Endpoint registered: sender=:1.197 path=/MediaEndpoint/A2DPSource/aac
déc. 22 12:12:57 cilaos.kervao.fr bluetoothd[857]: Endpoint registered: sender=:1.197 path=/MediaEndpoint/A2DPSink/opus_g
déc. 22 12:12:57 cilaos.kervao.fr bluetoothd[857]: Endpoint registered: sender=:1.197 path=/MediaEndpoint/A2DPSource/opus_g
déc. 22 12:12:57 cilaos.kervao.fr bluetoothd[857]: Endpoint registered: sender=:1.197 path=/MediaEndpoint/A2DPSink/sbc
déc. 22 12:12:57 cilaos.kervao.fr bluetoothd[857]: Endpoint registered: sender=:1.197 path=/MediaEndpoint/A2DPSource/sbc
déc. 22 12:12:57 cilaos.kervao.fr bluetoothd[857]: Endpoint registered: sender=:1.197 path=/MediaEndpoint/A2DPSource/aptx_ll_1
déc. 22 12:12:57 cilaos.kervao.fr bluetoothd[857]: Endpoint registered: sender=:1.197 path=/MediaEndpoint/A2DPSource/aptx_ll_0
déc. 22 12:12:57 cilaos.kervao.fr bluetoothd[857]: Endpoint registered: sender=:1.197 path=/MediaEndpoint/A2DPSource/aptx_ll_duplex_1
déc. 22 12:12:57 cilaos.kervao.fr bluetoothd[857]: Endpoint registered: sender=:1.197 path=/MediaEndpoint/A2DPSource/aptx_ll_duplex_0
déc. 22 12:12:57 cilaos.kervao.fr bluetoothd[857]: Endpoint registered: sender=:1.197 path=/MediaEndpoint/A2DPSource/faststream
déc. 22 12:12:57 cilaos.kervao.fr bluetoothd[857]: Endpoint registered: sender=:1.197 path=/MediaEndpoint/A2DPSource/faststream_duplex
déc. 22 12:12:57 cilaos.kervao.fr bluetoothd[857]: Endpoint registered: sender=:1.197 path=/MediaEndpoint/A2DPSink/opus_05
déc. 22 12:12:57 cilaos.kervao.fr bluetoothd[857]: Endpoint registered: sender=:1.197 path=/MediaEndpoint/A2DPSource/opus_05
déc. 22 12:12:57 cilaos.kervao.fr bluetoothd[857]: Endpoint registered: sender=:1.197 path=/MediaEndpoint/A2DPSink/opus_05_duplex
déc. 22 12:12:57 cilaos.kervao.fr bluetoothd[857]: Endpoint registered: sender=:1.197 path=/MediaEndpoint/A2DPSource/opus_05_duplex

C’est tout bon en ce qui concerne les nouveaux codecs. Et là je constate avec désappointement que blueman ne m’offre pas mieux, je recompile donc bluez qui fournit le daemon bluetoothd qu’on trouvera ici. Je l’installe en tapant les commandes:

tar xvf bluez-5.66.tar.xz
cd bluez-5.66/
./configure --enable-experimental
make

puis en tant que root make install. On modifie le fichier de configuration /etc/bluetooth/main.conf pour que LE Audio soit bien en compte, en modifiant les lignes suivantes :

# Enables D-Bus experimental interfaces
# Possible values: true or false
Experimental = true

# Enables kernel experimental features, alternatively a list of UUIDs
# can be given.
# Possible values: true,false,<UUID List>
# Possible UUIDS:
# d4992530-b9ec-469f-ab01-6c481c47da1c (BlueZ Experimental Debug)
# 671b10b5-42c0-4696-9227-eb28d1b049d6 (BlueZ Experimental Simultaneous Central and Peripheral)
# 15c0a148-c273-11ea-b3de-0242ac130004 (BlueZ Experimental LL privacy)
# 330859bc-7506-492d-9370-9a6f0614037f (BlueZ Experimental Bluetooth Quality Report)
# a6695ace-ee7f-4fb9-881a-5fac66c629af (BlueZ Experimental Offload Codecs)
6fbaf188-05e0-496a-9885-d6ddfdb4e03e (BlueZ Experimental ISO socket)
# Defaults to false.
KernelExperimental = true

Et là je me retrouve avec une installation hybride entre une installation système et local bluez et pipewire avec un mix de fichiers et les services systemd des versions locales qui ont écrasé les versions système. Au reboot du PC, c’est bien par défaut les binaires locaux qui sont lancés, pour vérifier cela il suffit de taper systemctl –user status pipewire et voilà le résultat

● pipewire.service - PipeWire Multimedia Service
     Loaded: loaded (/usr/local/lib/systemd/user/pipewire.service; enabled; preset: disabled)
     Active: active (running) since Sun 2024-12-22 12:20:23 CET; 1h 23min ago
TriggeredBy: ● pipewire.socket
   Main PID: 6430 (pipewire)
      Tasks: 3 (limit: 9205)
     Memory: 9.9M
        CPU: 6.371s
     CGroup: /user.slice/user-5001.slice/user@5001.service/session.slice/pipewire.service
             └─6430 /usr/local/bin/pipewire

déc. 22 12:20:23 cilaos.kervao.fr systemd[6414]: Started pipewire.service.

Et voilà ce que donne systemctl –user status wireplumber

● wireplumber.service - Multimedia Service Session Manager
     Loaded: loaded (/usr/local/lib/systemd/user/wireplumber.service; enabled; preset: disabled)
     Active: active (running) since Sun 2024-12-22 12:20:23 CET; 1h 24min ago
   Main PID: 6431 (wireplumber)
      Tasks: 6 (limit: 9205)
     Memory: 7.1M
        CPU: 38.317s
     CGroup: /user.slice/user-5001.slice/user@5001.service/session.slice/wireplumber.service
             └─6431 /usr/local/bin/wireplumber -c /usr/local/share/wireplumber/wireplumber.conf

déc. 22 12:20:23 cilaos.kervao.fr systemd[6414]: Started wireplumber.service.
déc. 22 12:20:23 cilaos.kervao.fr wireplumber[6431]: wp-internal-comp-loader: Loading profile 'main'
déc. 22 12:20:23 cilaos.kervao.fr wireplumber[6431]: wp-device: SPA handle 'api.libcamera.enum.manager' could not be loaded; is it installed?
déc. 22 12:20:23 cilaos.kervao.fr wireplumber[6431]: s-monitors-libcamera: PipeWire's libcamera SPA plugin is missing or broken. Some camera types may not be supported.

Je ne prête pas attention au dernier warning, car je n’ai pas compilé pipewire avec libcamera. Et en tant que root si je tape systemctl status bluetooth, j’obtiens :

● bluetooth.service - Bluetooth service
     Loaded: loaded (/usr/lib/systemd/system/bluetooth.service; enabled; preset: enabled)
     Active: active (running) since Sun 2024-12-22 12:19:47 CET; 1h 8min ago
       Docs: man:bluetoothd(8)
   Main PID: 850 (bluetoothd)
     Status: "Running"
      Tasks: 1 (limit: 9205)
     Memory: 3.2M
        CPU: 1.517s
     CGroup: /system.slice/bluetooth.service
             └─850 /usr/local/libexec/bluetooth/bluetoothd

Dans un premier temps j’avais erreur comme quoi wireplumber ne trouvait pas les codecs, j’ai dû en tant que root taper :

mv /usr/share/pipewire /usr/share/pipewire.system
ln -s /usr/local/share/pipeline /usr/share

Puis ensuite il me disait que ma barre de son était déjà connectée et pas moyen de l’utiliser, j’ai dû totalement réinitialisé la connexion avec la commande bluetoothctl avec mon périphérique qui a l’identité AC:F1:08:56:5C:DF en tapant au prompt les commandes suivantes:

untrust AC:F1:08:56:5C:DF
remove AC:F1:08:56:5C:DF
scan on
scan off
pair AC:F1:08:56:5C:DF

Au bout de toutes ces pérégrinations je connecte ma barre de son avec blueman et je constate avec dépit que j’en suis au même stade avec SBC et SBC XQ comme codecs. En dernier ressort, je compile blueman, mais ça ne change rien à l’affaire.

Je me tourne vers les spécifications de ma barre de son LG SL10YG et ce n’est qu’à ce moment là que je comprends que les modes multicanaux ne marchent que via l’interface HDMI et qu’elle se repose sur Bluetooth 4.2 qui ne prend pas en charge le LE Audio (qui arrive avec la version 5.2). J’aurais dû commencer par là !!

D’ailleurs la commande bluetoothctl info me renvoie :

UUID: Audio Sink                (0000110b-0000-1000-8000-00805f9b34fb)

j’aurais du avoir quelque chose comme :

UUUUID: Published Audio Capabilities (00001850-0000-1000-8000-00805f9b34fb)

Fin du sketch qui m’aura pris quelques heures et qui m’a permis de passer à pipewire et de découvrir son fonctionnement.

Mon installation est stable dans cet état, mais pour revenir en arrière, il faut désinstaller les installations locales de pipewire et bluetooth (make uninstall dans les répertoires d’installation) et réinstaller les packages pipewire et bluetooth avec la commande urpmi –replacepkgs –force.

Laisser un commentaire