commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r11584 - in gnuradio/branches/developers/n4hy/pfb_iir2


From: n4hy
Subject: [Commit-gnuradio] r11584 - in gnuradio/branches/developers/n4hy/pfb_iir2: gnuradio-core/src/lib/filter gnuradio-examples/python/pfb
Date: Wed, 12 Aug 2009 07:30:14 -0600 (MDT)

Author: n4hy
Date: 2009-08-12 07:30:13 -0600 (Wed, 12 Aug 2009)
New Revision: 11584

Added:
   
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-examples/python/pfb/Makefile.am
Modified:
   
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc
   
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h
   
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.i
   
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc
   
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h
   
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.cc
   
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h
   
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.cc
   
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h
   
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-examples/python/pfb/channelize.py
   
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-examples/python/pfb/chirp_channelize.py
   
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-examples/python/pfb/decimate.py
   
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-examples/python/pfb/interpolate.py
Log:
putting pfb to look at half band and different arbitrary resampling structure

Modified: 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc
===================================================================
--- 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc
 2009-08-12 03:39:03 UTC (rev 11583)
+++ 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc
 2009-08-12 13:30:13 UTC (rev 11584)
@@ -30,23 +30,38 @@
 #include <gr_io_signature.h>
 
 gr_pfb_arb_resampler_ccf_sptr gr_make_pfb_arb_resampler_ccf (float rate, 
-                                                            const 
std::vector<float> &taps)
+                                                            const 
std::vector<float> &taps,
+                                                            unsigned int 
filter_size)
 {
-  return gr_pfb_arb_resampler_ccf_sptr (new gr_pfb_arb_resampler_ccf (rate, 
taps));
+  return gr_pfb_arb_resampler_ccf_sptr (new gr_pfb_arb_resampler_ccf (rate, 
taps,
+                                                                     
filter_size));
 }
 
 
 gr_pfb_arb_resampler_ccf::gr_pfb_arb_resampler_ccf (float rate, 
-                                                   const std::vector<float> 
&taps)
+                                                   const std::vector<float> 
&taps,
+                                                   unsigned int filter_size)
   : gr_block ("pfb_arb_resampler_ccf",
              gr_make_io_signature (1, 1, sizeof(gr_complex)),
              gr_make_io_signature (1, 1, sizeof(gr_complex))),
     d_updated (false)
 {
-  d_int_rate = 32;
+  /* The number of filters is specified by the user as the filter size;
+     this is also the interpolation rate of the filter. We use it and the
+     rate provided to determine the decimation rate. This acts as a
+     rational resampler. The flt_rate is calculated as the residual
+     between the integer decimation rate and the real decimation rate and
+     will be used to determine to interpolation point of the resampling
+     process.
+  */
+  d_int_rate = filter_size;
   d_dec_rate = (unsigned int)floor(d_int_rate/rate);
   d_flt_rate = (d_int_rate/rate) - d_dec_rate;
+
+  // The accumulator keeps track of overflow to increment the stride correctly.
   d_acc = 0;
+
+  // Store the last filter between calls to work
   d_last_filter = 0;
   
   d_filters = std::vector<gr_fir_ccf*>(d_int_rate);
@@ -78,13 +93,21 @@
 
   // Create d_numchan vectors to store each channel's taps
   d_taps.resize(d_int_rate);
+
+  // Make a vector of the taps plus fill it out with 0's to fill
+  // each polyphase filter with exactly d_taps_per_filter
+  std::vector<float> tmp_taps;
+  tmp_taps = taps;
+  while((float)(tmp_taps.size()) < d_int_rate*d_taps_per_filter) {
+    tmp_taps.push_back(0.0);
+  }
   
   // Partition the filter
   for(i = 0; i < d_int_rate; i++) {
     // Each channel uses all d_taps_per_filter with 0's if not enough taps to 
fill out
     d_taps[i] = std::vector<float>(d_taps_per_filter, 0);
     for(j = 0; j < d_taps_per_filter; j++) {
-      d_taps[i][j] = taps[i + j*d_int_rate];  // add taps to channels in 
reverse order
+      d_taps[i][j] = tmp_taps[i + j*d_int_rate];  // add taps to channels in 
reverse order
     }
     
     // Build a filter for each channel and add it's taps to it
@@ -124,34 +147,48 @@
     return 0;               // history requirements may have changed.
   }
 
-  int i = 0, j = 0, count = 0;
+  int i = 0, j, count = 0;
   gr_complex o0, o1;
 
+  // Restore the last filter position
   j = d_last_filter;
-  while(i < noutput_items) {
+
+  // produce output as long as we can and there are enough input samples
+  while((i < noutput_items) && (count < ninput_items[0]-1)) {
+
     // start j by wrapping around mod the number of channels
-    
-    while(j < d_int_rate) {
+    while((j < d_int_rate) && (i < noutput_items)) {
       // Take the current filter output
       o0 = d_filters[j]->filter(&in[count]);
 
       // Take the next filter output; wrap around to 0 if necessary
       if(j+1 == d_int_rate)
+       // Use the sample of the next input item through the first filter
        o1 = d_filters[0]->filter(&in[count+1]);
-      else
-       o1 = d_filters[j]->filter(&in[count]);
+      else {
+       // Use the sample from the current input item through the nex filter
+       o1 = d_filters[j+1]->filter(&in[count]);
+      }
 
-      out[i] = o0 + (o1 - o0)*d_flt_rate;
+      //out[i] = o0;                     // nearest-neighbor approach
+      out[i] = o0 + (o1 - o0)*d_acc;     // linearly interpolate between 
samples
       i++;
-
-      d_acc += d_dec_rate + d_flt_rate;
-      j = (int)floor(d_acc);
+      
+      // Accumulate the position in the stream for the interpolated point.
+      // If it goes above 1, roll around to zero and increment the stride
+      // length this time by the decimation rate plus 1 for the increment
+      // due to the acculated position.
+      d_acc += d_flt_rate;
+      j += d_dec_rate + (int)floor(d_acc);
+      d_acc = fmodf(d_acc, 1.0);
     }
-    count++;
-    j = j % d_int_rate;
-    d_acc = d_acc - floor(d_acc);    
+    if(i < noutput_items) {              // keep state for next entry
+      count++;                           // we have fully consumed another 
input
+      j = j % d_int_rate;                // roll filter around
+    }
   }
 
+  // Store the current filter position
   d_last_filter = j;
 
   consume_each(count);

Modified: 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h
===================================================================
--- 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h
  2009-08-12 03:39:03 UTC (rev 11583)
+++ 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h
  2009-08-12 13:30:13 UTC (rev 11584)
@@ -29,41 +29,124 @@
 class gr_pfb_arb_resampler_ccf;
 typedef boost::shared_ptr<gr_pfb_arb_resampler_ccf> 
gr_pfb_arb_resampler_ccf_sptr;
 gr_pfb_arb_resampler_ccf_sptr gr_make_pfb_arb_resampler_ccf (float rate,
-                                                            const 
std::vector<float> &taps);
+                                                            const 
std::vector<float> &taps,
+                                                            unsigned int 
filter_size=32);
 
 class gr_fir_ccf;
 
 /*!
- * \brief FIR filter with gr_complex input, gr_complex output and float taps
+ * \class gr_pfb_arb_resampler_ccf
+ *
+ * \brief Polyphase filterbank arbitrary resampler with 
+ *        gr_complex input, gr_complex output and float taps
+ *
  * \ingroup filter_blk
+ * 
+ * This block takes in a signal stream and performs arbitrary
+ * resampling. The resampling rate can be any real
+ * number <EM>r</EM>. The resampling is done by constructing
+ * <EM>N</EM> filters where <EM>N</EM> is the interpolation rate.  We
+ * then calculate <EM>D</EM> where <EM>D = floor(N/r)</EM>.
+ *
+ * Using <EM>N</EM> and <EM>D</EM>, we can perform rational resampling
+ * where <EM>N/D</EM> is a rational number close to the input rate
+ * <EM>r</EM> where we have <EM>N</EM> filters and we cycle through
+ * them as a polyphase filterbank with a stride of <EM>D</EM> so that
+ * <EM>i+1 = (i + D) % N</EM>.
+ *
+ * To get the arbitrary rate, we want to interpolate between two
+ * points. For each value out, we take an output from the current
+ * filter, <EM>i</EM>, and the next filter <EM>i+1</EM> and then
+ * linearly interpolate between the two based on the real resampling
+ * rate we want.
+ *
+ * The linear interpolation only provides us with an approximation to
+ * the real sampling rate specified. The error is a quantization error
+ * between the two filters we used as our interpolation points.  To
+ * this end, the number of filters, <EM>N</EM>, used determines the
+ * quantization error; the larger <EM>N</EM>, the smaller the
+ * noise. You can design for a specified noise floor by setting the
+ * filter size (parameters <EM>filter_size</EM>). The size defaults to
+ * 32 filters, which is about as good as most implementations need.
+ *
+ * The trick with designing this filter is in how to specify the taps
+ * of the prototype filter. Like the PFB interpolator, the taps are
+ * specified using the interpolated filter rate. In this case, that
+ * rate is the input sample rate multiplied by the number of filters
+ * in the filterbank, which is also the interpolation rate. All other
+ * values should be relative to this rate.
+ *
+ * For example, for a 32-filter arbitrary resampler and using the
+ * GNU Radio's firdes utility to build the filter, we build a low-pass
+ * filter with a sampling rate of <EM>fs</EM>, a 3-dB bandwidth of
+ * <EM>BW</EM> and a transition bandwidth of <EM>TB</EM>. We can also
+ * specify the out-of-band attenuation to use, <EM>ATT</EM>, and the
+ * filter window function (a Blackman-harris window in this case). The
+ * first input is the gain of the filter, which we specify here as the
+ * interpolation rate (<EM>32</EM>).
+ *
+ *      <B><EM>self._taps = gr.firdes.low_pass_2(32, 32*fs, BW, TB, 
+ *           attenuation_dB=ATT, window=gr.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
+ *
+ * The theory behind this block can be found in Chapter 7.5 of 
+ * the following book.
+ *
+ *    <B><EM>f. harris, Multirate Signal Processing for Communication 
+ *       Systems," Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
  */
+
 class gr_pfb_arb_resampler_ccf : public gr_block
 {
  private:
+  /*!
+   * Build the polyphase filterbank arbitray resampler.
+   * \param rate  (float) Specifies the resampling rate to use
+   * \param taps  (vector/list of floats) The prototype filter to populate the 
filterbank. The taps
+   *                                      should be generated at the 
filter_size sampling rate.
+   * \param filter_size (unsigned int) The number of filters in the filter 
bank. This is directly
+                                       related to quantization noise 
introduced during the resampling.
+                                      Defaults to 32 filters.
+   */
   friend gr_pfb_arb_resampler_ccf_sptr gr_make_pfb_arb_resampler_ccf (float 
rate,
-                                                                     const 
std::vector<float> &taps);
+                                                                     const 
std::vector<float> &taps,
+                                                                     unsigned 
int filter_size);
 
   std::vector<gr_fir_ccf*> d_filters;
   std::vector< std::vector<float> > d_taps;
-  unsigned int             d_int_rate;
-  unsigned int             d_dec_rate;
-  float                    d_flt_rate;
+  unsigned int             d_int_rate;          // the number of filters 
(interpolation rate)
+  unsigned int             d_dec_rate;          // the stride through the 
filters (decimation rate)
+  float                    d_flt_rate;          // residual rate for the 
linear interpolation
   float                    d_acc;
   unsigned int             d_last_filter;
   unsigned int             d_taps_per_filter;
   bool                    d_updated;
 
   /*!
-   * Construct a Polyphase filterbank for channelization with the given 
-   * number of channels and taps
+   * Build the polyphase filterbank arbitray resampler.
+   * \param rate  (float) Specifies the resampling rate to use
+   * \param taps  (vector/list of floats) The prototype filter to populate the 
filterbank. The taps
+   *                                      should be generated at the 
filter_size sampling rate.
+   * \param filter_size (unsigned int) The number of filters in the filter 
bank. This is directly
+                                       related to quantization noise 
introduced during the resampling.
+                                      Defaults to 32 filters.
    */
   gr_pfb_arb_resampler_ccf (float rate, 
-                          const std::vector<float> &taps);
+                           const std::vector<float> &taps,
+                           unsigned int filter_size);
   
 public:
   ~gr_pfb_arb_resampler_ccf ();
   
+  /*!
+   * Resets the filterbank's filter taps with the new prototype filter
+   * \param taps    (vector/list of floats) The prototype filter to populate 
the filterbank. The taps
+   *                                        should be generated at the 
interpolated sampling rate.
+   */
   void set_taps (const std::vector<float> &taps);
+
+  /*!
+   * Print all of the filterbank taps to screen.
+   */
   void print_taps();
   
   int general_work (int noutput_items,

Modified: 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.i
===================================================================
--- 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.i
  2009-08-12 03:39:03 UTC (rev 11583)
+++ 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.i
  2009-08-12 13:30:13 UTC (rev 11584)
@@ -23,13 +23,15 @@
 GR_SWIG_BLOCK_MAGIC(gr,pfb_arb_resampler_ccf);
 
 gr_pfb_arb_resampler_ccf_sptr gr_make_pfb_arb_resampler_ccf (float rate,
-                                                            const 
std::vector<float> &taps);
+                                                            const 
std::vector<float> &taps,
+                                                            unsigned int 
filter_size=32);
 
 class gr_pfb_arb_resampler_ccf : public gr_block
 {
  private:
   gr_pfb_arb_resampler_ccf (float rate,
-                           const std::vector<float> &taps);
+                           const std::vector<float> &taps,
+                           unsigned int filter_size);
 
  public:
   ~gr_pfb_arb_resampler_ccf ();

Modified: 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc
===================================================================
--- 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc
   2009-08-12 03:39:03 UTC (rev 11583)
+++ 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc
   2009-08-12 13:30:13 UTC (rev 11584)
@@ -76,18 +76,26 @@
   d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_numchans);
 
   // Create d_numchan vectors to store each channel's taps
