changeset 1:106bc2d4f702

added timing analyser file
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Sat, 23 Nov 2013 15:44:47 +0000
parents 82352cfc0b23
children 50ba55abea8c
files DrumTimingLoader_OF/PerformanceAnalyserSrc/TimingAnalyser.cpp DrumTimingLoader_OF/PerformanceAnalyserSrc/TimingAnalyser.h DrumTimingLoader_OF/PreciseOnsetLocator.cpp
diffstat 3 files changed, 1463 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DrumTimingLoader_OF/PerformanceAnalyserSrc/TimingAnalyser.cpp	Sat Nov 23 15:44:47 2013 +0000
@@ -0,0 +1,1143 @@
+/*
+ *  TimingAnalyser.cpp
+ *  performanceTimingAnalyser
+ *
+ *  Created by Andrew on 17/12/2011.
+ *  Copyright 2011 QMUL. All rights reserved.
+ *
+ */
+
+#include "TimingAnalyser.h"
+
+//FROM TestApp.cpp
+//change these to your preferred filepaths for exporting the data
+//timingDataFilepath = "/Users/andrew/outputFile.txt";//here as decoded tempo and phase
+//change this to your filepath for storing the final path as output
+//can then load it back in easily without reanalysing using this...
+//	importFileFromStoredData(fileToLoad);
+//processBeatTimesFilepath = "//Users/andrew/processedBeats";//here as a list of beat times
+//this latter will be a smoothed version of the original
+
+//RESTRICT PHASE HOP POSSIBLE
+
+
+//Correct or DELETE this BeatPosition variable - what is it? Why used?
+
+
+TimingAnalyser::TimingAnalyser(){
+
+	moveMatrixToOptimalCostPosition = true;
+	
+	tempoScalar = 2.0;
+	phaseScalar = 2.0;
+	
+	phaseCost = 1000.4;//a phase jump is 1.5 (y-x) where y now becomes the predicted position
+	tempoCost = 2.8;//a tempo jump of z msec per period is charged at 2z units
+	
+	drawIOIintervals = false;
+	
+	drawExpressiveTimingData = true;
+	
+	printHistory = false;
+	mozartTriplets = false;
+	
+	movementFactor = 0.5;
+	drawBPM = true;
+	
+	//COST VARIABLES - Assuming that a simple error is costing linear (t-x) where x is predicted time
+
+	
+	blackAndWhite = true;
+	
+	setTempoLimits(400);
+
+	
+	//index between which we look at the variation
+	tempoVariationStartIndex = 4;
+	
+	
+	DoubleVector v;
+	v.assign(phaseRange, 0.0);
+	logProbabilityMatrix.assign(tempoRange, v);	
+	previousLogMatrix = logProbabilityMatrix;
+	
+	//[tempo][phase]
+	phaseMinimumOffset = -1 * phaseScalar*(phaseRange - 1)/2;//offset in millis
+	globalTimeOffset = 0;//global offset in millis
+	
+	lastBeatPosition = 0;
+
+
+	numberOfPointsPerPage = 80;
+	startPoint = 0;
+	
+	//	initialiseRoutes();
+		
+	recentPhaseShift = 0;
+	recentTempoShift = 0;
+
+/*	meanGlobalTempo = 440;
+	tempoMinimumOffset = meanGlobalTempo - (tempoRange-1)/2;
+	meanTempoIndex = (tempoRange - 1)/2;
+	meanTempo = tempoMinimumOffset + meanTempoIndex;
+*/	
+	meanPhaseIndex = (phaseRange - 1)/2;
+	
+	currentBestTempo = meanTempoIndex;
+	currentBestPhase = meanPhaseIndex;
+	
+	printf("Mean tempo initialised at %i and mean index %i\n", meanTempo, meanTempoIndex);
+	int	minDrawTempo = minimumTempo + minimumPhaseHop - 4;
+	int	maxDrawTempo = maximumTempo + maximumPhaseHop + 4;
+	
+	ofTrueTypeFont::setGlobalDpi(72);
+	timesFont.loadFont("TimesNewRoman.ttf", 18, true, true);
+	timesFont.setLineHeight(18.0f);
+	timesFont.setLetterSpacing(1.037);
+	
+}
+
+void TimingAnalyser::initialiseRoutes(){
+}
+
+void TimingAnalyser::clearData(){
+	timingData.clear();
+	basicInterOnsetInterval.clear();
+	beatPosition.clear();
+}
+
+void TimingAnalyser::setTempoLimits(const int& newGlobalTempo){
+	
+	meanGlobalTempo = newGlobalTempo;
+	tempoMinimumOffset = meanGlobalTempo - (tempoScalar*(tempoRange-1)/2);
+	meanTempoIndex = (tempoRange - 1)/2;
+	meanTempo = tempoMinimumOffset + meanTempoIndex*tempoScalar;
+	
+	printf("Setting tempo to %i units i.e. %f ms\n", newGlobalTempo, getTempo(meanTempoIndex));
+}
+
+
+double TimingAnalyser::getPhaseIndexFromEventTime(const double& eventTime){
+	return eventTime / phaseScalar;
+}
+
+double TimingAnalyser::getTempoInUnits(const double& tempoInMs){
+	return tempoInMs / tempoScalar;
+}
+
+//NEW UPDATE METHOD
+double TimingAnalyser::getBestMinimumCost(const int& newTempoInUnits, const int& newPhaseInUnits, Route& r){
+//new method to check all points in last matrix
+	//new phase is the phase point from zero in units
+	//including any offsets etc
+	
+	double cost = 0;
+	double bestCost = INFINITY;
+	Path* lastPath;
+	int minPhase = 0;
+	int minTempo = 0;
+	r.tempoHop = 0;
+	r.phaseHop = 0;
+
+	//int tempoHop, phaseHop; no need
+	if (pathHistory.size() > 0)
+	lastPath = &pathHistory[pathHistory.size()-1]; 
+	else{
+	//	printf("Initiating first path...\n");
+	}
+	
+	for (int tempo = 0;tempo < tempoRange;tempo++){
+	
+		for (int phase = 0;phase < phaseRange;phase++){
+		//change tempo
+			cost = 0;
+			int phasePoint = 0;
+			
+			if (pathHistory.size() > 0){
+				cost = (*lastPath).currentRoute[tempo][phase].totalCost;
+				cost += tempoCost * abs(newTempoInUnits - (tempo + (*lastPath).tempoOffset));
+				
+			//our point then projects forwards at the new tempo
+			phasePoint = phase + (*lastPath).phaseOffset + newTempoInUnits;
+			//phase cost is
+				cost += phaseHopCost(newPhaseInUnits - phasePoint);//i.e. phaseCost * abs(newPhaseInUnits - phasePoint);
+			}//else it's the first point and all previous cost is zero
+			
+			if (cost < bestCost){
+				bestCost = cost;
+				minPhase = phase;
+				minTempo = tempo;
+
+				if (pathHistory.size() > 0){
+					r.tempoHop = newTempoInUnits - (tempo + (*lastPath).tempoOffset);
+					r.phaseHop = newPhaseInUnits - phasePoint;
+				} else{
+					r.tempoHop = 0;
+					r.phaseHop = 0;
+				}
+				
+				r.previousTempoIndex = tempo;
+				r.previousPhaseIndex = phase;
+				
+			}//end if mew minimum
+		}
+	}
+	
+/*	printf("best cost for tempo-phase pair %i, %i from tempo %i and phase %i, hop %i, %i is %.2f\n", 
+		   newTempoInUnits, newPhaseInUnits, 
+		   minTempo, minPhase,
+		   r.tempoHop, r.phaseHop, bestCost);
+*/	return bestCost;
+}
+
+
+void TimingAnalyser::printCostMatrix(const RouteMatrix& m){
+	printf("\n");
+	for (int i = 0; i< m.size();i++){
+		printf("Tempo %.1f (index %i)\n", getTempo(i), i);
+		for (int k = 0;k < m[i].size();k++){
+			printf("%.1f (new %.1f + prev %.1f (%i,%i)), ", m[i][k].totalCost, 
+				   m[i][k].addedCost,m[i][k].previousCost, 
+				   m[i][k].previousTempoIndex, m[i][k].previousPhaseIndex );
+		}
+		printf("\n");
+	}
+}
+
+void TimingAnalyser::updateCostToPoint(const int& eventTime, const int& eventBeatLocation){
+	
+	//	previousLogMatrix = logProbabilityMatrix;//store previous matrix - settings are in pathHistory vector
+	printf("\nTiming Analyser: update cost to %i, \n", eventTime);
+	//event beat location %i is 1 so don't bother printing
+//	printf("old phase range is %.1f to %.1f\n", getPhase(0), getPhase(phaseRange-1));
+//	printf("old tempo range is %.1f to %.1f\n", getTempo(0), getTempo(tempoRange-1));
+	
+	int interval = 1;
+	
+	//setting the new path offset points
+	RouteMatrix r_mat;
+	Path* lastPath;
+	
+	Path p;//the new path point
+	p.tempoOffset = tempoMinimumOffset;//for now keep it the same
+	
+	if (pathHistory.size() > 0){
+		lastPath = &pathHistory[pathHistory.size()-1];
+		int ioi = (int) getTempoInUnits(eventTime - (*lastPath).eventTimeObserved);
+		p.tempoOffset = ioi - ((tempoRange-1)/2);
+		tempoMinimumOffset = p.tempoOffset;
+		printf("New time %i, last time %i diff %i: IOI is %i\n", 
+			   eventTime, (*lastPath).eventTimeObserved,
+			   (eventTime - (*lastPath).eventTimeObserved), ioi);
+	}
+	
+	//and in tempo units!
+	p.phaseOffset = round(getPhaseIndexFromEventTime(eventTime)) + phaseMinimumOffset;//in units
+	//abandoned - now using the offset too - dont need - (phaseRange/2) as in the get phase fn
+	printf("NEW PHASE and tempo offsets %i and %i, \n", p.phaseOffset, p.tempoOffset);
+	//end set offset pts
+	
+	for (int tempoIndex = 0;tempoIndex < logProbabilityMatrix.size();tempoIndex++){
+		RouteVector r_vec;
+		
+		for (int phase = 0;phase < logProbabilityMatrix[tempoIndex].size();phase++){
+			
+
+			Route r;
+			
+			double bestCost = getBestMinimumCost(p.tempoOffset + tempoIndex, phase + p.phaseOffset, r);
+			double newCost = fabs(getPhaseIndexFromEventTime(eventTime) - (p.phaseOffset + phase));
+
+			//this is the phase position that would lead to this current tempo and phase iwthout any hopping
+			//the bestPreviousCost calculates the best oposition including hopping
+			
+			//then we compare the past cost
+			
+			r.previousCost = bestCost;	
+			
+			//this is the best past cost that can get us to current location
+			//then we need new cost
+			
+			r.addedCost = newCost;
+
+			//r.globalPhaseOffset = globalTimeOffset;
+			
+			logProbabilityMatrix[tempoIndex][phase] = bestCost + newCost;	
+			r.totalCost = bestCost + newCost;					
+			
+			//just to check we get this right!
+			r.tempoIndex = tempoIndex;
+			r.phaseIndex = phase;
+			
+			r_vec.push_back(r);
+		}
+		r_mat.push_back(r_vec);
+	}
+	//history.push_back(r_mat);
+	
+	//printHistory(); - defunct as using pathHistory instead
+	//printBestPath();
+	//printf("Global offset %i ph min off %i\n", globalTimeOffset, phaseMinimumOffset);
+	
+	//new method using Path class 
+	p.currentRoute = r_mat;
+	
+	globalTimeOffset = p.phaseOffset;
+	
+	//store the settings for the matrix at this time step
+	//p.globalPhaseOffset = globalTimeOffset;
+//	p.tempoOffset = tempoMinimumOffset;
+
+	setBestTempoAndPhase(p);
+	lastBeatPosition = eventBeatLocation;
+	printf(" error %i ", (int)(eventTime - getPhase(currentBestPhase, globalTimeOffset)));
+	p.phaseShiftApplied = recentPhaseShift;//this is what we did in the recent step
+	p.tempoShiftApplied = recentTempoShift;
+	//so is the shift by which current stored matrix and indices differ from the last path
+	
+	p.eventTimeObserved = eventTime;
+	p.costMatrix = logProbabilityMatrix;
+	
+	if (pathHistory.size() > 0){
+		//then can calculate inter-onset interval
+		int ioi = eventTime - pathHistory[pathHistory.size()-1].eventTimeObserved;
+		basicInterOnsetInterval.push_back(ioi);
+		printf("ioi for time %i is %i\n", eventTime, ioi);
+	}
+	printf("New PATH offset is %i\n", p.phaseOffset);
+	pathHistory.push_back(p);
+	
+	//prints the complete cost matrix at every step
+	//printCostMatrix(p.currentRoute);
+	
+	
+	if (printHistory)
+		printPathHistory();
+	
+	//	printf(", SHIFT (%i, %i)\n", p.phaseShiftApplied,  p.tempoShiftApplied);
+	
+	//loaded the new prob matrix to the main log one
+	//now looking to shift
+	
+	//change global offset to match new position
+	//	printLogMatrix();
+	
+	
+	previousLogMatrix = logProbabilityMatrix;//store previous matrix - settings are in pathHistory vector
+	
+	//	printLogMatrix();	
+	
+}
+
+
+
+void TimingAnalyser::printIOIdata(){
+	for (int i = 0;i < basicInterOnsetInterval.size();i++){
+		printf("IOI[%i] : %i\n", i, basicInterOnsetInterval[i]);
+	}
+}
+
+
+void TimingAnalyser::checkShiftMatrix(){
+
+	if (moveMatrixToOptimalCostPosition){
+		int phaseShiftIndex = (int)(meanPhaseIndex + movementFactor*(currentBestPhase - meanPhaseIndex));
+		int tempoShiftIndex = (int)(meanTempoIndex + movementFactor*(currentBestTempo - meanTempoIndex));
+		printf("current best tempo %i, best phase %i, mean tempo %i, shift of %i\n", currentBestTempo, currentBestPhase, meanTempoIndex, tempoShiftIndex);
+		shiftMatrixToMatchBestPhase(phaseShiftIndex);
+		shiftMatrixToMatchBestTempo(tempoShiftIndex);
+	}
+	
+}
+
+
+
+void TimingAnalyser::shiftMatrixToMatchBestPhase(const int& bestPhaseIndex){
+
+//	int bestPhaseIndex = pathHistory[pathHistory.size()-1].bestPhase;
+	printf("SHIFT:: BEST PHASE %i, ", bestPhaseIndex);
+	
+	int shift = bestPhaseIndex - meanPhaseIndex;
+	DoubleMatrix tmpMat = logProbabilityMatrix;
+	
+	for (int t = 0;t < tempoRange;t++){
+		for (int p = 0;p < phaseRange;p++){
+			int switchIndex = p + shift;
+			if (switchIndex < phaseRange && switchIndex >= 0){
+				logProbabilityMatrix[t][p] = tmpMat[t][switchIndex];
+			}else{
+				logProbabilityMatrix[t][p] = INFINITY;
+			}
+		}
+	}
+	globalTimeOffset += shift * phaseScalar;
+	printf("new phase shift of %i and offset is %i \n", shift, globalTimeOffset);
+	recentPhaseShift = shift;
+}
+
+void TimingAnalyser::shiftMatrixToMatchBestTempo(const int& bestTempoIndex){
+	
+	//	int bestPhaseIndex = pathHistory[pathHistory.size()-1].bestPhase;
+	printf("SHIFT:: BEST TEMPO %i, ", bestTempoIndex);
+	
+	int shift = bestTempoIndex - meanTempoIndex;
+	DoubleMatrix tmpMat = logProbabilityMatrix;
+	
+	for (int t = 0;t < tempoRange;t++){
+		for (int p = 0;p < phaseRange;p++){
+			int switchIndex = t + shift;
+			if (switchIndex < tempoRange && switchIndex >= 0){
+				logProbabilityMatrix[t][p] = tmpMat[switchIndex][p];
+			}else{
+				logProbabilityMatrix[t][p] = INFINITY;
+			}
+		}
+	}
+	
+	tempoMinimumOffset += shift * tempoScalar;
+	printf("new tempo shift of %i and tempo offset is %i \n", shift, tempoMinimumOffset);
+	recentTempoShift = shift;
+}
+
+
+bool TimingAnalyser::checkPhaseRange(const int& phaseToCheck){
+
+	if (phaseToCheck < phaseRange &&  phaseToCheck >= 0)
+		return true;
+	else 
+		return false;
+}
+
+bool TimingAnalyser::checkTempoRange(const int& tempoToCheck){
+	
+	if (tempoToCheck < tempoRange &&  tempoToCheck >= 0)
+		return true;
+	else 
+		return false;
+}
+
+double TimingAnalyser::phaseHopCost(const int& phaseHop){
+	//printf("phase hop %i returns %f", phaseHop, phaseCost*abs(phaseHop));
+	return phaseCost*abs(phaseHop);
+}
+
+double TimingAnalyser::tempoHopCost(const int& tempoHop){
+	return tempoCost*abs(tempoHop);
+}
+
+double TimingAnalyser::getTempo(const int& tempoIndex){
+	return (tempoMinimumOffset + tempoIndex*tempoScalar);
+}
+
+double TimingAnalyser::getPhase(const int& phaseIndex){
+	return globalTimeOffset + (phaseIndex*phaseScalar);
+}
+
+double TimingAnalyser::getTempo(const int& tempoIndex, const int& tempoOffset){
+	return ((tempoOffset + tempoIndex)*tempoScalar);
+}
+
+double TimingAnalyser::getPhase(const int& phaseIndex, const int& phaseOffset){
+	//phase offset for middle of matrix
+	return (phaseOffset + phaseIndex)*phaseScalar;
+}
+
+int TimingAnalyser::getTempoIndex(const double& tempo){
+	double index = tempo;
+	index -= tempoMinimumOffset;
+	index /= tempoScalar;
+	return (int)round(index);
+}
+
+
+int TimingAnalyser::getPhaseIndex(const double& location){
+	double index = location;
+	index -= globalTimeOffset;
+	index -= phaseMinimumOffset;
+	index /= phaseScalar;
+	return (int)round(index);
+}
+
+
+double TimingAnalyser::getMinimumTransitionCost(const int& interval, const int& tempoIndex, const int& phaseIndex){
+	
+	double minimumCost = 100000000.0;//very big
+	
+	//need to get the location of where we are now
+	int endLocation = 0;//getBeatLocation()
+	
+//	int zeroLocation = getBeatLocation();	
+//	getLocation(0, 0, beatPosition + interval);
+	int tempo = 0;
+	
+//	for (int tempo = 0;tempo < logProbabilityMatrix.size();tempo++){
+		for (int phase = 0;phase < logProbabilityMatrix[tempo].size();phase++){
+			
+			//double tempoTransition = getTempoTransitionCost(tempoIndex - tempo);
+			//double phaseTransition = getPhaseTransitionCost(phaseindex - phase);
+			
+			
+			
+		}
+//	}
+			
+		return minimumCost;
+}
+
+
+double TimingAnalyser::getMaximum(){
+	double maxVal = 1.0;
+	for (int tempo = 0;tempo < logProbabilityMatrix.size();tempo++){
+		for (int phase = 0;phase < logProbabilityMatrix[tempo].size();phase++){
+		if (logProbabilityMatrix[tempo][phase] > maxVal && logProbabilityMatrix[tempo][phase] < INFINITY)
+			maxVal = logProbabilityMatrix[tempo][phase];
+		}
+	}
+	return maxVal;
+}
+
+void TimingAnalyser::drawCostMatrix(){
+	double maximum = getMaximum();
+	double width = ofGetWidth() / phaseRange;
+	double height = ofGetHeight() / tempoRange;
+	
+	for (int tempo = 0;tempo < logProbabilityMatrix.size();tempo++){
+		for (int phase = 0;phase < logProbabilityMatrix[tempo].size();phase++){
+			
+			ofSetColor(0,0, 255.0*(maximum - logProbabilityMatrix[tempo][phase])/maximum );
+			ofRect(phase*width, tempo*height, width, height);
+			ofSetColor(255,255,255);
+			
+			string infoStr = "T "+ofToString(getTempo(tempo, tempoMinimumOffset));
+			infoStr += "\nP "+ofToString(phase)+" ("+ofToString(getPhase(phase, globalTimeOffset))+")";
+			infoStr += "\n"+ofToString(logProbabilityMatrix[tempo][phase]);
+			
+		//	ofDrawBitmapString(infoStr, phase*width + 10, tempo*height + 10);
+		}
+	}
+	
+}
+
+
+void TimingAnalyser::setBestTempoAndPhase(Path& newPath){
+
+	double bestCost = newPath.currentRoute[currentBestTempo][currentBestPhase].totalCost;// INFINITY;
+	for (int t = 0;t < tempoRange;t++){
+		for (int p = 0;p < phaseRange;p++){
+			if (newPath.currentRoute[t][p].totalCost < bestCost){
+				bestCost = newPath.currentRoute[t][p].totalCost;
+				currentBestPhase = p;
+				currentBestTempo = t;
+			}
+		}
+	}
+	
+	newPath.bestTempo = currentBestTempo;// bestTempo;
+	newPath.bestPhase = currentBestPhase;// bestPhase;
+	
+	printf("BEST TEMPO %i, PHASE %i :: ", currentBestTempo, currentBestPhase);
+	string tString = "Tempo "+ofToString(getTempo(currentBestTempo, tempoMinimumOffset));
+	tString += ", Phase "+ofToString(getPhase(currentBestPhase, globalTimeOffset));
+	tString += ", BEST COST "+ofToString(bestCost);
+	//tstring += ", error "+ofToString()
+	printf("i.e. %s", tString.c_str());
+	
+}	
+
+void TimingAnalyser::printPathHistory(){
+/*	printf("tempo %i (%3.0f), phase %i (%3.0f)\n", pathHistory[i].bestTempo, 
+		   getTempo(pathHistory[i].bestTempo, pathHistory[i].tempoOffset),
+		   pathHistory[i].bestPhase, 
+		   getPhase(pathHistory[i].bestPhase, pathHistory[i].globalPhaseOffset)
+		   );
+	*/
+	int tempo, phase;
+	
+	RouteMatrix* tmpRoute;
+	int pathIndex = pathHistory.size()-1;
+	if ( pathHistory.size() > 0){
+		pathHistory[0].phaseShiftApplied = 0;//hack to fix non zero
+		tempo = pathHistory[pathHistory.size()-1].bestTempo;
+		phase = pathHistory[pathHistory.size()-1].bestPhase;
+
+		printf("PATH BEST[%i] tempo %i (%3.0f), phase %i (%3.0f) at COST %3.3f preCOST %3.3f addCOST %3.3f\n", 
+		pathIndex,
+		tempo, getTempo(tempo, pathHistory[pathHistory.size()-1].tempoOffset),
+		phase, getPhase(phase, pathHistory[pathHistory.size()-1].phaseOffset),
+		pathHistory[pathHistory.size()-1].currentRoute[tempo][phase].totalCost,
+			   pathHistory[pathHistory.size()-1].currentRoute[tempo][phase].previousCost,
+			   pathHistory[pathHistory.size()-1].currentRoute[tempo][phase].addedCost
+			 );
+	}//end if 
+	
+	
+	while (pathIndex >= 0 && pathIndex < pathHistory.size()){
+	//	printf("index %i, history size %i\n", pathIndex, pathHistory.size());
+		tmpRoute = &(pathHistory[pathIndex].currentRoute);
+		int previousTempo = (*tmpRoute)[tempo][phase].previousTempoIndex;
+		int previousPhase = (*tmpRoute)[tempo][phase].previousPhaseIndex;// + pathHistory[pathIndex].phaseShiftApplied;
+		//above was error on 24/12 that created wrong results - it is already included!
+		
+		printf("PTH[%i](%i,%i)\total{%3.2f}\t(prevCost %3.2f (%3.2f, %3.2f, %3.2f)\t:: adddedCost %3.2f\t: hop (%i, %i)\tprevious (%i, %i) applied (%i, %i){%i, %i}, ", 
+			   pathIndex,  
+			   tempo, phase, 
+			   (*tmpRoute)[tempo][phase].totalCost, 
+			   (*tmpRoute)[tempo][phase].previousCost,
+			   (*tmpRoute)[tempo][phase].preHopCost,
+			   (*tmpRoute)[tempo][phase].tempoHopCost,
+			   (*tmpRoute)[tempo][phase].phaseHopCost,			   
+			    (*tmpRoute)[tempo][phase].addedCost,
+			    (*tmpRoute)[tempo][phase].tempoHop, 
+			   (*tmpRoute)[tempo][phase].phaseHop,
+			   previousTempo, previousPhase,  
+			   pathHistory[pathIndex].tempoShiftApplied, pathHistory[pathIndex].phaseShiftApplied,
+			  pathHistory[pathIndex].tempoOffset,  pathHistory[pathIndex].phaseOffset	   
+			   
+			   );
+		
+		if (pathIndex > 0){
+			printf("Tempo %3.0f Phase %3.0f (PRED %3.0f) @event %i (%3.0f)\n", 
+				   getTempo(previousTempo, pathHistory[pathIndex-1].tempoOffset),
+				   getPhase(previousPhase, pathHistory[pathIndex-1].phaseOffset),
+				   getPhase(previousPhase, pathHistory[pathIndex-1].phaseOffset) + getTempo(previousTempo, pathHistory[pathIndex-1].tempoOffset),
+				   pathHistory[pathIndex].eventTimeObserved,
+				   getPhase(phase, pathHistory[pathIndex].phaseOffset)
+				   );
+		}
+
+		tempo =	 previousTempo;
+		phase =  previousPhase;
+		
+		pathIndex--;
+	}
+	
+
+}
+
+
+void TimingAnalyser::processPathHistory(){
+
+	printf("Process path history...\n");
+	
+	timingData.clear();
+	
+	maximumTempo = 0;
+	minimumTempo = INFINITY;
+	
+	minimumPhaseHop = 0;
+	maximumPhaseHop = 0;
+	
+	printf("\n");
+	int tempo, phase;
+	
+	RouteMatrix* tmpRoute;
+	int pathIndex = pathHistory.size()-1;
+	int observedPhasePoint;
+	int observedTempo, observedEventTime;
+	int storedTempoHop = 0;
+	int storedTempo = 0;
+	
+	if ( pathHistory.size() > 0){
+		pathHistory[0].phaseShiftApplied = 0;//hack to fix non zero
+		tempo = pathHistory[pathIndex].bestTempo;
+		phase = pathHistory[pathIndex].bestPhase;
+		observedPhasePoint = getPhase(phase, pathHistory[pathIndex].phaseOffset);
+		
+	}
+		
+	while (pathIndex >= 0){
+		tmpRoute = &(pathHistory[pathIndex].currentRoute);
+		int previousTempo = (*tmpRoute)[tempo][phase].previousTempoIndex;
+		int previousPhase = (*tmpRoute)[tempo][phase].previousPhaseIndex;		
+		IntVector v;
+	
+		observedTempo = storedTempo;
+		observedPhasePoint = (int)round(getPhase(phase, pathHistory[pathIndex].phaseOffset));
+		observedEventTime =  pathHistory[pathIndex].eventTimeObserved;
+		
+		if (observedTempo > maximumTempo)
+			maximumTempo = observedTempo;
+		
+		if (observedTempo < minimumTempo && observedTempo > 0)
+			minimumTempo = observedTempo;
+		
+		int phaseHop = (*tmpRoute)[tempo][phase].phaseHop;
+		
+		if (phaseHop < minimumPhaseHop)
+			minimumPhaseHop = phaseHop;
+		
+		if (phaseHop > maximumPhaseHop)
+			maximumPhaseHop = phaseHop;
+		
+		v.push_back(observedTempo);//timingdata[][0]
+		v.push_back(observedPhasePoint);//timingdata[][1]
+		v.push_back(observedEventTime);//timingdata[][2]
+		v.push_back(storedTempoHop);
+		v.push_back( (*tmpRoute)[tempo][phase].phaseHop);//timingData[][4]
+		v.push_back(observedEventTime - observedPhasePoint);//timingdata[][5]
+		
+		timingData.push_back(v);
+		
+		
+		printf("Index %i TEMPO %i, PHASE %i, EVENT %i HOP (%i, %i) error %i \n", 
+			   (int) timingData.size(),
+			   observedTempo, observedPhasePoint, 
+			   observedEventTime, storedTempoHop,
+			   (*tmpRoute)[tempo][phase].phaseHop, 
+			   (observedEventTime - observedPhasePoint));
+		//checking this ned to align tempo, observed phase and observed events
+		
+		//N.B. MUST STORE THIS FROM FUTURE POINT
+		storedTempo = (int)round(getTempo(tempo, pathHistory[pathIndex].tempoOffset));
+		storedTempoHop = (*tmpRoute)[tempo][phase].tempoHop;
+		
+		tempo =	 previousTempo;
+		phase =  previousPhase;
+		
+		pathIndex--;
+	}
+	
+	reverse(timingData.begin(), timingData.end());
+
+	clearHistogram();
+	
+	for (int i = 0;i < timingData.size();i++){
+		printf("Rev index %i tempo %i, phase hop %i, error %i, beat location %i\n", i, 
+			   timingData[i][0], timingData[i][4], timingData[i][5], (int) beatPosition[i]);
+		
+		int error = (int) timingData[i][4] + timingData[i][5];
+		
+		if (abs(error) < 30 && (int)beatPosition[i] - 1 < timingHistogram.size())
+			timingHistogram[(int)beatPosition[i] - 1].push_back(error);
+	}
+	
+	printf("Maximum is %f and min %f hopMin %i hopMax %i\n", maximumTempo, minimumTempo, minimumPhaseHop, maximumPhaseHop);
+	minDrawTempo = minimumTempo + minimumPhaseHop - 4;
+	maxDrawTempo = maximumTempo + maximumPhaseHop + 4;
+	
+	getHistogramResults();
+	
+}
+
+void TimingAnalyser::clearHistogram(){
+	
+	timingHistogram.clear();
+	IntVector v;
+	for (int i = 0;i < 4;i++){
+		v.clear();
+		timingHistogram.push_back(v);
+	}
+}
+
+
+void TimingAnalyser::getHistogramResults(){
+	DoubleVector results;
+	for (int i = 0;i < 4;i++){
+		double total;
+		for (int k = 0; k < timingHistogram[i].size();k++){
+			total += timingHistogram[i][k];
+		}
+		total /= timingHistogram[i].size();
+		results.push_back(total);
+		printf("Mean at beat %i is %.2f\n", i, results[i]);
+	}
+}
+
+#pragma mark -drawTempoCurve
+void TimingAnalyser::drawTempoCurve(){
+	if (timingData.size() > 0){
+		screenWidth = ofGetWidth();
+		screenHeight = ofGetHeight();
+		double height = screenHeight;
+//		int	minDrawTempo = minimumTempo + minimumPhaseHop - 4;
+//		int	maxDrawTempo = maximumTempo + maximumPhaseHop + 4;
+		
+		if (maximumTempo > 0)
+			height /= (maxDrawTempo - minDrawTempo);
+	
+		double bpmMaxTempo = msToBpm(minDrawTempo);
+		double bpmMinTempo = msToBpm(maxDrawTempo);
+		double bpmHeight = screenHeight / (bpmMaxTempo - bpmMinTempo);
+		
+	//int minHeightPixels = minHeight * height;
+		
+		ofBackground(255);
+		double width = ofGetWidth()/numberOfPointsPerPage;
+	
+		int lastHeightPoint = getHeightPoint(height * (timingData[0][0] - minDrawTempo) );
+		int newHeightPoint;
+		
+		double error;
+		int Xpoint;
+		
+		//horizonal lines for tempo
+		ofSetColor(150);
+		if(!drawBPM){
+		int horizontalTempo = minDrawTempo + 20 - minDrawTempo%20;
+	//	while (horizontalTempo > minDrawTempo)
+	//		horizontalTempo -= 20;
+			while (horizontalTempo < maxDrawTempo){
+				ofSetColor(150);
+				ofLine(0, getHeightPoint(height*(horizontalTempo - minDrawTempo)), screenWidth, getHeightPoint(height*(horizontalTempo - minDrawTempo)));
+				ofSetColor(50);
+			ofDrawBitmapString(ofToString(horizontalTempo), 20, getHeightPoint(height*(horizontalTempo - minDrawTempo)));
+			//	timesFont.drawString(ofToString(horizontalTempo), 20, getHeightPoint(height*(horizontalTempo - minDrawTempo)));//FONT
+				horizontalTempo += 20;
+			}//end while
+		
+		} else{
+			int resolution = 2;
+			
+				if (maxDrawTempo - minDrawTempo > 150)
+					resolution = 4;
+			if (maxDrawTempo - minDrawTempo > 400)
+				resolution = 8;
+			
+			int horizontalTempo = (int)bpmMinTempo + resolution - ((int)bpmMinTempo % resolution);//mod ten above min
+			while (horizontalTempo < bpmMaxTempo) {
+				int tmp = getHeightPoint(bpmHeight * (horizontalTempo - bpmMinTempo));
+				ofSetColor(150);
+				ofLine(0, tmp , screenWidth, tmp);
+				ofSetColor(50);
+				ofDrawBitmapString(ofToString(horizontalTempo), 20, tmp+2);
+				std::string number = ofToString(horizontalTempo);
+//				timesFont.drawString(number, 20, tmp+2);//FONT
+				horizontalTempo += resolution;
+			}
+			
+		}
+
+		//vertical bars 
+		int solidBarEvery = 4;//normally every four beats
+		
+		int counter = 0;
+		for (int i = 0;i < timingData.size();i++){
+			ofSetColor(200);
+			bool drawLine = false;
+
+			
+			//this useful for drawing on ISMIR paper
+			if (mozartTriplets){
+				//stronger lines on the bars
+				solidBarEvery = 12;//- pollini triplets
+				
+				if ((i % solidBarEvery == 0)){// || beatPosition[i] == 0 ){
+					ofSetColor(80);
+					drawLine = true;
+					counter = 0;
+				}
+				
+				//normal every three (eighth notes)
+				if (i % 3 == 0 && mozartTriplets){
+					drawLine = true;
+				}
+			} 
+			
+			
+			int beatsPerBar = 4;//set 3 for some beatles tracks
+			int mainBeat = 0; 
+			
+			if ((int)i % beatsPerBar == mainBeat && !mozartTriplets){
+				//was BeatPosoiton[i] - dodgy
+				drawLine = true;
+			}
+			/*
+			if (i == tempoVariationEndIndex){
+				ofSetColor(200, 0,0);
+				drawLine = true;
+			}
+			 */
+			
+			if (drawLine){
+				ofLine((i-startPoint) * width, 0, (i-startPoint) * width, ofGetHeight());
+			}
+		}
+		
+		
+		for (int i = startPoint+1;i < min((int)timingData.size(), startPoint + numberOfPointsPerPage);i++){
+			if (!drawIOIintervals){
+			ofSetColor(0,0,0);
+			Xpoint = (i-startPoint) * width ;
+			if (!drawBPM)
+				newHeightPoint = getHeightPoint(height * (timingData[i][0] - minDrawTempo));
+			else 
+				newHeightPoint = getHeightPoint(bpmHeight * (msToBpm(timingData[i][0]) - bpmMinTempo));
+
+			ofLine((i-startPoint-1) * width, lastHeightPoint,Xpoint, newHeightPoint);
+			lastHeightPoint = newHeightPoint;
+			
+			error = timingData[i][2] - timingData[i][1];
+			int phaseHop = timingData[i][4];
+			
+			if (!blackAndWhite)
+				ofSetColor(255,0,0);
+			else 
+				ofSetColor(155);
+			
+			if (drawExpressiveTimingData)
+			ofLine(Xpoint, newHeightPoint, Xpoint, newHeightPoint - (phaseHop * height));
+			//line up from tempo to where we observe point
+			
+			if (!blackAndWhite)
+				ofSetColor(0,0, 155);
+			else 
+				ofSetColor(60);
+				
+			if (drawExpressiveTimingData)	
+			ofCircle(Xpoint, newHeightPoint - ((phaseHop + error) * height), 2);
+//			ofLine((i-startPoint) * width , screenHeight/2, (i-startPoint) * width , (screenHeight/2)*(1+(timingData[i][3]/60.0)));
+			
+			if (!blackAndWhite)	
+				ofSetColor(0,0,255);
+			ofLine(((playingIndex)-startPoint) * width, 0, ((playingIndex)-startPoint) * width, screenHeight);
+			
+			}//if not draw IOI
+			
+			if (drawIOIintervals){	
+				ofSetColor(160,160,160);
+				ofLine((i-startPoint-1) * width, getHeightPoint(height * (basicInterOnsetInterval[i-1]- minDrawTempo)), 
+					   (i-startPoint) * width, getHeightPoint(height * (basicInterOnsetInterval[i]- minDrawTempo)) );
+			}
+	//		ofLine((i-startPoint) * width , screenHeight/2, (i-startPoint) * width , (screenHeight/2)*(1+(timingData[i][4]/60.0)));
+			
+		}//end for
+	
+	}
+	
+}
+
+
+void TimingAnalyser::widenDrawWindow(){
+	maxDrawTempo += 2;
+	minDrawTempo -= 2;
+}
+
+
+
+
+void TimingAnalyser::narrowDrawWindow(){
+	maxDrawTempo -= 2;
+	minDrawTempo += 2;
+}
+
+void TimingAnalyser::moveDrawWindowUp(){
+	maxDrawTempo += 2;
+	minDrawTempo += 2;
+}
+
+void TimingAnalyser::moveDrawWindowDown(){
+	maxDrawTempo -= 2;
+	minDrawTempo -= 2;
+}
+
+int TimingAnalyser::getIndexAtMouseXposition(const int& Xpos){
+	int numberPointsIn = (int)round(Xpos * numberOfPointsPerPage / ofGetWidth());
+	
+	printf("number pts %i size %i , start %i no. in from left %i\n", 
+		   numberOfPointsPerPage, (int)timingData.size(), 
+		   startPoint, numberPointsIn);
+	
+	numberPointsIn += startPoint;
+	
+	printf("MOUSE X IS %i == %i\n", Xpos, numberPointsIn);
+	
+	return min((int)timingData.size(), numberPointsIn);
+}
+
+int TimingAnalyser::getHeightPoint(float f){
+	return (int)round(screenHeight - f);
+}
+
+
+
+void TimingAnalyser::printMatrix(DoubleMatrix& logMatrix){
+	for (int t = 0;t < logMatrix.size();t++){
+	for (int p = 0;p < logMatrix[t].size();p++){
+		printf("(%i,%i)= %2.1f ", t, p, logMatrix[t][p]);
+	}
+		printf("\n");
+	}
+
+}
+
+void TimingAnalyser::printLogMatrix(){
+	printf("\n");
+	for (int p = 0;p < phaseRange;p++){
+	printf("LOG M [%i] %2.2f, ", p, logProbabilityMatrix[0][p]);
+	}
+	printf("offset %i\n", globalTimeOffset);
+}
+
+void TimingAnalyser::exportTimingData(){
+	ofstream ofs(timingDataFilepath.c_str());
+//	ofs << "output timng data size " << (int) timingData.size() << "IOI size " << (int)basicInterOnsetInterval.size() << endl;
+	
+	for (int i = 0;i < min((int)timingData.size(), (int) basicInterOnsetInterval.size());i++){
+		for (int k = 0; k < 5;k++){
+			ofs << timingData[i][k] << "\t";
+		}
+		ofs << basicInterOnsetInterval[i] << "\t";
+		ofs << endl;
+	}
+
+}
+
+void TimingAnalyser::importTimingData(std::string importFileName){
+	ifstream ifs(importFileName.c_str());
+	printf("IMPORT FILE %s\n", importFileName.c_str());
+	timingData.clear();
+	string value;
+	int count = 0;
+	//Notation n;
+	IntVector v;
+	while ( ifs.good() )
+	{
+		getline ( ifs, value, '\n' ); // read a string until next enter command
+		//		cout << "disp " <<  string( value, 0, value.length()-1 ) << endl; // display value removing the first and the last character from it
+		
+		//printf("size of line is %i\n", (int)value.size()); 
+		v.clear();
+		
+		if (value.size() > 0){
+			
+			string::size_type start = value.find_first_not_of(" \t\v");
+			string part = value.substr(start, string::npos);
+			string otherPart = value;
+			printf("input line%i : '%s'\n", count, otherPart.c_str());
+			size_t found;
+			found=part.find_first_of("\t\n");
+			size_t startC = 0;
+			int r = 0;
+			while (found!=string::npos){
+				string section = otherPart.substr(startC, found - startC);
+				int  my_int = atoi(section.c_str());
+				v.push_back(my_int);
+				printf("timing[%i][%i] ", count, r, my_int);
+				printf("section '%s'\n", section.c_str());
+				
+				startC= otherPart.find_first_not_of("\t\n",found);
+				found = otherPart.find_first_of("\t\n",found+1);
+				r++;
+			}
+			timingData.push_back(v);
+		}//end if > 0
+ 
+		count++;
+	
+	 }
+	
+	
+	basicInterOnsetInterval.clear();
+	
+	maximumTempo = 0;
+	minimumTempo = INFINITY;
+	
+	for (int i = 0;i < max(0, (int)timingData.size()-1);i++){
+		printf("TEMPO %i %i IOI %i\n", timingData[i][0], timingData[i][1], timingData[i][4]);
+		
+		basicInterOnsetInterval.push_back(timingData[i][5]);
+		
+		int observedTempo = timingData[i][0];
+	//	printf("observed %i\n", observedTempo);
+		
+		if (observedTempo > maximumTempo)
+			maximumTempo = observedTempo;
+		
+		if (observedTempo < minimumTempo && observedTempo > 0)
+			minimumTempo = observedTempo;
+		
+	}
+	
+	
+	printf("min t %f, Max t %f\n", minimumTempo, maximumTempo);
+}
+
+
+void TimingAnalyser::exportProcessedBeatTimes(const double& firstBeatTime){
+	ofstream ofs(processedBeatTimesFilepath.c_str());
+	
+	for (int i = 0;i < min((int)timingData.size(), (int) basicInterOnsetInterval.size());i++){
+		double beatTime = (timingData[i][1] + firstBeatTime)/1000.0;
+		printf("Beat %i : %f\n", i, beatTime);
+		ofs << beatTime;
+		ofs << endl;
+	}
+}
+
+
+double TimingAnalyser::msToBpm(const double& ms){
+	return 60000./ms;
+}
+
+
+void TimingAnalyser::calculateTempoLimits(){
+	
+	maximumTempo = 0;
+	minimumTempo = INFINITY;
+	
+	for (int i = 0;i < max(0, (int)timingData.size()-1);i++){
+		
+		int observedTempo = timingData[i][0];
+		
+		if (observedTempo > maximumTempo)
+			maximumTempo = observedTempo;
+		
+		if (observedTempo < minimumTempo && observedTempo > 0)
+			minimumTempo = observedTempo;
+		
+	}
+	
+	tempoVariationStartIndex = min(4, (int)timingData.size());
+	tempoVariationEndIndex = max(0, (int)timingData.size() - 4);
+	printf("VARIATION TO BE CALCULATED BETWEEN %i and %i\n", tempoVariationStartIndex, tempoVariationEndIndex);
+}
+
+double TimingAnalyser::calculateTempoVariation(){
+	if (timingData.size() > tempoVariationStartIndex && tempoVariationEndIndex + 1< timingData.size()){
+		double mean = 0;
+		
+		for (int i = tempoVariationStartIndex;i <= tempoVariationEndIndex;i++){
+			mean += timingData[i][0];
+		}
+		mean /= (tempoVariationEndIndex - tempoVariationStartIndex);
+		double variation = 0;
+		double fluctuation = 0;
+		int lastValue = timingData[tempoVariationStartIndex][0];
+		
+		for (int i = tempoVariationStartIndex;i <= tempoVariationEndIndex;i++){
+			variation += (timingData[i][0] - mean)*(timingData[i][0] - mean);
+			fluctuation += abs(timingData[i][0] - lastValue);
+			lastValue = timingData[i][0];
+		}
+		variation /= (tempoVariationEndIndex - tempoVariationStartIndex);
+		variation = sqrt(variation);
+		fluctuation /= (tempoVariationEndIndex - tempoVariationStartIndex);
+		
+		double slope = (double) timingData[tempoVariationStartIndex][0] / timingData[tempoVariationEndIndex][0];
+		printf("TEMPO STATS:\nMean: %.2f\nVariance %.2f \nSlope %.1f per cent\nAverage delta Tempo %.2f", 
+			   mean, variation, (slope*100.0), fluctuation);
+	}
+
+}
+
+
+void TimingAnalyser::zoomIn(){
+	numberOfPointsPerPage /= 2;
+}
+
+
+void TimingAnalyser::zoomOut(){
+	numberOfPointsPerPage *= 2;
+}
+
+
+/*
+ double TimingAnalyser::getCost(const int& eventTime, const int& eventLocation, const int& tempoIndex, const int& phaseIndex){
+ 
+ double interval = eventLocation - lastBeatPosition;
+ double newLocation = getPhase(phaseIndex) + interval*getTempo(tempoIndex);	
+ double phaseCost = fabs(newLocation - eventTime);
+ 
+ return phaseCost;
+ }
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DrumTimingLoader_OF/PerformanceAnalyserSrc/TimingAnalyser.h	Sat Nov 23 15:44:47 2013 +0000
@@ -0,0 +1,212 @@
+/*
+ *  TimingAnalyser.h
+ *  performanceTimingAnalyser
+ *
+ *  Created by Andrew on 17/12/2011.
+ *  Copyright 2011 QMUL. All rights reserved.
+ *
+ */
+#ifndef TIMING_ANALYSER
+#define TIMING_ANALYSER	
+
+#include "ofMain.h"
+
+#include <vector>
+#include <cstdlib>
+using namespace std;
+
+//big matrix stores cost
+
+
+struct Route {
+	int tempoIndex, phaseIndex;
+	double addedCost, totalCost;
+	int previousTempoIndex;
+	int previousPhaseIndex;
+	int phaseHop, tempoHop;
+	double previousCost;
+	double preHopCost;
+	double phaseHopCost, tempoHopCost;
+	
+	//	int currentTempoIndex, currentPhaseIndex;
+	//	int globalPhaseOffset;
+	//	int tempoMinimumOffset;
+};
+
+typedef std::vector<Route> RouteVector;
+typedef std::vector<RouteVector> RouteMatrix;
+typedef std::vector<RouteMatrix> RouteHistory;
+
+typedef std::vector<double> DoubleVector;
+typedef std::vector<DoubleVector> DoubleMatrix;
+
+struct  Path{
+	RouteMatrix currentRoute;
+	int bestTempo, bestPhase;
+//	int globalPhaseOffset;
+	int tempoOffset, phaseOffset;
+	int phaseShiftApplied;
+	int tempoShiftApplied;
+	int eventTimeObserved;
+	DoubleMatrix costMatrix;
+};
+typedef std::vector<Path> PathVector;
+
+class TimingAnalyser{
+	public:
+	TimingAnalyser();
+	//size of matrix and mean tempo determined here
+	static const int tempoRange = 47;
+	static const int phaseRange = 57;
+	int meanGlobalTempo ;
+	
+	std::string timingDataFilepath;
+	std::string processedBeatTimesFilepath;
+	
+	void setTempoLimits(const int& newGlobalTempo);
+	
+	DoubleMatrix previousLogMatrix;
+	
+	typedef std::vector<int> IntVector;
+	typedef std::vector<IntVector> IntMatrix;
+	IntMatrix timingData;
+	IntVector basicInterOnsetInterval;
+	
+	
+	void printCostMatrix(const RouteMatrix& m);
+	//NEW COST METHODS:
+	void updateCostToPoint(const int& eventTime, const int& eventBeatLocation);
+	double getBestMinimumCost(const int& newTempoInUnits, const int& newPhaseInUnits, Route& r);
+	
+	double getPhaseIndexFromEventTime(const double& eventTime);
+	double getTempoInUnits(const double& tempoInMs);
+	
+	
+	
+	PathVector pathHistory;
+	void setBestTempoAndPhase(Path& newPath);
+	void  printPathHistory();
+	void printIOIdata();
+	void processPathHistory();
+	
+//	RouteMatrix routes;
+//	RouteHistory history;
+	
+	int playingIndex;
+	
+//	void printHistory();
+	//void printBestPath();
+	
+	int phaseMinimumOffset;
+	int globalTimeOffset;
+	int tempoMinimumOffset;
+	double maximumTempo, minimumTempo;
+	double screenHeight, screenWidth ;
+	
+	void drawTempoCurve();
+	int getHeightPoint(float f);
+	
+	int numberOfPointsPerPage;
+	bool printHistory;
+	
+	double tempoCost, phaseCost;
+	
+	DoubleMatrix logProbabilityMatrix;
+	double lastBeatPosition;
+	
+	int	minimumPhaseHop, maximumPhaseHop ;
+	
+//	double getCost(const int& eventTime, const int& interval, const int& tempoIndex, const int& phaseIndex);
+	void updateCost(const int& eventTime, const int& eventBeatLocation);
+	void updateMatrixOffsets(const int& eventTime);
+	
+	void checkShiftMatrix();
+	void shiftMatrixToMatchBestPhase(const int& bestPhaseIndex);
+	void shiftMatrixToMatchBestTempo(const int& bestTempoIndex);
+	int recentPhaseShift, recentTempoShift;
+	bool moveMatrixToOptimalCostPosition;
+	
+	int startPoint;//for drawing
+
+
+	float movementFactor;
+//	static const double tempoMinimumOffset = meanGlobalTempo - (tempoRange-1)/2;
+	
+	bool checkPhaseRange(const int& phaseToCheck);
+	bool checkTempoRange(const int& tempoToCheck);
+
+	double phaseHopCost(const int& phaseHop);
+	double tempoHopCost(const int& tempoHop);
+	
+	double tempoScalar, phaseScalar;
+	int meanTempo;
+	int meanTempoIndex, meanPhaseIndex;
+	
+	int currentBestTempo, currentBestPhase;
+	
+	double getPhase(const int& phaseIndex);
+	double getTempo(const int& tempoIndex);
+	double getTempo(const int& tempoIndex, const int& tempoOffset);
+	double getPhase(const int& phaseIndex, const int& phaseOffset);
+	
+	int getTempoIndex(const double& tempo);
+	int getPhaseIndex(const double& location);
+	
+	double getBestPreviousCost(const int& tempoIndex, const int& phaseIndex, Route& r);
+	//double getlocation(const int& tempoIndex, const int& phaseIndex);
+	void getLocation(const int& tempoIndex, const int& phaseIndex, const int& interval);
+	void drawCostMatrix();
+	double getMaximum();
+	
+	double getMinimumTransitionCost(const int& interval, const int& tempoIndex, const int& phaseIndex);
+	//int getBeatLocation(const int& phaseIndex);
+	//int getProjectedBeatLocation(const int& tempoIndex, const int& phaseIndex, const int& interval);
+	
+	void initialiseRoutes();
+	void printLogMatrix();
+	void printMatrix(DoubleMatrix& logMatrix);
+	
+	void exportTimingData();
+	void importTimingData(std::string importFileName);
+	void exportProcessedBeatTimes(const double& firstBeatTime);
+	
+	bool drawIOIintervals;
+	
+	void calculateTempoLimits();
+	void clearData();
+	
+	int getIndexAtMouseXposition(const int& Xpos);
+	
+	int	minDrawTempo, maxDrawTempo;
+	bool drawBPM;
+	double msToBpm(const double& ms);
+
+	void moveDrawWindowUp();
+	void moveDrawWindowDown();
+	void widenDrawWindow();
+	void narrowDrawWindow();
+	
+	bool blackAndWhite;
+	DoubleVector beatPosition;
+	
+	IntMatrix timingHistogram;
+	void clearHistogram();
+	void getHistogramResults();
+	
+	bool drawExpressiveTimingData;
+	bool mozartTriplets;
+	
+	int tempoVariationStartIndex;
+	int tempoVariationEndIndex;
+	double calculateTempoVariation();
+	
+	ofTrueTypeFont timesFont;//FONT
+	
+	//vars added since new project on Drum Timing
+	double offsetToFirstPoint;//this set at beginning - when we load in beat times that do not start at zero;
+	
+	void zoomIn();
+	void zoomOut();
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DrumTimingLoader_OF/PreciseOnsetLocator.cpp	Sat Nov 23 15:44:47 2013 +0000
@@ -0,0 +1,108 @@
+/*
+ *  PreciseOnsetLocator.cpp
+ *  peakOnsetDetector
+ *
+ *  Created by Andrew on 21/09/2012.
+ *  Copyright 2012 QMUL. All rights reserved.
+ *
+ */
+
+#include "PreciseOnsetLocator.h"
+
+PreciseOnsetLocator::PreciseOnsetLocator(){
+	setup(512);
+}
+
+PreciseOnsetLocator::~PreciseOnsetLocator(){
+	onsetSamples.clear();
+	recentBufferSamples.clear();
+}
+
+
+void PreciseOnsetLocator::setup(const int& size){
+	onsetSamples.clear();
+	recentBufferSamples.clear();
+	bufferSize = size;
+	onsetSamples.assign(bufferSize, 0.0);
+	recentBufferSamples.assign(bufferSize, 0.0);
+}
+
+void PreciseOnsetLocator::storeSamples(double* newSamples){
+	
+	for (int i = 0;i < bufferSize;i++)
+		recentBufferSamples[i] = newSamples[i];
+	
+}
+
+int PreciseOnsetLocator::findExactOnset(double* frame){
+	//store the samples - mainly for viewing actually
+	onsetSamples.clear();
+	for (int i = 0; i < bufferSize;i++) {
+		onsetSamples.push_back(frame[i]);
+	}
+	
+	double energySum = 0;
+	double lastEnergySum, hopsizeLastEnergySum;
+	double energyDifference;
+	int bestEnergyIndex = 0;
+	double bestEnergyDifference = 0;
+	int endIndex = bufferSize;
+	int hopSize;
+	
+	for (int resolution = bufferSize/2;resolution > 1;resolution/=2){
+		printf("resolution %i\n", resolution);
+		
+		bestEnergyDifference = 0;
+		//	printf("previous energy %f", lastEnergySum);
+		//initialise last energySum
+		hopSize = resolution/2;
+		
+		
+		lastEnergySum = getLastEnergySum(bestEnergyIndex, resolution);
+		hopsizeLastEnergySum = getLastEnergySum(bestEnergyIndex + hopSize, resolution);
+		
+		for (int startIndex = bestEnergyIndex;startIndex + resolution <= endIndex;startIndex += hopSize){
+			printf("index %i last energy %f hop energy %f ", startIndex, lastEnergySum, hopsizeLastEnergySum);
+			
+			//sum the energy for this new frame
+			energySum = 0;
+			for (int i = 0;i < resolution;i++){
+				energySum += onsetSamples[startIndex + i] * onsetSamples[startIndex + i];
+			}
+			
+			printf("energysum %f\n", energySum);
+			//check if new max difference
+			energyDifference = energySum - lastEnergySum;
+			if (energyDifference > bestEnergyDifference){
+				bestEnergyDifference = energyDifference;
+				bestEnergyIndex = startIndex;
+			}
+			
+			//store the values for checking in two loops time (because proceeding at resolution/2 each step)
+			//eg 0_to_128 compared to -128_to_0, 64_to_196 compared to -64_to_64, then 128_256 compared with 0_to_128, 
+			lastEnergySum = hopsizeLastEnergySum;// energySum;
+			hopsizeLastEnergySum = energySum;
+			
+		}
+		printf("winning index is %i\n", bestEnergyIndex);
+		endIndex = bestEnergyIndex + resolution;
+		
+	}
+	printf("TOTAL WINNER %i\n", bestEnergyIndex);
+	return bestEnergyIndex;
+	
+}
+
+double PreciseOnsetLocator::getLastEnergySum(const int& startIndex, const int& vectorSize){
+	double lastEnergySum = 0;
+	
+	for (int i = startIndex - vectorSize;i < startIndex;i++){
+		if (i > 0)
+			lastEnergySum += onsetSamples[i] * onsetSamples[i];
+		else {
+			lastEnergySum += recentBufferSamples[bufferSize + i] * recentBufferSamples[bufferSize + i];
+		}
+	}
+	return lastEnergySum;
+	
+}