view jnmr/testApp.cpp @ 52:13194a9dca77 tip

Added exporting of image and text data
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Tue, 17 Jul 2012 22:13:10 +0100
parents 158f5f38e9d3
children
line wrap: on
line source
#include "testApp.h"


testApp::testApp(ofxArgs* args){
	this->args = args;
}

#pragma mark -Initialise

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

	
	
	root = "/Users/andrew/Documents/work/Alignment/MuseScore/RWC/Classical_RWC_Groundtruth/RM-C0";
	outputFileRoot = "../../../data/FilesOut/rwcOutputData_RM-C0";
	annotationRoot = "/Users/andrew/Documents/work/Alignment/MuseScore/RWC/ANNOTATION/RM-C0";
	//myfile.open("../../../data/FilesOut/exampletest2.txt");
	
	
	
 	//diffFile.open("../../../data/FilesOut/diffTest.txt");
	
//	midiEvents.fileOutput = &myfile;
	
	
	
	this->args->printArgs();
	this->args->printOpts();

	createRWCfilenameStrings();
	
	loadRWCfileNumber(2);
	openOutputFile(2);
	loadAnnotation(2);

	midiEvents.differenceOutput = &diffFile;
	
/*	if (this->args->getCount() > 0){
		museScoreFilename = this->args->getString(1);
	//printf("MUSESCORE FILENAME IS %s\n", museScoreFilename);
	cout << "running!! " << museScoreFilename << endl;
	midiFileName = museScoreFilename;
	}
*/	

	int retVal = cannamMainFunction();
	
	ofSetVerticalSync(true);
	//ofBackground(255,255,255);
	midiPort = 2;
	midiIn.listPorts();
	midiIn.openPort(midiPort);
	midiPortName = "";
	//midiPortName = midiIn.portNames(midiPort);
	
	transpose = 0;
	noteInStream.transposeVal = &transpose;
	
	noteInStream.startTime = &midiEvents.startPlayingTime;//point start time of note in stream to the same time in MIDI events

	noteInStream.factor = &midiEvents.ticksFactor;
	printf("TICKS FACTOR %f \n", midiEvents.ticksFactor);//noteInStream->factor)
	
//	portName = "hello";//midiIn.portNames[2];
//	printf("MIDI PORT %c\n", portName);
	cout << "MIDI PORT " << endl;//portName << endl;
	
	
	//midiIn.addListener(this);	
	ofAddListener(midiIn.newMessageEvent, this, &testApp::newMessage);

	
	verdana30.loadFont("verdana.ttf", 50, true, true);
	verdana30.setLineHeight(48.0f);
	verdana30.setLetterSpacing(1.035);
	
	playing = false;
	readyToStart = true;
	
	receiver.setup( PORT );

	sender.setup( HOST, SEND_PORT );
	
	screenWidth = ofGetWidth();
	screenHeight = ofGetHeight();
	midiEvents.screenWidth = &screenWidth;
	midiEvents.screenHeight = &screenHeight;
	//midiEvents.drawTempoMode = true;
	ofSetFrameRate(30);
	
	midiEvents.ticksPerScreen += 4000;
	lastScoreIndexSent = 0;
	performanceRating = 0.0;

	liveInputPlaying = false;
	lastScoreIndexSent = 0;
	midiEvents.bestMatchIndex = 0;
	
	
}
#pragma mark -Update
//--------------------------------------------------------------
void testApp::update(){
	if (playing){
		midiEvents.updatePlayPosition();//this fn calls	midiEvents.bayesStruct.updateBestEstimate();
	}
//	drawer.tickLocation+=20;
	checkOSCmessages();
	
	if (midiEvents.recordedEventTimes.size() > 0)
	checkNewScoreNote();
	
}

