跳转至

GEQ Module Design (geq_v1)

概述

geq_v1 是多通道图形均衡器(Graphic/Parametric EQ),每通道最多 50 个 biquad 滤波器频段,支持实时频响曲线可视化和拖拽控制。

参数

参数 ID 类型 范围 默认值 说明
enable bool - true 模块启用/禁用
bandsPerChannel int 1~50 5 每通道频段数
bandType#${b}#${ch} enum LP/HP/PK/LSV/HSV PK 第b频段第ch通道的滤波器类型
bandFreq#${b}#${ch} float 20~20000 Hz 1000 Hz 中心/截止频率
bandGain#${b}#${ch} float -24~24 dB 0 dB 频段增益(LP/HP 无效)
bandQ#${b}#${ch} float 0.1~20 0.707 品质因数(带宽)

滤波器类型

类型 说明 Gain 有效
LP 低通滤波器
HP 高通滤波器
PK 峰值(Peaking EQ)
LSV 低频搁架(Low Shelf)
HSV 高频搁架(High Shelf)

频率响应计算(Biquad)

基于 Audio EQ Cookbook(Robert Bristow-Johnson)的双二阶滤波器公式:

// 核心传递函数(z变换):
// H(z) = (b0 + b1*z^-1 + b2*z^-2) / (1 + a1*z^-1 + a2*z^-2)

// 频率响应幅度(dB):
// |H(e^jw)|_dB = 10 * log10(|numerator|^2 / |denominator|^2)
// 其中 e^jw = cos(w) + j*sin(w),w = 2π*f/fs

纯 JavaScript 计算(无需 AudioContext),可在任意环境运行。

Canvas 可视化

  • 尺寸:640×220 px
  • X 轴:20 Hz ~ 20 kHz(对数刻度)
  • Y 轴:±30 dB(线性刻度)
  • 频率采样点:512 个
  • 总频响 = 所有 band dB 叠加

拖拽交互

操作 效果
点击 band 控制点 选中该 band(高亮显示)
拖拽 X 更新 bandFreq(对数映射)
拖拽 Y(PK/LSV/HSV) 更新 bandGain
拖拽 Y(LP/HP) 更新 bandQ(上方→大Q,下方→小Q)

坐标映射

// 频率 → X 坐标(对数)
freqToX(f) = log10(f / 20) / log10(1000) * width

// X 坐标 → 频率
xToFreq(x) = 20 * 1000^(x / width)

// dB → Y 坐标
dbToY(db) = height - ((db - minDb) / (maxDb - minDb)) * height

// Y 坐标 → dB
yToDb(y) = minDb + (1 - y/height) * (maxDb - minDb)

通道联动(per-band)

  • linkedChannelsPerBand = Map<bandIdx, Set<chIdx>>
  • 修改 Band B 的参数时,自动同步到联动 Set 中的所有通道
  • 每行右侧 [🔗N] 按钮点击打开通道选择 popover
  • 视觉标记:按钮颜色高亮,显示联动通道数

UI 布局

[标题] [关闭]
[CH1 CH2 ... CH20 Tab] [Band 数: 5]
┌─────────────────────────────────────┐
│  Canvas 640×220 (频响曲线 + 控制点)  │
├─────────────────────────────────────┤
│ Band │ 类型 │  频率  │  增益 │ Q值 │链路│
│  1   │[PK▼] │[1000] │[ 0.0]│[0.71]│[🔗]│
│  2   │[LP▼] │[8000] │[N/A ]│[0.71]│[🔗]│
└─────────────────────────────────────┘

持久化

linkStore.setParamValue(instanceId, `bandType#${b}#${ch}`, 'PK')
linkStore.setParamValue(instanceId, `bandFreq#${b}#${ch}`, 1000)
linkStore.setParamValue(instanceId, `bandGain#${b}#${ch}`, 0)
linkStore.setParamValue(instanceId, `bandQ#${b}#${ch}`, 0.707)
linkStore.setParamValue(instanceId, 'bandsPerChannel', 5)

DSP 内存布局

Offset Size 说明
0 1 enable
1 4 bandsPerChannel
5 50×20×4×4 band params (type, freq, gain, Q) × 20ch × 50bands

Total: 16005 bytes(满配 50 bands × 20 ch) 实际用量 = bandsPerChannel × 20 × 16 bytes