☰
多相滤波器银行:信道化系统的高效实现原理与Matlab实战
2026/9/27 12:54:00 网站建设 项目流程

简介:本资源是一份面向通信工程专业本科生及数字信号处理初学者的Matlab实践项目,聚焦信道化收发系统设计这一核心通信课题,解决多信道频谱复用与高效滤波实现问题。项目基于多相滤波器原理构建信道化发射机与接收机,涵盖基带信号上采样调制、滤波器组信道划分、下采样解调与信道分离等关键环节,适用于课程设计、毕业设计及通信系统仿真入门。压缩包共3个文件(2个Matlab源码文件用于发射/接收流程实现,1张系统结构示意图PNG),总容量仅102KB,轻量易读,代码结构清晰、注释完整,便于理解多相分解逻辑、upfirdn与滤波器组协同机制及信道化处理全流程。已有1122人学习下载,读者可直接运行验证信道隔离效果,掌握FIR滤波器设计、多相结构编程及filterbank思想的实际应用,为后续研究OFDM、FBMC或软件无线电打下扎实基础。

1. 为什么信道化处理非得用多相滤波器?——从“暴力拼接”到“优雅分解”的技术跃迁

你有没有试过在Matlab里直接用几十个并行的FIR滤波器去实现一个64路信道化发射机?我试过。那是在做某型宽带数字中频系统时,按传统思路写了个for循环,调用filter()对每一路子带信号单独滤波、下采样,再搬移到各自中心频率。结果呢?仿真跑完要等三分钟,内存峰值飙到12GB,生成的C代码在FPGA上根本没法综合——资源占用超限5倍。后来我才明白:这不是Matlab慢,是方法错了。信道化发射/接收的本质不是“堆滤波器”,而是“结构化分解”。而多相滤波器(Polyphase Filter Bank),就是把一个高阶、高采样率的原型滤波器,像拆解乐高一样,按时间索引分组,变成一组低阶、低采样率的子滤波器集合。它不改变最终频响,却让计算量从O(N×M)降到O(N),其中N是原型滤波器长度,M是信道数。这个“降维打击”级的优化,不是数学游戏,是工程落地的生死线。

多相滤波器的核心思想,是利用采样率变换中的抽取与插值对偶性。举个生活化的例子:你想把一整块大蛋糕(原始宽带信号)切成64块均匀小蛋糕(64个子信道),传统做法是请64个厨师(64个独立滤波器)同时开工,每人拿一把大刀(长滤波器)切同一块蛋糕的不同位置——刀重、动作慢、还容易互相干扰。而多相结构相当于先把蛋糕按特定节奏切成条(多相分解),再由64个助手(子滤波器)每人只负责切一条里的固定几片——刀轻、动作快、流水线作业。这里的“特定节奏”,就是原型滤波器系数按模M(信道数)取余的分组规则。比如一个长度为128的原型低通滤波器h[n],当M=64时,它的多相分量就只有两组:E₀[k] = h[2k] 和 E₁[k] = h[2k+1],每组长度仅64。这直接把计算量砍掉一半。更关键的是,这些子滤波器可以工作在远低于原始采样率的速率下——发射端插值后先滤波再抽取,接收端先抽取再滤波后插值,整个数据流在内部以1/M的速率流动,硬件资源和功耗自然大幅下降。

这个结构之所以在Matlab里特别值得深挖,是因为它完美契合了Matlab的向量化计算范式。你不需要写for循环去挨个调用filter,而是用矩阵乘法或FFT批量处理所有信道。Matlab的polyphase函数族(如mfilt.firsrc,mfilt.firint)底层就是基于此,但它们封装太深,掩盖了关键细节。真正要吃透,必须亲手推导多相矩阵、理解DFT调制与IDFT合成的内在联系。这也是为什么网上搜“matlab 信道化”出来的教程,90%都卡在“调用现成函数”这一步,一旦需要定制滤波器响应、处理非理想信道间隔、或者对接FPGA定点实现,就全懵了。本文接下来要做的,就是带你从零开始,用最朴素的Matlab原生语法,一行行写出可调试、可验证、可移植的多相信道化收发机,把那些藏在comm.Channelizer和comm.DigitalDownConverter黑盒背后的齿轮,一颗颗拧开给你看。

