Statistics
| Branch: | Tag: | Revision:

root / gnuradio-core / src / python / gnuradio / blks2impl / filterbank.py @ 3f32342f

History | View | Annotate | Download (5.8 kB)

1
#
2
# Copyright 2005,2007 Free Software Foundation, Inc.
3
# 
4
# This file is part of GNU Radio
5
# 
6
# GNU Radio is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 3, or (at your option)
9
# any later version.
10
# 
11
# GNU Radio is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
# 
16
# You should have received a copy of the GNU General Public License
17
# along with GNU Radio; see the file COPYING.  If not, write to
18
# the Free Software Foundation, Inc., 51 Franklin Street,
19
# Boston, MA 02110-1301, USA.
20
# 
21
22
import sys
23
from gnuradio import gr, gru
24
25
def _generate_synthesis_taps(mpoints):
26
    return []   # FIXME
27
28
29
def _split_taps(taps, mpoints):
30
    assert (len(taps) % mpoints) == 0
31
    result = [list() for x in range(mpoints)]
32
    for i in xrange(len(taps)):
33
        (result[i % mpoints]).append(taps[i])
34
    return [tuple(x) for x in result]
35
36
37
class synthesis_filterbank(gr.hier_block2):
38
    """
39
    Uniformly modulated polyphase DFT filter bank: synthesis
40
41
    See http://cnx.org/content/m10424/latest
42
    """
43
    def __init__(self, mpoints, taps=None):
44
        """
45
        Takes M complex streams in, produces single complex stream out
46
        that runs at M times the input sample rate
47
48
        @param mpoints: number of freq bins/interpolation factor/subbands
49
        @param taps:    filter taps for subband filter
50
51
        The channel spacing is equal to the input sample rate.
52
        The total bandwidth and output sample rate are equal the input
53
        sample rate * nchannels.
54
55
        Output stream to frequency mapping:
56
        
57
          channel zero is at zero frequency.
58
59
          if mpoints is odd:
60
            
61
            Channels with increasing positive frequencies come from
62
            channels 1 through (N-1)/2.
63
64
            Channel (N+1)/2 is the maximum negative frequency, and
65
            frequency increases through N-1 which is one channel lower
66
            than the zero frequency.
67
68
          if mpoints is even:
69
70
            Channels with increasing positive frequencies come from
71
            channels 1 through (N/2)-1.
72
73
            Channel (N/2) is evenly split between the max positive and
74
            negative bins.
75
76
            Channel (N/2)+1 is the maximum negative frequency, and
77
            frequency increases through N-1 which is one channel lower
78
            than the zero frequency.
79
80
            Channels near the frequency extremes end up getting cut
81
            off by subsequent filters and therefore have diminished
82
            utility.
83
        """
84
        item_size = gr.sizeof_gr_complex
85
        gr.hier_block2.__init__(self, "synthesis_filterbank",
86
                                gr.io_signature(mpoints, mpoints, item_size), # Input signature
87
                                gr.io_signature(1, 1, item_size))             # Output signature
88
89
90
        if taps is None:
91
            taps = _generate_synthesis_taps(mpoints)
92
93
        # pad taps to multiple of mpoints
94
        r = len(taps) % mpoints
95
        if r != 0:
96
            taps = taps + (mpoints - r) * (0,)
97
98
        # split in mpoints separate set of taps
99
        sub_taps = _split_taps(taps, mpoints)
100
101
        self.ss2v = gr.streams_to_vector(item_size, mpoints)
102
        self.ifft = gr.fft_vcc(mpoints, False, [])
103
        self.v2ss = gr.vector_to_streams(item_size, mpoints)
104
        # mpoints filters go in here...
105
        self.ss2s = gr.streams_to_stream(item_size, mpoints)
106
107
        for i in range(mpoints):
108
            self.connect((self, i), (self.ss2v, i))
109
            
110
        self.connect(self.ss2v, self.ifft, self.v2ss)
111
112
        # build mpoints fir filters...
113
        for i in range(mpoints):
114
            f = gr.fft_filter_ccc(1, sub_taps[i])
115
            self.connect((self.v2ss, i), f)
116
            self.connect(f, (self.ss2s, i))
117
118
        self.connect(self.ss2s, self)
119
        
120
class analysis_filterbank(gr.hier_block2):
121
    """
122
    Uniformly modulated polyphase DFT filter bank: analysis
123
124
    See http://cnx.org/content/m10424/latest
125
    """
126
    def __init__(self, mpoints, taps=None):
127
        """
128
        Takes 1 complex stream in, produces M complex streams out
129
        that runs at 1/M times the input sample rate
130
131
        @param mpoints: number of freq bins/interpolation factor/subbands
132
        @param taps:    filter taps for subband filter
133
134
        Same channel to frequency mapping as described above.
135
        """
136
        item_size = gr.sizeof_gr_complex
137
        gr.hier_block2.__init__(self, "analysis_filterbank",
138
                                gr.io_signature(1, 1, item_size),             # Input signature
139
                                gr.io_signature(mpoints, mpoints, item_size)) # Output signature
140
        
141
        if taps is None:
142
            taps = _generate_synthesis_taps(mpoints)
143
144
        # pad taps to multiple of mpoints
145
        r = len(taps) % mpoints
146
        if r != 0:
147
            taps = taps + (mpoints - r) * (0,)
148
        
149
        # split in mpoints separate set of taps
150
        sub_taps = _split_taps(taps, mpoints)
151
152
        # print >> sys.stderr, "mpoints =", mpoints, "len(sub_taps) =", len(sub_taps) 
153
        
154
        self.s2ss = gr.stream_to_streams(item_size, mpoints)
155
        # filters here
156
        self.ss2v = gr.streams_to_vector(item_size, mpoints)
157
        self.fft = gr.fft_vcc(mpoints, True, [])
158
        self.v2ss = gr.vector_to_streams(item_size, mpoints)
159
160
        self.connect(self, self.s2ss)
161
        
162
        # build mpoints fir filters...
163
        for i in range(mpoints):
164
            f = gr.fft_filter_ccc(1, sub_taps[mpoints-i-1])
165
            self.connect((self.s2ss, i), f)
166
            self.connect(f, (self.ss2v, i))
167
            self.connect((self.v2ss, i), (self, i))
168
            
169
        self.connect(self.ss2v, self.fft, self.v2ss)