-  std::vector< std::vector<float> > vtaps(d_numchans);
+  d_taps.resize(d_numchans);
 
+  // Make a vector of the taps plus fill it out with 0's to fill
+  // each polyphase filter with exactly d_taps_per_filter
+  std::vector<float> tmp_taps;
+  tmp_taps = taps;
+  while((float)(tmp_taps.size()) < d_numchans*d_taps_per_filter) {
+    tmp_taps.push_back(0.0);
+  }
+ 
   // Partition the filter
   for(i = 0; i < d_numchans; i++) {
     // Each channel uses all d_taps_per_filter with 0's if not enough taps to 
fill out
-    vtaps[i] = std::vector<float>(d_taps_per_filter, 0);
+    d_taps[i] = std::vector<float>(d_taps_per_filter, 0);
     for(j = 0; j < d_taps_per_filter; j++) {
-      vtaps[i][j] = taps[i + j*d_numchans];  // add taps to channels in 
reverse order
+      d_taps[i][j] = tmp_taps[i + j*d_numchans];  // add taps to channels in 
reverse order
     }
     
     // Build a filter for each channel and add it's taps to it
-    d_filters[i]->set_taps(vtaps[i]);
+    d_filters[i]->set_taps(d_taps[i]);
   }
 
   // Set the history to ensure enough input items for each filter
@@ -96,6 +104,20 @@
   d_updated = true;
 }
 
