音频频谱图

把音频画成频谱图,看清各个频率的能量随时间是涨是落。横轴时间、纵轴频率、颜色是强弱,还能叠加波形图并导出 PNG。

音频只在这台浏览器里解码和分析,不会上传。能读什么格式取决于浏览器自带的解码器,mp3、wav、m4a、ogg 一般都能读。

选择一个音频文件开始

使用说明

频谱图回答的是「什么时候响了什么频率」,波形图只回答「什么时候响得多大声」。画法是把音频切成一段段短帧,每帧做一次傅里叶变换,得到这一刻各个频率的强度,再按时间顺序把这些列拼成一张图:横轴时间、纵轴频率、颜色是强度。所以纵向上一条条水平的亮线是稳定的音(基频和谐波),竖直的亮痕是瞬态(鼓点、拍手、爆音),一片均匀的雾状就是宽带噪声。

这里的傅里叶变换是自己实现的 radix-2 Cooley-Tukey:先把一帧采样按位反转重排,再从长度 2 逐级翻倍做蝶形运算,复杂度是 n 乘 log2(n)。没有引第三方库,代价是几十行可读代码,收益是首屏不用多下载几十 KB。帧与帧之间重叠 75%(帧移取 FFT 大小的四分之一),这样时间轴不会一格一格跳。

加窗和 dB 是两个容易忽略但影响很大的环节。一帧只有几千个采样,直接硬切会在两端造出突变,能量泄漏到整条频率轴上,所以默认用 Hann 窗把两端压到零。幅度谱按窗函数的相干增益归一化,一条打满量程的正弦读出来正好是 0 dBFS,换窗函数整张图也不会整体变亮或变暗。至于颜色,「按窗内峰值归一化」会把每一列各自拉到 0 dB,安静段落看得清、但帧间强弱关系被抹掉,需要比较不同时刻能量大小时要关掉它。

三个数字都在同一份「按帧平均」的功率谱上算出来,口径统一。主频是能量最高的那条谱线,配合相邻谱线的 dB 值做抛物线插值,精度上限仍是频率分辨率;噪底是所有格子 dB 值的第 10 百分位,代表安静格子的水平;频谱重心是按功率加权的平均频率,用线性功率而不是 dB 值,因为 dB 是对数量、直接平均会把结果压偏。注意这些都是整段音频的汇总,脉冲性的声响会被平均掉,看瞬时成分还得靠图。

长音频的两个天花板是内存和时间:解码后整段音频以 32 位浮点驻留内存,分帧计算量随时长线性上涨,所以帧数有一个上限,超长音频会自动降低时间分辨率(每一列代表更长的时间)。真想看清细节,先用音频剪切把它剪成十几秒再进来;要把几段拼起来看整体走向用音频裁剪拼接;从视频里取音轨用视频提取音频;要测录音设备的底噪水平,用麦克风测试更直接。

常见问题

频谱图和波形图有什么区别?

波形图只画一件事:振幅随时间怎么变,一维信息,看不出声音里有哪些成分。频谱图是时间 × 频率 × 能量三样一起画:横轴时间、纵轴频率、颜色深浅表示该频率在该时刻的强弱,基频、谐波、噪声、齿音、削顶都能摊开看见。两者叠加显示时,频谱图在上、波形图在下,共用一条时间轴,方便对着某个瞬间看它的频率构成。

FFT 大小该怎么选?

FFT 大小决定频率分辨率:分辨率等于采样率除以 FFT 大小,默认 2048 点在 44100 Hz 下每个 bin 是 21.53 Hz,能分辨的最小间隔大致就是这个量级。FFT 越大频率分得越细,但每一帧覆盖的时间越长,时间轴会变糊:512 适合看短促的打击声,4096 适合看稳定的低频音高。两边的取舍没法同时满足,先想清楚要看的是时间还是频率。

窗函数有什么区别,该选哪个?

加窗是为了对付截断:一帧只有几百到几千个采样,两端被硬切会产生突变,能量会泄漏到整条频率轴上。Hann 窗两端平滑降到零,泄漏最小、噪底最干净,是默认选择;Hamming 窗主瓣更窄、频率定位略准,但旁瓣拖尾更长,强信号旁边会出现几道鬼影;矩形等于不加窗,只在观察单个精确落点的正弦时有意义。

动态范围的上下限怎么设?

上限是颜色映射的白点,默认 0 dBFS,也就是数字音频能表达的最大值;下限是黑点,默认 -90 dB,更弱的格子直接涂成背景色。下限调到 -120 能看到更弱的分量,代价是背景整体变亮、对比度下降;调到 -60 只留最响的部分,看语音基频更清爽。调完不用重算,颜色是渲染时按当前范围映射的。

纵轴为什么默认用对数刻度?

因为人耳对频率的感知接近对数:100 Hz 到 200 Hz 听起来是一个八度,10 kHz 到 10.2 kHz 几乎听不出区别,但两者在线性刻度上占据的宽度差了近百倍。对数刻度把每个八度摊成等宽,低频细节才看得见;线性刻度适合看谐波这种等间距的规律,或者只想关注 0 到 5 kHz 这一段。

给出的主频准不准?

它是一段音频里能量最大的那一个频率,不表示整段都是这个音。图上的位置受 bin 宽度限制:2048 点 FFT 在 44100 Hz 下每个 bin 是 21.53 Hz,真实频率落在两条谱线之间时最多差半个 bin;这里另外用相邻谱线的 dB 值做了抛物线插值,能把误差压到几分之一 bin。要看整段的音高变化,把 FFT 调大,或者先用音频裁剪截一小段再分析更稳。

噪底那个数字为什么会变?

它是所有帧、所有 bin 的 dB 值抽样后从小到大排序的第 10 百分位,代表大量安静格子的水平。句子之间的静音、被窗函数压到接近零的帧边界都会拉低它;整段都很响、没有静音段时它又会明显偏高。它适合快速判断这段录音本底干不干净,不适合当作设备的精确噪声指标;要测设备底噪得用麦克风测试那一类的工具。

30 分钟以上的录音要算多久?

分帧的计算量约等于 帧数 × FFT 大小 × log2(FFT 大小)。为了让长音频不至卡死,帧数有上限(3000 帧),超过时自动加大帧移、降低时间分辨率,也就是每一列代表更长的一段时间,界面上会实时显示已处理多少帧。想看清细节,先用音频裁剪剪出十几秒一段再分析,比在这张图上放大有效得多。