当前位置: 首页 > news >正文

gr-filter 滤波与多速率模块完整源码分析

1. gr-filter 整体定位与功能分类

定位

gr-filter是 GNU Radio 的滤波与采样率变换核心包,负责:

  • FIR/IIR 滤波
  • 抽取/插值/有理数/任意比率重采样
  • 多相滤波器组(PFB)信道化
  • 滤波器系数设计(firdes
  • 通信专用成形滤波(RRC、高斯)

依赖

gnuradio-runtime → 块基类、调度 gr-fft → FFT 加速滤波、窗函数 gr-blocks → 部分辅助块 Volk → SIMD 卷积

功能分类(GRC 树)

类别代表块流程作用
FIR/IIR 滤波fir_filter_xxxiir_filter_xxxfft_filter_xxx抗混叠、信道选择、音频 LPF
多速率interp_fir_filterrational_resamplerpfb_arb_resampler改变采样率
PFB 架构pfb_channelizerpfb_decimator/interpolatorpfb_synthesizer高效多信道、多相抽取/插值
频移+滤波freq_xlating_fir_filterfreq_xlating_fft_filter下变频+滤波一体
系数设计firdesoptfirpm_remez离线/在线生成 taps
通信成形root_raised_cosine_filter、RRC/Gaussian taps脉冲成形、匹配滤波
简单滤波dc_blockersingle_pole_iirlow_pass_filterDC 消除、一阶平滑
其他hilbert_fcfilterbankmmse_resampler希尔伯特变换、滤波器组、分数插值

源码结构

gr-filter/ ├── include/gnuradio/filter/ # API + kernel 类(fir_filter, fft_filter, pfb_*) ├── lib/ # *_impl.cc + firdes.cc + pm_remez.cc ├── python/filter/ # PyBind11 + optfir.py + pfb.py └── grc/ # GRC 块定义

接口调用(总入口)

fromgnuradioimportfilter,gr,fft# 设计系数taps=filter.firdes.low_pass(gain=1.0,sampling_freq=fs,cutoff_freq=fc,transition_width=tw,window=fft.window.WIN_HAMMING)# 使用滤波器lpf=filter.fir_filter_fff(1,taps)# decim=1 普通 FIRtb.connect(src,lpf,dst)

2. FIR/IIR 滤波器底层源码实现

2.1 FIR 核心公式

离散卷积(FIR):

[
y[n] = \sum_{k=0}^{N-1} h[k] \cdot x[n-k]
]

传递函数:(H(z) = \sum_{k=0}^{N-1} h[k] z^{-k})

2.2 FIR 架构:Kernel + Block 两层

Kernel 类include/gnuradio/filter/fir_filter.h):纯算法,可被多块复用。

OUT_T filter(const IN_T input[]) const; void filterN(OUT_T output[], const IN_T input[], unsigned long n); void filterNdec(OUT_T output[], ..., unsigned int decimate);

Block 类fir_filter_blk_impl.cc):包装为 GNU Radio 块。

if (this->decimation() == 1) { d_fir.filterN(out, in, noutput_items); } else { d_fir.filterNdec(out, in, noutput_items, this->decimation()); }
  • decimation=1:普通 FIR
  • decimation>1:FIR + 抽取(每 D 点输出 1 点)
  • set_history(ntaps):保留历史样本供卷积

实现优化

  • taps反转存储(std::reverse)适配卷积方向
  • 多份对齐 tapsd_aligned_taps)处理非对齐输入
  • float/complex 走VOLK点积内核

2.3 IIR 核心公式

Direct Form I 差分方程(newstyle=false,与 scipy/MATLAB 一致):

[
y[n] + \sum_{k=1}^{M} a_k y[n-k] = \sum_{k=0}^{N} b_k x[n-k]
]

[
H(z) = \frac{\sum_{k=0}^{N} b_k z^{-k}}{1 + \sum_{k=1}^{M} a_k z^{-k}}
]

  • fftaps= 前馈系数 (b_k)
  • fbtaps= 反馈系数 (a_k)((a_0) 被忽略)

