Mercurial > hg > audio-time-warp
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; } */