View Raw SPL
/*****************************************************************************
* *
* FMDEMOD.SPL Copyright (C) 2000-2013 DSP Development Corporation *
* All Rights Reserved *
* *
* Author: Randy Race *
* *
* Synopsis: FM Demodulation using the Hilbert Transform *
* *
* Revisions: 8 Feb 2000 RRR Creation *
* 22 May 2013 RRR optional fmin/fmax modulation range *
* *
*****************************************************************************/
#if @HELP_FMDEMOD
FMDEMOD
Purpose: Demodulates an FM series using the Hilbert Transform
Syntax: FMDEMOD(s, fc, fdev)
s - the input series
fc - Optional, a real. The center frequency of the frequency
modulated result. Defaults to -1, estimate the center
frequency using the FFT.
fdev - Optional, a real. The frqeuency deviation. Defaults to 1.
Returns: A series or array
Example:
W1: gtriwave(1000,.001, 4)
W2: W1 * 100 + 20
W3: cos(integ(2*pi*w2))
W4: demodfm(w3)
W2 represents the scaled information signal and W3 is the
resulting frequency modulated signal. The amplitude of W2
determines the instantaneous frequency of W3. The instantaneous
frequency of W3 ranges from:
min(w3) == 20 Hz
to
max(w3) == 120 Hz
W4 is the demodulated result.
Example:
W1: gtriwave(1000, .001, 4) * 100 + 20
W2: fmmod(w1, 200, 2)
W3: fmdemodfm(w2, 200, 2)
Same as above except the minimum and maximum modulation
frequencies are specified in W4 to scale the result.
Remarks:
FMDEMOD uses HILB to calculate the Hilbert Transform.
If FC is < 0, the center frequency is estimated using
SINFIT3.
See FMMOD to frequency modulate a series.
See DEMODAM to demodulate an amplitude modulated series.
See Also:
Demodam
Hilb
Modfm
#endif
/* demodulate an FM series using the Hilbert transform */
ITERATE fmdemod(s, fc, fdev)
{
local h, fm, fit, coef;
if (argc < 3)
{
if (argc < 2)
{
if (argc < 1) error("fmdemod - input series required");
/* estimate frequency */
fc = -1;
}
fdev = 1;
}
if (fc < 0)
{
/* estimate center frequency */
(fit, coef) = sinfit3(s);
fc = coef[2];
}
/* hilbert transform */
h = hilb(s) * exp(-i * 2 * pi * fc * xvals(s));
fm = deriv(unwrap(phase(h))) / (2 * pi * fdev);
/* restore the offset */
setxoffset(fm, xoffset(s));
return(fm);
}