changeset 25:2a025ea7c793

hackday work to get live midi input, follow the notes, output measure, read measure in with midi file
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Sat, 03 Dec 2011 21:09:13 +0000
parents 5a11b19906c7
children 179365726f07
files hackday/CannamMidiFileLoader.cpp hackday/CannamMidiFileLoader.h hackday/MidiInputStream.cpp hackday/midiEventHolder.cpp hackday/midiEventHolder.h hackday/testApp.cpp hackday/testApp.h
diffstat 7 files changed, 184 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/hackday/CannamMidiFileLoader.cpp	Sat Dec 03 17:19:43 2011 +0000
+++ b/hackday/CannamMidiFileLoader.cpp	Sat Dec 03 21:09:13 2011 +0000
@@ -21,7 +21,7 @@
 		
 		setTempoFromMidiValue(500000, myMidiEvents);//default is 120bpm
 		myMidiEvents.pulsesPerQuarternote = 240;//default
-	
+		myMidiEvents.measureVector.push_back(0);
 		//int main(int argc, char **argv)
 		//{
 		//	if (argc != 2) {
@@ -54,6 +54,8 @@
 				if (printMidiInfo)
 					cout << "Timing division: " << fr.getTimingDivision() << " ppq" << endl;
 			myMidiEvents.pulsesPerQuarternote = fr.getTimingDivision();
+			ticksPerMeasure = myMidiEvents.pulsesPerQuarternote * 4;//default setting
+			
 		} else {
 			int frames = 256 - (td >> 8);
 			int subframes = td & 0xff;
@@ -102,9 +104,9 @@
 								if (printMidiInfo)
 								cout << t << ": Tempo: " << 60000000.0 / double(tempo) << endl;
 							setTempoFromMidiValue(tempo, myMidiEvents);
-							
-							
+						
 							printf("period double is %f\n", myMidiEvents.period);
+						
 						}
 							break;
 							
@@ -112,8 +114,12 @@
 						{
 							int numerator = j->getMetaMessage()[0];
 							int denominator = 1 << (int)j->getMetaMessage()[1];
-							if (printMidiInfo)
+							
+							newTimeSignature(t, numerator, denominator, myMidiEvents);
+							
+							//if (printMidiInfo)
 							cout << t << ": Time signature: " << numerator << "/" << denominator << endl;
+							printf(" ticks %i Time signature: %i by %i ", t,  numerator , denominator );
 						}
 							
 						case MIDI_KEY_SIGNATURE:
@@ -259,15 +265,26 @@
 	if (printMidiInfo)
 	myMidiEvents.printRecordedEvents();
 	
+	//printMeasuresSoFar(myMidiEvents);
+	
+	if (myMidiEvents.recordedNoteOnMatrix.size() > 0){
+		
+		printf("END FILE MEASURE UPDATE\n");
+		updateMeasureToTickPosition(myMidiEvents.recordedNoteOnMatrix[myMidiEvents.recordedNoteOnMatrix.size()-1][0], myMidiEvents);
+	//	printMeasuresSoFar(myMidiEvents);
+	}
+	
 //	printf("|||||||||||||||||||||| \n\n\n\n\n\n\n");
 	myMidiEvents.reorderMatrixFromNoteTimes(myMidiEvents.recordedNoteOnMatrix);
 	myMidiEvents.correctTiming(myMidiEvents.recordedNoteOnMatrix);
 	myMidiEvents.doublecheckOrder(myMidiEvents.recordedNoteOnMatrix);
 
 	createEventTiming(myMidiEvents);
-
+	
 	if (printMidiInfo)
-	myMidiEvents.printRecordedEvents();		
+	myMidiEvents.printRecordedEvents();	
+	
+	//printMeasuresSoFar(myMidiEvents);
 	
 }//end cannam midi main
 	
@@ -298,4 +315,35 @@
 }
 	
 
