整段频谱为什么找不到声音发生的时间:短时傅里叶变换
两段声音都先后出现一个低音和一个高音,只把顺序交换,整段频率结果就可能看起来完全一样。要让程序找回“哪个声音先出现”,需要把录音分成互相重叠的小段,每到一个位置就重新计算一次。
第 14 课已经把一整段录音换成了一条曲线:横轴是频率,也就是一秒重复多少次,纵轴是每个频率有多强。这条曲线能看出小提琴、钢琴、萨克斯和噪声(也就是沙沙作响、没有固定高低的那种声音)各自由哪些成分组成,却指不出钢琴是在哪一刻敲下的。
本课要做的实验是:先故意造出两段“整段结果相同、声音顺序相反”的信号,再检查移动小段以后,程序能不能找回先后顺序。完整代码在第 15 课脚本,运行环境仍沿用课程总纲中的一次性配置。
实验:交换低音和高音的顺序,整段频谱还能分辨吗
先生成两段 1 秒声音。两段都包含每秒重复 300 次的低音和每秒重复 900 次的高音:
- 第一段先播放 300 Hz,再播放 900 Hz。
- 第二段正好反过来,先播放 900 Hz,再播放 300 Hz。
这里的 Hz 读作赫兹,就是一秒重复多少次。第 02 课解释过它与听到的高低有什么关系。
脚本先对两段完整声音各算一次幅度谱,也就是第 12 课那条「每个频率有多强」的曲线。两条曲线的最大差只有 4.547e-13。这个数已经接近浮点计算留下的舍入误差,意味着只看整段幅度谱,程序无法判断谁先谁后。
接着,脚本每次只看 800 个样本,每隔 400 个样本向右移动一次。第一段开头最强的是 300 Hz,结尾最强的是 900 Hz;第二段则从 900 Hz 变成 300 Hz。顺序重新出现了。
图 1:中间的整段幅度谱只有相同的 300 Hz 和 900 Hz 峰。下方逐帧结果才显示:一段从低到高,另一段从高到低。
这里要补一个边界,免得把话说过头:信息并没有凭空消失。只要保留完整的复数结果——也就是第 11 课那种一个数同时记住「有多强」和「从哪里起步」——DFT 仍然能把原声音一个数不差地重建回来。
真正的问题有两层。第一,每个 DFT 系数概括的都是整段录音,它身上没有一个属于自己的时间坐标。第二,我们最常看的幅度谱只取了模,把相位(也就是那个「从哪里起步」)整个丢掉了。两件事加起来,整段幅度谱就答不出「这个成分在第几秒」。
互动持续版
静态图文到这里,接下来让声音和图形动起来
购买后解锁完整课程,以及只有官网互动版才能提供的声音、动画和可操作实验。
- 完整声音对比、分步动画与 8 个交互实验
- 微信账号登录,手机和电脑同步访问
- 申请加入课程会员群,交流、反馈和接收更新
- 持续获得这门课程的勘误与内容升级