annotate SpectrogramProcessor.cpp @ 33:a824d7d14eb9

Clamp band boundaries to block size
author Chris Cannam
date Thu, 04 Sep 2014 10:40:31 +0100
parents fe23998968b4
children 4cf2d163127b
rev   line source
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@25 59 //calculate max of spectrogram
c@25 60 float SpectrogramProcessor::calculateMax(const Spectrogram &spectrogram)
c@25 61 {
c@25 62 float max = 0;
c@25 63
c@25 64 int length = spectrogram.size();
c@25 65 int height = length > 0 ? spectrogram[0].size() : 0;
c@25 66
c@25 67 for (int i = 0; i < length; i++){
c@25 68 for (int j = 0; j < height; j++){
c@25 69 max = max > fabs(spectrogram[i][j]) ? max : fabs(spectrogram[i][j]);
c@25 70 }
c@25 71 }
c@25 72
c@25 73 return max;
c@25 74 }
c@25 75
c@9 76 //process method
c@25 77 Spectrogram SpectrogramProcessor::process(const float * const pInput, const size_t &inputLength, const float * pWindow) const
c@13 78 {
c@14 79 Spectrogram spectrogram;
c@7 80
c@24 81 int readBlockPointerIndex = 0;
c@24 82 int writeBlockPointer = 0;
c@7 83
c@14 84 //cout << m_hopSize << endl;
c@24 85 while(readBlockPointerIndex <= (int)inputLength) {
c@7 86
c@14 87 int readPointer = readBlockPointerIndex - m_windowLength/2;
c@20 88 for (int n = 0; n < (int)m_windowLength; n++){
c@14 89 if(readPointer < 0 || readPointer >= (int)inputLength){
c@13 90 m_pFftInput[n] = 0.0; //pad with zeros
c@7 91 }
c@7 92 else{
c@13 93 m_pFftInput[n] = pInput[readPointer] * pWindow[n];
c@7 94 }
c@7 95 readPointer++;
c@7 96 }
c@20 97 for (int n = m_windowLength; n < (int)m_fftLength; n++){
c@13 98 m_pFftInput[n] = 0.0;
c@9 99 }
c@7 100
c@21 101 //cerr << m_fftLength << endl;
c@13 102 FFT::forward(m_fftLength, m_pFftInput, 0, m_pFftOutputReal, m_pFftOutputImag);
c@7 103
c@14 104 vector<float> binValues;
c@7 105 //@todo: sample at logarithmic spacing? Leave for host?
c@20 106 for(int k = 0; k < (int)m_numberOfOutputBins; k++){
c@14 107 binValues.push_back(m_pFftOutputReal[k]*m_pFftOutputReal[k] + m_pFftOutputImag[k]*m_pFftOutputImag[k]); //Magnitude or power?
c@13 108 //std::cout << spectrogram[k][writeBlockPointer] << std::endl;
c@7 109 }
c@14 110 spectrogram.push_back(binValues);
c@7 111
c@14 112 readBlockPointerIndex += m_hopSize;
c@7 113 writeBlockPointer++;
c@7 114 }
c@7 115
c@25 116 return spectrogram;
Chris@10 117 }