Настройка звука 5.1 на SB Live! (emu10k1) со срезом верхов на сабвуфере
Что вообще делаем
Допустим, у нас есть "тупой" усилитель и акустическая система 5.1. И надо красиво вывести звук из linux чтобы ничего не пердело и не хрипело.
Через функциональность alsa переопределяем путь звука, последовательно прогоняя его через различные "плагины". Наруливаем разводку stereo на 6 каналов, а канал саба с помощью LADSPA прогоняем через фильтр, который отрезает высокие частоты, а на сателлитах отрезаем низкие частоты.
Кстати, в интернете можно встретить примеры среза частот с использованием протухшего BLOP. Мы заюзаем более актуальный инструмент.
Предыстория, или ремонт трансформатора
Всё началось с месяц назад, когда у меня в акустической системе Microlab AH-500 сдох силовой трансформатор. Это тороидальный понижающий трансформатор с двумя вторичными обмотками. Понижение 10-и кратное, т.е. 220 -> 22. Проверка мультиметром показала, что в первичной обмотке обрыв цепи. Смотал вторичную обмотку, и когда показалась первичная, оказалось, что там стоит термопредохранитель на 130 градусов, и вот он-то и сдох. Перемотал обратно вторичную обмотку, геморой тот ещё. Рекомендую посмотреть ну например это видео. Для ускорения процесса обмоточный провод собирается в шпульку, чтобы не протаскивать всю длину провода на каждом витке. Отдельно надо сказать, что натягивать провод надо СИЛЬНО, чтобы изнутри тора витки ложились прямо чётко один к другому. Иначе пойдёт нахлёст, и отверстие в торе станет так мало, что туда не влезет крепёжный болт. FAIL. У меня так и произошло, поэтому вторичку пришлось мотать два раза.
При обратной "сборке" трансформатора термопредохранитель взял номиналом поменьше, а именно, на 100 градусов, и поставил его снаружи вторичной обмотки. В общем, всё успешно собрал обратно, акустика завелась как и было.
В процессе ковыряний с трансформатором наткнулся на то, что некоторые люди подключают звуковуху напрямую на оконечный усилитель (в AH500 он конструктивно выполнен в сабвуфере) без преампа. Таким образом избавляемся от ряда помех и шумов, вносимым данным оборудованием в звуковой тракт.
В таком варианте получается, что усилитель всё время раскрыт полностью, и нам нужно контролировать мастер-громкость на стороне компьютера, плюс неплохо бы срезать высокие частоты из канала сабвуфера, и опционально срезать низы на сателлитах.
Пакеты
- alsa-plugins: тут нас интересует плагин upmix. Он позволяет раскидать стерео звук на 6 каналов. Документация /usr/share/doc/alsa-plugins-*/upmix.txt.bz2
- ladspa-cmt: собственно LADSPA, интерфейс для подключения фильтра
- swh-plugins: тут у нас непосредственно ladspa-плагины, в том числе тот, которым будем срезать верха.
.asoundrc
Настройка осуществляется через .asoundrc, или /etc/asound.conf, если хочется системно. Читать его следует снизу вверх. Далее следуют секции с комментариями к ним.
После прохождения через фильтры звук надо преобразовать из float в integer, без этого вроде как не работает (не проверял). Отсюда звук уходит на определённый в alsa девайс surround51 - 5.1-канальный вывод. Дефиниции можно глянуть в /usr/share/alsa/pcm/surround51.conf (там кстати есть раскладка по каналам) ну и для интереса - карты. У меня это /usr/share/alsa/cards/EMU10K1.conf. Тут на всякий случай можно сказать, что если отправлять звук не на surround51, а на какой-нибудь дефолтный, то получите совсем не то, что ожидалось, т.к. туда уйдут только первые два канала, т.е. фронты левый и правый, и уже там дальше с них "размиксуются" тылы, центр и саб. И таким образом срезка работать не будет.
# Convert float data from "lowpass51" to integer data
# and pass it on to the next device.
pcm.lowpass_float {
type lfloat
slave {
pcm "surround51"
format "S16_LE"
}
}
Основная магия. 0-й плагин делает пропуск без изменений тех каналов, которые не будут далее затронуты другими плагинами, 1-6 - отрезают низы на сателлиты, а 6-й отрезает верха на канале сабвуфера. id - непосредственно идентификатор нужного фильтра. В секции controls - частота среза. В данном конфиге 0-й плагин на самом деле не нужен, т.к. через фильтры проходят все каналы. Но для примера решил оставить, вдруг кому-то не потребуется делать срез частот на каких-то каналах.
# Lowpass filter.
# Requires "ladspa" for plugin support,
# "cmt" for identity_audio plugin and
# "swh-plugins" for lpf plugin.
# See http://www.ladspa.org/.
pcm.lowpass51 {
type ladspa
slave.pcm "lowpass_float"
path "/usr/lib64/ladspa"
plugins {
# Copies all audio of all channels to other plugins.
# If no other plugin handles a channel, it comes out unchanged.
0 {
id 1098 # Identity (Audio) (1098/identity_audio)
policy duplicate
input.bindings.0 "Input";
output.bindings.0 "Output";
}
1 {
id 1052 # High Pass Filter
policy none
input.bindings.0 "Input";
output.bindings.0 "Output";
input {
controls [ 100 ]
}
}
2 {
id 1052 # High Pass Filter
policy none
input.bindings.1 "Input";
output.bindings.1 "Output";
input {
controls [ 100 ]
}
}
3 {
id 1052 # High Pass Filter
policy none
input.bindings.2 "Input";
output.bindings.2 "Output";
input {
controls [ 100 ]
}
}
4 {
id 1052 # High Pass Filter
policy none
input.bindings.3 "Input";
output.bindings.3 "Output";
input {
controls [ 100 ]
}
}
5 {
id 1052 # High Pass Filter
policy none
input.bindings.4 "Input";
output.bindings.4 "Output";
input {
controls [ 100 ]
}
}
# Actual low-pass filter functionality.
# Operate on channel 5 (LFE) and remove
# frequencies higher than X Hz.
6 {
id 1051 # Low Pass Filter (One Pole) (1051/lpf)
policy none
input.bindings.5 "Input";
output.bindings.5 "Output";
input {
controls [ 300 ]
}
}
}
}
Тут у нас происходит раскидка стерео на 5.1. Upmix копирует фронтальные каналы в соответствующие тыловые с небольшим добавлением задержки (delay), по дефолту 15 ms. Центр и саб - среднее от суммы левого и правого канала.
# Automatic upmixing. Requires package "alsa-plugins".
pcm.upmix51 {
type upmix
# Simply "lowpass51" won't work.
# "plug:..." specifies a plug device like
# the long form for the default device below
# and takes care of channel/format conversions
# automatically.
slave.pcm "plug:lowpass51"
# Specifying the number of channels to upmix to here is mandatory.
channels 6
}
Т.к. аппаратной крутилки мастер-уровня теперь нет, появилась потребность удобно рулить громкостью всех каналов одновременно, чтобы не крутить всё в alsamixer-е по-отдельности. Без указания min_dB max_dB регулятор не работал (всегда был на максимуме). Так же тут следует упомянуть, что в миксере он появится только после первой попытки использования, т.е. надо проиграть что-нибудь. Простого редактирования .asoundrc недостаточно. Так же можно убедиться в его появлении в amixer controls.
# Custom master volume control
pcm.softvol {
type softvol
slave.pcm "upmix51"
min_dB -51.0
max_dB 0.0
control {
name "SoftMaster"
card 0
}
}
Собственно первый в цепочке дефольный девайс, куда попадает звук от всех приложений, если в них не выбрано что-то не-дефолтное. Тут мы берём весь звук и отправляем на цепочку обработки в "softvol" и далее.
# Default device to be used by all applications playing all sorts of sources.
# There's automatic upmixing for 2.0 sources and native playback of 5.1 sources.
# (possibly others as supported by the upmix plugin)
pcm.!default {
type plug
slave.pcm "softvol"
}
Софтварный миксер
Для интереса я пробовал так же подключать в цепочку софтварный миксер dmix, но такая конфигурация нормально не заработала. Конфиг примерно такой:
# The first ALSA device of the first soundcard
# (here: Analog Multichannel Ouput).
# See /proc/asound and "aplay -l".
pcm.sndcard {
type hw
card 0
device 0
}
# Dmix software mixing device.
# Takes multiple input streams, resamples them to target
# rate (here: 48kHz) and sends it to the sound card.
pcm.dmix51 {
type dmix
ipc_key 1024
slave {
#pcm "sndcard"
pcm "surround51"
channels 6
rate 48000
period_time 0 # Fixes audio crackling/stutter
period_size 1024 # with libsamplerate and chromium.
buffer_time 0 # Not all options may be
buffer_size 4096 # absolutely necessary.
}
}
# Convert float data from "lowpass51" to integer data
# and pass it on to the next device.
pcm.lowpass_float {
type lfloat
slave {
pcm "dmix51"
format "S16_LE"
}
}
Если из этого dmix51 отправлять звук на "surround51", получаем ошибку "Invalid type 'multi' for slave PCM". Если же отправлять на "sndcard", то от 6-и каналов остаётся 2, и все усилия по срезанию частот оказываются зря.
Настройки миксера
На всякий случай пояснение по настройкам регуляторов в alsamixer для моей карты на чипе SigmaTel STAC9708,11:
- Master, PCM - ругулируют громкость фронтов.
- Center, LFE - регулируют громкость центра и саба при выводе звука на "surround51". При выводе просто на default device (типа hw:0,0) на звук не влияют.
- Wave - громкость фронтов в режиме "default device", работает в совокупности с Master и PCM.
- Wave Surround - тылы в режиме "default device".
- Wave Center, Wave LFE - центр и саб в режиме "default device".
Биндинг на хоткеи i3
Чтобы удобно рулить громкостью глобально, биндим их на хоткеи. Для i3 это выглядит так:
# global volume controls
bindsym $mod+Shift+Up exec amixer -q set SoftMaster 2dB+ unmute
bindsym $mod+Shift+Down exec amixer -q set SoftMaster 2dB- unmute
Проблема с transcribe
Для снятия музыкальных партий я использую программу Transcribe, и оказалось, что при выводе звука на surround51 при воспроизведении появились неприятные потрескивания. Откуда оно взялось, выяснить не удалось, поэтому пришлось настроить в ней вывод звука минуя всю цепочку surround51. Для этого в настройках Playback указываем "Gstreamer device name" - "alsasink device=hw:0,0"
Полезные ссылки, которые пригодились
- ALSA automatic upmixing with lowpass filtering and dmix support
- How do I make ALSA upmix 2.0 to 2.1?
- asound.conf: Filter for Subwoofer Channel? [nearly solved]
- How to use softvol to control the master volume