Ever since I started using my current laptop (a ThinkPad E14 Gen 4,
currently running Debian 12), I have had the following issue: when I
connect headphones to the laptop, the audio goes to the headphones as
expected, but when I disconnect the headphones, the audio goes to the
HDMI output instead of going back to the laptop speakers. As it happens,
my external monitor (an Eizo FlexScan EV2360) has audio output, but it’s
pretty low-quality and I don’t use it. But PulseAudio (or is it ALSA?)
assigns higher priority to the HDMI outputs, so as soon as the
headphones are disconnected, it looks for the available device with the
highest priority and picks the HDMI one. You can see the priority of
each audio sink (output) by using pactl
:
$ pactl list sinks | grep priority: [Out] HDMI3: HDMI / DisplayPort 3 Output (type: HDMI, priority: 700, not available) [Out] HDMI2: HDMI / DisplayPort 2 Output (type: HDMI, priority: 600, not available) [Out] HDMI1: HDMI / DisplayPort 1 Output (type: HDMI, priority: 500, available) [Out] Speaker: Speaker (type: Speaker, priority: 100, availability unknown) [Out] Headphones: Headphones (type: Headphones, priority: 200, not available)
In this case, the HDMI1 output is available and has priority 500, whereas the speakers have priority 100.
The solution is to change the HDMI priorities. The problem is
where to set this. In my particular case, this was set in
/usr/share/alsa/ucm2/Intel/sof-hda-dsp/Hdmi.conf
(included
from /usr/share/alsa/ucm2/Intel/sof-hda-dsp/Hdmi.conf
),
which looks like this:
# Use case Configuration for sof-hda-dsp Include.hdmi.File "/codecs/hda/hdmi.conf" If.hdmi1 { Condition { Type AlwaysTrue } True.Macro.hdmi1.HDMI { Number 1 Device 3 Priority 500 } } If.hdmi2 { Condition { Type AlwaysTrue } True.Macro.hdmi1.HDMI { Number 2 Device 4 Priority 600 } } If.hdmi3 { Condition { Type AlwaysTrue } True.Macro.hdmi1.HDMI { Number 3 Device 5 Priority 700 } }
I just changed the values 500, 600, 700 manually to 50, 60, 70 in
this file. This is not a very good solution because this file belongs to
the alsa-ucm-conf
package and will get overridden whenever
I upgrade it, but since this is Debian stable, I don’t have to worry
about this any time soon. There is probably a better way to override
these values, but I don’t know enough about either ALSA or PulseAudio
(and I’m not particularly keen on learning more, unless my fellow
readers know and want to leave a helpful comment), so this will have to
do for now.
* * *
Another recurring issue is getting Bluetooth headphones to become the
selected default device when they are connected. It seems that Bluetooth
devices get created dynamically with a
bunch of hardcoded priorities (and worse, sometimes I get a device
with priority 40
and sometimes 0
, I don’t know
why). But it also seems that the priorities just don’t have any effect
on the selection of the Bluetooth device. I was having a curious issue
where some programs would pick the headphones and some wouldn’t, and the
default device would remain unchanged (which among other things meant that
my multimedia keys set the volume of the wrong device). What seems to be going on is that
PulseAudio remembered the associations of certain programs (e.g., VLC)
with the headphones, but only for those programs where I had at some
point manually changed the output sink manually via
pavucontrol
. The solution here was two-step:
In /etc/pulse/default.pa
, replace the line that
says:
load-module module-stream-restore
with:
load-module module-stream-restore restore_device=false
This will make PulseAudio not try to remember associations between specific programs and devices. From now on, all programs get the default sources/sinks when they connect to PulseAudio.
Set the default sink manually to the Bluetooth headphones. Use
pactl list sinks
to figure out the sink name:
$ pactl list sinks | grep Name: Name: alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp_5__sink Name: alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp_4__sink Name: alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp_3__sink Name: alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp__sink Name: bluez_sink.C8_7B_23_9F_B3_21.a2dp_sink
Then set it (replacing with the appropriate device name):
pactl set-default-sink bluez_sink.C8_7B_23_9F_B3_21.a2dp_sink
The result of this is that PulseAudio will remember the headphones as the default sink device when they are present, but will revert to the built-in sound card when not.
I still don’t know why this works even though the Bluetooth device’s
priority is lower than the built-in sound card. (There is a PulseAudio
module called module-switch-on-connect
that provides
behavior like this, but it is not enabled on my system, and it does not
show up as loaded in the pactl list
output.) But It Works
For Me™.
O SoX (SOund eXchange; pacotes sox e libsox-fmt-all no Debian) é uma biblioteca e um programa de linha de comando que permitem converter entre diversos formatos de arquivo de áudio, opcionalmente aplicando filtros. A sintaxe básica do comando sox é:
sox [opções-globais] [opções-de-formato] entrada1 [[opções-de-formato] entrada2 ...] [opções-de-formato] saída [filtros ...]
Por exemplo, para gravar do microfone (usando ALSA) em um arquivo WAV:
sox -t alsa default -t wav blabla.wav
(Use Control-C para terminar a gravação. Tecnicamente o -t wav pode ser omitido, já que o sox é capaz de deduzir o formato do arquivo pela extensão.)
Um par de filtros particularmente interessante é o noiseprof/noisered, que permitem eliminar ou reduzir ruído constante de fundo. Isso é feito em duas etapas. Primeiro, executa-se o sox com o filtro noiseprof [profile.txt] sobre uma "amostra de silêncio", i.e., um trecho de áudio que consista apenas do ruído de fundo, de maneira a produzir um profile de ruído. Você pode capturar o "silêncio" do microfone ou de algum outro arquivo que consista apenas de silêncio (a opção --null pode ser usada no lugar do arquivo de saída, já que estamos interessados apenas no profile de ruído):
sox -t alsa default --null noiseprof profile.txt sox algum-arquivo-que-consista-apenas-de-silêncio.wav --null noiseprof profile.txt
Alternativamente, você pode selecionar um trecho de um arquivo com o filtro trim início [duração] e usá-lo como fonte de silêncio:
# Seleciona o intervalo de de 1s até 2.5s. Aqui usamos '-t alsa default' como # saída para podermos ouvir se o trecho selecionado de fato corresponde a "silêncio". sox entrada.wav -t alsa default trim 1 1.5 noiseprof profile.txt
Se o nome do arquivo de profile for omitido, o sox escreve o profile na stdout.
Gerado o profile de ruído, podemos usar o filtro noisered [profile.txt [quantidade]] para remover o ruído do arquivo completo. quantidade é um número entre 0 e 1 indicando a quantidade de ruído que deve ser removida. Quanto maior o número, mais ruído será removido – e mais não-ruído também. Experimente com números pequenos (e.g., 0, 0.05, 0.1, etc.) primeiro.
sox entrada.wav saída.wav noisered profile.txt 0.05
Se você tem um microfone problemático, você pode querer guardar o arquivo de profile para usos futuros (assumindo que o padrão de ruído produzido seja sempre o mesmo).
Se o arquivo de entrada para o noisered não for especificado ou for -, o sox lê o profile da stdin. Assim, você pode combinar o profiling e a redução em um pipeline:
sox entrada.wav --null trim 0 1 noiseprof | sox entrada.wav saída.wav noisered - 0.05
Para mais informações, consulte a manpage do sox.
Copyright © 2010-2024 Vítor De Araújo
O conteúdo deste blog, a menos que de outra forma especificado, pode ser utilizado segundo os termos da licença Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International.
Powered by Blognir.