view src/testApp.cpp @ 0:bcb0d40158f4

started audio file loader project - using oF_061
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Tue, 30 Aug 2011 20:18:34 +0100
parents
children ba2a17cf81bf
line wrap: on
line source
#include "testApp.h"
#include "stdio.h"
#include "aubio.h"
#include <iostream>
#include <cstring>
#include <string>
#include <cstdlib> 


const double samplingFrequency = 44100.0;
	
//--------------------------------------------------------------
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)
	
	//nb THIS CODE WOULD BE USEFUL IF WE EVER WANTED REAL-TIME INPUT - VIA ofSoundSteam
	

//	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;
	
	audioScale = 1000.0;
	
	scrollWidth = 1600;
	
	//int readcount = 0; // counts number of samples read from sound file

	//string inputFilename = "sound/GetIntoTheGroove.wav";// input file name placed in bin

	sfinfo.format = 0;
	
	moveOn = true;

	//loading audio files

	const char	*infilename = "../../../data/sound/bach4_short1.wav";	
	loadNewAudio(infilename);
	
	audioPlaying = false;

	drawSpectralDifferenceFunction = false;

	screenToDraw = 1;
	

}


void testApp::initialiseVariables(){
	
//	energyIndex = 0;
//	frameIndex = 0;
//	chromaIndex = 0;
	chromoGramm.initialise(FRAMESIZE,2048);//framesize 512 and hopsize 2048
}


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

	audioPosition = loadedAudio.getPosition() * totalNumberOfFrames;//frameIndex;//the position in number of frames
	currentPlayingFrame = audioPosition;
	audioPosition = (int) audioPosition % scrollWidth ;
	audioPosition /= scrollWidth;
	
	audioHolder.playPosition = loadedAudio.getPosition() * audioHolder.audioVector.size();
}

//--------------------------------------------------------------
void testApp::draw(){
	switch (screenToDraw){
		case 0:
			if (drawSpectralDifferenceFunction)
				drawSpectralDifference(&chromaMatrix);
			else
				drawDoubleMatrix(&chromaMatrix);
			
			drawEnergyVectorFromPointer(&firstEnergyVector);
			ofSetColor(0xFFFFFF);
			ofLine(audioPosition*width, 0, audioPosition*width, height);
			break;
			case 1:
		//	audioHolder.drawAudioVectorMillis(1000, 1000+audioScale);
			audioHolder.drawAudioVectorSamples(audioHolder.playPosition - audioHolder.audioScaleSamples*0.5, audioHolder.playPosition+audioHolder.audioScaleSamples*0.5);
			ofSetColor(100,100,100);
			ofLine(width/2, 0, width/2, height);
			break;
	}
	

	
	//ofSetColor(255,0,0);
	//drawEnergyVectorFromPointer(&audioVector);
	


	ofDrawBitmapString(soundFileName,80,480);
		
}


void testApp::drawEnergyVectorFromPointer(DoubleVector* energyVec){
	
	ofSetColor(0xFF0066);
	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;
		if (j < (*energyVec).size())
		ofLine(i*screenWidth/scrollWidth, screenHeight - ((*energyVec)[j]*screenHeight/heightFactor),
			   screenWidth*(i+1)/scrollWidth, screenHeight - ((*energyVec)[j+1]*screenHeight/heightFactor));
		
	}
}

