Mercurial > hg > midi-score-follower
view src/DynamicBayesianArray.cpp @ 1:1a32ce016bb9
Changed bestEstimate timing to work via time sent from Max not the elapsed time. This had caused some problems, but this version now working surprisingly well on MIDI files with variable timing.
author | Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk> |
---|---|
date | Thu, 18 Aug 2011 23:27:42 +0100 |
parents | b299a65a3ad0 |
children |
line wrap: on
line source
/* * DynamicDynamicBayesianArray.cpp * midiCannamReader * * Created by Andrew on 17/07/2011. * Copyright 2011 QMUL. All rights reserved. * */ #include "DynamicBayesianArray.h" #include "math.h" #include "ofMain.h" DynamicBayesianArray::DynamicBayesianArray(){ // prior.createVector(240); // likelihood.createVector(240); // posterior.createVector(240); testVector.createVector(240); testVector.addGaussianShape(100,10, 0.1); likelihoodNoise = 0.5; likelihoodMean = ARRAY_SIZE/2; likelihoodStdDev = ARRAY_SIZE / 12; initialiseArray(); } void DynamicBayesianArray::initialiseArray(){ //maximumIndex = 12;//change this setGaussianPrior(ARRAY_SIZE/2, ARRAY_SIZE/1); setGaussianLikelihood(ARRAY_SIZE/2, ARRAY_SIZE/1);//likelihoodMean, likelihoodStdDev); calculatePosterior(); renormalisePosterior(); posteriorDecayRate = 0.06; eighthNoteProportion = 0.35;//must be less than 0.5 to discriminate - was 0.4 earlySixteenthNoteProportion = 0; lateSixteenthNoteProportion = 0; decayNoiseAmount = 0.1; decayNoiseStdDev = ARRAY_SIZE/24; standardDeviation = likelihoodStdDev; setDecayNoiseGaussian(ARRAY_SIZE/2, decayNoiseStdDev); setGaussianLikelihood(likelihoodMean, likelihoodStdDev); } void DynamicBayesianArray::setGaussianPrior(float mean, float StdDev){ int i; for (i=0;i<ARRAY_SIZE;i++){ prior[i] = (1/(StdDev*sqrt(2*PI)))*exp(-1*(i-mean)*(i-mean)/(2*StdDev*StdDev)); //posterior[i] = prior[i]; } } void DynamicBayesianArray::setGaussianPosterior(float mean, float StdDev){ int i; for (i=0;i<ARRAY_SIZE;i++){ posterior[i] = (1/(StdDev*sqrt(2*PI)))*exp(-1*(i-mean)*(i-mean)/(2*StdDev*StdDev)); } } void DynamicBayesianArray::setGaussianLikelihood(float mean, float StdDev){ if (mean >= 0 && mean <= ARRAY_SIZE){ int i; float eighthDifference; int eighthPosition = ((int)mean + ARRAY_SIZE/2)%ARRAY_SIZE; float mainDifference; float gaussianProportion = 1 - likelihoodNoise; for (i=0;i < ARRAY_SIZE;i++){ mainDifference = min( double(fabs(i-mean)) , (double)(i + ARRAY_SIZE - mean)); //without * (1 - eighthNoteProportion) likelihood[i] = gaussianProportion * (1/(StdDev*sqrt(2*PI)))*exp(-1*(mainDifference)*(mainDifference)/(2*StdDev*StdDev)) ; likelihood[i] += (likelihoodNoise / ARRAY_SIZE); //likelihood[i] = (float) max(gaussianProportion * (1/(StdDev*sqrt(2*PI)))*exp(-1*(i-mean)*(i-mean)/(2*StdDev*StdDev)) , //(double) (likelihoodNoise / ARRAY_SIZE) ); } // renormaliseArray(&likelihood[0], ARRAY_SIZE); }//end if mean within limits } void DynamicBayesianArray::calculatePosterior(){ int i; for (i=0;i < ARRAY_SIZE;i++){ posterior[i] = likelihood[i] * prior[i]; } //renormalisePosterior(); } float DynamicBayesianArray::getMaximum(float *ptr, int length){ int i; float max = 0; for (i=0;i < length;i++){ if (*(ptr+i)>max) max = *(ptr+i); } maximumValue = max; return max; } float* DynamicBayesianArray::getMaximumEstimate(float *ptr, int length){ float returnArray[2]; int i; float max = 0; maximumIndex = 0; for (i=0;i < length;i++){ if (*(ptr+i)>max){ max = *(ptr+i); maximumIndex = i; } } returnArray[0] = max; returnArray[1] = maximumIndex; maximumValue = max; return &returnArray[0]; } double DynamicBayesianArray::getIntegratedEstimateIndex(){ int i; float integratedQuantity = 0; float integratedTotal = 0; double integratedIndex = 0; for (i=0;i < ARRAY_SIZE;i++){ integratedQuantity += posterior[i];//the values of the probability distribution integratedTotal += i*posterior[i]; } if (integratedQuantity > 0){ integratedIndex = integratedTotal / integratedQuantity; } integratedEstimate = (float) integratedIndex; return integratedIndex; } double DynamicBayesianArray::calculateStandardDeviation(){ double total = 0; double pdfSum; double variance = 0; for (int i=0;i < ARRAY_SIZE;i++){ //*posterior[i] * total += posterior[i] * (i - integratedEstimate) * (i - integratedEstimate);//the values of the probability distribution pdfSum += posterior[i]; } if (pdfSum > 0) variance = total / pdfSum; else variance = ARRAY_SIZE; standardDeviation = sqrt(variance); return standardDeviation; } void DynamicBayesianArray::renormaliseArray(float *ptr, int length){ int i; float totalArea = 0; for (i=0;i < length;i++){ totalArea += *(ptr+i); } for (i=0;i < length;i++){ *(ptr+i) /= totalArea; } } void DynamicBayesianArray::resetPrior(){ int i; for (i=0;i<ARRAY_SIZE;i++){ prior[i] = posterior[i]; } } void DynamicBayesianArray::renormalisePosterior(){ int i; float totalArea = 0; for (i=0;i < ARRAY_SIZE;i++){ totalArea += posterior[i]; } for (i=0;i < ARRAY_SIZE;i++){ posterior[i] /= totalArea; } } void DynamicBayesianArray::decayPosterior(){ float *pointer; pointer = getMaximumEstimate(&posterior[0], ARRAY_SIZE); float maximum; maximum = *pointer; int i; for (i=0;i<ARRAY_SIZE;i++){ posterior[i] += (maximum - posterior[i]) * posteriorDecayRate * 0.01;;//usded to be * maximum not minus value } maximumIndex = *(pointer+1); } void DynamicBayesianArray::setDecayNoiseGaussian(float mean, float StdDev){ int i; for (i=0;i<ARRAY_SIZE;i++){ decayNoiseArray[i] = (1/(StdDev*sqrt(2*PI)))*exp(-1*(i-mean)*(i-mean)/(2*StdDev*StdDev)); } } void DynamicBayesianArray::decayPosteriorWithGaussianNoise(){ int i; float currentMaximum = getMaximum(&posterior[0], ARRAY_SIZE); for (i=0;i<ARRAY_SIZE;i++){ posterior[i] += decayNoiseArray[(i - (int)maximumIndex + ((3*ARRAY_SIZE)/2)) % ARRAY_SIZE] * currentMaximum * decayNoiseAmount; //posteriorDecayRate * 0.01;;//usded to be * maximum not minus value } } void DynamicBayesianArray::resetMaximumPosterior(){ int i; float max = 0; for (i=0;i < ARRAY_SIZE;i++){ if (posterior[i]>max){ maximumIndex = i; max = posterior[i]; } } } void DynamicBayesianArray::translateDistribution(int translationIndex){ int tmpIndex; //copy array int i; for (i=0;i < ARRAY_SIZE;i++){ tempPosteriorArray[i] = posterior[i] ; } //translate values for (i=0;i < ARRAY_SIZE;i++){ tmpIndex = (i + translationIndex + ARRAY_SIZE)%ARRAY_SIZE; posterior[tmpIndex] = tempPosteriorArray[i]; } //now delete tmp array } void DynamicBayesianArray::drawFloatArray(float* arrayToDraw, const int& minIndex, const int& maxIndex){ if (minIndex >= 0){ double stepSize = ofGetWidth() / (double)(maxIndex - minIndex); double screenHeight = ofGetHeight(); double maxVal = getMaximum(&arrayToDraw[0], maxIndex); for (int i = minIndex+1;i < maxIndex;i++){ ofLine (stepSize*(i-1), screenHeight * (1 - arrayToDraw[i-1] / maxVal), stepSize*i, screenHeight * (1 - arrayToDraw[i] / maxVal) ); } } } /* void DynamicBayesianArray::drawDoubleArray(double[]& arrayToDraw, const int& minIndex, const int& maxIndex){ if (minIndex >= 0 && maxIndex <= arrayToDraw.size(0)) } */ /* void DynamicBayesianArray::setGaussianLikelihoodForBeats(float mean, float StdDev){ //this has eighth and sixteenth positions included if (mean >= 0 && mean <= ARRAY_SIZE){ int i; float eighthDifference; int eighthPosition = ((int)mean + ARRAY_SIZE/2)%ARRAY_SIZE; int earlySixteenthPosition = ((int)mean + (3*ARRAY_SIZE/4))%ARRAY_SIZE;; int lateSixteenthPosition = ((int)mean + (ARRAY_SIZE/4))%ARRAY_SIZE;; float mainDifference, sixteenthDifference; float gaussianProportion = 1 - likelihoodNoise; float mainProportion = (1 - eighthNoteProportion - earlySixteenthNoteProportion - lateSixteenthNoteProportion); for (i=0;i < ARRAY_SIZE;i++){ mainDifference = min( fabs(i-mean) , (double)(i + ARRAY_SIZE - mean)); likelihood[i] = gaussianProportion * mainProportion * (1/(StdDev*sqrt(2*PI)))*exp(-1*(mainDifference)*(mainDifference)/(2*StdDev*StdDev)) ; eighthDifference = min( abs(i - eighthPosition) , i + ARRAY_SIZE - eighthPosition); eighthDifference = min(eighthDifference , (float)(ARRAY_SIZE + eighthPosition - i )); //for e.g. +0.43, or -0.47 we require the gaussian around the half note too likelihood[i] += gaussianProportion * eighthNoteProportion * (1/(StdDev*sqrt(2*PI)))*exp(-1*(eighthDifference)*(eighthDifference)/(2*StdDev*StdDev)) ; sixteenthDifference = min( abs(i - earlySixteenthPosition) , i + ARRAY_SIZE - earlySixteenthPosition); sixteenthDifference = min(sixteenthDifference , (float)(ARRAY_SIZE + earlySixteenthPosition - i )); //for e.g. +0.43, or -0.47 we require the gaussian around the half note too likelihood[i] += gaussianProportion * earlySixteenthNoteProportion * (1/(StdDev*sqrt(2*PI)))*exp(-1*(sixteenthDifference)*(sixteenthDifference)/(2*StdDev*StdDev)) ; sixteenthDifference = min( abs(i - lateSixteenthPosition) , i + ARRAY_SIZE - lateSixteenthPosition); sixteenthDifference = min(sixteenthDifference , (float)(ARRAY_SIZE + lateSixteenthPosition - i )); //for e.g. +0.43, or -0.47 we require the gaussian around the half note too likelihood[i] += gaussianProportion * lateSixteenthNoteProportion * (1/(StdDev*sqrt(2*PI)))*exp(-1*(sixteenthDifference)*(sixteenthDifference)/(2*StdDev*StdDev)) ; likelihood[i] += (likelihoodNoise / ARRAY_SIZE); //likelihood[i] = (float) max(gaussianProportion * (1/(StdDev*sqrt(2*PI)))*exp(-1*(i-mean)*(i-mean)/(2*StdDev*StdDev)) , //(double) (likelihoodNoise / ARRAY_SIZE) ); } // renormaliseArray(&likelihood[0], ARRAY_SIZE); }//end if mean within limits } */