c@7
|
1 //
|
c@17
|
2 // SpectrogramProcessor.cpp
|
c@7
|
3 // Tempogram
|
c@7
|
4 //
|
c@7
|
5 // Created by Carl Bussey on 07/08/2014.
|
c@7
|
6 // Copyright (c) 2014 Carl Bussey. All rights reserved.
|
c@7
|
7 //
|
c@7
|
8
|
c@14
|
9 #include "SpectrogramProcessor.h"
|
c@7
|
10 using namespace std;
|
c@7
|
11 using Vamp::FFT;
|
c@13
|
12 #include <iostream>
|
c@7
|
13
|
c@14
|
14 SpectrogramProcessor::SpectrogramProcessor(const size_t &windowLength, const size_t &fftLength, const size_t &hopSize) :
|
c@9
|
15 m_windowLength(windowLength),
|
c@7
|
16 m_fftLength(fftLength),
|
c@7
|
17 m_hopSize(hopSize),
|
c@8
|
18 m_numberOfOutputBins(ceil(fftLength/2) + 1),
|
c@13
|
19 m_pFftInput(0),
|
c@13
|
20 m_pFftOutputReal(0),
|
c@13
|
21 m_pFftOutputImag(0)
|
c@7
|
22 {
|
c@7
|
23 initialise();
|
c@7
|
24 }
|
c@7
|
25
|
c@11
|
26 SpectrogramProcessor::~SpectrogramProcessor(){
|
c@7
|
27 cleanup();
|
c@7
|
28 }
|
c@7
|
29
|
c@11
|
30 void SpectrogramProcessor::initialise(){
|
c@13
|
31 m_pFftInput = new double [m_fftLength];
|
c@13
|
32 m_pFftOutputReal = new double [m_fftLength];
|
c@13
|
33 m_pFftOutputImag = new double [m_fftLength];
|
c@7
|
34 }
|
c@7
|
35
|
c@11
|
36 void SpectrogramProcessor::cleanup(){
|
c@13
|
37 delete []m_pFftInput;
|
c@13
|
38 delete []m_pFftOutputReal;
|
c@13
|
39 delete []m_pFftOutputImag;
|
c@7
|
40
|
c@13
|
41 m_pFftInput = m_pFftOutputReal = m_pFftOutputImag = 0;
|
c@7
|
42 }
|
c@7
|
43
|
c@14
|
44 SpectrogramTransposed SpectrogramProcessor::transpose(const Spectrogram &spectrogram){
|
c@14
|
45 int numberOfBlocks = spectrogram.size();
|
c@14
|
46 int numberOfBins = spectrogram[0].size();
|
c@14
|
47
|
c@14
|
48 SpectrogramTransposed spectrogramT(numberOfBins, vector<float>(numberOfBlocks));
|
c@14
|
49
|
c@14
|
50 for (int i = 0; i < numberOfBlocks; i++){
|
c@14
|
51 for (int j = 0; j < numberOfBins; j++){
|
c@14
|
52 spectrogramT[j][i] = spectrogram[i][j];
|
c@14
|
53 }
|
c@14
|
54 }
|
c@14
|
55
|
c@14
|
56 return spectrogramT;
|
c@14
|
57 }
|
c@14
|
58
|
c@9
|
59 //process method
|
c@14
|
60 Spectrogram SpectrogramProcessor::process(const float * const pInput, const size_t &inputLength, const float * pWindow, const bool &transposeOutput) const
|
c@13
|
61 {
|
c@14
|
62 Spectrogram spectrogram;
|
c@7
|
63
|
c@24
|
64 int readBlockPointerIndex = 0;
|
c@24
|
65 int writeBlockPointer = 0;
|
c@7
|
66
|
c@14
|
67 //cout << m_hopSize << endl;
|
c@24
|
68 while(readBlockPointerIndex <= (int)inputLength) {
|
c@7
|
69
|
c@14
|
70 int readPointer = readBlockPointerIndex - m_windowLength/2;
|
c@20
|
71 for (int n = 0; n < (int)m_windowLength; n++){
|
c@14
|
72 if(readPointer < 0 || readPointer >= (int)inputLength){
|
c@13
|
73 m_pFftInput[n] = 0.0; //pad with zeros
|
c@7
|
74 }
|
c@7
|
75 else{
|
c@13
|
76 m_pFftInput[n] = pInput[readPointer] * pWindow[n];
|
c@7
|
77 }
|
c@7
|
78 readPointer++;
|
c@7
|
79 }
|
c@20
|
80 for (int n = m_windowLength; n < (int)m_fftLength; n++){
|
c@13
|
81 m_pFftInput[n] = 0.0;
|
c@9
|
82 }
|
c@7
|
83
|
c@21
|
84 //cerr << m_fftLength << endl;
|
c@13
|
85 FFT::forward(m_fftLength, m_pFftInput, 0, m_pFftOutputReal, m_pFftOutputImag);
|
c@7
|
86
|
c@14
|
87 vector<float> binValues;
|
c@7
|
88 //@todo: sample at logarithmic spacing? Leave for host?
|
c@20
|
89 for(int k = 0; k < (int)m_numberOfOutputBins; k++){
|
c@14
|
90 binValues.push_back(m_pFftOutputReal[k]*m_pFftOutputReal[k] + m_pFftOutputImag[k]*m_pFftOutputImag[k]); //Magnitude or power?
|
c@13
|
91 //std::cout << spectrogram[k][writeBlockPointer] << std::endl;
|
c@7
|
92 }
|
c@14
|
93 spectrogram.push_back(binValues);
|
c@7
|
94
|
c@14
|
95 readBlockPointerIndex += m_hopSize;
|
c@7
|
96 writeBlockPointer++;
|
c@7
|
97 }
|
c@7
|
98
|
c@14
|
99 if(transposeOutput) return transpose(spectrogram);
|
c@14
|
100 else return spectrogram;
|
Chris@10
|
101 }
|