View Raw SPL
/*****************************************************************************
* *
* FREQSAMP.SPL Copyright (C) 1998-2000 DSP Development Corporation *
* All Rights Reserved *
* *
* Author: Randy Race *
* *
* Synopsis: Designs FIR filter from magnitude response *
* *
* Revisions: 28 Apr 1998 RRR Creation *
* 21 Mar 2000 RRR interpolates XY input *
* *
*****************************************************************************/
#include
#if @HELP_FREQSAMP
FREQSAMP
Purpose: Designs a FIR filter from a given magnitude response using
the frequency sampling method
Syntax: FREQSAMP(f, m, full)
f - an XY series specifying the desired frequencies
(in Hertz) and magnitudes of the filter OR an
explicit series specifying the frequencies only
m - an optional series, explicit desired magnitudes
full - an optional integer specifying if f and m
represent the entire magnitude response (default 0)
Returns: A series, the impulse response of the filter
Example:
W1: {0, 1, 10, 20, 30}
W2: {1, 1, 2, 0, 0}
W3: xy(w1, w2)
W4: freqsamp(w3)
W5: mag(fft(w4, bestpow2(length(w4))))
W4 contains a 61 point linear phase FIR filter. The filter
has unity gain from at 0 and 1 Hz and a gain of 2 at
10 Hz. W5 shows the magnitude response of the filter.
Example:
freqsamp(w1, w2)
Same as above except the frequencies and magnitudes
are specified explicitly.
Example:
W1: {1, 1, 2, 1, 0, 0}
W2: Freqsamp(W1);
W3: Mag(fft(w2));overp(w1, lred)
An arbitrary magnitude response is created in W1 and the
magnitude response of the resulting frequency sampling
filter is compared in W3.
Example:
W1: Hamming(gsinc(100, .1, 2*pi, -5*2*pi));setxoffset(-5.0)
W2: Mag(fft(w1))
W3: Freqsamp(w2, 1)
W4: W1-w3
W1 creates a simple 1 Hz low pass filter with a gain of
5.0. The impulse response using the frequency sampling
method is compared to the original impulse response in
W4. The entire magnitude response is used to design the
filter.
Remarks:
The FIR filter is designed by performing the IFFT of the
given magnitude response after adding a linear phase
component. The resulting FIR filter has linear phase.
FREQSAMP sorts the input frequencies in ascending order.
If a frequency of 0 Hz is not specified, a 0 Hz term
equal to the magnitude of the frequency nearest 0
is added to the list.
See Also
Ifft
DADiSP Filters Module
Xyinterp
#endif
/* builds a linear phase FIR filter from a given magnitude response */
freqsamp(f, m, full)
{
local lm, isodd, fmag, L, N, k, p, imp;
local s, h;
if (argc < 3)
{
full = FALSE;
if (argc < 2)
{
m = yvals(f);
f = xvals(f);
}
else
{
if (isscalar(m))
{
full = castint(m);
m = yvals(f);
f = xvals(f);
}
}
}
/* sort values in ascending order */
h = grade(f, 1);
f = f[h];
m = m[h];
/* get XY plot so we can interpolate it */
m = xy(f, m);
/* add DC term if required */
if (f[1] != 0)
{
m = {xy({0}, {m[1]}), m};
printf("freqsamp: Setting DC Value to %g", m[1]);
}
/* interpolate to equally spaced samples */
m = xyinterp(m);
lm = length(m);
isodd = lm % 2;
if (full)
{
/* use given full magnitude response */
fmag = m;
}
else
{
/* build magnitude response by concating mirror image */
if (isodd)
{
fmag = {m, m[lm], rev(m[2..(lm-1)])};
}
else
{
fmag = {m, rev(m[2..(lm-1)])};
}
}
/* linear phase parameters */
L = length(fmag);
if (isodd)
{
N = (L - 1) / 2;
}
else
{
N = L / 2;
}
k = (0..(L - 1));
/* phase */
p = exp(-2 * pi * i * N * k / L);
/*
* IFFT to get impulse response - the imaginary part should
* be zero or close to zero, but we remove it anyway
*/
imp = real(ifft(fmag * p));
/* correct deltax and offset for non-causal response */
setdeltax(imp, rate(m) / L);
setxoffset(imp, -(N)*deltax(imp));
return(imp);
}