# Listening to FM Radio in Software, Step by Step

Figure 5 shows our strategy for listening to an FM station. If we remove the carrier, we're left with a baseband signal that has an instantaneous frequency proportional to the original message m(t). Thus, our challenge is to find a way to remove the carrier and compute the instantaneous frequency.

The first part is easy. We get rid of the carrier by using our software digital downconverter (DDC) block, freq_xlating_fir_filter_scf. This block is composed conceptually of a numerically controlled oscillator that generates sine and cosine waveforms at the frequency that we want to translate to zero, a mixer (that's a multiplier to us software folks) and a decimating finite impulse response filter. The scf suffix indicates that this block takes a stream of shorts on its input, produces a stream of complexes on its output and uses floating-point taps to specify the filter.

The digital downconverter does its job by taking advantage of a trigonometric identity that says when you multiply two sinusoids of frequency f1 and f2 together, the result is composed of two new sinusoids, one at f1+f2 and the other at f1–f2. In our case, we multiply the incoming signal by the frequency of the carrier. The output consists of two components, one at 2x the carrier and one at zero. We get rid of the 2x component with a low-pass filter, leaving us the baseband signal.

A straightforward implementation of the digital downconverter block in software is extremely expensive computationally. We'd be performing the sine and cosine generation and multiplication at the full input rate. On a Pentium 4, computing sine and cosine takes on the order of 150 cycles. Given a 20M sample/sec input stream, we'd be burning up 20e6 * 150 = 3e9 cycles/sec merely computing sine and cosine! Definitely a non-starter.

The good news is there's a better way to implement the DDC in software. This technique, described by Vanu Bose, et al., in “Virtual Radios” (see Resources), allows us to run all of the computation at the decimated rate by rearranging the order of the operations and using frequency-specific complex filter coefficients instead of real coefficients. The end result is a big win! We can do it in real time!

The next job is to compute the instantaneous frequency of the baseband signal. We use the quadrature_demod_cf block for this. We approximate differentiating the phase by determining the angle between adjacent samples. Recall that the downconverter block produces complex numbers on its output. Using a bit more trigonometry, we can determine the angle between two subsequent samples by multiplying one by the complex conjugate of the other and then taking the arc tangent of the product. Listings 1 and 2 show the implementation of the quadrature_demod_cf block. Once you know what you want, it doesn't take much code. The bulk of the signal processing is the three-line loop in sync_work.

**
Listing 1. Quadrature Demodulator Header**

/* * Copyright 2004 Free Software Foundation, Inc. * * This file is part of GNU Radio * * GNU Radio is free software; you can redistribute * it and/or modify it under the terms of the GNU * General Public License as published by the Free * Software Foundation; either version 2, or (at * your option) any later version. */ #ifndef INCLUDED_GR_QUADRATURE_DEMOD_CF_H #define INCLUDED_GR_QUADRATURE_DEMOD_CF_H #include <gr_sync_block.h> class gr_quadrature_demod_cf; typedef boost::shared_ptr<gr_quadrature_demod_cf> gr_quadrature_demod_cf_sptr; gr_quadrature_demod_cf_sptr gr_make_quadrature_demod_cf (float gain); /* * quadrature demodulator: complex in, float out */ class gr_quadrature_demod_cf : public gr_sync_block { friend gr_quadrature_demod_cf_sptr gr_make_quadrature_demod_cf (float gain); gr_quadrature_demod_cf (float gain); float d_gain; public: int sync_work ( int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); }; #endif /* INCLUDED_GR_QUADRATURE_DEMOD_CF_H */

## Trending Topics

My Childhood in a Cigar Box | Jan 17, 2017 |

Rogue Wave Software's TotalView for HPC and CodeDynamics | Jan 13, 2017 |

Papa's Got a Brand New NAS | Jan 12, 2017 |

Panther MPC, Inc.'s Panther Alpha | Jan 11, 2017 |

Simplenote, Simply Awesome! | Jan 10, 2017 |

GENIVI Alliance's GENIVI Vehicle Simulator | Jan 09, 2017 |

- My Childhood in a Cigar Box
- Tech Tip: Really Simple HTTP Server with Python
- Papa's Got a Brand New NAS
- Applied Expert Systems, Inc.'s CleverView for TCP/IP on Linux
- Panther MPC, Inc.'s Panther Alpha
- Rogue Wave Software's TotalView for HPC and CodeDynamics
- Simplenote, Simply Awesome!
- Returning Values from Bash Functions
- Debugging Democracy
- NethServer: Linux without All That Linux Stuff

## Comments

## @dinesh

and that is why lots of americans don't have jobs, right?

## fm demodulation

sir, i need the total detail of fm demodulation which have sdr applications using vhdl domain and also matlab programs and vhdl coding for all about fm demodu.........

fm demodu rceiver circuit diagram also plz send it to my mailid as soon as possible sir

## details

I would like to start a New Fm station. can u give the details for what r the software we want to bye

## Off-Line station break-out

If the break-down of the signal(s) into multiple stations is too much for your CPU, how about recording a more raw version of the input and then breaking it down into multiple stations at a more leisurely rate, possibly even on more than one computer.

If this seems reasonable, could you give some ideas on where to make these changes?

Thanks