view src/testApp.cpp @ 0:572c856e38ac

Starting up openFrameworks project for audio time warping. The ofxFileReader goes in addons of your OF folder, the libraries and source (chromogram, fftw and source code src+ timewarp) are probably best kept in the repository, then dragged into the project afresh. That way, as we update the repository, the code that the openFrameworks project looks for will be updated.
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Tue, 17 May 2011 08:48:58 +0100
parents
children 6842ff391568
line wrap: on
line source
#include "testApp.h"
#include "stdio.h"
#include "aubio.h"
#include <iostream>
#include <cstring>
#include <string>
#include <cstdlib> 

//FIX CHORDS IN THE NEW POINTER VERSION OF THE PROCESS AUDIO FN

//BUG IN WHETHER SECOND SONG LOADED OR NOT


//CHECK THAT DTW will not call beyond the limits of the two chroma if different sizes

//CALC DTW on different sizes

//CHECK CORRECT BEST ALIGNMENT METHOD FOR DTW

//RE-DO DRAW SO THAT IT DOES NOT CALCULATE EVERY POINT BUT DOES IN SQUARE CHUNKS	

//UPDATE START FRAME SO ALIGNMENT IS ALWAYS ON SCREEN
//--------------------------------------------------------------
void testApp::setup(){

	ofBackground(255,255,255);

	// 2 output channels,
	// 0 input channels
	// 22050 samples per second
	// 256 samples per buffer
	// 4 num buffers (latency)
	

//	ofSetDataPathRoot("../bin/data/");

//DONT NEED ANY OF THIS
	sampleRate 			= 44100;
	phase 				= 0;
	phaseAdder 			= 0.0f;
	phaseAdderTarget 	= 0.0f;
	volume				= 0.1f;
	bNoise 				= false;
	lAudio = new float[256];
	rAudio = new float[256];
	ofSoundStreamSetup(2,0,this, sampleRate,256, 4);
//UNTIL HERE
	
	
	ofSetFrameRate(60);
	
	
	fvec_t * my_fvec_t;
	aubio_onset_t* my_aubio_result;
	aubio_onsetdetection_t * my_onset_detection;
	
	scrollWidth = 1600;
	chromoLength = scrollWidth/CHROMA_CONVERSION_FACTOR;

	
	sfinfo.format = 0;
	
	moveOn = true;

	//loading audio files
	loadSoundFiles();			
	
	loadFirstAudioFile();
	
	secondFileName = "../../../data/sound/1-01BachBWV 846_v2.wav";

	loadSecondAudio(secondFileName);//i.e. load same as first file
	
	backwardsAlignmentIndex = 0;//remember that this goes backwards!

	tw.initialiseVariables();
	tw.calculateSimilarityMatrix();	
	tw.calculateAlignmentMatrix();
	tw.calculateMinimumAlignmentPath();
	printf("\n gettem hereafter!");	
	//set not to play
	audioPlaying = false;

	drawSecondMatrix = false;
	drawSpectralDifferenceFunction = false;
	drawSimilarity = true;

	screenHeight = ofGetHeight() ;
	screenWidth = ofGetWidth();
	
	diagonalPenalty = 2;//penalises diagonal so all path gradients equal weighting
	
	initialiseVariables();
	
	
}


void testApp::initialiseVariables(){
	
	frameIndex = 0;
	chromaIndex = 0;
//	chromoGramm.initialise(FRAMESIZE,2048);//framesize 512 and hopsize 2048
	audioPosition = 0;
	
	backwardsAlignmentIndex = tw.backwardsAlignmentPath[0].size()-1;//go back to beginning for drawing
	numberOfScrollWidthsForFirstFile = 0;
	numberOfScrollWidthsForSecondFile = 0;
	
	(*playingAudio).setPaused(true);	
	audioPlaying = false;
	audioPaused = true;
	
	tw.initialiseVariables();
}


//--------------------------------------------------------------
void testApp::update(){
	textString = "energy index [";
	textString += ofToString(xIndex);
	textString += "] = ";
	textString += ofToString(energy[xIndex]);
	
	chordString = "Chord : ";
	chordString += ofToString(rootChord[currentPlayingFrame/CHROMA_CONVERSION_FACTOR]);
	
	if (firstAudioFilePlaying){
	audioPosition = (*playingAudio).getPosition() * tw.firstEnergyVector.size();
		updateAlignmentPathIndex(0);
	}
	else {
	audioPosition = (*playingAudio).getPosition() * tw.secondEnergyVector.size();	
		updateAlignmentPathIndex(1);
	}
	
	//if(!audioPaused)
	//printScoreForRow(audioPosition/CHROMA_CONVERSION_FACTOR, (audioPosition/CHROMA_CONVERSION_FACTOR)+10);
	
	//the position in number of frames
	//totalNumberOfFrames was used but is the most recently loaded file length
	
	currentPlayingFrame = audioPosition;
	audioPosition = (int) audioPosition % scrollWidth ;
	audioPosition /= scrollWidth;
	
	ofSoundUpdate();
	
	
}

