changeset 2:50ba55abea8c

updating files to newer version
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Sat, 23 Nov 2013 15:49:27 +0000
parents 106bc2d4f702
children 303edbbcf1bd
files DrumTimingLoader_OF/PerformanceAnalyserSrc/TimingAnalyser.cpp DrumTimingLoader_OF/PerformanceAnalyserSrc/TimingAnalyser.h DrumTimingLoader_OF/ofxAudioFileLoader/LoadedAudioHolder.cpp DrumTimingLoader_OF/ofxAudioFileLoader/LoadedAudioHolder.h DrumTimingLoader_OF/ofxAudioFileLoader/ofxSoundFileLoader.cpp DrumTimingLoader_OF/src/DrumTimingLoader.cpp DrumTimingLoader_OF/src/DrumTimingLoader.h DrumTimingLoader_OF/src/RecordedMultipleAudio.cpp DrumTimingLoader_OF/src/RecordedMultipleAudio.h DrumTimingLoader_OF/src/testApp.cpp
diffstat 10 files changed, 287 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/DrumTimingLoader_OF/PerformanceAnalyserSrc/TimingAnalyser.cpp	Sat Nov 23 15:44:47 2013 +0000
+++ b/DrumTimingLoader_OF/PerformanceAnalyserSrc/TimingAnalyser.cpp	Sat Nov 23 15:49:27 2013 +0000
@@ -28,8 +28,9 @@
 
 	moveMatrixToOptimalCostPosition = true;
 	
-	tempoScalar = 2.0;
-	phaseScalar = 2.0;
+	//resolution in ms
+	tempoScalar = 1.0;
+	phaseScalar = 1.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
@@ -204,6 +205,24 @@
 	}
 }
 
+void TimingAnalyser::updatePlayIndex(const double& seconds){
+	double millis = seconds * 1000.0;
+	
+	while (playingIndex < timingData.size() && getNoteTime(playingIndex) < millis)
+		playingIndex++;
+	
+	while (playingIndex > 0 && getNoteTime(playingIndex) > millis)
+		playingIndex--;
+	
+	if (playingIndex > startPoint + numberOfPointsPerPage)
+		startPoint += numberOfPointsPerPage;//scrolling with play
+	
+}
+
+double TimingAnalyser::getNoteTime(const int& index){
+		return offsetToFirstPoint + timingData[index][2];//
+}
+
 void TimingAnalyser::updateCostToPoint(const int& eventTime, const int& eventBeatLocation){
 	
 	//	previousLogMatrix = logProbabilityMatrix;//store previous matrix - settings are in pathHistory vector
@@ -887,8 +906,8 @@
 			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);
+			//if (!blackAndWhite)	
+			ofSetColor(0,0,255);
 			ofLine(((playingIndex)-startPoint) * width, 0, ((playingIndex)-startPoint) * width, screenHeight);
 			
 			}//if not draw IOI
@@ -906,28 +925,26 @@
 	
 }
 
+static const int moveAmount = 2;
 
 void TimingAnalyser::widenDrawWindow(){
-	maxDrawTempo += 2;
-	minDrawTempo -= 2;
+	maxDrawTempo += moveAmount;
+	minDrawTempo -= moveAmount;
 }
 
