c@0
|
1 //
|
c@0
|
2 // FIRFilter.cpp
|
c@0
|
3 // Tempogram
|
c@0
|
4 //
|
c@0
|
5 // Created by Carl Bussey on 25/06/2014.
|
c@0
|
6 // Copyright (c) 2014 Carl Bussey. All rights reserved.
|
c@0
|
7 //
|
c@0
|
8
|
c@0
|
9 #include "FIRFilter.h"
|
c@7
|
10
|
c@0
|
11 using namespace std;
|
c@0
|
12 using Vamp::FFT;
|
c@0
|
13
|
c@13
|
14 FIRFilter::FIRFilter(const size_t &lengthInput, const size_t &numberOfCoefficients) :
|
c@8
|
15 m_lengthInput(lengthInput),
|
c@8
|
16 m_numberOfCoefficients(numberOfCoefficients),
|
c@13
|
17 m_pFftInput(0),
|
c@13
|
18 m_pFftCoefficients(0),
|
c@13
|
19 m_pFftReal1(0),
|
c@13
|
20 m_pFftImag1(0),
|
c@13
|
21 m_pFftReal2(0),
|
c@13
|
22 m_pFftImag2(0),
|
c@13
|
23 m_pFftFilteredReal(0),
|
c@13
|
24 m_pFftFilteredImag(0),
|
c@13
|
25 m_pFftOutputReal(0),
|
c@13
|
26 m_pFftOutputImag(0)
|
c@0
|
27 {
|
c@0
|
28 initialise();
|
c@0
|
29 }
|
c@0
|
30
|
c@0
|
31 FIRFilter::~FIRFilter()
|
c@0
|
32 {
|
c@0
|
33 cleanup();
|
c@0
|
34 }
|
c@0
|
35
|
c@9
|
36 //allocate memory
|
c@0
|
37 void
|
c@0
|
38 FIRFilter::initialise()
|
c@0
|
39 {
|
c@9
|
40 //next power of 2
|
c@8
|
41 m_lengthFIRFFT = pow(2,(ceil(log2(m_lengthInput+m_numberOfCoefficients-1))));
|
c@0
|
42
|
c@13
|
43 m_pFftInput = new double[m_lengthFIRFFT];
|
c@13
|
44 m_pFftCoefficients = new double[m_lengthFIRFFT];
|
c@13
|
45 m_pFftReal1 = new double[m_lengthFIRFFT];
|
c@13
|
46 m_pFftImag1 = new double[m_lengthFIRFFT];
|
c@13
|
47 m_pFftReal2 = new double[m_lengthFIRFFT];
|
c@13
|
48 m_pFftImag2 = new double[m_lengthFIRFFT];
|
c@13
|
49 m_pFftFilteredReal = new double[m_lengthFIRFFT];
|
c@13
|
50 m_pFftFilteredImag = new double[m_lengthFIRFFT];
|
c@13
|
51 m_pFftOutputReal = new double[m_lengthFIRFFT];
|
c@13
|
52 m_pFftOutputImag = new double[m_lengthFIRFFT];
|
c@0
|
53
|
c@13
|
54 for(unsigned int i = 0; i < m_lengthFIRFFT; i++){
|
c@13
|
55 m_pFftInput[i] = m_pFftCoefficients[i] = m_pFftReal1[i] = m_pFftImag1[i] = m_pFftReal2[i] = m_pFftImag2[i] = m_pFftFilteredReal[i] = m_pFftFilteredImag[i] = m_pFftOutputReal[i] = m_pFftOutputImag[i] = 0.0;
|
c@0
|
56 }
|
c@0
|
57 }
|
c@0
|
58
|
c@0
|
59 void
|
c@13
|
60 FIRFilter::process(const float* pInput, const float* pCoefficients, float* pOutput)
|
c@0
|
61 {
|
c@9
|
62 //Copy to same length FFT buffers
|
c@13
|
63 for(unsigned int i = 0; i < m_lengthFIRFFT; i++){
|
c@13
|
64 m_pFftInput[i] = i < m_lengthInput ? pInput[i] : 0.0;
|
c@13
|
65 m_pFftCoefficients[i] = i < m_numberOfCoefficients ? pCoefficients[i] : 0.0;
|
c@0
|
66 }
|
c@0
|
67
|
c@13
|
68 FFT::forward(m_lengthFIRFFT, m_pFftInput, 0, m_pFftReal1, m_pFftImag1);
|
c@13
|
69 FFT::forward(m_lengthFIRFFT, m_pFftCoefficients, 0, m_pFftReal2, m_pFftImag2);
|
c@7
|
70
|
c@9
|
71 //Multiply FFT coefficients. Multiplication in freq domain is convolution in time domain.
|
c@13
|
72 for (unsigned int i = 0; i < m_lengthFIRFFT; i++){
|
c@13
|
73 m_pFftFilteredReal[i] = (m_pFftReal1[i] * m_pFftReal2[i]) - (m_pFftImag1[i] * m_pFftImag2[i]);
|
c@13
|
74 m_pFftFilteredImag[i] = (m_pFftReal1[i] * m_pFftImag2[i]) + (m_pFftReal2[i] * m_pFftImag1[i]);
|
c@0
|
75 }
|
c@13
|
76
|
c@13
|
77 FFT::inverse(m_lengthFIRFFT, m_pFftFilteredReal, m_pFftFilteredImag, m_pFftOutputReal, m_pFftOutputImag);
|
c@0
|
78
|
c@9
|
79 //copy to output
|
c@13
|
80 for (unsigned int i = 0; i < m_lengthInput; i++){
|
c@13
|
81 pOutput[i] = m_pFftOutputReal[i];
|
c@0
|
82 }
|
c@0
|
83 }
|
c@0
|
84
|
c@9
|
85 //remove memory allocations
|
c@0
|
86 void
|
c@0
|
87 FIRFilter::cleanup()
|
c@0
|
88 {
|
c@13
|
89 delete []m_pFftInput;
|
c@13
|
90 delete []m_pFftCoefficients;
|
c@13
|
91 delete []m_pFftReal1;
|
c@13
|
92 delete []m_pFftImag1;
|
c@13
|
93 delete []m_pFftReal2;
|
c@13
|
94 delete []m_pFftImag2;
|
c@13
|
95 delete []m_pFftFilteredReal;
|
c@13
|
96 delete []m_pFftFilteredImag;
|
c@13
|
97 delete []m_pFftOutputReal;
|
c@13
|
98 delete []m_pFftOutputImag;
|
c@13
|
99 m_pFftInput = m_pFftCoefficients = m_pFftReal1 = m_pFftImag1 = m_pFftReal2 = m_pFftImag2 = m_pFftFilteredReal = m_pFftFilteredImag = m_pFftOutputReal = m_pFftOutputImag = 0;
|
Chris@10
|
100 }
|