Listening to FM Radio in Software, Step by Step

Get started in software-defined radio with a project that can tune in two FM stations at once.

Tying this all together, Figure 6 shows the output of the digital downconverter, and Figure 7 shows the output of the quadrature demodulator. In Figure 7, you can see all the components of the FM waveform. From 0 to about 16kHz is the left plus right (L+R) audio. The peak at 19kHz is the stereo pilot tone. The left minus right (L-R) stereo information is centered at 2x the pilot (38kHz) and is AM-modulated on top of the FM. Additional subcarriers are sometimes found in the region of 57kHz–96kHz.

Figure 6. FFT at Output of Digital Downconverter

Figure 7. FFT of Demodulated FM Signal

To keep life simple, we low pass the output of the quadrature demodulator with a cutoff frequency of 16kHz. This gives us a monaural output that we connect to the sound card outputs.

A Multichannel Receiver

Listing 3, available from the Linux Journal FTP site (see Resources), is the Python code that implements the overall receiver. In fact, it can listen to two FM stations at the same time, one out the left speaker and one out the right! I'm not arguing that this is a particularly practical application, but it does illustrate some of the power of software radio. This idea of extracting multiple stations concurrently could be used as the basis of a multichannel TiVo-like device for radio.

The code is split into three functions. main handles the argument parsing, manages the RF front end and controls the main signal processing loop. If we're receiving a single station, we tell the RF front end to put the station right at the center of the tuner's output frequency, the IF. If we're receiving two stations, we ensure that they're within 5.5MHz of each other. This restriction is due to the SAW filter built in to the cable modem tuner. It's a bandpass filter centered at 5.75MHz that's about 6MHz wide, the width of a North American TV channel. In this case, we split the difference and tune the front end exactly halfway between the two stations. build_graph instantiates the common signal processing blocks and connects them together. In both the single and dual-station modes, we use a single high-speed analog-to-digital converter for input and a single sound card for output. For each station that we want to receive concurrently, we instantiate a digital downconverter, quadrature demodulator and low-pass filter.

There's More Than One Way to Do It!

The maximum number of stations that can be received concurrently is a function of the speed of your computer. Even with our fancy implementation, most of the CPU cycles still are burned in the freq_xlating_fir_filter blocks. What we've described could be called the dumb ADC/brute-force method. One way to free up computational resources is to move the digital downconversion into hardware. Companies such as Texas Instruments, Intersil and Analog Devices sell dedicated ASICs that do this. The strategy used in the Universal Software Radio Peripheral (USRP) is to code the digital downconverter in the Verilog hardware description language and then download the resulting bitstream over the USB into the FPGA. This gives us a combined hardware/software system that maximizes flexibility while still allowing us to off-load some of the more computationally intensive parts into hardware. For more information on the USRP, see the GNU Radio Wiki.



Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.


Anonymous's picture

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

fm demodulation

dinesh's picture

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


saamy's picture

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

JLM's picture

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?