-
-
-
 void TimingAnalyser::narrowDrawWindow(){
-	maxDrawTempo -= 2;
-	minDrawTempo += 2;
+	maxDrawTempo -= moveAmount;
+	minDrawTempo += moveAmount;
 }
 
 void TimingAnalyser::moveDrawWindowUp(){
-	maxDrawTempo += 2;
-	minDrawTempo += 2;
+	maxDrawTempo += moveAmount;
+	minDrawTempo += moveAmount;
 }
 
 void TimingAnalyser::moveDrawWindowDown(){
-	maxDrawTempo -= 2;
-	minDrawTempo -= 2;
+	maxDrawTempo -= moveAmount;
+	minDrawTempo -= moveAmount;
 }
 
 int TimingAnalyser::getIndexAtMouseXposition(const int& Xpos){
--- a/DrumTimingLoader_OF/PerformanceAnalyserSrc/TimingAnalyser.h	Sat Nov 23 15:44:47 2013 +0000
+++ b/DrumTimingLoader_OF/PerformanceAnalyserSrc/TimingAnalyser.h	Sat Nov 23 15:49:27 2013 +0000
@@ -72,6 +72,8 @@
 	IntMatrix timingData;
 	IntVector basicInterOnsetInterval;
 	
+	void updatePlayIndex(const double& seconds);
+	double getNoteTime(const int& index);
 	
 	void printCostMatrix(const RouteMatrix& m);
 	//NEW COST METHODS:
@@ -170,6 +172,8 @@
 	void importTimingData(std::string importFileName);
 	void exportProcessedBeatTimes(const double& firstBeatTime);
 	
+	
+	
 	bool drawIOIintervals;
 	
 	void calculateTempoLimits();
--- a/DrumTimingLoader_OF/ofxAudioFileLoader/LoadedAudioHolder.cpp	Sat Nov 23 15:44:47 2013 +0000
+++ b/DrumTimingLoader_OF/ofxAudioFileLoader/LoadedAudioHolder.cpp	Sat Nov 23 15:49:27 2013 +0000
@@ -45,9 +45,12 @@
 void LoadedAudioHolder::copyOnsetTimes(){
 
 	onsetTimesMillis.clear();
+	onsetTimesFrames.clear();
 	
-	for (int i = 0;i < fileLoader.onsetDetect.chromaOnsets.size();i++)
+	for (int i = 0;i < fileLoader.onsetDetect.chromaOnsets.size();i++){
 		onsetTimesMillis.push_back(fileLoader.onsetDetect.chromaOnsets[i].millisTime);
+		onsetTimesFrames.push_back(fileLoader.onsetDetect.chromaOnsets[i].frameTime);
+	}
 	
 }
 
--- a/DrumTimingLoader_OF/ofxAudioFileLoader/LoadedAudioHolder.h	Sat Nov 23 15:44:47 2013 +0000
+++ b/DrumTimingLoader_OF/ofxAudioFileLoader/LoadedAudioHolder.h	Sat Nov 23 15:49:27 2013 +0000
@@ -50,7 +50,11 @@
 	void setTrackType(const int& type);
 	
 	typedef vector<double> DoubleVector;
-	DoubleVector onsetTimesMillis;
+	DoubleVector onsetTimesMillis;//onset times as measured by the chroma-onset detector
+	
+	typedef vector<int> IntVector;
+	IntVector onsetTimesFrames;
+	
 	void copyOnsetTimes();
 	
 private:
--- a/DrumTimingLoader_OF/ofxAudioFileLoader/ofxSoundFileLoader.cpp	Sat Nov 23 15:44:47 2013 +0000
+++ b/DrumTimingLoader_OF/ofxAudioFileLoader/ofxSoundFileLoader.cpp	Sat Nov 23 15:49:27 2013 +0000
@@ -27,8 +27,9 @@
 }
 
 void ofxSoundFileLoader::updateToAudioPosition(const float& audioPosition){
-	
-	audioHolder.playPosition = audioPosition * audioHolder.audioVector.size();
+	//updates info on file as it plays
+	audioHolder.playPosition = audioPosition * audioHolder.length;//size();
+	//printf("update pos %f size %i\n", audioHolder.playPosition, (int)audioHolder.audioVector.size());
 	onsetDetect.playPosition = audioPosition;
 }
 
--- a/DrumTimingLoader_OF/src/DrumTimingLoader.cpp	Sat Nov 23 15:44:47 2013 +0000
+++ b/DrumTimingLoader_OF/src/DrumTimingLoader.cpp	Sat Nov 23 15:49:27 2013 +0000
@@ -18,15 +18,19 @@
 	
 	recordedTracks.loadTestAudio();
 	/*
-	calculateRecordedTempoData();
-	printf("\n audioeventmatcher\nFIRST PASS: FINAL recorded tempo is %f\n", recordedTempoData.playingTempo);
-	setTempoPrior(recordedTempoData.playingTempo);
-	calculateRecordedTempoData();//now calculate again using better prior
+		calculateRecordedTempoData();
+		printf("\n audioeventmatcher\nFIRST PASS: FINAL recorded tempo is %f\n", recordedTempoData.playingTempo);
+		setTempoPrior(recordedTempoData.playingTempo);
+		calculateRecordedTempoData();//now calculate again using better prior
+		
+		printf("\n audioeventmatcher\nSECOND PASS: FINAL recorded tempo is %f\n", recordedTempoData.playingTempo);
+		printf("GLOBAL TEMPO of RECORDED FILES\n");
+	*/
 	