void testApp::updateAlignmentPathIndex(int identifier){
	
	int chromaPosition = audioPosition/CHROMA_CONVERSION_FACTOR;
	
	while (tw.backwardsAlignmentPath[identifier][backwardsAlignmentIndex] < chromaPosition)
	{
		backwardsAlignmentIndex--;
	}
	
}

//--------------------------------------------------------------
void testApp::draw(){

	if (drawSimilarity)
		drawSimilarityMatrix();
	else
	drawChromoGram();

		
}


void testApp::drawEnergyVectorFromPointer(DoubleVector* energyVec){
	
	float screenHeight = ofGetHeight() ;
	float screenWidth = ofGetWidth();  
	float heightFactor = 8;
	int i, j, startingFrame;
	startingFrame = currentPlayingFrame / scrollWidth;//i.e. number of scroll widths in
	startingFrame *= scrollWidth;
	
	for (i = 0; i < scrollWidth - 1; i++){
		j = i + startingFrame;
		ofLine(i*screenWidth/scrollWidth, screenHeight - ((*energyVec)[j]*screenHeight/heightFactor),
			   screenWidth*(i+1)/scrollWidth, screenHeight - ((*energyVec)[j+1]*screenHeight/heightFactor));
		
	}
}

void testApp::drawSpectralDifference(DoubleMatrix* dMatrix){
	if ((*dMatrix).size()>0){
		
	float screenHeight = ofGetHeight() ;
	float screenWidth = ofGetWidth();
	float heightFactor = 8;
	double difference;
	int i, j, startingFrame;
	startingFrame = currentPlayingFrame / scrollWidth;//i.e. number of scroll widths in
	startingFrame *= scrollWidth;//starting frame in terms of energy frames
	startingFrame /= CHROMA_CONVERSION_FACTOR; //in terms of chroma frames
	
	
	for (i = 1; i < chromoLength; i++){//changed to add 1
		j = i + startingFrame;
		for (int y = 0;y < 12;y++){			
			difference = (*dMatrix)[j][11-y] - (*dMatrix)[j-1][11-y];
				if (difference < 0)
					difference = 0;//half wave rectify
			
			ofSetColor(0,0,255 * difference);//, 0;
			ofRect(i*screenWidth/chromoLength,y*screenHeight/12,screenWidth/chromoLength,screenHeight/12);
		}//end y
	}//end i
		
	}///end if matrix has content
	else{
		printf("Error - please load audio first");
	}
	
}


void testApp::drawChromoGram(){
	
	DoubleMatrix* dptr;
	DoubleVector* eptr;
	string whichFileString;
	
	if (drawSecondMatrix){
		
		dptr = &tw.secondMatrix;
		eptr = &tw.secondEnergyVector;

		whichFileString = "second file";
		
	}else {
		
		dptr = &tw.chromaMatrix;
		eptr = &tw.firstEnergyVector;
		whichFileString = "first file";
	}
	
	
	
	if (drawSpectralDifferenceFunction)
		drawSpectralDifference(dptr);
	else
		drawDoubleMatrix(dptr);
	
	ofSetColor(0xFF6666);
	drawEnergyVectorFromPointer(eptr);
	
	ofDrawBitmapString(textString,80,480);
	
	
	ofSetColor(0xFFFFFF);
	ofLine(audioPosition*width, 0, audioPosition*width, height);
	
	 
	ofDrawBitmapString(chordString,80,580);
	
	ofDrawBitmapString(soundFileName,80,480);
	
	ofDrawBitmapString(whichFileString,80,80);

}

void testApp::drawDoubleMatrix(DoubleMatrix* dMatrix){
	if ((*dMatrix).size()>0){
			
	float screenHeight = ofGetHeight() ;
	float screenWidth = ofGetWidth();
	float heightFactor = 8;
	int i, j, startingFrame;
	startingFrame = currentPlayingFrame / scrollWidth;//i.e. number of scroll widths in
	startingFrame *= scrollWidth;//starting frame in terms of energy frames
	startingFrame /= CHROMA_CONVERSION_FACTOR; //in terms of chroma frames
	
	float chromoLength = scrollWidth/CHROMA_CONVERSION_FACTOR;
	for (i = 0; i < chromoLength; i++){
		j = i + startingFrame;
		for (int y = 0;y < 12;y++){
			ofSetColor(0,0,255 * (*dMatrix)[j][11-y]);//, 0;
			ofRect(i*screenWidth/chromoLength,y*screenHeight/12,screenWidth/chromoLength,screenHeight/12);
		}//end y
	}//end i
	
	}///end if matrix has content
	else{
		printf("Error - please load audio first");
	}
	
	
}