文件iir_filter_ffd_impl.cc→ kerneliir_filter<i,o,tap,acc>

2.4 firdes:FIR 系数设计

低通(窗函数法,firdes.cc):

理想低通冲激响应(sinc):

[
h[n] = \frac{\sin(2\pi f_c n / f_s)}{\pi n} \cdot w[n], \quad n \neq 0
]
[
h[0] = \frac{2 f_c}{f_s} \cdot w[0]
]

再归一化使 DC 增益 =gain

流程作用

场景用法
接收音频 LPFfir_filter_fff(decim, taps)
FM 去加重后音频滤波wfm_rcv中 FIR decim
抗混叠抽取前 LPF
IIR 去加重iir_filter_ffd(btaps, ataps)(gr-analog fm_emph 使用)

涉及语法

  • 三层模板fir_filter<IN_T, OUT_T, TAP_T>
  • sync_decimator(FIR+抽取)
  • Kernel/Block 分离
  • volk::vector对齐内存

接口调用

importgnuradio.fftasfftfromgnuradioimportfilter# 设计 + 使用taps=filter.firdes.low_pass(1.0,48000,5000,1000,fft.window.WIN_HAMMING)fir=filter.fir_filter_fff(1,taps)# 普通 FIRfir_decim=filter.fir_filter_fff(4,taps)# 4 倍抽取 FIR# IIR(来自 scipy 设计时 oldstyle=False)iir=filter.iir_filter_ffd(fftaps,fbtaps,oldstyle=False)# GRC 层次块(设计+滤波一体)lpf=filter.low_pass_filter(1,samp_rate,cutoff,transition,window)
#include<gnuradio/filter/fir_filter_blk.h>autofir=gr::filter::fir_filter_blk<float,float,float>::make(1,taps);

3. FFT 加速滤波原理与源码优化逻辑

3.1 原理:Overlap-Add / 频域卷积

时域卷积等价于频域相乘:

[
y[n] = x[n] * h[n] \Leftrightarrow Y[k] = X[k] \cdot H[k]
]

当 tap 数 (N) 较大时,FFT 法复杂度约 (O(N\log N)),优于直接卷积 (O(N \cdot L))。

