模块总览块 / 类文件能力rational_resamplerrational_resampler_impl.cc有理数倍率 (L/M)interp_fir_filterinterp_fir_filter_impl.cc整数插值 (L)pfb_interpolator_ccfpfb_interpolator_ccf_impl.ccPFB 插值pfb_decimator_ccfpfb_decimator_ccf_impl.ccPFB 抽取 选信道pfb_channelizer_ccfpfb_channelizer_ccf_impl.cc多信道化pfb_arb_resampler_*pfb_arb_resampler.cc任意实数倍率mmse_resampler_*mmse_resampler_impl.cc符号同步 / 细粒度重采样polyphase_filterbankpolyphase_filterbank.ccPFB 公共基类firdes::low_passfirdes.cc抗混叠原型滤波器1. 采样率转换底层原理1.1 数学模型设输入采样率 (f_{s,in})目标 (f_{s,out})转换比[r \frac{f_{s,out}}{f_{s,in}} \frac{L}{M}]经典三阶段结构上采样 (L) 倍插入 (L-1) 个零 → 频谱压缩并产生 (L-1) 组镜像抗镜像/抗混叠 FIR截止频率 (\le \min(f_{s,in}/2,, f_{s,out}/2))下采样 (M) 倍每 (M) 点取 1 点Noble 恒等式多相实现的基础先插零再 FIR 再抽取等价于把原型 FIR (h[n]) 拆成 (L) 条多相支路每条只算“有效”样本计算量从 (O(N \cdot L)) 降到 (O(N))。GNU Radio 中rational_resampler把插值、滤波、抽取合成一步用多相 FIR 数组d_firs[L]实现。1.2 源码set_relative_rate与 GCD 化简auto d std::gcd(interpolation, decimation); // ... if (taps.empty()) { interpolation / d; decimation / d; staps design_resampler_filterTAP_T(interpolation, decimation, fractional_bw); } // ... this-set_relative_rate(uint64_t{ interpolation }, uint64_t{ decimation });set_relative_rate(L, M)告诉调度器每产出 (M) 个输出样本大约消耗 (L) 个输入样本general_work块用forecast精确估算。GCD 约分(48/32 \to 3/2)滤波器支路数从 48 降到 3显著省内存与 CPU。1.3general_work多相指针调度unsigned int ctr 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; } } d_ctr ctr;含义ctr当前使用的多相支路索引 (0 \ldots L-1)每输出 1 点ctr M当ctr L时输入前进 1 样本并ctr - L等价于在“虚拟”的 (L) 倍插值流上每 (M) 点取 1 点但只对非零相位做 FIR在信号链中的位置ADC 采样率与算法符号率不匹配时的粗对齐如 2 Msps → 1.28 Msps。1.4 涉及语法语法用途C 类模板rational_resamplerIN_T,OUT_T,TAP_T多类型实例化ccc/ccf/fff 等general_workforecast非固定 1:1 的blockreinterpret_cast无类型 buffer → 样本指针std::gcd有理数约分1.5 接口调用fromgnuradioimportfilter# L3, M2 → 输出率 输入率 × 3/2# taps 为空则自动设计 Kaiser 低通rrfilter.rational_resampler_ccc(interpolation3,decimation2,taps[],# 或自定义 tapsfractional_bw0.4# 自动设计时的通带比例)tb.connect(src,rr,sink)Cfilter::rational_resampler_ccc::make(3, 2, taps, 0.4f)。2. 抽取、插值抗混叠滤波源码逻辑2.1 理论为何要滤波操作风险滤波要求插值 (L)镜像出现在 (\pm k f_s/L)低通截止 (\le f_{s,out}/2)抽取 (M)频谱折叠混叠先低通至 (f_{s,out}/2)再抽点自动设计函数design_resampler_filter根据 (r L/M) 选过渡带float rate float(interpolation) / float(decimation); if (rate 1.0) { trans_width halfband - fractional_bw; // 扩采样防镜像 mid_transition_band halfband - trans_width / 2.0; } else { trans_width rate * (halfband - fractional_bw); // 降采样防混叠 mid_transition_band rate * halfband - trans_width / 2.0; } return firdes::low_pass(interpolation, interpolation, mid_transition_band, trans_width, fft::window::WIN_KAISER, beta);设计采样率取interpolation文档说明当 (L \ge M) 时滤波器工作在插值后的最高速率(L \cdot f_{s,in}) 上。2.2 原型 FIRfirdes::low_passint ntaps compute_ntaps(sampling_freq, transition_width, window_type, param); double fwT0 2 * GR_M_PI * cutoff_freq / sampling_freq; for (int n -M; n M; n) { if (n 0) taps[n M] fwT0 / GR_M_PI * w[n M]; else taps[n M] sin(n * fwT0) / (n * GR_M_PI) * w[n M]; // sinc × 窗 }理想低通冲激响应 (h_d[n] \frac{\sin(\omega_c n)}{\pi n})再乘 Kaiser 窗控制旁瓣。2.3 多相拆分install_taps插值 FIR 与有理重采样共用同一拆分逻辑for (int i 0; i (int)taps.size(); i) xtaps[i % nfilters][i / nfilters] taps[i];原型 (h[0], h[1], \ldots, h[N-1]) → 第 (k) 相(h[k], h[kL], h[k2L], \ldots)插值interp_fir_filter的 workfor (int i 0; i ni; i) { for (int nf 0; nf nfilters; nf) { out[nf] d_firs[nf].filter(in[i]); // 1 输入 → L 输出 } out nfilters; }继承sync_interpolator调度器已知输出是输入的 (L) 倍。2.4 PFB 抽取pfb_decimator_ccf输入经stream_to_streams分成 (M) 路相位 0…M-1每路进一条多相 FIR再旋转相加选出第 (k) 信道// y[i] Σ_{j0}^{M-1} x[j][i] · exp(2π j k / M) for (unsigned int j 0; j d_rate; j) { out[i] d_tmp[j * noutput_items i] * d_rotator[j]; }或用FFT代替显式复指数work_fir_fft计算 (O(M \log M)) 但 (M) 大时更高效。在链路中的位置发射符号流 →插值 RRC抗镜像接收高采样 IQ →抽取 低通抗混叠→ 符号同步2.5 Python 便捷封装自动 tapsgr-filter/python/filter/pfb.py中decimator_ccf/interpolator_ccf用optfir.low_pass生成覆盖 0.4 归一化带宽的原型滤波器并包装stream_to_streams。fromgnuradio.filterimportpfb# 8 倍抽取选第 0 信道自动设计 tapsdecpfb.decimator_ccf(decim8,channel0,atten100)interppfb.interpolator_ccf(interp4,atten100)3. 多相滤波组PFB核心源码解析3.1 基类polyphase_filterbankd_taps_per_filter ceil(ntaps / d_nfilts); for (i 0; i d_nfilts; i) { for (j 0; j d_taps_per_filter; j) { d_taps[i][j] tmp_taps[i j * d_nfilts]; // 多相分解 } d_fir_filters[i].set_taps(d_taps[i]); d_fft_filters[i].set_taps(d_taps[i]); // 可选 FFT 卷积 }每条支路一个kernel::fir_filter_ccfd_fft_filters供长滤波器 batch 处理。3.2 PFB 插值器while (i noutput_items) { for (unsigned int j 0; j d_rate; j) { out[i] d_fir_filters[j].filter(in[count]); i; } count; }1 个输入样本 → 依次通过 (L) 条多相 FIR → (L) 个输出。与interp_fir_filter数学等价接口与 PFB 家族一致。3.3 PFB 信道化器pfb_channelizer_ccf将宽带信号分成 (M) 个等带宽子信道每信道采样率 (f_s/M)。输入(M) 路 deinterleaved 流stream_to_streams每路多相 FIR →IFFT/FFT 旋转→ 输出 (M) 信道向量oversample_rate限制为 (N/i,, i \in [1,N])支持 fractional 信道化作用频谱监测、多载波并行解调、信道选择配合set_channel_map。3.4 底层 FIRkernel::fir_filterfloat fir_filterfloat,float,float::filter(const float input[]) const { volk_32f_x2_dot_prod_32f_a(..., ar, d_aligned_taps[al].data(), d_ntaps al); return d_output[0]; }taps 内部反转卷积 vs 相关VOLK对齐点积SIMD 加速filterNdec支持抽 decimate 步长的批量滤波3.5 涉及语法继承pfb_decimator_ccf_impl : sync_block, polyphase_filterbanksync_interpolator固定 (L:1) 输出比gr::thread::scoped_lock运行时set_taps线程安全set_history(nt)FIR 需要过去 (nt-1) 个样本4. 任意分数倍重采样实现机制GNU Radio 提供两条路径PFB 任意重采样宽带、带抗混叠和MMSE 重采样窄带、低延迟、适合符号同步。4.1pfb_arb_resampler多相 线性插值速率分解void pfb_arb_resampler_ccf::set_rate(float rate) { d_dec_rate (unsigned int)floor(d_int_rate / rate); // D floor(N/r) d_flt_rate (d_int_rate / rate) - d_dec_rate; // 小数部分 μ }(N )filter_size默认 32多相滤波器个数(D \lfloor N/r \rfloor)支路步进(\mu N/r - D)相邻两支路输出的线性插值权重差分滤波器导数支路diff_filter[0] -1; diff_filter[1] 1; for (i 0; i newtaps.size() - 1; i) { difftaps.push_back(newtaps[i1] - newtaps[i]); // 近似 dh/dn }输出[y \approx y_0 \mu \cdot \frac{dy}{dn}]其中 (y_0 h_j * x)(dy/dn) 来自差分 taps 的 FIR实现相邻多相滤波器之间的亚滤波器相位插值。核心循环while (j d_int_rate) { o0 d_filters[j].filter(input[i_in]); o1 d_diff_filters[j].filter(input[i_in]); output[i_out] o0 o1 * d_acc; d_acc d_flt_rate; j d_dec_rate (int)floor(d_acc); d_acc fmodf(d_acc, 1.0); } i_in (int)(j / d_int_rate); j j % d_int_rate;状态变量d_last_filter、d_acc跨work()调用保持连续。Block 包装int pfb_arb_resampler_ccf_impl::general_work(...) { int nitems floorf((float)noutput_items / relative_rate()); int processed d_resamp.filter(out, in, nitems, nitems_read); consume_each(nitems_read); return processed; }set_relative_rate(rate)声明非整数比forecast按noutput/rate估算输入需求。自动滤波器设计Pythonif(rate 1): halfband 0.5 * rate # 降采样截止 ∝ 输出 Nyquist return filter.firdes.low_pass_2(flt_size, flt_size, bw, tb, atten, ...) else: # 升采样防镜像halfband 0.54.2mmse_resamplerFarrow / MMSE 插值用于符号定时恢复输入率与输出率接近 1:1只需微调相位 (\mu)。while (idx_out noutput_items idx_in max_input_index) { out[idx_out] d_resamp.interpolate(in[idx_in], static_castfloat(d_mu)); d_mu d_delta_mu; idx_in static_castint(floor(d_mu)); d_mu - floor(d_mu); }d_delta_mu 重采样比输出/输入可 1 或 1mmse_fir_interpolator预存129 组FIRNSTEPS1(\mu) 量化到最近步进int imu (int)rint(mu * NSTEPS); return filters[imu].filter(input);支持第二路输入动态比率以及 PMT 消息改resamp_ratio/mu。4.3 两种任意重采样对比pfb_arb_resamplermmse_resampler典型 (r)任意如 2.5、0.73≈1 ± 小偏差抗混叠有完整 LPF弱短 MMSE FIR用途脉冲成形、速率匹配symbol_sync、Gardner 后微调延迟较大原型 FIR 群时延较小4.4 接口示例fromgnuradioimportfilter# 8000 → 20000 Hz等价 rate2.5rate20000.0/8000.0resampfilter.pfb.arb_resampler_ccf(rate,tapsNone,flt_size32)# 符号同步timing error 反馈到 resamp_ratiommsefilter.mmse_resampler_cc(phase_shift0.0,resamp_ratio1.0epsilon)5. 通信系统中重采样工程应用5.1 发射链成形 整数/任意上采样generic_mod_demod.py标准做法self.rrc_taps filter.firdes.root_raised_cosine( nfilts, nfilts, 1.0, self._excess_bw, ntaps) self.rrc_filter filter.pfb_arb_resampler_ccf( self._samples_per_symbol, self.rrc_taps)流程位置比特 → 映射 → 符号 → [pfb_arb_resampler sps] → USRP/DAC ↑ RRC 内置同时完成 sps 倍上采样RRC taps 按nfilts32为虚拟采样率设计见注释与 PFB 的 32 相结构匹配skiphead去掉 FIR 群时延引入的瞬态5.2 接收链多级速率变换典型接收机USRP (高 fs) → [可选 rational_resampler 或 pfb_decimator] 粗降到几 MHz → AGC / FLL → symbol_sync (内部 mmse_resampler_cc) 细调 TO → 判决粗匹配rational_resampler(3,2)或pfb_decimator_ccf细同步mmse_resampler_cc Gardner / PFB 时钟同步qa_pfb_clock_sync.py用pfb_arb_resampler做 RRC 匹配滤波5.3 分组 / 突发通信gr-digital/examples/packet/tx_stage6.grcburst_shaper → pfb_arb_resampler → fir_filter → USRP突发成形后按信道带宽重采样再经额外 FIR 整形。5.4 多载波 / 频谱分析fromgnuradio.filterimportpfb chpfb.channelizer_ccf(numchans8,oversample_rate2)8 路并行子信道每路 (f_s/8)用于多信号并行解调或窄带 DDC。5.5 工程选型建议场景推荐块(L/M) 固定有理数rational_resampler整数 (L) 上采样 自定义 tapsinterp_fir_filter或pfb.interpolator_ccf整数 (M) 下采样 选频pfb.decimator_ccf任意实数比 抗混叠pfb.arb_resampler_ccf符号时钟跟踪mmse_resampler_cc多信道并行pfb.channelizer_ccf5.6 完整 Python 流图示例参考gr-filter/examples/resampler.pyreratefs_out/fs_in tapsfilter.firdes.low_pass_2(32,32,0.25,0.1,80)self.resampfilter.pfb.arb_resampler_ccf(rerate,taps,flt_size32)self.connect(src,head,self.resamp,sink)语法知识汇总层级知识点GNU Radio 块模型sync_block/sync_interpolator/general_workforecastconsume_eachC 模板rational_resamplerIN_T,OUT_T,TAP_T多类型导出Kernel 层kernel::fir_filter、kernel::pfb_arb_resampler_*可被 block 复用Pythonfilter.pfb.*hier_block2 包装firdes/optfir设计 taps性能VOLK SIMD、set_output_multiple批量对齐线程安全scoped_lockd_updated延迟重装 taps小结GNU Radio 多速率处理的统一思想是用Noble 恒等式把“插零→FIR→抽取”折叠成多相 FIR 阵列 指针调度有理数倍用rational_resampler的ctr状态机任意实数倍用pfb_arb_resampler的 (N/D) 步进 差分线性插值符号级微调用mmse_resampler的 (\mu) accumulator。抗混叠/抗镜像由firdes::low_pass或 Pythonpfb.create_taps按 (r) 与 Nyquist 约束自动或手动设计。