void testApp::checkOSCmessages(){
	
	// check for waiting messages
	while( receiver.hasWaitingMessages() )
	{
		ofxOscMessage m;
		receiver.getNextMessage( &m );
		
		if ( m.getAddress() == "/midinoteon" )
		{
			int newMidiOnPitch = m.getArgAsInt32(0) + transpose;
			int velocity = m.getArgAsInt32(1);
			double time = m.getArgAsFloat(2);
			
			if (velocity != 0){
				if (readyToStart){
					startPlaying();
					printf("starting to PLAY!!!");
				}
				//	printf("MIDI NOTE %i \n", newMidiOnPitch);
				midiEvents.newNoteOnEvent(newMidiOnPitch, velocity, time);
				noteInStream.newNoteCounted(newMidiOnPitch);//counts notes for an overall score
			}
			
		}
		
		if ( m.getAddress() == "/setSpeedPrior" )
		{
			float speedPrior = m.getArgAsFloat(0);
			printf("speed prior set to %f\n", speedPrior);
			midiEvents.speedPriorValue = speedPrior;
			//midiEvents.bayesStruct.speedPriorValue = speedPrior;
		}
		
		if ( m.getAddress() == "/startplaying" )
		{
			//			prepareToStartOnNextNote();
			startPlaying();
		}
		
		if ( m.getAddress() == "/stopplaying" )
		{
			stopPlaying();
		}
		
		
		if ( m.getAddress() == "/integratedEstimate" )
		{
			midiEvents.bayesStruct.usingIntegratedTempoEstimate = true;
		}
		
		if ( m.getAddress() == "/MAPestimate" )
		{
			midiEvents.bayesStruct.usingIntegratedTempoEstimate = false;
		}
		
		
		if ( m.getAddress() == "/realtime" )
		{
			midiEvents.runningInRealTime = true;
		}
		
		
		if ( m.getAddress() == "/offline" )
		{
			midiEvents.runningInRealTime = false;
		}
		
		if ( m.getAddress() == "/minimumSpeedRatio" )
		{
			
			float minSpeed = m.getArgAsFloat(0);
			//printf("minimum speed received is  %f and max is %f\n", minSpeed, midiEvents.bayesStruct.relativeSpeedLikelihood.getIndexInRealTerms(midiEvents.bayesStruct.relativeSpeedLikelihood.length-1));
			if (minSpeed > 0 && minSpeed < midiEvents.bayesStruct.relativeSpeedLikelihood.getIndexInRealTerms(midiEvents.bayesStruct.relativeSpeedLikelihood.length-1)){
				printf("minimum speed accepted is %f\n", minSpeed);
				midiEvents.minimumMatchSpeed = minSpeed;
			}
		}
		
		if ( m.getAddress() == "/maximumSpeedRatio" )
		{
			
			float maxSpeed = m.getArgAsFloat(0);
			//printf("minimum speed received is  %f and max is %f\n", minSpeed, midiEvents.bayesStruct.relativeSpeedLikelihood.getIndexInRealTerms(midiEvents.bayesStruct.relativeSpeedLikelihood.length-1));
			if (maxSpeed > midiEvents.minimumMatchSpeed && maxSpeed <= midiEvents.bayesStruct.relativeSpeedLikelihood.getIndexInRealTerms(midiEvents.bayesStruct.relativeSpeedLikelihood.length-1)){
				printf("maximum speed accepted is %f\n", maxSpeed);
				midiEvents.maximumMatchSpeed = maxSpeed;
			}
		}
		
		if ( m.getAddress() == "/likelihoodToNoiseRatio" )
		{
			
			float ratio = m.getArgAsFloat(0);
			
			if (ratio > 0.001 && ratio < 0.6){
				midiEvents.likelihoodToNoiseRatio = ratio;
				printf("likelihood for events relative to noise uses ratio %f\n", ratio);
			}
			
		}
		
		if ( m.getAddress() == "/duration" )
		{
			
			float playedDuration = m.getArgAsFloat(0);
			double recordedDuration =	midiEvents.recordedEventTimes[midiEvents.recordedEventTimes.size()-1];
			midiEvents.speedPriorValue = recordedDuration/playedDuration;
			midiEvents.testSpeedPriorSetting();
			printf("played duration %f, recorded %f\n", playedDuration, recordedDuration);
			printf("speed prior set to %f\n", midiEvents.bayesStruct.speedPriorValue);
			
		}
		
		if ( m.getAddress() == "/RWCfile" ){
			openOutputFile(m.getArgAsInt32(0));
			loadRWCfileNumber(m.getArgAsInt32(0));
			loadAnnotation(m.getArgAsInt32(0));
		}
		
		
	}//end while osc
	
}


