Random Quote Board

The Five Methods for Frequency Demodulation

Gary Schafer, March 2025

Yes, I've covered frequency demodulators before (Post #1, Post #2, Post #3). The problem is that I tend to use those posts as references. The information I need is scattered amongst those three posts. Here, I'm going to consolidate the ones that are unique to each other. I'm also going to add some details that I didn't understand (or even know) at the time of the original posts.

There are five unique methods (so far!) for frequency demodulating a signal using digital techniques. These are:

  1. The phase differential method, which provides two, different ways to frequency demodulated a signal.
  2. The FM-to-AM method, which also has two ways to demodulate a signal.
  3. The PLL method
  4. The delay line discriminator
  5. The zero crossing discriminator

Let's dig in.

Phase Differential

Frequency is a change of phase over time. Put in mathematical terms, this is:

\( \Large f = {\Delta \theta \over {\Delta t}} \)

where:

There are two ways to calculate this phase difference. These are to calculate the phase, then calculate the difference. The second is to calculate the difference, then calculate the phase.

The Arctan-and-Derivative Method

The first phase differential method is just calculate the phase of each sample, then subtract the phase between samples. Straightforward, right? Not so fast. There's the +/-π phase boundary problem. My original solution for that was not elegant. Like, at all. Until I read a post on the DSPrelated.com website that explained that there is a way to make it work. It involves the use of integers. In math using integers, typically, if there's overflow (the numbers go past their limits), the numbers will "wrap-around". This means that, if they go past their upper or lower limit, the numbers will go to the other extreme and continue.

For example, using a signed 16-bit integer ("short"), if the value is at the upper limit (+32767), and one more is added, it will flip around to the lower extreme (-32768).

Here's an example using Gnu Radio Companion (GRC). The flowgraph uses a basic sinusoid which is converted from floating point numbers ("floats") to "shorts" (signed 16-bit integers). Due to the scaling at the input of the "Float to Short" block, the sinusoid amplitude is at the limits of what the "short" data type can handle (+/-215). The output is split to show how the addition of values changes the waveform and shows the "wrap-around" affect.

Gnu Radio Companion flowgraph showing blocks connected from left to right. The first block is a \
Gnu Radio Companion (GRC) flowgraph to demonstrate how integer wrapping occurs. The signal source generates a basic sinusoid. That sinusoid is input to the "Float to Short" block, which scales the values such that the sinusoid amplitude is at the limits of what signed 16-bit integers can handle (+/-215). The "Add Const" block adds to these amplitudes such that those values at the upper limit are pushed past the limit. They then "wrap" back to the lower limit (-215).
Time domain display showing the amplitudes of a sinusoid, one the original sinusoid, and the other a sinusoid whose upper values have been pushed past the upper limit, and are wrapped around to the lower limit. The resulting waveform shows the upper part of the sinusoid being dropped to the bottom of the display before suddenly going back up once the values are not past the upper limit.
This is a time domain display of the resulting waveform. The blue line is the original sinuosoid, while the red line is the sinusoid whose upper values have been pushed past the limit of the signed 16-bit integers. Note that the top of the peak is now appearing at the bottom of the display. This is the effect of the "wrap around" that occurs with integers.

We can use this same concept for a frequency demodulator. First, calculate the phase of each sample. Second, convert that phase from floating point to integer. Finally, calculate the difference using integer math (so that any values that cross the +/-π boundary wrap around). I'm going to call this (in honor of Mark Napier, the engineer who allowed me to understand it) the "arctan and derivative" method.

A quick aside. You cannot do with this the floating point numbers, then convert them to integers and expect the "wrapping" to work. In Gnu Radio, any numbers outside of the limits of the integers will not wrap, they will be clipped. Hence, to make this work, you must convert to integer values first, then perform the math that requires the wrapping to occur.

Guess what? It works. Below is a flowgraph using this concept.

