资讯详情

资讯详情

FM立体声调制解调仿真:从MPX复合信号到PLL相干解码全流程解析

简介面向MATLAB信号处理与通信原理学习者这份FM立体声调制解调仿真工程提供了一条从原理到代码的完整路径。工程实现了FM调制解调全流程覆盖立体声基带合成、高频载波调制、解调及音频还原代码注释详尽关键调制参数可自由修改便于对比不同参数下的频谱与波形变化借助时域和频域双重展示抽象的频率调制过程被具象化非常适合课程设计、实验报告或自学立体声系统。压缩包仅88KB总共包含2个文件以MATLAB脚本.m和音频测试文件.m4a为主体脚本内集成了仿真算法与绘图输出音频文件则用于验证解调效果结构精简下载后即可直接运行。目前已有863人学习使用对于希望快速上手FM仿真、减少排错成本的读者而言这份小巧的资料能帮助理解立体声FM的关键链路并可作为进一步二次开发的基础。1. FM调制解调仿真立体声链路最难的不是调制是解码端那三件套“FM调制解调仿真”后面挂上“立体声”三个字难度重心就完全变了。单声道FM你只需要做预加重、调频、鉴频、去加重四步一旦标了“立体声”发射端要合成MPX复合信号接收端要从19kHz导频锁出38kHz副载波再做相干解调恢复L-R支路任何一环的相位没对齐最终左右声道分离度就是零听感比单声道还差。标题里的“完整过程”指的是一条完整链路立体声输入 → 预加重 → MPX合成 → 调频 → 信道 → 鉴频 → MPX解码 → 左右声道输出。这套链路在音频无线传输、广播车载工程和通信系统仿真里几乎天天遇到适合通信仿真方向的学生、做无线音频方案评估的工程师以及想在现有项目里核对调制指标的人。这篇笔记不依赖任何现成源码包按标准工程链路把每一步参数和代码写成可直接照做的形式。2. 立体声FM在传什么MPX复合信号与预加重设计2.1 LR/L-R矩阵为什么立体声要额外传一路“差信号”FM立体声从来没有把左右声道各自调制出去而是传和信号M与差信号S。编码关系很简单M L RS L − R接收端恢复L 0.5×(M S)R 0.5×(M − S)这么做的第一个理由是兼容性。单声道接收机只需要解调出M就能听到完整节目立体声接收机再去解码S重新分离左右。如果发射端直接传L和R老式单声道收音机就必须选其中一路听兼容代价太大而且两路音频占用的频谱资源也要翻倍。第二个理由是频谱利用。S信号并不直接占用独立频段而是先与38kHz副载波相乘形成抑制载波的双边带信号DSB-SC占据音频带上方23kHz到53kHz的区间。19kHz处再放一个半频导频用来在接收端恢复38kHz副载波的相位。整个复合信号合在一起叫MPXMultiplex信号它才是FM调制器真正要调制的“基带”。很多初做仿真的人直接在左右声道上做FM调制出来也能听但那根本不是立体声广播只是两个独立声道做了一次模拟调频而已。2.2 预加重FM解调噪声随频率平方抬升必须人为抬高音频高频FM鉴频器输出的噪声功率谱不是平坦的。对理想鉴频器来说噪声电压谱密度随频率线性上升功率谱密度随频率平方上升也就是说解调后高频段的噪声远比低频段大。所以FM发射端必须做预加重把音频高频部分相对抬起来接收端再做对称的去加重把它压回去同时把鉴频器产生的高频噪声一起压平恢复平坦的频响。两个常见时间常数75μs和50μs。国内FM广播和北美标准使用75μs欧洲部分国家用50μs。仿真里一定要保证发射与接收两端使用同一个值否则声音会闷或者刺耳。数字实现上去加重是一个一阶低通系数可以用单极点形式直接给出alpha exp(−1 / (T × fs))y[n] x[n] × (1 − alpha) y[n−1] × alpha发射端预加重我习惯用差分近似。一阶预加重连续域传递函数是H(s) 1 sT对应到离散域就是当前采样与前一采样的差分再乘以T·fspre[n] x[n] T × fs × (x[n] − x[n−1])这个形式在音频带内与理论响应吻合高频每倍频程抬约6dB。注意一个容易搞错的点预加重只能对L、R音频分别做或者对M与S基带分别做不能对整个MPX复合信号做。如果对MPX整体预加重19kHz导频和38kHz副载波都会被抬升接收端导频锁相会出问题立体声解码直接失效。2.3 MPX频谱规划0到96kHz的频段怎么安排整个仿真链路里系统采样率不是随便选的。MPX信号的频段分布决定了最低采样率。常见安排如下表信号成分频率范围作用MLR0 ~ 15kHz单声道兼容信号立体声接收机也靠它恢复中低频导频19kHz 单音供接收端PLL锁定恢复38kHz副载波相位SL−RDSB-SC23kHz ~ 53kHz38kHz副载波被S调制后的上下边带RDS可选57kHz ±2kHz数字数据广播本文不涉及采样率我直接固定在192kHz。此时奈奎斯特频率是96kHz能完整容纳到57kHz以上的RDS频段也给滤波器留出了过渡带。对复基带仿真来说192kHz采样率处理几秒钟音频非常轻松。这里必须澄清一个仿真里最常见的概念误区系统采样率与“射频载波频率”完全无关。FM广播的真实载波在88MHz到108MHz之间但仿真不需要真的生成这么高的频率。做复基带仿真时载波被搬移到0Hz附近调制的核心信息全部体现在相位增量上。采样率只由基带信号的最高频率决定192kHz足够。这也是后面仿真不会内存爆炸的前提。3. 用MATLAB搭出发射链路预加重、MPX合成与相位积分调频3.1 从左右声道到MPX复合信号先用一段代码把双声道音频合成为MPX复合信号。这里用两个不同频率的正弦波作为测试素材方便后面检查左右分离度。% 系统参数 fs 192e3; % 系统采样率覆盖0~96kHz T 75e-6; % 预加重时间常数国内FM广播标准 % 测试音频左声道1kHz右声道2kHz t (0:fs*2-1)./fs; % 生成2秒时间轴 xL 0.5 * sin(2*pi*1000*t); xR 0.4 * sin(2*pi*2000*t); % 1) 对左右声道分别做预加重函数见3.2 pL preEmphasis(xL, T, fs); pR preEmphasis(xR, T, fs); % 2) 矩阵编码 M pL pR; % LR S pL - pR; % L-R % 3) 峰值归一化保证MPX不越过满调制度 peak max(abs(M)) max(abs(S)) 0.1; M M / peak; S S / peak; % 4) 合成MPX复合信号 pilot 0.1 * sin(2*pi*19000*t); % 19kHz导频幅度10% sub S .* sin(2*pi*38000*t); % 38kHz副载波DSB-SC mpx M pilot sub;逻辑说明预加重放在矩阵编码之前保证M和S各自带上了正确的高频提升。峰值归一化是必须做的一步。MPX信号最终会驱动FM调制器100%调制对应75kHz峰值频偏如果峰值超过1瞬时频偏就超过标准值解调端必然失真。导频幅度固定取0.1也就是复合信号峰值的10%这个比例不能随意加大否则会挤占音频信号的调制度。做完这一步可以用频谱图检查MPX0到15kHz是M成分19kHz有一条清晰的导频谱线23kHz到53kHz是S的DSB-SC边带。三条特征齐全发射端基带部分就正常了。3.2 一阶预加重实现与带限3.1里调用的preEmphasis函数工程上常用差分近似实现加上一个15kHz低通做带限。代码如下function pre preEmphasis(x, T, fs) % 一阶预加重近似H(s) 1 T*s dx diff(x); % 后向差分x[n] - x[n-1] pre x (T * fs) * [0; dx]; % 高频提升 % 带限到15kHz防止带外能量进入导频和副载波区 [b, a] butter(4, 2*15000/fs, low); pre filter(b, a, pre); end参数说明T×fs在这个配置下等于75e-6乘以192e3算出来是14.4所以差分项增益相当大高频抬升效果明显。但差分近似的响应在接近奈奎斯特频率处会一路冲上去必须用低通把它限制在15kHz以内。滤波器的阶数取四阶Butterworth过渡带够陡又不至于产生严重群延迟。顺序不能反。先预加重、后低通抬升的是音频内的高频先低通再预加重等于高频已经被滤掉一部分再抬升效果就弱了。这个细节直接影响后面去加重之后的频响平坦度。工程上如果不想用差分近似也可以用双线性变换把H(s)1sT离散化但对仿真来说当前写法足够关键是保证峰值归一化正确。3.3 用相位积分产生FM信号相位连续才是关键FM的本质是相位调制。数字实现不生成真实载波而是用复基带信号把信息写在相位累加结果上% 归一化MPX保证100%调制时峰值频偏75kHz mpx mpx / max(abs(mpx)); % FM广播标准最大频偏 freqDev 75e3; % 相位累加theta[n] 2*pi*freqDev/fs * cumsum(mpx) phase 2*pi * freqDev / fs * cumsum(mpx); % 复基带FM信号 fmTx exp(1j * phase);为什么用相位积分而不是直接改振荡器频率因为FM信号瞬时频率是相位的导数直接用一个频率变量做sin(2*pi*f*cumsum?)这种近似本质也是相位积分。如果写成每步直接改变正弦函数里的频率参数相位会产生跳变听感上全是咔哒声。用cumsum累加相位天然保证相位连续。freqDev / fs是每个采样点允许的最大相位增量当mpx等于1时瞬时频偏就是75kHz。信道模型可以直接加在这个复基带信号上。需要测抗噪声性能时叠加复高斯白噪声信噪比按整个192kHz带宽计算。这个复基带形式下噪声对相位的影响等价于真实射频链路里信噪比的影响结论可以直接用来评估解调门限。4. 接收端鉴频、导频锁相与立体声解码4.1 复基带差分鉴频由相位增量还原瞬时频偏接收端第一步是加噪并做鉴频。代码里fmTx是发射端复基带信号先叠加上噪声再用相邻采样共轭相乘求相位差。% 信道复高斯白噪声SNR按整个fs带宽定义 snr 50; % 信噪比单位dB pn 10^(-snr/10); % 噪声功率 noise sqrt(pn/2) * randn(size(fmTx)) 1j*sqrt(pn/2)*randn(size(fmTx)); fmRx fmTx noise; % 差分鉴频相邻采样相位差 - 瞬时频偏 instFreq angle(fmRx(2:end) .* conj(fmRx(1:end-1))) * fs / (2*pi); % 还原归一化MPX基带 mpxRx instFreq / freqDev;逻辑说明fmRx[n] * conj(fmRx[n-1])的相位就是两个相邻采样之间的相位增量除以采样间隔得到瞬时频率再除以freqDev还原到−1到1的幅度范围。这个差分鉴频器等价于理想鉴频器不受输入信号包络起伏影响实现也最简单。唯一的坑是当信噪比很低时angle输出会因为噪声出现相位跳跃尖刺解调出的MPX会有一串毛刺。工程做法是先对fmRx做窄带滤波再鉴频或者在鉴频输出后加一个中值滤波去掉单点尖刺。教学仿真里信噪比一般给到30dB以上这个问题不明显但心里要有数。4.2 从MPX中分离M与S滤波器带宽决定立体声底噪鉴频输出mpxRx是完整的MPX复合信号接下来要按频段拆开。M是0到15kHz基带S是23kHz到53kHz的DSB-SC双边带信号% M支路0~15kHz低通 [b_m, a_m] butter(4, 2*15000/fs, low); Mraw filter(b_m, a_m, mpxRx); % S支路23~53kHz带通只保留副载波边带 [b_s, a_s] butter(4, [23000, 53000]/(fs/2), bandpass); Sraw filter(b_s, a_s, mpxRx);参数说明S支路的带通滤波器非常关键。带宽如果开宽了比如从15kHz直接通到60kHz鉴频器的高频噪声会被大量放进来解码后L-R支路的嘶嘶声会明显盖过信号。带宽如果收窄了比如截止到50kHzS信号的高频边带被切掉解码出的声音细节就丢失。四阶Butterworth在这个频段有平坦的带内响应群延迟也相对可控是仿真里稳妥的选择。这里先强调一点去加重不要放在mpxRx整体上做。去加重是15kHz以下的一阶低通特性如果对整段MPX去加重S副载波所处的23kHz到53kHz频段会被大幅压掉立体声信息直接丢了。正确位置是等S副载波解调到基带之后和M支路各自做去加重。4.3 19kHz导频PLL立体声解码的心脏这一步是整个立体声仿真里最容易被卡住的地方。S信号是用38kHz副载波做DSB-SC调制的抑制了载波所以接收端必须自己恢复一个与发射端相位一致的38kHz信号去做相干解调。恢复的办法是锁19kHz导频再把锁相环输出的相位倍频到38kHz。先给出导频PLL的实现% 19kHz窄带通提取导频 [b_p, a_p] butter(2, [18900, 19100]/(fs/2), bandpass); pilotSig filter(b_p, a_p, mpxRx); % 二阶PLL参数 N length(pilotSig); kp 6e-3; % 比例增益决定牵引速度 ki 2e-5; % 积分增益决定稳态相位误差 freqStep 2*pi*19000/fs; % VCO中心频率对应的相位步进 acc 0; ph 0; vco zeros(N, 1); for n 1:N vco(n) sin(ph); % VCO参考信号 err pilotSig(n) * vco(n); % 乘法鉴相 ph ph freqStep kp*err acc; % 相位更新 acc acc ki*err; % 积分支路 end逻辑说明乘法鉴相输出的误差项里包含低频相位差和两倍频分量。两倍频分量在环路里被自然平均掉kp和ki共同决定牵引范围与噪声性能。kp太小锁得慢kp太大会在锁定点附近抖动ki负责消除稳态相位误差。实际调试中如果PLL始终锁不住先对pilotSig做一次FFT把最大谱线对应的频率作为freqStep的初值PLL很快就能入锁。锁住19kHz导频后VCO相位ph就是19kHz信号的相位。要恢复38kHz副载波对相位乘2即可因为导频与副载波在发射端本来就是2倍频关系% 再生38kHz副载波 subCarr sin(2 * ph); % S支路相干解调下变频到基带 Sbase 2 * Sraw .* subCarr; % 低通取0~15kHz基带再做去加重 [b_lp, a_lp] butter(4, 2*15000/fs, low); Sbase filter(b_lp, a_lp, Sbase); alpha exp(-1/(T*fs)); deOne (x) filter(1-alpha, [1, -alpha], x); Mhat deOne(Mraw); Shat deOne(Sbase); % 解码矩阵 Lhat 0.5 * (Mhat Shat); Rhat 0.5 * (Mhat - Shat);参数说明Sbase乘以2是因为DSB-SC相干解调后信号电平只有原S的一半乘2补回来。Mhat与Shat各自去加重然后进矩阵顺序不能乱。实际接收机里去加重网络通常放在解码矩阵之后对L和R分别处理数学上两者等价前提是M和S支路的去加重响应完全一致。仿真里对M和S分别去加重更直观也方便单独检查哪一路有问题。副载波相位是这里最玄学的部分。Sraw经过一个带通滤波器后会有群延迟38kHz副载波的相位会被折弯如果直接用sin(2*ph)去乘副载波相位差会造成L-R幅度衰减甚至左右串扰。工程上要么用零相位滤波filtfilt做离线处理要么记录滤波器群延迟并转成相位补偿量。分离度卡在20dB上不去的时候优先怀疑这里。5. 立体声FM仿真的5个高频翻车点现象、原因与排查5.1 立体声指示灯不亮PLL失锁解码结果等同单声道现象M支路声音完全正常S支路出来全是噪声分离度接近0dB整个节目听感就是单声道。原因PLL没有锁住19kHz导频。常见诱因有三个。导频带通滤波器带宽太窄导致导频幅度被压掉VCO初始频率与19kHz偏差超过环路牵引范围kp和ki参数没配对环路在锁定点附近持续振荡。解决先对pilotSig做FFT把最大谱线频率作为VCO初始频率然后观察vco(n) * pilotSig(n)的均值锁定状态下这个值稳定在某个非零直流电平附近失锁时则在正负间跳动。调参顺序是先给大kp快速牵引再切换小环路带宽压噪声。5.2 声音发闷去加重时间常数不匹配现象解码出的节目人声发闷高频明显缺失左右声场变窄。原因发射端和接收端的时间常数不统一比如发射用了75μs预加重接收却用了50μs去加重或者误把去加重放在了整个MPX信号上导致23kHz到53kHz的S副载波被低通压掉。解决把T统一为75μs。检查代码里是不是有两处T变量一处改了另一处没改。验证方法是分别输入1kHz和10kHz单音跑全链路比较输出幅度。正常情况两者应当基本持平如果10kHz明显低了去加重就过头了。5.3 仿真跑不动把采样率绑在真实载波频率上现象几秒钟的音频输入后程序内存暴涨甚至直接卡死。原因代码试图生成88MHz到108MHz的真实载波采样率被迫拉到数百MHz一个采样点对应的时间极短数据量指数膨胀。这是FM仿真新手最常踩的坑。解决改用复基带仿真采样率只用192kHz。调频信息全部体现在复信号的相位里真实载波频率被“搬走”不影响任何调制解调结论。对比关系很简单真实射频仿真可能需要每秒上亿个采样点复基带仿真每秒只需要不到20万个。5.4 L-R支路嘶嘶声明显副载波没有真正相干解调现象单声道部分干净切到立体声后背景噪声明显增大高频段有持续咝声。原因S支路带通带宽太宽把带外FM噪声全收进来了或者副载波恢复用了独立38kHz振荡器而没有跟踪导频相位导致解调出现拍频。解决S带通严格设为23kHz到53kHz。副载波必须从PLL相位乘2得到不能用固定频率正弦波。解调后的Sbase再加15kHz低通进一步压掉带外噪声。低信噪比条件下PLL环路带宽收窄能改善高频噪声但带宽不能低于能跟踪导频漂移的程度。5.5 分离度上不去矩阵、导频幅度与相位误差逐个查现象用单声道信号测试左右分离度只有20dB左右距离35dB的可用门槛有明显差距。原因导频幅度偏低或偏高M与S两路滤波器群延迟不一致导致相位对不齐矩阵系数写错比如用了M±S而不是0.5倍。解决导频幅度固定在10%。滤波器统一使用相同类型和阶数或者直接改用filtfilt消除群延迟影响。矩阵写死为0.5*(MhatShat)和0.5*(Mhat-Shat)。排查顺序是先看导频幅度再看PLL锁定相位最后查滤波器群延迟通常一轮下来就能定位到问题环节。6. 把仿真结果当回事分离度与频偏的量化验证仿真跑通只是开始真正能说服自己的是量化指标。立体声FM最核心的两个指标是分离度和峰值频偏。分离度测试方法左声道输入1kHz单音右声道置零跑完整链路后计算左右输出功率比% 输入xL为1kHz正弦xR全零 sep 10 * log10( mean(Lhat.^2) / mean(Rhat.^2) ); if sep 40 disp(分离度达标); else disp(分离度偏低按第5章顺序排查); end理想情况下Rhat应为零实际工程仿真能到40dB以上就算良好。如果有35dB以下的离散抖动优先检查PLL相位和滤波器群延迟。峰值频偏验证更简单。mpxRx是根据瞬时频偏还原的MPX基带它的幅度直接代表调制深度。检查max(abs(mpxRx))是否接近1。如果明显超过1说明发射端归一化没做好如果远低于1说明导频和副载波幅度分配不合理可听的动态范围被压缩了。我个人的工程习惯是每次调这类仿真先拿1kHz单音、无噪声条件跑通全链路确认分离度达标后再加入导频、副载波和预加重最后才换音乐素材和加噪。一次只改一个环节中间每个节点的频谱和波形都保存下来。以前我调PLL参数时一次动了好几个系数结果不知道是环路带宽还是群延迟的问题来回折腾了大半天。后来强制自己分段验证问题定位从玄学变成了流程。希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →