View Raw SPL
/*****************************************************************************
* *
* DEMODFM.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_DEMODFM
DEMODFM
Purpose: Demodulates an FM series using the Hilbert Transform
Syntax: DEMODFM(s, fmin, fmax)
s - the input series
fmin - Optional. A real, the minimum modulation frequency used
to scale the result. If not specified, no output scaling
is performed.
fmax - Optional. A real, the maximum modulation frequency used
to scale the result. If not specified, no output scaling
is performed.
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)
W2: modfm(w1, 20, 100)
W3: demodfm(w2)
W4: demodfm(w2, 20, 100)
Same as above except the minimum and maximum modulation
frequencies are specified in W4 to scale the result.
Remarks:
DEMODFM uses HILB to calculate the Hilbert Transform.
See MODFM 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 demodfm(s, fmin, fmax)
{
local h, fm;
if (argc < 3)
{
if (argc < 2)
{
if (argc < 1) error("demodfm - input series required");
/* no scaling */
fmin = -1;
}
fmax = fmin;
}
/* hilbert transform */
h = hilb(s) * exp(-i * 2 * pi * rate(s) * xvals(s));
fm = deriv(unwrap(phase(h))) / (2 * pi);
/* amplitude scaling */
if (fmin > 0 && fmax > 0 && not(fmin == fmax))
{
fm = rescale(fm, min(s), max(s), fmin, fmax);
}
/* restore the offset */
setxoffset(fm, xoffset(s));
return(fm);
}