diff include/Midi.h @ 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/include/Midi.h	Thu Feb 04 18:41:30 2016 +0000
+++ b/include/Midi.h	Fri Feb 05 06:16:35 2016 +0000
@@ -13,9 +13,194 @@
 
 typedef unsigned char midi_byte_t;
 
+
+typedef enum midiMessageType{
+	kmmNoteOff = 0,
+	kmmNoteOn,
+	kmmPolyphonicKeyPressure,
+	kmmControlChange,
+	kmmProgramChange,
+	kmmChannelPressure,
+	kmmPitchBend,
+	kmmNone,
+	kmmAny,
+} MidiMessageType;
+#define midiMessageStatusBytesLength 7+2 //2 being kmmNone and kmmAny
+
+extern midi_byte_t midiMessageStatusBytes[midiMessageStatusBytesLength];
+extern unsigned int midiMessageNumDataBytes[midiMessageStatusBytesLength];
+
+class MidiChannelMessage{
+public:
+	MidiChannelMessage();
+	MidiChannelMessage(MidiMessageType type);
+	virtual ~MidiChannelMessage();
+	MidiMessageType getType();
+	int getChannel();
+	unsigned int getNumDataBytes(){
+		return midiMessageNumDataBytes[(unsigned int)_type];
+	}
+	void setDataByte(unsigned int dataByteIndex, midi_byte_t input){
+		_dataBytes[dataByteIndex] = input;
+	}
+	void setType(MidiMessageType type){
+		_type = type;
+		_statusByte = midiMessageStatusBytes[_type];
+	}
+	void setChannel(midi_byte_t channel){
+		_channel = channel;
+	}
+	midi_byte_t getDataByte(unsigned int index){
+		return _dataBytes[index];
+	}
+	void clear(){
+		for(int n = 0; n<maxDataBytes; n++){
+			_dataBytes[n] = 0;
+		}
+		_type = kmmNone;
+		_statusByte = 0;
+	}
+	void prettyPrint(){
+		rt_printf("MessageType: %x,  ", this->getType());
+		rt_printf("channel: %u, ", this->getChannel());
+		for(int n = 0; n < this->getNumDataBytes(); n++){
+			rt_printf("data%d: %d, ", n + 1, this->getDataByte(n));
+		}
+		rt_printf("\n");
+	}
+
+private:
+	const static int maxDataBytes = 2;
+protected:
+	midi_byte_t _statusByte;
+	midi_byte_t _dataBytes[maxDataBytes]; // where 2 is the maximum number of data bytes for a channel message
+	MidiMessageType _type;
+	midi_byte_t _channel;
+};
+/*
+class MidiControlChangeMessage : public MidiChannelMessage{
+	int number;
+	int value;
+public:
+	int getNumber();
+	int getNumDataBytes();
+	int setDataByte(midi_byte_t input, unsigned int dataByteIndex);
+	int getValue();
+	int set(midi_byte_t* input);
+};
+
+class MidiNoteMessage : public MidiChannelMessage{
+	int note;
+	int velocity;
+public:
+	int getNote();
+	int getVelocity();
+	int getNumDataBytes();
+	int setDataByte(midi_byte_t input, unsigned int dataByteIndex);
+};
+
+class MidiProgramChangeMessage : public MidiChannelMessage{
+	midi_byte_t program;
+public:
+	int getNumDataBytes();
+	int setDataByte(midi_byte_t input, unsigned int dataByteIndex);
+	midi_byte_t getProgram();
+};
+*/
+
+class MidiParser{
+private:
+	std::vector<MidiChannelMessage> messages;
+	unsigned int writePointer;
+	unsigned int readPointer;
+	unsigned int elapsedDataBytes;
+	bool waitingForStatus;
+public:
+	MidiParser(){
+		waitingForStatus = true;
+		elapsedDataBytes= 0;
+		messages.resize(100); // 100 is the number of messages that can be buffered
+		writePointer = 0;
+		readPointer = 0;
+	}
+
+	/**
+	 * Parses some midi messages.
+	 *
+	 * @param input the array to read from
+	 * @param length the maximum number of values available at the array
+	 *
+	 * @return the number of bytes parsed
+	 */
+	int parse(midi_byte_t* input, unsigned int length);
+	int callme(){
+		return readPointer;
+	};
+	int numAvailableMessages(){
+		int num = (writePointer - readPointer + messages.size() ) % messages.size();
+		if(num > 0){
+			int a = a +1;
+			a = callme();
+		}
+		return num;
+	}
+	/**
+	 * Get the oldest channel message in the buffer.
+	 *
+	 * You should not call this function when numAvailableMessages() returns 0.
+	 * @param type the type of the message to retrieve
+	 * @return a copy of the oldest message of the give type in the buffer
+	 */
+	MidiChannelMessage getNextChannelMessage(/*MidiMessageType type*/){
+		MidiChannelMessage message;
+		message = messages[readPointer];
+		if(message.getType() == kmmNone){
+			message.clear();
+		}
+		messages[readPointer].setType(kmmNone); // do not use it again
+		readPointer++;
+		if(readPointer == messages.size()){
+			readPointer = 0;
+		}
+		return message;
+	};
+
+//	MidiChannelMessage getNextChannelMessage(){
+//		getNextChannelMessage(kmmAny);
+//	}
+//	MidiControlChangeMessage* getNextControlChangeMessage(){
+//		return (MidiControlChangeMessage*)getNextChannelMessage(kmmControlChange);
+//	};
+//	MidiProgramChangeMessage* getNextProgramChangeMessage(){
+//		return (MidiProgramChangeMessage*)getNextChannelMessage(kmmProgramChange);
+//	};
+//	MidiNoteMessage* getNextNoteOnMessage(){
+//		return (MidiNoteMessage*)getNextChannelMessage(kmmNoteOn);
+//	};
+};
+
+
 class Midi {
 public:
 	Midi();
+
+	/**
+	 * Enable the input MidiParser.
+	 *
+	 * If the parser is enabled, readFrom() will return an error code.
+	 * Midi messages should instead be retrieved via, e.g.: getMidiParser()->getNextChannelMessage();
+	 *
+	 * @param enable true to enable the input MidiParser, false to disable it.
+	 */
+	void enableParser(bool enable);
+
+	/**
+	 * Get access to the input parser in use, if any.
+	 *
+	 * @return a pointer to the instance of MidiParser, if currently enabled, zero otherwise.
+	 */
+	MidiParser* getParser();
+
 	/**
 	 * Open the specified input Midi port and start reading from it.
 	 * @param port Midi port to open
@@ -50,7 +235,12 @@
 	 * @return 1 on success, -1 on error
 	 */
 	int writeOutput(midi_byte_t* bytes, unsigned int length);
-
+	/**
+	 * Gives access to the midi parser, if it has been activated.
+	 *
+	 * @return a pointer to the midi parser if active, zero otherwise
+	 */
+	MidiParser* getMidiParser();
 	virtual ~Midi();
 	static void midiInputLoop();
 	static void midiOutputLoop();
@@ -67,6 +257,8 @@
 	std::vector<midi_byte_t> outputBytes;
 	unsigned int outputBytesWritePointer;
 	unsigned int outputBytesReadPointer;
+	MidiParser* inputParser;
+	bool parserEnabled;
 	static std::vector<Midi*> objAddrs[2];
 	static AuxiliaryTask midiInputTask;
 	static AuxiliaryTask midiOutputTask;