
简介面向船舶工程与信号处理方向这套压缩包提供舰船噪声信号的建模与仿真程序用来辨识螺旋桨、机械运转、流体扰动等典型噪声源并分析其频谱特性与传播规律适合从事舰船声隐身、水声探测或噪声控制的技术人员作为入门参考。包内只包含一个MATLAB脚本文件压缩后约692字节代码量虽小却涵盖噪声源建模、物理模型构建、滤波与频谱分析、参数调节及可视化输出等完整环节便于快速理解噪声仿真的整体逻辑也可在此基础上扩展成更复杂的仿真系统。该程序已被568人学习浏览说明其简洁写法具有一定的参考价值。运行时可针对不同舰型调整转速、结构阻尼等关键参数并结合实测数据校正模型最终输出噪声频谱和声压级分布为舰船设计阶段的降噪优化与反探测策略制定提供量化依据。1. 舰船噪声仿真的第一步把目标拆成可计算的噪声场做水声目标识别、声呐算法验证或者水下数据集增强最缺的不是算法而是带真实特征的舰船噪声样本。实船采集成本高、海域受限、工况不可控一次出海能拿到的干净目标信号非常有限。舰船噪声建模要做的是把“一条船在水下听起来是什么样”翻译成可重复生成的数字信号低频线谱、连续谱、螺旋桨调制都能在确定参数下复现。jianchuanzaoshengxinhao.rar这类压缩包通常只是素材或工程文件真正可复用的是生成链路本身能把带标注的舰船信号稳定产出来。下面从物理结构入手先把 ship noise 拆成可计算的三部分再进入 Python 实现和批量生产参数。2. 从物理量到数字量舰船噪声的三类源与频域骨架要生成能用的舰船噪声仿真信号第一步不是写代码而是分清噪声里到底有哪几类成分。水声工程里对舰船辐射噪声的经典分解是机械噪声、螺旋桨噪声和水动力噪声。三者在频带分布、产生机理和信号特征上完全不同建模时分开处理比用一个统一滤波器靠谱得多。噪声源频谱形态建模方法机械噪声离散线谱加窄带峰正弦叠加频率加小抖动螺旋桨空化宽带连续谱白噪声做频谱整形螺旋桨调制低频包络起伏连续谱乘周期性包络水动力噪声由水流撞击船体和舱壁激起能量集中在低频、方向性强远场仿真时通常归入连续谱整体处理。2.1 机械噪声与线谱为什么先算离散频率机械噪声来自主机、辅机、减速齿轮箱和轴系等旋转与往复部件。内燃机气缸爆发、齿轮啮合、泵与电机转动都会在某个基频及其谐波上形成窄带辐射。这些频率在频谱上表现为一根根离散的“线”所以叫线谱。建模时把线谱当作若干正弦分量叠加即可。对一台转速 n 转每分钟的主机基频 f0 n / 60谐波出现在 k × f0k 为正整数。轴频比主机转速低一两个量级常在 1~30 Hz 之间齿轮箱或叶片频率能到几十到几百赫兹。仿真初值可以这样设轴频 1.5~15 Hz叶频等于轴频乘叶片数常见 4~7 叶主机谐波 50~200 Hz。每次生成给线谱加不超过 ±2% 的随机频偏模拟转速波动否则信号听起来像电子振荡器这也是仿真信号被一下识破的最常见原因。计算谐波表不用手写循环直接按轴频展开def harmonic_freqs(shaft_hz, blades5, n_harm8): # 返回第一个轴频、后续叶频谐波 f_leaf shaft_hz * blades return [shaft_hz] [f_leaf * k for k in range(1, n_harm 1)]harmonic_freqs把转速参数和螺旋桨几何参数映射成线谱表首位是轴频本身后面是叶频的连续整数倍。n_harm 决定保留多少个高次谐波取 6~10 足够覆盖 100 Hz 以内的主要特征取太高只会增加运算量频谱尾部幅度已经衰减到可忽略。2.2 螺旋桨空化与连续谱总声级与斜率怎么定当螺旋桨转速提高到一定程度叶片背压降到饱和蒸汽压以下水发生空化并产生大量气泡。气泡破裂和湍流脉动在很宽的频带内辐射噪声表现为平滑下降的连续谱。船速越快空化越强连续谱整体抬升谱峰频率也往高处移动。工程实现上连续谱常用分段折线包络近似。一套可用的折线模型是10 Hz~100 Hz 按 1/f 抬升100 Hz~1 kHz 基本平坦1 kHz 以上按功率谱每倍频程 6 dB 滚降。不同文献给的经验值差异较大关键保留“低频抬升、高频滚降”的大趋势。写成频域乘子就是def envelope_piecewise(freqs, f_lo100, f_hi1000, rolloff_db6): g np.ones_like(freqs) g[freqs f_lo] (freqs[freqs f_lo] / f_lo) ** -1.0 g[freqs f_hi] (freqs[freqs f_hi] / f_hi) ** (-rolloff_db / 6) return g100 Hz 以下的指数取 -1意味着幅度随频率降低而升高保证低频段不缺能量高频段-rolloff_db / 6换算成功率谱斜率正好是每倍频程 -6 dB。f_lo、f_hi 和 rolloff_db 三个参数直接影响听感和频谱形态批量扫参时优先调它们。更精细的做法是用多个不同中心频率的 1/f^α 型随机序列叠加来替代单一白噪声整形α 取 1~2。这种做法能避免连续谱在频段交界处出现不自然的折角代价是生成时间上升适合对频谱平滑度要求较高的训练集。2.3 调制谱低频包络是舰船噪声的灵魂螺旋桨叶片切割水流使空化强度周期性变化宽带噪声的包络以叶频为周期起伏。对宽带信号检波后再做频谱分析低频段会看到明显峰值这叫调制谱或 DEMON 谱。轴频、叶频和叶片数信息基本都藏在里面是区分船型、估计航速的重要依据。建模时对连续谱乘一个与转速周期相关的慢变包络m(t) 1 m_a × sin(2π f_leaf t φ)其中 m_a 是调制深度常见 0.1~0.5。多叶片之间的几何差异会让轴频处出现一个小峰所以包络里还要再混入轴频分量。正是这一层调制让生成信号从“持续嘶声”变成有节奏的水下噪声。提醒一点调制只作用于与空化相关的宽频部分机械线谱通常不调或调制很浅。如果把调制直接乘到整段信号上低频线谱会被人为地打上周期缺口频谱和真实记录对不上。3. 舰船噪声建模的 Python 复现最小生成器与参数旋钮有了物理分解写一个可复用的舰船噪声生成器就简单了。下面这套用 numpy 和 scipy 实现的链路是水声数据增强里常用的骨架按“线谱 连续谱 调制包络”三个模块拼接参数全部外置方便批量扫参也方便以后替换成实测拟合的参数。3.1 用 numpy 构造线谱分量线谱合成的本质是多个正弦波的叠加。为了避免谱线只在某几个固定初相上起振每个分量都分配独立随机相位为了模拟转速起伏瞬时频率再叠一层随机抖动import numpy as np def gen_line_spectrum(freqs, amps, fs, dur, jitter0.02, seed0): rng np.random.default_rng(seed) t np.arange(int(fs * dur)) / fs x np.zeros_like(t) for f, a in zip(freqs, amps): # 瞬时频率在设定值附近随机游走 f_inst f * (1 jitter * rng.standard_normal(t.size)) # 用累计相位代替 f*t避免频率突变造成相位跳变 phase 2 * np.pi * np.cumsum(f_inst) / fs x a * np.sin(phase rng.uniform(0, 2 * np.pi)) return x参数里最需要注意jitter。抖动太小PSD 上是竖得笔直的谱峰抖动超过 5%谱线会宽到和窄带噪声无法区分丢失线谱特征。常规取 1%~3%具体看目标船的转速稳定程度。freqs 的单位是 Hzamps 是相对幅度可以先按 1.0 归一化之后在合成端整体调增益。3.2 连续谱噪声的频域整形连续谱不关心相位细节直接对白噪声做频域整形效率最高。先生成高斯白噪声rfft 变换到频域乘上目标包络再变换回时域from scipy.fft import rfft, irfft def gen_continuum(fs, dur, seed0): rng np.random.default_rng(seed) n int(fs * dur) w rng.standard_normal(n) spec rfft(w) freqs np.fft.rfftfreq(n, 1 / fs) envelope envelope_piecewise(freqs) # 复用折线频谱包络 spec * envelope return irfft(spec, n)rfft只保留一半频谱irfft 会按共轭对称恢复实数时间序列。相比直接用滤波器做卷积频域整形的好处是相位不被滤波器群延迟扰乱而且改包络形状非常直观加大 100 Hz 以下的指数低频马上变重抬高频带平台信号整体就变亮。注意 irfft 的结果会带一个与包络能量相关的缩放系数不需要特意还原后面合成时统一归一化。3.3 螺旋桨调制包络乘在连续谱上调制只在空化连续谱上做文章。先构造一个 1 附近波动的包络再与连续谱相乘def gen_propeller_mod(fs, dur, shaft_freq, blades5, mod_depth0.35, seed1): rng np.random.default_rng(seed) t np.arange(int(fs * dur)) / fs f_leaf shaft_freq * blades m 1.0 mod_depth * ( 0.7 * np.sin(2 * np.pi * f_leaf * t rng.uniform(0, 2 * np.pi)) 0.3 * np.sin(2 * np.pi * shaft_freq * t rng.uniform(0, 2 * np.pi)) ) return m包络里 70% 的权重放在叶频30% 放在轴频。叶频决定调制谱主峰位置轴频分量制造叶片加工误差带来的小峰权重不同正好对应物理上的主次关系。mod_depth 到 0.5 以上时包络最低点接近 0合成信号出现明显的“静音-爆发”交替更像严重空化正常巡航状态保持 0.2~0.4。三块拼起来就是完整目标信号fs 44100 dur 20 x_line gen_line_spectrum(harmonic_freqs(7.5, blades5), [0.6, 0.3, 0.15, 0.1, 0.08, 0.05, 0.03, 0.02, 0.01], fs, dur, seed0) x_cont gen_continuum(fs, dur, seed0) mod gen_propeller_mod(fs, dur, shaft_freq7.5, blades5, mod_depth0.35) x_ship x_line 1.2 * x_cont * modx_line的幅度列表比谐波频率表长或短都行zip 会按短的截断。1.2 是连续谱通道的增益用来平衡线谱和宽带成分的声级差实际标定时以 PSD 上两者相对高度为准。3.4 输出 wav 文件采样率、位深与动态范围浮点数组不能直接写 wav。按整数 PCM 输出前先归一化并留 10% 余量防削顶x_ship / np.max(np.abs(x_ship)) pcm (x_ship * 0.9 * 32767).astype(np.int16) import soundfile as sf sf.write(ship_noise.wav, pcm, fs, subtypePCM_16)采样率选用要看后续处理需求。水声记录里 8 kHz 和 16 kHz 很常见舰船噪声能量集中在 2 kHz 以下时用 8 kHz 就够文件体积小、FFT 运算快如果还要做传播损失模拟或高频水动力成分才需要 44.1 kHz 以上。16 bit 位深对应 96 dB 动态范围足够容纳线谱和连续谱的幅度差。把上面几个模块用到的参数汇总起来方便批量扫参时快速定位参数推荐范围说明轴频1.5~15 Hz低速商船偏低高速快艇偏高叶片数4~7已知桨型时直接取真值叶频轴频 × 叶片数调制谱主峰位置调制深度0.2~0.4大于 0.5 进入严重空化状态连续谱高频滚降6~12 dB/oct过大会淹没高频成分线谱频偏1%~3%反映转速稳定程度到这里一条可落盘的舰船噪声已经生成完毕。参数怎么按船型标定、怎么看频谱验证下一章直接对拍。4. 舰船噪声仿真的参数标定不同船型与工况怎么设代码骨架跑通只是开始仿真效果好不好的关键在参数标定。没有实测数据时可以从公开水声学和声呐工程教材里的量级起步再按仿真目的微调。4.1 三类典型目标的参数速查表目标类型轴频范围叶片数叶频线谱主要频带连续谱特征大型商船1.5~3 Hz57.5~15 Hz2~100 Hz 密集低频强高频衰减快中型护卫舰3~6 Hz515~30 Hz10~200 Hz中频段平台较宽高速巡逻艇8~15 Hz3~424~60 Hz30~400 Hz整体频段偏高这里给的是远场被动声呐常用的简化参照。同一艘船在不同航速下差异非常大低速巡航时机噪声占主导连续谱不明显高速工况下空化噪声迅速上抬线谱甚至会被连续谱淹没一部分。把轴频当输入变量而不是固定常量才能做出“同一条船两种航速两种声音”的效果。低速水下目标会额外表现为线谱集中在 10 Hz 以下、连续谱极低这要求仿真时长足够长才能看到低频细节。按上面的参数表生成 20 秒信号频率分辨率能到 0.05 Hz 量级覆盖 10 Hz 以下的轴频不成问题。4.2 频域验证用 PSD 对拍仿真信号生成之后先别急着听用 Welch 功率谱密度看一眼整体形态。线谱位置、连续谱斜率、高频滚降是否符合预设PSD 上一目了然from scipy.signal import welch f, psd welch(x_ship, fs, npersegfs * 2, noverlapfs, detrendlinear) peak_idx np.argsort(psd)[-5:] for i in sorted(peak_idx): print(f{f[i]:10.2f} Hz {10 * np.log10(psd[i] 1e-12):8.2f} dB)nperseg 取 fs×2频率分辨率约 0.5 Hz能分开相邻很近的低频线谱。nperseg 太短会把两个线谱糊成一个峰。noverlap 取 50% 以上谱估计方差更小曲线更平滑。打印函数里加 1e-12 是防止 PSD 为零时取对数出现负无穷。线谱峰打印出来之后和harmonic_freqs给的频率表对一次偏差应在 0.5 Hz 以内。连续谱形态看整体包络100 Hz 以下应明显抬升1 kHz 以上平滑衰减。高频衰减若太慢多半是 rolloff_db 设小了低频抬不起来就把 envelope_piecewise 里 f_lo 调高到 200 Hz 试试。4.3 三个常见“像假船”的坑线谱太尖、连续谱太平、包络太规整线谱太尖。没有抖动或抖动过小频谱上是竖得笔直的窄峰。真实记录里转速起伏和传播效应会把谱峰展宽到零点几赫兹到几赫兹。把 jitter 调到 1%~3%或者对每条线谱在频域卷积一个高斯窗都能让峰形自然一些。连续谱太平。只用白噪声低通滤波得到的连续谱在 1 kHz 以上衰减非常快低频段又不够强。低频缺能量会表现为仿真信号“发飘”不够厚重。除了调低 f_lo还可以把低频包络指数改到 -1.2 左右让 50 Hz 附近再抬高一截。包络太规整。调制包络用纯正弦叠加DEMON 谱只有一根或两根干净谱线。真实信号里湍流和空化不规则会让调制深度缓慢波动。给调制深度叠加一个 0.1~0.3 Hz 的随机慢变能显著增加自然感也不破坏叶频主峰的位置。注意验证时把仿真信号和可参考的记录放在同一组 nperseg、同一窗函数下对比否则人耳听着差不多谱形差别却被掩盖了。5. 从单条信号到数据集舰船噪声仿真的批量生产单条验证只是功能层面真正有训练集价值的是批量生产。检测和分类模型通常需要成百上千条带标注的样本并且标签不能出错。批量生成要解决三件事随机性可复现、工况合理分布、生成速度能接受。5.1 用种子和工况组合保证可复现每个样本用样本 ID 做随机种子。例如 seed 1000 sample_id这样任何一条样本都能重新生成调参后旧样本依然可追溯。船型、轴频、调制深度、环境信噪比按工况表组合from itertools import product shaft_list [2.0, 4.0, 7.5] depth_list [0.2, 0.35, 0.5] snr_list [0, 6, 12] combos list(product(shaft_list, depth_list, snr_list))combos 长度是 3×3×327再乘以目标类型就是整个参数空间。生成前算好组合数避免把 27 和 100 个样本 ID 的对应关系搞乱。工程上我会把每条样本的sample_id、ship_type、shaft、mod_depth、snr和对应 wav 文件名打包成一个 CSV作为训练时的元数据。模型看过标签之后任何一条数据都能回溯到生成参数排错时不用猜。5.2 把环境噪声与信道衰减叠进仿真舰船辐射噪声到接收端之前还要经过传播衰减、多途和海洋环境噪声叠加。近程窄带仿真里可以只做三件事距离增益、时延副本、环境噪声加噪。距离增益按球面扩展取 20 log10(R) dBR 是接收距离。R 从 100 m 到 1 km 就差 20 dB影响远大于频率吸收所以近程场景优先调这个值。多途用延迟副本近似时延 10~20 ms衰减 0.3~0.5。环境噪声用另一段独立连续谱噪声海况高的场景再加 0.1~0.5 Hz 的慢扰动。合成函数如下def add_channel(x_ship, fs, delay_ms15, atten0.4, snr_db10, sea_amp0.05, seed0): rng np.random.default_rng(seed) delay int(fs * delay_ms / 1000) multi np.zeros_like(x_ship) multi[delay:] x_ship[:-delay] * atten noise rng.standard_normal(x_ship.size) * sea_amp sig x_ship multi sig sig / np.sqrt(np.mean(sig**2)) # 信号功率归一化 noise noise / np.sqrt(np.mean(noise**2)) * (10 ** (-snr_db / 20)) return sig noisesnr_db 按功率比计算。snr_db 取负值时目标完全沉在环境噪声下面这是数据增强要重点覆盖的难例取 10 以上时目标清晰可辨模型容易学但容易过拟合。5.3 并行生成与数组预分配一次生成 20 秒 44.1 kHz 信号做一次 FFT/IFFT 和几个正弦表计算开销很小瓶颈是几百上千条样本的 Python 循环。用进程池按样本 ID 分块是最省事的加速方式from concurrent.futures import ProcessPoolExecutor def produce_one(sample_id): # 封装 gen_line_spectrum / gen_continuum / gen_propeller_mod / add_channel ... with ProcessPoolExecutor(max_workers8) as pool: results list(pool.map(produce_one, range(500)))每个 worker 里要用 sample_id 重建独立的 numpy 随机数生成器不要依赖模块级 np.random 状态。进程池模式下全局状态会被复制到子进程如果不重新播种所有子进程会生成一模一样的信号这是批量生成最常见的数据事故。运行前先固定 max_workers然后连续跑两次对比输出文件的哈希确认随机性差异真实存在于样本间而不是进程间。6. 进阶技巧用解调谱提炼舰船噪声的轴频特征仿真信号做出来之后最容易被忽略的验证维度是调制谱形态。时域波形听着像不代表调制结构就对了而调制谱恰恰是舰船目标识别里区分船型和估计航速最稳定的特征。这里用一个完整流程把生成的 ship noise 的轴频特征提取出来。6.1 从宽带信号到包络谱的 4 步提取 DEMON 谱的流程分四步带通滤波、希尔伯特包络检波、去直流加窗、Welch 谱估计。带通取 300~1500 Hz。这个频带包含螺旋桨空化能量又避开低频线谱干扰。hilbert 变换取包络得到幅度起伏的时间序列。包络减均值并乘 Hanning 窗抑制频谱泄漏。对包络做 Welch 估计在 1~100 Hz 低频段找峰。from scipy.signal import butter, sosfiltfilt, welch from scipy.signal import hilbert def demod_spectrum(x, fs, low300, high1500): sos butter(4, [low, high], btypeband, fsfs, outputsos) y sosfiltfilt(sos, x) env np.abs(hilbert(y)) env - env.mean() env * np.hanning(env.size) f, p welch(env, fs, npersegfs, noverlapfs // 2) mask (f 1) (f 100) return f[mask], p[mask]nperseg 取 fs 等于 1 秒窗频率分辨率约 1 Hz。对轴频只有 2 Hz 的目标还要把 nperseg 加长到 fs×2 甚至 fs×4换取更细的低频分辨率。带通范围不是死的低速大船的轴频和叶频都低于 8 Hz这时带通下限要降到 100 Hz 附近。6.2 保持目标转速稳定性的两个参数生成端有两个参数直接影响 DEMON 谱质量。第一个是轴频漂移率。实测信号的轴频变化一般在每分钟 0.5% 以内远低于多数合成器默认的随机抖动。做法是给 shaft_freq 加一条缓慢的周期调制而不是采样级白噪声抖动t np.arange(int(fs * dur)) / fs shaft 7.5 * (1 0.005 * np.sin(2 * np.pi * 0.05 * t))0.005 是 ±0.5% 的漂移范围0.05 Hz 是漂移速率模拟 20 秒内的慢变速趋势。直接在叶频上做这个处理DEMON 谱主峰会更宽更自然。第二个参数是调制深度。mod_depth 大于 0.5 时包络高次谐波明显增强轴频的倍频容易盖过叶频峰造成识别歧义。0.25~0.35 区间得到的谱线结构最干净低于 0.1 时包络峰基本淹没在噪声里提取失败率迅速上升。6.3 验证参数时对照这几个指标指标合理范围偏大/偏小说明轴频峰信噪比大于 6 dB过低时检查带通范围或调制深度叶频峰与轴频峰幅度比1.5~3过大时减小调制深度轴频峰值频率偏差小于 3%过大时检查漂移率和相位累加实现按这几项对照生成信号的 demod_spectrum能快速定位是调制太弱、带通选错还是轴频模型偏差。把这套提取逻辑挂到批量生成器后面每个样本除了 wav 还输出一段归一化后的对数 DEMON 谱。做训练时直接在低频包络特征域切数据信号长度从 20 秒缩到 2 秒也不丢轴频信息分类器的输入维度能降一个数量级。本文还有配套的精品资源点击获取