andrew@0: /* andrew@0: * BayesianArrayStructure.cpp andrew@0: * midiCannamReader andrew@0: * andrew@0: * Created by Andrew on 17/07/2011. andrew@0: * Copyright 2011 QMUL. All rights reserved. andrew@0: * andrew@0: */ andrew@0: andrew@0: #include "BayesianArrayStructure.h" andrew@0: andrew@0: BayesianArrayStructure::BayesianArrayStructure(){ andrew@0: printf("Bayesian structure: DeFault constructor called"); andrew@0: andrew@0: prior.createVector(1); andrew@0: likelihood.createVector(1); andrew@0: posterior.createVector(1); andrew@0: andrew@0: andrew@0: tmpPrior.createVector(240); andrew@0: tmpPrior.addGaussianShape(100, 40, 1); andrew@0: tmpPrior.addGaussianShape(200, 10, 0.2); andrew@0: tmpPrior.translateDistribution(20); andrew@0: andrew@0: lastEventTime = ofGetElapsedTimeMillis(); andrew@0: andrew@0: speedDecayWidth = 20; andrew@0: speedDecayAmount = 10; andrew@0: } andrew@0: andrew@0: BayesianArrayStructure::BayesianArrayStructure(int length){ andrew@0: printf("BAYESIAN STURTUCRE CREATED LENGTH: %i\n", length); andrew@0: //this constructor isnt called it seems andrew@0: prior.createVector(length); andrew@0: likelihood.createVector(length); andrew@0: posterior.createVector(length); andrew@0: andrew@0: } andrew@0: andrew@0: andrew@0: andrew@0: void BayesianArrayStructure::resetSize(int length){ andrew@0: printf("BAYESIAN STRUCTURE size is : %i\n", length); andrew@0: andrew@0: prior.createVector(length); andrew@0: likelihood.createVector(length); andrew@0: posterior.createVector(length); andrew@0: andrew@0: acceleration.createVector(length); andrew@0: andrew@0: } andrew@0: andrew@0: andrew@0: andrew@0: void BayesianArrayStructure::resetSpeedToOne(){ andrew@0: relativeSpeedPrior.zero(); andrew@0: relativeSpeedPosterior.zero(); andrew@0: relativeSpeedLikelihood.zero(); andrew@0: andrew@0: relativeSpeedPosterior.addGaussianShape(40, 5, 0.6); andrew@0: andrew@0: relativeSpeedPosterior.addGaussianShape(100, 5, 0.8); andrew@0: relativeSpeedPosterior.renormalise(); andrew@0: relativeSpeedPosterior.getMaximum(); andrew@0: andrew@0: acceleration.addGaussianShape(2000, 20, 0.8); andrew@0: andrew@0: } andrew@0: andrew@0: void BayesianArrayStructure::resetSpeedSize(int length){ andrew@0: printf("BAYESIAN SPEED size is : %i\n", length); andrew@0: andrew@0: relativeSpeedPrior.createVector(length); andrew@0: relativeSpeedLikelihood.createVector(length); andrew@0: relativeSpeedPosterior.createVector(length); andrew@0: andrew@0: andrew@0: andrew@0: } andrew@0: void BayesianArrayStructure::setRelativeSpeedScalar(double f){ andrew@0: relativeSpeedPrior.scalar = f; andrew@0: relativeSpeedPosterior.scalar = f; andrew@0: relativeSpeedLikelihood.scalar = f; andrew@0: } andrew@0: andrew@0: void BayesianArrayStructure::simpleExample(){ andrew@0: //simple example andrew@0: prior.addGaussianShape(50, 10, 1); andrew@0: prior.addGaussianShape(150, 30, 0.3); andrew@0: prior.addGaussianShape(250, 30, 0.2); andrew@0: andrew@0: likelihood.addGaussianShape(90, 20, 0.6); andrew@0: likelihood.addConstant(0.02); andrew@0: posterior.doProduct(prior, likelihood); andrew@0: andrew@0: // relativeSpeedPosterior.addToIndex(100, 1); andrew@0: // relativeSpeedPosterior.addToIndex(40, 0.7); andrew@0: relativeSpeedPosterior.addGaussianShape(100, 20, 1); andrew@0: // relativeSpeedPosterior.addGaussianShape(10, 2, 0.5); andrew@0: relativeSpeedPosterior.getMaximum(); andrew@0: andrew@0: } andrew@0: andrew@0: void BayesianArrayStructure::copyPriorToPosterior(){ andrew@0: andrew@0: for (int i = 0;i < prior.arraySize;i++){ andrew@0: posterior.array[i] = prior.array[i]; andrew@0: } andrew@0: } andrew@0: andrew@0: void BayesianArrayStructure::resetArrays(){ andrew@0: prior.zero(); andrew@0: likelihood.zero(); andrew@0: prior.addGaussianShape(0, 80, 1); andrew@0: likelihood.addConstant(1); andrew@0: posterior.zero(); andrew@0: posterior.addGaussianShape(0, 60, 1); andrew@0: setNewDistributionOffsets(0); andrew@0: bestEstimate = 0; andrew@0: // lastBestEstimateUpdateTime = ofGetElapsedTimeMillis(); andrew@0: andrew@0: } andrew@0: andrew@0: void BayesianArrayStructure::updateBestEstimate(){ andrew@0: double timeDiff = ofGetElapsedTimeMillis() - lastEventTime;//lastBestEstimateUpdateTime; andrew@0: andrew@0: bestEstimate = posterior.getIndexInRealTerms(posterior.MAPestimate) + timeDiff*relativeSpeedPosterior.getIndexInRealTerms(relativeSpeedPosterior.MAPestimate); andrew@0: // andrew@0: //lastBestEstimateUpdateTime = ofGetElapsedTimeMillis(); andrew@0: } andrew@0: andrew@0: void BayesianArrayStructure::calculatePosterior(){ andrew@0: posterior.doProduct(prior, likelihood); andrew@0: posterior.renormalise(); andrew@0: andrew@0: /* andrew@0: int i; andrew@0: for (i = 0;i < prior.length;i++){ andrew@0: // printf("priori [%i] is %f\n", i, prior[i]); andrew@0: *(posterior+i) = *(prior+i); andrew@0: // posterior[i] = likelihood[i] * prior[i]; andrew@0: } andrew@0: */ andrew@0: andrew@0: andrew@0: } andrew@0: andrew@0: andrew@0: andrew@0: andrew@0: void BayesianArrayStructure::setNewDistributionOffsets(const double& newOffset){ andrew@0: prior.offset = newOffset; andrew@0: likelihood.offset = newOffset; andrew@0: // posterior.offset = newOffset; andrew@0: } andrew@0: andrew@0: andrew@0: void BayesianArrayStructure::crossUpdateArrays(DynamicVector& position, DynamicVector& speed, double timeDifference){ andrew@0: //set the cutoff for offset of position first! XXX andrew@0: andrew@0: // printf("time difference %f, ", timeDifference); andrew@0: andrew@0: double timeDifferenceInPositionVectorUnits = timeDifference / prior.scalar; andrew@0: andrew@0: prior.zero();//kill prior andrew@0: calculateNewPriorOffset(timeDifference);//set new prior offset here andrew@0: andrew@0: for (int i = 0;i < speed.arraySize;i++){ andrew@0: // printf("[%i] %f\n", i, speed.array[i]); andrew@0: //set speed andrew@0: double speedValue = speed.getIndexInRealTerms(i);//so for scalar 0.01, 50 -> speed value of 0.5 andrew@0: andrew@0: //so we have moved andrew@0: int distanceMoved = round(timeDifferenceInPositionVectorUnits * speedValue);//round the value andrew@0: andrew@0: if (speed.array[i] != 0){ andrew@0: andrew@0: // printf("speed [%i] gives %f moved %i\n", i, speedValue, distanceMoved); andrew@0: andrew@0: for (int postIndex = 0;postIndex < position.arraySize;postIndex++){ andrew@0: //old posterior contributing to new prior andrew@0: int newPriorIndex = postIndex + position.offset - prior.offset + distanceMoved; andrew@0: if (newPriorIndex >= 0 && newPriorIndex < prior.arraySize){ andrew@0: prior.addToIndex(newPriorIndex, position.array[postIndex]*speed.array[i]); andrew@0: // printf("adding [%i] : %f\n", newPriorIndex, posterior.array[postIndex]*speed.array[i]); andrew@0: } andrew@0: andrew@0: } andrew@0: andrew@0: }//if not zero andrew@0: }//end speed andrew@0: andrew@0: prior.renormalise(); andrew@0: andrew@0: } andrew@0: andrew@0: void BayesianArrayStructure::calculateNewPriorOffset(const double& timeDifference){ andrew@0: andrew@0: double maxSpeed = relativeSpeedPosterior.getIndexInRealTerms(relativeSpeedPosterior.MAPestimate); andrew@0: // printf("Maxspeed is %f\n", maxSpeed); andrew@0: andrew@0: double priorMax = posterior.getMaximum(); andrew@0: double distanceTravelled = maxSpeed * (timeDifference / prior.scalar); andrew@0: double newMaxLocation = posterior.MAPestimate + distanceTravelled; andrew@0: // printf("MAP: %i, tim df %f, distance %f, new location %f\n", posterior.MAPestimate, timeDifference, distanceTravelled, newMaxLocation); andrew@0: andrew@0: } andrew@0: andrew@0: andrew@0: void BayesianArrayStructure::decaySpeedDistribution(double timeDifference){ andrew@0: andrew@0: // commented for the moment andrew@0: double relativeAmount = max(1.0, timeDifference/1000.); andrew@0: // printf("decay %f around %i \n", timeDifference, relativeSpeedPosterior.MAPestimate); andrew@0: relativeAmount *= speedDecayAmount; andrew@0: relativeSpeedPosterior.renormalise(); andrew@0: relativeSpeedPosterior.addGaussianShape(relativeSpeedPosterior.MAPestimate, speedDecayWidth, relativeAmount); andrew@0: andrew@0: relativeSpeedPosterior.renormalise(); andrew@0: double newMax = relativeSpeedPosterior.getMaximum(); andrew@0: andrew@0: //old code andrew@0: // relativeSpeedPosterior.addGaussianShape(relativeSpeedPosterior.MAPestimate, speedDecayWidth, 10); andrew@0: //relativeSpeedPosterior.addConstant(1); andrew@0: andrew@0: /* andrew@0: relativeSpeedPrior.copyFromDynamicVector(relativeSpeedPosterior); andrew@0: relativeSpeedLikelihood.zero(); andrew@0: relativeSpeedLikelihood.addConstant(0.2); andrew@0: relativeSpeedLikelihood.addGaussianShape(relativeSpeedPosterior.maximumValue, speedDecayWidth, relativeAmount); andrew@0: relativeSpeedPosterior.doProduct(relativeSpeedPrior, relativeSpeedLikelihood); andrew@0: relativeSpeedPosterior.renormalise(); andrew@0: */ andrew@0: andrew@0: andrew@0: andrew@0: } andrew@0: andrew@0: void BayesianArrayStructure::updateTempoDistribution(const double& speedRatio, const double& matchFactor){ andrew@0: //speedratio is speed of played relative to the recording andrew@0: andrew@0: double index = relativeSpeedLikelihood.getRealTermsAsIndex(speedRatio); andrew@0: // printf("\nindex of likelihood would be %f\n", index); andrew@0: if (index >= 0 && index < relativeSpeedPrior.length){ andrew@0: //then we can do update andrew@0: andrew@0: //set new likelihood andrew@0: relativeSpeedLikelihood.zero(); andrew@1: relativeSpeedLikelihood.addConstant(0.05); andrew@0: andrew@0: relativeSpeedLikelihood.addGaussianShape(index , 5, 0.5*matchFactor); andrew@0: andrew@0: andrew@0: //copy posterior to prior andrew@0: relativeSpeedPrior.copyFromDynamicVector(relativeSpeedPosterior); andrew@0: andrew@0: //update andrew@0: relativeSpeedPosterior.doProduct(relativeSpeedPrior, relativeSpeedLikelihood); andrew@0: andrew@0: //normalise andrew@0: relativeSpeedPosterior.renormalise(); andrew@0: andrew@0: relativeSpeedPosterior.getMaximum(); andrew@0: }//end if within range andrew@0: andrew@0: andrew@0: } andrew@0: andrew@0: andrew@0: void BayesianArrayStructure::setFlatTempoLikelihood(){ //set new likelihood andrew@0: relativeSpeedLikelihood.zero(); andrew@0: relativeSpeedLikelihood.addConstant(0.3); andrew@0: } andrew@0: andrew@0: void BayesianArrayStructure::updateTempoLikelihood(const double& speedRatio, const double& matchFactor){ andrew@0: andrew@0: double index = relativeSpeedLikelihood.getRealTermsAsIndex(speedRatio); andrew@0: andrew@0: if (index >= 0 && index < relativeSpeedPrior.length){ andrew@0: relativeSpeedLikelihood.addGaussianShape(index , 5, 0.5);//*matchFactor); andrew@0: } andrew@0: } andrew@0: andrew@0: andrew@0: void BayesianArrayStructure::calculateTempoUpdate(){ andrew@0: //copy posterior to prior andrew@0: relativeSpeedPrior.copyFromDynamicVector(relativeSpeedPosterior); andrew@0: andrew@0: //update andrew@0: relativeSpeedPosterior.doProduct(relativeSpeedPrior, relativeSpeedLikelihood); andrew@0: andrew@0: //normalise andrew@0: relativeSpeedPosterior.renormalise(); andrew@0: andrew@0: relativeSpeedPosterior.getMaximum(); andrew@0: andrew@0: } andrew@0: andrew@0: andrew@0: void BayesianArrayStructure::drawArrays(){ andrew@0: andrew@0: //bayesArray.drawFloatArray(&bayesArray.prior[0], 0, 200); andrew@0: //bayesArray.drawFloatArray(&bayesArray.prior[0], 0, 200); andrew@0: andrew@0: int displaySize = prior.arraySize; andrew@0: ofSetColor(255,0,0); andrew@0: prior.drawVector(0, displaySize); andrew@0: ofSetColor(0,255,0); andrew@0: likelihood.drawVector(0, displaySize); andrew@0: ofSetColor(0,0,255); andrew@0: posterior.drawVector(0, displaySize); andrew@0: ofSetColor(255,255,0); andrew@0: relativeSpeedPosterior.drawVector(0, relativeSpeedPosterior.arraySize); andrew@0: andrew@0: // ofSetColor(255,255,255); andrew@0: // tmpPrior.drawVector(0,300); andrew@0: andrew@0: } andrew@0: andrew@0: andrew@0: void BayesianArrayStructure::drawTempoArrays(){ andrew@0: ofSetColor(0,255,255); andrew@0: relativeSpeedPrior.drawVector(0, relativeSpeedPrior.arraySize); andrew@0: andrew@0: ofSetColor(255,0,255); andrew@0: relativeSpeedLikelihood.drawVector(0, relativeSpeedLikelihood.arraySize); andrew@0: andrew@0: ofSetColor(255,255,0); andrew@0: relativeSpeedPosterior.drawVector(0, relativeSpeedPosterior.arraySize); andrew@0: andrew@0: ofSetColor(255,255, 255); andrew@0: ofLine(screenWidth/2, 0, screenWidth/2, ofGetHeight());//middle of screen andrew@0: andrew@0: ofSetColor(0, 255, 0); andrew@0: double fractionOfScreen = ((double)relativeSpeedPosterior.MAPestimate / relativeSpeedPosterior.length); andrew@0: ofLine(screenWidth * fractionOfScreen, 0, screenWidth * fractionOfScreen, ofGetHeight()); andrew@0: } andrew@0: andrew@0: andrew@0: void BayesianArrayStructure::drawArraysRelativeToTimeframe(const double& startTimeMillis, const double& endTimeMillis){ andrew@0: andrew@0: screenWidth = ofGetWidth(); andrew@0: andrew@0: int startArrayIndex = 0; andrew@0: andrew@0: if (prior.getIndexInRealTerms(prior.arraySize-1) > startTimeMillis){ andrew@0: //i.e. the array is on the page andrew@0: andrew@0: while (prior.getIndexInRealTerms(startArrayIndex) < startTimeMillis){ andrew@0: startArrayIndex++; andrew@0: } andrew@0: int endArrayIndex = prior.arraySize-1; andrew@0: //could find constraints here andrew@0: if (prior.getIndexInRealTerms(prior.arraySize-1) > endTimeMillis) andrew@0: endArrayIndex = (floor)((endTimeMillis - prior.offset)/prior.scalar); andrew@0: andrew@0: //so we need to figure where start and end array are on screen andrew@0: int startScreenPosition, endScreenPosition; andrew@0: double screenWidthMillis = endTimeMillis - startTimeMillis; andrew@0: andrew@0: startScreenPosition = (prior.getIndexInRealTerms(startArrayIndex) - startTimeMillis)*screenWidth/screenWidthMillis; andrew@0: endScreenPosition = (double)(prior.getIndexInRealTerms(endArrayIndex) - startTimeMillis)*screenWidth/screenWidthMillis; andrew@0: andrew@0: ofSetColor(0,0,100); andrew@0: string relativeString = " offset "+ofToString(prior.offset, 1);//starttimes("+ofToString(startTimeMillis)+", "+ofToString(endTimeMillis); andrew@0: relativeString += ": index "+ofToString(startArrayIndex)+" , "+ofToString(endArrayIndex)+" ["; andrew@0: // relativeString += ofToString(prior.getIndexInRealTerms(endArrayIndex), 3)+"] (sc-width:"+ofToString(screenWidthMillis, 1)+") "; andrew@0: relativeString += " mapped to screen "+ofToString(startScreenPosition)+" , "+ofToString(endScreenPosition); andrew@0: ofDrawBitmapString(relativeString, 100, 180); andrew@0: andrew@1: ofSetColor(255, 255, 0); andrew@0: likelihood.drawConstrainedVector(startArrayIndex, endArrayIndex, startScreenPosition, endScreenPosition); andrew@0: andrew@0: ofSetColor(0,0,200); andrew@0: prior.drawConstrainedVector(startArrayIndex, endArrayIndex, startScreenPosition, endScreenPosition); andrew@0: andrew@0: ofSetColor(200, 0, 0); andrew@0: posterior.drawConstrainedVector(startArrayIndex, endArrayIndex, startScreenPosition, endScreenPosition); andrew@0: andrew@1: andrew@0: // ofSetColor(0, 200, 255); andrew@0: // acceleration.drawConstrainedVector(startArrayIndex, endArrayIndex, startScreenPosition, endScreenPosition); andrew@0: andrew@0: andrew@0: } andrew@0: andrew@0: }