-	printf("\n audioeventmatcher\nSECOND PASS: FINAL recorded tempo is %f\n", recordedTempoData.playingTempo);
-	printf("GLOBAL TEMPO of RECORDED FILES\n");
-	*/ 
-	
+}
+
+void DrumTimingLoader::update(){
+	recordedTracks.updatePosition();
 }
 
 
@@ -37,6 +41,9 @@
 		recordedTracks.drawTracks();
 	else 
 		recordedTracks.drumTimingAnalyser.drawTempoCurve();
+	
+	ofSetColor(0);
+	ofDrawBitmapString("play pos sec: "+ofToString(recordedTracks.playPositionSeconds, 2), 20, 20);
 }
 
 void DrumTimingLoader::windowResized(int w, int h){
--- a/DrumTimingLoader_OF/src/DrumTimingLoader.h	Sat Nov 23 15:44:47 2013 +0000
+++ b/DrumTimingLoader_OF/src/DrumTimingLoader.h	Sat Nov 23 15:49:27 2013 +0000
@@ -17,12 +17,15 @@
 #include <fstream>
 using namespace std;
 
+//just stores recordedTracks
+
 
 class DrumTimingLoader{
 	
 	public:
 		DrumTimingLoader();
 		void initialise();
+		void update();
 		void draw();
 	void windowResized(int w, int h);
 	RecordedMultipleAudio recordedTracks;
--- a/DrumTimingLoader_OF/src/RecordedMultipleAudio.cpp	Sat Nov 23 15:44:47 2013 +0000
+++ b/DrumTimingLoader_OF/src/RecordedMultipleAudio.cpp	Sat Nov 23 15:49:27 2013 +0000
@@ -1,6 +1,6 @@
 /*
  *  RecordedMultipleAudio.cpp
- *  MultipleAudioMathcher
+ *  Drum Timing Analyser
  *
  *  Created by Andrew on 31/01/2012.
  *  Copyright 2012 QMUL. All rights reserved.
@@ -9,26 +9,42 @@
 
 #include "RecordedMultipleAudio.h"
 
+const bool printExportInfo = false;
+
 RecordedMultipleAudio::RecordedMultipleAudio(){
 	
 	infoFilepath = "../../../data/errorData.txt";
+	
+	exactOnsetFilePath = "../../../data/exactOnsetTimes.txt";
+	kickRelativeTempoFilePath = "../../../data/kickRelativeTempoTimes.txt";
+	kickRelativeErrorsFilePath = "../../../data/kickRelativeErrorTimes.txt";	
+	kickRelativeClickFilePath = "../../../data/kickRelativeClickTimes.txt";
+	
+	drumTimerTempoFilePath = "../../../data/drummerTimerTempoTimes.txt";
+	drumTimerErrorsFilePath = "../../../data/drummerTimerErrorTimes.txt";
+	drumTimerClickFilePath = "../../../data/drummerTimerClickTimes.txt";
+	
 	//infoFilepath = "/Users/andrew/errorData.txt";
 	
 	timingOffset = 0;
+	playPositionSeconds = 3.4;
 }
 
 void RecordedMultipleAudio::loadTestAudio(){
 
+	int multitrackToLoad = 7;
 
 	numberOfAudioTracks = 2;
 	
 	printf("loaded max val  is %f\n", loadedAudioFiles[0].fileLoader.onsetDetect.onsetDetector.maximumDetectionValue);
 	
-	int multitrackToLoad = 5;
+
+	
 	setDifferentMultitracks(multitrackToLoad);//command to load this set of audio files - see below
 
 	drumTimingAnalyser.phaseCost = 1000;//v high - i.e. dont do phase 
 	
+	
 	drawWindow = 1;
 	trackScreenHeight = 0.25;
 	
@@ -82,35 +98,71 @@
 			sonicVizBeatsFilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeOne_4/PennyArcade_take4_beats.txt";
 			break;	
 			
+		/*	
 		case 5:
 			roomfilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/neuamnn_bip.wav";
 			kickfilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/kick_bip.wav";
 			snarefilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/snare_bip.wav";
 			sonicVizBeatsFilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/PennyArcade_take5_beats.txt";
 			break;	
+		*/	
+		case 5:
+			roomfilename = "/Volumes/MiniSaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/neuamnn_bip.wav";
+			kickfilename = "/Volumes/MiniSaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/kick_bip.wav";
+			snarefilename = "/Volumes/MiniSaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/snare_bip.wav";
+			sonicVizBeatsFilename = "/Volumes/MiniSaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/PennyArcade_take5_beats.txt";
+			break;		
 			
 			
+		case 6:
+			roomfilename = "/Users/andrew/Documents/work/Alignment/FunkyDrummerAnalysis/FunkyDrummerBreak.wav";
+			kickfilename = "/Users/andrew/Documents/work/Alignment/FunkyDrummerAnalysis/FunkyDrummerBreak.wav";
+			snarefilename = "/Users/andrew/Documents/work/Alignment/FunkyDrummerAnalysis/FunkyDrummerBreak.wav";
+			sonicVizBeatsFilename = "/Users/andrew/Documents/work/Alignment/FunkyDrummerAnalysis/FunkyDrummerBeats.txt";
+			break;		
+			
+		case 7:
+			roomfilename = "/Users/andrew/Music/Logic/Tractors_April13/tractorIsaak2/Bounces/Take23_mono.wav";
+			kickfilename = "/Users/andrew/Music/Logic/Tractors_April13/tractorIsaak2/Bounces/Take23_mono.wav";
+			snarefilename = "/Users/andrew/Music/Logic/Tractors_April13/tractorIsaak2/Bounces/Take23_mono.wav";
+			sonicVizBeatsFilename = "/Users/andrew/Music/Logic/Tractors_April13/tractorIsaak2/Bounces/IsaakTake23MonoBeats.txt";
+			break;		
+			
 			
 	}
 	if (kickfilename != NULL){
-		
+		printf("Loading Kick file: %s\n", kickfilename);
 		loadAudioTrack(kickfilename, 0);
 	}
 	
 	if (roomfilename != NULL){	
-		printf("roomfilename: %s\n", roomfilename);
+		printf("loading room: %s\n", roomfilename);
 		loadAudioTrack(roomfilename, 1);
 	}
 	
-	if (snarefilename != NULL)
+	if (snarefilename != NULL){
+		printf("Loading Snare file: %s\n", kickfilename);
 		loadAudioTrack(snarefilename, 2);
+	}
 	
 	if (sonicVizBeatsFilename.c_str() != NULL){
+		printf("Reading sonic viz beats: %s\n", sonicVizBeatsFilename.c_str());
 		readInBeatsFile(sonicVizBeatsFilename);
 		printBeatTimes();
 		checkFileErrors(0);
 		checkFileErrors(2);
 		findBeatOnsets();
+		
+		exportErrorInformation();
+		exportExactOnsetTimes();
+		
+		exportKickRelativeTempoTimes();
+		exportKickRelativeErrorTimes();
+		exportKickRelativeClickTimes();
+		
+		exportDrumTimerTempoTimes();
+		exportDrumTimerErrorTimes();
+		exportDrumTimerClickTimes();
 	}
 }
 
