c@7
|
1 //
|
c@7
|
2 // Spectrogram.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@7
|
9 #include "Spectrogram.h"
|
c@7
|
10 #include <iostream>
|
c@7
|
11 using namespace std;
|
c@7
|
12 using Vamp::FFT;
|
c@7
|
13
|
c@7
|
14 Spectrogram::Spectrogram(unsigned int inputLength, unsigned int fftLength, unsigned int hopSize) :
|
c@7
|
15 m_inputLength(inputLength),
|
c@7
|
16 m_fftLength(fftLength),
|
c@7
|
17 m_hopSize(hopSize),
|
c@7
|
18 m_numberOfOutputBins(floor(fftLength/2 + 0.5) + 1),
|
c@7
|
19 fftInput(NULL),
|
c@7
|
20 fftOutputReal(NULL),
|
c@7
|
21 fftOutputImag(NULL)
|
c@7
|
22 {
|
c@7
|
23 initialise();
|
c@7
|
24 }
|
c@7
|
25
|
c@7
|
26 Spectrogram::~Spectrogram(){
|
c@7
|
27 cleanup();
|
c@7
|
28 }
|
c@7
|
29
|
c@7
|
30 void Spectrogram::initialise(){
|
c@7
|
31 fftInput = new double [m_fftLength];
|
c@7
|
32 fftOutputReal = new double [m_fftLength];
|
c@7
|
33 fftOutputImag = new double [m_fftLength];
|
c@7
|
34
|
c@7
|
35 int numberOfBlocks = ceil(m_inputLength/m_hopSize) + m_fftLength/m_hopSize-1;
|
c@7
|
36 spectrogramOutput = vector< vector<float> >(m_numberOfOutputBins, vector<float>(numberOfBlocks));
|
c@7
|
37 }
|
c@7
|
38
|
c@7
|
39 void Spectrogram::cleanup(){
|
c@7
|
40 delete []fftInput;
|
c@7
|
41 delete []fftOutputReal;
|
c@7
|
42 delete []fftOutputImag;
|
c@7
|
43
|
c@7
|
44 fftInput = fftOutputReal = fftOutputImag = NULL;
|
c@7
|
45
|
c@7
|
46 cerr << "Spectrogram" << endl;
|
c@7
|
47 }
|
c@7
|
48
|
c@7
|
49 vector< vector<float> > Spectrogram::audioToMagnitudeSpectrogram(const float * const input, const float * window){
|
c@7
|
50
|
c@7
|
51 int readPointerBeginIndex = m_hopSize-m_fftLength;
|
c@7
|
52 int writeBlockPointer = 0;
|
c@7
|
53
|
c@7
|
54 while(readPointerBeginIndex < m_inputLength){
|
c@7
|
55
|
c@7
|
56 int readPointer = readPointerBeginIndex;
|
c@7
|
57 for (int n = 0; n < m_fftLength; n++){
|
c@7
|
58 if(readPointer < 0 || readPointer >= m_inputLength){
|
c@7
|
59 fftInput[n] = 0.0; //pad with zeros
|
c@7
|
60 }
|
c@7
|
61 else{
|
c@7
|
62 fftInput[n] = input[readPointer] * window[n];
|
c@7
|
63 }
|
c@7
|
64 readPointer++;
|
c@7
|
65 }
|
c@7
|
66
|
c@7
|
67 FFT::forward(m_fftLength, fftInput, NULL, fftOutputReal, fftOutputImag);
|
c@7
|
68
|
c@7
|
69 //@todo: sample at logarithmic spacing? Leave for host?
|
c@7
|
70 for(int k = 0; k < m_numberOfOutputBins; k++){
|
c@7
|
71 spectrogramOutput[k][writeBlockPointer] = (fftOutputReal[k]*fftOutputReal[k] + fftOutputImag[k]*fftOutputImag[k]); //Magnitude or power?
|
c@7
|
72 }
|
c@7
|
73
|
c@7
|
74 readPointerBeginIndex += m_hopSize;
|
c@7
|
75 writeBlockPointer++;
|
c@7
|
76 }
|
c@7
|
77
|
c@7
|
78 return spectrogramOutput;
|
c@7
|
79 } |