+void CannamMidiFileLoader::newTimeSignature(int ticks, int numerator, int denominator, midiEventHolder& myMidiEvents){
 
+	updateMeasureToTickPosition(ticks, myMidiEvents);
+	
+	ticksPerMeasure = myMidiEvents.pulsesPerQuarternote * 4 * numerator / denominator;
+	
+}
+
+void CannamMidiFileLoader::updateMeasureToTickPosition(int ticks,  midiEventHolder& myMidiEvents){
+	printf("update measure at tick pos %i at tpm %i\n", ticks, ticksPerMeasure);
+	
+	int measureVectorSize = myMidiEvents.measureVector.size();
+	int lastMeasurePosition = 0;
+	
+	if (measureVectorSize > 0)
+		lastMeasurePosition = myMidiEvents.measureVector[measureVectorSize-1];
+	
+while (lastMeasurePosition < ticks){
+	//update
+	lastMeasurePosition += ticksPerMeasure;
+	myMidiEvents.measureVector.push_back(lastMeasurePosition);
+	cout << "MEASURE " << myMidiEvents.measureVector.size()-1 << " is " << lastMeasurePosition << endl;
+	printf("MEASURE %i is %i \n", (int)myMidiEvents.measureVector.size()-1 , lastMeasurePosition);
+	}
+}
+
+
+void CannamMidiFileLoader::printMeasuresSoFar(midiEventHolder& myMidiEvents){
+	for (int i = 0;i < myMidiEvents.measureVector.size();i++){
+		printf("measure [%i] at %i\n", i, myMidiEvents.measureVector[i]);
+	}
+}
\ No newline at end of file
--- a/hackday/CannamMidiFileLoader.h	Sat Dec 03 17:19:43 2011 +0000
+++ b/hackday/CannamMidiFileLoader.h	Sat Dec 03 21:09:13 2011 +0000
@@ -32,8 +32,11 @@
 	IntVector v;
 	int noteOnIndex;
 	
-	
+	int ticksPerMeasure;
+	void newTimeSignature(int ticks, int numerator, int denominator, midiEventHolder& myMidiEvents);
+	void updateMeasureToTickPosition(int ticks,  midiEventHolder& myMidiEvents);
 	bool printMidiInfo;
+	void printMeasuresSoFar(midiEventHolder& myMidiEvents);
 	
 };
 #endif
\ No newline at end of file
--- a/hackday/MidiInputStream.cpp	Sat Dec 03 17:19:43 2011 +0000
+++ b/hackday/MidiInputStream.cpp	Sat Dec 03 21:09:13 2011 +0000
@@ -32,9 +32,9 @@
 			newPitch = (int)args.byteOne;
 			newPitch += (*transposeVal);
 			
-			printf("note on %i", args.byteOne);
+	//		printf("note on %i", args.byteOne);
 			if (args.byteTwo){
-				printf("volume is %i\n", args.byteTwo);
+			//	printf("volume is %i\n", args.byteTwo);
 				double time = ofGetElapsedTimeMillis();
 				eventTimesForNote[newPitch] = time;
 				
@@ -43,10 +43,12 @@
 			}else{
 				double time = ofGetElapsedTimeMillis();
 				time -= eventTimesForNote[newPitch];
-				printf(", OFF after %f millis %f ticks\n", time, time * (*factor));
+			//	printf(", OFF after %f millis %f ticks\n", time, time * (*factor));
 				
 				int index = endNote(newPitch);
-				midiInputEvents[index].push_back(time * (*factor));
+				//correct the length of note time
+				if (midiInputEvents[index].size() > 2)
+				midiInputEvents[index][3] = (time * (*factor));
 			}
 			
 			break;
@@ -64,7 +66,7 @@
 	while (index > 0 && midiInputEvents[index][1] != notePitch){
 		index--;
 	}
-	printf("found index %i\n", index);
+//	printf("found index %i\n", index);
 	return index;
 }
 
--- a/hackday/midiEventHolder.cpp	Sat Dec 03 17:19:43 2011 +0000
+++ b/hackday/midiEventHolder.cpp	Sat Dec 03 21:09:13 2011 +0000
@@ -20,7 +20,7 @@
 	runningInRealTime = true;
 	bayesStruct.realTimeMode = &runningInRealTime;
 	
-	minimumMatchSpeed = 0.0;
+	minimumMatchSpeed = 0.5;
 	maximumMatchSpeed = 2.0;
 	minimumTimeIntervalForTempoUpdate = 150;
 	
