3 from gnuradio import gr, eng_notation
4 from gnuradio import audio
5 # from gnuradio import usrp
6 from gnuradio.eng_option import eng_option
7 from optparse import OptionParser
13 # return a gr.flow_graph
15 def build_graph (input_filename, repeat):
16 adc_rate = 64e6 # USRP A/D sampling rate
17 decim = 250 # FPGA decimated by this amount
19 quad_rate = adc_rate / decim # 256 kHz (the sample rate of the file)
21 audio_rate = quad_rate / audio_decimation # 32 kHz
26 # src = usrp.source_c (0, decim)
27 # src.set_rx_freq (0, -IF_freq)
29 src = gr.file_source (gr.sizeof_gr_complex, input_filename, repeat)
31 (head, tail) = build_pipeline (fg, quad_rate, audio_decimation)
33 # sound card as final sink
34 audio_sink = audio.sink (int (audio_rate))
36 # now wire it all together
37 fg.connect (src, head)
38 fg.connect (tail, (audio_sink, 0))
42 def build_pipeline (fg, quad_rate, audio_decimation):
43 '''Given a flow_graph, fg, construct a pipeline
44 for demodulating a broadcast FM signal. The
45 input is the downconverteed complex baseband
46 signal. The output is the demodulated audio.
48 build_pipeline returns a two element tuple
49 containing the input and output endpoints.
51 fm_demod_gain = 2200.0/32768.0
52 audio_rate = quad_rate / audio_decimation
55 # input: complex; output: float
56 fm_demod = gr.quadrature_demod_cf (volume*fm_demod_gain)
58 # compute FIR filter taps for audio filter
59 width_of_transition_band = audio_rate / 32
60 audio_coeffs = gr.firdes.low_pass (1.0, # gain
61 quad_rate, # sampling rate
62 audio_rate/2 - width_of_transition_band,
63 width_of_transition_band,
64 gr.firdes.WIN_HAMMING)
66 TAU = 75e-6 # 75us in US, 50us in EUR
67 fftaps = [ 1 - math.exp(-1/TAU/quad_rate), 0]
68 fbtaps= [ 0 , math.exp(-1/TAU/quad_rate) ]
69 deemph = gr.iir_filter_ffd(fftaps,fbtaps)
71 # input: float; output: float
72 audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs)
74 fg.connect (fm_demod, deemph)
75 fg.connect (deemph, audio_filter)
76 return ((fm_demod, 0), (audio_filter, 0))
80 usage = "usage: %prog [options] filename"
81 parser = OptionParser (option_class=eng_option, usage=usage)
82 parser.add_option ("-r", "--repeat", action="store_true", default=False)
83 # parser.add_option (... your stuff here...)
84 (options, args) = parser.parse_args ()
90 fg = build_graph (args[0], options.repeat)
92 fg.start () # fork thread(s) and return
93 raw_input ('Press Enter to quit: ')
96 if __name__ == '__main__':