@@ -177,7 +229,7 @@
 		
 	}//end while
 	
-	//	printBeatTimes();
+		
 	printf("There are %i BEAT annotations\n", (int)beatTimes.size());
 	
 }
@@ -191,8 +243,11 @@
 
 void RecordedMultipleAudio::checkFileErrors(int channel){
 	int beatIndex = 0;
-	int cutoff = 50;//ms width to check
+	int cutoff = 60;//ms width to check
 	for (int i = 0;i < loadedAudioFiles[channel].onsetTimesMillis.size();i++){
+		
+		printf("onset time %i ms %i frames ", (int)loadedAudioFiles[channel].onsetTimesMillis[i], (int)loadedAudioFiles[channel].onsetTimesFrames[i]);
+		
 		while (beatIndex < beatTimes.size() && 1000.0*beatTimes[beatIndex] < loadedAudioFiles[channel].onsetTimesMillis[i] - cutoff) {
 			beatIndex++;
 		}
@@ -205,9 +260,9 @@
 			
 		}else{
 			if (channel == 0) 
-				printf("Out of Beat: Kick Time %f beat error %f\n", 1000.0*beatTimes[beatIndex], loadedAudioFiles[0].onsetTimesMillis[i], error);
+				printf("Ch.0 Out of Beat: Kick Time %f beat error %f\n", 1000.0*beatTimes[beatIndex], loadedAudioFiles[0].onsetTimesMillis[i], error);
 			else 
-				printf("Out of Beat: %f Snare Time %f best error %f\n", 1000.0*beatTimes[beatIndex], loadedAudioFiles[0].onsetTimesMillis[i], error);
+				printf("Ch.2 Out of Beat: %f Snare Time %f best error %f\n", 1000.0*beatTimes[beatIndex], loadedAudioFiles[0].onsetTimesMillis[i], error);
 			
 		}
 	}