void testApp::drawSpectralDifference(DoubleMatrix* dMatrix){
	int matrixSize = (*dMatrix).size();
	if (matrixSize > 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
	
	float chromoLength = scrollWidth/CHROMA_CONVERSION_FACTOR;
	for (i = 1; i < chromoLength; i++){//changed to add 1
		j = i + startingFrame;
		for (int y = 0;y < 12;y++){			

			if (j < matrixSize)
				difference = (*dMatrix)[j][11-y] - (*dMatrix)[j-1][11-y];
			else 
				difference = 0;
			
			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::drawDoubleMatrix(DoubleMatrix* dMatrix){
	//used to draw the chromagram matrix
	int matrixSize = (*dMatrix).size();
	if (matrixSize > 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++){
			
			if (j < matrixSize)
			ofSetColor(0,0,255 * (*dMatrix)[j][11-y]);
			else 
			ofSetColor(0,0,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::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 : file %s okay, ", infilename);
		printf("number of channels is %i\n", sfinfo.channels);
		sndfileInfoString = "Opened okay ";
		
	};
	
}


void testApp::processAudioToDoubleMatrix(Chromagram* chromaG, DoubleMatrix* myDoubleMatrix, DoubleVector* energyVector){

	myDoubleMatrix->clear();
	energyVector->clear();
	
	audioHolder.audioVector.clear();
	audioHolder.audioMatrix.clear();
	
//	energyIndex = 0;
//	frameIndex = 0;
//	chromaIndex = 0;//	WHY NEED THIS?
	chromaG->initialise(FRAMESIZE,2048);//framesize 512 and hopsize 2048 
	chromaG->maximumChromaValue = 0;
	
	


// HERE IS THE CLASSIC LOADING FILE CODE
 //DEALS WITH MORE THAN MONO
	int channels = sfinfo.channels;
	int blocksize = FRAMESIZE;
	
	float buf [channels * blocksize] ;
	int k, m, readcount ;
	
	DoubleVector d;
	while ((readcount = sf_readf_float (infile, buf, blocksize)) > 0){
		for (k = 0 ; k < readcount ; k++){	
			d.clear();
			for (m = 0 ; m < channels ; m++){
				d.push_back(buf [k * channels + m]);
				//		 fprintf (outfile, " % 12.10f", buf [k * channels + m]) ;
				//		 fprintf (outfile, "\n") ;
					if (m == 0){
					//makes the vector hold the mono file
					//this is the one we use for chromagram analysis etc
					audioHolder.audioVector.push_back(buf[k * channels + 0]);
					frame[k] = buf[k*channels + 0];
					}
				
			} 
			audioHolder.audioMatrix.push_back(d);
			//storing the full soundfile in multiple channels in the audioMatrix
		}
		
		
		chromaG->processframe(frame);
		
		if (chromaG->chromaready)
		{
			DoubleVector d;
			
			for (int i = 0;i<12;i++){
				//chromoGramVector[chromaIndex][i] = chromoGramm.rawChroma[i] / chromoGramm.maximumChromaValue;
				d.push_back(chromaG->rawChroma[i]);// / chromaG->maximumChromaValue);	
				
			}	
			
			myDoubleMatrix->push_back(d);
			
			//There was a method to detect chord but deleted
			//	chord.C_Detect(chromoGramm.chroma,chromoGramm.chroma_low);
			//	rootChord[chromaIndex] = chord.root;
			
			
		}//end if chromagRamm ready
		
	//	frameIndex++;
		
		//get energy of the current frame and wait
		double energyValue = getEnergyOfFrame();
		energyVector->push_back(energyValue);
		
		
		
	}//end 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;	
		}
	}
	

	printf("size of energy vector is %d \n", (int) energyVector->size());
	
	totalNumberOfFrames = (int) energyVector->size();//frameIndex;//used to use this - but switch to energy vector's size instead

//	printf("Total frames %i energy index %i and Chroma index %i \n", frameIndex, energyIndex, chromaIndex);
	
	printf("audio vector size is %i\n", (int) audioHolder.audioVector.size());
	audioHolder.length = (int) audioHolder.audioVector.size();
}


//--------------------------------------------------------------
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 == 'q')
		screenToDraw = 1 - screenToDraw;
	
	if (key == OF_KEY_DOWN){
		if (scrollWidth > 600)
		scrollWidth += 400;
		else
		scrollWidth *= 2;
	}
	
	if (key == OF_KEY_RIGHT){
		loadedAudio.setPosition(min(1.0, loadedAudio.getPosition() + (audioHolder.audioScaleSamples/(4.0*audioHolder.audioVector.size()))) );
//	audioHolder.playPosition = loadedAudio.getPosition() * audioHolder.audioVector.size();
	}
	
	if (key == OF_KEY_LEFT){
		loadedAudio.setPosition(max(0.0, loadedAudio.getPosition() - (audioHolder.audioScaleSamples/(4.0*audioHolder.audioVector.size()))));
		//	audioHolder.playPosition = loadedAudio.getPosition() * audioHolder.audioVector.size();
	}
	
	
	if (key == OF_KEY_UP){
		if (scrollWidth > 600)
		scrollWidth -= 400;
		else
		scrollWidth /= 2;
	}
		
		if (key == ' '){
			if (!audioPlaying) {
				loadedAudio.play();
				loadedAudio.setPaused(false);
				audioPlaying = true;
				audioPaused = false;
			}
			else{
			audioPaused = !audioPaused;
			loadedAudio.setPaused(audioPaused);
			}
		
		}

	if (key == OF_KEY_RETURN){
			audioPlaying = false;
			loadedAudio.setPaused(true);
		loadedAudio.setPosition(0.0);
	}
	
	
	if (key == 'o'){
		openNewAudioFileWithdialogBox();
	}

		
	if (key == 'd'){
		drawSpectralDifferenceFunction = !drawSpectralDifferenceFunction;
	}
	
	if (key == 'u'){
		audioScale *= 2.;
	audioHolder.audioScaleSamples *= 2.;
	}
	
	if (key == 'j'){
		audioScale /= 2.;	
		audioHolder.audioScaleSamples /= 2.;
	}
}

//--------------------------------------------------------------
void testApp::keyReleased  (int key){

}

void testApp::openNewAudioFileWithdialogBox(){
	
	//open audio file
	string *filePtr;
	filePtr = &soundFileName;	
	
	if (getFilenameFromDialogBox(filePtr)){
		printf("Mainfile: Loaded name okay :\n'%s' \n", soundFileName.c_str());	
	}
	
	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);
	xIndex = (int)(pan*firstEnergyVector.size());
}

