在 GNURadio Companion 中收听 FM 广播

背景

以前买过 RTL-SDR,用 Gqrx 做过收音机,当时还给 Homebrew 尝试提交过几个 sdr 相关的 pr,但是限于知识的缺乏,后来就没有再继续尝试了。

前两天,@OceanS2000 讲了一次 Tunight: 高级收音机使用入门,又勾起了我的兴趣,所以我来尝试一下在 GNURadio Companion 中收听 FM 广播电台。

我没有上过无线电相关课程,所以下面有一些内容可能不正确或者不准确。

安装

我的实验环境是 NixOS,所以是用下面的配置来安装 gnuradio 的:

# SDR
# https://github.com/NixOS/nixpkgs/pull/170253
(gnuradio.override { extraMakeWrapperArgs = [ "--prefix" "SOAPY_SDR_PLUGIN_PATH" ":" (soapyrtlsdr + "/lib/SoapySDR/modules0.8/") ]; })
soapysdr-with-plugins

其中 gnuradio 的 override 是为了让它可以找到 soapyrtlsdr 的库,否则它会找不到设备;soapysdr-with-plugins 是为了提供 SoapySDRUtil 命令,来确认它可以找到 RTL-SDR 设备:

$ SoapySDRUtil --probe
----------------------------------------------------
-- Device identification
----------------------------------------------------
  driver=RTLSDR
  hardware=R820T
  origin=https://github.com/pothosware/SoapyRTLSDR
  rtl=0

----------------------------------------------------
-- Peripheral summary
----------------------------------------------------
  Channels: 1 Rx, 0 Tx
  Timestamps: NO
  Other Settings:
     * Direct Sampling - RTL-SDR Direct Sampling Mode
       [key=direct_samp, default=0, type=string, options=(0, 1, 2)]
     * Offset Tune - RTL-SDR Offset Tuning Mode
       [key=offset_tune, default=false, type=bool]
     * I/Q Swap - RTL-SDR I/Q Swap Mode
       [key=iq_swap, default=false, type=bool]
     * Digital AGC - RTL-SDR digital AGC Mode
       [key=digital_agc, default=false, type=bool]

----------------------------------------------------
-- RX Channel 0
----------------------------------------------------
  Full-duplex: NO
  Supports AGC: YES
  Stream formats: CS8, CS16, CF32
  Native format: CS8 [full-scale=128]
  Stream args:
     * Buffer Size - Number of bytes per buffer, multiples of 512 only.
       [key=bufflen, units=bytes, default=262144, type=int]
     * Ring buffers - Number of buffers in the ring.
       [key=buffers, units=buffers, default=15, type=int]
     * Async buffers - Number of async usb buffers (advanced).
       [key=asyncBuffs, units=buffers, default=0, type=int]
  Antennas: RX
  Full gain range: [0, 49.6] dB
    TUNER gain range: [0, 49.6] dB
  Full freq range: [23.999, 1764] MHz
    RF freq range: [24, 1764] MHz
    CORR freq range: [-0.001, 0.001] MHz
  Sample rates: 0.25, 1.024, 1.536, 1.792, 1.92, 2.048, 2.16, 2.56, 2.88, 3.2 MSps

寻找 FM 广播

接着,就可以在 GRC(GNURadio Companion) 中从 RTL-SDR 读取数据了。首先,我按照 Guided Tutorial Hardware Considerations 的方法进行分析,可以看到哪些频率上有信号:

图中的参数:

  • Sample Rate: 3.2MHz,这里要取比较大,如果太小可能找不到信号

可以看到在 100.6MHz 附近有比较明显的信号,查询了一下,这对应了北京新闻广播 FM100.6,确实是一个 FM 广播电台。通过修改中心频率,还可以找到附近的 FM97.4 音乐广播和 FM 103.9 交通广播。

收听 FM 广播

找到频率以后,就可以进行 FM 解调了。我继续按照 FM Demod 的方法进行搭建,由于我用的是 RTL-SDR,考虑到它支持的采样率,我选取了 2.88MHz 采样率,经过一个 1/10 的 Rational Resampler 变成 288KHz 采样率,再进行 FM 解调,最后得到 288KHz / 6 = 48KHz 的音频,然后保存在 WAV 文件中:

图中的参数:

  • Sample Rate: 2.88MHz,这里取了 48KHz 的整数倍数
  • Rational Resampler - Decimation: FM Demod 的 Decimation 不能太大,所以这里先进行 10 倍降采样,把采样率从 2.88MHz 降到 288KHz
  • FM Demod - Channel Rate: 输入的采样率是 288KHz
  • FM Demod - Audio Decimation: 6 倍降采样,这样输出就是 48KHz
  • FM Demod - Deviation: 75KHz,维基百科:The maximum frequency deviation of the carrier is usually specified and regulated by the licensing authorities in each country. For a stereo broadcast, the maximum permitted carrier deviation is invariably ±75 kHz, although a little higher is permitted in the United States when SCA systems are used. For a monophonic broadcast, again the most common permitted maximum deviation is ±75 kHz. However, some countries specify a lower value for monophonic broadcasts, such as ±50 kHz.[5]
  • FM Demod - Audio Pass/Audio Stop: 低通滤波器参数,保留 0-16 KHz 的频率(Passband),到 20KHz 截止(Stopband)

运行一段时间,收听保存下来的 wav 文件,发现可以清晰地听到广播电台的声音。

把输出改成 Audio Sink(Sample Rate = 48KHz),然后就可以当成收音机应用来跑了:

grcc -r rtlsdr_fm_play.grc
comments powered by Disqus