De quoi s'agit-il?
J'ai récemment eu l'opportunité de me pencher sur la possibilité d'écouter dans de bonnes conditions des enregistrements sonores qui disposent de plus de deux canaux. Des films en 5.1 (6 canaux) quoi. Et j'ai découvert un univers complexe et contre intuitif, qui plus est, mais ce n'est qu'une impression non vérifié, peu utilisé donc moins testé. J'ai donc eu envie d'écrire ici mon retour d'expérience avec l'espoir qu'il permettra à d'autres d'y voir clair plus vite que moi.
Il n'est ici pas question de juger de la qualité sonore des différentes technologies mise en œuvre, ni de construire un référentiel historique rigoureux. L'objet est de poser l'architecture et les clés qui permettent d'avoir une idée de pourquoi ça ne marche pas, de manière très pratique.
Les matériels
Les matériels que l'on veut mettre en place sont, selon ce qui est disponible sur le marché, les suivants :
- Un ordinateur plutôt classique pour les standards d'aujourd'hui avec une carte son intégrée à la carte mère.
- Un amplificateur audio numérique capable d'alimenter six voies de haut-parleurs (dit amplificateur 5.1). Afin éventuellement de connecter d'autres appareils, j'ai trouvé intéressant qu'il puisse faire office de commutateur HDMI et acquérir le son via HDMI (dit récepteur AV 5.1).
- Un jeu de cinq enceintes et un caisson de basses.
On va s'intéresser à la liaison entre l'ordinateur et le réception AV.
Liaison numérique multicanal
Il semble que les moyens de transmettre un son multicanal (plus que stéréo) entre deux appareils grand public soient les suivants :
- à l'aide d'autant de câbles que de voies, souvent avec des connecteurs RCA, mais c'est souvent analogique et ça fait beaucoup de câbles, c'est pourquoi je n'ai pas creusé cette piste.
- en numérique avec un câble fibre optique et des connecteurs TOSLINK ou un câble coaxial avec connecteurs RCA ou AES-EBU et le protocole S/PDIF (IEC958).
- en numérique sur HDMI ce qui a l'avantage de tout faire passer dans le même câble (audio et vidéo numérique).
En HDMI, il y a plusieurs façons de transmettre un son numérique multicanal dont au moins les suivantes :
- LPCM : il faut comprendre toutes les voies décodées sans compression
- encodé dans un signal stéréo (souvent le CODEC AC3 ou DTS mais il y en a d'autres). Mais pourquoi donc cacher six voies dans deux? Cela s'explique parce qu'historiquement, le protocole S/PDIF fut conçu pour le CD et deux voies. On peut remarquer que l'AC3 ou le DTS sont des encodages avec pertes.
Y'a pas le son des dialogues
Par exemple, sur le récepteur AV que j'ai choisi pour son faible encombrement, mais qui vu son faible prix, est plutôt bas de gamme, les capacités affichées sont explicites :
$ cat /proc/asound/card0/eld#2.3
monitor_present 1
eld_valid 1
monitor_name LT-1080
connection_type HDMI
eld_version [0x2] CEA-861D or below
edid_version [0x3] CEA-861-B, C or D
manufacture_id 0x8d32
product_id 0x2c02
port_id 0x0
support_hdcp 0
support_ai 0
audio_sync_delay 0
speakers [0x1] FL/FR
sad_count 3
sad0_coding_type [0x1] LPCM
sad0_channels 2
sad0_rates [0x1ee0] 32000 44100 48000 88200 96000 176400 192000
sad0_bits [0xe0000] 16 20 24
sad1_coding_type [0x2] AC-3
sad1_channels 8
sad1_rates [0xe0] 32000 44100 48000
sad1_max_bitrate 448000
sad2_coding_type [0x7] DTS
sad2_channels 8
sad2_rates [0xe0] 32000 44100 48000
sad2_max_bitrate 1536000
Ou y voit :
- le support du LPCM mais seulement jusqu'à 2 voies
- le support du CODEC AC-3 ou DTS jusqu'à 8 voies. Ce qui est faux car il n'a que 6 voies mais probablement qu'il faut mentir pour être compatible avec certains équipements.
Ce qu'il faut comprendre, c'est qu'on ne pourra pas envoyer à ce récepteur AV plus que du stéréo en LPCM. Le LPCM, c'est pourtant ce que fait pulseaudio
par défaut. Par conséquent, selon le profil de sortie sélectionné dans pulseaudio
:
- avec
output:hdmi-stereo
, les 6 voies fournies par le lecteur vidéo seront remixées vers 2 voies (stéréo) pour s'adapter à la sortie (stereo downmix). Recevant un signal stéréo et étant en mode 5.1, le récepteur AV va dupliquer ces 2 voies sur toutes les enceintes (selon des règles de filtrage et d'atténuation qui lui sont propres). La conséquence est que les dialogues qui sont usuellement exclusivement sur la voie centrale seront aussi audibles via les autres enceintes. output:hdmi-surround
enverra les 6 voies décodées en LPCM. Comme le récepteur AV n'en supporte que 2, on entendra que les 2 premières, avant-gauche et avant-droit. Symptôme le plus évident : comme la voie centrale est ignorée, aucun dialogue ne sera audible.
Le profil se change dans pavucontrol
ou en ligne de commande, par exemple :
$ pacmd set-card-profile 0 output:hdmi-surround
Il va donc falloir envoyer du DTS ou de l'AC3 dans une sortie stéréo pour que ça marche. C'est la solution bien connue de ceux qui sont contraints de passer par un câble TOSLINK.
Les solutions logicielles pour sortir en AC3
Les composants logiciels
Vraiment rapidement, les composants logiciels suivants sont impliqués :
- le lecteur de média qui va interpréter un fichier ou un disque
pulseaudio
qui permet entre autre de gérer l'accès par de multiples applications, et de mixer le tout vers la bonne sortie sonore (en fonction de ce qui est branché), après d'éventuels traitements.- ALSA qui gère l'accès au matériel sonore de l'ordinateur.
passthrough
L'une des solutions les plus mises en avant est celle de la transmission brute (passthrough). Elle vise à limiter les encodages avec pertes et décodages du son en visant de ne laisser entre le média source et les enceintes qu'une seule étape de décodage faite par le récepteur AV. Ceci ne vaut bien sûr que si le média source est déjà dans un CODEC supporté.
Pour le mettre en œuvre, si on utilise pulseaudio
et qu'on veut autoriser le signal AC3 ou DTS à passer à travers, et bien paramétrer le profil de sortie en stéréo (oui ce n'est pas logique, mais il faut se rappeler que les 6 voies sont encodées dans un signal stéréo), par exemple sur la carte 0
:
$ pacmd set-card-profile 0 output:hdmi-stereo
$ pactl set-sink-formats 0 "pcm; ac3-iec61937; dts-iec61937"
(ou cocher les cases correspondantes dans pavucontrol
)
Et dans tous les cas il faudra indiquer à son logiciel de lecture qu'il faut envoyer le signal brute à la sortie sonore, par exemple pour mpv
:
audio-spdif=ac3,dts # enable passthrough
audio-channels=5.1,stereo
af=lavcac3enc # encode audio output into AC3
Il est intéressant de se plonger dans la documentation du filtre de sortie audio lavcac3enc
pour constater qu'il a été bien pensé : il ne fait rien s'il ne reçoit que du stéréo ou s'il reçoit déjà du AC3, ce qui évite de dégrader en théorie la qualité par un encodage/décodage de plus. Par contre, si la source est autre chose, on évite pas le décodage puis l'encodage à nouveau.
Les limites de cette solution sont les suivantes :
- Aucun traitement du son n'est possible : on ne peut même pas changer le volume au niveau logiciel.
- Constat avec certains médias d'un décalage entre le son et l'image, croissant avec la durée de lecture.
Toutes les voies décodées
Si on laisse le décodage au logiciel, le HDMI permet de sortir les 6 voies décodées (LPCM à 6 voies). Le profil pulseaudio
à mettre en œuvre est le suivant:
$ pacmd set-card-profile 0 output:hdmi-surround
Si le récepteur AV le supporte, pas de problème, c'est une bonne solution, peut être la solution qui a ma préférence.
La limite de cette solution est que beaucoup de récepteurs AV ne supportent le LPCM qu'en stéréo. On peut donc se retrouver avec un son qui ne sera pas à 6 voies comme attendu :
- comme vu précédemment, absence de son dans les dialogues : seules les voies avant stéréo sont restituées, les autres ignorées.
- un son 6 voies simulé par le récepteur AV à partir d'un signal stéréo au moyen de règles qui lui sont propres. Cela se détecte simplement en se plaçant entre une voie avant et la voie centrale : si les dialogues viennent à la fois de la voie centrale est des voies avant, on a une mauvaise configuration.
Encodage à la volée par ALSA (via pulseaudio)
Comme d'être encodée en AC3 est une contrainte de notre sortie sonore, autant le gérer de manière globale pour toutes les applications. Ainsi, pour un jeu ou n'importe quel lecteur de média, le son sera encodé à la volée.
Pour le mettre en œuvre, si on utilise pulseaudio
, le profil
correspond n'existe pas. J'ai ajouté manuellement ce qui allait bien dans
/usr/share/pulseaudio/alsa-mixer/profile-sets/default.conf
:
[Mapping hdmi-ac3-surround-extra1]
description = Digital Surround 5.1 (HDMI 2/AC3)
device-strings = plug:{SLAVE="a52:%f,'hw:%f,7'"}
paths-output = hdmi-output-1
channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe
priority = 6
direction = output
Le profil se change dans pavucontrol
ou en ligne de commande, par exemple :
$ pacmd set-card-profile 0 output:hdmi-ac3-surround-extra1
Les limites de cette solution sont les suivantes :
- Nécessite de modifier un fichier de
pulseaudio
qui n'est pas fait pour être configuré. - Constat avec certains médias d'un décalage constant entre le son et l'image.
pulseaudio
continue de consommer du CPU (3-4% chez moi) même s'il n'y a plus de lecteur de média en cours.- Si le fichier source est déjà en AC3, il est décodé puis encodé à nouveau, donc avec de probables pertes que je n'ai pas pu mettre en évidence avec mon oreille non entrainée.
Il existe aussi un plugin dcaenc
pour ALSA pour encoder à la volée en DTS mais j'ai constaté qu'il prenait 15-20% d'un cœur CPU en lecture contre seulement 3-4% pour l'encodage en AC3 par a52
. De plus il ne semble plus maintenu et n'est pas disponible dans ma distribution de prédilection même si j'ai pu assez rapidement créer un paquet.
Encodage à la volée par ALSA (sans pulseaudio)
Comme la sortie sonore que j'utilise est dédiée à cet usage, et pour m'affranchir des petits bémols liés à pulseaudio
, j'ai retiré ce dernier de l'équation.
On crée d'abord une sortie ALSA à utiliser (ac3hdmi
) qui adapte le format et transmet à l'encodeur AC3 (a52hdmi
) :
$ cat /etc/asound.conf
pcm.a52hdmi {
type a52
slavepcm "hdmi:CARD=PCH,DEV=1" # CARD and DEV to adapt from aplay -L
bitrate 640
}
pcm.ac3hdmi {
type plug
slave.pcm "a52hdmi"
}
Ensuite, on utilise cette nouvelle sortie dans notre lecteur, par exemple avec mpv
:
audio-channels=5.1,stereo
video-sync=display-resample # may improve A/V sync
ao=alsa
audio-device="alsa/ac3hdmi"
Il est probable qu'on puisse s'affranchir de la déclaration dans /etc/asound.conf
avec pour mpv
:
audio-device="alsa/plug:{SLAVE=\"a52:0,'hw:0,7'\"}" # to adapt from aplay -L
La limite de cette solution sont les suivantes :
- Le lecteur vidéo aura l'usage exclusif de la sortie sonore, ce qui ne pose pas de problème dans mon cas.
- Si le fichier source est déjà en AC3, il est décodé puis encodé à nouveau, donc avec de probables pertes que je n'ai pas pu mettre en évidence avec mon oreille non entrainée.
Quelles leçons?
On peut en tirer les leçons suivantes :
- Même si cela ne figure pas dans les fiches techniques, s'assurer que le récepteur AV de notre choix supporte le LPCM 6 voies au minimum sur ses entrées HDMI. Et cela ne semble par le cas de tous les 5.1ch audio decoder qui peuplent Amazon et Aliexpress. C'est dommage, car des appareils assez communs comme la Nintendo Switch ou la freebox mini 4K n'encode pas le sortie audio sur HDMI en AC3 ou DTS, probablement pour une question de paiement de licence à Dolby.
- Il est facile de planter sa configuration et de ne pas profiter des 6 voies indépendantes sans qu'il soit évident de s'en apercevoir.
- Les solutions de contournement de certaines limites technologiques d'une époque durent dans le temps.
- Les fonctions peu utilisées sont souvent plus bancales qu'on ne pourrait l'attendre :
- Add alsa profiles for HDMI/AC3 (#1327) · Issues · PulseAudio / pulseaudio
- Add alsa plugin profiles for HDMI/AC3 (#3832) · Issues · PipeWire / pipewire
- #998125 - libasound2-plugins: Config file for a52 plugin (60-a52-encoder.conf) produces no/garbled sound via optical digital out (S/PDIF) - Debian Bug report logs
- Kodi qui est au cœur de ce cas d'utilisation a probablement la page qui aide le mieux à comprendre ces sujets : PulseAudio - Official Kodi Wiki . Le reste est perdu dans des forums, des listes de diffusion ou des rapports de bugs.
- Sans avoir cherché longtemps, il semblerait que les solutions soient plus limitées avec
pipewire
(qui remplacerapulseaudio
?) : le passthrough n'est pas (encore?) supporté.
Et voici un petit schéma pour résumer tout cela : Architecture physique son numérique multicanal Linux.