summaryrefslogtreecommitdiff
path: root/gnuradio-core/src/python/gnuradio/optfir.py
diff options
context:
space:
mode:
Diffstat (limited to 'gnuradio-core/src/python/gnuradio/optfir.py')
-rw-r--r--gnuradio-core/src/python/gnuradio/optfir.py359
1 files changed, 0 insertions, 359 deletions
diff --git a/gnuradio-core/src/python/gnuradio/optfir.py b/gnuradio-core/src/python/gnuradio/optfir.py
deleted file mode 100644
index bbd48dae75..0000000000
--- a/gnuradio-core/src/python/gnuradio/optfir.py
+++ /dev/null
@@ -1,359 +0,0 @@
-#
-# Copyright 2004,2005,2009 Free Software Foundation, Inc.
-#
-# This file is part of GNU Radio
-#
-# GNU Radio is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GNU Radio is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Radio; see the file COPYING. If not, write to
-# the Free Software Foundation, Inc., 51 Franklin Street,
-# Boston, MA 02110-1301, USA.
-#
-
-'''
-Routines for designing optimal FIR filters.
-
-For a great intro to how all this stuff works, see section 6.6 of
-"Digital Signal Processing: A Practical Approach", Emmanuael C. Ifeachor
-and Barrie W. Jervis, Adison-Wesley, 1993. ISBN 0-201-54413-X.
-'''
-
-import math, cmath
-from gnuradio import gr
-
-remez = gr.remez
-
-def low_pass (gain, Fs, freq1, freq2, passband_ripple_db, stopband_atten_db,
- nextra_taps=2):
- """
- Builds a low pass filter.
-
- Args:
- gain: Filter gain in the passband (linear)
- Fs: Sampling rate (sps)
- freq1: End of pass band (in Hz)
- freq2: Start of stop band (in Hz)
- passband_ripple_db: Pass band ripple in dB (should be small, < 1)
- stopband_atten_db: Stop band attenuation in dB (should be large, >= 60)
- nextra_taps: Extra taps to use in the filter (default=2)
- """
- passband_dev = passband_ripple_to_dev (passband_ripple_db)
- stopband_dev = stopband_atten_to_dev (stopband_atten_db)
- desired_ampls = (gain, 0)
- (n, fo, ao, w) = remezord ([freq1, freq2], desired_ampls,
- [passband_dev, stopband_dev], Fs)
- # The remezord typically under-estimates the filter order, so add 2 taps by default
- taps = gr.remez (n + nextra_taps, fo, ao, w, "bandpass")
- return taps
-
-def band_pass (gain, Fs, freq_sb1, freq_pb1, freq_pb2, freq_sb2,
- passband_ripple_db, stopband_atten_db,
- nextra_taps=2):
- """
- Builds a band pass filter.
-
- Args:
- gain: Filter gain in the passband (linear)
- Fs: Sampling rate (sps)
- freq_sb1: End of stop band (in Hz)
- freq_pb1: Start of pass band (in Hz)
- freq_pb2: End of pass band (in Hz)
- freq_sb2: Start of stop band (in Hz)
- passband_ripple_db: Pass band ripple in dB (should be small, < 1)
- stopband_atten_db: Stop band attenuation in dB (should be large, >= 60)
- nextra_taps: Extra taps to use in the filter (default=2)
- """
- passband_dev = passband_ripple_to_dev (passband_ripple_db)
- stopband_dev = stopband_atten_to_dev (stopband_atten_db)
- desired_ampls = (0, gain, 0)
- desired_freqs = [freq_sb1, freq_pb1, freq_pb2, freq_sb2]
- desired_ripple = [stopband_dev, passband_dev, stopband_dev]
- (n, fo, ao, w) = remezord (desired_freqs, desired_ampls,
- desired_ripple, Fs)
- # The remezord typically under-estimates the filter order, so add 2 taps by default
- taps = gr.remez (n + nextra_taps, fo, ao, w, "bandpass")
- return taps
-
-
-def complex_band_pass (gain, Fs, freq_sb1, freq_pb1, freq_pb2, freq_sb2,
- passband_ripple_db, stopband_atten_db,
- nextra_taps=2):
- """
- Builds a band pass filter with complex taps by making an LPF and
- spinning it up to the right center frequency
-
- Args:
- gain: Filter gain in the passband (linear)
- Fs: Sampling rate (sps)
- freq_sb1: End of stop band (in Hz)
- freq_pb1: Start of pass band (in Hz)
- freq_pb2: End of pass band (in Hz)
- freq_sb2: Start of stop band (in Hz)
- passband_ripple_db: Pass band ripple in dB (should be small, < 1)
- stopband_atten_db: Stop band attenuation in dB (should be large, >= 60)
- nextra_taps: Extra taps to use in the filter (default=2)
- """
- center_freq = (freq_pb2 + freq_pb1) / 2.0
- lp_pb = (freq_pb2 - center_freq)/1.0
- lp_sb = freq_sb2 - center_freq
- lptaps = low_pass(gain, Fs, lp_pb, lp_sb, passband_ripple_db,
- stopband_atten_db, nextra_taps)
- spinner = [cmath.exp(2j*cmath.pi*center_freq/Fs*i) for i in xrange(len(lptaps))]
- taps = [s*t for s,t in zip(spinner, lptaps)]
- return taps
-
-
-def band_reject (gain, Fs, freq_pb1, freq_sb1, freq_sb2, freq_pb2,
- passband_ripple_db, stopband_atten_db,
- nextra_taps=2):
- """
- Builds a band reject filter
- spinning it up to the right center frequency
-
- Args:
- gain: Filter gain in the passband (linear)
- Fs: Sampling rate (sps)
- freq_pb1: End of pass band (in Hz)
- freq_sb1: Start of stop band (in Hz)
- freq_sb2: End of stop band (in Hz)
- freq_pb2: Start of pass band (in Hz)
- passband_ripple_db: Pass band ripple in dB (should be small, < 1)
- stopband_atten_db: Stop band attenuation in dB (should be large, >= 60)
- nextra_taps: Extra taps to use in the filter (default=2)
- """
- passband_dev = passband_ripple_to_dev (passband_ripple_db)
- stopband_dev = stopband_atten_to_dev (stopband_atten_db)
- desired_ampls = (gain, 0, gain)
- desired_freqs = [freq_pb1, freq_sb1, freq_sb2, freq_pb2]
- desired_ripple = [passband_dev, stopband_dev, passband_dev]
- (n, fo, ao, w) = remezord (desired_freqs, desired_ampls,
- desired_ripple, Fs)
- # Make sure we use an odd number of taps
- if((n+nextra_taps)%2 == 1):
- n += 1
- # The remezord typically under-estimates the filter order, so add 2 taps by default
- taps = gr.remez (n + nextra_taps, fo, ao, w, "bandpass")
- return taps
-
-
-def high_pass (gain, Fs, freq1, freq2, passband_ripple_db, stopband_atten_db,
- nextra_taps=2):
- """
- Builds a high pass filter.
-
- Args:
- gain: Filter gain in the passband (linear)
- Fs: Sampling rate (sps)
- freq1: End of stop band (in Hz)
- freq2: Start of pass band (in Hz)
- passband_ripple_db: Pass band ripple in dB (should be small, < 1)
- stopband_atten_db: Stop band attenuation in dB (should be large, >= 60)
- nextra_taps: Extra taps to use in the filter (default=2)
- """
- passband_dev = passband_ripple_to_dev (passband_ripple_db)
- stopband_dev = stopband_atten_to_dev (stopband_atten_db)
- desired_ampls = (0, 1)
- (n, fo, ao, w) = remezord ([freq1, freq2], desired_ampls,
- [stopband_dev, passband_dev], Fs)
- # For a HPF, we need to use an odd number of taps
- # In gr.remez, ntaps = n+1, so n must be even
- if((n+nextra_taps)%2 == 1):
- n += 1
-
- # The remezord typically under-estimates the filter order, so add 2 taps by default
- taps = gr.remez (n + nextra_taps, fo, ao, w, "bandpass")
- return taps
-
-# ----------------------------------------------------------------
-
-def stopband_atten_to_dev (atten_db):
- """Convert a stopband attenuation in dB to an absolute value"""
- return 10**(-atten_db/20)
-
-def passband_ripple_to_dev (ripple_db):
- """Convert passband ripple spec expressed in dB to an absolute value"""
- return (10**(ripple_db/20)-1)/(10**(ripple_db/20)+1)
-
-# ----------------------------------------------------------------
-
-def remezord (fcuts, mags, devs, fsamp = 2):
- '''
- FIR order estimator (lowpass, highpass, bandpass, mulitiband).
-
- (n, fo, ao, w) = remezord (f, a, dev)
- (n, fo, ao, w) = remezord (f, a, dev, fs)
-
- (n, fo, ao, w) = remezord (f, a, dev) finds the approximate order,
- normalized frequency band edges, frequency band amplitudes, and
- weights that meet input specifications f, a, and dev, to use with
- the remez command.
-
- * f is a sequence of frequency band edges (between 0 and Fs/2, where
- Fs is the sampling frequency), and a is a sequence specifying the
- desired amplitude on the bands defined by f. The length of f is
- twice the length of a, minus 2. The desired function is
- piecewise constant.
-
- * dev is a sequence the same size as a that specifies the maximum
- allowable deviation or ripples between the frequency response
- and the desired amplitude of the output filter, for each band.
-
- Use remez with the resulting order n, frequency sequence fo,
- amplitude response sequence ao, and weights w to design the filter b
- which approximately meets the specifications given by remezord
- input parameters f, a, and dev:
-
- b = remez (n, fo, ao, w)
-
- (n, fo, ao, w) = remezord (f, a, dev, Fs) specifies a sampling frequency Fs.
-
- Fs defaults to 2 Hz, implying a Nyquist frequency of 1 Hz. You can
- therefore specify band edges scaled to a particular applications
- sampling frequency.
-
- In some cases remezord underestimates the order n. If the filter
- does not meet the specifications, try a higher order such as n+1
- or n+2.
- '''
- # get local copies
- fcuts = fcuts[:]
- mags = mags[:]
- devs = devs[:]
-
- for i in range (len (fcuts)):
- fcuts[i] = float (fcuts[i]) / fsamp
-
- nf = len (fcuts)
- nm = len (mags)
- nd = len (devs)
- nbands = nm
-
- if nm != nd:
- raise ValueError, "Length of mags and devs must be equal"
-
- if nf != 2 * (nbands - 1):
- raise ValueError, "Length of f must be 2 * len (mags) - 2"
-
- for i in range (len (mags)):
- if mags[i] != 0: # if not stopband, get relative deviation
- devs[i] = devs[i] / mags[i]
-
- # separate the passband and stopband edges
- f1 = fcuts[0::2]
- f2 = fcuts[1::2]
-
- n = 0
- min_delta = 2
- for i in range (len (f1)):
- if f2[i] - f1[i] < min_delta:
- n = i
- min_delta = f2[i] - f1[i]
-
- if nbands == 2:
- # lowpass or highpass case (use formula)
- l = lporder (f1[n], f2[n], devs[0], devs[1])
- else:
- # bandpass or multipass case
- # try different lowpasses and take the worst one that
- # goes through the BP specs
- l = 0
- for i in range (1, nbands-1):
- l1 = lporder (f1[i-1], f2[i-1], devs[i], devs[i-1])
- l2 = lporder (f1[i], f2[i], devs[i], devs[i+1])
- l = max (l, l1, l2)
-
- n = int (math.ceil (l)) - 1 # need order, not length for remez
-
- # cook up remez compatible result
- ff = [0] + fcuts + [1]
- for i in range (1, len (ff) - 1):
- ff[i] *= 2
-
- aa = []
- for a in mags:
- aa = aa + [a, a]
-
- max_dev = max (devs)
- wts = [1] * len(devs)
- for i in range (len (wts)):
- wts[i] = max_dev / devs[i]
-
- return (n, ff, aa, wts)
-
-# ----------------------------------------------------------------
-
-def lporder (freq1, freq2, delta_p, delta_s):
- '''
- FIR lowpass filter length estimator. freq1 and freq2 are
- normalized to the sampling frequency. delta_p is the passband
- deviation (ripple), delta_s is the stopband deviation (ripple).
-
- Note, this works for high pass filters too (freq1 > freq2), but
- doesnt work well if the transition is near f == 0 or f == fs/2
-
- From Herrmann et al (1973), Practical design rules for optimum
- finite impulse response filters. Bell System Technical J., 52, 769-99
- '''
- df = abs (freq2 - freq1)
- ddp = math.log10 (delta_p)
- dds = math.log10 (delta_s)
-
- a1 = 5.309e-3
- a2 = 7.114e-2
- a3 = -4.761e-1
- a4 = -2.66e-3
- a5 = -5.941e-1
- a6 = -4.278e-1
-
- b1 = 11.01217
- b2 = 0.5124401
-
- t1 = a1 * ddp * ddp
- t2 = a2 * ddp
- t3 = a4 * ddp * ddp
- t4 = a5 * ddp
-
- dinf=((t1 + t2 + a3) * dds) + (t3 + t4 + a6)
- ff = b1 + b2 * (ddp - dds)
- n = dinf / df - ff * df + 1
- return n
-
-
-def bporder (freq1, freq2, delta_p, delta_s):
- '''
- FIR bandpass filter length estimator. freq1 and freq2 are
- normalized to the sampling frequency. delta_p is the passband
- deviation (ripple), delta_s is the stopband deviation (ripple).
-
- From Mintzer and Liu (1979)
- '''
- df = abs (freq2 - freq1)
- ddp = math.log10 (delta_p)
- dds = math.log10 (delta_s)
-
- a1 = 0.01201
- a2 = 0.09664
- a3 = -0.51325
- a4 = 0.00203
- a5 = -0.57054
- a6 = -0.44314
-
- t1 = a1 * ddp * ddp
- t2 = a2 * ddp
- t3 = a4 * ddp * ddp
- t4 = a5 * ddp
-
- cinf = dds * (t1 + t2 + a3) + t3 + t4 + a6
- ginf = -14.6 * math.log10 (delta_p / delta_s) - 16.9
- n = cinf / df + ginf * df + 1
- return n
-