@@ -235,6 +290,7 @@
 		double newBeatTime = beatTimes[k]*1000.0;
 		int beatPosition = k % 4;
 		OnsetInformation information;
+		double bestBeatDifference = 1000;//i.e. high
 		switch (beatPosition) {
 			case 0: case 2://check for kick when it is on the `one' or 'three' (0 or 2 in our metrical position)
 			//	printf("check %i kindex %i\n", beatPosition, kickIndex);
@@ -242,14 +298,15 @@
 					kickIndex++;
 					kickTime = loadedAudioFiles[0].onsetTimesMillis[kickIndex];
 			//		printf("checking beat[%i] %f kick %f error %f\n", k, beatTimes[k]*1000.0, kickTime, (kickTime - beatTimes[k]*1000.0));
-					if (fabs(kickTime - beatTimes[k]*1000.0) < cutoff){
+					if (fabs(kickTime - beatTimes[k]*1000.0) < cutoff && fabs(kickTime - beatTimes[k]*1000.0) < bestBeatDifference){
 						beatFound = true;
-						printf("beat[%i] %f kick %f error %f\n", k, beatTimes[k]*1000.0, kickTime, (kickTime - beatTimes[k]*1000.0));
+						printf("beat[%i] pos %i time %f kick %f error %f\n", k, beatPosition, beatTimes[k]*1000.0, kickTime, (kickTime - beatTimes[k]*1000.0));
 
 						information.error = (kickTime - beatTimes[k]*1000.0);//FOR NOW ONLY
 						information.metricalPosition = beatPosition;
 						information.type = 0;	
 						information.exactOnsetTime = kickTime;
+						bestBeatDifference = fabs(kickTime - beatTimes[k]*1000.0);
 			//			exactBeatPositions.push_back(kickTime);
 					}
 				}
@@ -259,14 +316,15 @@
 				while (snareIndex < loadedAudioFiles[1].onsetTimesMillis.size() && loadedAudioFiles[1].onsetTimesMillis[snareIndex] < newBeatTime - cutoff ){
 					snareIndex++;
 					snareTime = loadedAudioFiles[1].onsetTimesMillis[snareIndex];
-					if (fabs(snareTime - beatTimes[k]*1000.0) < cutoff){
+					if (fabs(snareTime - beatTimes[k]*1000.0) < cutoff && fabs(snareTime - beatTimes[k]*1000.0) < bestBeatDifference){
 						beatFound = true;
 					//	snareErrors.push_back((beatTimes[k]*1000.0 - snareTime));
 						information.error = (snareTime - beatTimes[k]*1000.0);
 						information.metricalPosition = beatPosition;//.push_back(beatPosition);
 						information.type = 1;
 						information.exactOnsetTime = snareTime;
-						printf("beat[%i] %f snare %f error %f\n", k, beatTimes[k]*1000.0, snareTime, (snareTime - beatTimes[k]*1000.0));
+						bestBeatDifference = fabs(snareTime - beatTimes[k]*1000.0);
+						printf("beat[%i] pos %i tim e%f snare %f error %f\n", k, beatPosition, beatTimes[k]*1000.0, snareTime, (snareTime - beatTimes[k]*1000.0));
 			//			exactBeatPositions.push_back(snareTime);
 					}
 				}
@@ -290,6 +348,9 @@
 	
 	calculateTimingAnalysis();
 	
+	
+	//so our exact beat times are then information.exactOnsetTime
+	
 }
 
 #pragma mark -doTimingAnalysis
@@ -320,8 +381,6 @@
 	
 	alternativeKickRelativeAnalysis();
 	
-	exportErrorInformation();
-	
 	displayKickRelativeMedianErrors();//NB messes ther order of these
 	
 	//this was how we did it in multimatch program
@@ -339,7 +398,8 @@
 		onsetInfo[i].error = drumTimingAnalyser.timingData[i][5];
 		onsetInfo[i].clickTime = drumTimingAnalyser.timingData[i][1] + timingOffset;//this is where teh timing analyser placed the click times
 		errorsByMetricalPosition[onsetInfo[i].metricalPosition].push_back(onsetInfo[i].error);
-		printf("beat %i metrical posn %i exact beat time %f error %i\n", i, onsetInfo[i].metricalPosition, onsetInfo[i].exactOnsetTime, (int)onsetInfo[i].error);
+		printf("beat %i metrical posn %i exact onset time %f click time %i error %i\n", i, onsetInfo[i].metricalPosition, onsetInfo[i].exactOnsetTime, 
+			   onsetInfo[i].clickTime, (int)onsetInfo[i].error);
 	}
 	displayMedianErrors();
 }
