Chris@43
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@43
|
2
|
Chris@43
|
3 /*
|
Chris@43
|
4 Vamp Tempogram Plugin
|
Chris@43
|
5 Carl Bussey, Centre for Digital Music, Queen Mary University of London
|
Chris@43
|
6 Copyright 2014 Queen Mary University of London.
|
Chris@43
|
7
|
Chris@43
|
8 This program is free software; you can redistribute it and/or
|
Chris@43
|
9 modify it under the terms of the GNU General Public License as
|
Chris@43
|
10 published by the Free Software Foundation; either version 2 of the
|
Chris@43
|
11 License, or (at your option) any later version. See the file
|
Chris@43
|
12 COPYING included with this distribution for more information.
|
Chris@43
|
13 */
|
c@0
|
14
|
c@0
|
15 #include "FIRFilter.h"
|
c@7
|
16
|
c@0
|
17 using namespace std;
|
c@0
|
18 using Vamp::FFT;
|
c@0
|
19
|
c@13
|
20 FIRFilter::FIRFilter(const size_t &lengthInput, const size_t &numberOfCoefficients) :
|
c@8
|
21 m_lengthInput(lengthInput),
|
c@8
|
22 m_numberOfCoefficients(numberOfCoefficients),
|
c@13
|
23 m_pFftInput(0),
|
c@13
|
24 m_pFftCoefficients(0),
|
c@13
|
25 m_pFftReal1(0),
|
c@13
|
26 m_pFftImag1(0),
|
c@13
|
27 m_pFftReal2(0),
|
c@13
|
28 m_pFftImag2(0),
|
c@13
|
29 m_pFftFilteredReal(0),
|
c@13
|
30 m_pFftFilteredImag(0),
|
c@13
|
31 m_pFftOutputReal(0),
|
c@13
|
32 m_pFftOutputImag(0)
|
c@0
|
33 {
|
c@0
|
34 initialise();
|
c@0
|
35 }
|
c@0
|
36
|
c@0
|
37 FIRFilter::~FIRFilter()
|
c@0
|
38 {
|
c@0
|
39 cleanup();
|
c@0
|
40 }
|
c@0
|
41
|
c@9
|
42 //allocate memory
|
c@0
|
43 void
|
c@0
|
44 FIRFilter::initialise()
|
c@0
|
45 {
|
c@9
|
46 //next power of 2
|
c@8
|
47 m_lengthFIRFFT = pow(2,(ceil(log2(m_lengthInput+m_numberOfCoefficients-1))));
|
c@0
|
48
|
c@13
|
49 m_pFftInput = new double[m_lengthFIRFFT];
|
c@13
|
50 m_pFftCoefficients = new double[m_lengthFIRFFT];
|
c@13
|
51 m_pFftReal1 = new double[m_lengthFIRFFT];
|
c@13
|
52 m_pFftImag1 = new double[m_lengthFIRFFT];
|
c@13
|
53 m_pFftReal2 = new double[m_lengthFIRFFT];
|
c@13
|
54 m_pFftImag2 = new double[m_lengthFIRFFT];
|
c@13
|
55 m_pFftFilteredReal = new double[m_lengthFIRFFT];
|
c@13
|
56 m_pFftFilteredImag = new double[m_lengthFIRFFT];
|
c@13
|
57 m_pFftOutputReal = new double[m_lengthFIRFFT];
|
c@13
|
58 m_pFftOutputImag = new double[m_lengthFIRFFT];
|
c@0
|
59
|
c@20
|
60 for(int i = 0; i < (int)m_lengthFIRFFT; i++){
|
c@13
|
61 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
|
62 }
|
c@0
|
63 }
|
c@0
|
64
|
c@0
|
65 void
|
c@15
|
66 FIRFilter::process(const float* pInput, const float* pCoefficients, float* pOutput, OutputTypeArgument outputType)
|
c@0
|
67 {
|
c@15
|
68
|
c@9
|
69 //Copy to same length FFT buffers
|
c@20
|
70 for(int i = 0; i < (int)m_lengthFIRFFT; i++){
|
c@20
|
71 m_pFftInput[i] = i < (int)m_lengthInput ? pInput[i] : 0.0;
|
c@20
|
72 m_pFftCoefficients[i] = i < (int)m_numberOfCoefficients ? pCoefficients[i] : 0.0;
|
c@0
|
73 }
|
c@0
|
74
|
c@13
|
75 FFT::forward(m_lengthFIRFFT, m_pFftInput, 0, m_pFftReal1, m_pFftImag1);
|
c@13
|
76 FFT::forward(m_lengthFIRFFT, m_pFftCoefficients, 0, m_pFftReal2, m_pFftImag2);
|
c@7
|
77
|
c@9
|
78 //Multiply FFT coefficients. Multiplication in freq domain is convolution in time domain.
|
c@20
|
79 for (int i = 0; i < (int)m_lengthFIRFFT; i++){
|
c@13
|
80 m_pFftFilteredReal[i] = (m_pFftReal1[i] * m_pFftReal2[i]) - (m_pFftImag1[i] * m_pFftImag2[i]);
|
c@13
|
81 m_pFftFilteredImag[i] = (m_pFftReal1[i] * m_pFftImag2[i]) + (m_pFftReal2[i] * m_pFftImag1[i]);
|
c@0
|
82 }
|
c@13
|
83
|
c@13
|
84 FFT::inverse(m_lengthFIRFFT, m_pFftFilteredReal, m_pFftFilteredImag, m_pFftOutputReal, m_pFftOutputImag);
|
c@0
|
85
|
c@9
|
86 //copy to output
|
c@15
|
87 int offset = 0;
|
c@20
|
88 int outputLength = m_lengthInput;
|
c@35
|
89 if (outputType == all) outputLength = m_lengthInput+m_numberOfCoefficients-1;
|
c@20
|
90 else if (outputType == middle) offset = floor(m_numberOfCoefficients/2.0f);
|
c@15
|
91 else if (outputType != first) cerr << "FIRFilter::process(params) - " << outputType << " is not a valid argument. outputType is set to first." << endl;
|
c@15
|
92
|
c@20
|
93 for (int i = 0; i < outputLength; i++){
|
c@14
|
94 pOutput[i] = m_pFftOutputReal[i + offset];
|
c@0
|
95 }
|
c@0
|
96 }
|
c@0
|
97
|
c@9
|
98 //remove memory allocations
|
c@0
|
99 void
|
c@0
|
100 FIRFilter::cleanup()
|
c@0
|
101 {
|
c@13
|
102 delete []m_pFftInput;
|
c@13
|
103 delete []m_pFftCoefficients;
|
c@13
|
104 delete []m_pFftReal1;
|
c@13
|
105 delete []m_pFftImag1;
|
c@13
|
106 delete []m_pFftReal2;
|
c@13
|
107 delete []m_pFftImag2;
|
c@13
|
108 delete []m_pFftFilteredReal;
|
c@13
|
109 delete []m_pFftFilteredImag;
|
c@13
|
110 delete []m_pFftOutputReal;
|
c@13
|
111 delete []m_pFftOutputImag;
|
c@13
|
112 m_pFftInput = m_pFftCoefficients = m_pFftReal1 = m_pFftImag1 = m_pFftReal2 = m_pFftImag2 = m_pFftFilteredReal = m_pFftFilteredImag = m_pFftOutputReal = m_pFftOutputImag = 0;
|
Chris@10
|
113 }
|