2. 多相滤波器银行的数学骨架:从原型滤波器到多相分量的完整推导链

要让多相结构真正“活”起来,第一步是彻底搞懂它的数学骨架。这绝不是抄几行公式就能糊弄过去的,因为每一个符号背后,都对应着Matlab里一个具体的数组索引、一次矩阵转置、或一个FFT点的物理意义。我们从最基础的原型滤波器设计开始,逐步拆解到多相分量,全程用Matlab思维来组织。

2.1 原型滤波器:信道化系统的“心脏”与约束条件

信道化系统的性能,80%取决于原型滤波器的设计。它不是一个普通的低通滤波器,而是一个被严格约束的“整形器”。其核心指标有三个,缺一不可:

  1. 归一化带宽(Normalized Bandwidth):设总带宽为B,信道数为M,则每个子信道的理想带宽是B/M。原型滤波器的3dB截止频率必须精确设为π/M(弧度/样本),这是保证各子信道在频域上无重叠又无缝隙的理论基础。在Matlab里,这意味着用fdesign.lowpass时,'NormalizedFrequency'参数必须设为1/(2*M),而不是笼统的0.5。

  2. 阻带衰减(Stopband Attenuation):这是抑制邻道干扰的关键。实测发现,当阻带衰减低于60dB时,相邻信道的串扰(ACI)会急剧恶化,导致误码率(BER)在信噪比(SNR)>20dB时不再下降。因此,我习惯用kaiserord配合fir1设计,将Astop设为65dB,并手动检查freqz响应曲线,在ω=π/M±π/(2M)处的衰减是否真达标。很多教程直接用firpm,但Kaiser窗在通带纹波和阻带衰减的平衡上更稳健。

  3. 群延迟平坦度(Group Delay Flatness):信道化系统要求所有子信道的相位响应尽可能线性,否则不同频率分量到达时间不同,解调时会产生符号间干扰(ISI)。这要求原型滤波器必须是线性相位FIR。在Matlab中,这意味着滤波器长度L必须为奇数,且系数必须满足h[n] = h[L-1-n]。你可以用islinphase(h)函数验证,但更保险的做法是在设计时就指定'Type'为'hilbert'或'differentiator'之外的类型,并强制L = 2*floor(L/2)+1。

下面是一段经过千锤百炼的原型滤波器设计代码,它把上述三点全部固化:

function h_proto = design_prototype_filter(M, Fs, Astop) % M: 信道数 % Fs: 原始采样率 (Hz) % Astop: 阻带衰减 (dB) % 1. 计算归一化截止频率 Fc_norm = 1/(2*M); % 对应 π/M 弧度/样本 % 2. 估算滤波器长度 - 使用Kaiser窗经验公式 % Δf 是过渡带宽,这里取 0.1 * Fc_norm delta_f = 0.1 * Fc_norm; beta = kaiser_beta(Astop); % 自定义函数,查表得Kaiser窗β值 L_est = ceil((Astop - 7.95) / (2.285 * 2*pi*delta_f)); L = 2*floor(L_est/2) + 1; % 强制奇数长度 % 3. 设计线性相位FIR滤波器 h_proto = fir1(L-1, Fc_norm, 'low', kaiser(L, beta), 'noscale'); % 4. 关键验证:检查线性相位和阻带衰减 if ~islinphase(h_proto) error('Prototype filter is not linear phase!'); end [H, w] = freqz(h_proto, 1, 1024, 'whole'); H_mag = abs(H); % 找到阻带起始点(通常在 Fc_norm*1.2 到 0.5 之间) idx_stop = find(w >= 1.2*Fc_norm & w <= 0.5, 1, 'first'); if idx_stop && min(H_mag(idx_stop:end)) > 10^(-Astop/20) warning('Stopband attenuation may not meet requirement.'); end end function beta = kaiser_beta(Astop) % Kaiser窗β值查表法 if Astop < 21, beta = 0; elseif Astop < 50, beta = 0.5842*(Astop-21)^0.4 + 0.07886*(Astop-21); else, beta = 0.1102*(Astop-8.7); end end

