comparison 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
comparison
equal deleted inserted replaced
196:0029562391b1 197:265a527f8be8
11 #include <BeagleRT.h> 11 #include <BeagleRT.h>
12 #include <vector> 12 #include <vector>
13 13
14 typedef unsigned char midi_byte_t; 14 typedef unsigned char midi_byte_t;
15 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
33 class MidiChannelMessage{
34 public:
35 MidiChannelMessage();
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(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
111 class MidiParser{
112 private:
113 std::vector<MidiChannelMessage> messages;
114 unsigned int writePointer;
115 unsigned int readPointer;
116 unsigned int elapsedDataBytes;
117 bool waitingForStatus;
118 public:
119 MidiParser(){
120 waitingForStatus = true;
121 elapsedDataBytes= 0;
122 messages.resize(100); // 100 is the number of messages that can be buffered
123 writePointer = 0;
124 readPointer = 0;
125 }
126
127 /**
128 * Parses some midi messages.
129 *
130 * @param input the array to read from
131 * @param length the maximum number of values available at the array
132 *
133 * @return the number of bytes parsed
134 */
135 int parse(midi_byte_t* input, unsigned int length);
136 int callme(){
137 return readPointer;
138 };
139 int numAvailableMessages(){
140 int num = (writePointer - readPointer + messages.size() ) % messages.size();
141 if(num > 0){
142 int a = a +1;
143 a = callme();
144 }
145 return num;
146 }
147 /**
148 * Get the oldest channel message in the buffer.
149 *
150 * You should not call this function when numAvailableMessages() returns 0.
151 * @param type the type of the message to retrieve
152 * @return a copy of the oldest message of the give type in the buffer
153 */
154 MidiChannelMessage getNextChannelMessage(/*MidiMessageType type*/){
155 MidiChannelMessage message;
156 message = messages[readPointer];
157 if(message.getType() == kmmNone){
158 message.clear();
159 }
160 messages[readPointer].setType(kmmNone); // do not use it again
161 readPointer++;
162 if(readPointer == messages.size()){
163 readPointer = 0;
164 }
165 return message;
166 };
167
168 // MidiChannelMessage getNextChannelMessage(){
169 // getNextChannelMessage(kmmAny);
170 // }
171 // MidiControlChangeMessage* getNextControlChangeMessage(){
172 // return (MidiControlChangeMessage*)getNextChannelMessage(kmmControlChange);
173 // };
174 // MidiProgramChangeMessage* getNextProgramChangeMessage(){
175 // return (MidiProgramChangeMessage*)getNextChannelMessage(kmmProgramChange);
176 // };
177 // MidiNoteMessage* getNextNoteOnMessage(){
178 // return (MidiNoteMessage*)getNextChannelMessage(kmmNoteOn);
179 // };
180 };
181
182
16 class Midi { 183 class Midi {
17 public: 184 public:
18 Midi(); 185 Midi();
186
187 /**
188 * Enable the input MidiParser.
189 *
190 * If the parser is enabled, readFrom() will return an error code.
191 * Midi messages should instead be retrieved via, e.g.: getMidiParser()->getNextChannelMessage();
192 *
193 * @param enable true to enable the input MidiParser, false to disable it.
194 */
195 void enableParser(bool enable);
196
197 /**
198 * Get access to the input parser in use, if any.
199 *
200 * @return a pointer to the instance of MidiParser, if currently enabled, zero otherwise.
201 */
202 MidiParser* getParser();
203
19 /** 204 /**
20 * Open the specified input Midi port and start reading from it. 205 * Open the specified input Midi port and start reading from it.
21 * @param port Midi port to open 206 * @param port Midi port to open
22 * @return 1 on success, -1 on failure 207 * @return 1 on success, -1 on failure
23 */ 208 */
48 * @param bytes an array of bytes to be written 233 * @param bytes an array of bytes to be written
49 * @param length number of bytes to write 234 * @param length number of bytes to write
50 * @return 1 on success, -1 on error 235 * @return 1 on success, -1 on error
51 */ 236 */
52 int writeOutput(midi_byte_t* bytes, unsigned int length); 237 int writeOutput(midi_byte_t* bytes, unsigned int length);
53 238 /**
239 * Gives access to the midi parser, if it has been activated.
240 *
241 * @return a pointer to the midi parser if active, zero otherwise
242 */
243 MidiParser* getMidiParser();
54 virtual ~Midi(); 244 virtual ~Midi();
55 static void midiInputLoop(); 245 static void midiInputLoop();
56 static void midiOutputLoop(); 246 static void midiOutputLoop();
57 static bool staticConstructed; 247 static bool staticConstructed;
58 static void staticConstructor(); 248 static void staticConstructor();
65 unsigned int inputBytesWritePointer; 255 unsigned int inputBytesWritePointer;
66 unsigned int inputBytesReadPointer; 256 unsigned int inputBytesReadPointer;
67 std::vector<midi_byte_t> outputBytes; 257 std::vector<midi_byte_t> outputBytes;
68 unsigned int outputBytesWritePointer; 258 unsigned int outputBytesWritePointer;
69 unsigned int outputBytesReadPointer; 259 unsigned int outputBytesReadPointer;
260 MidiParser* inputParser;
261 bool parserEnabled;
70 static std::vector<Midi*> objAddrs[2]; 262 static std::vector<Midi*> objAddrs[2];
71 static AuxiliaryTask midiInputTask; 263 static AuxiliaryTask midiInputTask;
72 static AuxiliaryTask midiOutputTask; 264 static AuxiliaryTask midiOutputTask;
73 }; 265 };
74 266