comparison Spectrogram.cpp @ 9:be59b4a73f49

* Added Spectrogram zero padding functionality * Made output bins correspond to BPM * User can now specify a range of output bins to view * Comments added
author Carl Bussey <c.bussey@se10.qmul.ac.uk>
date Tue, 12 Aug 2014 14:40:37 +0100
parents 4e429b9f2b4d
children 17a260410116 09fb76606b2b
comparison
equal deleted inserted replaced
8:4e429b9f2b4d 9:be59b4a73f49
5 // Created by Carl Bussey on 07/08/2014. 5 // Created by Carl Bussey on 07/08/2014.
6 // Copyright (c) 2014 Carl Bussey. All rights reserved. 6 // Copyright (c) 2014 Carl Bussey. All rights reserved.
7 // 7 //
8 8
9 #include "Spectrogram.h" 9 #include "Spectrogram.h"
10 #include <iostream>
11 using namespace std; 10 using namespace std;
12 using Vamp::FFT; 11 using Vamp::FFT;
13 12
14 Spectrogram::Spectrogram(unsigned int inputLength, unsigned int fftLength, unsigned int hopSize) : 13 Spectrogram::Spectrogram(unsigned int inputLength, unsigned int windowLength, unsigned int fftLength, unsigned int hopSize) :
15 m_inputLength(inputLength), 14 m_inputLength(inputLength),
15 m_windowLength(windowLength),
16 m_fftLength(fftLength), 16 m_fftLength(fftLength),
17 m_hopSize(hopSize), 17 m_hopSize(hopSize),
18 m_numberOfOutputBins(ceil(fftLength/2) + 1), 18 m_numberOfOutputBins(ceil(fftLength/2) + 1),
19 fftInput(NULL), 19 fftInput(NULL),
20 fftOutputReal(NULL), 20 fftOutputReal(NULL),
30 void Spectrogram::initialise(){ 30 void Spectrogram::initialise(){
31 fftInput = new double [m_fftLength]; 31 fftInput = new double [m_fftLength];
32 fftOutputReal = new double [m_fftLength]; 32 fftOutputReal = new double [m_fftLength];
33 fftOutputImag = new double [m_fftLength]; 33 fftOutputImag = new double [m_fftLength];
34 34
35 int numberOfBlocks = ceil(m_inputLength/m_hopSize) + 2*(ceil(m_fftLength/m_hopSize)-1); //The last term corresponds to overlaps at the beginning and end with padded zeros. I.e., if m_hopSize = m_fftLength/2, there'll be 1 overlap at each end. If m_hopSize = m_fftLength/4, there'll be 3 overlaps at each end, etc... 35 int numberOfBlocks = ceil(m_inputLength/m_hopSize) + 2*(ceil(m_windowLength/m_hopSize)-1); //The last term corresponds to overlaps at the beginning and end with padded zeros. I.e., if m_hopSize = m_windowLength/2, there'll be 1 overlap at each end. If m_hopSize = m_windowLength/4, there'll be 3 overlaps at each end, etc...
36 spectrogramOutput = vector< vector<float> >(m_numberOfOutputBins, vector<float>(numberOfBlocks)); 36 spectrogramOutput = vector< vector<float> >(m_numberOfOutputBins, vector<float>(numberOfBlocks));
37 } 37 }
38 38
39 void Spectrogram::cleanup(){ 39 void Spectrogram::cleanup(){
40 delete []fftInput; 40 delete []fftInput;
42 delete []fftOutputImag; 42 delete []fftOutputImag;
43 43
44 fftInput = fftOutputReal = fftOutputImag = NULL; 44 fftInput = fftOutputReal = fftOutputImag = NULL;
45 } 45 }
46 46
47 //process method
47 vector< vector<float> > Spectrogram::audioToMagnitudeSpectrogram(const float * const input, const float * window){ 48 vector< vector<float> > Spectrogram::audioToMagnitudeSpectrogram(const float * const input, const float * window){
48 49
49 int readPointerBeginIndex = m_hopSize-m_fftLength; 50 int readPointerBeginIndex = m_hopSize-m_windowLength;
50 int writeBlockPointer = 0; 51 int writeBlockPointer = 0;
51 52
52 while(readPointerBeginIndex < m_inputLength){ 53 while(readPointerBeginIndex < m_inputLength){
53 54
54 int readPointer = readPointerBeginIndex; 55 int readPointer = readPointerBeginIndex;
55 for (int n = 0; n < m_fftLength; n++){ 56 for (int n = 0; n < m_windowLength; n++){
56 if(readPointer < 0 || readPointer >= m_inputLength){ 57 if(readPointer < 0 || readPointer >= m_inputLength){
57 fftInput[n] = 0.0; //pad with zeros 58 fftInput[n] = 0.0; //pad with zeros
58 } 59 }
59 else{ 60 else{
60 fftInput[n] = input[readPointer] * window[n]; 61 fftInput[n] = input[readPointer] * window[n];
61 } 62 }
62 readPointer++; 63 readPointer++;
63 } 64 }
65 for (int n = m_windowLength; n < m_fftLength; n++){
66 fftInput[n] = 0.0;
67 }
64 68
65 FFT::forward(m_fftLength, fftInput, NULL, fftOutputReal, fftOutputImag); 69 FFT::forward(m_fftLength, fftInput, NULL, fftOutputReal, fftOutputImag);
66 70
67 //@todo: sample at logarithmic spacing? Leave for host? 71 //@todo: sample at logarithmic spacing? Leave for host?
68 for(int k = 0; k < m_numberOfOutputBins; k++){ 72 for(int k = 0; k < m_numberOfOutputBins; k++){
69 spectrogramOutput[k][writeBlockPointer] = (fftOutputReal[k]*fftOutputReal[k] + fftOutputImag[k]*fftOutputImag[k]); //Magnitude or power? 73 spectrogramOutput[k][writeBlockPointer] = (fftOutputReal[k]*fftOutputReal[k] + fftOutputImag[k]*fftOutputImag[k]); //Magnitude or power?
70 cerr << writeBlockPointer << " : " << spectrogramOutput[k].size() << endl;
71 } 74 }
72 75
73 readPointerBeginIndex += m_hopSize; 76 readPointerBeginIndex += m_hopSize;
74 writeBlockPointer++; 77 writeBlockPointer++;
75 } 78 }