void testApp::drawSimilarityMatrix(){

	int simHeight = (tw.similarityMatrix[0]).size();
	int simWidth = tw.similarityMatrix.size();
	
	int sizeOfMatrix = tw.chromaMatrix.size();
	int sizeOfSecondMatrix = tw.secondMatrix.size();
	
	int startingXframe = tw.backwardsAlignmentPath[0][backwardsAlignmentIndex] / (scrollWidth/CHROMA_CONVERSION_FACTOR);
	int startingYframe = tw.backwardsAlignmentPath[1][backwardsAlignmentIndex] / (scrollWidth/CHROMA_CONVERSION_FACTOR);
	
	int startingFrame = findStartWidthFrame();
	startingFrame = numberOfScrollWidthsForFirstFile * scrollWidth/CHROMA_CONVERSION_FACTOR;
	
	startingXframe = startingXframe * scrollWidth/CHROMA_CONVERSION_FACTOR;
	startingYframe = startingYframe * scrollWidth/CHROMA_CONVERSION_FACTOR;
	//need to fix for second file too
	
	int *indexOfAlignmentPathTested;
	int lengthOfPath = tw.backwardsAlignmentPath[0].size()-1;
	indexOfAlignmentPathTested = &lengthOfPath;
	
	int xcoord;
	for (int x = 0;x < screenWidth;x++)
	{
		for (int y =0;y < screenHeight;y++){
		
			xcoord = (x / screenWidth) * chromoLength;//was simWidth
			//xcoord += startingFrame;
			xcoord += startingXframe;
			
			int ycoord = y * chromoLength/ screenHeight;
			//ycoord += startingFrame;
			ycoord += startingYframe;
			
			int colour = 0;
			//int ycoord = y * simHeight/ screenHeight;
			//y += startingFrame;
			if (xcoord < sizeOfMatrix && ycoord < sizeOfSecondMatrix)
			colour = tw.similarityMatrix[xcoord][ycoord]*255;
			

		 ofSetColor(colour,0,0);
		
		ofRect(x,y,1,1);
			
		}
	}
	
	drawAlignmentPath(startingXframe, startingYframe);
	
	//SET TEXT
	string textString;
	textString = "width : ";
	textString += ofToString(simWidth);
	
	textString += "  height : ";
	textString += ofToString(simHeight);
	
	textString += "  startframe : ";
	textString += ofToString(startingFrame);

	textString += "  Xframe : ";
	textString += ofToString(startingXframe);

	textString += "  Yframe : ";
	textString += ofToString(startingYframe);
	
	textString += "  currentFrame : ";
	textString += ofToString(currentPlayingFrame);

	textString += "  scrollwidth: ";
	textString += ofToString(scrollWidth);

	textString += "  xcoord: ";
	textString += ofToString(xcoord);

	textString += "  Clength: ";
	textString += ofToString(chromoLength);

	textString += "  no.Scrolls: ";
	textString += ofToString(numberOfScrollWidthsForFirstFile);
	//END SET TEXT
	
	ofSetColor(0x0000FF);
	if (firstAudioFilePlaying){
	ofLine(audioPosition*screenWidth, 0, audioPosition*screenWidth, height);
		checkIfAudioPositionExceedsWidthForFirstFile();	
		
			//draw values:
		xcoord = currentPlayingFrame / CHROMA_CONVERSION_FACTOR;
		ofSetColor(255, 255, 255);
			for (int y = 0;y < chromoLength; y+=max(1, (int)(20 * chromoLength / screenHeight))){
		
				float value = tw.alignmentMeasureMatrix[xcoord][y+startingYframe];
				int ycoord = y * screenHeight/chromoLength;
				ofDrawBitmapString(ofToString(value, 2) , audioPosition*screenWidth , ycoord);
			}
	}
	else{
	ofLine(0, audioPosition*screenHeight, screenWidth, audioPosition*screenHeight);	
	}
		
	ofDrawBitmapString(textString,80,580);
	
	ofDrawBitmapString(userInfoString,80,80);
	
}


void  testApp::checkIfAudioPositionExceedsWidthForFirstFile()
{
	if (currentPlayingFrame > scrollWidth*(numberOfScrollWidthsForFirstFile+1))
		numberOfScrollWidthsForFirstFile++;
}

int testApp::findStartWidthFrame(){
	int startingFrame;
		startingFrame = currentPlayingFrame / scrollWidth;//i.e. number of scroll widths in
		startingFrame *= scrollWidth;//starting frame in terms of energy frames
		startingFrame /= CHROMA_CONVERSION_FACTOR; 

 return startingFrame;
}

