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@7
|
14
|
c@14
|
15 #include "SpectrogramProcessor.h"
|
c@7
|
16 using namespace std;
|
c@7
|
17 using Vamp::FFT;
|
c@13
|
18 #include <iostream>
|
c@7
|
19
|
c@14
|
20 SpectrogramProcessor::SpectrogramProcessor(const size_t &windowLength, const size_t &fftLength, const size_t &hopSize) :
|
c@9
|
21 m_windowLength(windowLength),
|
c@7
|
22 m_fftLength(fftLength),
|
c@7
|
23 m_hopSize(hopSize),
|
c@8
|
24 m_numberOfOutputBins(ceil(fftLength/2) + 1),
|
c@13
|
25 m_pFftInput(0),
|
c@13
|
26 m_pFftOutputReal(0),
|
c@13
|
27 m_pFftOutputImag(0)
|
c@7
|
28 {
|
c@7
|
29 initialise();
|
c@7
|
30 }
|
c@7
|
31
|
c@11
|
32 SpectrogramProcessor::~SpectrogramProcessor(){
|
c@7
|
33 cleanup();
|
c@7
|
34 }
|
c@7
|
35
|
c@11
|
36 void SpectrogramProcessor::initialise(){
|
c@13
|
37 m_pFftInput = new double [m_fftLength];
|
c@13
|
38 m_pFftOutputReal = new double [m_fftLength];
|
c@13
|
39 m_pFftOutputImag = new double [m_fftLength];
|
c@7
|
40 }
|
c@7
|
41
|
c@11
|
42 void SpectrogramProcessor::cleanup(){
|
c@13
|
43 delete []m_pFftInput;
|
c@13
|
44 delete []m_pFftOutputReal;
|
c@13
|
45 delete []m_pFftOutputImag;
|
c@7
|
46
|
c@13
|
47 m_pFftInput = m_pFftOutputReal = m_pFftOutputImag = 0;
|
c@7
|
48 }
|
c@7
|
49
|
c@14
|
50 SpectrogramTransposed SpectrogramProcessor::transpose(const Spectrogram &spectrogram){
|
c@14
|
51 int numberOfBlocks = spectrogram.size();
|
c@14
|
52 int numberOfBins = spectrogram[0].size();
|
c@14
|
53
|
c@14
|
54 SpectrogramTransposed spectrogramT(numberOfBins, vector<float>(numberOfBlocks));
|
c@14
|
55
|
c@14
|
56 for (int i = 0; i < numberOfBlocks; i++){
|
c@14
|
57 for (int j = 0; j < numberOfBins; j++){
|
c@14
|
58 spectrogramT[j][i] = spectrogram[i][j];
|
c@14
|
59 }
|
c@14
|
60 }
|
c@14
|
61
|
c@14
|
62 return spectrogramT;
|
c@14
|
63 }
|
c@14
|
64
|
c@25
|
65 //calculate max of spectrogram
|
c@25
|
66 float SpectrogramProcessor::calculateMax(const Spectrogram &spectrogram)
|
c@25
|
67 {
|
c@25
|
68 float max = 0;
|
c@25
|
69
|
c@25
|
70 int length = spectrogram.size();
|
c@25
|
71 int height = length > 0 ? spectrogram[0].size() : 0;
|
c@25
|
72
|
c@25
|
73 for (int i = 0; i < length; i++){
|
c@25
|
74 for (int j = 0; j < height; j++){
|
c@25
|
75 max = max > fabs(spectrogram[i][j]) ? max : fabs(spectrogram[i][j]);
|
c@25
|
76 }
|
c@25
|
77 }
|
c@25
|
78
|
c@25
|
79 return max;
|
c@25
|
80 }
|
c@25
|
81
|
c@9
|
82 //process method
|
c@25
|
83 Spectrogram SpectrogramProcessor::process(const float * const pInput, const size_t &inputLength, const float * pWindow) const
|
c@13
|
84 {
|
c@14
|
85 Spectrogram spectrogram;
|
c@7
|
86
|
c@24
|
87 int readBlockPointerIndex = 0;
|
c@24
|
88 int writeBlockPointer = 0;
|
c@7
|
89
|
c@14
|
90 //cout << m_hopSize << endl;
|
c@24
|
91 while(readBlockPointerIndex <= (int)inputLength) {
|
c@7
|
92
|
c@14
|
93 int readPointer = readBlockPointerIndex - m_windowLength/2;
|
c@20
|
94 for (int n = 0; n < (int)m_windowLength; n++){
|
c@14
|
95 if(readPointer < 0 || readPointer >= (int)inputLength){
|
c@13
|
96 m_pFftInput[n] = 0.0; //pad with zeros
|
c@7
|
97 }
|
c@7
|
98 else{
|
c@13
|
99 m_pFftInput[n] = pInput[readPointer] * pWindow[n];
|
c@7
|
100 }
|
c@7
|
101 readPointer++;
|
c@7
|
102 }
|
c@20
|
103 for (int n = m_windowLength; n < (int)m_fftLength; n++){
|
c@13
|
104 m_pFftInput[n] = 0.0;
|
c@9
|
105 }
|
c@7
|
106
|
c@21
|
107 //cerr << m_fftLength << endl;
|
c@13
|
108 FFT::forward(m_fftLength, m_pFftInput, 0, m_pFftOutputReal, m_pFftOutputImag);
|
c@7
|
109
|
c@14
|
110 vector<float> binValues;
|
c@7
|
111 //@todo: sample at logarithmic spacing? Leave for host?
|
c@20
|
112 for(int k = 0; k < (int)m_numberOfOutputBins; k++){
|
c@14
|
113 binValues.push_back(m_pFftOutputReal[k]*m_pFftOutputReal[k] + m_pFftOutputImag[k]*m_pFftOutputImag[k]); //Magnitude or power?
|
c@13
|
114 //std::cout << spectrogram[k][writeBlockPointer] << std::endl;
|
c@7
|
115 }
|
c@14
|
116 spectrogram.push_back(binValues);
|
c@7
|
117
|
c@14
|
118 readBlockPointerIndex += m_hopSize;
|
c@7
|
119 writeBlockPointer++;
|
c@7
|
120 }
|
c@7
|
121
|
c@25
|
122 return spectrogram;
|
Chris@10
|
123 }
|