Gnu Radio Companion flowgraph showing the demodulation of a frequency modulated signal using the phase and derivative method. The flowgraph shows a \
GRC flowgraph that uses the "arctan and derivative" frequency demodulation method. The filtered signal passes through the "Complex to Arg" block, which calculates the phase of each complex sample. The phase values are scaled by dividing by π (so that the limits are +/-1), then multiplied by 215, so that they're at the limits of what a signed 16-bit integer can handle. Once converted from floating point to short (again, signed 16-bit integer), the delay and subtract blocks calculate the phase difference between samples. Due to the use of the integers, and the fact that any values outside of the limits will wrap around, there are no "spikes" as there were if all of the processing occurred with floating point numbers. Once the samples are converted back to floating point (the "Short to Float" block), the signal is now fully frequency demodulated and can be handled as such.
Two signal displays, one over the other. On top is a time domain display showing the baseband signal from a FM broadcast station. The bottom shows the baseband spectrum from the same station. Both displays show no errors in the signal, showing that the demodulation method works quite well.
The time (top) and spectrum (bottom) of the baseband signal from the FM broadcast station. The time domain display shows no "spikes" that would indicate problems at the +/-π boundary. The spectrum shows a clear FM broadcast station, with all parts of the composite signal clearly seen. This includes the L+R audio channel, the 19 kHz pilot tone, the L-R stereo signal, the RDS signal, and a SCA signal at 67 kHz.

Personally, I think this works really well. My only issue is the conversion to an integer, specifically a "short" (16-bit integer). The 32-bit floating point numbers that GRC normally uses for processing provides 23 bits of dynamic range. Thus, we're losing 7 bits of dynamic range converting to the short. What if we used the GRC "integer" data type (32-bit integer)? Well, in that case, we'd gain 9 bits. Unfortunately, I've not been able to figure out how to make that work in GRC. Yet. I'll keep trying.

The Polar Discriminator

The second method for calculating the phase difference is to first calculate the difference, then calculate the phase. This is the basis of the (improperly-named) Quadrature Demod block in Gnu Radio. You might be wondering, "How do you calculate the difference of the phase before you actually calculate the phase?" Excellent question! It's one of those things that you can do with complex numbers, as James Shima explained in his 1995 paper. Complex numbers can be represented in either Cartesian format (e.g. x+jy) or in polar format (e.g. Me). They are equivalent representations. The values relate as follows:

\( \Large M = \sqrt{x^2 + y^2} \) <- Calculate the magnitude

\( \Large \omega = \arctan \left( {y \over x} \right) \) <- Calculate the phase

This leads to how we can calculate the difference before we calculate the actual phase. If you multiply two complex samples together using the polar notation, you get:

\( \Large M_1 \exp^{j \omega_1} \times M_2 \exp^{j \omega_2} \)

For our purposes, we don't care about the magnitudes. We only care about the phase. This reduces the equation to the following:

\( \Large \exp^{j \omega_1} \times \exp^{j \omega_2} \)

When you multiply two numbers of the same base, their exponents add. Thus, the equation becomes:

\( \Large \exp^{j \omega_1} \times \exp^{j \omega_2} = \exp^{j ( \omega_1 + \omega_2)} \)

This would give us the phase sum. We want the phase difference. To do this, we need to flip the sign of the second value. Since these are complex samples, there's an easy way to do this. That is to flip the sign of the imaginary component. The term for this is the complex conjugate. If we conjugate the second value, we wind up with the following equation:

\( \Large \exp^{j \omega_1} \times \exp^{-j \omega_2} = \exp^{j ( \omega_1 - \omega_2)} \)

This leads to the general flow of calculating the phase difference before you actually calculate the phase is as follows:

  1. Split the samples, with one sample being delayed (to allow for calculating phase between consecutive samples) while the other is unaltered.
  2. Calculate the complex conjugate of the delayed sample. This allows for the calculation of the phase difference.
  3. Multiply the two samples (the original sample and the delayed-and-conjugated sample).

Once you've completed these, three steps, you've calculated the phase difference even though you've not yet calculated the actual phase. The only thing left to do is to calculate the actual phase, which in GRC can be done using the "Complex to Arg" block (the "argument" in math terms is the same as the "arctangent").

At which point, the signal is frequency demodulated. We call this a polar discriminator because we're using the polar format of complex samples to effectively perform the demodulation. To be clear, we DO NOT have to change the complex samples to the polar format before we perform these calculations. We simply take two, consecutive samples, conjugate the previous one, and multiply them together. That's because the Cartesian forms and the polar forms are the same. Thus, looking at the flowgraph below implementing this concept, note that there are no "Cartesian to Polar" blocks. Just conjugate the delayed sample, multiply the two consecutive samples together, calculate the phase of the product sample and VIOLA! Instant frequency demodulation.

