#!/usr/bin/env python from gnuradio import gr, eng_notation from gnuradio import audio from gnuradio import usrp from gnuradio.eng_option import eng_option from optparse import OptionParser import sys import math # # Tune a demodulate a narrow band FM audio signal from an IF stream. # # @param fileName file that contains 256ksps complex IF data in gr format # @param channelOffset frequency to tune where 0 is center of sampled IF # # @return flow_graph # def build_graph (fileName, channelOffset): adc_rate = 64e6 usrp_decim = 250 if_rate = adc_rate / usrp_decim # 256 kHz if_decim = 4 demod_rate = if_rate / if_decim # 64 kHz audio_decimation = 2 audio_rate = demod_rate / audio_decimation # 16 kHz fg = gr.flow_graph () src = gr.file_source (gr.sizeof_gr_complex, fileName) (head, tail) = build_pipeline (fg, if_rate, if_decim, audio_rate, audio_decimation, channelOffset) # sound card as final sink audio_sink = audio.sink (int (audio_rate)) # now wire it all together fg.connect (src, head) fg.connect (tail, (audio_sink, 0)) return fg def build_pipeline (fg, if_rate, if_decim, audio_rate, audio_decimation, channelOffset): # Filter around FM modulated channel (16KHz wide) = 2 * (5KHz Deviation + 3KHz Max Audio Freq) # Note the FM modulated bandwidth is wider than the audio pass band. # This filter gives us our adjacent channel rejection. channel_coeffs = gr.firdes.low_pass (1.0, if_rate, 10e3, 6e3, gr.firdes.WIN_HANN) # Select desired channel ddc = gr.freq_xlating_fir_filter_ccf (if_decim, channel_coeffs, channelOffset, if_rate) # Demod and scale to prevent overflow. fm_demod = gr.quadrature_demod_cf (0.2) # Filter the output audio. # We use a band pass to get rid of the 60Hz AC hum on the signal. # Some of the NOAA equipment is very old. # The real audio band pass is 150 - 5000Hz because we decimate down 2:1. audio_coeffs = gr.firdes.band_pass (1.0, if_rate, 300, 10000, 1000, gr.firdes.WIN_HANN) audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) # Connect the chain fg.connect (ddc, fm_demod) fg.connect (fm_demod, audio_filter) return ((ddc, 0), (audio_filter, 0)) def main (args): if len(args) != 2: sys.stderr.write ('usage: nfm_rcv_file filename tuning(KHz)\n') sys.exit (1) fg = build_graph (args[0], float(args[1]) * 1000) fg.start () # fork thread(s) and return raw_input ('Press Enter to quit: ') fg.stop () if __name__ == '__main__': main (sys.argv[1:])