void testApp::checkNewScoreNote(){
	if (lastScoreIndexSent != midiEvents.bestMatchIndex){
	//then we send out new note
		sendNoteToMuseScore();
		lastScoreIndexSent = midiEvents.bestMatchIndex;
		findMeasure();
	}
}

void testApp::findMeasure(){
	int ticks = midiEvents.recordedNoteOnMatrix[midiEvents.bestMatchIndex][0];
	int tmpMeasure = lastMeasureSent;
	
	while (lastMeasureSent > 0 && midiEvents.measureVector[lastMeasureSent] > ticks) {
		lastMeasureSent--;
	}
	
	while (lastMeasureSent < midiEvents.measureVector.size() && midiEvents.measureVector[lastMeasureSent] < ticks) {
		lastMeasureSent++;
	}
	if (lastMeasureSent != tmpMeasure){
	//sendMeasureToMuseScore();
	performanceRating =	noteInStream.calculateTotalScore(midiEvents);
	}
	

}

void testApp::sendBlackNotes(){
	ofxOscMessage m;
	m.setAddress( "/plugin" );
	string noteString;	
	noteString = "blacknotes.js";
	m.addStringArg( noteString);
	sender.sendMessage( m ); 
}

void testApp::sendNoteToMuseScore(){
	int noteToSendIndex = lastScoreIndexSent;
	while (noteToSendIndex < midiEvents.bestMatchIndex){
		noteToSendIndex++;
		if (midiEvents.recordedNoteOnMatrix.size() > 0 && noteToSendIndex < midiEvents.recordedNoteOnMatrix.size()){
			int ticks = midiEvents.recordedNoteOnMatrix[noteToSendIndex][0];//midiEvents.bestMatchIndex
			int pitch = midiEvents.recordedNoteOnMatrix[noteToSendIndex][1];
			//	printf("sending to muse score %i, %i \n", ticks, pitch);
			sendNoteDataByOsc(pitch, ticks);
		}
	}
	/*
		ofxOscMessage m;
		m.setAddress( "/plugin" );
		string noteString;	
		noteString = "blackNotes.js";
		m.addStringArg( noteString);
		sender.sendMessage( m ); 
	*/

	
//	/color-note 60,3440
	
	//crappy javascript message
	/*
			ofxOscMessage m;
			m.setAddress( "/plugin" );
			string noteString;	
			noteString = "coloronenote.js";
			noteString += ",myTick,"+ofToString(ticks)+",myPitch,"+ofToString(pitch);
		//	printf("%s\n", noteString);
			m.addStringArg( noteString);
			sender.sendMessage( m ); */

		   
	//	   /plugin coloronenote.js mytick 100 mypitch 56;
}

void testApp::sendNoteDataByOsc(const int& pitch, const int& ticks){
	ofxOscMessage m;
	m.setAddress( "/color-note" );
	string noteString;	
	noteString = ofToString(ticks);
	noteString += ","+ofToString(pitch);
	m.addStringArg( noteString);
	sender.sendMessage( m );
}

void testApp::sendMeasureToMuseScore(){

	printf("sending measure to muse score %i \n", lastMeasureSent);
	
	ofxOscMessage m;
	m.setAddress( "/select-measure" );
	m.addIntArg(lastMeasureSent);
	sender.sendMessage( m );  
	
	//		/select-measure 6
	//	   /plugin coloronenote.js mytick 100 mypitch 56;
}


