annotate FIRFilter.cpp @ 47:cb79f27f0748

Clamp cyclic tempogram min and max BPM to the BPM equivalents of the actual underlying min and max tempogram bins, rather than the "input" min and max BPM (fixed root cause of #1054)
author Chris Cannam
date Mon, 29 Sep 2014 16:20:16 +0100
parents 4cf2d163127b
children
rev   line source
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 }