void testApp::drawAlignmentPath(int startingChromaXFrame, int startingChromaYFrame){
	//draw alignment path
	int endingChromaXFrame = startingChromaXFrame + chromoLength;
	int endingChromaYFrame = startingChromaYFrame + chromoLength;
	
	float chromoWidth = screenWidth / chromoLength;
	float chromoHeight = screenHeight / chromoLength;
	
	int index = tw.backwardsAlignmentPath[0].size()-1;
	//OPTIMISE XXX

	
	while (tw.backwardsAlignmentPath[0][index] < startingChromaXFrame){
		index --;
	}
	
	int printIndex = index;
	int backAlign = tw.backwardsAlignmentPath[0][index];
	int printxcoord;
	int xcoord;
	
	while (tw.backwardsAlignmentPath[0][index] < endingChromaXFrame) {
		xcoord = tw.backwardsAlignmentPath[0][index];
		int ycoord = tw.backwardsAlignmentPath[1][index];
		
		printxcoord = xcoord;
		int colour = tw.similarityMatrix[xcoord][ycoord]*255;
		
		float value = tw.alignmentMeasureMatrix[xcoord][ycoord] ;
		
								
		xcoord -= startingChromaXFrame;
		ycoord -= startingChromaYFrame;
		ofSetColor(0,0,colour);
		ofRect(xcoord*chromoWidth, ycoord*chromoHeight, chromoWidth, chromoHeight);
//		ofSetColor(255, 255, 255);
//		ofDrawBitmapString(ofToString(value, 2), xcoord*chromoWidth, ycoord*chromoHeight);
		index--;
	}
	
//	drawHoverAlignmentValues();
//	printf("ALIGN score :[%i] : %f \n", backwardsAlignmentPath[1][backwardsAlignmentIndex], alignmentMeasureMatrix[ backwardsAlignmentPath[0][backwardsAlignmentIndex] ][ (int) backwardsAlignmentPath[1][backwardsAlignmentIndex] ]);

	
	//SET TEXT
	string textString;
	textString = "ALIGNMENT PATH  ";
	
	textString += "backward A index ";
	textString += ofToString(backwardsAlignmentIndex);
	
	textString += "  starting X frame ";
	textString += ofToString(startingChromaXFrame);
	
	textString += "  initial xcoord ";
	textString += ofToString(printxcoord);
	
	textString += "  first index ";
	textString += ofToString(printIndex);

	textString += "  backalign[index] ";
	textString += ofToString(backAlign);
	
	textString += "  final xcoord ";
	textString += ofToString(xcoord);
	
	
	
	
	ofSetColor(255,255,255); 
	ofDrawBitmapString(textString,80,640);
	
}






void testApp::loadSoundFiles(){
		
		//assume libsndfile looks in the folder where the app is run
		//therefore ../../../ gets to the bin folder
		//we then need data/sounds/to get to the sound folder
		//this is different to the usual OF default folder
	//was const char	
	const char	*infilename = "../../../data/sound/1-01BachBWV 846.wav";	
	loadLibSndFile(infilename);

	string loadfilename = "sound/1-01BachBWV 846.wav";//PicturesMixer6.aif";	
	loadedAudio.loadSound(loadfilename);
	playingAudio = &loadedAudio;

}

void testApp::loadLibSndFile(const char *infilename){
	
	if (!sf_close(infile)){
		printf("closed sndfile okay \n");
	}
	
	// Open Input File with lib snd file
    if (! (infile = sf_open (infilename, SFM_READ, &sfinfo)))
    {   // Open failed
        printf ("SF OPEN routine Not able to open input file %s.\n", infilename) ;
        // Print the error message from libsndfile. 
        puts (sf_strerror (NULL)) ;
		
	} else{
		printf("SF OPEN opened file %s okay.\n", infilename);
		sndfileInfoString = "Opened okay ";
		
	};
	
}

void testApp::processAudioToDoubleMatrix(Chromagram* chromaG, DoubleMatrix* myDoubleMatrix, DoubleVector* energyVector){
	//wendy
	myDoubleMatrix->clear();
	energyVector->clear();
	
	frameIndex = 0;
//	chromaIndex = 0;//	WHY NEED THIS?
	chromaG->initialise(FRAMESIZE,2048);//framesize 512 and hopsize 2048 
	chromaG->maximumChromaValue = 0;
	
	int readcount = 1; // counts number of samples read from sound file
	printf("processing audio from doublematrix \n");
			printf("readcount %i", readcount);
	while(readcount != 0 && moveOn == true)
	{
		
		// read FRAMESIZE samples from 'infile' and save in 'data'
		readcount = sf_read_float(infile, frame, FRAMESIZE);
		
		//printf("readcount %i", readcount);
		
		//processing frame - downsampled to 11025Hz
		//8192 samples per chroma frame
		chromaG->processframe(frame);
		
		if (chromaG->chromaready)
		{
				DoubleVector d;
				
				for (int i = 0;i<12;i++){
					d.push_back(chromaG->rawChroma[i]);// / chromaG->maximumChromaValue);	
					
				}	
				//this would do chord detection
				
				myDoubleMatrix->push_back(d);
	
			
		}//end if chromagRamm ready
		
		//printf("calling drawSndFile %i", frameIndex);
		frameIndex++;
		
		
		//	putEnergyInFrame();
		//get energy of the current frame and wait
		
		double energyValue = getEnergyOfFrame();
		energyVector->push_back(energyValue);

		
	}//end while readcount
	
	printf("Max chroma value is %f \n", chromaG->maximumChromaValue);
	
	//normalise
	int length = myDoubleMatrix->size();
	printf("length of chromagram is %d frames\n", length);
	length = (*myDoubleMatrix)[0].size();
		printf("height of dmatrix is %d\n", length);
	
	for (int i = 0; i < myDoubleMatrix->size();i++){
		for (int j = 0; j < ((*myDoubleMatrix)[0]).size();j++){
	(*myDoubleMatrix)[i][j] /= chromaG->maximumChromaValue;	
		}
	}
	
	int size;
	size = energyVector->size();
	printf("size of energy vector is %d \n", size);
	
	totalNumberOfFrames = frameIndex;//used to use this - but switch to energy vector's size instead
//	totalNumberOfFrames = size;
	
//	int size = myDoubleMatrix->size() * CHROMA_CONVERSION_FACTOR;
//	printf("size of double matrix is %d and frame index %d", size, frameIndex);
	
	printf("Total frames %i  and Chroma index %i \n", frameIndex, chromaIndex);
	
	
}