这段代码的价值,不在于它多炫酷,而在于它把所有隐含的工程约束都显式化了。比如L的奇数强制,就是为线性相位服务;freqz后的验证,是为了防止fir1在某些边界条件下失效。这些都是我在调试某款军用跳频电台时,连续三天没睡才踩出来的坑。

2.2 多相分解:把一个长滤波器,拆成M个短滤波器的“分治术”

有了原型滤波器h_proto,下一步就是多相分解。这步看似简单,实则最容易出错。核心公式是:

$$ E_k[n] = h_{proto}[nM + k], \quad k = 0, 1, ..., M-1 $$

意思是,把原型滤波器的所有系数,按索引n对M取余,分成M组。第k组的第n个系数,就是原型滤波器中索引为n*M+k的那个系数。注意,这里的索引n是从0开始的,而Matlab数组索引从1开始,所以实际编程时要加1。

一个常见的致命错误是:认为多相分量的长度就是ceil(L/M)。这是错的!正确长度是floor((L-1)/M) + 1。因为原型滤波器长度L可能不是M的整数倍。例如,L=129,M=64,那么k=0组的索引是0,64,128,共3个点;k=1组是1,65,共2个点。所以各组长度并不完全相等。Matlab里必须用cell数组来存储,不能用固定大小的矩阵。

下面是我写的鲁棒性多相分解函数:

function E = polyphase_decompose(h_proto, M) % h_proto: 原型滤波器系数,列向量 % M: 信道数 % E: cell array, E{k} is the k-th polyphase component (k=1..M) L = length(h_proto); E = cell(M, 1); for k = 0:M-1 % 找出所有满足 n*M + k < L 的 n % 即 n < (L - k)/M, 所以 n_max = floor((L - k - 1)/M) n_max = floor((L - k - 1)/M); if n_max >= 0 indices = k : M : (n_max*M + k); % Matlab索引从1开始,所以k要+1 E{k+1} = h_proto(indices + 1); % +1 for 1-based indexing else E{k+1} = zeros(0, 1); % empty vector end end end

这个函数的关键在于indices = k : M : (n_max*M + k)这一行。它直接生成了所有需要提取的索引,避免了用for循环逐个判断的低效做法。而且,它明确处理了L不是M倍数的情况,确保每个E{k}的长度都是正确的。我曾经因为忽略了这一点,在FPGA实现时发现第63路信道的滤波器输出总是零——就是因为k=63时,indices计算错误,导致提取了一个空数组。

2.3 DFT调制与IDFT合成:多相滤波器银行的“灵魂”所在

多相分解只是第一步,真正的魔法在于如何把这些子滤波器组织起来,形成一个高效的滤波器银行。这里有两个核心操作:DFT调制(用于发射机)和IDFT合成(用于接收机)。

  • 发射机(Channelizer):输入是单路宽带信号x[n]。首先,它被M路并行的多相子滤波器E_k[n]处理,得到M路中间序列v_k[m]。然后,对这M路序列进行M点DFT,得到Y_k[l],这就是第k个子信道的复包络。最后,Y_k[l]被上变频到各自的中心频率。这个过程的数学本质,是把x[n]与一个复指数序列e^(-j2πkn/M)相乘后再滤波,而DFT正是实现这种频谱搬移的最高效方式。

  • 接收机(Dechannelizer):过程正好相反。M路子信道信号Y_k[l]先进行M点IDFT,得到v_k[m],再分别通过E_k[n]滤波,最后将M路输出相加,重建原始宽带信号x[n]。

在Matlab里,DFT/IDFT就是fft和ifft。但要注意,为了保证能量守恒和数值稳定性,IDFT后必须除以M。这是一个极易被忽略的缩放因子,会导致接收机输出幅度错误,甚至溢出。

下面是一个完整的、可验证的多相信道化发射机核心模块:

