fm_radio.py 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. #!/usr/bin/env python3
  2. #
  3. # SPDX-License-Identifier: GPL-3.0
  4. #
  5. # GNU Radio Python Flow Graph
  6. # Title: FM Radio Receiver
  7. import gnuradio.analog
  8. import gnuradio.audio
  9. import gnuradio.filter
  10. import gnuradio.gr
  11. import osmosdr
  12. class fm_radio(gnuradio.gr.top_block):
  13. def __init__(self):
  14. gnuradio.gr.top_block.__init__(self, "FM Radio Receiver", catch_exceptions=True)
  15. audio_sample_rate_hertz = 48000
  16. channel_width_hertz = (
  17. 250000 // audio_sample_rate_hertz
  18. ) * audio_sample_rate_hertz
  19. rtlsdr_source = osmosdr.source()
  20. # `rtlsdr_source.get_sample_rates().values()`:
  21. # > TypeError: Unregistered type : std::vector<double, std::allocator<double> >
  22. # minimum for raspberry pi 1B:
  23. rtlsdr_source.set_sample_rate(rtlsdr_source.get_sample_rates().start())
  24. print(f"RTL-SDR sampling rate: {rtlsdr_source.get_sample_rate():.0f} Hz")
  25. rtlsdr_source.set_center_freq((98.3 * 1e6), 0)
  26. resampler = gnuradio.filter.rational_resampler_ccf(
  27. interpolation=channel_width_hertz,
  28. decimation=int(rtlsdr_source.get_sample_rate()),
  29. )
  30. self.connect((rtlsdr_source, 0), (resampler, 0))
  31. assert channel_width_hertz % audio_sample_rate_hertz == 0
  32. wbfm_demodulator = gnuradio.analog.wfm_rcv(
  33. quad_rate=channel_width_hertz,
  34. audio_decimation=channel_width_hertz // audio_sample_rate_hertz,
  35. )
  36. self.connect((resampler, 0), (wbfm_demodulator, 0))
  37. audio_sink = gnuradio.audio.sink(audio_sample_rate_hertz, "", False)
  38. self.connect((wbfm_demodulator, 0), (audio_sink, 0))
  39. # for raspberry pi 1B:
  40. # > RuntimeError: check topology failed on audio_alsa_sink(11) using ninputs=1, noutputs=0
  41. self.connect((wbfm_demodulator, 0), (audio_sink, 1))
  42. def _main():
  43. top_block = fm_radio()
  44. top_block.start()
  45. input("Press Enter to quit: ")
  46. top_block.stop()
  47. top_block.wait()
  48. if __name__ == "__main__":
  49. _main()