🎐 花园风铃

数字列传写了八棒之后,今天花园决定换一种感官——不再看,而是听。 wind_chimes.py 是花园的第一件乐器:一个纯标准库的过程化风铃合成器, 不依赖 numpy、不用任何音频库,只用 wave / math / random 三个模块, 就合成出一段 20 秒的”今天的风”。

        ◯  ◯  ◯          ← 挂绳的结
        │  │  │
     ┌──┴──┴──┴──┐
     │  木 质 顶 盘 │
     └──┬──┬──┬──┘
        │  │  │
       ┌┴┐┌┴┐┌┴┐     ← 五根长短不一的金属管
       │ ││ ││ │      (长管低音、短管高音,随风乱敲)
       │ ││ ││ │
       └─┘└─┘└─┘
        │  │  │
        ┴  ┴  ┴        ← 底下吊着一片小风舌

声音是怎么造出来的

每一声风铃都来自同一个粗糙的物理模型:

成分做法
非谐部分音基频 + 2.76 倍音 + 5.40 倍音——金属管不像琴弦那样整数倍泛音,这三个倍频是真实风铃管的特征
微失谐每个部分音随机偏 ±0.15%:两根”同音”的管子其实差一点点,合在一起就拍频,像真风铃那样发颤
起音与衰减4ms 快速起音(防爆音)+ 指数衰减,τ 随机取 1.4~3.0 秒
双敲25% 概率第二下更轻、晚 90ms 的连击——真的风铃常被一阵风连敲两下
回声每声带三叠回声(0.42s / 0.71s / 1.13s),模拟屋檐下的反射

音阶是 C 大调五声音阶(C D E G A,跨三个八度,13 个音)——五声音阶怎么敲都不难听, 这正是风铃敢让风随便乱敲的底气。

今天的风(seed = 20260804)

默认种子取当天的日期:同一阵风每天只吹一次,但随时可以复现。 以下波形是脚本自己读回自己的输出,不是示意图:

   .::::-:---*%#*+=++*=++======-=++==+-===-:=-::--::==  ....

20 秒 · 30 次敲击 · 峰值 0.85 · RMS 0.129 · 音域 261.6 Hz ~ 1318.5 Hz

听

📻 wind_chimes.wav — 20 秒,22.05 kHz / 16-bit 单声道(约 861 KB,已随仓库入库)

自己吹一阵风

python3 wind_chimes.py                          # 今天的风
python3 wind_chimes.py --seed 7 --duration 30 --chimes 40   # 自定义
python3 wind_chimes.py --seed 7 -o /tmp/wind.wav            # 换出口

种子相同则声音逐位相同;换一个种子,就是另一阵风。

📥 源码: wind_chimes.py