diff core/Midi.cpp @ 197:265a527f8be8

Added MidiParser for channel messages
author Giulio Moro <giuliomoro@yahoo.it>
date Fri, 05 Feb 2016 06:16:35 +0000
parents b3a306da03e0
children b128e3ea84ff
line wrap: on
line diff
--- a/core/Midi.cpp	Thu Feb 04 18:41:30 2016 +0000
+++ b/core/Midi.cpp	Fri Feb 05 06:16:35 2016 +0000
@@ -12,14 +12,68 @@
 #define kMidiInput 0
 #define kMidiOutput 1
 
+
+midi_byte_t midiMessageStatusBytes[midiMessageStatusBytesLength]=
+{
+	0x80,
+	0x90,
+	0xA0,
+	0xB0,
+	0xC0,
+	0xD0,
+	0xE0,
+	0
+};
+
+unsigned int midiMessageNumDataBytes[midiMessageStatusBytesLength]={2, 2, 2, 2, 1, 1, 2, 0};
+
 bool Midi::staticConstructed;
 AuxiliaryTask Midi::midiInputTask;
 AuxiliaryTask Midi::midiOutputTask;
 std::vector<Midi *> Midi::objAddrs[2];
 
+int MidiParser::parse(midi_byte_t* input, unsigned int length){
+	unsigned int consumedBytes = 0;
+	for(unsigned int n = 0; n < length; n++){
+		consumedBytes++;
+		if(waitingForStatus == true){
+			int statusByte = input[n];
+			MidiMessageType newType = kmmNone;
+			if (statusByte >= 0x80){//it actually is a status byte
+				for(int n = 0; n < midiMessageStatusBytesLength; n++){ //find the statusByte in the array
+					if(midiMessageStatusBytes[n] == (statusByte&0xf0)){
+						newType = (MidiMessageType)n;
+						break;
+					}
+				}
+				elapsedDataBytes = 0;
+				waitingForStatus = false;
+				messages[writePointer].setType(newType);
+				messages[writePointer].setChannel((midi_byte_t)(statusByte&0xf));
+				consumedBytes++;
+			} else { // either something went wrong or it's a system message
+				continue;
+			}
+		} else {
+			messages[writePointer].setDataByte(elapsedDataBytes, input[n]);
+			elapsedDataBytes++;
+			if(elapsedDataBytes == messages[writePointer].getNumDataBytes()){
+				waitingForStatus = true;
+				writePointer++;
+				if(writePointer == messages.size()){
+					writePointer = 0;
+				}
+			}
+		}
+	}
+	return consumedBytes;
+};
+
+
 Midi::Midi(){
 	outputPort = -1;
 	inputPort = -1;
+	inputParser = 0;
 	size_t inputBytesInitialSize = 1000;
 	inputBytes.resize(inputBytesInitialSize);
 	outputBytes.resize(inputBytesInitialSize);
@@ -37,6 +91,18 @@
 }
 
 Midi::~Midi(){}
+
+void Midi::enableParser(bool enable){
+	if(enable == true){
+		delete inputParser;
+		inputParser = new MidiParser();
+		parserEnabled = true;
+	} else {
+		delete inputParser;
+		parserEnabled = false;
+	}
+}
+
 void Midi::midiInputLoop(){
 	printf("Midi input loop %d\n", objAddrs[kMidiInput].size());
 	for(unsigned int n = 0; n < objAddrs[kMidiInput].size(); n++){
@@ -66,9 +132,32 @@
 		if(inputBytesWritePointer == inputBytes.size()){ //wrap pointer around
 			inputBytesWritePointer = 0;
 		}
+		if(parserEnabled == true && ret > 0){ // if the parser is enabled and there is new data, send the data to it
+			int input;
+			while((input=getInput()) >= 0){
+				midi_byte_t inputByte = (midi_byte_t)(input);
+//				printf("__0x%x\n", input);
+				inputParser->parse(&inputByte, 1);
+			}
+//			if(inputBytesReadPointer == inputBytesWritePointer){
+				// this should never be the case, it should only happen when ret == 0
+//			} else {
+
+//				unsigned int length = (inputBytesWritePointer - inputBytesReadPointer + inputBytes.size())
+//						% inputBytes.size();
+//				rt_printf("inputBytes: 0x%x 0x%x 0x%x", inputBytes[inputBytesReadPointer],
+//						inputBytes[inputBytesReadPointer+1], inputBytes[inputBytesReadPointer+2]);
+//				length = inputParser->parse(&inputBytes[inputBytesReadPointer], length);
+//				inputBytesReadPointer += length; //if parserEnabled, the readPointer is incremented here,
+//											     //so calls to getInput() should be avoided
+//				if(inputBytesReadPointer == inputBytes.size()){
+//					inputBytesReadPointer = 0;
+//				}
+//			}
+		}
 		if(ret < maxBytesToRead){ //no more data to retrieve at the moment
 			usleep(1000);
-		} // otherwise there might be more data ready to be read, so don't sleep
+		} // otherwise there might be more data ready to be read (we were at the end of the buffer), so don't sleep
 	}
 }
 
@@ -85,21 +174,10 @@
 		int ret;
 		ret = write(outputPort, &outputBytes[outputBytesReadPointer], sizeof(midi_byte_t)*length);
 		if(ret < 0){ //error occurred
-//			if(errno != EAGAIN){ // () would return EAGAIN when no data are available to read just now
-//				rt_printf("Error while writing midi %d\n", errno);
-//			}
 			rt_printf("error occurred while writing: %d\n", errno);
 			usleep(10000); //wait before retrying
 			continue;
 		}
-
-//		inputBytesWritePointer += ret;
-//		if(inputBytesWritePointer == inputBytes.size()){ //wrap pointer around
-//			inputBytesWritePointer = 0;
-//		}
-//		if(ret < maxBytesToRead){ //no more data to retrieve at the moment
-//			usleep(1000);
-//		} // otherwise there might be more data ready to be read, so don't sleep
 	}
 }
 int Midi::readFrom(int port){
@@ -129,6 +207,9 @@
 }
 
 int Midi::getInput(){
+//	if(parserEnabled == true) {
+//		return -3;
+//	}
 	if(inputPort < 0)
 		return -2;
 	if(inputBytesReadPointer == inputBytesWritePointer){
@@ -141,6 +222,13 @@
 	return inputMessage;
 }
 
+MidiParser* Midi::getParser(){
+	if(parserEnabled == false){
+		return 0;
+	}
+	return inputParser;
+};
+
 int Midi::writeOutput(midi_byte_t byte){
 	return writeOutput(&byte, 1);
 }
@@ -152,3 +240,29 @@
 	else
 		return 1;
 }
+
+MidiChannelMessage::MidiChannelMessage(){};
+MidiChannelMessage::MidiChannelMessage(MidiMessageType type){
+	setType(type);
+};
+MidiChannelMessage::~MidiChannelMessage(){};
+MidiMessageType MidiChannelMessage::getType(){
+	return _type;
+};
+int MidiChannelMessage::getChannel(){
+	return _channel;
+};
+//int MidiChannelMessage::set(midi_byte_t* input);
+//
+//int MidiControlChangeMessage ::getValue();
+//int MidiControlChangeMessage::set(midi_byte_t* input){
+//	channel = input[0];
+//	number = input[1];
+//	value = input[2];
+//	return 3;
+//}
+
+//int MidiNoteMessage::getNote();
+//int MidiNoteMessage::getVelocity();
+
+//midi_byte_t MidiProgramChangeMessage::getProgram();