@@ -352,23 +412,25 @@
 	double recentBeatTime, currentTempo;	
 	kickRelativeErrors.clear();
 	kickRelativeClickTimes.clear();
+	kickRelativeTempo.clear();
 	
 	for (int i = 0;i < drumTimingAnalyser.timingData.size();i++){
 		int beatPosition = i%4;
-		if (beatPosition == 0){
+		if (beatPosition == 0){//then divide kicks and get even division
 			recentBeatTime = onsetInfo[i].exactOnsetTime;
 			if (i+4 < onsetInfo.size())
 				currentTempo =  (onsetInfo[i+4].exactOnsetTime - onsetInfo[i].exactOnsetTime)/4.0;
 			printf("new beat time %f tempo %f\n", recentBeatTime, currentTempo);
 		}
 		double error = onsetInfo[i].exactOnsetTime - (recentBeatTime + beatPosition*currentTempo);
-		printf("Beat %i KR Predicted Beat %f Actual exact %f KRerror %f DTerror %i\n", beatPosition, (recentBeatTime + beatPosition*currentTempo), onsetInfo[i].exactOnsetTime, error, (int)onsetInfo[i].error); 
+		printf("Beat %i KR Predicted Beat: %f Onset: %f KRerror %f DTerror %i\n", beatPosition, (recentBeatTime + beatPosition*currentTempo), onsetInfo[i].exactOnsetTime, error, (int)onsetInfo[i].error); 
 		kickRelativeErrors.push_back(error);
 		kickRelativeClickTimes.push_back(recentBeatTime + beatPosition*currentTempo);
+		kickRelativeTempo.push_back(currentTempo);
 	}
 }
 
-#pragma label -exportInfo
+#pragma mark -exportInfo
 void RecordedMultipleAudio::exportErrorInformation(){
 	printf("Export final timing information\n");
 	
@@ -382,6 +444,93 @@
 	
 }
 
