最近视频号有个清华老哥天天站黑板面前讲信号处理:
(我一看这不就是科普版,这真实干活不瞎眼了),赶紧在路上怒写一个完整版的 SINC 函数奉献给社会!!!希望大家看开心~
从数学角度看 sinc 函数
两种常用定义
数学定义
信号处理常用的“归一化 sinc”
归一化的好处:零点刚好落在整数点 ,非常适合“在整数点做插值”的场景(比如 那一类)。
实线:
虚线:,整体形状一样,只是沿 x 轴拉伸/压缩了一点。
基本形状与性质
中间有一个“主瓣”,在 处取值 1;往两边衰减,并出现正负交替的“旁瓣”。在未归一化定义下,零点在 ;在归一化定义下,零点刚好在 。
数学性质:
极限存在且为 1(用洛必达法则)
所以我们定义 sinc(0)=1 是连续的。
偶函数
因为 ,分子分母都变号。
振荡衰减当 , 始终在 [-1,1] 内,而分母 变大:
所以尾巴按 衰减。
积分与能量
这是很多傅里叶积分里经常出现的结果。 对于归一化 sinc,
这像一个“单位面积核”,在建模里很有用(卷积核、插值核)。
从“信号与系统”的视角看 sinc
理想低通滤波器:矩形频响 ↔ sinc 冲激响应
在经典连续时间傅里叶变换的约定下,矩形频域 ↔ sinc 时域 是一对标准变换对:
频域:理想低通滤波器
时域:冲激响应(我用归一化 sinc 写得好看一点)
下张图看到的就是一个以 t=0 对称、像 sinc 的脉冲:中间最高,往两边有无限长的振荡尾巴。
任何一个 LTI 系统都可以用“冲激响应 h(t)”来描述;理想低通的冲激响应恰好是 sinc,所以 “用理想低通滤波信号 = 用 sinc 和信号做卷积”。
重要现实问题:这个 sinc 冲激响应 无限长(从 到 );而且左右对称,非因果(t<0 也有响应);这意味着理想低通滤波器物理上不可实现,我们只能在数学上把它当作极限模型,现实里必须用“有限长度 & 近似”的滤波器来逼近它(FIR 窗函数设计就是这么来的)。
采样定理:sinc 是“完美插值核”
香农采样定理讲的是:
若连续时间信号 带宽有限(带限到 Hz),且以采样频率 采样,则原信号可以用无限长 sinc 插值精确重构。
最经典的公式(用归一化 sinc):
其中 ,且
翻译成人话:每一个采样点 在连续时间上对应一个以 为中心的 sinc“脉冲”;所有这些 sinc 叠加在一起,刚好把原信号拼出来;
在采样点处 :
由于 当 是非零整数,且 ,所以只有 这一项保留下来,完美“插值通过采样点”。(也就是示波器的时域波形的插值由来,我记忆是之前写过的)
蓝色实线:原本连续信号(两路低频正弦叠加)。
圆点:按一定采样频率取的离散点。
虚线:用 sinc 插值公式重构出来的连续曲线。
由于我选的是“确实带限且采样频率足够高”的例子,重构曲线和原曲线是重合的(几乎看不出两条线)。
这就是 sinc 在信号与系统里最经典、最核心的角色:理想插值核 和 理想低通滤波核 是同一个东西,只是换了一个场景。
从数学建模角度怎么用 sinc?
可以把 sinc 看成是一种“核函数(kernel)”,类似于高斯核、三角核,只是形状不同。几个典型的建模思路:
连续信号/场的插值与重构
给定一串样本值 ,我们希望构造一个连续函数 :
这就是“基函数展开”:每个样本点乘一个“基函数”再加起来。
当 时,这个展开在带限信号假设下是严格无失真的;其它常见选择还有 B 样条、高斯、Lanczos(其实就是多项 sinc 的组合)等,往往是“牺牲一点精度,换取局部性和更好数值特性”。
从建模角度看:sinc 模型对应的是“带限 + 无噪声 + 无限长度核”这一理想假设,这提供了一个基准;现实系统达不到,就设计各种近似核去逼近这个理想。
有限长度 sinc 与窗函数(FIR 滤波器设计)
理想低通的冲激响应是 sinc,但它太长,不可实现;常用操作:截断 + 加窗:
从无限长的 sinc 中截出一个长为 的对称窗口:
乘上一个窗函数 (Hamming, Blackman 等):
这样我们得到一个有限长 FIR 滤波器,其频响逼近矩形低通,但有一点通带波纹、阻带衰减有限;从最原始的观点来看,这整个设计流程就是:
拿 sinc 当“原型”,再做有限化和修饰。
在很多 “矩形开口”/“有限长度窗” 的问题里,sinc 都会蹦出来:时域里,对信号乘上一个有限时长的矩形窗(只观察一小段时间),其频域多了一个 sinc 形状的卷积核 → 这就是频谱泄漏的根源;总之谁有矩形谁就有 sinc,不是在时域就是在频域/空间频域。
(恭喜读者可以看到这里,在信号与系统的功力已经有鄙人的百分之五了,hhhh)
上面的文章已经把 SINC 这个函数的本体说差不多了,但是最终我们还是要应用的,在之前 FFT 的窗的文章已经写过了,但是无妨,基础知识常写常新,以及 SINC 的故事还没有结束。
好,那我们就接着刚才的 sinc,从“窗函数 + 时宽带宽积 ≈ 常数”这条线,把信号与系统和数学建模串起来。
你刚看到的几组图分别是:
-
连续时间:矩形窗 w(t) 和它的频率响应 |W(f)|(典型 sinc) -
离散时间:Rect / Hann / Blackman 三种窗在时域、频域的对比 -
用窗函数加权截断 sinc 设计 FIR 低通滤波器的幅频响应
下面我分三块讲:
窗函数的本质:时域乘窗 = 频域卷积
离散时间场景里,设原信号/理想冲激响应为 ,窗函数为 ,则
其 DTFT(离散时间傅里叶变换)满足:
也就是:
时域相乘 → 频域卷积
在 FIR 设计里:
:通常是理想低通的 sinc 冲激响应(无限长)
:我们选定的窗函数(有限支持 N 点)。
:真正实现的 FIR 系统冲激响应。
:就是我们得到的近似低通滤波器的频率响应。
在时域,用窗函数“剪掉”了 sinc 的两端(截断+平滑);在频域,把理想的矩形频响 跟窗函数频响 做卷积:所以矩形不再是完美的直上直下了,边缘被抹圆,带来了过渡带和旁瓣。
矩形窗:最简单的窗函数,让“时宽带宽积”直观可见
连续时间:矩形 ↔ sinc
我们定义一个宽度为 的矩形窗:
它的傅里叶变换是(采用 f 作为频率):
图里看到的时域是扁扁的一块,频域是一个以 0 为中心的 sinc 形状。
零点位置:
第一对零点在 ;主瓣宽度(从负第一零点到正第一零点)约为 。
于是我们可以很自然地定义:
时间宽度:
频率主瓣宽度:
那么:
如果你一个定义(比如半宽度、0.5 幅值点等)常数会稍微变一下,但都体现同一个现象:
在时间上截得越短(T 越小),频域主瓣越宽;在时间上留得越长(T 越大),频域越集中。 时宽 × 带宽 ≈ 常数,这就是“时宽带宽积”/不确定性原理的直观版本。
归一化与“积为一”的说法
如果想写得“刚好等于 1”,可以通过简单的归一化来做到。
例如,把变量换成无量纲形式:令 ,则矩形窗写成 ,支持区间长度为 1:;对应的频域变量用 ,则频响应是 ,其主瓣宽度约 。如果再把“带宽定义的一半”或者使用某个对称定义(比如取 ),就可以人为地把“时宽 × 带宽”调整成 1。这就是很多教材里说的那种“合适定义下的时宽带宽积为 1”的感觉,本质是尺度归一化的问题。
从建模角度我们更关注的是: 无论你怎样缩放,只要你压缩了时间,就必然拉宽频谱;整体面积保持不变;这个可以用连续时间傅里叶变换的缩放性质来精确表达。
缩放性质 + 数学建模:为什么“越短越宽,越长越窄”
假设 与其傅里叶变换 是一对变换对:
对任意非零实数 ,有缩放性质:
若 :时间轴压缩(信号变化更快),频谱拉宽;
若 :时间轴拉长(信号变化更慢),频谱收窄。
把矩形窗看成 ,即 ,可以把 ,那么
本质结论是:
“时宽带宽积为常数”是傅里叶缩放性质的直接体现,矩形窗 + sinc 刚好是非常直观的一对例子。
离散时间窗函数频谱:Rect / Hann / Blackman 对比
三种窗的数学定义(长度 N)
设 为窗长,
矩形窗(Rect)
汉宁窗(Hann)
Blackman 窗
对应的 DTFT:
在代码里我用
W = exp(-1j * outer(w_axis, k)) @ w
直接算出了连续频率轴上的频响。
时域形状 vs 频域特性
从频域图你能看到:
Rect 窗:主瓣最窄(过渡带最陡),但旁瓣最高(频谱泄漏严重,约 -13dB)。
Hann 窗:主瓣稍宽一点,旁瓣大幅降低(约 -31dB)。
Blackman 窗:主瓣更宽,但旁瓣压得更低(约 -58dB)。
这就是窗函数设计的核心 trade-off:
想要频域旁瓣低,就要让时域窗“边缘更平滑”(更“宽”); 想要频域主瓣窄,就要让时域窗“更集中、更接近矩形”。 换句话说,就是把“有限长度的时宽”如何分配给“主瓣宽度”和“旁瓣高度”的问题。
用窗函数修饰 sinc 设计 FIR 低通:一个完整建模思路
刚才的最后一组图就是这一块:sinc + 窗。
理想低通的离散冲激响应
在离散时间域,目标是一个理想低通滤波器,频率响应:
其理想(无限长)冲激响应(采样的 sinc)是:
我在代码里用归一化 sinc 写成:
wc = 0.4 * np.pi
M = (N - 1) // 2
m = np.arange(-M, M+1)
h_ideal = (wc/np.pi) * sinc_norm((wc/np.pi) * m)
其中 sinc_norm(x) = sin(pi x)/(pi x)。
有限长度约束:乘以窗函数
由于实际 FIR 必须是有限长 N(这里 N=51),我们只能取:
在图里看到:用 Rect 窗:时间上是“截断的 sinc”,频域有明显旁瓣。
用 Hann/Blackman:时间上头尾逐渐收敛到 0,频域旁瓣压下去,但主瓣拓宽(过渡带变宽)。
数学建模:优化意义
如果严肃一点看,可以把 FIR 设计写成一个优化问题:
决策变量:冲激响应 (或者窗权系数 )。
目标:尽量逼近理想频响 ,例如最小化平方误差:
约束:
支持长度有限: for n outside ;或者要求线性相位、对称性 等;甚至可以添加“时宽-带宽积”的约束,如控制过渡带宽度、旁瓣级别等。
窗函数法实际上是一个非常工程化、简化版的解法:先写出“满足频率形状”的无约束解 (无限长 sinc);再用一个选好的窗 把它截断成有限长,使其满足实现约束;窗的形状、长度 N 就隐含地决定了“带宽(主瓣宽度)”和“旁瓣抑制”之间的权衡—实际上就是在“时宽带宽积 ~ 常数”的约束下,调节频谱的分布。
Python 仿真源码
import numpy as np
import matplotlib.pyplot as plt
# ============================================
# 1. 连续时间:矩形窗 <-> sinc 频响
# ============================================
# 时域矩形窗
T = 1.0 # 窗宽
t = np.linspace(-1.5, 1.5, 2000)
rect_t = np.where(np.abs(t) <= T/2, 1.0, 0.0)
# 频域响应:W(f) = T * sinc_norm(f T)
def sinc_norm(x):
y = np.ones_like(x)
nz = x != 0
y[nz] = np.sin(np.pi * x[nz]) / (np.pi * x[nz])
return y
f = np.linspace(-10, 10, 4000)
Wf = T * sinc_norm(f * T)
plt.figure(figsize=(6,4))

