-
Notifications
You must be signed in to change notification settings - Fork 6
/
PPF.cc
executable file
·76 lines (59 loc) · 2.1 KB
/
PPF.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include "PPF.h"
#include <complex>
#include <cmath>
#include <stdexcept>
PPF::PPF(unsigned nrChannels, unsigned nrTaps, unsigned nrSamplesPerIntegration, bool verbose)
:
nrSamplesPerIntegration(nrSamplesPerIntegration),
nrChannels(nrChannels),
nrTaps(nrTaps),
filterBank(verbose, nrTaps, nrChannels, KAISER),
FIRs(nrChannels),
FFTinData(boost::extents[nrTaps - 1 + nrSamplesPerIntegration][nrChannels])
{
init_fft();
// In CEP, the first subband is from -98 KHz to 98 KHz, rather than from 0 to 195 KHz.
// To avoid that the FFT outputs the channels in the wrong order (from 128 to
// 255 followed by channels 0 to 127), we multiply each second FFT input by -1.
// This is efficiently achieved by negating the FIR filter constants of all
// uneven FIR filters.
filterBank.negateWeights();
// Init the FIR filters themselves with the weights of the filterbank.
for (unsigned chan = 0; chan < nrChannels; chan ++) {
FIRs[chan].init(nrTaps, verbose);
FIRs[chan].setWeights(filterBank.getWeights(chan));
}
}
PPF::~PPF()
{
destroy_fft();
}
void PPF::init_fft()
{
fftwf_complex *buf = static_cast<fftwf_complex *>(fftwf_malloc(2 * nrChannels * sizeof(fftwf_complex)));
assert(buf);
FFTWPlan = fftwf_plan_dft_1d(nrChannels, buf, buf + nrChannels, FFTW_FORWARD, FFTW_ESTIMATE);
fftwf_free(buf);
}
void PPF::destroy_fft()
{
fftwf_destroy_plan(FFTWPlan);
}
void PPF::filter(const std::vector<fcomplex> &in, boost::multi_array<fcomplex, 2> &out)
{
for (int chan = 0; chan < (int) nrChannels; chan ++) {
for (unsigned time = 0; time < nrTaps - 1 + nrSamplesPerIntegration; time ++) {
fcomplex sample = in[chan*nrSamplesPerIntegration + time];
FFTinData[time][chan] = FIRs[chan].processNextSample(sample);
}
}
std::vector<fcomplex> fftOutData(nrChannels);
for (int time = 0; time < nrSamplesPerIntegration; time++) {
fftwf_execute_dft(FFTWPlan,
(fftwf_complex *) FFTinData[nrTaps - 1 + time].origin(),
(fftwf_complex *) (void *) &fftOutData[0]);
for (unsigned chan = 0; chan < nrChannels; chan++) {
out[chan][time] = fftOutData[chan];
}
}
}