But, wait, you might ask. Why doesn't this method have to worry about the +/-π boundary problem? I had the same thought, but I figured out the reason why it works.

What this has done is to calculate the phase difference. But remember that frequency is a change of phase over time. Where's the time difference? Well, since this is a sampled signal, the time difference is the sample period (the time between samples). This leads to:

\( \Large f = { {\Delta\theta} \over {T_S}} \)

where:

Dividing by the sample period is the sample as multiplying by the sample rate. Which means we the calculation can be:

\( \Large f = { {\Delta\theta} \times {f_S}} \)

where:

The one problem left is that the units for this calculation would be in radians. As an engineer, we're used to hertz (Hz). The conversion from radians to Hz is to divide by 2π. The calculation now becomes:

\( \Large f = {{ {\Delta\theta} \times {f_S}} \over {2 \pi}} \) in Hz

where:

The calculation above would provide a result in which the amplitude would be the actual frequency deviation of the original FM signal. For example, in the US, FM broadcast stations use a deviation of 75 kHz or higher (up to 82 kHz, in some cases). Even a relatively narrowband FM transmitter would still be several thousands of Hz. To account for this, the last part of our scaling will be to normalize the output amplitudes due to the deviation. This means to divide by the deviation value. The final equation becomes:

\( \Large f = {{ {\Delta\theta} \times {f_S}} \over {2 \pi \times deviation}} \) in Hz

where:

What we've just calculated is a scaling factor that will be used to put the output of the demodulator into more concrete values that we can use.

Putting this altogether into a flowgraph, we wind up with the following:

GRC flowgraph showing blocks needed for a polar discriminator. A RTL-SDR block in the upper, left connects to a filter. The filter connects splits between a connection straight to a \
The filtered signal is split between an unaltered sample going directly to a "Multiply" block, along with the other half of the split being delayed one sample (for the difference between samples) and conjugated (so that the multiplication turns into a difference value of the phase) before being fed into the other half of the "Multiply" block. The output of the "Multiply" block is a sample whose phase is the phase difference between consecutive samples. The "Complex to Arg" block actually calculates the phase of the difference samples. The "Multiply Const" block scales the phase difference, using the same value as would be put in the "Gain" parameter of the "Quadrature Demod" block. The signal is now fully demodulated.
A constellation display and a time domain display of the output of a polar discriminator.
These two displays show a constellation plot (left) of the output of the "Multiply" block of the polar discriminator. This shows how the samples are centered on the positive x-axis. As these are the phase differences, this is to be expected. The only way the phase difference could be greater than +/-π is for the sample rate to violate the Nyquist limit. The right-most display is from the conversion of the complex samples to the actual phase difference values (after the "Complex to Arg" block).

This frequency demodulation method is how GRC's "Quadrature Demod" block works. Thus, we could replace all of the blocks between the output of the lowpass filter and the input of the time and frequency sinks with the "Quadrature Demod" block, as shown below:

GRC flowgraph showing a small set of blocks going from left to right. The first block is a RTL-SDR source block. It connects to a FFT lowpass filter block, then into a quadrature demod block, which provides the frequency demodulation. The output of the quadrature demod block feeds into a time domain display and a frequency domain display.
GRC flowgraph showing equivalent to that shown above. The delay, complex conjugate, multiply, complex-to-arg and multiply constant blocks are replaced with one block, the "Quadrature Demod" block.
Screenshot showing a time domain display along the top half of the screen and a spectral display along the bottom half. A set of controls cover a thin line at the top of the screen.
This is a screenshot showing the time domain display (top row) and frequency domain display (bottom row) of the baseband signal from a FM broadcast station demodulated using the polar discriminator.

Note that the "Gain" value of the "Quadrature Demod" block is the scaling value we calculated (Gain: (sample rate)/(2*π*deviation)).

There are several variations of the polar discriminator. This includes:

FM-to-AM Conversion