+void
+gr_pfb_channelizer_ccf::print_taps()
+{
+  unsigned int i, j;
+  for(i = 0; i < d_numchans; i++) {
+    printf("filter[%d]: [", i);
+    for(j = 0; j < d_taps_per_filter; j++) {
+      printf(" %.4e", d_taps[i][j]);
+    }
+    printf("]\n\n");
+  }
+}
+
+
 int
 gr_pfb_channelizer_ccf::work (int noutput_items,
                              gr_vector_const_void_star &input_items,

Modified: 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h
===================================================================
--- 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h
    2009-08-12 03:39:03 UTC (rev 11583)
+++ 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h
    2009-08-12 13:30:13 UTC (rev 11584)
@@ -34,25 +34,90 @@
 class gr_fir_ccf;
 class gri_fft_complex;
 
+
 /*!
- * \brief FIR filter with gr_complex input, gr_complex output and float taps
+ * \class gr_pfb_channelizer_ccf
+ *
+ * \brief Polyphase filterbank channelizer with 
+ *        gr_complex input, gr_complex output and float taps
+ *
  * \ingroup filter_blk
+ *
+ * This block takes in complex inputs and channelizes it to <EM>M</EM>
+ * channels of equal bandwidth. Each of the resulting channels is
+ * decimated to the new rate that is the input sampling rate
+ * <EM>fs</EM> divided by the number of channels, <EM>M</EM>.
+ *
+ * The PFB channelizer code takes the taps generated above and builds
+ * a set of filters. The set contains <EM>M</EM> number of filters
+ * and each filter contains ceil(taps.size()/decim) number of taps.
+ * Each tap from the filter prototype is sequentially inserted into
+ * the next filter. When all of the input taps are used, the remaining
+ * filters in the filterbank are filled out with 0's to make sure each
+ * filter has the same number of taps.
+ *
+ * Each filter operates using the gr_fir filter classs of GNU Radio,
+ * which takes the input stream at <EM>i</EM> and performs the inner
+ * product calculation to <EM>i+(n-1)</EM> where <EM>n</EM> is the
+ * number of filter taps. To efficiently handle this in the GNU Radio
+ * structure, each filter input must come from its own input
+ * stream. So the channelizer must be provided with <EM>M</EM> streams
+ * where the input stream has been deinterleaved. This is most easily
+ * done using the gr_stream_to_streams block.
+ *
+ * The output is then produced as a vector, where index <EM>i</EM> in
+ * the vector is the next sample from the <EM>i</EM>th channel. This
+ * is most easily handled by sending the output to a
+ * gr_vector_to_streams block to handle the conversion and passing
+ * <EM>M</EM> streams out.
+ *
+ * The input and output formatting is done using a hier_block2 called
+ * pfb_channelizer_ccf. This can take in a single stream and outputs
+ * <EM>M</EM> streams based on the behavior described above.
+ *
+ * The filter's taps should be based on the input sampling rate.
+ *
+ * For example, using the GNU Radio's firdes utility to building
+ * filters, we build a low-pass filter with a sampling rate of 
+ * <EM>fs</EM>, a 3-dB bandwidth of <EM>BW</EM> and a transition
+ * bandwidth of <EM>TB</EM>. We can also specify the out-of-band
+ * attenuation to use, <EM>ATT</EM>, and the filter window
+ * function (a Blackman-harris window in this case). The first input
+ *  is the gain of the filter, which we specify here as unity.
+ *
+ *      <B><EM>self._taps = gr.firdes.low_pass_2(1, fs, BW, TB, 
+ *           attenuation_dB=ATT, window=gr.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
+ *
+ * The theory behind this block can be found in Chapter 6 of 
+ * the following book.
+ *
+ *    <B><EM>f. harris, Multirate Signal Processing for Communication 
+ *       Systems," Upper Saddle River, NJ: Prentice Hall, Inc. 2004.
+ *
  */
+
 class gr_pfb_channelizer_ccf : public gr_sync_block
 {
  private:
+  /*!
+   * Build the polyphase filterbank decimator.
+   * \param numchans (unsigned integer) Specifies the number of channels 
<EM>M</EM>
+   * \param taps    (vector/list of floats) The prototype filter to populate 
the filterbank.
+   */
   friend gr_pfb_channelizer_ccf_sptr gr_make_pfb_channelizer_ccf (unsigned int 
numchans,
                                                                  const 
std::vector<float> &taps);
 
   std::vector<gr_fir_ccf*> d_filters;
+  std::vector< std::vector<float> > d_taps;
   gri_fft_complex         *d_fft;
   unsigned int             d_numchans;
   unsigned int             d_taps_per_filter;
   bool                    d_updated;
 
   /*!
-   * Construct a Polyphase filterbank for channelization with the given 
-   * number of channels and taps
+   * Build the polyphase filterbank decimator.
+   * \param numchans (unsigned integer) Specifies the number of channels 
<EM>M</EM>
+   * \param taps    (vector/list of floats) The prototype filter to populate 
the filterbank.
    */
   gr_pfb_channelizer_ccf (unsigned int numchans, 
                          const std::vector<float> &taps);
@@ -60,7 +125,16 @@
 public:
   ~gr_pfb_channelizer_ccf ();
   
+  /*!
+   * Resets the filterbank's filter taps with the new prototype filter
+   * \param taps    (vector/list of floats) The prototype filter to populate 
the filterbank.
+   */
   void set_taps (const std::vector<float> &taps);
+
+  /*!
+   * Print all of the filterbank taps to screen.
+   */
+  void print_taps();
   
   int work (int noutput_items,
            gr_vector_const_void_star &input_items,

Modified: 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.cc
===================================================================
--- 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.cc
     2009-08-12 03:39:03 UTC (rev 11583)
+++ 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.cc
     2009-08-12 13:30:13 UTC (rev 11584)
@@ -82,18 +82,26 @@
   d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_rate);
 
   // Create d_numchan vectors to store each channel's taps
-  std::vector< std::vector<float> > vtaps(d_rate);
+  d_taps.resize(d_rate);
 
+  // Make a vector of the taps plus fill it out with 0's to fill
+  // each polyphase filter with exactly d_taps_per_filter
+  std::vector<float> tmp_taps;
+  tmp_taps = taps;
+  while((float)(tmp_taps.size()) < d_rate*d_taps_per_filter) {
+    tmp_taps.push_back(0.0);
+  }
+  
   // Partition the filter
   for(i = 0; i < d_rate; i++) {
     // Each channel uses all d_taps_per_filter with 0's if not enough taps to 
fill out
-    vtaps[i] = std::vector<float>(d_taps_per_filter, 0);
+    d_taps[i] = std::vector<float>(d_taps_per_filter, 0);
     for(j = 0; j < d_taps_per_filter; j++) {
-      vtaps[i][j] = taps[i + j*d_rate];  // add taps to channels in reverse 
order
+      d_taps[i][j] = tmp_taps[i + j*d_rate];  // add taps to channels in 
reverse order
     }
     
     // Build a filter for each channel and add it's taps to it
-    d_filters[i]->set_taps(vtaps[i]);
+    d_filters[i]->set_taps(d_taps[i]);
   }
 
   // Set the history to ensure enough input items for each filter
@@ -102,7 +110,21 @@
   d_updated = true;
 }
 
+void
+gr_pfb_decimator_ccf::print_taps()
+{
+  unsigned int i, j;
+  for(i = 0; i < d_rate; i++) {
+    printf("filter[%d]: [", i);
+    for(j = 0; j < d_taps_per_filter; j++) {
+      printf(" %.4e", d_taps[i][j]);
+    }
+    printf("]\n\n");
+  }
+}
+
 #define ROTATEFFT
+
 int
 gr_pfb_decimator_ccf::work (int noutput_items,
                            gr_vector_const_void_star &input_items,

Modified: 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h
===================================================================
--- 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h
      2009-08-12 03:39:03 UTC (rev 11583)
+++ 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h
      2009-08-12 13:30:13 UTC (rev 11584)
@@ -36,17 +36,77 @@
 class gri_fft_complex;
 
 /*!
- * \brief FIR filter with gr_complex input, gr_complex output and float taps
+ * \class gr_pfb_decimator_ccf
+ * \brief Polyphase filterbank bandpass decimator with gr_complex 
+ *        input, gr_complex output and float taps
+ *
  * \ingroup filter_blk
+ * 
+ * This block takes in a signal stream and performs interger down-
+ * sampling (decimation) with a polyphase filterbank. The first input
+ * is the integer specifying how much to decimate by. The second
+ * input is a vector (Python list) of floating-point taps of the 
+ * prototype filter. The third input specifies the channel to extract.
+ * By default, the zeroth channel is used, which is the baseband 
+ * channel (first Nyquist zone).
+ *
+ * The <EM>channel</EM> parameter specifies which channel to use since
+ * this class is capable of bandpass decimation. Given a complex input
+ * stream at a sampling rate of <EM>fs</EM> and a decimation rate of
+ * <EM>decim</EM>, the input frequency domain is split into 
+ * <EM>decim</EM> channels that represent the Nyquist zones. Using the
+ * polyphase filterbank, we can select any one of these channels to
+ * decimate.
+ *
+ * The output signal will be the basebanded and decimated signal from
+ * that channel. This concept is very similar to the PFB channelizer
+ * (see #gr_pfb_channelizer_ccf) where only a single channel is 
+ * extracted at a time.
+ *
+ * The filter's taps should be based on the sampling rate before
+ * decimation.
+ *
+ * For example, using the GNU Radio's firdes utility to building
+ * filters, we build a low-pass filter with a sampling rate of 
+ * <EM>fs</EM>, a 3-dB bandwidth of <EM>BW</EM> and a transition
+ * bandwidth of <EM>TB</EM>. We can also specify the out-of-band
+ * attenuation to use, <EM>ATT</EM>, and the filter window
+ * function (a Blackman-harris window in this case). The first input
+ *  is the gain of the filter, which we specify here as unity.
+ *
+ *      <B><EM>self._taps = gr.firdes.low_pass_2(1, fs, BW, TB, 
+ *           attenuation_dB=ATT, window=gr.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
+ *
+ * The PFB decimator code takes the taps generated above and builds a
+ * set of filters. The set contains <EM>decim</EM> number of filters
+ * and each filter contains ceil(taps.size()/decim) number of taps.
+ * Each tap from the filter prototype is sequentially inserted into
+ * the next filter. When all of the input taps are used, the remaining
+ * filters in the filterbank are filled out with 0's to make sure each 
+ * filter has the same number of taps.
+ *
+ * The theory behind this block can be found in Chapter 6 of 
+ * the following book.
+ *
+ *    <B><EM>f. harris, Multirate Signal Processing for Communication 
+ *       Systems," Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
  */
+
 class gr_pfb_decimator_ccf : public gr_sync_block
 {
  private:
+  /*!
+   * Build the polyphase filterbank decimator.
+   * \param decim   (unsigned integer) Specifies the decimation rate to use
+   * \param taps    (vector/list of floats) The prototype filter to populate 
the filterbank.
+   * \param channel (unsigned integer) Selects the channel to return 
[default=0].
+   */
   friend gr_pfb_decimator_ccf_sptr gr_make_pfb_decimator_ccf (unsigned int 
decim,
                                                              const 
std::vector<float> &taps,
                                                              unsigned int 
channel);
 
   std::vector<gr_fir_ccf*> d_filters;
+  std::vector< std::vector<float> > d_taps;
   gri_fft_complex         *d_fft;
   unsigned int             d_rate;
   unsigned int             d_chan;
@@ -55,8 +115,10 @@
   gr_complex              *d_rotator;
 
   /*!
-   * Construct a Polyphase filterbank for channelization with the given 
-   * number of channels and taps
+   * Build the polyphase filterbank decimator.
+   * \param decim   (unsigned integer) Specifies the decimation rate to use
+   * \param taps    (vector/list of floats) The prototype filter to populate 
the filterbank.
+   * \param channel (unsigned integer) Selects the channel to return 
[default=0].
    */
   gr_pfb_decimator_ccf (unsigned int decim, 
                        const std::vector<float> &taps,
@@ -65,9 +127,19 @@
 public:
   ~gr_pfb_decimator_ccf ();
   
-  void set_taps (const std::vector<float> &taps);
-  //void set_channel (unsigned int channel);
+  /*!
+   * Resets the filterbank's filter taps with the new prototype filter
+   * \param taps    (vector/list of floats) The prototype filter to populate 
the filterbank.
+   */
+   void set_taps (const std::vector<float> &taps);
 
+  /*!
+   * Print all of the filterbank taps to screen.
+   */
+  void print_taps();
+   
+ //void set_channel (unsigned int channel);
+
   int work (int noutput_items,
            gr_vector_const_void_star &input_items,
            gr_vector_void_star &output_items);

Modified: 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.cc
===================================================================
--- 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.cc
  2009-08-12 03:39:03 UTC (rev 11583)
+++ 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.cc
  2009-08-12 13:30:13 UTC (rev 11584)
@@ -75,13 +75,21 @@
   // Create d_numchan vectors to store each channel's taps
   //std::vector< std::vector<float> > vtaps(d_rate);
   d_taps.resize(d_rate);
+
+  // Make a vector of the taps plus fill it out with 0's to fill
+  // each polyphase filter with exactly d_taps_per_filter
+  std::vector<float> tmp_taps;
+  tmp_taps = taps;
+  while((float)(tmp_taps.size()) < d_rate*d_taps_per_filter) {
+    tmp_taps.push_back(0.0);
+  }
   
   // Partition the filter
   for(i = 0; i < d_rate; i++) {
     // Each channel uses all d_taps_per_filter with 0's if not enough taps to 
fill out
     d_taps[i] = std::vector<float>(d_taps_per_filter, 0);
     for(j = 0; j < d_taps_per_filter; j++) {
-      d_taps[i][j] = taps[i + j*d_rate];  // add taps to channels in reverse 
order
+      d_taps[i][j] = tmp_taps[i + j*d_rate];  // add taps to channels in 
reverse order
     }
     
     // Build a filter for each channel and add it's taps to it
@@ -103,7 +111,7 @@
     for(j = 0; j < d_taps_per_filter; j++) {
       printf(" %.4e", d_taps[i][j]);
     }
-    printf("]\n");
+    printf("]\n\n");
   }
 }
 

Modified: 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h
===================================================================
--- 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h
   2009-08-12 03:39:03 UTC (rev 11583)
+++ 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h
   2009-08-12 13:30:13 UTC (rev 11584)
@@ -34,12 +34,60 @@
 class gr_fir_ccf;
 
 /*!
- * \brief FIR filter with gr_complex input, gr_complex output and float taps
+ * \class gr_pfb_interpolator_ccf
+ * \brief Polyphase filterbank interpolator with gr_complex input,
+ * gr_complex output and float taps
+ *
  * \ingroup filter_blk
+ * 
+ * This block takes in a signal stream and performs interger up-
+ * sampling (interpolation) with a polyphase filterbank. The first
+ * input is the integer specifying how much to interpolate by. The
+ * second input is a vector (Python list) of floating-point taps of
+ * the prototype filter.
+ *
+ * The filter's taps should be based on the interpolation rate
+ * specified. That is, the bandwidth specified is relative to the
+ * bandwidth after interpolation.
+ *
+ * For example, using the GNU Radio's firdes utility to building
+ * filters, we build a low-pass filter with a sampling rate of
+ * <EM>fs</EM>, a 3-dB bandwidth of <EM>BW</EM> and a transition
+ * bandwidth of <EM>TB</EM>. We can also specify the out-of-band
+ * attenuation to use, ATT, and the filter window function (a
+ * Blackman-harris window in this case). The first input is the gain,
+ * which is also specified as the interpolation rate so that the
+ * output levels are the same as the input (this creates an overall
+ * increase in power).
+ *
+ *      <B><EM>self._taps = gr.firdes.low_pass_2(interp, interp*fs, BW, TB, 
+ *           attenuation_dB=ATT, window=gr.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
+ *
+ * The PFB interpolator code takes the taps generated above and builds
+ * a set of filters. The set contains <EM>interp</EM> number of
+ * filters and each filter contains ceil(taps.size()/interp) number of
+ * taps. Each tap from the filter prototype is sequentially inserted
+ * into the next filter. When all of the input taps are used, the
+ * remaining filters in the filterbank are filled out with 0's to make
+ * sure each filter has the same number of taps.
+ *
+ * The theory behind this block can be found in Chapter 7.1 of the
+ * following book.
+ *
+ *    <B><EM>f. harris, <EM>Multirate Signal Processing for Communication
+ *       Systems</EM>," Upper Saddle River, NJ: Prentice Hall,
+ *       Inc. 2004.</EM></B>
  */
+
 class gr_pfb_interpolator_ccf : public gr_sync_interpolator
 {
  private:
+  /*!
+   * Build the polyphase filterbank interpolator.
+   * \param interp  (unsigned integer) Specifies the interpolation rate to use
+   * \param taps    (vector/list of floats) The prototype filter to populate 
the filterbank. The taps
+   *                                        should be generated at the 
interpolated sampling rate.
+   */
   friend gr_pfb_interpolator_ccf_sptr gr_make_pfb_interpolator_ccf (unsigned 
int interp,
                                                                    const 
std::vector<float> &taps);
 
@@ -50,8 +98,10 @@
   bool                    d_updated;
 
   /*!
-   * Construct a Polyphase filterbank for channelization with the given 
-   * number of channels and taps
+   * Construct a Polyphase filterbank interpolator
+   * \param interp  (unsigned integer) Specifies the interpolation rate to use
+   * \param taps    (vector/list of floats) The prototype filter to populate 
the filterbank. The taps
+   *                                        should be generated at the 
interpolated sampling rate.
    */
   gr_pfb_interpolator_ccf (unsigned int interp, 
                           const std::vector<float> &taps);
@@ -59,7 +109,16 @@
 public:
   ~gr_pfb_interpolator_ccf ();
   
+  /*!
+   * Resets the filterbank's filter taps with the new prototype filter
+   * \param taps    (vector/list of floats) The prototype filter to populate 
the filterbank. The taps
+   *                                        should be generated at the 
interpolated sampling rate.
+   */
   void set_taps (const std::vector<float> &taps);
+
+  /*!
+   * Print all of the filterbank taps to screen.
+   */
   void print_taps();
   
   int work (int noutput_items,

Added: 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-examples/python/pfb/Makefile.am
===================================================================
--- 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-examples/python/pfb/Makefile.am
                         (rev 0)
+++ 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-examples/python/pfb/Makefile.am
 2009-08-12 13:30:13 UTC (rev 11584)
@@ -0,0 +1,31 @@
+#
+# Copyright 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.
+# 
+
+include $(top_srcdir)/Makefile.common
+
+ourdatadir = $(exampledir)/pfb
+
+dist_ourdata_SCRIPTS =         \
+       channelize.py           \
+       chirp_channelize.py     \
+       decimate.py             \
+       interpolate.py          \
+       fmtest.py

Modified: 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-examples/python/pfb/channelize.py
===================================================================
--- 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-examples/python/pfb/channelize.py
       2009-08-12 03:39:03 UTC (rev 11583)
+++ 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-examples/python/pfb/channelize.py
       2009-08-12 13:30:13 UTC (rev 11584)
@@ -1,49 +1,72 @@
 #!/usr/bin/env python
+#
+# Copyright 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.
+# 
 
 from gnuradio import gr, blks2
-import math
-import os
+import os, time
 import scipy, pylab
 from scipy import fftpack
-import time
+from pylab import mlab
 
-#print os.getpid()
-#raw_input()
-
 class pfb_top_block(gr.top_block):
     def __init__(self):
         gr.top_block.__init__(self)
 
-        self._N = 2000000
-        self._fs = 9000
-        self._Tmax = self._N * (1.0/self._fs)
-        self._M = 9
-        self._taps = gr.firdes.low_pass_2(1, self._fs, 475,50, 100,5)
+        self._N = 2000000        # number of samples to use
+        self._fs = 9000          # initial sampling rate
+        self._M = 9              # Number of channels to channelize
 
-        fc = 200
+        # Create a set of taps for the PFB channelizer
+        self._taps = gr.firdes.low_pass_2(1, self._fs, 475.50, 50, 
+                                          attenuation_dB=10, 
window=gr.firdes.WIN_BLACKMAN_hARRIS)
 
-        tpc = math.ceil(float(len(self._taps)) /  float(self._M))
-
+        # Calculate the number of taps per channel for our own information
+        tpc = scipy.ceil(float(len(self._taps)) /  float(self._M))
         print "Number of taps:     ", len(self._taps)
         print "Number of channels: ", self._M
         print "Taps per channel:   ", tpc
         
+        # Create a set of signals at different frequencies
+        #   freqs lists the frequencies of the signals that get stored 
+        #   in the list "signals", which then get summed together
         self.signals = list()
         self.add = gr.add_cc()
-        freqs = [-4070, -3050, -2030, -1010, 10, 1020, 2040, 3060, 4300]
+        freqs = [-4070, -3050, -2030, -1010, 10, 1020, 2040, 3060, 4080]
         for i in xrange(len(freqs)):
             self.signals.append(gr.sig_source_c(self._fs, gr.GR_SIN_WAVE, 
freqs[i], 1))
             self.connect(self.signals[i], (self.add,i))
 
         self.head = gr.head(gr.sizeof_gr_complex, self._N)
+
+        # Construct the channelizer filter
         self.pfb = blks2.pfb_channelizer_ccf(self._M, self._taps)
+
+        # Construct a vector sink for the input signal to the channelizer
         self.snk_i = gr.vector_sink_c()
 
         # Connect the blocks
         self.connect(self.add, self.head, self.pfb)
         self.connect(self.add, self.snk_i)
 
-        # Create a file sink for each of M output channels of the filter and 
connect it
+        # Create a vector sink for each of M output channels of the filter and 
connect it
         self.snks = list()
         for i in xrange(self._M):
             self.snks.append(gr.vector_sink_c())
@@ -75,9 +98,9 @@
         d = tb.snk_i.data()[Ns:Ne]
         spin_f = fig_in.add_subplot(2, 1, 1)
 
-        X,freq = spin_f.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs,
-                            window = lambda d: d*winfunc(fftlen),
-                            visible=False)
+        X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs,
+                          window = lambda d: d*winfunc(fftlen),
+                          scale_by_freq=True)
         X_in = 10.0*scipy.log10(abs(fftpack.fftshift(X)))
         f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size))
         pin_f = spin_f.plot(f_in, X_in, "b")
@@ -88,7 +111,11 @@
         spin_f.set_xlabel("Frequency (Hz)")
         spin_f.set_ylabel("Power (dBW)")
 
-        t_in = scipy.arange(0, tb._Tmax, tb._Tmax/float(len(d)))
+
+        Ts = 1.0/fs
+        Tmax = len(d)*Ts
+        
+        t_in = scipy.arange(0, Tmax, Ts)
         x_in = scipy.array(d)
         spin_t = fig_in.add_subplot(2, 1, 2)
         pin_t = spin_t.plot(t_in, x_in.real, "b")
@@ -105,6 +132,8 @@
         # Plot each of the channels outputs. Frequencies on Figure 2 and
         # time signals on Figure 3
         fs_o = tb._fs / tb._M
+        Ts_o = 1.0/fs_o
+        Tmax_o = len(d)*Ts_o
         for i in xrange(len(tb.snks)):
             # remove issues with the transients at the beginning
             # also remove some corruption at the end of the stream
@@ -112,9 +141,9 @@
             d = tb.snks[i].data()[Ns:Ne]
 
             sp1_f = fig1.add_subplot(Nrows, Ncols, 1+i)
-            X,freq = sp1_f.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs_o,
-                               window = lambda d: d*winfunc(fftlen),
-                               visible=False)
+            X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs_o,
+                              window = lambda d: d*winfunc(fftlen),
+                              scale_by_freq=True)
             X_o = 10.0*scipy.log10(abs(fftpack.fftshift(X)))
             f_o = scipy.arange(-fs_o/2.0, fs_o/2.0, fs_o/float(X_o.size))
             p2_f = sp1_f.plot(f_o, X_o, "b")
