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@13: #include c@7: c@13: SpectrogramProcessor::SpectrogramProcessor(const size_t &inputLength, const size_t &windowLength, const size_t &fftLength, const size_t &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@13: m_pFftInput(0), c@13: m_pFftOutputReal(0), c@13: m_pFftOutputImag(0) c@7: { c@7: initialise(); c@7: } c@7: c@11: SpectrogramProcessor::~SpectrogramProcessor(){ c@7: cleanup(); c@7: } c@7: c@11: void SpectrogramProcessor::initialise(){ c@13: m_pFftInput = new double [m_fftLength]; c@13: m_pFftOutputReal = new double [m_fftLength]; c@13: m_pFftOutputImag = new double [m_fftLength]; c@7: } c@7: c@11: void SpectrogramProcessor::cleanup(){ c@13: delete []m_pFftInput; c@13: delete []m_pFftOutputReal; c@13: delete []m_pFftOutputImag; c@7: c@13: m_pFftInput = m_pFftOutputReal = m_pFftOutputImag = 0; c@7: } c@7: c@9: //process method c@13: Spectrogram SpectrogramProcessor::process(const float * const pInput, const float * pWindow) const c@13: { c@13: 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@13: Spectrogram spectrogram(m_numberOfOutputBins, vector(numberOfBlocks)); c@7: c@9: int readPointerBeginIndex = m_hopSize-m_windowLength; c@13: unsigned int writeBlockPointer = 0; c@7: c@13: while(readPointerBeginIndex < (int)m_inputLength){ c@7: c@7: int readPointer = readPointerBeginIndex; c@13: for (unsigned int n = 0; n < m_windowLength; n++){ c@13: if(readPointer < 0 || readPointer >= (int)m_inputLength){ c@13: m_pFftInput[n] = 0.0; //pad with zeros c@7: } c@7: else{ c@13: m_pFftInput[n] = pInput[readPointer] * pWindow[n]; c@7: } c@7: readPointer++; c@7: } c@13: for (unsigned int n = m_windowLength; n < m_fftLength; n++){ c@13: m_pFftInput[n] = 0.0; c@9: } c@7: c@13: FFT::forward(m_fftLength, m_pFftInput, 0, m_pFftOutputReal, m_pFftOutputImag); c@7: c@7: //@todo: sample at logarithmic spacing? Leave for host? c@13: for(unsigned int k = 0; k < m_numberOfOutputBins; k++){ c@13: spectrogram[k][writeBlockPointer] = (m_pFftOutputReal[k]*m_pFftOutputReal[k] + m_pFftOutputImag[k]*m_pFftOutputImag[k]); //Magnitude or power? c@13: //std::cout << spectrogram[k][writeBlockPointer] << std::endl; c@7: } c@7: c@7: readPointerBeginIndex += m_hopSize; c@7: writeBlockPointer++; c@7: } c@7: c@13: return spectrogram; Chris@10: }