This concept looks at taking the frequency deviation of the FM signal and applying a process that will create an AM signal based on the deviation. There are two methods for this. (NOTE: I originally thought of them as unique; on review, they're really the same just with different methods to create the AM component.) These are slope detection and differentiate and envelope detection. Both methods add an AM component to the FM signal, then AM detect the signal. The only difference is how they create the AM component. The slope detector uses a filter; the differentiate-and-envelope detector uses a differentiator.

Both rely on a frequency offset from the complex center frequency of 0 Hz. The slope detection method offsets a filter from 0 Hz; the differentiate-and-envelope detection method offsets the signal from 0 Hz.

Slope Detection

The idea of the slope detector is that we change the amplitude of the signal based on its instantaneous frequency using the slope of a filter . In other words, we add an amplitude modulation along with the frequency modulation. In other words, we make it both FM and AM at the same time. We create this effect by using a filter with a very wide transition width (the sloped part of the filter). The flowgraph appears as follows:

GRC flowgraph showing several, connected blocks. The first block is a RTL-SDR source block. This connects to a filter block, followed by another bandpass filter. A few virtual blocks connect to top row of blocks with the bottom row. The second row starts with a automatic gain control or AGC block. The AGC connects to a complex-to-mag block, then into a DC block. The output of the DC block goes into a time domain display and a frequency domain display.
This flowgraph uses slope detection to frequency demodulate a FM signal. The input signal (coming out of the lowpass filter) is passed through a bandpass filter that is offset from 0 Hz such that the lower transition band covers 0 Hz. Lower frequencies will experience more attenuation, while higher frequencies will experience less attenuation. As the FM signal deviates between high and low frequencies, it will effectively become amplitude modulated based on the information signal. The follow-on "Complex to Mag" block amplitude demodulates the signal. The AGC before this block and the DC block after it are needed due to the fact that the AM demodulation is noncoherent.

Slope detection requires the use of a filter with a wide transition width. The filter is a complex bandpass filter using complex taps. This allows for it to be offcenter in the spectrum. The lower transition band covers the FM signal, which after being filtered, is the sole signal centered at 0 Hz.

This is a spectral display showing a curve of the bandpass filter. This filter is slightly offcenter, with the majority of the filter above 0 Hz. The lower transition band covers the signal at 0 Hz. The other signal is a filtered FM broadcast station.
This is an overlay showing the spectral impulse response of the bandpass filter (in blue) with the filtered FM signal (in red). Note that the lower transition band of the bandpass filter covers the FM signal.
Zoomed in view of the filter impulse response with the FM signal. There's a curve showing the filter response curving down from right to left, with the spectrum of the FM signal overlaid.
This is a zoomed-in view of the bandpass filter impulse response (blue) with the filtered FM signal (red). Note that, in this view, the slope of the filter can be seen to drop from upper right to lower left. As the FM signal deviates to a lower frequency, its amplitude is also lowered. As the signal deviates to a higher frequency, its amplitude is not attenuated as much.

The result of this demodulator is shown below.

Time domain display and frequency domain display of the frequency demodulated FM broadcast station using the slope detector. The time domain display runs the width of the screen on top, while the spectral display runs the width of the screen underneath it. A thin line at the very top has controls for the center frequency and gain of the SDR.
This is a time domain display (top) and spectrum (bottom) of the frequency demodulated FM station using the slope detection method. Note that, in the spectral display, the base of the 19 kHz pilot tone is rather noisy compared to either of the phase difference methods outlined above.

Comparing this demodulator with the polar discriminator above, it has (in my opinion) worse performance. If you look at the spectral display of the baseband output of the slope detector above, then compare it with the spectrum of the baseband from the polar discriminator, you see a lot more noise at the base of the 19 kHz pilot tone in the slope detector than from the polar discriminator. Further, adding an audio sink, the audio sounded worse (a slight noise present in the slope detector that was not present in the polar discriminator).

Differentiate-and-Envelope Detection

This method also adds an AM component to the FM signal, except it uses a differentiator to add the AM component as opposed to a filter as in the slope detector. The slope detector uses a filter that is offcenter from 0 Hz. In the differentiate-and-envelope detector, the signal is offcenter from 0 Hz before the differentiator is applied.

For this processing, I used the Lyons' 7-tap differentiator. To ensure that the differentiator stays within the linear portion of operation, the sample rate is not decimated after passing through the lowpass filter. Further, the offset of the signal from 0 Hz plays an important part in how well the demodulation works. I've not yet found what I think of as the optimal value for this offset, though it is definitely based on the bandwidth of the signal. A high sample rate is also required to ensure that the signal will not be aliased.

A GRC flowgraph showing three rows of blocks. The top row shows the Options block, a variable block for the sample rate, and three range blocks. These range blocks control the center frequency and gain of the SDR, while the last block controls the volume of the audio output. The second row starts with the SDR, passes through a lowpass filter, a frequency shifter that shifts the frequency of the FM signal so that it is offcenter, a differentiator, an automatic gain control block, a complex-to-mag block which AM detects the signal, a rational resampler to resample the signal so just enough for the FM baseband signal, a DC blocker to remove the DC signal present at the output of the complex-to-mag block, followed by displays for the time domain and spectrum as well as an audio output.
The differentiate-and-envelope detection flowgraph. The output of the SDR passes through a lowpass filter. The filtered FM signal is frequency shifted so that it is slightly offcenter from 0 Hz. This will ensure that the differentiator works as it relies on some amplitude variations for proper operation. The amount of frequency shift will affect how well the frequency demodulator works. The block following is the differentiator, which uses the Lyons' 7-tap differentiator. The resulting AM signal passes through an automatic gain control (AGC) block to ensure it has proper amplitude. The next block, the "Complex to Mag" block, AM detects the signal using a noncoherent method. The "Rational Resampler" adjusts the sample rate to 240 kHz, ensuring it has enough bandwidth for the signal plus a small transition width. The DC block removes the DC signal present at the output of the "Complex to Mag" block. The rest are displays and an audio sink.
A screenshot showing two displays, one on top of the other. The top display runs the width of the screen and shows a spectral display of the output of the differentiate-and-envelope detector. The bottom row shows a time domain display of the same signal. Across the top are two, short rows with controls for the center frequency and gain of the SDR, along with a control of the audio volume.
Spectral and time displays of the output of the differentiate-and-envelope detector. Just as with the slope detector, the spectrum shows some noise present at the base of the 19 kHz pilot tone; however, it is not as high as with the slope detector.

The performance of this demodulator was slightly better than the slope detection method, perhaps because the differentiator is more linear than the slope of the filter, so that frequency changes map more closely to amplitude changes in the information signal. However, its performance will probably never match that of the phase difference methods for the reason posited by James Shima (my emphasis added):

The other issue with using the derivative formulation is that it is not as accurate as the atan version. Why? Because the first order difference in phase of the message is more accurate than the first order difference of the entire signal. In other words, for sinusoidal messages the atan version gives exact results for the true derivative, whereas this is not true for the derivative formulation you listed. As such, for more complex message signals atan version should show less error.

In other words, calculating the difference of the phase is (phase differential) is a far more accurate demodulation method than calculating the difference of the entire signal (differential-and-envelope). Which explains why the differential-and-envelope method does not provide as clean a demodulation as does either the phase differential methods.

Summary

All told, the FM-to-AM conversion demodulators are probably the worst type of FM demodulators. Don't get me wrong; they work. Sort of. But they do not provide as clean a demodulation as the phase difference method. Further, there are some aspects that need to be tweaked. For example, both need a higher sample rate to ensure the differentiators work properly. The differentiate-and-envelope detector also needs its center frequency offset adjusted. These are things that do not exist in the phase difference methods.

The Phase Lock Loop

A phase lock loop (PLL) is a circuit that uses feedback to lock to the frequency of a signal. One of the uses of such a circuit is to demodulate signals, specifically FM signals.

Normally, I would try to make a PLL in Gnu Radio using individual components. Unfortunately, GRC does not have a mechanism to allow feedback within a flowgraph. The good news is that it does have a PLL block that we can use, specifically the "PLL Frequency Detector" block. This block has three parameters. These are:

The nice thing about the "PLL Frequency Detector" block is that, just as with the "Quadrature Demod" block, it is the only block required for demodulation. However, unlike with the "Quadrature Demod" block, the "PLL Frequency Detector" needs a bit of help with the output amplitude. Therefore, a "Multiply Const" block right after will typically be needed if you wish to use it for display or other processing purposes.

Gnu Radio flowgraph for a frequency demodulator using the PLL Frequency Detector block.
Gnu Radio flowgraph showing how to use the "PLL Frequency Detector" block to frequency demodulate a FM broadcast station. The filtered signal is passed through the PLL block. The loop bandwidth, min phase/sample and max phase/sample are set to provide optimal frequency demodulation. The output amplitude will vary, however, so its necessary to add a manual scaling using a "Multiply Const" block. (NOTE: I tried an AGC block in place of the "Multiply Const" block and it was... less than optimal.)
Time domain and spectral displays of the output of the demodulated FM station. The spectral display shows the usual signals of a FM broadcast composite signal.
This is the output of the PLL Frequency Detector. The spectrum shows a better demodulation than with the FM-to-AM conversion methods.

Demodulation with the "PLL Frequency Detector" may be as good as the phase differential methods. However, as the output requires constant amplitude tweaking, I still prefer the more-consistent output of the phase differential methods.

The Delay Line Discriminator

These last two are special in that they require the signal to be changed from complex to real in order to work. Every other frequency demodulator works from complex samples (though there are a couple that can also work from real samples, such as both of the FM-to-AM methods). This one and the next one (the zero crossing discriminator) only work with real samples. That means that the FM signal has to be shifted to an IF, since a real-only signal cannot cross the 0 Hz or Nyquist frequency boundaries. If it does so, it will alias. Let's talk about how to get the signal to an IF for a moment.


The Frequency Shift Method for Processing

Remember how I said earlier that I've picked up a few things since my first posts on FM demodulators back in the dark ages of 2019? Here's one of those things. Rather than tuning the SDR directly to the frequency of the signal being demodulated, filtering it, then frequency shifting it, I'm simply going to tune my SDR offset from the signal center frequency, then filter using a bandpass filter. The output will be a signal whose center frequency is at some IF. The result is the same as if I had used the first method (tune directly to signal, filter, then frequency shift), only it saves the processing of creating the complex sinusoid and multiplying it with the incoming samples. As fred harris points out, the taps for the filter might have different values (due to the fact that I'm using complex taps for the bandpass filter vs the real taps of the lowpass filter), but the number of taps remains the same. This, in turn, means I'm not having to do any more processing for the bandpass vs lowpass filter. They're the same, processing-wise. This will be the method I use for the delay line discriminator and the zero crossing discriminator.


