3. 水声信号生成与合成

水声信号处理的第一步,是能在计算机里“造”出可信的信号。无论是做检测、估计还是通信算法验证,我们都需要先构造出已知真值的合成数据,再拿算法去处理,看它能否还原出这些真值。本节围绕四类基础信号——单频、多频、线性调频(LFM)、噪声——展开Python生成方法,并最终把它们叠加成一段带目标与噪声的水声接收信号。

先约定采样与时间轴。水声信号常工作在几百赫兹到几十千赫兹,采样率 fs 需满足奈奎斯特条件,一般取最高频率的2.5倍以上。下面统一用 fs = 48000 Hz、时长 T = 1.0 s 作为示例参数,时间轴 t = np.arange(N)/fs,其中 N = int(fs*T)。所有信号都以这一时间轴为基准,便于后续叠加。

单频与多频信号

单频信号是最基本的测试信号,形式为 s(t) = A·cos(2πf₀t + φ)。在Python中一行即可生成:

import numpy as np
fs, T = 48000, 1.0
N = int(fs*T)
t = np.arange(N)/fs
f0, A, phi = 1000.0, 1.0, 0.0
s_cw = A*np.cos(2*np.pi*f0*t + phi)

多频信号是若干单频分量的线性叠加,用于模拟谐波目标或宽带梳状谱:s(t) = Σ Aᵢ·cos(2πfᵢt + φᵢ)。例如取 800 Hz、1600 Hz、2400 Hz 三个谐波,幅度依次递减,可写成循环累加或向量化求和。多频信号的关键在于各分量的频率、幅度、初相都可独立控制,这让我们能精确设计频谱结构,用来检验滤波器是否只保留了期望的谱线。

线性调频信号

LFM信号(chirp)的频率随时间线性变化,是主动声呐最常用的波形,因为它能在保持较长脉宽(高能量)的同时获得较大带宽(高距离分辨率)。其瞬时频率 f(t) = f_start + k·t,调频斜率 k = (f_end − f_start)/T,相位是频率的积分,因此:

f_start, f_end = 2000.0, 8000.0
k = (f_end - f_start)/T
phase = 2*np.pi*(f_start*t + 0.5*k*t**2)
s_lfm = np.cos(phase)

注意相位中的 0.5*k*t² 项不能漏掉,否则瞬时频率会算错。生成后可用短时傅里叶变换观察时频图,应看到一条从 2 kHz 斜升到 8 kHz 的直线,这是判断LFM是否正确的直观依据。

白噪声与有色噪声

白噪声各频点功率谱平坦,用 np.random.randn(N) 生成高斯白噪声即可,其方差对应噪声功率。海洋环境噪声却并非白色:受航运、风浪、生物活动影响,其功率谱通常随频率升高而下降,在中低频段近似按 1/f^α 衰减。生成有色噪声的常用做法是频域整形——对白噪声做FFT,乘以目标幅度谱 |H(f)| ∝ f^(−α/2),再逆变换回时域:

def colored_noise(N, fs, alpha=1.0, seed=0):
    rng = np.random.default_rng(seed)
    w = rng.standard_normal(N)
    W = np.fft.rfft(w)
    f = np.fft.rfftfreq(N, 1/fs)
    f[0] = f[1]                      # 避免直流处除零
    shape = f**(-alpha/2)
    y = np.fft.irfft(W*shape, n=N)
    return y/np.std(y)               # 归一化到单位方差

参数 alpha 控制谱倾斜程度:alpha=0 退化为白噪声,alpha=1 近似粉红噪声,alpha=2 为布朗噪声。归一化后噪声功率可控,便于按目标信噪比叠加。这是海洋环境噪声建模的初步手段,虽未包含真实传播与指向性,但足以支撑算法级仿真。

水声接收信号合成链路 单频 / 多频 cos(2πf₀t+φ) 线性调频 LFM f: 2k→8k Hz 目标信号 s(t) 幅度 A、时延 τ 高斯白噪声 randn(N) 有色噪声整形 |H(f)|∝f^(−α/2) 叠加合成 x = s + n 按 SNR 定噪声功率 接收信号 x(t) fs=48 kHz, T=1 s 用于检测/估计验证 目标分支控制频率/时延,噪声分支控制谱形与功率,二者在时域直接相加

按信噪比合成接收信号

有了目标信号和噪声,最后一步是按指定信噪比叠加。信噪比定义为信号功率与噪声功率之比,工程上常用分贝表示:SNR_dB = 10·log10(Ps/Pn)。若已知信号功率 Ps 和期望的 SNR_dB,则噪声功率应为 Pn = Ps / 10^(SNR_dB/10),再把单位方差噪声乘以 sqrt(Pn) 即可:

Ps = np.mean(s_lfm**2)
snr_db = -5.0
Pn = Ps / (10**(snr_db/10))
n = colored_noise(N, fs, alpha=1.0)
n = n*np.sqrt(Pn)
x = s_lfm + n

这里 snr_db = -5 表示噪声功率约为信号功率的3.16倍,属于低信噪比场景,适合检验匹配滤波等检测算法。合成后应做两项检查:一是用 np.mean(x**2) 反算实际信噪比,确认与设定值一致(误差应很小);二是画时域波形和功率谱,观察目标谱线或LFM斜线是否仍可辨认。若目标完全淹没在噪声中,正是低信噪比检测算法要解决的问题。

合成信号的真值(目标频率、时延、调频斜率、信噪比)都是已知的,这正是仿真数据的价值:算法输出可以与真值逐项比对,从而定量评估检测概率、时延估计误差等指标。