@@ -125,15 +154,15 @@
             sp1_f.set_xlabel("Frequency (Hz)")
             sp1_f.set_ylabel("Power (dBW)")
 
-            
             x_o = scipy.array(d)
-            t_o = scipy.arange(0, tb._Tmax, tb._Tmax/float(x_o.size))
+            t_o = scipy.arange(0, Tmax_o, Ts_o)
             sp2_o = fig2.add_subplot(Nrows, Ncols, 1+i)
             p2_o = sp2_o.plot(t_o, x_o.real, "b")
             p2_o = sp2_o.plot(t_o, x_o.imag, "r")
             sp2_o.set_xlim([min(t_o), max(t_o)+1]) 
             sp2_o.set_ylim([-2, 2]) 
 
+            sp2_o.set_title(("Channel %d" % i), weight="bold")
             sp2_o.set_xlabel("Time (s)")
             sp2_o.set_ylabel("Amplitude")
 

Modified: 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-examples/python/pfb/chirp_channelize.py
===================================================================
--- 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-examples/python/pfb/chirp_channelize.py
 2009-08-12 03:39:03 UTC (rev 11583)
+++ 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-examples/python/pfb/chirp_channelize.py
 2009-08-12 13:30:13 UTC (rev 11584)
@@ -1,49 +1,76 @@
 #!/usr/bin/env python