void testApp::newMessage(ofxMidiEventArgs &args){

	int pitch;
	if (noteInStream.noteInReceived(args)){
	double timeNow = ofGetElapsedTimeMillis();
		
		if (!liveInputPlaying){
			firstNoteTime = timeNow;
			liveInputPlaying = true;
			startPlaying();
			printf("FIRST LIVE NOTE IS NOW AT TIME %f\n", timeNow);
		}
		
		pitch = args.byteOne + transpose;
		
		midiEvents.newNoteOnEvent(pitch, args.byteTwo, timeNow - firstNoteTime);
		
		
		int tickTime = midiEvents.getEventTimeTicks(timeNow-firstNoteTime);
		IntVector v;
		v.push_back(tickTime);
		v.push_back(pitch);
		v.push_back(args.byteTwo);
		v.push_back(200);//tmp time til note off happens
		noteInStream.midiInputEvents.push_back(v);
		noteInStream.midiInputTimes.push_back(timeNow - firstNoteTime);
		//printf("NOTE %i at time %f at tick time %i\n", pitch, (timeNow - firstNoteTime), tickTime);
	}
	
//	cout << "MIDI message [port: " << args.port << ", channel: " << args.channel << ", status: " << args.status << ", byteOne: " << pitch << ", byteTwo: " << args.byteTwo << ", timestamp: " << args.timestamp << "]" << endl;
}

#pragma mark -Draw

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

	midiEvents.drawFile();
/*	
	string info = "Measure ";
	info += ofToString(lastMeasureSent);
	info += "  Last note ";
	info += ofToString(lastScoreIndexSent);	
	ofDrawBitmapString(info, 20, 20);
*/	
	midiEvents.drawMidiFile(noteInStream.midiInputEvents);

	//drawMuseScoreText();
	
	ofSetHexColor(0x000000);
	ofDrawBitmapString(midiPortName, 20, ofGetHeight() - 20);
	
}

void testApp::drawMuseScoreText(){
	string ratingString = ofToString(performanceRating*100,0)+"%";
	if (performanceRating > 0.84)
		ratingString += "!* *";
	string extraText = "";
	if (performanceRating > 0.9){
		extraText += " pretty good, huh?";
	}
	if (performanceRating > 0.95)
		extraText = " blimey! ";
	if (performanceRating > 0.97)
		extraText = " maestro!";
	
	ratingString += extraText;  
	verdana30.drawString(ratingString, 20, 60);
}

#pragma mark -keyInput
//--------------------------------------------------------------
void testApp::keyPressed(int key){

	if (key == '.'){
		midiPort++;
		midiIn.openPort(midiPort);
	}

	if (key == ',' && midiPort > 0){
		midiPort--;
		midiIn.openPort(midiPort);
	}

	if (key == '-')
		transpose -= 12;
	
	if (key == '=')
		transpose += 12;
	
	if (key == 'c'){
		double timenow = ofGetElapsedTimeMillis();
		//midiEvents.exampleCrossUpdate();
		timenow *= -1;
		timenow += ofGetElapsedTimeMillis();
		printf("CROSS UPDATE TOOK %f", timenow);
	}

	
	if (key == OF_KEY_LEFT){
		
	}
	
	if (key == OF_KEY_RIGHT)
	
	if (key == OF_KEY_RETURN)
		stopPlaying();
	
	if (key == OF_KEY_UP){
		if (midiEvents.ticksPerScreen >= 4000)
		midiEvents.ticksPerScreen += 2000;
		else 
			midiEvents.ticksPerScreen += 500;
	}
	
	if (key == 'm'){
//		midiEvents.findMatch(84, 0, 10000);
	}
	
	if (key == 'b'){
		sendBlackNotes();
	}
	
	
	if (key == 'n'){
		midiEvents.printInterNoteIntervals();
	}
	
	if (key == OF_KEY_DOWN){
		if (midiEvents.ticksPerScreen >= 4000)
		midiEvents.ticksPerScreen -= 2000;
	else if (midiEvents.ticksPerScreen > 500)
		midiEvents.ticksPerScreen -= 500;
	}
	
	if (key == 'w')
		midiEvents.printMatchMatrix();
	
	if (key == 'k'){
		noteInStream.printNotes();
	}
	
	if (key == 'p'){
		//midiEvents.printNotes();
		midiEvents.bayesStruct.posterior.printArray();
	}

	if (key == 'l')
		midiEvents.bayesStruct.decaySpeedDistribution(100);
	
	if (key == 'f'){
		//flip
		midiEvents.drawTempoMode = !midiEvents.drawTempoMode;
		midiEvents.drawPhaseMode = !midiEvents.drawPhaseMode;
	}
	
	
	if (key == 't'){
		midiEvents.drawTempoMode = !midiEvents.drawTempoMode;
	}
	
	if (key == 'y')
		midiEvents.drawPhaseMode = !midiEvents.drawPhaseMode;
	
	if (key == 'r'){
		noteInStream.reset();
		liveInputPlaying = false;
		stopPlaying();
		lastMeasureSent = 0;
		sendMeasureToMuseScore();
		sendBlackNotes();
		lastScoreIndexSent = 0;
		performanceRating = 0;
		
	}
	
	if (key == 'o' || key == 'O'){
		loadRecordedMidiFile();
	}

	if (key == 'v'){
		midiEvents.bayesStruct.drawPrior = midiEvents.bayesStruct.drawPosterior;
		midiEvents.bayesStruct.drawLikelihood = !midiEvents.bayesStruct.drawLikelihood;
		midiEvents.bayesStruct.drawPrior = !midiEvents.bayesStruct.drawPrior;
		midiEvents.bayesStruct.drawPosterior = !midiEvents.bayesStruct.drawPosterior;
	}
	
	if (key == 'x'){
	midiEvents.bayesStruct.drawPrior = !midiEvents.bayesStruct.drawPrior;
	}
	
	if (key == 'g'){
		midiEvents.writeAllDistributions();
	}
}