//--------------------------------------------------------------
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;
}
//--------------------------------------------------------------
void testApp::audioRequested 	(float * output, int bufferSize, int nChannels){
	//pan = 0.5f;
	float leftScale = 1 - pan;
	float rightScale = pan;

}


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


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 canceled. ";
	}
	
	

}


void testApp::loadNewAudio(string soundFileName){

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

	processAudioToDoubleMatrix(&chromoGramm, &chromaMatrix, &firstEnergyVector);
	
	audioPlaying = false;
}






double testApp::getEnergyOfFrame(){
	
	float totalEnergyInFrame = 0;
	
	for (int i = 0;i<FRAMESIZE;i++){
		
		totalEnergyInFrame += (frame[i] * frame[i]);
		
	}
	totalEnergyInFrame = sqrt(totalEnergyInFrame);
	
	return totalEnergyInFrame;
}




//JUNK METHODS BEFORE SWITCHING TO VECTORS TO HOLD ENERGY AND CHROMA
//THESE ARE BETTER AS THEY ARE DYNAMIC

/*
 void testApp::drawChromoGram(){
 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(255*chromoGramVector[j][11-y],0,0);
 ofRect(i*screenWidth/chromoLength,y*screenHeight/12,screenWidth/chromoLength,screenHeight/12);
 }//end y
 }//end i
 
 }
 */



/*
 void testApp::drawChromaMatrix(){
 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,255*chromaMatrix[j][11-y],0);
 ofRect(i*screenWidth/chromoLength,y*screenHeight/12,screenWidth/chromoLength,screenHeight/12);
 }//end y
 }//end i
 
 }
 */




/*
 
 
 int readcount = 1; // counts number of samples read from sound file
 printf("processing audio from doublematrix \n");
 
 while(readcount != 0 && moveOn == true)
 {
 
 // read FRAMESIZE samples from 'infile' and save in 'data'
 readcount = sf_read_float(infile, frame, FRAMESIZE);
 
 
 for (int i = 0;i < FRAMESIZE;i++)
 audioHolder.audioVector.push_back(frame[i]);
 
 printf("frame%f\n", frame[0]);
 //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++){
 //chromoGramVector[chromaIndex][i] = chromoGramm.rawChroma[i] / chromoGramm.maximumChromaValue;
 d.push_back(chromaG->rawChroma[i]);// / chromaG->maximumChromaValue);	
 
 }	
 
 myDoubleMatrix->push_back(d);
 
 //There was a method to detect chord but deleted
 //	chord.C_Detect(chromoGramm.chroma,chromoGramm.chroma_low);
 //	rootChord[chromaIndex] = chord.root;
 
 
 }//end if chromagRamm ready
 
 //printf("calling drawSndFile %i", frameIndex);
 //	frameIndex++;
 
 //get energy of the current frame and wait
 double energyValue = getEnergyOfFrame();
 energyVector->push_back(energyValue);
 
 
 }//end while readcount
 
 
 */