3.2 关键参数(fft_filter.cc

d_ntaps = ntaps; d_fftsize = (int)(2 * pow(2.0, ceil(log(double(ntaps)) / log(2.0)))); d_nsamples = d_fftsize - d_ntaps + 1;
符号含义
d_ntaps滤波器阶数
d_fftsizeFFT 长度(≥ 2×ntaps,2 的幂)
d_nsamples每块有效输出样本数
d_tail块间重叠相加的“尾巴”

3.3 处理流程

  1. 预计算:对 taps 做 FFT →d_xformed_taps(乘 (1/N) 缩放)
  2. 每块处理
    • 输入d_nsamples点 + 零填充 → 长度d_fftsize
    • 正向 FFT → 与d_xformed_taps相乘(VOLK)
    • 逆向 IFFT
    • 加上上一块d_tail(overlap-add)
    • 输出前d_nsamples点,保存新 tail
volk_32fc_x2_multiply_32fc_a(c, a, d_xformed_taps.data(), ...); d_invfft->execute(); for (j = 0; j < tailsize(); j++) d_invfft->get_outbuf()[j] += d_tail[j]; ... memcpy(&d_tail[0], d_invfft->get_outbuf() + d_nsamples, ...);

3.4 何时用 FFT 滤波

  • tap 很长(数百~数千)时比 FIR 直接卷积更快
  • pfb_decimator可选use_fft_filters=True
  • freq_xlating_fft_filter结合频移

流程作用

广播/宽信道、高阶 LPF、大 tap 数信道化中的性能优化路径

接口调用

# FFT 滤波块(支持 decimation)fft_fir=filter.fft_filter_fff(decimation=4,taps=taps,nthreads=1)fft_fir_ccf=filter.fft_filter_ccf(decimation=1,taps=taps)

4. 抽取/插值滤波、多相滤波架构

4.1 插值 FIR(interp_fir_filter

公式:先插零再滤波,等价于多相实现。

插值 (L) 倍:输出采样率 (f_s’ = L \cdot f_s)

多相分解:原 taps (h[n]) 拆成 (L) 个子滤波器:

[
h_r[k] = h[r + kL], \quad r = 0,1,\ldots,L-1
]

每个输入样本依次通过 (L) 个子滤波器,产生 (L) 个输出。

继承sync_interpolator(1 输入 : L 输出)

4.2 有理数重采样(rational_resampler

采样率变换:

[
f_{out} = f_{in} \cdot \frac{L}{M}
]

(L)=interpolation,(M)=decimation。

多相 FIR 银行+ 计数器d_ctr

while ((i < noutput_items) && (count < ninput_items[0])) { out[i++] = d_firs[ctr].filter(in); ctr += this->decimation(); while (ctr >= this->interpolation()) { ctr -= this->interpolation(); in++; count++; } }
  • 每输入 1 点,按相位ctr选子滤波器输出
  • 无用户 taps 时自动用 Kaiser 窗设计 LPF(design_resampler_filter
  • std::gcd(L,M)约简降低复杂度

4.3 多相滤波器组(PFB)通用架构

核心思想:把原型滤波器 (H(z)) 分解为 (N) 个多相分支:

[
H(z) = \sum_{k=0}^{N-1} z^{-k} H_k(z^N)
]

作用
pfb_decimator_ccf(N) 路输入 → 选 1 路信道输出(抽取+选频)
pfb_interpolator_ccf1 路 → (N) 路(插值+合成)
pfb_channelizer_ccf宽输入 → 多窄带信道(FFT 信道化)
pfb_synthesizer_ccf多信道 → 宽输出(合成)

pfb_decimator还含复数旋转器 (e^{j2\pi k \cdot \text{chan}/N}) 选信道。

流程作用

ADC 高采样率 → [抽取 FIR] → 低采样率基带 音频 48k → [插值 FIR] → 240k 供 FM 调制 任意 L/M → [rational_resampler] → 统一采样率 宽频谱 → [pfb_channelizer] → 多路窄带信道

接口调用

# 插值interp=filter.interp_fir_filter_fff(interpolation=4,taps=taps)# 有理数重采样 48k → 44.1k 类场景rr=filter.rational_resampler_fff(interpolation=441,decimation=480,taps=[],fractional_bw=0.4)# PFB 抽取(8 选 1 信道)pfb_dec=filter.pfb_decimator_ccf(decim=8,taps=taps,channel=0)# PFB 插值pfb_int=filter.pfb_interpolator_ccf(interp=8,taps=taps)# PFB 信道化chan=filter.pfb_channelizer_ccf(numchans=8,taps=taps)

5. 任意重采样模块底层原理

块名pfb_arb_resampler_xxx
Kernelpfb_arb_resampler.cc

5.1 目标

实现任意比率重采样 (f_{out} = r \cdot f_{in}),(r) 为任意浮点数(如 1.037)。

5.2 原理:多相滤波器 + 线性插值

  1. 设滤波器组数 (N =)filter_size(即d_int_rate
  2. 整数部分:(D = \lfloor N/r \rfloor)
  3. 小数部分:(f = N/r - D)(d_flt_rate
  4. 每输出 1 点:
    • 用第 (j) 个子滤波器 FIR 得 (o_0)
    • 用差分滤波器得 (o_1)((H’(z)) 近似)
    • 线性插值:(y = o_0 + o_1 \cdot \text{acc})
    • 累加器d_acc按小数步进更新,溢出时推进输入
o0 = d_filters[j].filter(&input[i_in]); o1 = d_diff_filters[j].filter(&input[i_in]); output[i_out] = o0 + o1 * d_acc;

差分 taps 由[-1, 1]差分器作用于原型 taps 得到,用于子样本级插值。

5.3 与 rational_resampler 对比

rational_resamplerpfb_arb_resampler
比率有理数 L/M任意浮点 r
精度精确近似(插值)
复杂度较低较高(双滤波器组)

流程作用

  • 音频设备采样率不匹配(48000 ↔ 44100)
  • 符号时钟恢复后的分数重采样
  • 软件无线电中非标比率变换

接口调用

# 浮点 → 浮点,重采样到 1.2 倍arb=filter.pfb_arb_resampler_fff(rate=1.2,taps=taps,filter_size=32)# 复数arb_ccf=filter.pfb_arb_resampler_ccf(rate=0.8,taps=taps,filter_size=32)

6. 通信专用 RRC/升余弦、高斯滤波源码

设计入口firdes.cc+ GRC 变量块variable_rrc_filter_taps

6.1 根升余弦(RRC)

用途:发送端脉冲成形;接收端匹配滤波。发送+接收 RRC 级联 ≈ 升余弦,消除 ISI。

频域:滚降系数 (\alpha \in [0,1])

时域firdes::root_raised_cosine,(T_s = 1/\text{symbol_rate}),(spb = f_s \cdot T_s)):

[
h(t) = \frac{4\alpha}{\pi\sqrt{T_s}} \cdot
\frac{\cos((1+\alpha)\pi t/T_s) + \frac{\sin((1-\alpha)\pi t/T_s)}{4\alpha t/T_s}}
{1 - (4\alpha t/T_s)^2}
]

((t=0) 及分母为 0 处用极限值处理,见源码if (fabs(x3) >= 0.000001)分支。)

6.2 高斯滤波

用途:GFSK/MSK(如蓝牙、GSM)频谱成形,限制带外辐射。

公式firdes::gaussian):

[
h[n] = \exp\left(-\frac{1}{2}\left(\frac{s \cdot n \cdot T_s}{T_{sym}}\right)^2\right)
]

其中 (s = \frac{1}{\sqrt{\ln 2 / (2\pi^2 B T^2)}}),(BT) 为带宽-符号时间积(bt参数)。

6.3 升余弦(RC)

firdes也提供raised_cosine(非 root),用于理论分析或特殊链路;实际通信多用RRC 对

流程作用

比特流 → [RRC 成形 FIR] → 上变频 → 信道 ↓ 限制带宽、控制 ISI GFSK: 比特 → [高斯 FIR] → 频率调制

接口调用

# 直接设计 tapsrrc_taps=filter.firdes.root_raised_cosine(gain=1.0,sampling_freq=8e6,# 8 样点/符号symbol_rate=1e6,# 1 Mspsalpha=0.35,# 滚降ntaps=11*8)# 通常 8~16 倍 spbgauss_taps=filter.firdes.gaussian(gain=1.0,spb=8,bt=0.35,ntaps=4*8)# 使用rrc_fir=filter.fir_filter_fff(1,rrc_taps)# GRC 层次块rrc_blk=filter.root_raised_cosine_filter(gain=1.0,sample_rate=fs,symbol_rate=Rs,alpha=0.35,ntaps=101)# 优化设计(需 scipy)fromgnuradio.filterimportoptfir taps=optfir.low_pass(1,fs,passband,stopband,ripple,atten)

7. DC 消除、简单高低通滤波

7.1 DC Blocker(dc_blocker_ff_impl.cc

问题:IQ 接收机常有 DC 偏置,影响解调/频谱。

原理:(H(z) = \frac{1 - z^{-D}}{1 - z^{-D}/D}) 的滑动平均实现(近似高通,截止 (\approx f_s/(2\pi D)))。

短形式(long_form=False):

[
y[n] = x[n-D+1] - \text{MA}_2(\text{MA}_1(x[n]))
]

长形式:四级滑动平均 + 延迟线,阻带更深。

y1 = d_ma_0.filter(in[i]); y2 = d_ma_1.filter(y1); out[i] = d_ma_0.delayed_sig() - y2;

流程作用:USRP/IQ 接收最前端,解调之前。

7.2 单极点 IIR(single_pole_iir_filter_ff

一阶 IIR 低通:

[
y[n] = \alpha x[n] + (1-\alpha) y[n-1]
]

(\alpha) 越小,截止频率越低。

流程作用:极简平滑、慢变 DC 跟踪(比 dc_blocker 更简单)。

7.3 简单高低通(GRC 层次块 + firdes)

low_pass_filterhigh_pass_filterband_pass_filter等:

内部 =firdes.low_pass(...)+fir_filter_fff(1, taps)

低通 firdes 公式(见第 2 节 sinc × 窗)。

高通:频谱反转低通:

[
h_{HP}[n] = h_{LP}[n] \cdot (-1)^n \quad \text{(或等效频域变换)}
]

接口调用

# DC 消除dc=filter.dc_blocker_ff(D=32,long_form=True)# floatdc_c=filter.dc_blocker_cc(D=32,long_form=False)# complex# 单极点 IIR 低通iir1=filter.single_pole_iir_filter_ff(alpha=0.01)# 简单低通(设计+滤波一体)lpf=filter.low_pass_filter(gain=1.0,samp_rate=48000,cutoff_freq=5000,transition_width=1000,window=fft.window.WIN_HAMMING)hpf=filter.high_pass_filter(1.0,48000,200,500,fft.window.WIN_HAMMING)bpf=filter.band_pass_filter(1.0,48000,200,4000,500,fft.window.WIN_HAMMING)

总览:典型信号处理流程

发射链

比特

root_raised_cosine FIR

interp_fir_filter 上采样

上变频

接收链

USRP IQ

dc_blocker_cc

freq_xlating_fir_filter 或 mix+FIR

rational_resampler 或 pfb_arb

fir_filter 信道 LPF

解调器 gr-analog


语法知识汇总

语法/模式示例位置用途
三层模板<IN,OUT,TAP>fir_filter_blk,rational_resampler多类型支持
Kernel + Block 分离kernel::fir_filter+fir_filter_blk_impl算法复用
sync_decimator/interpolatorFIR decim, interp_fir固定比率多速率
block+general_workrational_resampler任意 consume/produce
多相 taps 分解rational_resampler, pfb_*高效多速率
VOLK SIMDfir_filter, fft_filter卷积加速
FFT overlap-addfft_filter.cc长 FIR 加速
set_history/set_relative_rate多速率块调度器配合
firdes静态设计类firdes.cc系数生成
pm_remez等波纹最优 FIR精确通带设计
std::gcd约简rational_resampler降低多相数
std::deque延迟线dc_blocker滑动平均

Python 快速参考

功能调用
设计 LPF tapsfilter.firdes.low_pass(gain, fs, fc, tw, window)
设计 RRCfilter.firdes.root_raised_cosine(gain, fs, sym_rate, alpha, ntaps)
设计高斯filter.firdes.gaussian(gain, spb, bt, ntaps)
FIR 滤波filter.fir_filter_fff(decim, taps)
IIR 滤波filter.iir_filter_ffd(b, a, oldstyle=False)
FFT FIRfilter.fft_filter_fff(decim, taps)
插值filter.interp_fir_filter_fff(L, taps)
有理重采样filter.rational_resampler_fff(L, M, taps, fractional_bw=0.4)
任意重采样filter.pfb_arb_resampler_ccf(rate, taps, filter_size=32)
PFB 信道化filter.pfb_channelizer_ccf(numchans, taps)
DC 消除filter.dc_blocker_cc(D, long_form)
频移+滤波filter.freq_xlating_fir_filter_ccc(center_freq, samp_rate, taps)

与 gr-analog / gr-blocks 的分工

模块职责
gr-filter滤波、多速率、系数设计、RRC/高斯
gr-analogFM/AM 调制解调,调用 gr-filter 做音频 LPF
gr-fftFFT 引擎、窗函数
gr-blocks基础数学、类型转换

例如wfm_rcv中:quadrature_demod_cf(analog)+fir_filter_fff(filter)+fm_deemph(analog 的 IIR)。

http://www.jsqmd.com/news/887430/

相关文章:

  • 在Ubuntu 18.04上搞定Anubis 2.3静态版:从下载、配置到跑通第一个GNSS数据质量分析
  • 高性能Windows流媒体服务器部署:5大核心技术与3种实战架构深度解析
  • modelscope v1.37.1 修复 trust_remote_code 兼容性问题:一次看懂 2026-05-22 最新补丁版全部更新
  • iPaaS 应用场景深度解析:从系统孤岛到数据自由流动的六大实战路径
  • Windows自带的硬盘医生:当移动硬盘提示0x80070570时,除了CHKDSK你还可以试试这些方法
  • i7-10850H 和 T2000 显卡 的 HP ZBook Fury 15 G7
  • 淘金币自动化脚本:5分钟完成所有淘宝任务的终极指南
  • 为什么92%的团队误判DeepSeek生成代码的安全性?——一份被封存的内部质量审计报告(限时公开)
  • 告别录屏软件!用Unity Recorder在编辑器内搞定游戏宣传片(附Timeline联动教程)
  • 拾亩绿光纯亚麻籽微粉哪里靠谱
  • 基于ATtiny85与JQ8900-16P的极简嵌入式音频播放系统设计与实现
  • (毕业必看)实测靠谱的AI论文软件,毕业党收藏备用
  • 低精度神经网络训练:LMD算法与MXFP6技术解析
  • 基于Arduino与ACS712的智能待机功耗控制方案设计与实现
  • 2026现阶段温州实木全屋定制优质公司联系全攻略 - 2026年企业推荐榜
  • Sora 2商用红线预警:版权溯源链构建指南(含AI生成视频DCI数字版权登记全流程)
  • 从零到一:在LUNIX系统上部署Anubis并进行GNSS数据质量分析
  • 2026-05-26:移除前缀使数组严格递增。用go语言,给定整数数组 nums,你可以从数组开头“删掉一段连续的前缀”(前缀长度可以为 0)。要求删除后剩下的部分必须是严格递增的(即剩余数组中任意相
  • 若依框架TagView切换总刷新?别慌,先检查这两个命名规则(附代码示例)
  • 2026年5月国内专业水泥电杆底盘供应商排行:高压水泥电线杆、高强度水泥电杆、高强度水泥电线杆、低压水泥电线杆选择指南 - 优质品牌商家
  • 为 Hermes Agent 框架配置自定义 Taotoken 模型提供商
  • 手把手教你用Python从Excel读取数据,完成K-Means聚类并画出酷炫3D散点图
  • 2026年5月行业观察:莆田可靠的LV鞋店价值评估与供应链选择 - 2026年企业推荐榜
  • 基于ATtiny85的智能烙铁定时器:低成本安全卫士DIY指南
  • 别扔!用吃灰的TP-LINK-WR703N做个无线打印服务器,保姆级刷机教程(含Breed+OpenWrt)
  • 避坑指南:在Docker容器里为OpenCV编译Nvidia GPU硬解码支持,我踩过的那些‘库版本’的坑
  • CodeGraph:给 Claude Code/Codex 装上“代码地图“,Token 直降 35%
  • 2026柴油流量计技术解析与主流产品实测对比:沥青液位计/沥青液位计/液碱流量计/液碱流量计/液碱液位计/液碱液位计/选择指南 - 优质品牌商家
  • 2026年Q2硝酸液位计靠谱品牌排行及实测对比:液碱液位计、液碱液位计、煤气流量计、煤气流量计、电磁流量计、电磁流量计选择指南 - 优质品牌商家
  • GCBasic驱动Arduino LCD扩展板:从引脚映射到传感器集成