plt.plot(t, rect_t)
plt.title('连续时间矩形窗 w(t)')
plt.xlabel('t')
plt.ylabel('w(t)')
plt.grid(True)
plt.tight_layout()
plt.show()
plt.figure(figsize=(6,4))
plt.plot(f, np.abs(Wf))
plt.title('矩形窗的幅频响应 |W(f)|(sinc 形状)')
plt.xlabel('频率 f')
plt.ylabel('|W(f)|')
plt.grid(True)
plt.tight_layout()
plt.show()
# ============================================
# 2. 离散时间:不同窗函数的频谱(长度 N)
# ============================================
N = 51
n = np.arange(N)
# 三种窗函数
w_rect = np.ones(N)
w_hann = 0.5 - 0.5 * np.cos(2*np.pi*n/(N-1))
w_blackman = 0.42 - 0.5*np.cos(2*np.pi*n/(N-1)) + 0.08*np.cos(4*np.pi*n/(N-1))
# 频率轴(归一化 rad/samp)
w_axis = np.linspace(-np.pi, np.pi, 4096)
def dtft(w):
# 计算离散时间傅里叶变换(零相位对齐)
k = np.arange(len(w))
W = np.exp(-1j * np.outer(w_axis, k)) @ w
return W
W_rect = dtft(w_rect)
W_hann = dtft(w_hann)
W_blackman = dtft(w_blackman)
plt.figure(figsize=(6,4))
plt.plot(n, w_rect, label='Rect')
plt.plot(n, w_hann, label='Hann')
plt.plot(n, w_blackman, label='Blackman')
plt.title('三种长度 N=51 的窗函数(时域)')
plt.xlabel('n')
plt.ylabel('w[n]')
plt.grid(True)
plt.legend()
plt.tight_layout()
plt.show()
plt.figure(figsize=(6,4))
plt.plot(w_axis, 20*np.log10(np.abs(W_rect)/np.max(np.abs(W_rect)) + 1e-12), label='Rect')
plt.plot(w_axis, 20*np.log10(np.abs(W_hann)/np.max(np.abs(W_hann)) + 1e-12), label='Hann')
plt.plot(w_axis, 20*np.log10(np.abs(W_blackman)/np.max(np.abs(W_blackman)) + 1e-12), label='Blackman')
plt.title('三种窗函数的归一化幅频响应 (dB)')
plt.xlabel('归一化角频率 ω')
plt.ylabel('幅度 (dB)')
plt.ylim(-120, 5)
plt.grid(True)
plt.legend()
plt.tight_layout()
plt.show()
# ============================================
# 3. 用窗函数设计 FIR 低通:sinc * window
# ============================================
# 目标:理想低通截止频率 wc(归一化 rad/samp)
wc = 0.4 * np.pi
M = (N - 1) // 2
m = np.arange(-M, M+1)
# 理想低通冲激响应(截断 sinc)
h_ideal = (wc/np.pi) * sinc_norm((wc/np.pi) * m)
# 用三种窗加权
h_rect = h_ideal * w_rect
h_hann = h_ideal * w_hann
h_blackman = h_ideal * w_blackman
def freq_response(h):
k = np.arange(len(h))
H = np.exp(-1j * np.outer(w_axis, k)) @ h
return H
H_rect = freq_response(h_rect)
H_hann = freq_response(h_hann)
H_blackman = freq_response(h_blackman)
plt.figure(figsize=(6,4))
plt.stem(m, h_ideal, basefmt=" ")
plt.title('理想低通冲激响应(截断 sinc)')
plt.xlabel('n')
plt.ylabel('h_ideal[n]')
plt.grid(True)
plt.tight_layout()
plt.show()
plt.figure(figsize=(6,4))
plt.plot(w_axis, 20*np.log10(np.abs(H_rect) / np.max(np.abs(H_rect)) + 1e-12), label='Rect 窗')
plt.plot(w_axis, 20*np.log10(np.abs(H_hann) / np.max(np.abs(H_hann)) + 1e-12), label='Hann 窗')
plt.plot(w_axis, 20*np.log10(np.abs(H_blackman) / np.max(np.abs(H_blackman)) + 1e-12), label='Blackman 窗')
plt.axvline(wc, linestyle='--')
plt.axvline(-wc, linestyle='--')
plt.title('用窗设计的 FIR 低通滤波器幅频响应 (N=51)')
plt.xlabel('归一化角频率 ω')
plt.ylabel('幅度 (dB)')
plt.ylim(-120, 5)
plt.grid(True)
plt.legend()
plt.tight_layout()
plt.show()
import numpy as np
import matplotlib.pyplot as plt
# 1. Basic sinc vs normalized sinc
x = np.linspace(-10, 10, 2000)
def sinc_math(x):
y = np.ones_like(x)
nz = x != 0
y[nz] = np.sin(x[nz]) / x[nz]
return y
def sinc_norm(x):
y = np.ones_like(x)
nz = x != 0
y[nz] = np.sin(np.pi * x[nz]) / (np.pi * x[nz])
return y
y1 = sinc_math(x)
y2 = sinc_norm(x)
plt.figure(figsize=(6,4))
plt.plot(x, y1, label='sinc(x) = sin(x)/x')
plt.plot(x, y2, linestyle='--', label='sinc_norm(x) = sin(πx)/(πx)')
plt.axhline(0, linewidth=0.8)
plt.axvline(0, linewidth=0.8)
plt.xlim(-10, 10)
plt.ylim(-0.3, 1.2)
plt.legend()
plt.title('数学 sinc 与 归一化 sinc 对比')
plt.xlabel('x')
plt.ylabel('幅度')
plt.grid(True)
plt.tight_layout()
plt.show()
# 2. Ideal low-pass filter: rectangular in freq -> sinc in time
t = np.linspace(-1, 1, 2000)
B = 5 # Hz
# 连续时间理想低通冲激响应: h(t) = 2B * sinc(2Bt)
arg = 2 * B * t
h = np.ones_like(t) * 2 * B
nz = arg != 0
h[nz] = 2 * B * np.sin(np.pi * arg[nz]) / (np.pi * arg[nz])
plt.figure(figsize=(6,4))
plt.plot(t, h)
plt.axhline(0, linewidth=0.8)
plt.axvline(0, linewidth=0.8)
plt.title('理想低通滤波器冲激响应 = sinc 形状')
plt.xlabel('时间 t (s)')
plt.ylabel('h(t)')
plt.grid(True)
plt.tight_layout()
plt.show()
# 3. Sampling and sinc reconstruction demo
fs = 20.0 # 采样频率
T = 1/fs
t_cont = np.linspace(0, 1, 2000)
# 带限信号:两个正弦叠加,频率都在 Nyquist 以下
x_cont = np.sin(2*np.pi*3*t_cont) + 0.6*np.sin(2*np.pi*5*t_cont)
# 采样
n = np.arange(0, int(1/T))
t_samp = n * T
x_samp = np.sin(2*np.pi*3*t_samp) + 0.6*np.sin(2*np.pi*5*t_samp)
# 用 sinc 插值重构:
# x_rec(t) = sum x[n] sinc((t/T) - n)
x_rec = np.zeros_like(t_cont)
for k, xk in zip(n, x_samp):
x_rec += xk * sinc_norm(t_cont / T - k)
plt.figure(figsize=(6,4))
plt.plot(t_cont, x_cont, label='原连续信号')
plt.scatter(t_samp, x_samp, marker='o', label='采样点')
plt.plot(t_cont, x_rec, linestyle='--', label='sinc 重构信号')
plt.xlabel('时间 t (s)')
plt.ylabel('幅度')
plt.title('采样与 sinc 插值重构示意')
plt.grid(True)
plt.legend()
plt.tight_layout()
plt.show()