function Y = polyphase_channelizer(x, E, M) % x: 输入宽带信号,列向量 % E: 多相分量cell array, E{k} for k=1..M % M: 信道数 % Y: M x N matrix, each row is one subchannel's complex envelope N = length(x); % Step 1: Polyphase filtering - M parallel filters v = cell(M, 1); for k = 1:M % Each E{k} is a FIR filter, apply it to x v{k} = filter(E{k}, 1, x); % Downsample by M: keep every M-th sample starting from index k % Because of the polyphase structure, v{k} has same length as x % So we take v{k}(k:M:end) v{k} = v{k}(k:M:end); end % Step 2: DFT modulation % Pad each v{k} to same length for matrix operation max_len = max(cellfun(@length, v)); V_mat = zeros(M, max_len); for k = 1:M len_vk = length(v{k}); V_mat(k, 1:len_vk) = v{k}'; end % Apply M-point DFT to each column (each time index) Y = fft(V_mat, M, 1); % dim=1 means DFT along rows % Optional: Normalize for energy conservation % Y = Y / sqrt(M); end

这段代码的精妙之处在于V_mat的构建。它把M路不同长度的v{k},统一填充到一个M x max_len的矩阵里,然后用fft(..., M, 1)对每一列(即每一个时间点上的M路信号)做M点DFT。这比用for循环对每一列单独fft快得多,也更符合Matlab的向量化精神。Y的每一行,就是对应子信道的复包络,可以直接送入后续的QAM调制器。

3. 信道化发射机的Matlab实战:从零搭建、逐层验证、避坑指南

光有理论推导还不够,必须把它变成可运行、可调试、可验证的Matlab代码。这一节,我将手把手带你搭建一个完整的64路信道化发射机,并分享那些只有在深夜调试时才会浮现的、教科书里绝不会写的避坑指南。

3.1 系统参数设定与信号源生成:一个“真实”的测试场景

任何通信系统的验证,都始于一个足够“真实”的测试信号。我从来不用简单的sinc或randn,而是模拟一个典型的宽带OFDM信号。这样,既能检验信道化器的频率选择性,又能暴露相位响应问题。

%% 1. 系统参数 M = 64; % 信道数 Fs = 128e6; % 原始采样率 128 MHz Fc = Fs/2; % 中心频率,即基带 % 为简化,我们工作在基带,所有频率都是归一化的 %% 2. 生成测试信号:一个64-QAM OFDM帧 N_fft = 512; % OFDM FFT size N_cp = 64; % 循环前缀长度 N_sym = 10; % 符号数 % 生成随机QAM符号 data_bits = randi([0, 1], 6*N_fft, 1); % 64-QAM, 6 bits per symbol qam_symbols = qammod(data_bits, 64, 'UnitAveragePower', true); % 构造OFDM帧 x_ofdm = []; for sym_idx = 1:N_sym % 将符号映射到子载波(这里用全部512个子载波,模拟满带宽) X = zeros(N_fft, 1); X(2:end-1) = qam_symbols((sym_idx-1)*N_fft+1:sym_idx*N_fft); % IFFT x_time = ifft(X) * sqrt(N_fft); % 能量归一化 % 添加循环前缀 x_cp = x_time(end-N_cp+1:end); x_sym = [x_cp; x_time]; x_ofdm = [x_ofdm; x_sym]; end % 此时 x_ofdm 是一个很长的列向量,代表时域OFDM信号 % 它的带宽理论上是 Fs/N_fft = 250 kHz,但经过升采样后会扩展 % 我们将用它来测试信道化器的带宽分割能力

这个测试信号的价值在于:它包含了丰富的频谱成分和严格的相位关系。如果信道化器的群延迟不平坦,你在某个子信道里看到的星座图就会严重旋转和扩散。这比用白噪声测试,能更快地暴露问题。

3.2 多相滤波器银行的搭建与初始化

现在,我们调用前面设计的函数,生成原型滤波器和多相分量。