+
+void RecordedMultipleAudio::exportExactOnsetTimes(){
+	printf("Export exact beat times\n");
+	
+	ofstream ofs(exactOnsetFilePath.c_str());
+	for (int i = 0;i < onsetInfo.size();i++){// drumTimingAnalyser.timingData.size()
+		ofs << onsetInfo[i].exactOnsetTime/1000.0 << endl;
+		if (printExportInfo)
+			printf("exporting exact beat times %f\n", onsetInfo[i].exactOnsetTime);
+	}
+}
+
+void RecordedMultipleAudio::exportKickRelativeTempoTimes(){
+	printf("Export kick relative Tempo times\n");
+	
+	ofstream ofs(kickRelativeTempoFilePath.c_str());
+	for (int i = 0;i < kickRelativeTempo.size() && i < onsetInfo.size();i++){
+		ofs << onsetInfo[i].exactOnsetTime << "\t" << kickRelativeTempo[i] << endl;
+		if (printExportInfo)
+			printf("exporting tempo[%i]: onset %f %f\n", i, onsetInfo[i].exactOnsetTime, kickRelativeTempo[i]);
+	}	
+}
+
+void RecordedMultipleAudio::exportKickRelativeErrorTimes(){
+	printf("Export kick relative Error times\n");
+	
+	ofstream ofs(kickRelativeErrorsFilePath.c_str());
+	for (int i = 0;i < kickRelativeErrors.size() && i < onsetInfo.size();i++){
+		ofs << onsetInfo[i].exactOnsetTime << "\t" << kickRelativeErrors[i] << endl;
+		if (printExportInfo)
+			printf("exporting tempo[%i]: onset %f %f\n", i, onsetInfo[i].exactOnsetTime, kickRelativeErrors[i]);
+	}	
+}
+
+void RecordedMultipleAudio::exportKickRelativeClickTimes(){
+	printf("Export kick relative click times\n");
+	
+	ofstream ofs(kickRelativeClickFilePath.c_str());
+	for (int i = 0;i < kickRelativeClickTimes.size();i++){
+		ofs << kickRelativeClickTimes[i]/1000.0 << endl;
+		if (printExportInfo)
+			printf("exporting KD click [%i]:%f\n", i,kickRelativeClickTimes[i]);
+	}	
+}
+
+
+void RecordedMultipleAudio::exportDrumTimerTempoTimes(){
+	printf("Export drum timing tempo times\n");
+	
+	ofstream ofs(drumTimerTempoFilePath.c_str());
+	for (int i = 0;i < drumTimingAnalyser.timingData.size() && i < onsetInfo.size();i++){
+		ofs << onsetInfo[i].exactOnsetTime << "\t" << drumTimingAnalyser.timingData[i][0] << endl;
+		if (printExportInfo)
+			printf("exporting tempo[%i]: onset %f tempo %i\n", i, onsetInfo[i].exactOnsetTime, drumTimingAnalyser.timingData[i][0]);
+	}	
+}
+
+
+void RecordedMultipleAudio::exportDrumTimerErrorTimes(){
+	printf("Export drum timing Error times\n");
+	
+	ofstream ofs(drumTimerErrorsFilePath.c_str());
+	for (int i = 0;i < drumTimingAnalyser.timingData.size() && i < onsetInfo.size();i++){
+		ofs << onsetInfo[i].exactOnsetTime << "\t" << drumTimingAnalyser.timingData[i][5] << endl;
+		if (printExportInfo)
+			printf("exporting [%i]: onset %f error %i\n", i, onsetInfo[i].exactOnsetTime, drumTimingAnalyser.timingData[i][5]);
+	}	
+}
+
+
+void RecordedMultipleAudio::exportDrumTimerClickTimes(){
+	printf("Export drum timing Click times\n");
+	
+	ofstream ofs(drumTimerClickFilePath.c_str());
+	for (int i = 0;i < onsetInfo.size();i++){
+		ofs << onsetInfo[i].clickTime/1000.0 << endl;
+		if (printExportInfo)
+			printf("exporting click[%i] %i\n", i, onsetInfo[i].clickTime);
+	}	
+}
+
+
+
+
+
+
+
 void RecordedMultipleAudio::printKickRelativeErrors(){
 	for (int i = 0;i < kickRelativeErrors.size();i++){
 	printf("KR error [%i] : %.1f\n", i, kickRelativeErrors[i]);
@@ -456,12 +605,23 @@
 	} else {
 		drumTimingAnalyser.drawTempoCurve();
 	}
+	
+//	ofDrawBitmapString(ofToString(playPositionSeconds),20, 40);
 }
 
 #pragma mark -update 
 void RecordedMultipleAudio::updatePosition(){
 	for (int i = 0;i < numberOfAudioTracks;i++)
 		loadedAudioFiles[i].updateToPlayPosition();
+	
+	playPositionSeconds = samplesToSeconds(loadedAudioFiles[0].fileLoader.audioHolder.playPosition);
+	drumTimingAnalyser.updatePlayIndex(playPositionSeconds);
+	
+	
+}
+
+double RecordedMultipleAudio::samplesToSeconds(const double& samples){
+	return samples/44100.0;
 }
 
 void RecordedMultipleAudio::updatePositionToMillis(const double& millis){
@@ -474,12 +634,6 @@
 		loadedAudioFiles[i].updatePlaybackPositionToMillis(millis);
 }
 
