LINUX.ORG.RU

Статьи - Архив 2024, Декабрь

EasyEffects не нужно, или PipeWire для продвинутых: часть 3

Статьи — Desktop

Во второй части мы разобрали вопрос, как управлять параметрами эффектов в реальном времени, без перезапуска PipeWire.

Теперь рассмотрим, как можно добавить сторонний плагин, реализующий эффект, который не встроен в PipeWire, и как управлять его параметрами.

Модуль filter-chain, помимо встроенных (builtin) эффектов, поддерживает два самых распространенных в Linux стандарта DSP плагинов - LADSPA и LV2. Прежде всего, эти плагины предназначены для использования в DAW системе (цифровая звуковая рабочая станция, в которой «делают музыку»), такой как Ardour, Qtractor, LMMS. Они реализуют множество эффектов, таких как эквалайзер, компрессор, лимитер и тому подобное.

LADSPA это более простой и более старый стандарт, LV2 более развитый, но большинство популярных в Linux наборов LV2 плагинов поставляются и в LADSPA варианте. PipeWire может использовать плагины обоих стандартов, поэтому используем сразу LV2 вариант.

Реализуем очень нужный многим эффект – нормализацию громкости, или компрессию. То есть, нам нужно, чтобы тихие звуки стали громче, и были слышны в зашумлённой обстановке (на работе, к примеру) из плохих динамиков ноутбука. Также эта проблема очень актуальна при просмотре фильмов, часто есть огромная разница в громкости между диалогами и активными сценами (когда начинают бить морды). Надо эту разницу уменьшить.

Для этого мы используем замечательный набор плагинов LSP. Эти плагины доступны во всех основных форматах, мы же используем LV2 версию. В составе набора есть плагин Compressor Mono, который хорошо подходит для нашей задачи – там предусмотрен «обратный» режим работы, когда тихие звуки делаются более громкими (а не только громкие – более тихими, как в большинстве аналогичных плагинов). Это именно то, что нужно.

Добавим этот плагин в цепочку фильтров filter-chain. Для этого, сначала надо узнать такую вещь, как URI плагина. Это такая форма его названия, в виде веб-адреса. Но это не настоящая веб-ссылка, просто такая форма ))). В общем, это тяжело объяснить.

Чтобы узнать URI плагина, выполним команду lv2ls. Команда выдаст URI всех плагинов, которые установлены в системе. Среди них должен быть нужный нам плагин http://lsp-plug.in/plugins/lv2/compressor_mono. Если такого нет, надо установить набор плагинов LSP, при помощи пакетного менеджера дистрибутива.

Теперь добавим в конфиг-файл из предыдущих частей вот такой кусок, в массив nodes (полная версия конфига будет в конце статьи):

{
  type = lv2
  name = compressor
  label = compressor
  plugin = "http://lsp-plug.in/plugins/lv2/compressor_mono"
  control = { "cm" = 1 "cr" = 4.0}
}

Как видно, это очень похоже на добавление builtin эффекта. Только теперь тип будет lv2, plugin - указываем URI плагина. name, label – название, которое мы сами даём этому эффекту, может быть любое. По нему потом всё будет доступно через pw-cli для изменения параметров. Добавляем два параметра - "cm" = 1 это режим работы, который делает тихие звуки громче (а не громкие – тише). "cr" = 4.0 – это степень компрессии, во сколько раз. Чем больше это значение, тем больше будет выравниваться громкость.

Здесь важно, что параметров у этого плагина намного больше, а нам нужно указать только те, которые мы изменяем – остальные будут иметь значение по умолчанию.

Очень тяжелый вопрос: откуда же брать названия параметров плагина, допустимые значения этих параметров, чтобы прописать сюда? Как узнать, что есть вот именно два этих параметра, и они называются вот так?

Для этого используем утилиту lv2info. Выполним команду

lv2info http://lsp-plug.in/plugins/lv2/compressor_mono

В выводе команды видим всю информацию о плагине, нас интересуют блоки вида Port N:. Порты у плагина, упрощенно, есть двух видов - это входы/выходы, через которые передается звук, и параметры самого плагина, которые можно задавать и изменять. Находим среди портов те, которые соответствуют нужным нам параметрам. Ищем, ориентируясь на поле Name, оно говорящее, сразу понятно что это.