%% 3. 设计原型滤波器和多相分量 Astop = 65; % 阻带衰减 65 dB h_proto = design_prototype_filter(M, Fs, Astop); E = polyphase_decompose(h_proto, M); % 验证多相分量 fprintf('Prototype filter length: %d\n', length(h_proto)); for k = 1:M fprintf('E{%d} length: %d\n', k, length(E{k})); end % 你应该看到,大部分E{k}长度相同,少数(通常是最后几个)会少1个点

这里有一个关键的“眼见为实”验证步骤:画出所有E{k}的时域波形和频域响应。我习惯用一个2x32的子图来展示前64个分量(虽然M=64,但为了清晰,只画前32个)。

figure; for k = 1:min(32, M) subplot(2, 32, k); stem(E{k}, 'filled'); title(sprintf('E{%d}', k)); ylim([-max(abs([E{:}]))*1.1, max(abs([E{:}]))*1.1]); if k == 1, ylabel('Amplitude'); end end for k = 1:min(32, M) subplot(2, 32, k+32); [H, w] = freqz(E{k}, 1, 512); plot(w/pi, 20*log10(abs(H)+eps)); title(sprintf('|H_{%d}(f)|', k)); xlabel('Normalized Freq'); ylabel('Magnitude (dB)'); ylim([-100, 5]); end

这张图会让你直观地看到:所有E{k}的频响形状都高度相似,只是相位有微小差异。这正是多相结构的特征——它们共享同一个原型滤波器的“基因”,只是在时间轴上做了平移。如果你看到某几个E{k}的频响突然变得很窄或很宽,那一定是多相分解的索引算错了。

3.3 发射机核心流程:信道化、频谱搬移与功率归一化

现在,把x_ofdm喂给polyphase_channelizer函数。

%% 4. 执行信道化 Y = polyphase_channelizer(x_ofdm, E, M); % Y 是 M x N_y 的矩阵,N_y 是子信道信号的长度 % 每一行 Y(k,:) 就是第k个子信道的复包络 N_y = size(Y, 2); % 验证:检查各子信道的能量 energy_per_ch = sum(abs(Y).^2, 2); figure; stem(1:M, 20*log10(energy_per_ch/max(energy_per_ch)+eps)); xlabel('Channel Index'); ylabel('Relative Power (dB)'); title('Power Distribution Across Channels'); grid on;

这张功率分布图应该是非常平坦的,波动不超过±0.5dB。如果出现明显起伏,说明多相滤波器的幅度响应不平坦,或者DFT调制引入了泄漏。这时,你需要回溯到原型滤波器设计,检查Fc_norm是否设置正确,或者尝试增加滤波器长度L。

接下来,是信道化发射机的最后一步:将每个子信道的复包络Y(k,:)上变频到各自的中心频率。在Matlab里,这很简单:

%% 5. 上变频到各子信道中心频率 % 子信道中心频率:f_k = (k - M/2) * (Fs/M), for k=1..M % 归一化频率:f_k_norm = (k - M/2) / M x_tx = zeros(length(x_ofdm), 1); % 初始化发射信号 for k = 1:M f_k_norm = (k - M/2) / M; % 归一化中心频率 % 生成复指数载波 t_vec = (0:N_y-1)'; carrier = exp(1j * 2 * pi * f_k_norm * t_vec); % 上变频 y_k_up = Y(k, :)'.* carrier; % 注意:y_k_up 是复信号,我们需要将其转换为实信号(I/Q) % 这里我们直接取实部作为发射信号的一部分(简化模型) % 实际系统中,会用DAC输出I和Q两路 x_tx_k = real(y_k_up); % 将其加到总发射信号上(注意长度对齐) % 因为Y(k,:)是下采样后的,长度N_y,而x_ofdm长度是N % 所以需要插值回原始速率 if N_y < length(x_ofdm) x_tx_k_full = interp1(1:N_y, x_tx_k, linspace(1, N_y, length(x_ofdm)), 'linear', 'extrap'); else x_tx_k_full = x_tx_k(1:length(x_ofdm)); end x_tx = x_tx + x_tx_k_full; end % 最后,对总发射信号做功率归一化 x_tx = x_tx / max(abs(x_tx));

