做阵列信号处理的同学迟早要跟常规波束形成打交道。无论你是用麦克风阵列做语音增强还是在雷达、声呐、超声、射电天文里优化信噪比常规波束形成——也就是常说的延迟求和波束形成几乎都是第一个会被写进原型验证的“地基算法”。而时域波束形成和频域波束形成正好是这个算法的两条典型实现路径。很多人一开始分不清这两者的区别以为只是换个数学表达结果在工程里因为采样率、滤波器长度、处理帧长的问题踩了不少坑。这篇内容不打算搞教科书式的推演我直接把项目里最常碰到的实现细节、参数考量、坑和取舍经验拆开讲清楚。适合刚接触阵列处理的研究生、转做信号处理的工程师也适合那些已经在用现成工具箱、但想搞明白底层逻辑的同学。读完你至少能明白什么时候该走时域什么时候该走频域以及两种方案在计算量、延迟、精度上到底差在哪。1. 常规波束形成到底在解决什么问题1.1 从“阵列收波”说起假设你在房间里摆了一排麦克风远处有一个人说话。每个麦克风收到的信号并不是一模一样的——除了幅度上有点差别最关键的是到达时间不同。如果声源在麦克风阵列的侧前方那么离声源近的麦克风先收到声波离得远的后收到这个时间差在阵列处理里叫传播时延。常规波束形成的思路非常直白既然各阵元的信号只是时间上错开了那我按照某个方向把时间对齐再把它们加起来就行。对齐之后来自这个方向的信号会变成同相叠加幅度增大来自其他方向的信号因为相位不对齐叠加时会相互抵消幅度变小。这一增一减就是在做“空间滤波”——把特定方向的信号挑出来把其他方向的干扰压下去。这套逻辑在雷达上同样成立。天线阵列各单元收到的回波从某个方向回来时也存在固定的相位差补偿掉相位差再求和就等效于把接收波束指向那个方向。这就是常规波束形成最核心的本质补偿时延或者等价地补偿相位然后加权求和。严格来说常规波束形成并不追求“最优”——它没有自适应地去对抗干扰所以也被叫作静态波束形成。它的好处是稳健、计算简单、对误差不敏感而且结果好解释。很多系统第一版都会先用它验证可行性后续再换成MVDR、GSC这类自适应算法。可以说常规波束形成是阵列处理的“万金油”起点。1.2 时域实现和频域实现是同一个算法的两种“编译方式”常规波束形成的数学表达式很简单对每个阵元乘一个复权重再求和。但这个表达式落实到硬件或软件里并不是只有一种写法。时域波束形成直接对时间序列做操作。每个阵元的信号经过一个延迟线延迟量由波束指向角和阵元位置决定延迟完再做加权求和。它的特点是物理意义直观信号是连续流式处理的适合实时系统。频域波束形成则先把时域信号分帧、加窗、做傅里叶变换把信号从时间域搬到频率域。在频域里时延变成了一个随频率变化的相位因子所以波束形成就变成了对每个频点分别做一次复加权求和。处理完之后如果需要时域输出再做逆傅里叶变换。这两条路线看着是同一个算法的两种表示但实际工程里它们带来的系统约束完全不同。比如时域方案对分数延迟的实现精度敏感频域方案对帧长和窗函数敏感。下面我分别把这两条路线的细节展开讲。2. 时域波束形成延迟、求和这一个动作的背后2.1 核心实现流程拆解时域波束形成的实现流程可以分成四步。第一步确定阵列几何和波束指向。假设是均匀线阵阵元间距为 d波束指向角为 θ那么第 m 个阵元相对于参考阵元的时延是τ_m (m-1) · d · sinθ / c其中 c 是传播速度。注意这里 sinθ 的正负号决定了波束是往阵列的哪一侧偏转工程上需要统一约定角度正方向否则波束图会左右颠倒这是我见过最多人犯的低级错误。第二步实现时延补偿。这里要分两种情况如果采样率很高时延值刚好是采样周期的整数倍那只需要做整样本平移用循环缓冲区就能实现。但现实中很少这么幸运因为波束指向是连续变化的算出来的 τ_m 几乎不可能正好落在采样点上这时候就必须做分数延迟。第三步对延迟补偿后的各阵元信号做幅度加权。幅度加权就是开窗比如均匀加权、海明窗、切比雪夫窗等。加窗的目的是压低旁瓣但代价是主瓣变宽指向性变差。常规波束形成里如果你不对旁瓣做要求可以直接用矩形的均匀加权增益最大但阵列对旁瓣方向来的干扰没有压制能力。第四步把各阵元信号相加得到波束输出。如果是时域处理这个求和直接发生在时间序列上一次得到一串连续输出的采样点。整个过程看起来很简单但工程实现时最磨人的就是对时延的近似。我分开说一下。2.2 关键细节分数延迟的逼近方式分数延迟是时域波束形成里最核心的细节。当一个阵元的理论时延是 1.3 个采样周期时你不能直接把信号提前或推后 1 个或 2 个采样点那样会产生明显的波束畸变。常见的做法有几种。第一种是插值。线性插值实现最简单但性能较差尤其在信号频率接近采样率一半时幅度误差会变大。更常用的是 sinc 插值因为带限信号的理想插值函数就是 sinc 函数用截断的 sinc 核做插值可以得到很高的时延精度。实际项目里我会用凯塞窗对 sinc 核做加窗截断把截断长度控制在 8 到 16 个采样点这样能兼顾性能和计算量。第二种是使用专门设计的分数延迟 FIR 滤波器。你可以用最小二乘方法设计一组 FIR 滤波器每个滤波器对应一个特定的分数延迟量。业内也常用拉格朗日插值 FIR 滤波器它的系数直接由闭式公式给出设计成本低适合分数延迟量固定不变或变化缓慢的场景。第三种是用全通滤波器逼近分数延迟。一阶全通滤波器的群延迟在低频段近似平坦实现简单但高频段群延迟会偏差较大。如果系统处理的是窄带信号问题不大但如果是宽带语音或宽带雷达信号我建议别省这个事老老实实用加窗 sinc 插值或者高阶拉格朗日滤波器。注意分数延迟滤波器的设计目标不是让幅频响应平坦而是让群延迟在信号带宽内尽量等于目标延迟量。很多人调试时只看幅频响应忽略了相位响应结果滤波后信号波形看着没问题波束图却歪了其实就是群延迟误差在作怪。2.3 时域实现里的采样率与阵元间距约束时域波束形成有两个参数之间的匹配关系必须盯紧阵元间距 d 和系统采样率 fs。阵元间距的约束和空间混叠有关。射频频段或声学频段里阵列对空间信号的采样就是阵元位置上的“空间采样”。如果阵元间距太大高频率的信号在阵元之间产生相位模糊导致波束图在多个方向出现相同的响应这就是栅瓣。常规做法是让阵元间距不超过信号最高频率对应波长的一半也就是 d ≤ c / (2·f_max)。采样率的约束则和时延量化有关。如果 fs 不够高一个采样周期对应的传播距离就越长微小的时间差根本无法通过整数样本体现虽然分数延迟可以在一定程度上填补但对插值滤波器的精度要求会迅速上升。实际操作中我一般先确认波束指向扫描时需要的时延精度再反推合适的采样率。比如声学测向如果要求角度分辨率在 1 度以内在一米量级的阵列上采样率往往需要设计到 48kHz 甚至更高否则靠插值硬撑会明显增加计算负荷。还有一个容易忘记的约束通道一致性。时域波束形成假设所有通道的幅度响应和相位响应是一致的如果前端的放大链路、滤波器、ADC 采样时钟存在通道间偏差再做波束形成时就会引入系统性的波束指向偏差。所以时域波束形成器前面一定要有通道均衡校正环节。没有这个习惯波束形成效果的上限会被硬生生拉住。3. 频域波束形成换个坐标系看同一件事3.1 为什么要把信号搬到频域频域波束形成的出发点是对时延的另一种理解。在时域时延表现为波形在时间轴上的平移在频域时延表现为相位随频率线性变化。也就是说对第 m 个阵元的频域信号 X_m(f)要补偿的相位因子是H_m(f) e^{-j·2π·f·τ_m}这个表达式的含义是不同频率分量需要的相位补偿量不一样频率越高相位旋转角越大。这个“频率依赖”的特性让频域处理变得非常自然——你可以在每个频点上独立地做加权求和波束形成器就是一个频变的复加权矩阵。频域处理的第二个好处是容易和 FFT 的快速算法结合。分段信号的 FFT 计算效率很高尤其当 FIR 滤波器阶数较长时频域处理的整体计算量可以比时域卷积小一个数量级。这在通道数多、滤波器长的场景下优势非常明显比如 64 通道以上的麦克风阵列或者雷达的脉冲多普勒处理。第三个好处是便于做频率相关的处理。比如语音增强里不同频段的信噪比不一样我们可能希望高频段压低旁瓣、低频段保持主瓣宽度频域实现里只需要对不同频点设置不同权重即可时域实现要同时改全部滤波器的系数麻烦得多。3.2 分帧、加窗、FFT、相位补偿、合帧完整链路频域波束形成的标准处理链路我拆成八步第一步把每个通道的时域信号分段。分段的长度 N 通常取 2 的幂次比如 512、1024 点。段与段之间一般有重叠重叠率常见 50% 或 75%目的是减轻加窗带来的信息损失。第二步对每段信号加窗。为什么要加窗因为把无限长信号截断成有限帧本质上相当于乘了一个矩形窗矩形窗的频谱旁瓣很高会把信号的能量漏到邻近频点去。加上汉宁窗或者海明窗能显著抑制频谱泄漏。但加窗会压低帧边缘的样本值所以必须搭配重叠使用否则重构回来的时域信号幅度会周期性波动。第三步对加窗后的每帧数据做 FFT得到频域表示 X_m(k)其中 k 是频点序号。第四步计算每个阵元在每个频点上的相位补偿量。由于 FFT 后的频点是离散的f k·fs/N所以相位因子是 e^{-j·2π·k·fs·τ_m/N}。可以把这些预先算好存成查找表运行时直接查表乘进去省掉大量三角函数运算。第五步对每个频点独立做加权求和。这一步得到的就是波束形成的频域输出 Y(k)。如果还要加幅度加权比如切比雪夫窗就对各阵元都乘上对应的窗系数 w_m再求和。第六步如果需要时域输出对 Y(k) 做 IFFT得到当前帧的时域波束输出。第七步用重叠相加法或重叠保留法把相邻帧拼接回连续的时域信号。重叠相加的流程是各帧分别做 IFFT 后在时域按重叠位置相加重叠保留则是直接丢弃帧边缘的混叠部分。第八步如果后面还有下游处理记得把加窗引入的幅度因子补偿回来。否则你输出的信号幅度会整体偏小而且不同频率可能偏得不一样。这个链路里最核心的细节是相位补偿的准确度。FFT 本身不引入相位误差但如果你在第四步把 τ_m 算错哪怕只差一个采样点高频段的相位旋转差异也会被放大到无法忽略的程度。所以计算 τ_m 时务必统一用同一个参考阵元和同一个角度符号约定。3.3 频域独有的控制自由度频域波束形成有一个时域很难做到的优势频率不变波束图设计。时域波束形成里波束主瓣宽度随频率变化很自然——频率越高主瓣越窄。这在某些应用里是好事情但在语音处理中会造成频率失真高频信号方向性强低频信号方向性弱离轴声源的音色会被改变。频域处理可以对每个频点设计不同的等效孔径或权重让各频点的波束主瓣宽度保持一致这就是常说的恒定束宽波束形成。实现方式也不复杂先确定一个参考频率的波束图然后对每个频点设计一组权重让该频点的波束图尽量逼近参考频率的波束图。常用的约束是最小二乘拟合也可以用凸优化工具直接求解。这里虽然已经超出常规波束形成的范畴但它在工程中的价值很大值得知道频域路线天然支持这种扩展。另外一个方便之处是频域加权方便做“空间谱平滑”。当阵列存在相干干扰时常规波束形成的输出会出现明显畸变频域处理可以对相邻频点做一定的平滑或对角加载改善稳定性。这些操作在时域里虽然也能做但直观程度和实现成本都不如频域处理。4. 时域波束形成和频域波束形成到底怎么选4.1 计算量对比谁的乘法更少计算量是选型时绕不开的问题。我们用一次完整波束形成需要处理 N 个采样点来估算。时域方案里每个阵元需要一个分数延迟 FIR 滤波器假设滤波器阶数为 L那么对 M 个阵元处理 N 点信号需要的乘法次数大约是 M×N×L。如果 L16M8那这个数字是 128×N。这个计算量是实时的、流式的每个输出点都即时可得。频域方案里每帧数据要经过一次 FFT。对 N 点长度的帧做 FFT复杂度大约是 (N/2)·log2(N) 次复数乘法。M 个阵元就是 M 倍的 FFT 计算量。频域加权求和这一步只有 M 个复乘。再加上 IFFT 恢复时域总计算量大致是 (M1)·N·log2(N)。对比一下当 N1024 时log2(N)10频域计算量约为 10 倍的 M·N而时域如果 L16则是 16 倍的 M·N。表面看两者接近但如果滤波器阶数 L 增大到 64 或更高时域的计算量会急剧上升频域的优势就非常明显了。不过要注意频域方案有块处理延迟——你必须攒够一帧数据才能处理而时域方案是逐采样点处理的延迟可以做到极低。对语音实时交互这类对延迟敏感的场景时域方案往往更合适。4.2 宽带信号和窄带信号适配性不同信号带宽是另一个决定性的因素。窄带信号比如雷达的单频脉冲、通信里的单载波窄带信号用频域波束形成几乎是最自然的选择。可以把整个信号近似看成单一频率相位补偿只要针对中心频率做就可以实现非常简单。甚至可以在中频或基带直接用复加权完成波束形成不需要额外做精细的分数延迟。宽带信号比如语音、声呐的宽带线性调频、超声成像的短脉冲情况就要复杂一些。时域方案比较容易做到“真正的时间对齐”因为它的延迟补偿直接发生在时间轴上不受信号带宽限制。频域方案也可以做宽带但需要逐频点加权和逆变换处理链路更重实时性稍差。我个人的习惯是如果信号带宽相对中心频率小于 10%优先用频域如果带宽占中心频率的 30% 以上或者信号是瞬态冲击型优先用时域。这个经验值不是严格的界但能帮你在项目早期快速定方向。4.3 工程选型建议表根据这些对比我把几个关键维度整理成一张表方便你做方案初选维度时域波束形成频域波束形成延迟低流式输出高取决于帧长和重叠率计算量长滤波器时较高随滤波器阶数线性增长较低依赖 FFT宽带信号适配性好物理意义直观中需要逐频点处理实时性优中便于频率相关处理差优实现复杂度中较高典型应用实时语音、低延迟阵列雷达、声呐、离线处理这个表只能作参考。真实系统里还要考虑硬件平台——FPGA 上时域流水线结构非常友好DSP 上 FFT 库函数优化得好频域反而更容易跑起来。另外如果只有一路输出但通道很多频域处理时通道间的 FFT 可以复用节省不少内存。5. MATLAB复现时域与频域波束形成的对照实验5.1 实验设置下面我用一组 MATLAB 代码把两种实现跑一遍用同一个阵列和同一段信号方便对照。实验条件8 元均匀线阵阵元间距 0.05m信号是中心频率 3000Hz 的单频加部分宽带噪声采样率 24000Hz声源方向 30 度干扰方向 -20 度取 0.1 秒数据做处理。先定义公共参数。clear; clc; close all; c 340; % 声速 m/s fs 24000; % 采样率 d 0.05; % 阵元间距 M 8; % 阵元数 theta_source 30; % 期望方向 (度) theta_interf -20; % 干扰方向 (度) t (0:2400-1) / fs; % 0.1s % 构造源信号3kHz正弦 少量随机噪声 source sin(2*pi*3000*t). 0.05*randn(2400,1); % 计算阵元接收信号理想传播只有时延幅度一致 tau_source (0:M-1). * d * sind(theta_source) / c; tau_interf (0:M-1). * d * sind(theta_interf) / c; X zeros(M, length(t)); X_interf zeros(M, length(t)); for m 1:M X(m,:) circshift(source, round(tau_source(m)*fs)).; X_interf(m,:) circshift(source, round(tau_interf(m)*fs)). * 0.8; end X X X_interf;这段代码模拟了两个方向的波同时到达阵列只是时延不同幅度略有差别。实际系统里还会有混响和噪声这里先做一个最简单的理想对照。5.2 时域波束形成代码示例分数延迟我用线性插值来演示实际工程里可以替换成更精确的 sinc 插值。对每个阵元计算理论时延然后在离散信号上做延迟补偿。% 时域波束形成分数延迟 求和 theta_scan 30; % 对准30度 tau_scan (0:M-1). * d * sind(theta_scan) / c; y_time zeros(size(t)); for m 1:M delay_samples tau_scan(m) * fs; if delay_samples ~ 0 % 线性插值分数延迟或者换sinc插值 xm_interp interp1((0:length(t)-1), X(m,:), ... (0:length(t)-1) - delay_samples, linear, 0); else xm_interp X(m,:); end y_time y_time xm_interp; end y_time y_time / M; % 归一化 % 计算输出功率 power_time mean(y_time.^2); fprintf(时域波束形成输出功率: %.4f\n, power_time);关键点在于delay_samples是一个小数interp1在非整数索引处做了插值。这就是分数延迟补偿。5.3 频域波束形成代码示例频域实现的关键是先把信号分帧、加窗、做 FFT再在频域做相位补偿。% 频域波束形成 frame_len 512; hop frame_len / 2; n_frames floor((length(t) - frame_len) / hop) 1; win hann(frame_len, periodic); y_freq zeros(size(t)); wsum zeros(size(t)); % 用于重叠相加的归一化 for idx 1:n_frames start_idx (idx-1)*hop 1; end_idx start_idx frame_len - 1; X_frame zeros(M, frame_len); for m 1:M xseg X(m, start_idx:end_idx) .* win; X_frame(m,:) fft(xseg); end % 频域相位补偿逐频点加权求和 freqs (0:frame_len-1) * fs / frame_len; Y_frame zeros(1, frame_len); for k 1:frame_len phase_shift exp(1j * 2 * pi * freqs(k) * tau_scan); Y_frame(k) sum(X_frame(:,k) .* phase_shift) / M; end y_ifft real(ifft(Y_frame)) .* win; y_freq(start_idx:end_idx) y_freq(start_idx:end_idx) y_ifft; wsum(start_idx:end_idx) wsum(start_idx:end_idx) win.^2; end y_freq y_freq ./ (wsum eps); power_freq mean(y_freq.^2); fprintf(频域波束形成输出功率: %.4f\n, power_freq);这段代码演示了经典的重叠相加结构。注意每个频点的phase_shift随频点变化这就是宽带频域波束形成区别于窄带复加权的地方。5.4 实验结果解读与注意事项运行后你会发现两种方法的输出功率十分接近。时域的功率略大一点是因为线性插值本身带了轻微低通效应而频域方法加窗有 1.5dB 左右的损失这本希望通过重叠相加的归一化补回来但边界部分仍会有一点残留误差。但两者在真正工程实现上的差别并不体现在这个理想合成实验中。时域方案的坑在分数延迟滤波器的群延迟一致性上频域方案的坑在帧边界幅度的周期性调制上。如果直接拿这个结果去评估系统性能我会建议再补三个指标波束图的零点位置、宽带信号下输出信号的频谱失真、以及不同来波方向下输出功率的稳定度。常规波束形成的功能虽然简单这些指标却决定它到底能不能在实际系统里用。6. 常见问题与排查技巧实录6.1 高频踩坑点栅瓣、群延迟误差、帧边界调制栅瓣是最具欺骗性的问题。当你把阵元间距设成信号最高频率对应的一个波长时波束图会出现多个等高的峰值指向别的方向。有一次我在做超声阵列实验时因为阵元物理尺寸限制没法缩小间距结果在 45 度方向出现一个和目标方向同样高的假峰采集的数据看起来一切正常但成像位置完全错了。排查这类问题最有效的方法是画出波束图看清楚主瓣和栅瓣的位置然后检查 d 和 f_max 的乘积是否超过 c/2。群延迟误差问题我前面已经提过。这里再给一个快速检测技巧用波束形成器处理一个宽带的线性调频信号比较输出信号和参考阵元信号的互相关峰值位置如果发现峰值时间偏移随频率变化就说明分数延迟滤波器的群延迟不平坦。换用加窗 sinc 插值通常能直接解决。帧边界调制是频域方案特有的。如果你在频域处理完做 IFFT 重叠相加后发现输出信号存在周期性的幅度波动说明你的重叠相加归一化没做好。最直接的做法是改用 WOLA 结构分析窗和综合窗分开设计保证重叠相加后整体增益为 1。这个结构在实时语音处理里非常常见值得专门研究一下。6.2 问题速查表问题现象可能原因排查/解决思路波束指向偏了角度符号约定混乱或 τ_m 计算错误统一参考阵元检查角度正方向波束图多出等高假峰阵元间距 d 大于半倍最高频率波长重算空间采样约束减小间距或限制处理带宽输出信号有周期性幅度波动频域重叠相加归一化错误检查窗函数平方求和是否恒等于常数波束输出高频衰减分数延迟插值精度不足换加窗 sinc 插值或增加滤波器阶数时域与频域结果不一致频域相位补偿用的频率、时延单位不统一核对 FFT 频率分辨率和 τ 的秒/采样点换算静态波束图没零点通道增益不一致先做通道均衡/校准再谈波束形实时系统延迟超标帧长太长减小 FFT 长度提高重叠率必要时换时域方案6.3 几条值得记住的实操心得第一做波束形成之前先校准通道比调任何参数都重要。通道增益差 1dB、相位差 5 度波束的零陷深度就可能少 10 到 20dB。很多团队花大量时间调算法最后发现瓶颈在模拟前端的通道一致性上。第二仿真里务必加入量化误差和通道失配。干净的理想仿真会掩盖大量实现问题导致算法进硬件后性能骤降。我习惯在仿真阶段就给每个通道加入幅度误差、相位误差和轻微噪声这样评估出的波束图才接近真实水平。第三扫角度画波束图是排查一切问题的第一动作。无论时域还是频域实现第一步就是跑一个角度扫描把波束图打出来。一眼就能看出主瓣位置、旁瓣水平、有没有栅瓣。在这一步能发现的问题不要拖到整机联调再处理。第四频域方案里保存一份phase_shift查找表别每次处理都现场算三角函数运行速度能快好几倍。查找表可以用浮点精度存储内存占用也很小一个 1024 点 FFT、8 个阵元也只需要 8×1024 个复数。第五时域方案如果对实时性要求高优先用定点化友好的结构。把分数延迟滤波器系数提前量化为定点并做好直流校正避免定点实现时直流偏移导致动态范围损失。我在实际项目里最常见的组合是雷达、声呐等窄带或离线处理场景用频域波束形成实时语音增强、低延迟麦克风阵列用带分数延迟滤波器的时域波束形成。两者并不互斥一套系统里也完全可以在时域做波束指向、在频域做后置滤波各取所长。关键是先把这两条路线的底细摸透遇到性能问题时才能知道该从哪个环节下手。