Back to the delay line discriminator. The concept of it is this: if you multiply a sinusoid with one that is the same frequency but 90o (π/2 radians) out of phase with it, then you lowpass filter the product to get rid of the 2x frequency component, the result should be zero. But what if they're not exactly 90o out of phase? Then the result you get depends on whether the out-of-phaseness is more or less than 90o. As the phase is less than 90o, then the result will be DC value less than 0; greater than 90o means a DC value above 0.

How do we implement this concept? Take the FM signal, frequency shift it to an intermediate frequency (IF), convert it to real, then multiply it with a delayed version of itself. It's the amount of delay that is important. We need a delay that is 1/4 cycle of the IF. The 1/4 cycle means the phase difference is 90o. This leads to needing a number of samples per cycle of the IF that is evenly divisible by 4. Here's how I implemented this in Gnu Radio.

GRC flowgraph implementing a delay line discriminator for FM signals.
This is the flowgraph to implement the delay line discriminator. Due to the SDR tuned offset, the filtered FM signal is at an IF. The IF is the sample rate divided by 16. With the sample rate of 2.4 MHz, this means the IF is 2.4e6 / 16 = 150 kHz. The shifted signal is passed through an AGC (since amplitude is important in this case), then the signal is converted from complex to real. (NOTE: Adding the real and imaginary together helps to keep the signal amplitude as high as it can be.) The next, two blocks perform the actual frequency demodulation. Since there are 16 samples/cycle of the IF, a 1/4 delay would be 16/4 = 4 samples. The 1/4 delayed signal is multiplied with the non-delayed signal. After the multiplication, the signal is essentially demodulated. The follow-on lowpass filter removes the 2x IF frequency portion, leaving on the baseband (demodulated) information.