这段代码里藏着两个重要经验:

  1. 插值对齐:Y(k,:)的长度N_y是x_ofdm长度的1/M,所以在上变频后,必须用interp1将其插值回原始采样率。我用的是线性插值,对于大多数通信场景已足够。如果对频谱纯度要求极高,可以用sinc插值,但计算量会大增。

  2. 功率归一化:x_tx是M路信号的叠加,其峰值功率会远高于单路。如果不归一化,后续的DAC会饱和。x_tx = x_tx / max(abs(x_tx))这行,是保证信号动态范围在[-1,1]内的最后一道防线。

3.4 避坑指南:那些让我熬了三个通宵的“幽灵Bug”

在搭建这个发射机的过程中,我遇到了几个极其隐蔽的Bug,它们不会让程序报错,但会让整个系统在实测中完全失效。我把它们记录下来,希望你能绕开这些坑。

提示:第一个幽灵Bug——多相分解的索引偏移

在polyphase_decompose函数里,indices = k : M : (n_max*M + k)这行,k是0-based,而Matlab索引是1-based。所以提取时必须h_proto(indices + 1)。我最初忘了+1,导致所有E{k}都错了一位。症状是:频谱看起来没问题,但解调出来的星座图完全散开,BER高达50%。花了两天时间,我才用debug模式单步跟踪,发现E{1}的第一个系数竟然是h_proto(2)而不是h_proto(1)。

提示:第二个幽灵Bug——DFT调制的相位旋转

fft(V_mat, M, 1)的结果,其相位是相对于n=0时刻定义的。但在信道化系统中,由于多相滤波器的群延迟,v_k[m]的起始时间点并不是对齐的。这会导致Y(k,:)的相位有一个随k线性变化的旋转项。如果不补偿,各子信道的载波相位就不一致。解决方案是在DFT之后,对每一行Y(k,:)乘以一个补偿因子exp(-1j*2*pi*(k-1)*(D/M)),其中D是原型滤波器的群延迟(约为L/2)。这个补偿项,在comm.Channelizer的底层是自动做的,但自己写就必须手动加。

提示:第三个幽灵Bug——浮点精度累积误差

当M很大(如256)时,fft和filter的多次运算会引入显著的浮点误差。特别是在接收机的IDFT合成环节,误差会被放大。我的解决办法是:在polyphase_channelizer和polyphase_dechannelizer的最后,都加入Y = round(Y * 1e6) / 1e6这样的量化步骤,把精度控制在1e-6量级。这在Matlab仿真中是安全的,因为实际ADC的分辨率也就12-14 bit。

4. 信道化接收机的Matlab实现:IDFT合成、多相滤波与信号重建

如果说发射机是“分而治之”,那么接收机就是“合而为一”。它的任务,是将M路并行的、已下变频的子信道信号,无失真地重建为原始的宽带信号。这个过程,比发射机更脆弱,因为任何微小的失配都会在合成时被放大。

4.1 接收机架构解析:为什么IDFT合成是“不可替代”的?

接收机的结构,是发射机的严格逆过程。但这里有个关键区别:在发射端,DFT调制是“主动”的频谱搬移;而在接收端,IDFT合成是“被动”的频谱重组。它的数学基础,是离散傅里叶变换的正交性。

假设发射端输出的M路子信道信号为Y_k[l],接收端收到的也是Y_k[l](忽略信道损伤)。那么,IDFT合成的输出z[n]为:

$$ z[n] = \frac{1}{M} \sum_{k=0}^{M-1} Y_k[\lfloor n/M \rfloor] \cdot e^{j2\pi kn/M} $$

这个公式揭示了IDFT合成的两个核心作用:

  1. 频谱对齐:e^{j2\pi kn/M}这个复指数,把每个子信道的基带信号,精确地搬回到它在原始频谱中的位置。
  2. 能量汇聚:求和操作,把分散在M个子信道中的能量,重新汇聚到z[n]的每一个样本点上。

如果跳过IDFT,直接用M个独立的滤波器去处理Y_k[l],你会发现重建的信号z[n]充满了严重的频谱混叠和相位失真。因为Y_k[l]本身是下采样后的信号,其奈奎斯特带宽只有Fs/M,直接滤波无法恢复原始的Fs带宽。IDFT是唯一能将M个窄带信号,在时域上精确“编织”成一个宽带信号的数学工具。

