Software Defined Radio

Update - go to this page to get the latest version!

Digital Crystal Set

Here's my software definable radio, and here's the source code. (Take a look at Youssef's update, Summer 2011, below...)

 The Digital Crystal Set...

  • demonstrates that real time signal processing is possible under the Common Language Runtime (CLR).
  • implemented in C# only! No nasty DLLs with C++ or, dare I say it, C.
  • is AM only.
  • only plays wav files.
  • all processing is in the time domain. I'll leave FFTs for a later version.
  • a sampler that just might motivate others to play with SDR using C#. (It did!)

What the Digital Crystal Set is not...

The Digital Crystal Set is not a general purpose Software Defined Radio (SDR). For an SDR that's got features I recommend:

The Manual

Obtain a IQ wav file

Here's a sample I'll use in this manual. The wav file has 2 weak medium wave stations to tune to.

Install the .NET 2.0 runtime.

You'll need the "Microsoft .NET Framework Version 2.0 Redistributable Package (x86)".


Download the Digital Crystal Set and run it.


There's no configuration. You will need a sound card and speakers.


Click Open and select the mwam2.wav. Click Play. You will see the PLL struggle then lock, as you listen to  "DJ-V Bloodshot" on the album Fused Rocking Beats.

Tune away from 1000Hz to -7950Hz. (Yes there's a minus. Don't panic - it just means we're below the local oscillator frequency.) Now you can listen to Sunrise Radio.


Pass through / SDR

Click "Pass through" to listen to the raw IQ. "SDR" reverts to the signal processing path.

Bias and Gain settings

Adds a constant bias / gain to the input stream. Useful if the sound card  / SDR hardware is not balanced. Errors there will introduce the image signal on top of the wanted signal.

With the sample file on 1000Hz, changing any of the settings produces a heterodyne.  (There's a carrier/ sproggy around -1000Hz) The signal on -7950Hz is not so fussy - there's no interfering carrier around 7950Hz.

Mixer Frequency

Use the Mixer Frequency to tune either side of the local oscillator. Useful tuning limits are defined by the sampling rate and the quality of the sound card used in the recording.

Low Pass

This switches in a 3kHz Butterworth 5 pole infinite-impulse-response (IIR) low pass filter. This sits before the AM detector.


This switches in the Phase Locked Loop. The PLL error frequency is displayed here

Each division represents one Hz.

The PLL settings can be changed by clicking on "PLL Settings..." Increasing the bandwidth makes the lock more snappy.

Audio Gain

Audio gain sets the sound volume.

IQ phase plot

This show the IQ phase of the signal before the AM detector.

Source Code

Here's the core of the radio:

The complete original source code can be downloaded here. (Take a look at Youssef's update, Summer 2011, below...)

The mixer down converts the signal to 0 Hz.

There are 2 low pass filters, each for the I and Q signals.

The AM detector take the amplitude of the real signal component, removing the DC component.

Why is the PLL required?

"Why the Phase Locked Loop? - ordinary broadcast radios don't have them."

I'm playing with a synchronous detector.  I could just use the modulus - but that would be too easy!


      public float Demodulate1(Complex d)


            //_dc = 0.99f * _dc + 0.01f * d.Real;

            //return d.Real - _dc;


            return (float) Math.Sqrt(d.Imag * d.Imag + d.Real * d.Real);



The PLL is there to prevent the heterodyne between the station's carrier and the locally generated carrier.

When you tune in a station on an ordinary AM radio there is no heterodyne. There is no locally generated carrier in an ordinary AM radio. (The radio's first local oscillator is used to convert to the IF frequency.)

When recovering audio with SSB, we don't care about the carrier phase. You can resolve SSB on a AM radio by beating with a carrier introduced from a signal generator.

With two sidebands present, the sum of both sidebands are used. Each sideband should not interfere with the other.

The locally generated carrier has to be phase locked to the broadcast carrier, hence the PLL.


Summer 2011, and Youssef Touil contacts me. He's added a simple AM detector and USB and LSB detectors.

The source to his version is here.

Thanks Youssef!

A Year Later...

It's July 2012, a year since I was first in touch with Youssef. He has been exceptionally busy.
Please visit his web site.

(I think the only original part of my code in the SDR# source code is the four letter word "Play" on the winform button!)


Playing with SDR hardware

SDR#  SDRSharp


Comments to [email protected]

Page last updated
14th February 2014

Valid CSS!   Valid XHTML 1.0 Strict