-void RecordedMultipleAudio::switchScreens(){
-	for (int i = 0;i < numberOfAudioTracks;i++)
-		loadedAudioFiles[i].switchScreens();
-}
-
-
 void RecordedMultipleAudio::togglePlay(){
 	for (int i = 0;i < numberOfAudioTracks;i++)
 		loadedAudioFiles[i].togglePlay();
@@ -496,6 +650,7 @@
 	loadedAudioFiles[0].printEvents();
 }
 
+#pragma mark -ScreenFunctions
 void RecordedMultipleAudio::windowResized(const int& w, const int& h){
 	for (int i = 0;i < numberOfAudioTracks;i++)
 		loadedAudioFiles[i].windowResized(w, h);
@@ -522,4 +677,8 @@
 	
 }
 
+void RecordedMultipleAudio::switchScreens(){
+	for (int i = 0;i < numberOfAudioTracks;i++)
+		loadedAudioFiles[i].switchScreens();
+}
 
--- a/DrumTimingLoader_OF/src/RecordedMultipleAudio.h	Sat Nov 23 15:44:47 2013 +0000
+++ b/DrumTimingLoader_OF/src/RecordedMultipleAudio.h	Sat Nov 23 15:49:27 2013 +0000
@@ -25,7 +25,7 @@
 	int metricalPosition;
 	double exactOnsetTime;
 	double beatTimeToProcess;
-	double clickTime;//from the Timing Analyser
+	int clickTime;//from the Timing Analyser
 	int type;//0 for kick, 1 for snare
 };
 
@@ -95,11 +95,31 @@
 	//these should go into
 	
 	DoubleVector kickRelativeErrors;
+	DoubleVector kickRelativeTempo;
 	void printKickRelativeErrors();
 	void alternativeKickRelativeAnalysis();
 	DoubleVector kickRelativeClickTimes;
-	std::string infoFilepath;
+	std::string infoFilepath, exactOnsetFilePath;
+	std::string kickRelativeTempoFilePath, kickRelativeErrorsFilePath;
 	void exportErrorInformation();
+	void exportExactOnsetTimes();
+	
+	//exporting from the kick dividing method - i.e. kicks on the one
+	void exportKickRelativeTempoTimes();
+	void exportKickRelativeErrorTimes();
+	void exportKickRelativeClickTimes();
+	
+	std::string drumTimerTempoFilePath, drumTimerErrorsFilePath;
+	std::string drumTimerClickFilePath, kickRelativeClickFilePath;
+	
+	//exporting from the drum timng analyser - ismir 2012 method
+	void exportDrumTimerErrorTimes();
+	void exportDrumTimerTempoTimes();
+	void exportDrumTimerClickTimes();
+	
 	void displayKickRelativeMedianErrors();
+	
+	double samplesToSeconds(const double& samples);
+	double playPositionSeconds;
 };
 #endif
\ No newline at end of file
--- a/DrumTimingLoader_OF/src/testApp.cpp	Sat Nov 23 15:44:47 2013 +0000
+++ b/DrumTimingLoader_OF/src/testApp.cpp	Sat Nov 23 15:49:27 2013 +0000
@@ -7,7 +7,7 @@
 
 //--------------------------------------------------------------
 void testApp::update(){
-
+	drumTimer.update();//recordedTracks.updatePosition();
 }
 
 //--------------------------------------------------------------
@@ -27,7 +27,21 @@
 	if (key == OF_KEY_DOWN){
 		drumTimer.recordedTracks.zoomIn();
 	}
+
+	if (key == OF_KEY_RIGHT){
+		drumTimer.recordedTracks.drumTimingAnalyser.widenDrawWindow();
+		
+	}
 	
+	if (key == OF_KEY_LEFT){
+		drumTimer.recordedTracks.drumTimingAnalyser.narrowDrawWindow();
+	}
+	
+
+	if (key == ' '){
+		drumTimer.recordedTracks.togglePlay();
+	}
+			
 }
 
 //--------------------------------------------------------------