目录
torch.hann_window(N_FFT) 的原理及示例说明
(1)矩形窗(Rectangle Window) 调用格式:w=boxcar(n),根据长度 n 产生一个矩形窗 w。
(2)三角窗(Triangular Window) 调用格式:w=triang(n),根据长度 n 产生一个三角窗 w。
(3)汉宁窗(Hanning Window) 调用格式:w=hanning(n),根据长度 n 产生一个汉宁窗 w。
(4)海明窗(Hamming Window) 调用格式:w=hamming(n),根据长度 n 产生一个海明窗 w。
(5)布拉克曼窗(Blackman Window) 调用格式:w=blackman(n),根据长度 n 产生一个布拉克曼窗 w。
(6)恺撒窗(Kaiser Window) 调用格式:w=kaiser(n,beta),根据长度 n 和影响窗函数旁瓣的β参数产生一个恺撒窗w。
频谱泄露
2. 为什么会泄漏?
通俗解释:音乐剪切时的“咔哒”声是怎么产生的?
1. 直接剪切 = 信号的“悬崖式突变”
当你在音频编辑软件里直接剪切一段音乐(比如从波峰突然截断),相当于让声音信号瞬间从某个值跳到零(或另一个值)。这种突变会产生一个极短促的高频脉冲,人耳听到的就是“咔哒”声。
类比:
-
就像正在匀速行驶的汽车突然急刹车,乘客会“砰”地往前冲(类似声音信号的突变)。
-
或者像用剪刀剪断一根绷紧的橡皮筋,断口处会“啪”地弹一下(高频振动)。
2. 数学原理:不连续点 = 高频噪声
任何信号(包括音乐)都可以分解成不同频率的正弦波叠加。
-
平滑变化的信号 → 主要由低频成分组成(听起来自然)。
-
突然跳变的信号(如剪切点)→ 需要无数高频正弦波来拟合这个突变(数学上叫吉布斯现象)。
结果:
剪切点引入了一堆本不存在的超高频率成分,这些频率超过了音乐本身的音高范围,人耳就感知为“咔哒”声。
关键原因:信号被“暴力截断”
-
理想情况:如果信号是完美的正弦波,且截取完整的周期(比如从波峰开始,到波峰结束),FFT会看到干净的单一频率。
✅ 就像用剪刀剪断一根正在匀速摆动的绳子,绳子不会乱抖。 -
实际情况:信号截取时,起点和终点可能不连续(比如从半空中剪断绳子)。
❌ 绳子会“猛地一抖”(产生高频杂波),FFT会误判这些抖动为真实频率。
数学本质:
-
截断信号 = 原始信号 × 矩形窗(突然归零)。
-
矩形窗的频谱有无数旁瓣(类似“回声”),会污染真实频谱。
3. 窗函数如何解决泄漏?
窗函数的作用:让信号“温柔地开始,温柔地结束”
-
汉宁窗(Hann Window):两端平滑降到零,中间高。
-
相当于用手轻轻按住绳子两端,让它自然停止摆动,避免突然抖动。
-
结果:FFT频谱更干净,泄漏的能量被抑制。
-
汉宁窗原理
torch.hann_window(N_FFT)
的原理及示例说明
1. 汉宁窗(Hann Window)的作用
在短时傅里叶变换(STFT)中,直接对信号进行分帧并做FFT会产生频谱泄漏(Spectral Leakage),即能量扩散到邻近频率。汉宁窗的作用是减少频谱泄漏,使频谱更清晰。
汉宁窗的数学定义:
w[n]=0.5(1−cos(2πnN−1)),n=0,1,…,N−1w[n]=0.5(1−cos(N−12πn)),n=0,1,…,N−1
其中,NN 是窗口长度(N_FFT
)。
2. 代码解析
window = torch.hann_window(N_FFT).to(audio.device)
-
torch.hann_window(N_FFT)
:生成一个长度为N_FFT
的汉宁窗(值范围[0, 1]
)。 -
.to(audio.device)
:确保窗口和音频数据在同一个设备(CPU/GPU)上,避免计算错误。
3. 示例说明
假设 N_FFT = 8
,生成的汉宁窗如下:
import torch
N_FFT = 8
hann_window = torch.hann_window(N_FFT)
print(hann_window)
输出:
tensor([0.0000, 0.1883, 0.6113, 0.9505, 0.9505, 0.6113, 0.1883, 0.0000])
可视化:
n: 0 1 2 3 4 5 6 7 | | | | | | | | 0.0 0.188 0.611 0.950 0.950 0.611 0.188 0.0
-
窗口两端接近 0,中间接近 1,这样可以减少信号截断带来的频谱泄漏。
4. 汉宁窗如何影响STFT?
假设有一段音频信号 x
:
python
x = torch.tensor([1.0, 2.0, 3.0, 4.0, 3.0, 2.0, 1.0, 0.0]) # 假设是 8 个采样点
不加窗的FFT(直接计算):
python
stft_no_window = torch.fft.fft(x) print(torch.abs(stft_no_window))
输出(幅度谱):
tensor([16.0000, 6.8284, 4.0000, 2.8284, 0.0000, 2.8284, 4.0000, 6.8284])
加汉宁窗后的FFT:
windowed_x = x * hann_window # 信号加窗 stft_windowed = torch.fft.fft(windowed_x) print(torch.abs(stft_windowed))
输出(幅度谱):
tensor([ 7.6043, 3.5063, 1.0353, 0.3540, 0.0000, 0.3540, 1.0353, 3.5063])
对比分析:
-
不加窗:频谱能量分散,高频部分(如
6.8284
)较强,存在明显泄漏。 -
加汉宁窗:频谱更集中,高频分量(如
3.5063
)明显减弱,泄漏减少。
5. 为什么汉宁窗能减少频谱泄漏?
-
两端渐近于 0:减少信号截断带来的突变(Gibbs现象)。
-
平滑过渡:中间高、两端低的形状使频谱能量更集中在真实频率附近。
6. 实际应用(STFT)
在 torch.stft
中使用汉宁窗:
python
stft = torch.stft(audio, N_FFT, HOP_LENGTH, window=window, return_complex=True)
-
window=window
:对每一帧信号先加汉宁窗,再计算FFT,使频谱更准确。
数字信号处理的主要数学工具是傅里叶变换.而傅里叶变换是研究整个时间域和频率域的关系。不过,当运用计算机实现工程测试信号处理时,不可能对无限长的信号进行测量和运算,而是取其有限的时间片段进行分析。做法是从信号中截取一个时间片段,然后用截取的信号时间片段进行周期延拓处理,得到虚拟的无限长的信号,然后就可以对信号进行傅里叶变换、相关分析等数学处理。无限长的信号被截断以后,其频谱发生了畸变,原来集中在f(0)处的能量被分散到两个较宽的频带中去了(这种现象称之为频谱能量泄漏)。