Midi.h
1 /*
2  * Midi.h
3  *
4  * Created on: 15 Jan 2016
5  * Author: giulio
6  */
7 
8 #ifndef MIDI_H_
9 #define MIDI_H_
10 
11 #include <Bela.h>
12 #include <vector>
13 
14 typedef unsigned char midi_byte_t;
15 
16 
17 typedef enum midiMessageType{
18  kmmNoteOff = 0,
19  kmmNoteOn,
20  kmmPolyphonicKeyPressure,
21  kmmControlChange,
22  kmmProgramChange,
23  kmmChannelPressure,
24  kmmPitchBend,
25  kmmNone,
26  kmmAny,
27 } MidiMessageType;
28 #define midiMessageStatusBytesLength 7+2 //2 being kmmNone and kmmAny
29 
30 extern midi_byte_t midiMessageStatusBytes[midiMessageStatusBytesLength];
31 extern unsigned int midiMessageNumDataBytes[midiMessageStatusBytesLength];
32 
34 public:
36  MidiChannelMessage(MidiMessageType type);
37  virtual ~MidiChannelMessage();
38  MidiMessageType getType();
39  int getChannel();
40  unsigned int getNumDataBytes(){
41  return midiMessageNumDataBytes[(unsigned int)_type];
42  }
43  void setDataByte(unsigned int dataByteIndex, midi_byte_t input){
44  _dataBytes[dataByteIndex] = input;
45  }
46  void setType(MidiMessageType type){
47  _type = type;
48  _statusByte = midiMessageStatusBytes[_type];
49  }
50  void setChannel(midi_byte_t channel){
51  _channel = channel;
52  }
53  midi_byte_t getDataByte(unsigned int index){
54  return _dataBytes[index];
55  }
56  void clear(){
57  for(int n = 0; n<maxDataBytes; n++){
58  _dataBytes[n] = 0;
59  }
60  _type = kmmNone;
61  _statusByte = 0;
62  }
63  void prettyPrint(){
64  rt_printf("MessageType: %x, ", this->getType());
65  rt_printf("channel: %u, ", this->getChannel());
66  for(unsigned int n = 0; n < this->getNumDataBytes(); n++){
67  rt_printf("data%d: %d, ", n + 1, this->getDataByte(n));
68  }
69  rt_printf("\n");
70  }
71 
72 private:
73  const static int maxDataBytes = 2;
74 protected:
75  midi_byte_t _statusByte;
76  midi_byte_t _dataBytes[maxDataBytes]; // where 2 is the maximum number of data bytes for a channel message
77  MidiMessageType _type;
78  midi_byte_t _channel;
79 };
80 /*
81 class MidiControlChangeMessage : public MidiChannelMessage{
82  int number;
83  int value;
84 public:
85  int getNumber();
86  int getNumDataBytes();
87  int setDataByte(midi_byte_t input, unsigned int dataByteIndex);
88  int getValue();
89  int set(midi_byte_t* input);
90 };
91 
92 class MidiNoteMessage : public MidiChannelMessage{
93  int note;
94  int velocity;
95 public:
96  int getNote();
97  int getVelocity();
98  int getNumDataBytes();
99  int setDataByte(midi_byte_t input, unsigned int dataByteIndex);
100 };
101 
102 class MidiProgramChangeMessage : public MidiChannelMessage{
103  midi_byte_t program;
104 public:
105  int getNumDataBytes();
106  int setDataByte(midi_byte_t input, unsigned int dataByteIndex);
107  midi_byte_t getProgram();
108 };
109 */
110 
112 private:
113  std::vector<MidiChannelMessage> messages;
114  unsigned int writePointer;
115  unsigned int readPointer;
116  unsigned int elapsedDataBytes;
117  bool waitingForStatus;
118  void (*messageReadyCallback)(MidiChannelMessage,void*);
119  bool callbackEnabled;
120  void* callbackArg;
121 public:
122  MidiParser(){
123  waitingForStatus = true;
124  elapsedDataBytes= 0;
125  messages.resize(100); // 100 is the number of messages that can be buffered
126  writePointer = 0;
127  readPointer = 0;
128  callbackEnabled = false;
129  messageReadyCallback = NULL;
130  callbackArg = NULL;
131  }
132 
141  int parse(midi_byte_t* input, unsigned int length);
142 
160  void setCallback(void (*newCallback)(MidiChannelMessage, void*), void* arg=NULL){
161  callbackArg = arg;
162  messageReadyCallback = newCallback;
163  if(newCallback != NULL){
164  callbackEnabled = true;
165  } else {
166  callbackEnabled = false;
167  }
168  };
169 
176  return callbackEnabled;
177  };
178 
186  int num = (writePointer - readPointer + messages.size() ) % messages.size();
187  return num;
188  }
189 
200  MidiChannelMessage getNextChannelMessage(/*MidiMessageType type*/){
201  MidiChannelMessage message;
202  message = messages[readPointer];
203  if(message.getType() == kmmNone){
204  message.clear();
205  }
206  messages[readPointer].setType(kmmNone); // do not use it again
207  readPointer++;
208  if(readPointer == messages.size()){
209  readPointer = 0;
210  }
211  return message;
212  };
213 
214 // MidiChannelMessage getNextChannelMessage(){
215 // getNextChannelMessage(kmmAny);
216 // }
217 // MidiControlChangeMessage* getNextControlChangeMessage(){
218 // return (MidiControlChangeMessage*)getNextChannelMessage(kmmControlChange);
219 // };
220 // MidiProgramChangeMessage* getNextProgramChangeMessage(){
221 // return (MidiProgramChangeMessage*)getNextChannelMessage(kmmProgramChange);
222 // };
223 // MidiNoteMessage* getNextNoteOnMessage(){
224 // return (MidiNoteMessage*)getNextChannelMessage(kmmNoteOn);
225 // };
226 };
227 
228 
229 class Midi {
230 public:
231  Midi();
232 
241  void enableParser(bool enable);
242 
248  MidiParser* getParser();
249 
259  void setParserCallback(void (*callback)(MidiChannelMessage, void*), void* arg=NULL){
260  // if callback is not NULL, also enable the parser
261  enableParser(callback != NULL); //this needs to be first, as it deletes the parser(if exists)
262  getParser()->setCallback(callback, arg);
263  }
264 
270  int readFrom(int port);
271 
277  int writeTo(int port);
278 
284  int getInput();
285 
291  int writeOutput(midi_byte_t byte);
292 
299  int writeOutput(midi_byte_t* bytes, unsigned int length);
305  MidiParser* getMidiParser();
306  virtual ~Midi();
307  static void midiInputLoop();
308  static void midiOutputLoop();
309  static bool staticConstructed;
310  static void staticConstructor();
311 private:
312  int _getInput();
313  void readInputLoop();
314  void writeOutputLoop();
315  int outputPort;
316  int inputPort;
317  std::vector<midi_byte_t> inputBytes;
318  unsigned int inputBytesWritePointer;
319  unsigned int inputBytesReadPointer;
320  std::vector<midi_byte_t> outputBytes;
321  unsigned int outputBytesWritePointer;
322  unsigned int outputBytesReadPointer;
323  MidiParser* inputParser;
324  bool parserEnabled;
325  static std::vector<Midi*> objAddrs[2];
326  static AuxiliaryTask midiInputTask;
327  static AuxiliaryTask midiOutputTask;
328 };
329 
330 
331 #endif /* MIDI_H_ */
Definition: Midi.h:111
int numAvailableMessages()
Definition: Midi.h:185
bool isCallbackEnabled()
Definition: Midi.h:175
Definition: Midi.h:33
Definition: Midi.h:229
MidiChannelMessage getNextChannelMessage()
Definition: Midi.h:200
void setParserCallback(void(*callback)(MidiChannelMessage, void *), void *arg=NULL)
Definition: Midi.h:259
Main Bela public API.
void * AuxiliaryTask
Definition: Bela.h:289
void setCallback(void(*newCallback)(MidiChannelMessage, void *), void *arg=NULL)
Definition: Midi.h:160