annotate include/Midi.h @ 269:ac8eb07afcf5

Oxygen text added to each render.cpp file for the default projects. Text includes project explanation from Wiki, edited in places. Empty project added as a default project. Doxyfile updated. Each of the project locations added to INPUT configuration option. Consider just watching the whole project file so all new projects are automatically pulled through.
author Robert Jack <robert.h.jack@gmail.com>
date Tue, 17 May 2016 15:40:16 +0100
parents 6ca9b3f557bf
children e4392164b458
rev   line source
giuliomoro@181 1 /*
giuliomoro@181 2 * Midi.h
giuliomoro@181 3 *
giuliomoro@181 4 * Created on: 15 Jan 2016
giuliomoro@181 5 * Author: giulio
giuliomoro@181 6 */
giuliomoro@181 7
giuliomoro@181 8 #ifndef MIDI_H_
giuliomoro@181 9 #define MIDI_H_
giuliomoro@181 10
giuliomoro@181 11 #include <BeagleRT.h>
giuliomoro@181 12 #include <vector>
giuliomoro@181 13
giuliomoro@181 14 typedef unsigned char midi_byte_t;
giuliomoro@181 15
giuliomoro@197 16
giuliomoro@197 17 typedef enum midiMessageType{
giuliomoro@197 18 kmmNoteOff = 0,
giuliomoro@197 19 kmmNoteOn,
giuliomoro@197 20 kmmPolyphonicKeyPressure,
giuliomoro@197 21 kmmControlChange,
giuliomoro@197 22 kmmProgramChange,
giuliomoro@197 23 kmmChannelPressure,
giuliomoro@197 24 kmmPitchBend,
giuliomoro@197 25 kmmNone,
giuliomoro@197 26 kmmAny,
giuliomoro@197 27 } MidiMessageType;
giuliomoro@197 28 #define midiMessageStatusBytesLength 7+2 //2 being kmmNone and kmmAny
giuliomoro@197 29
giuliomoro@197 30 extern midi_byte_t midiMessageStatusBytes[midiMessageStatusBytesLength];
giuliomoro@197 31 extern unsigned int midiMessageNumDataBytes[midiMessageStatusBytesLength];
giuliomoro@197 32
giuliomoro@197 33 class MidiChannelMessage{
giuliomoro@197 34 public:
giuliomoro@197 35 MidiChannelMessage();
giuliomoro@197 36 MidiChannelMessage(MidiMessageType type);
giuliomoro@197 37 virtual ~MidiChannelMessage();
giuliomoro@197 38 MidiMessageType getType();
giuliomoro@197 39 int getChannel();
giuliomoro@197 40 unsigned int getNumDataBytes(){
giuliomoro@197 41 return midiMessageNumDataBytes[(unsigned int)_type];
giuliomoro@197 42 }
giuliomoro@197 43 void setDataByte(unsigned int dataByteIndex, midi_byte_t input){
giuliomoro@197 44 _dataBytes[dataByteIndex] = input;
giuliomoro@197 45 }
giuliomoro@197 46 void setType(MidiMessageType type){
giuliomoro@197 47 _type = type;
giuliomoro@197 48 _statusByte = midiMessageStatusBytes[_type];
giuliomoro@197 49 }
giuliomoro@197 50 void setChannel(midi_byte_t channel){
giuliomoro@197 51 _channel = channel;
giuliomoro@197 52 }
giuliomoro@197 53 midi_byte_t getDataByte(unsigned int index){
giuliomoro@197 54 return _dataBytes[index];
giuliomoro@197 55 }
giuliomoro@197 56 void clear(){
giuliomoro@197 57 for(int n = 0; n<maxDataBytes; n++){
giuliomoro@197 58 _dataBytes[n] = 0;
giuliomoro@197 59 }
giuliomoro@197 60 _type = kmmNone;
giuliomoro@197 61 _statusByte = 0;
giuliomoro@197 62 }
giuliomoro@197 63 void prettyPrint(){
giuliomoro@197 64 rt_printf("MessageType: %x, ", this->getType());
giuliomoro@197 65 rt_printf("channel: %u, ", this->getChannel());
giuliomoro@216 66 for(unsigned int n = 0; n < this->getNumDataBytes(); n++){
giuliomoro@197 67 rt_printf("data%d: %d, ", n + 1, this->getDataByte(n));
giuliomoro@197 68 }
giuliomoro@197 69 rt_printf("\n");
giuliomoro@197 70 }
giuliomoro@197 71
giuliomoro@197 72 private:
giuliomoro@197 73 const static int maxDataBytes = 2;
giuliomoro@197 74 protected:
giuliomoro@197 75 midi_byte_t _statusByte;
giuliomoro@197 76 midi_byte_t _dataBytes[maxDataBytes]; // where 2 is the maximum number of data bytes for a channel message
giuliomoro@197 77 MidiMessageType _type;
giuliomoro@197 78 midi_byte_t _channel;
giuliomoro@197 79 };
giuliomoro@197 80 /*
giuliomoro@197 81 class MidiControlChangeMessage : public MidiChannelMessage{
giuliomoro@197 82 int number;
giuliomoro@197 83 int value;
giuliomoro@197 84 public:
giuliomoro@197 85 int getNumber();
giuliomoro@197 86 int getNumDataBytes();
giuliomoro@197 87 int setDataByte(midi_byte_t input, unsigned int dataByteIndex);
giuliomoro@197 88 int getValue();
giuliomoro@197 89 int set(midi_byte_t* input);
giuliomoro@197 90 };
giuliomoro@197 91
giuliomoro@197 92 class MidiNoteMessage : public MidiChannelMessage{
giuliomoro@197 93 int note;
giuliomoro@197 94 int velocity;
giuliomoro@197 95 public:
giuliomoro@197 96 int getNote();
giuliomoro@197 97 int getVelocity();
giuliomoro@197 98 int getNumDataBytes();
giuliomoro@197 99 int setDataByte(midi_byte_t input, unsigned int dataByteIndex);
giuliomoro@197 100 };
giuliomoro@197 101
giuliomoro@197 102 class MidiProgramChangeMessage : public MidiChannelMessage{
giuliomoro@197 103 midi_byte_t program;
giuliomoro@197 104 public:
giuliomoro@197 105 int getNumDataBytes();
giuliomoro@197 106 int setDataByte(midi_byte_t input, unsigned int dataByteIndex);
giuliomoro@197 107 midi_byte_t getProgram();
giuliomoro@197 108 };
giuliomoro@197 109 */
giuliomoro@197 110
giuliomoro@197 111 class MidiParser{
giuliomoro@197 112 private:
giuliomoro@197 113 std::vector<MidiChannelMessage> messages;
giuliomoro@197 114 unsigned int writePointer;
giuliomoro@197 115 unsigned int readPointer;
giuliomoro@197 116 unsigned int elapsedDataBytes;
giuliomoro@197 117 bool waitingForStatus;
giuliomoro@226 118 void (*messageReadyCallback)(MidiChannelMessage,void*);
giuliomoro@224 119 bool callbackEnabled;
giuliomoro@226 120 void* callbackArg;
giuliomoro@197 121 public:
giuliomoro@197 122 MidiParser(){
giuliomoro@197 123 waitingForStatus = true;
giuliomoro@197 124 elapsedDataBytes= 0;
giuliomoro@197 125 messages.resize(100); // 100 is the number of messages that can be buffered
giuliomoro@197 126 writePointer = 0;
giuliomoro@197 127 readPointer = 0;
giuliomoro@224 128 callbackEnabled = false;
giuliomoro@224 129 messageReadyCallback = NULL;
giuliomoro@226 130 callbackArg = NULL;
giuliomoro@197 131 }
giuliomoro@197 132
giuliomoro@197 133 /**
giuliomoro@197 134 * Parses some midi messages.
giuliomoro@197 135 *
giuliomoro@197 136 * @param input the array to read from
giuliomoro@197 137 * @param length the maximum number of values available at the array
giuliomoro@197 138 *
giuliomoro@197 139 * @return the number of bytes parsed
giuliomoro@197 140 */
giuliomoro@197 141 int parse(midi_byte_t* input, unsigned int length);
giuliomoro@224 142
giuliomoro@225 143 /**
giuliomoro@225 144 * Sets the callback to call when a new MidiChannelMessage is available
giuliomoro@225 145 * from the input port.
giuliomoro@225 146 *
giuliomoro@226 147 * The callback will be called with two arguments:
giuliomoro@226 148 * callback(MidiChannelMessage newMessage, void* arg)
giuliomoro@226 149 *
giuliomoro@226 150 * In order to deactivate the callback, call this method with NULL as the
giuliomoro@226 151 * first argument.
giuliomoro@225 152 * While the callback is enabled, calling numAvailableMessages() and
giuliomoro@225 153 * getNextChannelMessage() is still possible, but it will probably always
giuliomoro@225 154 * return 0 as the callback is called as soon as a new message is available.
giuliomoro@225 155 *
giuliomoro@226 156 * @param newCallback the callback function.
giuliomoro@226 157 * @param arg the second argument to be passed to the callback function.
giuliomoro@225 158 *
giuliomoro@225 159 */
giuliomoro@226 160 void setCallback(void (*newCallback)(MidiChannelMessage, void*), void* arg=NULL){
giuliomoro@226 161 callbackArg = arg;
giuliomoro@224 162 messageReadyCallback = newCallback;
giuliomoro@224 163 if(newCallback != NULL){
giuliomoro@224 164 callbackEnabled = true;
giuliomoro@224 165 } else {
giuliomoro@224 166 callbackEnabled = false;
giuliomoro@224 167 }
giuliomoro@197 168 };
giuliomoro@224 169
giuliomoro@225 170 /**
giuliomoro@225 171 * Checks whether there is a callback currently set to be called
giuliomoro@225 172 * every time a new input MidiChannelMessage is available from the
giuliomoro@225 173 * input port.
giuliomoro@225 174 */
giuliomoro@224 175 bool isCallbackEnabled(){
giuliomoro@224 176 return callbackEnabled;
giuliomoro@224 177 };
giuliomoro@224 178
giuliomoro@225 179 /**
giuliomoro@225 180 * Returns the number of unread MidiChannelMessage available from the
giuliomoro@225 181 * input port.
giuliomoro@225 182 *
giuliomoro@225 183 */
giuliomoro@225 184
giuliomoro@197 185 int numAvailableMessages(){
giuliomoro@197 186 int num = (writePointer - readPointer + messages.size() ) % messages.size();
giuliomoro@197 187 return num;
giuliomoro@197 188 }
giuliomoro@225 189
giuliomoro@197 190 /**
giuliomoro@197 191 * Get the oldest channel message in the buffer.
giuliomoro@197 192 *
giuliomoro@199 193 * If this method is called when numAvailableMessages()==0, then
giuliomoro@199 194 * a message with all fields set to zero is returned.
giuliomoro@225 195 *
giuliomoro@197 196 * @param type the type of the message to retrieve
giuliomoro@225 197 *
giuliomoro@197 198 * @return a copy of the oldest message of the give type in the buffer
giuliomoro@197 199 */
giuliomoro@197 200 MidiChannelMessage getNextChannelMessage(/*MidiMessageType type*/){
giuliomoro@197 201 MidiChannelMessage message;
giuliomoro@197 202 message = messages[readPointer];
giuliomoro@197 203 if(message.getType() == kmmNone){
giuliomoro@197 204 message.clear();
giuliomoro@197 205 }
giuliomoro@197 206 messages[readPointer].setType(kmmNone); // do not use it again
giuliomoro@197 207 readPointer++;
giuliomoro@197 208 if(readPointer == messages.size()){
giuliomoro@197 209 readPointer = 0;
giuliomoro@197 210 }
giuliomoro@197 211 return message;
giuliomoro@197 212 };
giuliomoro@197 213
giuliomoro@197 214 // MidiChannelMessage getNextChannelMessage(){
giuliomoro@197 215 // getNextChannelMessage(kmmAny);
giuliomoro@197 216 // }
giuliomoro@197 217 // MidiControlChangeMessage* getNextControlChangeMessage(){
giuliomoro@197 218 // return (MidiControlChangeMessage*)getNextChannelMessage(kmmControlChange);
giuliomoro@197 219 // };
giuliomoro@197 220 // MidiProgramChangeMessage* getNextProgramChangeMessage(){
giuliomoro@197 221 // return (MidiProgramChangeMessage*)getNextChannelMessage(kmmProgramChange);
giuliomoro@197 222 // };
giuliomoro@197 223 // MidiNoteMessage* getNextNoteOnMessage(){
giuliomoro@197 224 // return (MidiNoteMessage*)getNextChannelMessage(kmmNoteOn);
giuliomoro@197 225 // };
giuliomoro@197 226 };
giuliomoro@197 227
giuliomoro@197 228
giuliomoro@181 229 class Midi {
giuliomoro@181 230 public:
giuliomoro@181 231 Midi();
giuliomoro@197 232
giuliomoro@197 233 /**
giuliomoro@197 234 * Enable the input MidiParser.
giuliomoro@197 235 *
giuliomoro@199 236 * If the parser is enabled, getInput() will return an error code.
giuliomoro@197 237 * Midi messages should instead be retrieved via, e.g.: getMidiParser()->getNextChannelMessage();
giuliomoro@197 238 *
giuliomoro@197 239 * @param enable true to enable the input MidiParser, false to disable it.
giuliomoro@197 240 */
giuliomoro@197 241 void enableParser(bool enable);
giuliomoro@197 242
giuliomoro@197 243 /**
giuliomoro@197 244 * Get access to the input parser in use, if any.
giuliomoro@197 245 *
giuliomoro@197 246 * @return a pointer to the instance of MidiParser, if currently enabled, zero otherwise.
giuliomoro@197 247 */
giuliomoro@197 248 MidiParser* getParser();
giuliomoro@197 249
giuliomoro@225 250 /**
giuliomoro@225 251 * Sets the callback to call when a new MidiChannelMessage is available
giuliomoro@225 252 * from the input port.
giuliomoro@225 253 *
giuliomoro@225 254 * Internally, it calls enableParser() and the MidiParser::setCallback();
giuliomoro@225 255 *
giuliomoro@226 256 * @param newCallback the callback function.
giuliomoro@226 257 * @param arg the second argument to be passed to the callback function.
giuliomoro@225 258 */
giuliomoro@226 259 void setParserCallback(void (*callback)(MidiChannelMessage, void*), void* arg=NULL){
giuliomoro@224 260 // if callback is not NULL, also enable the parser
giuliomoro@224 261 enableParser(callback != NULL); //this needs to be first, as it deletes the parser(if exists)
giuliomoro@226 262 getParser()->setCallback(callback, arg);
giuliomoro@224 263 }
giuliomoro@224 264
giuliomoro@181 265 /**
giuliomoro@181 266 * Open the specified input Midi port and start reading from it.
giuliomoro@181 267 * @param port Midi port to open
giuliomoro@181 268 * @return 1 on success, -1 on failure
giuliomoro@181 269 */
giuliomoro@181 270 int readFrom(int port);
giuliomoro@181 271 /**
giuliomoro@181 272 * Open the specified output Midi port and prepares to write to it.
giuliomoro@181 273 * @param port Midi port to open
giuliomoro@181 274 * @return 1 on success, -1 on failure
giuliomoro@181 275 */
giuliomoro@181 276 int writeTo(int port);
giuliomoro@181 277
giuliomoro@181 278 /**
giuliomoro@191 279 * Get received midi bytes, one at a time.
giuliomoro@181 280 * @return -1 if no new byte is available, -2 on error,
giuliomoro@181 281 * the oldest not yet retrieved midi byte otherwise
giuliomoro@181 282 */
giuliomoro@181 283 int getInput();
giuliomoro@181 284
giuliomoro@181 285 /**
giuliomoro@181 286 * Writes a Midi byte to the output port
giuliomoro@181 287 * @param byte the Midi byte to write
giuliomoro@181 288 * @return 1 on success, -1 on error
giuliomoro@181 289 */
giuliomoro@181 290 int writeOutput(midi_byte_t byte);
giuliomoro@181 291
giuliomoro@181 292 /**
giuliomoro@181 293 * Writes Midi bytes to the output port
giuliomoro@181 294 * @param bytes an array of bytes to be written
giuliomoro@181 295 * @param length number of bytes to write
giuliomoro@181 296 * @return 1 on success, -1 on error
giuliomoro@181 297 */
giuliomoro@191 298 int writeOutput(midi_byte_t* bytes, unsigned int length);
giuliomoro@197 299 /**
giuliomoro@197 300 * Gives access to the midi parser, if it has been activated.
giuliomoro@197 301 *
giuliomoro@197 302 * @return a pointer to the midi parser if active, zero otherwise
giuliomoro@197 303 */
giuliomoro@197 304 MidiParser* getMidiParser();
giuliomoro@181 305 virtual ~Midi();
giuliomoro@181 306 static void midiInputLoop();
giuliomoro@191 307 static void midiOutputLoop();
giuliomoro@181 308 static bool staticConstructed;
giuliomoro@181 309 static void staticConstructor();
giuliomoro@181 310 private:
giuliomoro@199 311 int _getInput();
giuliomoro@181 312 void readInputLoop();
giuliomoro@191 313 void writeOutputLoop();
giuliomoro@181 314 int outputPort;
giuliomoro@181 315 int inputPort;
giuliomoro@181 316 std::vector<midi_byte_t> inputBytes;
giuliomoro@181 317 unsigned int inputBytesWritePointer;
giuliomoro@181 318 unsigned int inputBytesReadPointer;
giuliomoro@181 319 std::vector<midi_byte_t> outputBytes;
giuliomoro@191 320 unsigned int outputBytesWritePointer;
giuliomoro@191 321 unsigned int outputBytesReadPointer;
giuliomoro@197 322 MidiParser* inputParser;
giuliomoro@197 323 bool parserEnabled;
giuliomoro@191 324 static std::vector<Midi*> objAddrs[2];
giuliomoro@181 325 static AuxiliaryTask midiInputTask;
giuliomoro@181 326 static AuxiliaryTask midiOutputTask;
giuliomoro@181 327 };
giuliomoro@181 328
giuliomoro@181 329
giuliomoro@181 330 #endif /* MIDI_H_ */