Hann Window and hamming window

他们都同属于升余弦家族,只是常数不一样。

注意,所以不管是hann还是hamming都在处相等。

hann

标准写法

中心对称写法

什么是窗函数的中心对称

其实这两个写法是等价的,只是第二种把“对称中心”给显式写出来了

定义:一个长度为的窗函数$\omegai是中心对称的,指的是它关于中点i_c =\frac{N-1}{2}左右镜像相等\omega[i_c+k]=\omega[i_c -k]也就是说把这个函数画出来,沿着轴i_c$,左右完全一样。

这里就会出现两种情况:

  • N为奇数
  • N为偶数

N为奇数

中点则为结果是一个整数;
这里以为例,得出
则对应关系为:
w[0]<->w[6]
w[1]<->w[5]
w[2]<->w[4]
w[3]和自己相对,自己是中心

N为偶数

中点则为结果是个小数以结尾;
这里以举例,
则对应关系为:
w[0]<->w[7]
w[1]<->w[6]
w[2]<->w[5]
w[3]<->w[4]

所以这个并不是随便写的,而是偶数长度时中心点落在两个采样点之间的自然结果

代码演示

我们可以用代码来验证一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False


fig, axes = plt.subplots(1, 2, figsize=(12, 4))

for ax, N in zip(axes, [7, 8]):
i = np.arange(N)
w = 0.5 - 0.5 * np.cos(2 * np.pi * i / (N - 1))
ax.plot(i, w, 'o-', color='steelblue')
ax.axvline((N - 1) / 2, color='red', linestyle='--', label=f'对称轴 i={(N-1)/2}')
ax.set_title(f'N={N}({"奇数" if N%2 else "偶数"})')
ax.set_xlabel('i')
ax.set_ylabel('w[i]')
ax.grid(alpha=0.3)
ax.legend()

plt.tight_layout()
plt.show()

最常见的Hann窗的写法是:

当然也可以写成:

从公式中看不出“对称中心”在哪,因为余弦是从扫到的对称轴在中间。

对称

我们首先定义为相对中心的偏移。

则原式为:

  • x的范围为:,关于0对称
  • 是偶函数则
  • 所以关于对称,也就是关于对称

当 时:

当时:

综上所述的作用就是把余弦的对称中心从平移到窗的中点

hamming

和Hann只差一个常数:

上面说过hann和hamming的中心处都等于1,所以中心对称的写法:

hamming两端不为0,时为了让窗函数在边界处的一阶不连续变小,从而压低第一旁瓣。

时域和频域的对比

时域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False


N = 64
n = np.arange(N)

w_hann = 0.5 - 0.5 * np.cos(2 * np.pi * n / (N - 1))
w_hamm = 0.54 - 0.46 * np.cos(2 * np.pi * n / (N - 1))

plt.figure(figsize=(10, 4))
plt.plot(n, w_hann, 'o-', label='Hann', markersize=4)
plt.plot(n, w_hamm, 's--', label='Hamming', markersize=4)
plt.title('Hann vs Hamming 时域 (N=64)')
plt.xlabel('n')
plt.ylabel('w[n]')
plt.legend()
plt.grid(alpha=0.3)
plt.show()

频域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

N = 64
n = np.arange(N)

w_hann = 0.5 - 0.5 * np.cos(2 * np.pi * n / (N - 1))
w_hamm = 0.54 - 0.46 * np.cos(2 * np.pi * n / (N - 1))

nfft = 8192
W_hann = np.fft.fftshift(np.fft.fft(w_hann, nfft))
W_hamm = np.fft.fftshift(np.fft.fft(w_hamm, nfft))

f = np.arange(nfft) - nfft//2
f = f / (nfft / N)

W_hann_dB = 20 * np.log10(np.abs(W_hann) / np.max(np.abs(W_hann)) + 1e-12)
W_hamm_dB = 20 * np.log10(np.abs(W_hamm) / np.max(np.abs(W_hamm)) + 1e-12)

plt.figure(figsize=(10, 6))
plt.plot(f, W_hann_dB, label='Hann', linewidth=2)
plt.plot(f, W_hamm_dB, '--', label='Hamming', linewidth=2)

plt.xlim(-5, 5)
plt.ylim(-100, 5)

plt.title('Hann vs Hamming 频谱包络对比 (N=64)')
plt.xlabel('归一化频率 (单位: 原始 bin 间距)')
plt.ylabel('幅度 (dB)')
plt.grid(alpha=0.3)
plt.legend()
plt.tight_layout()
plt.show()

总结

hann是”近端稍差,远端好”;Hamming是”近端好,远端差”

场景

  • Hann
    • 一般谱分析,要求远端旁瓣干净
    • 需要窗两端严格为0(重叠相加、滤波器设计)
    • 经典FFT谱分析常用Hann
  • Hamming
    • 要求第一旁瓣极低,容忍远端旁瓣
    • 语音处理、音频分析(STFT)常用Hamming

经验

  • 关心邻近强信号泄露->Hamming(第一旁瓣低)
  • 关心宽带噪声底、远端泄露->Hann(旁瓣衰减快)
  • 不确定时,Hann更为通用