@@ -105,7 +105,7 @@
 	matchesFound.clear();
 	noteOnMatches.clear();
 	recordedEventTimes.clear();
-	
+	measureVector.clear();
 	//played events:
 	playedEventTimes.clear();
 	playedNoteOnMatrix.clear();
@@ -140,7 +140,7 @@
 	//need to get new MAP position and set the offset of the arrays
 	//currently bestEstimate is the approx for the new MAP position
 	
-	
+	lastPlayedPitch = pitch;
 	//add the new event to our played information matrix
 	IntVector v;
 	v.push_back(pitch);
@@ -706,6 +706,16 @@
 		
 		int maxSize = recordedNoteOnMatrix[size-1][0];
 		
+		int tmpIndex = 0;
+		while (tmpIndex < measureVector.size() && measureVector[tmpIndex] < (numberOfScreensIn+1)*ticksPerScreen){
+			int measureLocation = measureVector[tmpIndex];
+		int xLocation = (float)(measureLocation - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen;
+			ofSetColor(155,155,0);
+			ofLine(xLocation, 0, xLocation, (*screenHeight));
+			tmpIndex++;
+		}
+		
+		
 	//	ofDrawBitmapString(tempoSpeedString, 20, 20);
 	/*	string indexString = "num screens in "+ofToString(numberOfScreensIn)+"; min index to print "+ofToString(minNoteIndexToPrint)+", max index to print "+ofToString(maxNoteIndexToPrint);
 		indexString += " size "+ofToString(size)+" tick loc "+ofToString(tickLocation)+" max size "+ofToString(maxSize);
@@ -717,13 +727,21 @@
 	
 	//ofDrawBitmapString(timeString, 20, 60);
 	
-
+//last played piutch
+	ofSetColor(0,200,0,50);
+	int yLocation = (*screenHeight) - ((lastPlayedPitch - noteMinimum )*(*screenHeight)/ (float)(noteMaximum - noteMinimum));						 
+	ofRect(0,yLocation, 100,  noteHeight);
+	
+	
+	
 }
 
 
 
 void midiEventHolder::drawMidiFile(IntMatrix& midiFileToDraw){
 	
+	//using this to draw the live input
+	
 	//draws midi file on scrolling screen
 	int size = midiFileToDraw.size();
 	if (size > 0){
@@ -752,23 +770,8 @@
 		
 		for (int tmpIndex = max(0,minNoteIndexToPrint);tmpIndex < min(maxNoteIndexToPrint, (int)midiFileToDraw.size());tmpIndex++){
 			
-			ofSetColor(255,0,255);
-	/*
-	 if (checkIfMatchedNote(tmpIndex))
-				ofSetColor(100,100,100);//0,0,255);
-			else if(noteOnMatches[tmpIndex]){
-				ofSetColor(255,0,255);//dark grey
-			}
-			else{
-				ofSetColor(255,255,255);//255,255,255);
-			}
-			*/
-			//ofSetColor(255,255,255);
-			if (tmpIndex == bestMatchIndex)
-				ofSetColor(255,0,0);//best recent match is in red
-			
-			//		 XXX replace ofgetwidth below
-			//if (tmpIndex >= 0 && tmpIndex < size)
+			ofSetColor(0,0,255, 200);
+
 			int xLocation = (float)(midiFileToDraw[tmpIndex][0] - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen;
 			int duration = (float)(midiFileToDraw[tmpIndex][3]*(*screenWidth))/(float)ticksPerScreen;
 			
--- a/hackday/midiEventHolder.h	Sat Dec 03 17:19:43 2011 +0000
+++ b/hackday/midiEventHolder.h	Sat Dec 03 21:09:13 2011 +0000
@@ -44,6 +44,7 @@
 	int playedNoteIndex;
 	IntMatrix matchMatrix;
 	IntVector bestMatchFound;
+	IntVector measureVector;
 	
 	DoubleMatrix matchConfidence;
 	double totalConfidence;
@@ -113,6 +114,7 @@
 	float noteHeight;
 	float tempo;
 	double lastPeriodUpdateTime;
+	int lastPlayedPitch;
 	
 	double playPositionInMillis;
 	
--- a/hackday/testApp.cpp	Sat Dec 03 17:19:43 2011 +0000
+++ b/hackday/testApp.cpp	Sat Dec 03 21:09:13 2011 +0000
@@ -13,7 +13,7 @@
 	midiIn.listPorts();
 	midiIn.openPort(2);
 	
-	transpose = 12;
+	transpose = 24;
 	noteInStream.transposeVal = &transpose;
 	
 	noteInStream.startTime = &midiEvents.startTime;//point start time of note in stream to the same time in MIDI events
@@ -35,6 +35,8 @@
 
 	
 	receiver.setup( PORT );
+
+	sender.setup( HOST, SEND_PORT );
 	
 	screenWidth = ofGetWidth();
 	screenHeight = ofGetHeight();
@@ -42,13 +44,16 @@
 	midiEvents.screenHeight = &screenHeight;
 	midiEvents.drawTempoMode = false;
 	ofSetFrameRate(30);
+	
+	midiEvents.ticksPerScreen += 4000;
+	lastScoreIndexSent = 0;
+	
 }
 
 //--------------------------------------------------------------
 void testApp::update(){
 	if (playing){
-		midiEvents.updatePlayPosition();
-	//	midiEvents.bayesStruct.updateBestEstimate();
+		midiEvents.updatePlayPosition();//this fn calls	midiEvents.bayesStruct.updateBestEstimate();
 	}
 //	drawer.tickLocation+=20;
 	
@@ -122,9 +127,72 @@
 		}
 		
 	}//end while osc