//--------------------------------------------------------------
void testApp::keyPressed  (int key){
	if (key == '-'){
		volume -= 0.05;
		volume = MAX(volume, 0);
	} else if (key == '+'){
		volume += 0.05;
		volume = MIN(volume, 1);
	}
	
	if (key == OF_KEY_DOWN){
		if (scrollWidth > 600)
		scrollWidth += 400;
		else
		scrollWidth *= 2;
		
		chromoLength = scrollWidth/CHROMA_CONVERSION_FACTOR;
	}
	
	if (key == OF_KEY_UP){
		if (scrollWidth > 600)
		scrollWidth -= 400;
		else
		scrollWidth /= 2;
		
		chromoLength = scrollWidth/CHROMA_CONVERSION_FACTOR;
	}

	if (key == OF_KEY_LEFT){
		
		(*playingAudio).setSpeed(-2);
		backwardsAlignmentIndex = tw.backwardsAlignmentPath[0].size()-1;
	}

	if (key == OF_KEY_RIGHT){
		
		(*playingAudio).setSpeed(2);
	}
	
	if (key == OF_KEY_RETURN){
		loadedAudio.stop();
		audioPlaying = false;
		audioPaused = true;
		initialiseVariables();
	}
	
		if (key == ' '){
			if (!audioPlaying) {
				(*playingAudio).play();
				(*playingAudio).setPaused(false);
				secondAudio.play();
				secondAudio.setPaused(true);
				
				firstAudioFilePlaying = true; 
				
				audioPlaying = true;
				audioPaused = false;
			}
			else{
			audioPaused = !audioPaused;
			(*playingAudio).setPaused(audioPaused);
			}
		
		}
	
	if (key == 'p'){
		swapBetweenPlayingFilesUsingAlignmentMatch();
		
		}
	
	if (key == 'o'){
		openNewAudioFileWithdialogBox();
	}
	
	if (key == 'l'){
		//open audio file
		string *filePtr, secondFileName;
		filePtr = &secondFileName;
		//so filePtr points to secondFileName
		
		if (getFilenameFromDialogBox(filePtr)){
			printf("Loaded name okay :\n'%s' \n", secondFileName.c_str());	
		 }
		
		loadSecondAudio(secondFileName);
		
		tw.calculateSimilarityMatrix();
		tw.calculateAlignmentMatrix();
		//printf("yabbo");
		tw.calculateMinimumAlignmentPath();
		//printf("got here!");
	}
	
	if (key == 's'){
		drawSimilarity = !drawSimilarity;
	}
	
	
	if (key == 'm'){
		drawSecondMatrix = !drawSecondMatrix;
	}
	
	if (key == 'd'){
		drawSpectralDifferenceFunction = !drawSpectralDifferenceFunction;
	}
	
}

//--------------------------------------------------------------
void testApp::keyReleased  (int key){
	if (key == OF_KEY_LEFT || OF_KEY_RIGHT){
		(*playingAudio).setSpeed(1);
		backwardsAlignmentIndex = tw.backwardsAlignmentPath[0].size()-1;
	}
	
}

void testApp::openNewAudioFileWithdialogBox(){
	
	//open audio file
	string *filePtr;
	filePtr = &soundFileName;	
	
	if (getFilenameFromDialogBox(filePtr)){
		printf("Mainfile: Loaded name okay :\n'%s' \n", soundFileName.c_str());	
	}
	
	//openFileDialogBox(); - replaced this lone by call to openFile Dialoguebox
	loadNewAudio(soundFileName);

}

//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y ){
	width = ofGetWidth();
	pan = (float)x / (float)width;
	float height = (float)ofGetHeight();
	float heightPct = ((height-y) / height);
	targetFrequency = 2000.0f * heightPct;
	phaseAdderTarget = (targetFrequency / (float) sampleRate) * TWO_PI;
	xIndex = (int)(pan*ENERGY_LENGTH);
}

//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){
	width = ofGetWidth();
	pan = (float)x / (float)width;
}

//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){
	bNoise = true;
	moveOn = true;
}


//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button){
	bNoise = false;
}

//--------------------------------------------------------------
void testApp::windowResized(int w, int h){
width = w;
height = h;
	screenHeight = ofGetHeight() ;
	screenWidth = ofGetWidth();
	
}
//--------------------------------------------------------------
void testApp::audioRequested 	(float * output, int bufferSize, int nChannels){
	//pan = 0.5f;
	float leftScale = 1 - pan;
	float rightScale = pan;

	// sin (n) seems to have trouble when n is very large, so we
	// keep phase in the range of 0-TWO_PI like this:
	while (phase > TWO_PI){
		phase -= TWO_PI;
	}


}


//--------------------------------------------------------------


bool testApp::getFilenameFromDialogBox(string* fileNameToSave){
	//this uses a pointer structure within the loader and returns true if the dialogue box was used successfully
	// first, create a string that will hold the URL
	string URL;
	
	// openFile(string& URL) returns 1 if a file was picked
	// returns 0 when something went wrong or the user pressed 'cancel'
	int response = ofxFileDialogOSX::openFile(URL);
	if(response){
		// now you can use the URL 
		*fileNameToSave = URL;
		//printf("\n filename is %s \n", soundFileName.c_str());
		return true;
	}
	else {
	//	soundFileName = "OPEN canceled. ";
		printf("\n open file cancelled \n");
		return false;
	}
	
}