+#
+# Copyright 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.
+# 
 
 from gnuradio import gr, blks2
-import math
-import os
+import os, time
 import scipy, pylab
 from scipy import fftpack
-import time
+from pylab import mlab
 
-#print os.getpid()
-#raw_input()
-
 class pfb_top_block(gr.top_block):
     def __init__(self):
         gr.top_block.__init__(self)
 
-        self._N = 200000
-        self._fs = 9000
-        self._Tmax = self._N * (1.0/self._fs)
-        self._M = 9
-        self._taps = gr.firdes.low_pass_2(1, self._fs, 800,100 ,90,5)
-        fc = 200
+        self._N = 200000         # number of samples to use
+        self._fs = 9000          # initial sampling rate
+        self._M = 9              # Number of channels to channelize
 
-        tpc = math.ceil(float(len(self._taps)) /  float(self._M))
+        # Create a set of taps for the PFB channelizer
+        self._taps = gr.firdes.low_pass_2(1, self._fs, 500, 20, 
+                                          attenuation_dB=10, 
window=gr.firdes.WIN_BLACKMAN_hARRIS)
 
+        # Calculate the number of taps per channel for our own information
+        tpc = scipy.ceil(float(len(self._taps)) /  float(self._M))
         print "Number of taps:     ", len(self._taps)
         print "Number of channels: ", self._M
         print "Taps per channel:   ", tpc
 
