Mercurial > hg > vamp-tempogram
diff NoveltyCurve.cpp @ 5:8d7e336b41e9
Adding NoveltyCurve.*
author | Carl Bussey <c.bussey@se10.qmul.ac.uk> |
---|---|
date | Tue, 05 Aug 2014 15:59:15 +0100 |
parents | |
children | 21147df9cb2d |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NoveltyCurve.cpp Tue Aug 05 15:59:15 2014 +0100 @@ -0,0 +1,139 @@ +// +// NoveltyCurve.cpp +// Tempogram +// +// Created by Carl Bussey on 10/07/2014. +// Copyright (c) 2014 Carl Bussey. All rights reserved. +// + +#include <cmath> +#include <vector> +#include <iostream> +#include "FIRFilter.h" +#include "WindowFunction.h" +using namespace std; +#include "NoveltyCurve.h" + +NoveltyCurve::NoveltyCurve(float samplingFrequency, int blockSize, int numberOfBlocks, int compressionConstant) : + m_samplingFrequency(samplingFrequency), + m_blockSize(blockSize), + m_numberOfBlocks(numberOfBlocks), + m_compressionConstant(compressionConstant), + m_numberOfBands(5), + m_bandBoundaries(NULL), + m_hannLength(65), + m_hannWindow(NULL), + m_bandSum(NULL) +{ + initialise(); +} + +NoveltyCurve::~NoveltyCurve(){ + cleanup(); +} + +void +NoveltyCurve::initialise(){ + data = vector<float>(m_numberOfBlocks); + + m_hannWindow = new float[m_hannLength]; + WindowFunction::hanning(m_hannWindow, m_hannLength, true); + + m_bandBoundaries = new int[m_numberOfBands+1]; //make index variable + + m_bandBoundaries[0] = 0; + for (int band = 1; band < m_numberOfBands; band++){ + float lowFreq = 500*pow(2.5, band-1); + m_bandBoundaries[band] = m_blockSize*lowFreq/m_samplingFrequency; + } + m_bandBoundaries[m_numberOfBands] = m_blockSize/2 + 1; + + m_bandSum = new float * [m_numberOfBands]; + for (int i = 0; i < m_numberOfBands; i++){ + m_bandSum[i] = new float[m_numberOfBlocks]; + } +} + +void +NoveltyCurve::cleanup(){ + delete []m_hannWindow; + m_hannWindow = NULL; + delete []m_bandBoundaries; + m_bandBoundaries = NULL; + + for(int i = 0; i < m_numberOfBands; i++){ + delete []m_bandSum[i]; + m_bandSum[i] = NULL; + } + delete []m_bandSum; + m_bandSum = NULL; +} + +float NoveltyCurve::calculateMax(float ** spectrogram){ + int specLength = (m_blockSize/2 + 1); + float max = 0; + + for (int j = 0; j < m_numberOfBlocks; j++){ + for (int i = 0; i < specLength; i++){ + max = max > spectrogram[i][j] ? max : spectrogram[i][j]; + } + } + + return max; +} + +void NoveltyCurve::subtractLocalAverage(float * noveltyCurve){ + vector<float> localAverage(m_numberOfBlocks); + + FIRFilter *filter = new FIRFilter(m_numberOfBlocks, m_hannLength); + filter->process(&noveltyCurve[0], m_hannWindow, &localAverage[0]); + delete filter; + + for (int i = 0; i < m_numberOfBlocks; i++){ + noveltyCurve[i] -= localAverage[i]; + noveltyCurve[i] = noveltyCurve[i] >= 0 ? noveltyCurve[i] : 0; + } +} + +vector<float> +NoveltyCurve::spectrogramToNoveltyCurve(float ** spectrogram){ + + float normaliseScale = calculateMax(spectrogram); + + for (int block = 0; block < m_numberOfBlocks; block++){ + + for (int band = 0; band < m_numberOfBands; band++){ + + int specIndex = m_bandBoundaries[band]; + int bandEnd = m_bandBoundaries[band+1]; + + while(specIndex < bandEnd){ + + spectrogram[specIndex][block] /= normaliseScale; //normalise + spectrogram[specIndex][block] = log(1+m_compressionConstant*spectrogram[specIndex][block]); + + int currentY = spectrogram[specIndex][block]; + int prevBlock = block-1; + int previousY = prevBlock >= 0 ? spectrogram[specIndex][prevBlock] : 0; + + if(currentY > previousY){ + m_bandSum[band][block] += (currentY - previousY); + } + + //cout << specIndex << endl; + specIndex++; + } + } + + float total = 0; + for(int band = 0; band < m_numberOfBands; band++){ + total += m_bandSum[band][block]; + } + float average = total/m_numberOfBands; + data[block] = average; + } + + subtractLocalAverage(&data[0]); + + return data; +} \ No newline at end of file