DSP

SDR# (SDRSharp)代码讲解 (四)

2019-07-13 20:04发布

前面讲完了AMDetector.cs,可以说你已经入了SDRDSP的门了,也具备一定的读代码能力了,接下去的无非是举一反三,按照之前说的那套格式实现其它类型的解调算法。比如我们接下来要讲的FMDetector.cs,总体结构和AMDetector.cs是很相似的,最重要的部分也是这个模块中对应的Demodulate方法。
这个Demodulate里的算法其实就是参照书中381页的9.7节的算法,只不过稍微有点区别,书里的算法是一路信号通过移相器取了共轭后,另一路信号做了延迟,然后把两路信号相乘后取角得到解调出的信号。
我们这里算法稍微有点不同,是把同一路的信号既做了延迟,又取了共轭。而与它相乘的另一路信号什么都没做。这两路信号相乘后,还是利用c#里的Argument函数实现了取角。
这两种方法实际上是同一种方法,最终实际解调出的波形只是符号反一反(有待确认?)。
所以Demodulate中最核心的其实只有3行代码。 var f=iq[i]*_iqState.Conjugate() 用于取共轭和乘法 var a=f.Argument() 用于取角 _iqState=iq[i] 用于实现延迟
这里实现延迟的方法比较巧妙,是利用了上一个循环中保留下来的iq数据存入_iqState中,这样它对于下一次循环就是经过延迟一个采样点的iq数据了,符合我们的预期,然后就可以取共轭,再相乘,最后取角了。
除了这些最核心的代码外,这个fm解调算法还有一些其他的内容,比如,如果那个乘法的结果过大,可以用一个缩放因子来减小它,然后再取角。
另外,FM信号还分窄带和宽带FM信号。如果是窄带FM信号,我们的解调算法还会调用ProcessSquelch方法对前面解调出的音频数据做进一步的处理。具体是用了hissFilter来对前面解调的audio数据做了滤波,这个hissFilter是用FirFilter这个类实现的。
然后在第95行把经过滤波的数据又去取了一下幅值,注意,别看这行里的变量很多,名字很长,其实_noiseAveragingRatio就是一个常量而已,这一行代码只是把前面的滤波结果再次做了一个低通滤波,然后把滤波出来的结果比较了一下预先设置的阈值,如果太响就静音。
个人认为这一段代码没必要细看,先不说这样的处理方式到底能提高多少效果,FM解调中窄带FM也只是一种特殊情况而已,这个FM解调算法只对窄带FM做了这种复杂的操作,而宽带FM根本不需要经过这些处理,照样能解调,那么这段代码不看也罢,照样可以认为看懂FM解调了,读者有兴趣也可以在前面Demodulate中注释掉这部分代码,包括后面对增益的修改,看看窄带FM的效果到底有多大区别。