-        data = scipy.arange(0, 1000, 100.0/float(self._N))
-        
-        #self.vco_input = gr.sig_source_f(self._fs, gr.GR_SIN_WAVE, 0.25, 100)
-        self.vco_input = gr.vector_source_f(data, False)
+        repeated = True
+        if(repeated):
+            self.vco_input = gr.sig_source_f(self._fs, gr.GR_SIN_WAVE, 0.25, 
110)
+        else:
+            amp = 100
+            data = scipy.arange(0, amp, amp/float(self._N))
+            self.vco_input = gr.vector_source_f(data, False)
+            
+        # Build a VCO controlled by either the sinusoid or single chirp tone
+        # Then convert this to a complex signal
         self.vco = gr.vco_f(self._fs, 225, 1)
         self.f2c = gr.float_to_complex()
 
         self.head = gr.head(gr.sizeof_gr_complex, self._N)
+
+        # Construct the channelizer filter
         self.pfb = blks2.pfb_channelizer_ccf(self._M, self._taps)
+
+        # Construct a vector sink for the input signal to the channelizer
         self.snk_i = gr.vector_sink_c()
 
-        # Connect the rest
+        # Connect the blocks
         self.connect(self.vco_input, self.vco, self.f2c)
         self.connect(self.f2c, self.head, self.pfb)
         self.connect(self.f2c, self.snk_i)
 
-        # Create a file sink for each of M output channels of the filter and 
connect it
+        # Create a vector sink for each of M output channels of the filter and 
connect it
         self.snks = list()
         for i in xrange(self._M):
             self.snks.append(gr.vector_sink_c())
@@ -60,42 +87,100 @@
     print "Run time: %f" % (tend - tstart)
 
     if 1:
-        fig1 = pylab.figure(1, figsize=(16,9))
-        fig2 = pylab.figure(2, figsize=(16,9))
+        fig_in = pylab.figure(1, figsize=(16,9), facecolor="w")
+        fig1 = pylab.figure(2, figsize=(16,9), facecolor="w")
+        fig2 = pylab.figure(3, figsize=(16,9), facecolor="w")
+        fig3 = pylab.figure(4, figsize=(16,9), facecolor="w")
         
-        Ns = 100
-        Ne = tb._N
+        Ns = 650
+        Ne = 20000
+
+        fftlen = 8192
+        winfunc = scipy.blackman
+        fs = tb._fs
+
+        # Plot the input signal on its own figure
         d = tb.snk_i.data()[Ns:Ne]
-        f_in = scipy.arange(-tb._fs/2.0, tb._fs/2.0, tb._fs/float(len(d)))
-        X_in = 10.0*scipy.log10(fftpack.fftshift(fftpack.fft(d, f_in.size)))
-        sp1_in = fig1.add_subplot(4, 3, 1)
-        p1_in = sp1_in.plot(f_in, X_in)
+        spin_f = fig_in.add_subplot(2, 1, 1)
+
+        X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs,
+                          window = lambda d: d*winfunc(fftlen),
+                          scale_by_freq=True)
+        X_in = 10.0*scipy.log10(abs(fftpack.fftshift(X)))
+        f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size))
+        pin_f = spin_f.plot(f_in, X_in, "b")
+        spin_f.set_xlim([min(f_in), max(f_in)+1]) 
+        spin_f.set_ylim([-200.0, 50.0]) 
+
+        spin_f.set_title("Input Signal", weight="bold")
+        spin_f.set_xlabel("Frequency (Hz)")
+        spin_f.set_ylabel("Power (dBW)")
+
+
+        Ts = 1.0/fs
+        Tmax = len(d)*Ts
         
-        t_in = scipy.arange(0, tb._Tmax, tb._Tmax/float(len(d)))
+        t_in = scipy.arange(0, Tmax, Ts)
         x_in = scipy.array(d)
-        sp2_in = fig2.add_subplot(4, 3, 1)
-        p2_in = sp2_in.plot(t_in, x_in.real, "b")
-        p2_in = sp2_in.plot(t_in, x_in.imag, "r")
-        
+        spin_t = fig_in.add_subplot(2, 1, 2)
+        pin_t = spin_t.plot(t_in, x_in.real, "b")
+        pin_t = spin_t.plot(t_in, x_in.imag, "r")
+
+        spin_t.set_xlabel("Time (s)")
+        spin_t.set_ylabel("Amplitude")
+
+        Ncols = int(scipy.floor(scipy.sqrt(tb._M)))
+        Nrows = int(scipy.floor(tb._M / Ncols))
+        if(tb._M % Ncols != 0):
+            Nrows += 1
+
+        # Plot each of the channels outputs. Frequencies on Figure 2 and
+        # time signals on Figure 3
         fs_o = tb._fs / tb._M
+        Ts_o = 1.0/fs_o
+        Tmax_o = len(d)*Ts_o
         for i in xrange(len(tb.snks)):
             # remove issues with the transients at the beginning
             # also remove some corruption at the end of the stream
             #    this is a bug, probably due to the corner cases
             d = tb.snks[i].data()[Ns:Ne]