void testApp::openFileDialogBox(){

	// first, create a string that will hold the URL
	string URL;
	
	// openFile(string& URL) returns 1 if a file was picked
	// returns 0 when something went wrong or the user pressed 'cancel'
	int response = ofxFileDialogOSX::openFile(URL);
	if(response){
		// now you can use the URL 
		soundFileName = URL;//"URL to open: \n "+URL;
	}else {
		soundFileName = "OPEN cancelled. ";
	}
	
	

}


void testApp::loadNewAudio(string soundFileName){

	loadedAudio.loadSound(soundFileName);
	
	//snd file method
	const char	*infilename = soundFileName.c_str() ;
	
	loadLibSndFile(infilename);
	
	loadFirstAudioFile();
	
	audioPlaying = false;
}



void testApp::loadFirstAudioFile(){
	Chromagram* cptr;
	DoubleMatrix* dptr;
	DoubleVector* eptr;
	
	cptr = &(tw.chromoGramm);
	dptr = &(tw.chromaMatrix);
	eptr = &(tw.firstEnergyVector);
	
	processAudioToDoubleMatrix(cptr, dptr, eptr);
	
}

void testApp::loadSecondAudio(string soundFileName){

	secondAudio.loadSound(soundFileName);

	const char	*infilename = soundFileName.c_str() ;	
	loadLibSndFile(infilename);

	Chromagram* cptr;
	DoubleMatrix* dptr;
	DoubleVector* eptr;
	cptr = &(tw.secondChromoGramm);
	dptr = &(tw.secondMatrix);
	eptr = &(tw.secondEnergyVector);
	
	processAudioToDoubleMatrix(cptr, dptr, eptr);//chromaMatrix);
	
}



double testApp::getEnergyOfFrame(){
	
	
	float totalEnergyInFrame = 0;
	
	for (int i = 0;i<FRAMESIZE;i++){
		
		totalEnergyInFrame += (frame[i] * frame[i]);
		
	}
	totalEnergyInFrame = sqrt(totalEnergyInFrame);
	
	return totalEnergyInFrame;
}
					
void testApp::swapBetweenPlayingFilesUsingAlignmentMatch(){
	ofSoundUpdate();
	//swapping between files
	//printf("current playing (energy scale) frame was %i \n", currentPlayingFrame);
	float oldPosition = (*playingAudio).getPosition();
	printf("playing position is %f \n", (*playingAudio).getPosition());

	//(*playingAudio).stop(); 
	(*playingAudio).setPaused(true);
	int newIndicator;
	if (firstAudioFilePlaying){
		playingAudio = &secondAudio;
		newIndicator = 1;	
		}
	else{
		playingAudio = &loadedAudio;
		newIndicator = 0;
		}
	printf("new indicator %i \n", newIndicator);
	
	printf("playing pos according to energy frames is %f \n ", 
		   (currentPlayingFrame/((float)tw.backwardsAlignmentPath[1-newIndicator][0]*CHROMA_CONVERSION_FACTOR)) );

		printf("predicts frame to be %f \n", (oldPosition*tw.backwardsAlignmentPath[1-newIndicator][0]));
	
	currentChromaFrame = oldPosition * (float) tw.backwardsAlignmentPath[1-newIndicator][0];
	printf("current chroma frame %i and using energy frames would have been %i \n", currentChromaFrame, currentPlayingFrame / CHROMA_CONVERSION_FACTOR);
	int matchingFrame = findMatchFromAlignment(firstAudioFilePlaying);	
	
	float relativePosition = matchingFrame / (float) tw.backwardsAlignmentPath[newIndicator][0];
	//i.e. the position as float [0,1] 0:beginning, 1 is end
	
	(*playingAudio).setPaused(false);
	(*playingAudio).setPosition(relativePosition);
	
	printf("matching frame is %i and length is %i \n", matchingFrame, tw.backwardsAlignmentPath[newIndicator][0]);
	printf("new playing position is %f \n", (*playingAudio).getPosition());
	
	firstAudioFilePlaying = !firstAudioFilePlaying;
	
	
}

int testApp::findMatchFromAlignment(bool whichFileToTest){
	//could use technique from middle of file and go either way to reduce latency for long search? 
	//- (not that this is a problem yet)
	int indicator;
	if (whichFileToTest)
		indicator = 0;
		else
		indicator = 1;

	int oppositeIndicator = 1 - indicator;
  
	int frame = tw.backwardsAlignmentPath[indicator].size()-1;

	
	while (tw.backwardsAlignmentPath[indicator][frame] < currentChromaFrame){
		frame--;
	}
	//printf("frame found is %i \n", frame);
	int frameToSwitchTo = tw.backwardsAlignmentPath[oppositeIndicator][frame];
	
	float calculatedPosition = (currentChromaFrame / (float) tw.backwardsAlignmentPath[indicator][0]);
	
	printf("(length was %i)\n",  tw.backwardsAlignmentPath[indicator][0]);
	
	printf("compares to position calculated from chroma length %f \n", calculatedPosition);
	printf("current frame %i maps to new frame %i \n", currentChromaFrame, frameToSwitchTo);
	printf("relative position of new frame is %f \n", (frameToSwitchTo / (float) tw.backwardsAlignmentPath[oppositeIndicator][0]) );
	return frameToSwitchTo; 

}

