Mercurial > hg > audio-time-warp
view src/testApp.cpp @ 4:f40577e6b30d
revised this to work with onset and chroma and looking now to do sequential DTW
author | Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk> |
---|---|
date | Wed, 08 Jun 2011 17:35:56 +0100 |
parents | 9ce18f24b266 |
children | 0d51e93bfe74 |
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 //-------------------------------------------------------------- /* Main functions here: Load file from a dialogue box with LibSndFile We then iterate through all the samples and call our relevant functions in the timeWarp object - i.e. onset, chroma and do the calculations for similarity and alignment TO DO: Find continual alignment between the playing file and the non-playing file - show the current location in the energy amd chroma draw fn for the non-playing file simplify the loading procedure */ 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; conversionFactor = 1;//CHROMA_CONVERSION_FACTOR; chromoLength = scrollWidth / conversionFactor;// CHROMA_CONVERSION_FACTOR; sfinfo.format = 0; moveOn = true; chromaG.initialise(FRAMESIZE, CHROMAGRAM_FRAMESIZE); onset = new OnsetDetectionFunction(512,1024,6,1); //loading audio files loadSoundFiles(); soundFileName = "../../../data/sound/Bach_short2.wav"; loadFirstAudioFile(); secondFileName = "../../../data/sound/Bach_short2.wav"; loadSecondAudio(secondFileName);//i.e. load same as first file backwardsAlignmentIndex = 0;//remember that this goes backwards! tw.initialiseVariables(); calculateSimilarityAndAlignment(); 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::calculateSimilarityAndAlignment(){ //here is the main TimeWarp similarity matrix calc, the minimum alignment matrix via dtw and then the backwards path estimate // tw.calculateSimilarityMatrixWithPointers(tw.chromaMatrix, tw.secondMatrix, &tw.similarityMatrix); // tw.calculateAlignmentMatrix(tw.chromaMatrix, tw.secondMatrix, &tw.alignmentMeasureMatrix); tw.calculateSimilarityMatrixWithPointers(tw.firstChromaEnergyMatrix, tw.secondChromaEnergyMatrix, &tw.similarityMatrix); tw.calculateAlignmentMatrix(tw.firstChromaEnergyMatrix, tw.secondChromaEnergyMatrix, &tw.alignmentMeasureMatrix); tw.calculateMinimumAlignmentPath(tw.alignmentMeasureMatrix); int hopsize = 200; int startFrameY = 0; for (int startFrameX = 0;startFrameX < 400;startFrameX += hopsize){ tw.calculatePartSimilarityMatrix(tw.firstChromaEnergyMatrix, tw.secondChromaEnergyMatrix, &tw.tmpSimilarityMatrix, startFrameX, startFrameY, startFrameX+400); tw.calculateAlignmentMatrix(tw.firstChromaEnergyMatrix, tw.secondChromaEnergyMatrix, &tw.tmpAlignmentMeasureMatrix); tw.calculateMinimumAlignmentPath(tw.tmpAlignmentMeasureMatrix); tw.extendForwardAlignmentPath(200); } // tw.calculatePartMinimumAlignmentPath(0, 0, 100, 100, &tw.partAlignmentMeasureMatrix); printf("ENERGY SIZE:%i, SIM SIZE:%i\n",(int)tw.firstEnergyVector.size(), (int)tw.similarityMatrix.size()); conversionFactor = (int)(tw.firstEnergyVector.size() / tw.similarityMatrix.size()); printf("CONVERSION factor %i\n", conversionFactor); chromoLength = scrollWidth / conversionFactor;// CHROMA_CONVERSION_FACTOR; } void testApp::initialiseVariables(){ 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/conversionFactor]);//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); currentPlayingFrame = audioPosition; audioPosition = (int) audioPosition % scrollWidth ; audioPosition /= scrollWidth; ofSoundUpdate(); } void testApp::updateAlignmentPathIndex(int identifier){ //this is the alignment where we are currently playing - i.e. switching between files int chromaPosition = audioPosition/conversionFactor;//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 = 1; int i, j, startingFrame; startingFrame = currentPlayingFrame / scrollWidth;//i.e. number of scroll widths in startingFrame *= scrollWidth; for (i = 0; i < scrollWidth - 1; i++){ j = min(i + startingFrame, (int)energyVec->size()-1); 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 /= conversionFactor;// CHROMA_CONVERSION_FACTOR; //in terms of chroma frames for (i = 1; i < chromoLength; i++){//changed to add 1 j = min(i + startingFrame, (int) dMatrix->size()-1 );//in case out of range 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 /= conversionFactor;//CHROMA_CONVERSION_FACTOR; //in terms of chroma frames float chromoLength = scrollWidth/conversionFactor;// CHROMA_CONVERSION_FACTOR; for (i = 0; i < chromoLength; i++){ j = min(i + startingFrame, (int) dMatrix->size()-1 ) ; 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 = (int) tw.similarityMatrix.size();//tw.chromaMatrix.size(); int sizeOfSecondMatrix = (int) tw.similarityMatrix[0].size(); int startingXframe = tw.backwardsAlignmentPath[0][backwardsAlignmentIndex] / (scrollWidth/conversionFactor); int startingYframe = tw.backwardsAlignmentPath[1][backwardsAlignmentIndex] / (scrollWidth/conversionFactor); int startingFrame = findStartWidthFrame(); startingFrame = numberOfScrollWidthsForFirstFile * scrollWidth/conversionFactor; startingXframe = startingXframe * scrollWidth/conversionFactor; startingYframe = startingYframe * scrollWidth/conversionFactor; //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); drawForwardsAlignmentPath(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 / conversionFactor; 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 /= conversionFactor;// 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 = min((int)(tw.similarityMatrix.size())-1,tw.backwardsAlignmentPath[0][index]); int ycoord = min((int)tw.backwardsAlignmentPath[1][index], (int)(tw.alignmentMeasureMatrix[0].size())-1); 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::drawForwardsAlignmentPath(int startingChromaXFrame, int startingChromaYFrame){ if (tw.forwardsAlignmentPath.size() > 0){ int endingChromaXFrame = startingChromaXFrame + chromoLength; int endingChromaYFrame = startingChromaYFrame + chromoLength; float chromoWidth = screenWidth / chromoLength; float chromoHeight = screenHeight / chromoLength; int index = 0; //OPTIMISE XXX while (tw.forwardsAlignmentPath[0][index] < startingChromaXFrame){ //get to NOW index ++; } // int printIndex = index; // int forwardsAlign = tw.forwardsAlignmentPath[0][index]; // int printxcoord; int xcoord; while (index < tw.forwardsAlignmentPath[0].size() && tw.forwardsAlignmentPath[0][index] < endingChromaXFrame) { xcoord = min((int)(tw.similarityMatrix.size())-1,tw.forwardsAlignmentPath[0][index]); int ycoord = min((int)tw.forwardsAlignmentPath[1][index], (int)(tw.alignmentMeasureMatrix[0].size())-1); // printxcoord = xcoord; int colour = 255;//tw.similarityMatrix[xcoord][ycoord]*255; //float value = tw.alignmentMeasureMatrix[xcoord][ycoord] ; xcoord -= startingChromaXFrame; ycoord -= startingChromaYFrame; ofSetColor(0,colour,0); ofRect(xcoord*chromoWidth, ycoord*chromoHeight, chromoWidth, chromoHeight); index++; }//end while }//end if forwards path exista } 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/Bach_short1.wav"; loadLibSndFile(infilename); string loadfilename = "sound/Bach_short1.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(DoubleMatrix* myDoubleMatrix, DoubleVector* energyVector){ //wendy myDoubleMatrix->clear(); energyVector->clear(); chromaG.initialise(FRAMESIZE, CHROMAGRAM_FRAMESIZE);//framesize 512 and hopsize 2048 - already done chromaG.maximumChromaValue = 1; double maximumEnergyValue = 1; 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); double doubleFrame[FRAMESIZE]; for (int k = 0;k< FRAMESIZE;k++){ doubleFrame[k] = frame[k]; } //8192 samples per chroma frame //processing frame - downsampled to 11025Hz 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); //so now is storing at d[i][current_index] }//end if chromagRamm ready // double energyValue = getEnergyOfFrame(); double energyValue = onset->getDFsample(doubleFrame); energyVector->push_back(energyValue); if (energyValue > maximumEnergyValue) maximumEnergyValue = energyValue; }//end while readcount printf("Max chroma value is %f \n", chromaG.maximumChromaValue); printf("length of chromagram is %d frames\n", (int)myDoubleMatrix->size()); printf("height of dmatrix is %d\n", (int)(*myDoubleMatrix)[0].size()); //normalise chroma matrix for (int i = 0; i < myDoubleMatrix->size();i++){ for (int j = 0; j < ((*myDoubleMatrix)[0]).size();j++){ //non-causal normalisation (*myDoubleMatrix)[i][j] /= chromaG.maximumChromaValue; } } printf("size of energy vector is %d \n", (int)energyVector->size()); //non causal normalisation for (int i = 0; i < energyVector->size();i++){ (*energyVector)[i] /= maximumEnergyValue; } // totalNumberOfFrames = (int)energyVector->size(); chromaConversionRatio = myDoubleMatrix->size() / (int)energyVector->size(); // int size = myDoubleMatrix->size() * CHROMA_CONVERSION_FACTOR; } //-------------------------------------------------------------- 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/conversionFactor;// CHROMA_CONVERSION_FACTOR; } if (key == OF_KEY_UP){ if (scrollWidth > 600) scrollWidth -= 400; else scrollWidth /= 2; chromoLength = scrollWidth/conversionFactor;// CHROMA_CONVERSION_FACTOR; } if (key == OF_KEY_LEFT){ (*playingAudio).setSpeed(-4); backwardsAlignmentIndex = tw.backwardsAlignmentPath[0].size()-1; } if (key == OF_KEY_RIGHT){ (*playingAudio).setSpeed(4); } 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); calculateSimilarityAndAlignment(); } 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(&tw.chromaMatrix, &tw.firstEnergyVector); tw.createCombinedMatrix(tw.chromaMatrix, tw.firstEnergyVector, &tw.firstChromaEnergyMatrix); } 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(&tw.secondMatrix, &tw.secondEnergyVector);//dptr, eptr);//chromaMatrix); tw.createCombinedMatrix(tw.secondMatrix, tw.secondEnergyVector, &tw.secondChromaEnergyMatrix); } 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]* conversionFactor)) );//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 / conversionFactor);//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; } 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; } */ /* 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; } */