View Raw SPL
/*****************************************************************************
* *
* ZLPFILT.SPL Copyright (C) 2008-2012 DSP Development Corporation *
* All Rights Reserved *
* *
* Author: Randy Race *
* *
* Synopsis: Low pass filtering by FFT zeroing *
* *
* Revisions: 18 Jul 2008 RRR Creation *
* 9 Mar 2012 RRR Optional frequency domain mask return *
* *
*****************************************************************************/
#include
#if @HELP_ZLPFILT
ZLPFILT
Purpose: Performs low pass filtering by zeroing the FFT values.
Syntax: ZLPFILT(s, fc, mask)
s - A series, the input series.
fc - A real, the low pass cutoff frequency. Defaults
to rate(s) / 10.
mask - Optional. An integer, return the frequency domain mask
only. Defaults to 0, return processed input.
Returns:
A series, the low pass filtered output.
Example:
W1: gsin(1000, 1/1000, 20) + gsin(1000, 1/1000, 1)
W2: zlpfilt(w1, 10)
W1 contains a 1 Hz sinewave with 20 Hz high frequency
sinusoidal noise.
W2 filters out the noise an returns the 1 Hz sinusoidal
component.
Remarks:
ZLPFILT performs low pass filtering by zeroing out the
high frequency components of the FFT of the input.
FFT zeroing is a crude but fast filtering operation.
However, the pass band and transition edge of the
equivalent filter will exhibit significant ripple. For a
flatter response, use traditional filter design methods
such as those offered by DADiSP/Filters.
If fc < 0, no filtering is performed.
If mask == 1, the frequency domain binary mask used to zero
out the stopband frequencies is returned.
See ZHPFILT for a high pass filter.
See Also:
DADiSP/Filters
Zhpfilt
#endif
/* FFT zeroing low pass filter */
ITERATE zlpfilt(s, fc, mask)
{
local len, bw, f, q;
if (argc < 3)
{
if (argc < 2)
{
if (argc < 1) error("zlpfilt - input series required");
fc = rate(s) / 10;
}
/* default to process input */
mask = 0;
}
len = length(s);
/* bin frequency width */
bw = rate(s) / len;
/* build low pass frequency mask */
f = zeros(len, 1, bw);
if (fc < 0)
{
/* no filtering, mask is inverted here */
return(mask ? not(f) : s);
}
/* index of samples to retain */
q = int(fc / bw) + 1;
if (q > len / 2)
{
q = len;
}
/* DC range passband */
f[1..q] = 1;
/* nyquist range passband */
if (q >= 2 && q < len)
{
f[(len - q + 2)..len] = 1;
}
if (mask)
{
/* low pass mask */
return(f);
}
else
{
/* frequency domain processing */
f = ifft(fft(s) * f);
if (isreal(s))
{
f = real(f);
}
setxoffset(f, xoffset(s));
return(f);
}
}