c@7: // c@7: // Spectrogram.cpp c@7: // Tempogram c@7: // c@7: // Created by Carl Bussey on 07/08/2014. c@7: // Copyright (c) 2014 Carl Bussey. All rights reserved. c@7: // c@7: c@7: #include "Spectrogram.h" c@7: using namespace std; c@7: using Vamp::FFT; c@7: c@9: Spectrogram::Spectrogram(unsigned int inputLength, unsigned int windowLength, unsigned int fftLength, unsigned int hopSize) : c@7: m_inputLength(inputLength), c@9: m_windowLength(windowLength), c@7: m_fftLength(fftLength), c@7: m_hopSize(hopSize), c@8: m_numberOfOutputBins(ceil(fftLength/2) + 1), c@7: fftInput(NULL), c@7: fftOutputReal(NULL), c@7: fftOutputImag(NULL) c@7: { c@7: initialise(); c@7: } c@7: c@7: Spectrogram::~Spectrogram(){ c@7: cleanup(); c@7: } c@7: c@7: void Spectrogram::initialise(){ c@7: fftInput = new double [m_fftLength]; c@7: fftOutputReal = new double [m_fftLength]; c@7: fftOutputImag = new double [m_fftLength]; c@7: c@9: 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... c@7: spectrogramOutput = vector< vector >(m_numberOfOutputBins, vector(numberOfBlocks)); c@7: } c@7: c@7: void Spectrogram::cleanup(){ c@7: delete []fftInput; c@7: delete []fftOutputReal; c@7: delete []fftOutputImag; c@7: c@7: fftInput = fftOutputReal = fftOutputImag = NULL; c@7: } c@7: c@9: //process method c@7: vector< vector > Spectrogram::audioToMagnitudeSpectrogram(const float * const input, const float * window){ c@7: c@9: int readPointerBeginIndex = m_hopSize-m_windowLength; c@7: int writeBlockPointer = 0; c@7: c@7: while(readPointerBeginIndex < m_inputLength){ c@7: c@7: int readPointer = readPointerBeginIndex; c@9: for (int n = 0; n < m_windowLength; n++){ c@7: if(readPointer < 0 || readPointer >= m_inputLength){ c@7: fftInput[n] = 0.0; //pad with zeros c@7: } c@7: else{ c@7: fftInput[n] = input[readPointer] * window[n]; c@7: } c@7: readPointer++; c@7: } c@9: for (int n = m_windowLength; n < m_fftLength; n++){ c@9: fftInput[n] = 0.0; c@9: } c@7: c@7: FFT::forward(m_fftLength, fftInput, NULL, fftOutputReal, fftOutputImag); c@7: c@7: //@todo: sample at logarithmic spacing? Leave for host? c@7: for(int k = 0; k < m_numberOfOutputBins; k++){ c@7: spectrogramOutput[k][writeBlockPointer] = (fftOutputReal[k]*fftOutputReal[k] + fftOutputImag[k]*fftOutputImag[k]); //Magnitude or power? c@7: } c@7: c@7: readPointerBeginIndex += m_hopSize; c@7: writeBlockPointer++; c@7: } c@7: c@7: return spectrogramOutput; c@7: }