linux/树莓派下均衡音频

信息处理 声音的 卷积 均衡
2022-02-14 10:02:49

我有一个用 Python 编写的音频流接收器,在树莓派上运行。该接收器将流式音频写入 alsa 设备,然后将其传递给驱动我制作的 DML 扬声器的放大器。DML 扬声器需要相当重的均衡才能使它们听起来正确 - 所以我想在 rpi 上添加数字信号处理。

使用 Room EQ Wizard,我创建了一个校正滤波器。我能够看到原始均衡器值(频率、增益和 Q),并将滤波器导出为脉冲响应 wav。我已经使用 shairport-sync 测试了这个 IR wav(我什至写了说明)并且效果很好

问题是如何在 linux(无头,无 GUI)下为来自 python 脚本的音频实现均衡。

我认为有三种不同的路线可以工作 -

  1. 使用基于软件的图形均衡器
  2. 在 python 编写音频后,在 ALSA 下对音频信号应用卷积
  3. 或者在写之前直接在python中

有一个alsa 均衡器插件,但是这太有限了,因为没有足够的频段,频段是预设频率,Q 是不可调节的。

还有一个实验性的alsa 卷积插件,不幸的是我无法工作。

我还发现这个问题让我思考python是否可以直接应用卷积。不幸的是,我不是 python(或音频处理)专家,所以这需要付出很多努力才能弄清楚。

有人知道可以满足我需要的均衡器或 alsa 插件吗?

2个回答

我查看了同时使用 CamillaDSP 和直接在 Python 中进行过滤,但两者的学习曲线似乎都很陡峭。

相反,我发现的是一个名为 ACDf 的 LADSPA 滤波器,它提供了一个多频带参数均衡器,可以直接与alsa. 让它工作的步骤非常简单:

  1. 下载ACDf源代码
  2. make它构建ACDf.so二进制文件然后移动到/usr/lib/ladspa/
  3. 在alsa配置文件中加载并配置ACDf插件~/.asoundrc

ACDf 多频段参数均衡器的配置选项允许您指定频率、增益和 q 因子。Room EQ Wizard 显示所有这三个值,因此只需将它们从 REW 转录到~/.asoundrc文件中即可。

左声道的一个均衡器频段配置如下所示:

        0 {
            label ACDf
            policy none
            input.bindings.0 "Input"   #process input channel 0 (left)
            output.bindings.0 "Output" #send to output channel 0
            input { controls [26 1 6.0 53.1 8.530 1 1]}
        }

请注意,这input/output.bindings.0是左侧输入/输出。用于1正确的通道。

在控制部分,数字如下:

  • 26- 参数均衡器是 26 号滤波器(ACDf 中有许多不同的滤波器可用)
  • 1- 不曾用过
  • 6.0- 分贝增益
  • 53.1- 以赫兹为单位的频率
  • 8.53- Q 因子
  • 1- 不曾用过
  • 1- 不曾用过

这是 Room EQ Wizard 为我的 DML 扬声器生成的 EQ: REW 建议的均衡器

现在我的完整 ~/.asoundrc 文件每个通道有 15 个 EQ 设置:

pcm.!default {
    type plug
    slave.pcm equalizer
}

