3.1 信号变换与多速率信号处理


3.1 信号变换与多速率信号处理

本节摘要:本节建立两个贯穿全书信号处理的工具直觉:傅里叶变换把"信号是什么频率组成"这个问题变成可计算的矩阵运算;多速率处理(抽取与内插)让数字系统可以在不同采样率之间自如换挡。RTL-SDR 从 2.048 MSPS 原始数据到 48 kHz 音频的旅程,就是一条典型的多速率流水线。

为什么先讲"变换"

拿到一串 I/Q 样本,最自然的追问是"这里面有什么"。时域看是杂乱的波形,人眼无法直接读出频率成分;傅里叶变换把这串样本投影到一族正弦基上,输出"每个频率占多少能量"的列表。换个说法:时域与频域是同一份数据的两张脸,变换就是转脸的动作。1965 年 Cooley 与 Tukey 的快速算法把计算量从平方量级降到对数量级——对百万点序列,这意味着从"小时"到"毫秒"的差距,频谱分析因此才从实验室特权变成人人可用的工具。

在你的实验里,FFT 是使用频率最高的操作,没有之一:看频谱用它,调增益用它,校频偏用它,识别调制还用它。第 4 章的 FM 解调虽然不靠 FFT,但判断"信号是否在中心、带宽是否合适"全靠它开路。

DFT 的直觉:一组相关运算

离散傅里叶变换(DFT)对每个候选频率 k 做一件事:把 N 个样本分别乘上一个频率为 k 的复指数,再求和。信号里恰好含有该频率成分时,乘积的同相部分互相累加,和很大;不含时,正负相消,和接近零。所以 DFT 输出的第 k 个点的模,就是"样本序列与第 k 个频率的相关程度"。这段描述对应到代码就是几行向量运算:

import numpy as np N = 1024 n = np.arange(N) x = 0.7 * np.exp(1j * 2 * np.pi * 50 * n / N) # 一个频率位于第 50 个 bin 的复正弦 k = np.arange(N) # 手工 DFT:矩阵形式,与 numpy.fft 结果一致(误差在浮点范围内) manual = np.abs(x @ np.exp(-1j * 2 * np.pi * np.outer(n, k) / N)) builtin = np.abs(np.fft.fft(x)) print("手工与库函数最大差异:", np.abs(manual - builtin).max()) # 约 1e-9 量级

跑一遍这个对照实验,"FFT 是黑盒"的感觉会消失大半:它没有任何魔法,只是把上面的矩阵乘法用巧妙的分治结构省算力。频谱的频率刻度也由此确定:第 k 个 bin 对应频率为采样率乘 k 再除以 N,第 3.3 节画频谱图时坐标轴就是这么来的。

频率分辨率同样由这条公式给出:分辨率等于采样率除以 FFT 点数。想分辨相距 5 kHz 的两个信号,在 2.048 MSPS 下至少需要 410 点;实践中取 1024 到 8192 点是常见区间——点数越多分辨率越高,但时间响应越慢,瀑布图的更新越迟钝。

抽取:把采样率降下来

RTL-SDR 以 2.048 MSPS 吐样本,但 FM 解调后只剩 48 kHz 的音频——中间发生了什么?答案是逐级抽取(decimation):保留需要的频带、丢弃带外成分、每 M 个样本取一个。顺序至关重要:先低通滤波再丢样本,滤波器挡住了带外能量,丢样本才不会引入混叠;反过来先丢后滤,带外噪声会折叠进带内,无法挽回。

噪声账也要算:每级抽取让总噪声功率按带宽比例缩小,而信号功率不变,于是信噪比提升。从 2.048 MHz 抽取到 48 kHz,带宽缩小约 42 倍,理论上信噪比改善约 16 dB——这就是为什么解调前总是先降到信号本来的带宽:带宽越窄,进来的噪声越少。第 6 章的滤波实战会把这个账算得更细。

图:抽取与内插的多速率流水线结构

图:抽取与内插的多速率流水线结构

内插:把采样率升上去

内插(interpolation)是抽取的镜像操作:在样本之间补零把速率抬上去,再用低通滤波把补零造成的镜像压掉、把阶梯状的波形抹平滑。声卡重采样、发射波形成形都靠它。工程上抽取与内插常组合成"有理数速率变换":先 L 倍内插再 M 倍抽取,即可实现 L 比 M 的任意速率比——把 48 kHz 音频重采到 44.1 kHz,用的就是 147 比 160 的组合。

一个完整的小实验

把抽取的概念落到代码:对第 2 章采集的样本做"滤波加抽取",观察噪声底变化。

import numpy as np import matplotlib.pyplot as plt from scipy.signal import firwin, lfilter raw = np.fromfile("strong_signal.iq", dtype=np.uint8).astype(np.float32) - 127.5 iq = (raw[0::2] + 1j * raw[1::2]) / 128.0 # 2.048 MSPS 复数样本 # 设计 96 阶低通 FIR,通带 200 kHz,用于抽取前的抗混叠 taps = firwin(96, 200e3 / (2.048e6 / 2)) filtered = lfilter(taps, 1.0, iq) decimated = filtered[::8] # 8 倍抽取,降到 256 kSPS def psd_db(x, fs): spec = np.abs(np.fft.fftshift(np.fft.fft(x[:65536]))) ** 2 f = np.fft.fftshift(np.fft.fftfreq(65536, 1 / fs)) return f, 10 * np.log10(spec / 65536) f1, p1 = psd_db(iq, 2.048e6) f2, p2 = psd_db(decimated, 256e3) plt.plot(f1/1e6, p1, alpha=0.6, label="2.048 MSPS 原始") plt.plot(f2/1e6, p2, label="抽取后 256 kSPS") plt.xlabel("频率 MHz"); plt.ylabel("功率谱密度 dB"); plt.legend(); plt.show()

对比两条曲线:抽取后的噪声底整体抬高约 9 dB(10 乘 log10 的 8 倍带宽比),但每赫兹的总噪声积分反而下降——单位带宽的信噪比变好了。看懂这张图,你就看懂了"窄带接收灵敏度更高"的全部数学。

常见问题

问题:抽取比是不是越大越好?

不是。抽取降低数据速率与算力负担,但抽取太狠会把信号本身的边带也切掉——比如对 200 kHz 的 FM 信号做 16 倍抽取(只剩 128 kHz 视野)就会削掉边带导致失真。原则:抽取后的带宽仍是目标信号带宽的 1.2 倍以上。

问题:DFT 与 FFT 是什么关系?

DFT 是数学定义,FFT 是计算 DFT 的高效算法,结果完全一致。就像"从北京到上海"是需求、高铁是实现——你总用 FFT,但理解 DFT 的定义才能理解频率刻度、泄漏这些现象从哪来。

问题:多速率处理在真实系统里用在哪?

无处不在:手机音频链路 48 kHz 与 44.1 kHz 的换算、SDR 从 2.048 MSPS 到 48 kHz 音频的全程、数字电视从 30 MSPS 到信道解码的逐级降速。第 5 章流图里的 Rational Resampler 块就是它的标准件形态。

本节要点回顾

  • 傅里叶变换是相关运算:FFT 只是省算力的实现,频率刻度等于采样率除以点数。
  • 分辨率公式:采样率除以 FFT 点数,点数与时间响应是一对取舍。
  • 抽取顺序铁律:先低通后丢样本;内插反之,先补零后滤波。
  • 带宽与灵敏度挂钩:带宽缩 8 倍,单位带宽信噪比提升约 9 dB。

下一节把采样定理本身讲透:采样率到底怎么选,欠采样时频谱如何折叠成你意想不到的样子。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U