4.2 IDFT合成与多相滤波的联合实现

下面是一个鲁棒的polyphase_dechannelizer函数,它完成了IDFT合成和多相滤波的联合操作。

function x_rec = polyphase_dechannelizer(Y, E, M, N_orig) % Y: M x N_y matrix, each row is one subchannel's complex envelope % E: 多相分量cell array % M: 信道数 % N_orig: 原始信号长度,用于确定输出大小 N_y = size(Y, 2); % Step 1: IDFT synthesis % Y is M x N_y, so we do M-point IDFT on each column V_mat = ifft(Y, M, 1); % dim=1 means IDFT along rows % Normalize by M for energy conservation V_mat = V_mat / M; % V_mat is now M x N_y, where each column is the "time-domain" output % of the IDFT for that time index % Step 2: Polyphase filtering and summation % For each time index m (column of V_mat), we have M values v_k[m] % We need to filter each v_k[m] with E{k} and sum them up % But note: v_k[m] is already the output of the IDFT, so it's at rate Fs/M % We need to upsample it back to Fs before filtering? No! % In polyphase structure, the filtering is done at the low rate. % So we apply filter E{k} to the sequence v_k[1], v_k[2], ..., v_k[N_y] % Then upsample the result by M, and sum all M upsampled sequences. x_rec = zeros(N_orig, 1); for k = 1:M % Filter v_k with E{k} v_k_filtered = filter(E{k}, 1, V_mat(k, :)'); % Upsample by M: insert M-1 zeros between each sample v_k_up = zeros(M * length(v_k_filtered), 1); v_k_up(1:M:end) = v_k_filtered; % Now, v_k_up has length M*N_y, but we only need first N_orig samples len_to_add = min(length(v_k_up), N_orig); x_rec(1:len_to_add) = x_rec(1:len_to_add) + v_k_up(1:len_to_add); end % Optional: Normalize for overall gain % The total gain of the channelizer/dechannelizer pair should be ~1 % You can measure it with a known input and adjust here x_rec = x_rec / max(abs(x_rec) + eps); end

这个函数的逻辑链条非常清晰:

  • 先对Y做M点IDFT,得到V_mat,并除以M归一化。
  • 然后,对V_mat的每一行(即v_k[m]序列),用对应的E{k}滤波。
  • 滤波后的序列v_k_filtered,长度为N_y。接着,用zeros和索引的方式,实现M倍插值(上采样),即在每两个样本间插入M-1个零。
  • 最后,把M路插值后的信号,在时域上逐点相加,得到重建信号x_rec。

这里的关键洞察是:多相滤波器的输出,本身就是上采样后的结果。E{k}的滤波操作,天然地完成了插值滤波的功能。所以,我们不需要像传统方法那样,先插值再滤波,而是直接用E{k}对低速率的v_k[m]滤波,其输出就等效于“插值+滤波”后的信号。

4.3 端到端验证:用OFDM信号测试重建保真度

现在,我们用前面生成的x_ofdm作为输入,经过发射机得到Y,再经过接收机得到x_rec,最后对比两者。

%% 6. 端到端测试 % 假设我们已经有了 Y 从发射机得到 % 现在用它来驱动接收机 x_rec = polyphase_dechannelizer(Y, E, M, length(x_ofdm)); % 计算重建误差 error_signal = x_ofdm - x_rec(1:length(x_ofdm)); mse = mean(abs(error_signal).^2); snr_db = 10*log10(mean(abs(x_ofdm).^2) / mse); fprintf('End-to-End SNR: %.2f dB\n', snr_db); % 画出时域对比 figure; subplot(2,1,1); plot(real(x_ofdm( <p> <a href="https://download.csdn.net/download/vvoennvv/88410042" style="color:#ec7500;font-size:14px;"> 本文还有配套的精品资源,点击获取 </a> <img alt="menu-r.4af5f7ec.gif" src="https://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif" style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;"> </p>

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询