/*
int testApp::findMinimumOfVector(DoubleVector *d){
	int minimumIndex = 0;
	double minimumValue = (*d)[0];
	for (int i = 0;i < d->size();i++){
		if ((*d)[i] < minimumValue){
			minimumIndex = i;
			minimumValue = (*d)[i];
		}
	}
	 
	return minimumIndex;
}
 */
/*
double testApp::getDistance(int i, int j){
	return (1 - similarityMatrix[i][j]);
}

double testApp::getMinimum(int i, int j, float newValue){
	double minimumValue = 0;
	
	if (i > 0){
		minimumValue = tw.alignmentMeasureMatrix[i-1][j];
		if (j > 0){
			minimumValue = min(minimumValue, alignmentMeasureMatrix[i-1][j-1] + newValue ) ;//penalises diagonal by 2
			minimumValue = min(minimumValue, alignmentMeasureMatrix[i][j-1]);
		}
	}
	else{//i.e. i == 0 
		if (j > 0)
			minimumValue = tw.alignmentMeasureMatrix[i][j-1];
	}
	
	return minimumValue;
}

*/

void testApp::printSimilarityMatrix(int sizeToPrint){
	
	printf("\n _ _ _ _\n");
	printf("Similarity Matrix \n");
	int i,j;
	DoubleVector d;
	int rowSize = sizeToPrint;
	
	for (int j = 0;j < rowSize;j++){
		printf("row %i : ", j);
		
		for (i = 0;i < rowSize;i++){			
			printf("%f , ", tw.similarityMatrix[i][j] );
		}
		printf("\n");
	}
	printf("...............\n");
	
}


void testApp::printAlignmentMatrix(){
	
	int size = tw.alignmentMeasureMatrix.size();
printf("\n _ _ _ _\n");
printf("align size is %i \n", size);
	
	int i,j;
	DoubleVector d;
	int rowSize = tw.alignmentMeasureMatrix.size();
	d = tw.alignmentMeasureMatrix[0];//choose initial size

	for (int j = 0;j < d.size();j++){
		printf("row %i : ", j);
		
		for (i = 0;i < rowSize;i++){
		d = tw.alignmentMeasureMatrix[i];
		
		//	printf("row %i , col %i, val : %f \n", i, j, alignmentMeasureMatrix[i][j] );
			printf("%f , ", tw.alignmentMeasureMatrix[i][j] );
		}
		printf("\n");
	}
	printf("...............\n");
	
}


void testApp::printScoreForRow(int row, int max){
	printf("alignment scores row %i \n", row);
	float minimum = tw.alignmentMeasureMatrix[row][0];
	int minimumIndex = 0;
	for (int i =0;i < max;i++){
		printf("[%i] %f ", i, tw.alignmentMeasureMatrix[row][i]);
		if (tw.alignmentMeasureMatrix[row][i] < minimum)
		{
			minimum = tw.alignmentMeasureMatrix[row][i] ;
			minimumIndex = i;
		}
		printf(" \n");
			}
	printf("Minimum [%i] : %f \n", minimumIndex, minimum);
	printf("ALIGN score :[%i] : %f \n", tw.backwardsAlignmentPath[1][backwardsAlignmentIndex], tw.alignmentMeasureMatrix[tw.backwardsAlignmentPath[0][backwardsAlignmentIndex] ][ (int) tw.backwardsAlignmentPath[1][backwardsAlignmentIndex] ]);
 
}













/*
 void testApp::calculateSimilarityMatrix(){
 similarityMatrix.clear();
 printf("calculating similarity matrix...");
 userInfoString = "calculating similarity matrix...";
 
 double distance, firstSum, secondSum;
 
 for (int x = 0;x < tw.chromaMatrix.size();x++){
 DoubleVector d;
 for (int y = 0;y < tw.secondMatrix.size();y++){
 
 //d.push_back( drand48() );	
 
 distance = 0;
 firstSum = 0;
 secondSum = 0;
 for (int z = 0;z < chromaMatrix[x].size();z++){//z is the twelve chromagram values
 
 distance += chromaMatrix[x][z] * secondMatrix[y][z];
 
 firstSum += chromaMatrix[x][z] * chromaMatrix[x][z];
 secondSum += secondMatrix[y][z] * secondMatrix[y][z];
 }
 
 if (firstSum > 0 && secondSum > 0)
 distance /= sqrt(firstSum * secondSum);
 
 
 d.push_back( distance);	
 
 }	//end for y
 
 similarityMatrix.push_back(d);
 
 }//end for x
 userInfoString += "; size =";
 userInfoString += ofToString(similarityMatrix.size() , 0);
 printf("..sim size: %i, height: %i \n", similarityMatrix.size(), (chromaMatrix[0]).size());
 
 }//end self sim
 
 */
