Mercurial > hg > beaglert
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;