Mercurial > hg > multitrack-audio-matcher
diff bayesianArraySrc/BayesianArrayStructure.cpp @ 0:c4f9e49226eb
Initialising repository. Live osc input registered. Files analysed offline.
author | Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk> |
---|---|
date | Tue, 31 Jan 2012 13:54:17 +0000 |
parents | |
children | 5e188c0035b6 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bayesianArraySrc/BayesianArrayStructure.cpp Tue Jan 31 13:54:17 2012 +0000 @@ -0,0 +1,585 @@ +/* + * BayesianArrayStructure.cpp + * midiCannamReader + * + * Created by Andrew on 17/07/2011. + * Copyright 2011 QMUL. All rights reserved. + * + */ + +//look at reset speed to one - what does this do? - get rid of? + + +#include "BayesianArrayStructure.h" + +BayesianArrayStructure::BayesianArrayStructure(){ + printf("Bayesian structure: DeFault constructor called"); + + usingIntegratedTempoEstimate = true;// use max index + + relativeSpeedLikelihoodStdDev = 5.0; + + prior.createVector(1); + likelihood.createVector(1); + posterior.createVector(1); + + speedPriorValue = 1.0;//default value for the speed prior + speedEstimate = speedPriorValue; + + lastEventTime = 0;//ofGetElapsedTimeMillis(); + + tmpBestEstimate = 0; + crossUpdateTimeThreshold = 60; + priorWidth = 50; + +} + +BayesianArrayStructure::BayesianArrayStructure(int length){ + printf("BAYESIAN STURCTURE CREATED LENGTH: %i\n", length); + //this constructor isnt called it seems + prior.createVector(length); + likelihood.createVector(length); + posterior.createVector(length); + + lastEventTime = 0; + + +} + + + +void BayesianArrayStructure::resetSize(int length){ + printf("BAYESIAN STRUCTURE size is : %i\n", length); + + prior.createVector(length); + likelihood.createVector(length); + posterior.createVector(length); + + acceleration.createVector(length); + +} + +void BayesianArrayStructure::resetSpeedSize(int length){ + printf("BAYESIAN reset SPEED size is : %i\n", length); + + relativeSpeedPrior.createVector(length); + relativeSpeedLikelihood.createVector(length); + relativeSpeedPosterior.createVector(length); + tmpPosteriorForStorage.createVector(length); + + + +} + +void BayesianArrayStructure::setRelativeSpeedScalar(double f){ + relativeSpeedPrior.scalar = f; + relativeSpeedPosterior.scalar = f; + relativeSpeedLikelihood.scalar = f; +} + +void BayesianArrayStructure::resetSpeedToOne(){ + relativeSpeedPrior.zero(); + relativeSpeedPosterior.zero(); + relativeSpeedLikelihood.zero(); + + + relativeSpeedPosterior.addGaussianShape(100, 20, 0.8); + relativeSpeedPosterior.renormalise(); + relativeSpeedPosterior.getMaximum(); + + setSpeedPrior(speedPriorValue); + speedEstimate = speedPriorValue; + + prior.zero(); + posterior.zero(); + + posterior.addToIndex(0, 1); + posterior.renormalise(); + +} + +void BayesianArrayStructure::setSpeedPrior(double f){ + speedPriorValue = f; + int index = relativeSpeedPosterior.getRealTermsAsIndex(speedPriorValue); + relativeSpeedPosterior.zero(); + relativeSpeedPosterior.addGaussianShape(index, priorWidth, 0.8); + relativeSpeedPosterior.renormalise(); + relativeSpeedPosterior.getMaximum(); + relativeSpeedPrior.copyFromDynamicVector(relativeSpeedPosterior); + printf("BAYES STRUCTU ' SPEED PRIOR %f . index %i\n", speedPriorValue, index); + +} + + +void BayesianArrayStructure::setPositionDistributionScalar(double f){ + if (f > 0){ + prior.scalar = f; + posterior.scalar = f; + likelihood.scalar = f; + } +} + +void BayesianArrayStructure::simpleExample(){ + relativeSpeedPosterior.getMaximum(); + relativeSpeedPrior.copyFromDynamicVector(relativeSpeedPosterior); +} + +void BayesianArrayStructure::copyPriorToPosterior(){ + + for (int i = 0;i < prior.arraySize;i++){ + posterior.array[i] = prior.array[i]; + } +} + +void BayesianArrayStructure::setStartPlaying(){ + + lastEventTime = 0; + bestEstimate = 0; + lastBestEstimateUpdateTime = 0; + if (*realTimeMode) + lastBestEstimateUpdateTime = ofGetElapsedTimeMillis(); + //cannot just be zero - offline bug + //printf("start playing - best estimate %f\n", lastBestEstimateUpdateTime); + + resetArrays(); +} + +void BayesianArrayStructure::resetArrays(){ + //called when we start playing + + prior.zero(); + likelihood.zero(); + posterior.zero(); + + updateCounter = 0; + + posterior.offset = -1000; + setNewDistributionOffsets(0); + + int zeroIndex = posterior.getRealTermsAsIndex(0); + + posterior.addGaussianShape(zeroIndex, 500, 1); + // posterior.addToIndex(0, 1); + likelihood.addConstant(1); + + updateCounter = 0; + + + printf("bayes reset arrays - best estimate %f\n", lastBestEstimateUpdateTime); + + setSpeedPrior(speedPriorValue); +} + + +void BayesianArrayStructure::zeroArrays(){ + prior.zero(); + likelihood.zero(); + posterior.zero(); + + relativeSpeedPrior.zero(); + relativeSpeedPosterior.zero(); + relativeSpeedLikelihood.zero(); + +} + + +void BayesianArrayStructure::updateTmpBestEstimate(const double& timeDifference){ + //input is the time since the start of playing +// double timeDiff = ofGetElapsedTimeMillis() - lastEventTime;//lastBestEstimateUpdateTime; + double timeDiff = timeDifference; + if (*realTimeMode) + timeDiff = ofGetElapsedTimeMillis() - lastBestEstimateUpdateTime; + + double tmp = relativeSpeedPosterior.getIntegratedEstimate(); + tmpBestEstimate = posterior.getIndexInRealTerms(posterior.MAPestimate) + timeDiff*relativeSpeedPosterior.getIndexInRealTerms(relativeSpeedPosterior.integratedEstimate); + // + //printf("tmp best %f and best %f time diff %f posterior MAP %f at speed %f\n", 0Estimate, bestEstimate, timeDifference, posterior.getIndexInRealTerms(posterior.MAPestimate), relativeSpeedPosterior.getIndexInRealTerms(relativeSpeedPosterior.integratedEstimate)); + //lastBestEstimateUpdateTime = ofGetElapsedTimeMillis(); +} + +void BayesianArrayStructure::updateBestEstimate(const double& timeDifference){ +// double timeDiff = ofGetElapsedTimeMillis() - lastEventTime;// + + double timeDiff = timeDifference; + + //Using timedifferencfe here will make it go wrong. Is time since beginning of playing + + if (*realTimeMode) + timeDiff = ofGetElapsedTimeMillis() - lastBestEstimateUpdateTime; + + //lastbest is time we started playing + + if (usingIntegratedTempoEstimate) + speedEstimateIndex = relativeSpeedPosterior.getIntegratedEstimate(); + else + speedEstimateIndex = relativeSpeedPosterior.MAPestimate; + + speedEstimate = relativeSpeedPosterior.getIndexInRealTerms(speedEstimateIndex); + bestEstimate = posterior.getIndexInRealTerms(posterior.MAPestimate) + timeDiff*speedEstimate; + +} + +void BayesianArrayStructure::calculatePosterior(){ + //posterior.doProduct(prior, likelihood); + + int i; + for (i = 0;i < posterior.length;i++){ + posterior.array[i] = likelihood.array[i] * prior.array[i]; + } + + posterior.renormalise(); + +} + + + + +void BayesianArrayStructure::setNewDistributionOffsets(const double& newOffset){ + prior.offset = newOffset; + likelihood.offset = newOffset; + //posterior.offset = newOffset; +} + + +void BayesianArrayStructure::crossUpdateArrays(DynamicVector& position, DynamicVector& speed, double timeDifference){ + //set the cutoff for offset of position first! XXX + +// printf("time difference %f, ", timeDifference); + + double timeDifferenceInPositionVectorUnits = timeDifference / prior.scalar; + + + prior.zero();//kill prior + calculateNewPriorOffset(timeDifference);//set new prior offset here + + if (timeDifferenceInPositionVectorUnits > crossUpdateTimeThreshold) + complexCrossUpdate(timeDifferenceInPositionVectorUnits); + else + translateByMaximumSpeed(timeDifferenceInPositionVectorUnits); + + + updateCounter++; + prior.renormalise(); + +} + +void BayesianArrayStructure::complexCrossUpdate(const double& timeDifferenceInPositionVectorUnits){ + int distanceMoved, newPriorIndex; + + double speedValue = relativeSpeedPosterior.offset; + + for (int i = 0;i < relativeSpeedPosterior.arraySize;i++){ + + // double speedValue = relativeSpeedPosterior.getIndexInRealTerms(i);//so for scalar 0.01, 50 -> speed value of 0.5 + + //so we have moved + distanceMoved = round(timeDifferenceInPositionVectorUnits * speedValue);//round the value + + if (relativeSpeedPosterior.array[i] != 0){ + double speedContribution = relativeSpeedPosterior.array[i]; + // printf("speed [%i] gives %f moved %i in %f units \n", i, speedValue, distanceMoved, timeDifferenceInPositionVectorUnits); + + newPriorIndex = posterior.offset - prior.offset + distanceMoved; + + for (int postIndex = 0;postIndex < posterior.arraySize;postIndex++){ + //old posterior contributing to new prior + // newPriorIndex = postIndex + posterior.offset - prior.offset + distanceMoved; + + if (newPriorIndex >= 0 && newPriorIndex < prior.arraySize){ + prior.addToIndex(newPriorIndex, posterior.array[postIndex]*speedContribution); + } + + newPriorIndex++;//optimised code - the commented line above explains how this works + }//end for + + + }//if not zero + speedValue += relativeSpeedPosterior.scalar; + //optimised line + //as we wanted: + // double speedValue = relativeSpeedPosterior.getIndexInRealTerms(i);//so for scalar 0.01, 50 -> speed value of 0.5 + }//end speed +} + + + +void BayesianArrayStructure::translateByMaximumSpeed(const double& timeDifferenceInPositionVectorUnits){ + + int distanceMoved, newPriorIndex; + + double speedValue = relativeSpeedPosterior.getIndexInRealTerms(relativeSpeedPosterior.integratedEstimate); + //so for scalar 0.01, 50 -> speed value of 0.5 + double speedContribution = relativeSpeedPosterior.array[relativeSpeedPosterior.integratedEstimate]; + //so we have moved + distanceMoved = round(timeDifferenceInPositionVectorUnits * speedValue);//round the value + // printf("speed [%i] gives %f moved %i in %f units \n", i, speedValue, distanceMoved, timeDifferenceInPositionVectorUnits); + + for (int postIndex = 0;postIndex < posterior.arraySize;postIndex++){ + //old posterior contributing to new prior + newPriorIndex = postIndex + posterior.offset - prior.offset + distanceMoved; + if (newPriorIndex >= 0 && newPriorIndex < prior.arraySize){ + prior.addToIndex(newPriorIndex, posterior.array[postIndex]*speedContribution); + } + + } + +} + +void BayesianArrayStructure::addGaussianNoiseToSpeedPosterior(const double& std_dev){ + tmpPosteriorForStorage.copyFromDynamicVector(relativeSpeedPosterior); + + for (int i = 0;i < relativeSpeedPosterior.length;i++){ + tmpPosteriorForStorage.addGaussianShape(i, std_dev, relativeSpeedPosterior.array[i]); + } + + tmpPosteriorForStorage.renormalise(); + + relativeSpeedPosterior.copyFromDynamicVector(tmpPosteriorForStorage); +} + + +void BayesianArrayStructure::addTriangularNoiseToSpeedPosterior(const double& std_dev){ + tmpPosteriorForStorage.copyFromDynamicVector(relativeSpeedPosterior); + + for (int i = 0;i < relativeSpeedPosterior.length;i++){ + //adding a linear amount depending on distance + tmpPosteriorForStorage.addTriangularShape(i, std_dev*2.0, relativeSpeedPosterior.array[i]); + } + + tmpPosteriorForStorage.renormalise(); + + relativeSpeedPosterior.copyFromDynamicVector(tmpPosteriorForStorage); +} + +void BayesianArrayStructure::calculateNewPriorOffset(const double& timeDifference){ + + double maxSpeed = relativeSpeedPosterior.getIndexInRealTerms(relativeSpeedPosterior.integratedEstimate); + // printf("Maxspeed is %f\n", maxSpeed); + + double priorMax = posterior.getMaximum(); + double distanceTravelled = maxSpeed * (timeDifference / prior.scalar); + double newMaxLocation = posterior.MAPestimate + distanceTravelled; + // printf("MAP: %i, tim df %f, distance %f, new location %f\n", posterior.MAPestimate, timeDifference, distanceTravelled, newMaxLocation); + +} + + +void BayesianArrayStructure::decaySpeedDistribution(double timeDifference){ + + // commented for the moment + double relativeAmount = max(1.0, timeDifference/1000.); +// printf("decay %f around %i \n", timeDifference, relativeSpeedPosterior.MAPestimate); + relativeAmount *= speedDecayAmount; + relativeSpeedPosterior.renormalise(); + relativeSpeedPosterior.addGaussianShape(relativeSpeedPosterior.MAPestimate, speedDecayWidth, relativeAmount); + + relativeSpeedPosterior.renormalise(); + double newMax = relativeSpeedPosterior.getMaximum(); + + //old code +// relativeSpeedPosterior.addGaussianShape(relativeSpeedPosterior.MAPestimate, speedDecayWidth, 10); + //relativeSpeedPosterior.addConstant(1); + + /* + relativeSpeedPrior.copyFromDynamicVector(relativeSpeedPosterior); + relativeSpeedLikelihood.zero(); + relativeSpeedLikelihood.addConstant(0.2); + relativeSpeedLikelihood.addGaussianShape(relativeSpeedPosterior.maximumValue, speedDecayWidth, relativeAmount); + relativeSpeedPosterior.doProduct(relativeSpeedPrior, relativeSpeedLikelihood); + relativeSpeedPosterior.renormalise(); + */ + + + +} + +void BayesianArrayStructure::setLikelihoodToConstant(){ + //set new likelihood + relativeSpeedLikelihood.zero(); + relativeSpeedLikelihood.addConstant(speedLikelihoodNoise); +} + + +void BayesianArrayStructure::updateTempoLikelihood(const double& speedRatio, const double& matchFactor){ + + //speedratio is speed of played relative to the recording + + double index = relativeSpeedLikelihood.getRealTermsAsIndex(speedRatio); + // printf("index of likelihood would be %f for ratio %f\n", index, speedRatio); + if (index >= 0 && index < relativeSpeedPrior.length){ + relativeSpeedLikelihood.addGaussianShape(index , relativeSpeedLikelihoodStdDev, matchFactor); + } +} + + + +void BayesianArrayStructure::updateTempoDistribution(){ + + //copy posterior to prior + relativeSpeedPrior.copyFromDynamicVector(relativeSpeedPosterior); + + //update + relativeSpeedPosterior.doProduct(relativeSpeedPrior, relativeSpeedLikelihood); + + //normalise + relativeSpeedPosterior.renormalise(); + + relativeSpeedPosterior.getMaximum(); + + //relativeSpeedPosterior.updateIntegratedEstimate(); - could be swayed when off to side + //so now limited to where there is room sround the MAP estimate + relativeSpeedPosterior.updateLimitedIntegratedEstimate(); + + speedEstimate = relativeSpeedPosterior.getIndexInRealTerms(relativeSpeedPosterior.integratedEstimate); +} + + +void BayesianArrayStructure::calculateTempoUpdate(){ + //copy posterior to prior + relativeSpeedPrior.copyFromDynamicVector(relativeSpeedPosterior); + + //update + relativeSpeedPosterior.doProduct(relativeSpeedPrior, relativeSpeedLikelihood); + + //normalise + relativeSpeedPosterior.renormalise(); + + relativeSpeedPosterior.getMaximum(); + +} + + +void BayesianArrayStructure::drawArrays(){ + + //bayesArray.drawFloatArray(&bayesArray.prior[0], 0, 200); + //bayesArray.drawFloatArray(&bayesArray.prior[0], 0, 200); + + int displaySize = prior.arraySize; + ofSetColor(0,0,255); + prior.drawVector(0, displaySize); + ofSetColor(0,255,0); + likelihood.drawVector(0, displaySize); + ofSetColor(255,0,255); + posterior.drawVector(0, displaySize); + + + +} + + +void BayesianArrayStructure::drawTempoArrays(){ + ofSetColor(0,0,255); +// relativeSpeedPrior.drawVector(0, relativeSpeedPrior.arraySize); + + ofSetColor(0,150,255); + relativeSpeedLikelihood.drawVector(0, relativeSpeedLikelihood.arraySize); + +// relativeSpeedLikelihood.drawConstrainedVector(0, 199, 0, 1000);// relativeSpeedLikelihood.arraySize); + ofSetColor(255,0,0); + relativeSpeedPosterior.drawVector(0, relativeSpeedPosterior.arraySize); + +// ofSetColor(0,0,255); +// tmpPosteriorForStorage.drawVector(0, tmpPosteriorForStorage.arraySize); + + ofSetColor(255,255, 255); + ofLine(screenWidth/2, 0, screenWidth/2, ofGetHeight());//middle of screen + + ofSetColor(25, 0, 250); + double fractionOfScreen = ((double)relativeSpeedPosterior.integratedEstimate / relativeSpeedPosterior.length); + ofLine(screenWidth * fractionOfScreen, 0, screenWidth * fractionOfScreen, ofGetHeight()); + + ofSetColor(255, 0, 20); + fractionOfScreen = ((double)relativeSpeedPosterior.MAPestimate / relativeSpeedPosterior.length); + ofLine(screenWidth * fractionOfScreen, 0, screenWidth * fractionOfScreen, ofGetHeight()); + + +} + + +void BayesianArrayStructure::drawArraysRelativeToTimeframe(const double& startTimeMillis, const double& endTimeMillis){ + + screenWidth = ofGetWidth(); + + int startArrayIndex = 0; + + if (prior.getIndexInRealTerms(prior.arraySize-1) > startTimeMillis){ + //i.e. the array is on the page + + while (prior.getIndexInRealTerms(startArrayIndex) < startTimeMillis){ + startArrayIndex++; + } + int endArrayIndex = prior.arraySize-1; + //could find constraints here + if (prior.getIndexInRealTerms(prior.arraySize-1) > endTimeMillis) + endArrayIndex = (floor)((endTimeMillis - prior.offset)/prior.scalar); + + //so we need to figure where start and end array are on screen + int startScreenPosition, endScreenPosition; + double screenWidthMillis = endTimeMillis - startTimeMillis; + + startScreenPosition = (prior.getIndexInRealTerms(startArrayIndex) - startTimeMillis)*screenWidth/screenWidthMillis; + endScreenPosition = (double)(prior.getIndexInRealTerms(endArrayIndex) - startTimeMillis)*screenWidth/screenWidthMillis; + + ofSetColor(0,0,100); + string relativeString = " offset "+ofToString(prior.offset, 1);//starttimes("+ofToString(startTimeMillis)+", "+ofToString(endTimeMillis); + relativeString += ": index "+ofToString(startArrayIndex)+" , "+ofToString(endArrayIndex)+" ["; +// relativeString += ofToString(prior.getIndexInRealTerms(endArrayIndex), 3)+"] (sc-width:"+ofToString(screenWidthMillis, 1)+") "; + relativeString += " mapped to screen "+ofToString(startScreenPosition)+" , "+ofToString(endScreenPosition); +// ofDrawBitmapString(relativeString, 100, 180); + + + + ofSetColor(100,100,100);//255, 255, 0); + likelihood.drawConstrainedVector(startArrayIndex, endArrayIndex, startScreenPosition, endScreenPosition); + +// ofSetColor(0,0,200); + ofSetColor(170,170,170);//00,200); + prior.drawConstrainedVector(startArrayIndex, endArrayIndex, startScreenPosition, endScreenPosition); + + ofSetColor(0,0,150); +// ofSetColor(200, 0, 0); + posterior.drawConstrainedVector(startArrayIndex, endArrayIndex, startScreenPosition, endScreenPosition); + + +// ofSetColor(0, 200, 255); +// acceleration.drawConstrainedVector(startArrayIndex, endArrayIndex, startScreenPosition, endScreenPosition); + + + } + +} + + +/* + + void BayesianArrayStructure::updateTempoDistribution(const double& speedRatio, const double& matchFactor){ + //speedratio is speed of played relative to the recording + + double index = relativeSpeedLikelihood.getRealTermsAsIndex(speedRatio); + // printf("\nindex of likelihood would be %f\n", index); + if (index >= 0 && index < relativeSpeedPrior.length){ + //then we can do update + + //set new likelihood + relativeSpeedLikelihood.zero(); + relativeSpeedLikelihood.addConstant(speedLikelihoodNoise); + + relativeSpeedLikelihood.addGaussianShape(index , 5, 0.5*matchFactor); + + + //copy posterior to prior + relativeSpeedPrior.copyFromDynamicVector(relativeSpeedPosterior); + + //update + relativeSpeedPosterior.doProduct(relativeSpeedPrior, relativeSpeedLikelihood); + + //normalise + relativeSpeedPosterior.renormalise(); + + relativeSpeedPosterior.getMaximum(); + }//end if within range + + + } + + */ \ No newline at end of file