-            f_o = scipy.arange(-fs_o/2.0, fs_o/2.0, fs_o/float(len(d)))
-            x_o = 10.0*scipy.log10(fftpack.fftshift(fftpack.fft(d)))
-            sp1_o = fig1.add_subplot(4, 3, 2+i)
-            p1_o = sp1_o.plot(f_o, x_o)
-            sp1_o.set_ylim([-50.0, 30.0])
-            
+
+            sp1_f = fig1.add_subplot(Nrows, Ncols, 1+i)
+            X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs_o,
+                              window = lambda d: d*winfunc(fftlen),
+                              scale_by_freq=True)
+            X_o = 10.0*scipy.log10(abs(X))
+            f_o = freq
+            p2_f = sp1_f.plot(f_o, X_o, "b")
+            sp1_f.set_xlim([min(f_o), max(f_o)+1]) 
+            sp1_f.set_ylim([-200.0, 50.0]) 
+
+            sp1_f.set_title(("Channel %d" % i), weight="bold")
+            sp1_f.set_xlabel("Frequency (Hz)")
+            sp1_f.set_ylabel("Power (dBW)")
+
             x_o = scipy.array(d)
-            t_o = scipy.arange(0, tb._Tmax, tb._Tmax/float(x_o.size))
-            sp2_o = fig2.add_subplot(4, 3, 2+i)
+            t_o = scipy.arange(0, Tmax_o, Ts_o)
+            sp2_o = fig2.add_subplot(Nrows, Ncols, 1+i)
             p2_o = sp2_o.plot(t_o, x_o.real, "b")
             p2_o = sp2_o.plot(t_o, x_o.imag, "r")
-            sp2_o.set_ylim([-1.0, 1.0])
-            
+            sp2_o.set_xlim([min(t_o), max(t_o)+1]) 
+            sp2_o.set_ylim([-2, 2]) 
+
+            sp2_o.set_title(("Channel %d" % i), weight="bold")
+            sp2_o.set_xlabel("Time (s)")
+            sp2_o.set_ylabel("Amplitude")
+
+
+            sp3 = fig3.add_subplot(1,1,1)
+            p3 = sp3.plot(t_o, x_o.real)
+            sp3.set_xlim([min(t_o), max(t_o)+1]) 
+            sp3.set_ylim([-2, 2]) 
+
+        sp3.set_title("All Channels")
+        sp3.set_xlabel("Time (s)")
+        sp3.set_ylabel("Amplitude") 
+
         pylab.show()
 
 

Modified: 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-examples/python/pfb/decimate.py
===================================================================
--- 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-examples/python/pfb/decimate.py
 2009-08-12 03:39:03 UTC (rev 11583)
+++ 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-examples/python/pfb/decimate.py
 2009-08-12 13:30:13 UTC (rev 11584)
@@ -1,10 +1,30 @@
 #!/usr/bin/env python
+#
+# Copyright 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.
+# 
 
 from gnuradio import gr, blks2
-import math
 import os
 import scipy, pylab
 from scipy import fftpack
+from pylab import mlab
 import time
 
 #print os.getpid()
@@ -14,28 +34,38 @@
     def __init__(self):
         gr.top_block.__init__(self)
 
-        self._N = 10000000
-        self._fs = 10000
-        self._Tmax = self._N * (1.0/self._fs)
-        self._decim = 20
-        self._taps = gr.firdes.low_pass_2(1, self._fs, 200, 50,120,5)
+        self._N = 10000000      # number of samples to use
+        self._fs = 10000        # initial sampling rate
+        self._decim = 20        # Decimation rate
+        
+        # Generate the prototype filter taps for the decimators with a 200 Hz 
bandwidth
+        self._taps = gr.firdes.low_pass_2(1, self._fs, 200, 150,
+                                          attenuation_dB=120, 
window=gr.firdes.WIN_BLACKMAN_hARRIS)
 
-        tpc = math.ceil(float(len(self._taps)) /  float(self._decim))
-
+        # Calculate the number of taps per channel for our own information
+        tpc = scipy.ceil(float(len(self._taps)) /  float(self._decim))
         print "Number of taps:     ", len(self._taps)
         print "Number of filters:  ", self._decim
         print "Taps per channel:   ", tpc
         
+        # Build the input signal source
+        # We create a list of freqs, and a sine wave is generated and added to 
the source
+        # for each one of these frequencies.
         self.signals = list()
         self.add = gr.add_cc()
-        freqs = [10, 2040]
+        freqs = [10, 20, 2040]
         for i in xrange(len(freqs)):
             self.signals.append(gr.sig_source_c(self._fs, gr.GR_SIN_WAVE, 
freqs[i], 1))
             self.connect(self.signals[i], (self.add,i))
 
         self.head = gr.head(gr.sizeof_gr_complex, self._N)
+        
+        # Construct a PFB decimator filter
         self.pfb = blks2.pfb_decimator_ccf(self._decim, self._taps, 0)
-        #self.pfb = gr.fir_filter_ccf(self._decim, self._taps)
+
+        # Construct a standard FIR decimating filter
+        self.dec = gr.fir_filter_ccf(self._decim, self._taps)
+
         self.snk_i = gr.vector_sink_c()
 
         # Connect the blocks
@@ -71,9 +101,9 @@
         d = tb.snk_i.data()[Ns:Ns+Ne]
         sp1_f = fig1.add_subplot(2, 1, 1)
 
-        X,freq = sp1_f.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs,
-                           window = lambda d: d*winfunc(fftlen),
-                           visible=False)
+        X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs,
+                          window = lambda d: d*winfunc(fftlen),
+                          scale_by_freq=True)
         X_in = 10.0*scipy.log10(abs(fftpack.fftshift(X)))
         f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size))
         p1_f = sp1_f.plot(f_in, X_in, "b")
@@ -84,7 +114,10 @@
         sp1_f.set_xlabel("Frequency (Hz)")
         sp1_f.set_ylabel("Power (dBW)")
         
-        t_in = scipy.arange(0, tb._Tmax, tb._Tmax/float(len(d)))
+        Ts = 1.0/fs
+        Tmax = len(d)*Ts
+
+        t_in = scipy.arange(0, Tmax, Ts)
         x_in = scipy.array(d)
         sp1_t = fig1.add_subplot(2, 1, 2)
         p1_t = sp1_t.plot(t_in, x_in.real, "b")
@@ -100,9 +133,9 @@
 
         sp2_f = fig2.add_subplot(2, 1, 1)
         d = tb.snk.data()[Ns:Ns+Ne]
-        X,freq = sp2_f.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs_o,
-                           window = lambda d: d*winfunc(fftlen),
-                           visible=False)
+        X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs_o,
+                          window = lambda d: d*winfunc(fftlen),
+                          scale_by_freq=True)
         X_o = 10.0*scipy.log10(abs(fftpack.fftshift(X)))
         f_o = scipy.arange(-fs_o/2.0, fs_o/2.0, fs_o/float(X_o.size))
         p2_f = sp2_f.plot(f_o, X_o, "b")
@@ -114,12 +147,15 @@
         sp2_f.set_ylabel("Power (dBW)")
         
 
+        Ts_o = 1.0/fs_o
+        Tmax_o = len(d)*Ts_o
+
         x_o = scipy.array(d)
-        t_o = scipy.arange(0, tb._Tmax, tb._Tmax/float(x_o.size))
+        t_o = scipy.arange(0, Tmax_o, Ts_o)
         sp2_t = fig2.add_subplot(2, 1, 2)
-        p2_t = sp2_t.plot(t_o, x_o.real, "b")
-        p2_t = sp2_t.plot(t_o, x_o.imag, "r")
-        sp2_t.set_ylim([-1.5, 1.5])
+        p2_t = sp2_t.plot(t_o, x_o.real, "b-o")
+        p2_t = sp2_t.plot(t_o, x_o.imag, "r-o")
+        sp2_t.set_ylim([-2.5, 2.5])
 
         sp2_t.set_xlabel("Time (s)")
         sp2_t.set_ylabel("Amplitude")

