Merge branch 'dfsg-orig'
[debian/gnuradio] / gnuradio-core / src / python / gnuradio / optfir.py
index bd43fcc9744bc64fbd187456c74d34042782e99f..aee1d2a0c19ac819aa7d6b2b632c2284d1915761 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright 2004,2005 Free Software Foundation, Inc.
+# Copyright 2004,2005,2009 Free Software Foundation, Inc.
 # 
 # This file is part of GNU Radio
 # 
@@ -27,32 +27,131 @@ For a great intro to how all this stuff works, see section 6.6 of
 and Barrie W. Jervis, Adison-Wesley, 1993.  ISBN 0-201-54413-X.
 '''
 
-import math
+import math, cmath
 from gnuradio import gr
 
 remez = gr.remez
 
 # ----------------------------------------------------------------
 
+##  Builds a low pass filter.
+#   @param gain  Filter gain in the passband (linear)
+#   @param Fs    Sampling rate (sps)
+#   @param freq1 End of pass band (in Hz)
+#   @param freq2 Start of stop band (in Hz)
+#   @param passband_ripple_db Pass band ripple in dB (should be small, < 1)
+#   @param stopband_atten_db  Stop band attenuation in dB (should be large, >= 60)
+#   @param nextra_taps  Extra taps to use in the filter (default=2)
 def low_pass (gain, Fs, freq1, freq2, passband_ripple_db, stopband_atten_db,
-              nextra_taps=0):
+              nextra_taps=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
 
-# FIXME high_passs is broken...
-def high_pass (Fs, freq1, freq2, stopband_atten_db, passband_ripple_db, 
-               nextra_taps=0):
-    """FIXME: broken"""
+##  Builds a band pass filter.
+#   @param gain  Filter gain in the passband (linear)
+#   @param Fs    Sampling rate (sps)
+#   @param freq_sb1 End of stop band (in Hz)
+#   @param freq_pb1 Start of pass band (in Hz)
+#   @param freq_pb2 End of pass band (in Hz)
+#   @param freq_sb2 Start of stop band (in Hz)
+#   @param passband_ripple_db Pass band ripple in dB (should be small, < 1)
+#   @param stopband_atten_db  Stop band attenuation in dB (should be large, >= 60)
+#   @param nextra_taps  Extra taps to use in the filter (default=2)
+def band_pass (gain, Fs, freq_sb1, freq_pb1, freq_pb2, freq_sb2,
+               passband_ripple_db, stopband_atten_db,
+               nextra_taps=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
+
+
+##  Builds a band pass filter with complex taps by making an LPF and
+#   spinning it up to the right center frequency
+#   @param gain  Filter gain in the passband (linear)
+#   @param Fs    Sampling rate (sps)
+#   @param freq_sb1 End of stop band (in Hz)
+#   @param freq_pb1 Start of pass band (in Hz)
+#   @param freq_pb2 End of pass band (in Hz)
+#   @param freq_sb2 Start of stop band (in Hz)
+#   @param passband_ripple_db Pass band ripple in dB (should be small, < 1)
+#   @param stopband_atten_db  Stop band attenuation in dB (should be large, >= 60)
+#   @param nextra_taps  Extra taps to use in the filter (default=2)
+def complex_band_pass (gain, Fs, freq_sb1, freq_pb1, freq_pb2, freq_sb2,
+                       passband_ripple_db, stopband_atten_db,
+                       nextra_taps=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
+
+
+##  Builds a band reject filter
+#   spinning it up to the right center frequency
+#   @param gain  Filter gain in the passband (linear)
+#   @param Fs    Sampling rate (sps)
+#   @param freq_pb1 End of pass band (in Hz)
+#   @param freq_sb1 Start of stop band (in Hz)
+#   @param freq_sb2 End of stop band (in Hz)
+#   @param freq_pb2 Start of pass band (in Hz)
+#   @param passband_ripple_db Pass band ripple in dB (should be small, < 1)
+#   @param stopband_atten_db  Stop band attenuation in dB (should be large, >= 60)
+#   @param nextra_taps  Extra taps to use in the filter (default=2)
+def band_reject (gain, Fs, freq_pb1, freq_sb1, freq_sb2, freq_pb2,
+                 passband_ripple_db, stopband_atten_db,
+                 nextra_taps=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
+
+
+##  Builds a high pass filter.
+#   @param gain  Filter gain in the passband (linear)
+#   @param Fs    Sampling rate (sps)
+#   @param freq1 End of stop band (in Hz)
+#   @param freq2 Start of pass band (in Hz)
+#   @param passband_ripple_db Pass band ripple in dB (should be small, < 1)
+#   @param stopband_atten_db  Stop band attenuation in dB (should be large, >= 60)
+#   @param nextra_taps  Extra taps to use in the filter (default=2)
+def high_pass (gain, Fs, freq1, freq2, passband_ripple_db, stopband_atten_db,
+               nextra_taps=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