pcm.equalizer {
    type ladspa
    path "/usr/lib/ladspa"
    channels 2
    slave {
        pcm "plughw:0"
    }

    plugins {
        0 {
            label ACDf
            policy none
            input.bindings.0 "Input"
            output.bindings.0 "Output"
            input { controls [26 1 6.0 53.1 8.530 1 1]}
        }
        1 {
            label ACDf
            policy none
            input.bindings.0 "Input"
            output.bindings.0 "Output"
            input { controls [26 1 -8.2 59.1 3.793 1 1]}
        }
        2 {
            label ACDf
            policy none
            input.bindings.0 "Input"
            output.bindings.0 "Output"
            input { controls [26 1 -6.0 69.7 9.912 1 1]}
        }
        3 {
            label ACDf
            policy none
            input.bindings.0 "Input"
            output.bindings.0 "Output"
            input { controls [26 1 -3.5 126 18.191 1 1]}
        }
        4 {
            label ACDf
            policy none
            input.bindings.0 "Input"
            output.bindings.0 "Output"
            input { controls [26 1 6.0 305 5.000 1 1]}
        }
        5 {
            label ACDf
            policy none
            input.bindings.0 "Input"
            output.bindings.0 "Output"
            input { controls [26 1 -5.4 325 5.000 1 1]}
        }
        6 {
            label ACDf
            policy none
            input.bindings.0 "Input"
            output.bindings.0 "Output"
            input { controls [26 1 -3.3 509 5.000 1 1]}
        }
        7 {
            label ACDf
            policy none
            input.bindings.0 "Input"
            output.bindings.0 "Output"
            input { controls [26 1 -4.3 685 5.000 1 1]}
        }
        8 {
            label ACDf
            policy none
            input.bindings.0 "Input"
            output.bindings.0 "Output"
            input { controls [26 1 6.0 1433 5.000 1 1]}
        }
        9 {
            label ACDf
            policy none
            input.bindings.0 "Input"
            output.bindings.0 "Output"
            input { controls [26 1 -8.2 1501 5.000 1 1]}
        }
        10 {
            label ACDf
            policy none
            input.bindings.0 "Input"
            output.bindings.0 "Output"
            input { controls [26 1 -5.8 1780 5.000 1 1]}
        }
        11 {
            label ACDf
            policy none
            input.bindings.0 "Input"
            output.bindings.0 "Output"
            input { controls [26 1 -5.8 2017 5.000 1 1]}
        }
        12 {
            label ACDf
            policy none
            input.bindings.0 "Input"
            output.bindings.0 "Output"
            input { controls [26 1 -5.4 2231 5.000 1 1]}
        }
        13 {
            label ACDf
            policy none
            input.bindings.0 "Input"
            output.bindings.0 "Output"
            input { controls [26 1 -8.3 3265 5.000 1 1]}
        }
        14 {
            label ACDf
            policy none
            input.bindings.0 "Input"
            output.bindings.0 "Output"
            input { controls [26 1 -4.1 4985 5.000 1 1]}
        }
        15 {
            label ACDf
            policy none
            input.bindings.1 "Input"
            output.bindings.1 "Output"
            input { controls [26 1 6.0 53.1 8.530 1 1]}
        }
        16 {
            label ACDf
            policy none
            input.bindings.1 "Input"
            output.bindings.1 "Output"
            input { controls [26 1 -8.2 59.1 3.793 1 1]}
        }
        17 {
            label ACDf
            policy none
            input.bindings.1 "Input"
            output.bindings.1 "Output"
            input { controls [26 1 -6.0 69.7 9.912 1 1]}
        }
        18 {
            label ACDf
            policy none
            input.bindings.1 "Input"
            output.bindings.1 "Output"
            input { controls [26 1 -3.5 126 18.191 1 1]}
        }
        19 {
            label ACDf
            policy none
            input.bindings.1 "Input"
            output.bindings.1 "Output"
            input { controls [26 1 6.0 305 5.000 1 1]}
        }
        20 {
            label ACDf
            policy none
            input.bindings.1 "Input"
            output.bindings.1 "Output"
            input { controls [26 1 -5.4 325 5.000 1 1]}
        }
        21 {
            label ACDf
            policy none
            input.bindings.1 "Input"
            output.bindings.1 "Output"
            input { controls [26 1 -3.3 509 5.000 1 1]}
        }
        22 {
            label ACDf
            policy none
            input.bindings.1 "Input"
            output.bindings.1 "Output"
            input { controls [26 1 -4.3 685 5.000 1 1]}
        }
        23 {
            label ACDf
            policy none
            input.bindings.1 "Input"
            output.bindings.1 "Output"
            input { controls [26 1 6.0 1433 5.000 1 1]}
        }
        24 {
            label ACDf
            policy none
            input.bindings.1 "Input"
            output.bindings.1 "Output"
            input { controls [26 1 -8.2 1501 5.000 1 1]}
        }
        25 {
            label ACDf
            policy none
            input.bindings.1 "Input"
            output.bindings.1 "Output"
            input { controls [26 1 -5.8 1780 5.000 1 1]}
        }
        26 {
            label ACDf
            policy none
            input.bindings.1 "Input"
            output.bindings.1 "Output"
            input { controls [26 1 -5.8 2017 5.000 1 1]}
        }
        27 {
            label ACDf
            policy none
            input.bindings.1 "Input"
            output.bindings.1 "Output"
            input { controls [26 1 -5.4 2231 5.000 1 1]}
        }
        28 {
            label ACDf
            policy none
            input.bindings.1 "Input"
            output.bindings.1 "Output"
            input { controls [26 1 -8.3 3265 5.000 1 1]}
        }
        29 {
            label ACDf
            policy none
            input.bindings.1 "Input"
            output.bindings.1 "Output"
            input { controls [26 1 -4.1 4985 5.000 1 1]}
        }
    }
}

非常感谢 jrubinstein 在GitHub 上的帮助。

您可以使用https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.sosfilt.html直接在 Python 中将其实现为 IIR 过滤器

每个 Room EQ 向导部分都可以使用 RBJs Audio EQ Cookbook 转换为二阶滤波器部分(参见例如https://www.w3.org/TR/audio-eq-cookbook/https://www.musicdsp。 org/en/latest/Filters/197-rbj-audio-eq-cookbook.html)。你想要“峰值均衡器”。然后只需将所有部分级联到一个 SOS 中。

注意:如果您的过滤器参数看起来像https://github.com/mikebrady/shairport-sync/wiki/Digital-Signal-Processing-with-Shairport-Sync我建议谨慎:您有很多非常高 Q 的功能是6 Hz/12 Hz(非常低的频率)。这些可能在数值上不稳定,你真的不需要它们。我会消除低于 30 Hz 的所有部分,并确保您在信号链的某处有合适的高通滤波器。