The results are not too shabby, though still not as good as the phase differential methods.

time domain display and spectral display of the baseband output of a delay line discriminator. The spectral display shows the usual output of a FM broadcast station. The time domain shows a somewhat wavy line indicative of a FM broadcast composite signal.
Time and spectral displays from the output of the delay line discriminator. The spectral display is similar to that from the FM-to-AM conversion methods; there's a fair amount of noise present at the base of the 19 kHz pilot tone, which is not present with the phase differential methods.

Zero Crossing Discriminator

This is my favorite method, though it is also the most computationally-expensive one. I like it because it's fun. The concept is this: shift the signal to a IF, convert it from complex to real, then turn each zero crossing of the IF sinusoid into an impulse. Essentially count the impulses. VOILA! The signal is demodulated. Why? Because, due to the frequency modulation, as the signal swings above the center frequency, the period will drop. (Remember, kids: Frequency is the inverse of the period, and the period is the inverse of the frequency.) As the period drops, the impulses will get closer together. This means more of them in a set time. The inverse is true as the frequency swings lower than the center frequency, the number of impulses will drop. These impulses can be "counted" through the straightforward method of lowpass filtering.

The downside to this method (and the reason why it's not a good method for implementing digitally) is that creating the impulses is effectively quantizing the levels based on the sample rate and the IF. The lower the sample rate or the higher the IF, the fewer the quantizing levels. In order to get performance equivalent to the phase differential methods, you need a reeeeeally high sample rate or a reeeeeally low IF. You're limited by the bandwidth of the signal to how low the IF can be. The limit is 1/2 of the bandwidth. For a FM broadcast station, this would be roughly 100 kHz. (NOTE: In the US, the deviation allowed is 75 kHz, with some cases allowing up to 82 kHz.) The maximum sample rate would be whatever your system can handle. In total, this means that this method is not a good one if you're looking to try this on a Raspberry Pi (though perhaps one of the newer ones might be able to handle it).

Gnu Radio flowgraph implementing a zero crossing discriminator.
This is the rather complicated flowgraph to create a zero crossing discriminator. To start, the SDR is offtuned from the desired signal, but still well within the instantaneous bandwidth of the SDR. A bandpass filter (as opposed to a lowpass filter) extracts the desired analog FM station. Using this method, there's no need for a frequency shifter as the signal is already shifted away from 0 Hz in preparation for conversion to real samples. After conversion from complex to real, the AGC block ensures that amplitudes of the samples are adequate to create clear impulses. The follow-on "Rational Resampler" block increases the sample rate in order to improve the "quantizing" noise due to creating impulses on a sampled signal. The delay and multiply blocks create impulses at the zero crossings. If the product of this multiplication is negative, then a zero crossing occurred. All other samples will be discarded. The "Multiply Const" block flips the sign of the samples so that the zero crossings are now positive, and all other samples are negative. The binary slicer turns the zero crossings into clear impulses with a value of 1, and all other samples are set to 0. The last thing to do is to filter the impulses to recover the baseband information. That's the purpose of the "FFT Low Pass Filter", which also adds some gain to ensure that the relatively low amplitude of the filtered impulses can be used for audio.

Using this flowgraph with two, different "interp" values (a value used to increase the sample rate), the results show that a higher sample rate definitely improves the output signal.

A screen showing four different signal displays. A RF spectum in the upper, left, a baseband spectum in the upper right, a time domain display of impulses in the lower left, and a time domain display of the baseband signal.
This is the displays of various aspects of a FM station before, during and after being demodulated using a zero crossing discriminator. The processed sample rate was 2.4 MHz. Note the relative signal-to-noise ratio of the RDS signal in the upper, right baseband spectrum.
A screen showing four different signal displays. A RF spectum in the upper, left, a baseband spectum in the upper right, a time domain display of impulses in the lower left, and a time domain display of the baseband signal.
Displays of the zero crossing discriminator, similar to the previous ones, except the sample rate has been increased by a factor of 10 (24 MHz sample rate). Note the relative SNR of the RDS signal in the upper, right baseband spectrum. Note how it compares to the RDS signal with the lower sample rate processing. Now the RDS has a much higher SNR. This is due to the fact that the higher processing sample rate lowers the "quantizing" noise of creating impulses on a sampled signal.

Again, this is my favorite demodulator despite the fact that it is not really practical for any actual, real-world situation. It's much more complicated, requires a lot more processing, and still will not get to the same accuracy as one of the phase differential methods.

Summary

There you have it. Pretty much every FM demodulator possible using digital techniques. I'm going to consider this my "reference page" for all things FM demodulation from here on. If I come across another demodulator, I probably won't add a blog post. I'll just update this page and add that new technique here.

Til next time!

Here's a Random Fact...