+
+	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();
+	}
+	
+
+}
+
+void testApp::sendNoteToMuseScore(){
+	int ticks = midiEvents.recordedNoteOnMatrix[midiEvents.bestMatchIndex][0];
+	int pitch = midiEvents.recordedNoteOnMatrix[midiEvents.bestMatchIndex][1];
+	printf("sending to muse score %i, %i \n", ticks, pitch);
+		
+		   ofxOscMessage m;
+		   m.setAddress( "/plugin" );
+		   m.addStringArg( "coloronenote.js" );
+		   m.addStringArg("mytick");
+		   m.addIntArg( ticks );
+		   m.addStringArg("mypitch");
+		   m.addIntArg( pitch);
+		   sender.sendMessage( m );  
+		   
+	//	   /plugin coloronenote.js mytick 100 mypitch 56;
+}
+
+
+
+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;
@@ -148,9 +216,10 @@
 		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);
+		//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;
@@ -161,6 +230,13 @@
 
 	midiEvents.drawFile();
 	
+	string info = "Measure ";
+	info += ofToString(lastMeasureSent);
+	info += "  Last note ";
+	info += ofToString(lastScoreIndexSent);
+	
+	ofSetHexColor(0x000000);
+	ofDrawBitmapString(info, 20, 20);
 	midiEvents.drawMidiFile(noteInStream.midiInputEvents);
 
 }
@@ -294,6 +370,9 @@
 void testApp::stopPlaying(){
 	playing = false;
 	liveInputPlaying = false;
+	lastScoreIndexSent = 0;
+	midiEvents.bestMatchIndex = 0;
+	sendNoteToMuseScore();
 }
 
 bool testApp::getFilenameFromDialogBox(string* fileNameToSave){
--- a/hackday/testApp.h	Sat Dec 03 17:19:43 2011 +0000
+++ b/hackday/testApp.h	Sat Dec 03 21:09:13 2011 +0000
@@ -32,6 +32,9 @@
 
 
 #define PORT 12121
+#define SEND_PORT 5282
+#define HOST "localhost"
+
 
 using namespace std;
 using namespace MIDIConstants;
@@ -82,6 +85,10 @@
 	char msg[255];
 	string portName;
 	
+	void checkNewScoreNote();
+	void sendNoteToMuseScore();
+	void sendMeasureToMuseScore();
+	void findMeasure();
 	// midi addon
 	ofxMidiIn	midiIn;
 	// this is your listener function
@@ -93,9 +100,11 @@
 	bool liveInputPlaying;
 	double timePlayed;	
 	int transpose;
+	int lastScoreIndexSent;
+	int lastMeasureSent;
 private:
 	ofxOscReceiver	receiver;
-	
+	ofxOscSender	sender;
 
 	
 };