三角波是芯片音乐中另一个关键波形。NES的2A03芯片专门有一个三角波通道用于低音线(Bass Line),它的声音比方波更柔和、更接近正弦波,但又带有独特的数字味道。
三角波可以看作方波经过积分得到的结果——它线性上升再线性下降,形成一个三角形。其傅里叶级数为:
f(t) = (8A/π²) × [sin(ωt) - sin(3ωt)/9 + sin(5ωt)/25 - ...]
关键特征:
NES的三角波通道有几个独特设计:
经典案例:《超级玛丽》地下关卡的低音线就是三角波通道演奏的。
生成三角波的关键是将线性递增的相位映射为"先上后下"的波形:
相位范围:0 → 2^N-1,一个完整周期
前半周期(0 到 2^(N-1)-1):输出从0线性上升到最大值
output = phase[N-2:0] (取低N-1位)
后半周期(2^(N-1) 到 2^N-1):输出从最大值线性下降到0
output = ~phase[N-2:0] (取反)
判断前半/后半周期的方法:检查相位的最高位。最高位=0是前半周期(上升),最高位=1是后半周期(下降)。
与方波相同,使用32位相位累加器。32位提供极高的频率精度——在50MHz时钟下,最小频率分辨率约为0.012Hz,远超音乐需求。
32位相位太长,不能直接用于波形映射。我们取相位的高BIT_DEPTH+1位(共9位):
wire [BIT_DEPTH:0] phase_top = phase[31 -: 9];
这9位中:最高位表示上升/下降,低8位表示在当前半周期中的位置。
根据最高位选择:上升时直接输出ramp值,下降时输出ramp的按位取反。取反操作在硬件中零成本(布线即可)。
32位相位,50MHz时钟:
// C3 (低音C) = 130.81Hz
freq_tune = round(130.81 * 2^32 / 50000000) = round(11242) = 11242
// 实际频率 = 11242 * 50000000 / 4294967296 = 130.81Hz ✅
// A2 (低音A) = 110Hz
freq_tune = round(110 * 2^32 / 50000000) = round(9449) = 9449
// 实际频率 = 9449 * 50000000 / 4294967296 = 110.00Hz ✅
32位相位的精度在可听范围内完全够用。
| 特征 | 方波 | 三角波 |
|---|---|---|
| 谐波 | 奇次谐波,1/n衰减 | 奇次谐波,1/n²衰减 |
| 音色 | 明亮、锋利、有攻击性 | 柔和、温暖、圆润 |
| 典型用途 | 主旋律、领奏 | 低音线、铺底 |
| NES音量控制 | 4级 | 无(固定音量) |
| 硬件复杂度 | 比较器即可 | 需要加减运算 |
| 占空比 | 可变 | 固定50% |
波形塑形者 — 掌握三角波生成原理,理解相位到幅度的映射方法,能对比分析不同波形的频谱特征!
// triangle_wave.v - 三角波发生器
// 使用相位累加器 + 线性映射生成三角波
module triangle_wave #(
parameter CLK_FREQ = 50000000,
parameter BIT_DEPTH = 8,
parameter PHASE_BITS = 32
)(
input wire clk,
input wire rst_n,
input wire [PHASE_BITS-1:0] freq_tune,
output wire [BIT_DEPTH-1:0] wave_out
);
reg [PHASE_BITS-1:0] phase;
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
phase <= {PHASE_BITS{1'b0}};
else
phase <= phase + freq_tune;
end
// 取相位高BIT_DEPTH+1位用于波形映射
// 最高位决定上升/下降,其余位决定幅度
wire [BIT_DEPTH:0] phase_top;
assign phase_top = phase[PHASE_BITS-1 -: (BIT_DEPTH+1)];
// 最高位=0时上升(0→max),最高位=1时下降(max→0)
wire [BIT_DEPTH-1:0] ramp;
assign ramp = phase_top[BIT_DEPTH-1:0];
assign wave_out = phase_top[BIT_DEPTH] ? (~ramp) : ramp;
endmodule
✅ Verilator验证通过
NES的三角波通道有一个独特的设计——它的三角波不是数学上精确的,而是由32级阶梯近似:
周期内32个位置对应的输出值:
位置 0-15: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15
位置 16-31: 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
实际DAC输出(7位线性):
0→15→0,每级增量 = 127/15 ≈ 8.47
量化后: 0, 8, 17, 25, 34, 42, 51, 59, 68, 76, 85, 93, 102, 110, 119, 127
这种32级离散阶梯在低频时可以听到明显的"台阶"失真,但在中高频时人耳感知为平滑的三角波。
NES三角波通道有两个特殊的控制位:
在芯片音乐中用三角波做低音有几种经典技巧:
在FM合成中我们经常需要正弦波,但正弦波查找表占用ROM。三角波可以作为正弦波的粗略近似——它们的奇次谐波结构相似,只是三角波的高次谐波衰减更快。在精度要求不高的场合,三角波可以替代正弦波。
| 谐波 | 正弦波 | 三角波 | 方波 |
|---|---|---|---|
| 1次(基频) | 1.000 | 1.000 | 1.000 |
| 3次 | 0.000 | -0.111 | 0.333 |
| 5次 | 0.000 | 0.040 | 0.200 |
| 7次 | 0.000 | -0.020 | 0.143 |
| 9次 | 0.000 | 0.012 | 0.111 |
三角波的傅里叶级数展开是理解其频谱的关键:
三角波(振幅A,周期T):
f(t) = (8A/π²) × Σ[(-1)^((n-1)/2) / n²] × sin(2πnt/T)
其中 n = 1, 3, 5, 7, ...(奇次谐波)
各次谐波振幅:
1次: 8A/π² ≈ 0.811A
3次: -8A/(9π²) ≈ -0.090A
5次: 8A/(25π²) ≈ 0.032A
7次: -8A/(49π²) ≈ -0.017A
对比方波:
1次: 4A/π ≈ 1.273A
3次: 4A/(3π) ≈ 0.424A
5次: 4A/(5π) ≈ 0.255A
→ 三角波的3次谐波仅为基频的11%
→ 方波的3次谐波为基频的33%
→ 三角波高次谐波衰减快3倍
NES作曲家使用三角波通道的技巧:
在实际系统中,需要一个模块根据选择信号输出不同波形:
module wave_select #(
parameter BIT_DEPTH = 8,
parameter PHASE_BITS = 32
)(
input wire [PHASE_BITS-1:0] phase,
input wire [1:0] wave_type, // 00=方波,01=三角,10=锯齿,11=噪声
input wire [1:0] duty, // 方波占空比
output wire [BIT_DEPTH-1:0] wave_out
);
reg [BIT_DEPTH-1:0] out;
always @(*) begin
case (wave_type)
2'b00: begin // 方波
case (duty)
2'b00: out = (phase[31:28] < 4'd2) ? 8'd255 : 8'd0;
2'b01: out = (phase[31:28] < 4'd4) ? 8'd255 : 8'd0;
2'b10: out = phase[31] ? 8'd0 : 8'd255;
2'b11: out = (phase[31:28] < 4'd12) ? 8'd255 : 8'd0;
endcase
end
2'b01: out = phase[31] ? ~phase[30:23] : phase[30:23];
2'b10: out = phase[31:24];
2'b11: out = {phase[31],phase[29],phase[27],phase[25],
phase[23],phase[21],phase[19],phase[17]};
default: out = 8'd0;
endcase
end
assign wave_out = out;
endmodule
三角波在芯片音乐中最常用的角色是低音线(Bass Line)。以下是一些编程技巧:
// 模式1: 每拍一个根音(最基础)
|C---|C---|C---|C---|
// 模式2: 八度跳跃(更有律动)
|C-c-|C-c-|C-c-|C-c-| (c=高八度C)
// 模式3: 行走贝斯(Walking Bass)
|C-E-|F-G-|A-F-|E-C-|
// 模式4: 断奏(Staccato)
|C.C.|C.C.|C.C.|C.C.| (.=休止)
// 模式5: 节奏型低音
|C--C|C--C|C-CC|C---|
三角波低音的魅力在于其"干净"——没有方波那样的高频泛音干扰,低音线条清晰可辨。