How does one recover the complex IQ data from the output of a FM modulator. I have combined my signals correctly and performed FM modulation on them, now I'm looking for a way to find the IQ values that correspond to each sample output of the FM modulator?

I am writing a modulator for my signal to test the performance of my demodulator and my demodulator depends on complex samples it would receive from a radio.

In other words, how do I perform the down conversion that happens within a tuned radio to produce IQ data?


I am not quite sure if you are asking how to perform the demodulation or how to down-mix a signal at some intermediate frequency to baseband prior to demodulation. I will assume the prior.

If you have the modulated signal it is quite easy to perform demodulation and recover the original signal.

Simply take the angle (atan2) of the output of a delay discriminator. If you are concerned with efficiency you can get fancier with your implementation. Example python code would look like the following:

# Calculate the complex vector between two adjacent data points
vectorDiff = data[1::1] * np.conjugate(data[0:-1:1]);
# Record the angle of the complex difference vectors
fmDemod = np.angle(tmp);

I recently wrote a blog post detailing an FM demodulator I wrote using Python. Here is a link. I used this project as an excuse to learn python and numpy.

** EDIT ** Quick and dirty way to perform down-conversion using the hilbert transform prior to FM demodulation (in python)

# Import the plotting library
from matplotlib import pyplot as plot
import scipy.signal
import numpy as np

# Define the setup
fCarrier = 10;
fAudio = 1;
fs = 1000;
timeEnd = 1;
time = np.linspace(0,2,fs*timeEnd);

# Create the signals
carrier = np.sin(2*np.pi*fCarrier*time);
audio = np.sin(2*np.pi*fAudio*time);
audioInt = -np.cos(2*np.pi*fAudio*time);
freqMod = np.sin(2*np.pi*fCarrier*time + 2*np.pi*1*audioInt);

# Downconvert
analyticSignal = scipy.signal.hilbert(freqMod); # wikipedia analytic signal
baseband = analyticSignal * np.exp(-2*np.pi*fCarrier*time*1j); # complex mixing
audioDemod = np.angle( baseband[1::1] * np.conjugate(baseband[0:-1:1]) ); # fm demod
  • $\begingroup$ I'm looking for the way to extract the complex values for a FM modulated signal (similar to what a radio would provide you). I'm modulating a signal using FM modulation which produces a composite (ampl/time) signal and I want the I and Q values that a radio would give if tuned to a frequency where someone was transmitting that signal. $\endgroup$ – tylerjw Oct 13 '14 at 14:41
  • $\begingroup$ So you have a real valued FM modulated signal that you'd like to demodulate. You need to perform a complex mixing (also called iq mixing or complex demodulation) operation to baseband the signal prior to performing the steps I suggested above. Check out the "How It Works" section of this PDF. It does a decent job of illustrating what you need to do: hunteng.co.uk/pdfs/tech/ddctheory.pdf I edited my answer above to include a quick and dirty way to do this using the hilbert transform. $\endgroup$ – dswiston Oct 18 '14 at 1:47

To add to @dswiston answer:

# Calculate the complex vector between two adjacent data points
vectorDiff = data[1::1] * np.conjugate(data[0:-1:1]);
# Record the angle of the complex difference vectors
fmDemodPhase = np.angle(vectorDiff);

It's worth adding another line that correlates the phase angle to absolute frequency:

fm = (fmDemodPhase * SampleRate) / (2 * np.pi)

Which gives an absolute frequency.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.