Слегка упоротая редакция

From system administration to disease reversal

Настройка звука 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"

Полезные ссылки, которые пригодились


blog comments powered by Disqus