blob: 80eab3ee325dc4560b1737beacf69d7ccfcdc908 [file] [log] [blame]
Tom Tsou35222292016-06-22 16:16:30 -07001/*
2 * Polyphase channelizer
3 *
4 * Copyright (C) 2012-2014 Tom Tsou <tom@tsou.cc>
5 * Copyright (C) 2015 Ettus Research LLC
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 * See the COPYING file in the main directory for details.
20 */
21
22#include <stdlib.h>
23#include <math.h>
24#include <assert.h>
25#include <string.h>
26#include <cstdio>
27
Tom Tsou35222292016-06-22 16:16:30 -070028#include "Channelizer.h"
29
30extern "C" {
31#include "common/fft.h"
32#include "common/convolve.h"
33}
34
35static void deinterleave(const float *in, size_t ilen,
36 float **out, size_t olen, size_t m)
37{
38 size_t i, n;
39
40 for (i = 0; i < olen; i++) {
41 for (n = 0; n < m; n++) {
42 out[m - 1 - n][2 * i + 0] = in[2 * (i * m + n) + 0];
43 out[m - 1 - n][2 * i + 1] = in[2 * (i * m + n) + 1];
44 }
45 }
46}
47
48size_t Channelizer::inputLen() const
49{
50 return blockLen * m;
51}
52
53size_t Channelizer::outputLen() const
54{
55 return blockLen;
56}
57
58float *Channelizer::outputBuffer(size_t chan) const
59{
60 if (chan >= m)
61 return NULL;
62
63 return hInputs[chan];
64}
65
66/*
67 * Implementation based on material found in:
68 *
69 * "harris, fred, Multirate Signal Processing, Upper Saddle River, NJ,
70 * Prentice Hall, 2006."
71 */
72bool Channelizer::rotate(const float *in, size_t len)
73{
74 size_t hSize = 2 * hLen * sizeof(float);
75
76 if (!checkLen(blockLen, len))
77 return false;
78
79 deinterleave(in, len, hInputs, blockLen, m);
80
81 /*
82 * Convolve through filterbank while applying and saving sample history
83 */
84 for (size_t i = 0; i < m; i++) {
85 memcpy(&hInputs[i][2 * -hLen], hist[i], hSize);
86 memcpy(hist[i], &hInputs[i][2 * (blockLen - hLen)], hSize);
87
88 convolve_real(hInputs[i], blockLen,
89 subFilters[i], hLen,
90 hOutputs[i], blockLen,
91 0, blockLen, 1, 0);
92 }
93
94 cxvec_fft(fftHandle);
95
96 return true;
97}
98
99/* Setup channelizer paramaters */
100Channelizer::Channelizer(size_t m, size_t blockLen, size_t hLen)
101 : ChannelizerBase(m, blockLen, hLen)
102{
103}
104
105Channelizer::~Channelizer()
106{
107}