Modified: 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-examples/python/pfb/interpolate.py
===================================================================
--- 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-examples/python/pfb/interpolate.py
      2009-08-12 03:39:03 UTC (rev 11583)
+++ 
gnuradio/branches/developers/n4hy/pfb_iir2/gnuradio-examples/python/pfb/interpolate.py
      2009-08-12 13:30:13 UTC (rev 11584)
@@ -1,10 +1,30 @@
 #!/usr/bin/env python
+#
+# Copyright 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.
+# 
 
 from gnuradio import gr, blks2
-import math
 import os
 import scipy, pylab
 from scipy import fftpack
+from pylab import mlab
 import time
 
 #print os.getpid()
@@ -14,36 +34,52 @@
     def __init__(self):
         gr.top_block.__init__(self)
 
+        self._N = 100000        # number of samples to use
+        self._fs = 2000         # initial sampling rate
+        self._interp = 5        # Interpolation rate for PFB interpolator
+        self._ainterp = 5.5       # Resampling rate for the PFB arbitrary 
resampler
+
+        # Frequencies of the signals we construct 
         freq1 = 100
-        freq2 = 500
+        freq2 = 200
 
-        self._N = 100000
-        self._fs = 2000
-        self._Tmax = self._N * (1.0/self._fs)
-        self._interp = 8
-        self._ainterp = 8
+        # Create a set of taps for the PFB interpolator
+        # This is based on the post-interpolation sample rate
+        self._taps = gr.firdes.low_pass_2(self._interp, self._interp*self._fs, 
freq2+50, 50, 
+                                          attenuation_dB=120, 
window=gr.firdes.WIN_BLACKMAN_hARRIS)
 
-        self._taps = gr.firdes.low_pass_2(self._interp, self._interp*self._fs, 
freq2+50, 150,120,5)
-        self._taps2 = gr.firdes.low_pass_2(32.0, 1,
-                                         0.4 / (32.0), 0.1/(32.0),100,5)
+        # Create a set of taps for the PFB arbitrary resampler
+        # The filter size is the number of filters in the filterbank; 32 will 
give very low side-lobes,
+        # and larger numbers will reduce these even farther
+        # The taps in this filter are based on a sampling rate of the filter 
size since it acts
+        # internally as an interpolator.
+        flt_size = 32
+        self._taps2 = gr.firdes.low_pass_2(flt_size, flt_size*self._fs, 
freq2+50, 150, 
+                                           attenuation_dB=120, 
window=gr.firdes.WIN_BLACKMAN_hARRIS)
 
-        tpc = math.ceil(float(len(self._taps)) /  float(self._interp))
-
+        # Calculate the number of taps per channel for our own information
+        tpc = scipy.ceil(float(len(self._taps)) /  float(self._interp))
         print "Number of taps:     ", len(self._taps)
         print "Number of filters:  ", self._interp
         print "Taps per channel:   ", tpc
-        
+
+        # Create a couple of signals at different frequencies
         self.signal1 = gr.sig_source_c(self._fs, gr.GR_SIN_WAVE, freq1, 0.5)
         self.signal2 = gr.sig_source_c(self._fs, gr.GR_SIN_WAVE, freq2, 0.5)
         self.signal = gr.add_cc()
         
         self.head = gr.head(gr.sizeof_gr_complex, self._N)
+
+        # Construct the PFB interpolator filter
         self.pfb = blks2.pfb_interpolator_ccf(self._interp, self._taps)
-        self.pfb_ar = blks2.pfb_arb_resampler_ccf(self._ainterp, self._taps2)
+
+        # Construct the PFB arbitrary resampler filter
+        self.pfb_ar = blks2.pfb_arb_resampler_ccf(self._ainterp, self._taps2, 
flt_size)
         self.snk_i = gr.vector_sink_c()
 
         #self.pfb_ar.pfb.print_taps()
-
+        #self.pfb.pfb.print_taps()
+        
         # Connect the blocks
         self.connect(self.signal1, self.head, (self.signal,0))
         self.connect(self.signal2, (self.signal,1))
@@ -51,7 +87,7 @@
         self.connect(self.signal, self.pfb_ar)
         self.connect(self.signal, self.snk_i)
 
-        # Create the sink for the interpolated siganl
+        # Create the sink for the interpolated signals
         self.snk1 = gr.vector_sink_c()
         self.snk2 = gr.vector_sink_c()
         self.connect(self.pfb, self.snk1)
@@ -84,9 +120,9 @@
         d = tb.snk_i.data()[Ns:Ns+Ne]
         sp1_f = fig1.add_subplot(2, 1, 1)
 
-        X,freq = sp1_f.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs,
-                           window = lambda d: d*winfunc(fftlen),
-                           visible=False)
+        X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs,
+                          window = lambda d: d*winfunc(fftlen),
+                          scale_by_freq=True)
         X_in = 10.0*scipy.log10(abs(fftpack.fftshift(X)))
         f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size))
         p1_f = sp1_f.plot(f_in, X_in, "b")
@@ -118,9 +154,9 @@
 
         sp2_f = fig2.add_subplot(2, 1, 1)
         d = tb.snk1.data()[Ns:Ns+(tb._interp*Ne)]
-        X,freq = sp2_f.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs,
-                           window = lambda d: d*winfunc(fftlen),
-                           visible=False)
+        X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs,
+                          window = lambda d: d*winfunc(fftlen),
+                          scale_by_freq=True)
         X_o = 10.0*scipy.log10(abs(fftpack.fftshift(X)))
         f_o = scipy.arange(-fs_int/2.0, fs_int/2.0, fs_int/float(X_o.size))
         p2_f = sp2_f.plot(f_o, X_o, "b")
@@ -151,20 +187,15 @@
 
         sp3_f = fig3.add_subplot(2, 1, 1)
         d = tb.snk2.data()[Ns:Ns+(tb._interp*Ne)]
-        X,freq = sp3_f.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs,
-                           window = lambda d: d*winfunc(fftlen),
-                           visible=False)
+        X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs,
+                          window = lambda d: d*winfunc(fftlen),
+                          scale_by_freq=True)
         X_o = 10.0*scipy.log10(abs(fftpack.fftshift(X)))
         f_o = scipy.arange(-fs_aint/2.0, fs_aint/2.0, fs_aint/float(X_o.size))
         p3_f = sp3_f.plot(f_o, X_o, "b")
         sp3_f.set_xlim([min(f_o), max(f_o)+1]) 
         sp3_f.set_ylim([-200.0, 50.0]) 
 
-        #f_o = scipy.arange(-fs_int/2.0, fs_int/2.0, fs_int/float(len(d)))
-        #X_o = 10.0*scipy.log10(fftpack.fftshift(fftpack.fft(d)))
-        #p3_f = sp3_f.plot(f_o, X_o)
-        #sp3_f.set_ylim([-50.0, 50.0])
-
         sp3_f.set_title("Output Signal from PFB Arbitrary Resampler", 
weight="bold")
         sp3_f.set_xlabel("Frequency (Hz)")
         sp3_f.set_ylabel("Power (dBW)")
@@ -173,10 +204,11 @@
         Tmax = len(d)*Ts_aint
 
         t_o = scipy.arange(0, Tmax, Ts_aint)
-        x_o1 = scipy.array(d)
+        x_o2 = scipy.array(d)
         sp3_f = fig3.add_subplot(2, 1, 2)
-        p3_f = sp3_f.plot(t_o, x_o1.real, "b-o")
-        #p3_f = sp3_f.plot(t_o, x_o.imag, "r-o")
+        p3_f = sp3_f.plot(t_o, x_o2.real, "b-o")
+        p3_f = sp3_f.plot(t_o, x_o1.real, "m-o")
+        #p3_f = sp3_f.plot(t_o, x_o2.imag, "r-o")
         sp3_f.set_ylim([-2.5, 2.5])
         
         sp3_f.set_title("Output Signal from PFB Arbitrary Resampler", 
weight="bold")





reply via email to

[Prev in Thread] Current Thread [Next in Thread]