Port 17:
Type:
  http://lv2plug.in/ns/lv2core#ControlPort
  http://lv2plug.in/ns/lv2core#InputPort
  Scale Points:
    0 = "Down"
    1 = "Up"
    2 = "Boot"

  Symbol:      cm
  Name:        Compression mode
  Minimum:     0.000000
  Maximum:     2.000000
  Default:     0.000000
  Properties:  http://lv2plug.in/ns/ext/port-props#hasStrictBounds
  http://lv2plug.in/ns/lv2core#integer                           
  http://lv2plug.in/ns/lv2core#enumeration

Это описание параметра cm, который мы меняем в конфиг-файле. Из этого куска мы узнаем, что есть параметр Name: Compression mode, он имеет имя Symbol: cm, может принимать значения 0, 1 или 2.

  Scale Points:
    0 = "Down"
    1 = "Up"
    2 = "Boot"

Нам нужен режим Up (делать громче тихий звук), значит мы должны установить этот параметр в значение 1.

Далее, надо «залинковать» этот дополнительный эффект к уже добавленному ранее эквалайзеру. Для этого добавляем в конфиг-файле, в массив links:

{ output = "eq_band_15:Out" input = "compressor:in" }

то есть подключить вход компрессора к выходу 15 полосы эквалайзера. И последний штрих: надо сделать выходом всей цепочки эффектов – выход компрессора.

outputs = [ "compressor:out" ]

Теперь, помимо эквалайзера, у нас в цепочке обработки будет компрессор. Какими параметрами может потребоваться управлять? Можно включать/отключать компрессор

pw-cli s 36 Props '{params = ["compressor:enabled" 0]}'
pw-cli s 36 Props '{params = ["compressor:enabled" 1]}'

Не забываем, что 36 – это номер ноды Equalizer Sink, у вас он может быть совсем другим. Как его определить - см. Часть 2.

Ещё можно подрегулировать степень компрессии, параметр cr.

 pw-cli s 36 Props '{params = ["compressor:cr" 10.0]}'

Вот и всё, два основных эффекта мы реализовали )). Полная версия получившегося конфиг-файла будет выглядеть так:

context.modules = [
    { name = libpipewire-module-filter-chain
        args = {
            node.description = "Equalizer Sink"
            media.name       = "Equalizer Sink"
            filter.graph = {
                nodes = [
                    {
                        type  = builtin
                        name  = eq_preamp
                        label = bq_highshelf
                        control = { "Freq" = 0 "Q" = 1.0 "Gain" = 5.0 }
                    }
                    {
                        type  = builtin
                        name  = eq_band_1
                        label = bq_peaking
                        control = { "Freq" = 25.0 "Q" = 1.7 "Gain" = -10.0 }
                    }
                    {
                        type  = builtin
                        name  = eq_band_2
                        label = bq_peaking
                        control = { "Freq" = 40.0 "Q" = 1.7 "Gain" = -10.0 }
                    }
                    {
                        type  = builtin
                        name  = eq_band_3
                        label = bq_peaking
                        control = { "Freq" = 63.0 "Q" = 1.7 "Gain" = -9.0}
                    }
                    {
                        type  = builtin
                        name  = eq_band_4
                        label = bq_peaking
                        control = { "Freq" = 100.0 "Q" = 1.7 "Gain" = 3.0 }
                    }
                    {
                        type  = builtin
                        name  = eq_band_5
                        label = bq_peaking
                        control = { "Freq" = 160.0 "Q" = 1.7 "Gain" = 3.0 }
                    }
                    {
                        type  = builtin
                        name  = eq_band_6
                        label = bq_peaking
                        control = { "Freq" = 250.0 "Q" = 1.7 "Gain" = 3.0 }
                    }
                    {
                        type  = builtin
                        name  = eq_band_7
                        label = bq_peaking
                        control = { "Freq" = 400.0 "Q" = 1.7 "Gain" = -5.0 }
                    }
                    {
                        type  = builtin
                        name  = eq_band_8
                        label = bq_peaking
                        control = { "Freq" = 630.0 "Q" = 1.7 "Gain" = -5.0 }
                    }
                    {
                        type  = builtin
                        name  = eq_band_9
                        label = bq_peaking
                        control = { "Freq" = 1000.0 "Q" = 1.7 "Gain" = -3.0 }
                    }
                    {
                        type  = builtin
                        name  = eq_band_10
                        label = bq_peaking
                        control = { "Freq" = 1600.0 "Q" = 1.7 "Gain" = -3.0 }
                    }
                    {
                        type  = builtin
                        name  = eq_band_11
                        label = bq_peaking
                        control = { "Freq" = 2500.0 "Q" = 1.7 "Gain" = -3.0 }
                    }
                    {
                        type  = builtin
                        name  = eq_band_12
                        label = bq_peaking
                        control = { "Freq" = 4000.0 "Q" = 1.7 "Gain" = -5.0 }
                    }
                    {
                        type  = builtin
                        name  = eq_band_13
                        label = bq_peaking
                        control = { "Freq" = 6300.0 "Q" = 1.7 "Gain" = -3.0 }
                    }
                    {
                        type  = builtin
                        name  = eq_band_14
                        label = bq_peaking
                        control = { "Freq" = 10000.0 "Q" = 1.7 "Gain" = 0.0 }
                    }
                    {
                        type  = builtin
                        name  = eq_band_15
                        label = bq_peaking
                        control = { "Freq" = 16000.0 "Q" = 1.7 "Gain" = 0.0 }
                    }
                    {
                        type = lv2
                        name = compressor
                        label = compressor
                        plugin = "http://lsp-plug.in/plugins/lv2/compressor_mono"
                        control = { "cm" = 1 "cr" = 4.0}
                    }
                ]
                links = [
                    { output = "eq_preamp:Out" input = "eq_band_1:In" }
                    { output = "eq_band_1:Out" input = "eq_band_2:In" }
                    { output = "eq_band_2:Out" input = "eq_band_3:In" }
                    { output = "eq_band_3:Out" input = "eq_band_4:In" }
                    { output = "eq_band_4:Out" input = "eq_band_5:In" }
                    { output = "eq_band_5:Out" input = "eq_band_6:In" }
                    { output = "eq_band_6:Out" input = "eq_band_7:In" }
                    { output = "eq_band_7:Out" input = "eq_band_8:In" }
                    { output = "eq_band_8:Out" input = "eq_band_9:In" }
                    { output = "eq_band_9:Out" input = "eq_band_10:In" }
                    { output = "eq_band_10:Out" input = "eq_band_11:In" }
                    { output = "eq_band_11:Out" input = "eq_band_12:In" }
                    { output = "eq_band_12:Out" input = "eq_band_13:In" }
                    { output = "eq_band_13:Out" input = "eq_band_14:In" }
                    { output = "eq_band_14:Out" input = "eq_band_15:In" }
                    { output = "eq_band_15:Out" input = "compressor:in" }
                ]
                inputs = [ "eq_preamp:In" ]
                outputs = [ "compressor:out" ]
            }
            capture.props = {
                node.name   = "effect_input.eq6"
                media.class = Audio/Sink
                audio.channels = 2
                audio.position=[FL FR]
            }
            playback.props = {
                node.name   = "effect_output.eq6"
                node.passive = true
                audio.channels = 2
                audio.position=[FL FR]
            }
        }
    }
]

 , ,

James_Holden
()

EasyEffects не нужно, или PipeWire для продвинутых: часть 2

Статьи — Desktop

В первой части мы создали конфиг-файл, который добавляет 15-полосный эквалайзер в граф PipeWire. Теперь разберем вопрос, а как же изменять его параметры на лету, без перезапуска PipeWire. Вопрос очень животрепещущий, редакция завалена письмами с ним. ))

В этой части мы разберем задачу на «низком» уровне CLI-утилит. На этой базе несложно сделать любой GUI-фронтенд, который позволит управлять параметрами уже из GUI.

( читать дальше... )

 , ,

James_Holden
()

EasyEffects не нужно, или PipeWire для продвинутых: часть 1

Статьи — Desktop

ВСТУПЛЕНИЕ

Звуковая система PipeWire принесла, без преувеличения, революцию в мир десктопно-мультимедийного Linux. Наконец то эта ОС получила продуманную, сделанную по уму понимающими в теме людьми, и сделанную качественно звуковую систему. Многие ее возможности присутствовали и раньше, в других более старых звуковых системах, но в PipeWire они собраны воедино и сформировали целую единую платформу, на которой можно реализовать огромное количество самых разных задач.

Но в пользовательской среде, эта революция практически не заметна, часто можно встретить мнение вида «ну играет ютуб и играет, мне хватает». Поэтому я решил сделать небольшой цикл статей, посвященный более продвинутому использованию PipeWire, раскрывающему его, без преувеличения, поразительные возможности. (Ну и чтобы изучить их самому в процессе, хехехе).

( читать дальше... )

 , ,

James_Holden
()