void testApp::loadRecordedMidiFile(){
	//open audio file
	string *filePtr;
	filePtr = &midiFileName;	
	
	if (getFilenameFromDialogBox(filePtr)){
		printf("Midifile: Loaded name okay :\n'%s' \n", midiFileName.c_str());	
		cannamMainFunction();
	}
}

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

}

//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y ){
	midiEvents.mouseX = midiEvents.getEventTimeMillis((x * midiEvents.ticksPerScreen)/ screenWidth);
}

//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::windowResized(int w, int h){
	screenWidth = w;
	screenHeight = h;
	midiEvents.noteHeight = screenHeight / (float)(midiEvents.noteMaximum - midiEvents.noteMinimum);
	
}

void testApp::prepareToStartOnNextNote(){
	readyToStart = true;
}


void testApp::startPlaying(){
	playing = !playing;
	midiEvents.reset();
	noteInStream.reset();
	midiEvents.setStartPlayingTimes();
	sendBlackNotes();
	readyToStart = false;
	//this is where we stop and start playing
}

void testApp::stopPlaying(){
	//midiEvents.printNoteCounter();
	//noteInStream.printTotalCount();
	
	noteInStream.calculateTotalScore(midiEvents);
	
	
	playing = false;
	liveInputPlaying = false;
	lastScoreIndexSent = 0;
	midiEvents.bestMatchIndex = 0;
	sendNoteToMuseScore();
	
	diffFile.close();
	//myfile.close();
	
}

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::openOutputFile(const int& i){
	if (diffFile.is_open())
		diffFile.close();
	string endBit = ".txt";
	string outputFileName = makeRWCfilename(outputFileRoot, i, endBit);
	/*
	if (i >= 10)
		outputFileName = outputFileRoot + ofToString(i)+".txt";
	else
		outputFileName = outputFileRoot + "0"+ofToString(i)+".txt";
	*/
	diffFile.open(outputFileName.c_str());
}

void testApp::loadRWCfileNumber(const int& i){
	if (i >= 0 && i <= 64){
		/*midiFileNumber = i;
			if (i >= 10)
				midiFileName = root + ofToString(midiFileNumber)+".MID";
			else
				midiFileName = root + "0"+ofToString(midiFileNumber)+".MID";
		*/
		midiFileName = root + rwcFileNameStrings[i]+".MID";
		printf("MIDI FILE:%s\n", midiFileName.c_str());
		cannamMainFunction();
	}
}