/*
 void testApp::calculateAlignmentMatrix(){
 
 //initialise alignment
 alignmentMeasureMatrix.clear();
 DoubleVector d;
 d.push_back(getDistance(0,0));
 alignmentMeasureMatrix.push_back(d);
 
 bool chromaCalculated = false;
 bool secondCalculated = false;
 
 while (!chromaCalculated || !secondCalculated) {
 
 if (!chromaCalculated)
 chromaCalculated = extendAlignmentAlong();
 
 if (!secondCalculated)
 secondCalculated = extendAlignmentUp();
 
 }
 
 }
 
 bool testApp::extendAlignmentUp(){
 DoubleVector d;
 d = alignmentMeasureMatrix[0];
 int heightSize = d.size();
 if (heightSize < secondMatrix.size()){
 //then we haven't finished yet
 for (int i = 0;i < alignmentMeasureMatrix.size();i++){
 double value = getDistance(i, heightSize);
 value += getMinimum(i, heightSize, value);	
 alignmentMeasureMatrix[i].push_back(value);
 }
 }
 if (alignmentMeasureMatrix[0].size() == secondMatrix.size())
 return true;
 else
 return false;
 
 }
 
 
 bool testApp::extendAlignmentAlong(){
 DoubleVector d;
 int widthSize = alignmentMeasureMatrix.size();
 if (widthSize < chromaMatrix.size()){
 //then we can extend along
 double value = getDistance(widthSize, 0);
 value += getMinimum(widthSize, 0, value);
 
 d.push_back(value);
 alignmentMeasureMatrix.push_back(d);
 
 for (int j = 1;j < alignmentMeasureMatrix[widthSize - 1].size();j++){
 value = getDistance(widthSize, j);
 value += getMinimum(widthSize, j, value);
 alignmentMeasureMatrix[widthSize].push_back(value);
 }
 
 //alignmentMeasureMatrix.push_back(d);
 }
 
 if (alignmentMeasureMatrix.size() == chromaMatrix.size())
 return true;
 else
 return false;
 
 }
 
 
 void testApp::calculateMinimumAlignmentPath(){
 //this requires one pass of the DTW algorithm and then works backwards from (N,M)
 //to find the optimal path to (0,0), where N and M are the lengths of the two chromoVectors respectively
 //minimumAlignmentPath.clear();
 backwardsAlignmentPath.clear();
 
 printf("Finding minimum Path \n");
 IntVector v;
 v.push_back(chromaMatrix.size()-1);
 backwardsAlignmentPath.push_back(v);
 v.clear();
 v.push_back(secondMatrix.size()-1);
 backwardsAlignmentPath.push_back(v);
 //so now backwards path[0][0] = size(chroma) and path[1][0] = size(secondMatrix)
 printf("backwards path %i : %i \n", backwardsAlignmentPath[0][0], backwardsAlignmentPath[1][0]);
 
 
 int indexOfBackwardsPath = 0;
 while (!findPreviousMinimumInBackwardsPath())	{
 indexOfBackwardsPath++;
 printf("backwards path %i : %i \n", backwardsAlignmentPath[0][indexOfBackwardsPath], backwardsAlignmentPath[1][indexOfBackwardsPath]);
 
 }
 //printf("final index of backwards path is %i and i is %i \n", backwardsAlignmentPath[0].size()-1, indexOfBackwardsPath);
 
 backwardsAlignmentIndex = backwardsAlignmentPath[0].size()-1;//remember that this goes backwards!
 
 }
 
 
 bool testApp::findPreviousMinimumInBackwardsPath(){
 int chromaPosition, secondPosition;
 int i,j;
 i = backwardsAlignmentPath[0][backwardsAlignmentPath[0].size()-1];
 j  = backwardsAlignmentPath[1][backwardsAlignmentPath[1].size()-1];
 
 double newMinimum;
 double *ptr;
 ptr = &newMinimum;
 newMinimum = alignmentMeasureMatrix[i][j];
 DoubleVector d;
 
 
 bool finishedAligning = true;
 
 if (i > 0){
 if (testForNewAlignmentMinimum(ptr, i-1, j)){
 chromaPosition = i-1;
 secondPosition = j;
 finishedAligning = false;
 }
 
 if (j>0 && testForNewAlignmentMinimum(ptr, i-1, j-1)){
 chromaPosition = i-1;
 secondPosition = j-1;
 finishedAligning = false;
 }
 }
 
 if (j > 0 && testForNewAlignmentMinimum(ptr, i, j-1)){
 chromaPosition = i;
 secondPosition = j-1;
 //newMinimum = alignmentMeasureMatrix[chromaPosition][secondPosition];
 finishedAligning = false;
 }
 
 if (!finishedAligning){
 backwardsAlignmentPath[0].push_back(chromaPosition);
 backwardsAlignmentPath[1].push_back(secondPosition);
 }
 
 return finishedAligning;
 
 }	
 
 
 
 bool testApp::testForNewAlignmentMinimum(double *previousMinimum, int i, int j){
 bool newMinimumFound = false;
 if (alignmentMeasureMatrix[i][j] < *previousMinimum){
 *previousMinimum = alignmentMeasureMatrix[i][j];							   
 newMinimumFound = true;
 }
 
 return newMinimumFound;							   
 }		
 */