view src/DynamicBayesianArray.cpp @ 11:df9c838d0b8f

fixed bug where the full midi file was sometimes not drawn (since minNoteIndexToPrint) was at the max and did not decrease properly in draw routine
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Tue, 25 Oct 2011 15:01:52 +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
 }
 */