乐理

全系音色合成器

① 现代器乐物理原理分类(声学 DSP 模型)
② 周礼八音体系(金、石、丝、竹、匏、土、革、木)
③ 十二平均律阶梯键盘 (三个八度 · 36半音)

一、 音色合成与十二平均律核心数学模型

1. 音色数学模型(傅里叶级数加时变包络):

音色(Timbre)由复合声波的泛音频谱比率 $r_k$ 与时变能量包络 $A_k(t)$ 共同决定:

$$x(t) = \sum_{k=1}^{N} A_k(t) \cdot \sin(2\pi \cdot r_k f_0 \cdot t + \phi_k) + \mathcal{F}_{\text{filter}}(\text{Noise}(t))$$

2. 十二平均律与自然大调音程数学机理(全全半全全全半):

十二平均律将一个八度(倍频程)等比分成 12 个半音,相邻半音的公比为 $\sqrt[12]{2} \approx 1.05946$:

$$f_n = f_{\text{base}} \times 2^{\frac{n}{12}} \quad (n \in [0, 11] \text{ 为半音序号})$$

“全全半全全全半”是自然大调(Major Scale)中相邻两个自然音级之间的音程步进(Interval Step):

  • 全音(Whole Step,跨 2 个半音):频率比为 $(\sqrt[12]{2})^2 = 2^{\frac{2}{12}} \approx 1.1225$,对应步进:$C \to D$、$D \to E$、$F \to G$、$G \to A$、$A \to B$。
  • 半音(Half Step,跨 1 个半音):频率比为 $2^{\frac{1}{12}} \approx 1.0595$,对应步进:自然大调中无黑键阻隔的 $E \to F$ 以及 $B \to C’$。

二、 核心代码架构与 Web Audio API 编程原理

程序采用原生 Web Audio API 构建实时音频拓扑图(Audio Graph),其信号处理链路如下:

【声源振荡器】OscillatorNode (Sine/Sawtooth/Square) $\to$ $f = f_0 \times r_k$ $\downarrow$ 【时域包络】GainNode (ADSR 时变包络计算) $\to$ setValueAtTime / exponentialRampToValueAtTime $\downarrow$ 【频响雕刻】BiquadFilterNode (低通 Lowpass / 峰值 Peaking) $\to$ 模拟共鸣箱与阻尼 $\downarrow$ 【总线输出】Master GainNode $\to$ AudioDestinationNode (声卡扬声器)

1. 频率与音阶计算代码实现:

// 遍历每个半音,通过 Math.pow(2, nIdx / 12) 严格实现十二平均律频率换算 const freq = oct.baseC * Math.pow(2, nIdx / 12);

2. 时域包络(ADSR)指数衰减代码实现:

// 利用 GainNode 的时间调度精确绘制能量起振 (Attack) 与指数耗散 (Decay & Release) g.gain.setValueAtTime(0.0001, t); g.gain.linearRampToValueAtTime(h.a, t + a); // 线性起振:A(t) = a * (t / a) g.gain.exponentialRampToValueAtTime(0.0001, t + a + d + r); // 指数衰减:A(t) = A_0 * e^(-alpha * t)

3. 加法合成 vs 减法合成代码控制流:

if (p.model === “subtractive”) { // 减法合成:生成富谐波母波 (Sawtooth) $\to$ 串联 BiquadFilter 动态滤波削切 osc.type = p.wave || ‘sawtooth’; osc.connect(gainNode); gainNode.connect(filterNode); } else { // 加法合成:并发派生 N 个 OscillatorNode 并行振荡,加权相加到 master 输出总线 p.harmonics.forEach(h => { const osc = ctx.createOscillator(); osc.frequency.setValueAtTime(freq * h.r, t); osc.connect(g); g.connect(out); }); }

三、 现代器乐声学 6 大类的数学与代码映射

纯音 (Sine) 电鸣基底
$$x(t) = A(t)\sin(2\pi f_0 t)$$
代码实现:harmonics: [{ r: 1.0, a: 1.0 }]。
单频简谐波,无泛音成分,频域表现为单一脉冲冲激 $\delta(f – f_0)$。
击弦 (String) 一维弦振动
$$\frac{\partial^2 y}{\partial t^2} = c^2 \frac{\partial^2 y}{\partial x^2} \implies r_k = k \ (k \in \mathbb{N}^+)$$
代码实现:r: [1.0, 2.0, 3.0, 4.0] + lowpass: 4000Hz。
两端固定边界导出完整整数谐波列,能量呈反比衰减 $A_k \propto 1/k$。
木管 (Woodwind) 闭管奇次谐波
$$r_k = 2m – 1 \implies r_k \in \{1, 3, 5, 7\dots\}$$
代码实现:r: [1.0, 3.0, 5.0, 7.0] + attack: 0.08s。
一端开一端闭的管内驻波共振,偶次谐波相互抵消,呈现空灵木质感。
铜管 (Brass) 减法合成与滤波
$$x_{\text{saw}}(t) \xrightarrow{\text{IIR Filter}} H(z) = \frac{b_0 + b_1 z^{-1} + b_2 z^{-2}}{1 + a_1 z^{-1} + a_2 z^{-2}}$$
代码实现:wave: "sawtooth" + lowpass: 2800Hz, Q: 2.0。
全阶锯齿波通过二阶低通滤波器动态衰减高频成分。
钟鸣 (Bell) 非谐波厚壳振动
$$r_k \notin \mathbb{Z} \implies r_k \in \{1.0, 2.01, 3.0, 4.16\}$$
代码实现:引入 $2.01f_0$ 与 $4.16f_0$ 微失谐泛音。
三维刚体弹性壳偏微分方程的非整数特征值,引入金属拍频干涉。
打击 (Percussion) 膜鸣贝塞尔解
$$\nabla^2 u = \frac{1}{c^2}\frac{\partial^2 u}{\partial t^2} \implies J_m(\alpha_{m,n}) = 0$$
代码实现:r: [0.5, 1.0, 1.73] + decay: 0.2s + lowpass: 400Hz。
二维圆膜振动由贝塞尔函数零点决定,能量集中在超低频且衰减极快。

四、 周礼八音体系的物理与代码映射

金 · 编钟 合瓦双振模
$$f_{\text{main}} = f_0, \ f_{\text{side}} = 1.20 f_0$$
代码实现:内置 r: 1.2 侧鼓音 + decay: 4.0s 长衰减 + lowpass: 3000Hz。正鼓音与侧鼓音双特征值共存。
石 · 特磬 板弯曲振动
$$r_k \in \{1.0, 2.5, 4.2\}, \ t_{\text{attack}} = 0.003\text{s}$$
代码实现:r: [1.0, 2.5, 4.2] + attack: 0.003s。欧拉-伯努利板振动,泛音稀疏跨度大,高频能量快速耗散。
丝 · 琴瑟 张弦拍频干涉
$$\sin(\omega t) + \sin(1.002\omega t) = 2\cos(0.001\omega t)\sin(1.001\omega t)$$
代码实现:r: 1.002 + peaking: 3200Hz, +6dB。微失谐干涉产生周期揉弦拍频,3.2kHz 处设箱体共鸣峰。
竹 · 箫笛 边棱管鸣与笛膜
$$r_k \in \{1, 3, 5\}, \ \text{Peaking}(2500\text{Hz}, +7\text{dB})$$
代码实现:奇次谐波 + attack: 0.12s 气流慢建立 + peaking: 2500Hz, +7dB 笛膜非线性共鸣。
匏 · 笙簧 自由簧管偶合
$$x(t) = \sum \text{Sawtooth}(2\pi \cdot \{1.0, 1.25, 1.5, 2.0\} f_0 t)$$
代码实现:wave: "sawtooth" + r: [1.0, 1.25, 1.5, 2.0]。簧片脉冲列内置大三度与纯五度耦合和鸣矩阵。
土 · 陶埙 亥姆霍兹共振
$$f_{\text{res}} = \frac{v}{2\pi}\sqrt{\frac{S}{V L’}}, \ r_k \in \{1.0, 2.0, 0.5\}$$
代码实现:基频占 70% + r: 0.5 低八度暗音 + lowpass: 2200Hz。空腔吸收高次谐波,基频圆润空灵。
革 · 建鼓 膜受迫振动
$$r_k \in \{0.25, 0.45, 0.8\}, \ \text{Lowpass}(250\text{Hz})$$
代码实现:r: [0.25, 0.45, 0.8] + decay: 0.45s + lowpass: 250Hz。超低频下潜与空气弹簧阻尼爆破。
木 · 雅柷 刚体强阻尼
$$x_{\text{sqr}}(t) \cdot e^{-\alpha t}, \ \alpha \ge 25 \ (\text{Decay} \le 0.12\text{s})$$
代码实现:wave: "square" + decay: 0.12s, release: 0.02s。实心方木碰撞,方波谐波伴随极短时域截断。