std::string testApp::makeRWCfilename(std::string& root, const int& fileID, std::string& endPart){
	std::string pathName;
	if (fileID >= 0 && fileID <= 64){

		pathName = root + rwcFileNameStrings[fileID]+endPart;
		/*
		if (fileID >= 10)
			pathName = root + ofToString(fileID)+endPart;
		else
			pathName = root + "0"+ofToString(fileID)+endPart;
		*/
		printf("MAKE FILE:%s\n", midiFileName.c_str());
	}
		return pathName;
}

void testApp::createRWCfilenameStrings(){
	rwcFileNameStrings.clear();
	for (int i = 1;i< 10;i++){
		rwcFileNameStrings.push_back("0"+ofToString(i));
	}
	for (int i = 10;i< 23;i++){
		rwcFileNameStrings.push_back(ofToString(i));
	}
	rwcFileNameStrings.push_back("23A");
	rwcFileNameStrings.push_back("23B");
	rwcFileNameStrings.push_back("23C");
	rwcFileNameStrings.push_back("23D");
	rwcFileNameStrings.push_back("23E");

	rwcFileNameStrings.push_back("24A");
	rwcFileNameStrings.push_back("24B");
	rwcFileNameStrings.push_back("24C");
	
	rwcFileNameStrings.push_back("25A");
	rwcFileNameStrings.push_back("25B");
	rwcFileNameStrings.push_back("25C");
	rwcFileNameStrings.push_back("25D");

	for (int i = 26;i< 35;i++){
		rwcFileNameStrings.push_back(ofToString(i));
	}
	rwcFileNameStrings.push_back("35A");
	rwcFileNameStrings.push_back("35B");
	rwcFileNameStrings.push_back("35C");
	for (int i = 36;i< 51;i++){
		rwcFileNameStrings.push_back(ofToString(i));
	}
	
//	for (int i = 0;i < rwcFileNameStrings.size();i++) {
//		printf("RWC{%i}:'%s'\n", i, rwcFileNameStrings[i].c_str());
//	}
	
}

void testApp::loadAnnotation(const int& fileID){
	
	string annotationEnding = "_annotation+WavPos.csv";
	string path = makeRWCfilename(annotationRoot, fileID, annotationEnding );
	midiEvents.myNotation.readInRWCfile(path);
}

int testApp::cannamMainFunction(){


	midiEvents.clearAllEvents();
	
	//int main(int argc, char **argv)
	//{
	//	if (argc != 2) {
	//		cerr << "Usage: midifile <file.mid>" << endl;
	//		return 1;
	//	}
		
	std::string filename = midiFileName;//argv[1];
	printf("Loading'%s'\n", midiFileName.c_str());

	fileLoader.loadFile(filename, midiEvents);
	
}//new end of load function

/*
void testApp::readInSomeValues(){
	

	printf("READ FILE\n");
	ifstream file ( "/Users/andrew/Documents/work/MuseScore/RWC/ANNOTATION/RM-C002_annotation+WavPos.csv" ); // declare file stream: http://www.cplusplus.com/reference/iostream/ifstream/
	string value;
	int count = 0;
	while ( file.good() )
	{
		getline ( file, value, ',' ); // read a string until next comma: http://www.cplusplus.com/reference/string/getline/
		cout << string( value, 1, value.length()-2 ); // display value removing the first and the last character from it
		
		string::size_type start = value.find_first_not_of(" \t\v");
		string part = value.substr(start, string::npos);
		//printf("%s (%i)\n", part.c_str(), count);
		float my_float;
		int my_int;
		switch (count%6) {
			case 1:
				printf("reading %s\n", part.c_str());
				my_float = atof(part.c_str());
				printf("float is %f\n", my_float);
				break;
			case 2:
				printf("reading %s\n", part.c_str());
				my_int = atoi(part.c_str());
				printf("float is %i\n", i);
				break;	
				
			default:
				break;
		}
		count++;
	}
	
}

 */