view hackday/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 f91b7b019350
children
line wrap: on
line source
#include "testApp.h"


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

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

 this->args->printArgs();
	this->args->printOpts();
	midiFileName = "../../../data/frerejacques.mid";
	
	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.startTime;//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;
	
}

//--------------------------------------------------------------
void testApp::update(){
	if (playing){
		midiEvents.updatePlayPosition();//this fn calls	midiEvents.bayesStruct.updateBestEstimate();
	}
//	drawer.tickLocation+=20;
	
	// 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);
			}

		}
		
		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();
		}
		
		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);
			}
		
		}
		
	}//end while osc
	if (midiEvents.recordedEventTimes.size() > 0)
	checkNewScoreNote();
	
}


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(){
	if (midiEvents.recordedNoteOnMatrix.size() > 0){
	int ticks = midiEvents.recordedNoteOnMatrix[midiEvents.bestMatchIndex][0];
	int pitch = midiEvents.recordedNoteOnMatrix[midiEvents.bestMatchIndex][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;
}

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

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

//	ofDrawBitmapString("Rating "+ofToString(performanceRating*100), 60, 50);
	//ofDrawBitmapString("filename "+museScoreFilename, 20, 80);
	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);
	
	ofSetHexColor(0x000000);
	ofDrawBitmapString(midiPortName, 20, ofGetHeight() - 20);
	
}

//--------------------------------------------------------------
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 == 'x')
		sendNoteDataByOsc(60, 0);
	
	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();
	}

	if (key == 'l')
		
		
		//midiEvents.bayesStruct.decaySpeedDistribution(100);
	
	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();
	}

	
	
}

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();
	
}

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;
	}
	
	
	
}




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];
	
//	fileLoader.chopBeginning = true;
	fileLoader.loadFile(filename, midiEvents);
	
}//new end of load function