Mercurial > hg > beaglert
comparison core/Midi.cpp @ 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 |
---|---|
10 #include <errno.h> | 10 #include <errno.h> |
11 | 11 |
12 #define kMidiInput 0 | 12 #define kMidiInput 0 |
13 #define kMidiOutput 1 | 13 #define kMidiOutput 1 |
14 | 14 |
15 | |
16 midi_byte_t midiMessageStatusBytes[midiMessageStatusBytesLength]= | |
17 { | |
18 0x80, | |
19 0x90, | |
20 0xA0, | |
21 0xB0, | |
22 0xC0, | |
23 0xD0, | |
24 0xE0, | |
25 0 | |
26 }; | |
27 | |
28 unsigned int midiMessageNumDataBytes[midiMessageStatusBytesLength]={2, 2, 2, 2, 1, 1, 2, 0}; | |
29 | |
15 bool Midi::staticConstructed; | 30 bool Midi::staticConstructed; |
16 AuxiliaryTask Midi::midiInputTask; | 31 AuxiliaryTask Midi::midiInputTask; |
17 AuxiliaryTask Midi::midiOutputTask; | 32 AuxiliaryTask Midi::midiOutputTask; |
18 std::vector<Midi *> Midi::objAddrs[2]; | 33 std::vector<Midi *> Midi::objAddrs[2]; |
19 | 34 |
35 int MidiParser::parse(midi_byte_t* input, unsigned int length){ | |
36 unsigned int consumedBytes = 0; | |
37 for(unsigned int n = 0; n < length; n++){ | |
38 consumedBytes++; | |
39 if(waitingForStatus == true){ | |
40 int statusByte = input[n]; | |
41 MidiMessageType newType = kmmNone; | |
42 if (statusByte >= 0x80){//it actually is a status byte | |
43 for(int n = 0; n < midiMessageStatusBytesLength; n++){ //find the statusByte in the array | |
44 if(midiMessageStatusBytes[n] == (statusByte&0xf0)){ | |
45 newType = (MidiMessageType)n; | |
46 break; | |
47 } | |
48 } | |
49 elapsedDataBytes = 0; | |
50 waitingForStatus = false; | |
51 messages[writePointer].setType(newType); | |
52 messages[writePointer].setChannel((midi_byte_t)(statusByte&0xf)); | |
53 consumedBytes++; | |
54 } else { // either something went wrong or it's a system message | |
55 continue; | |
56 } | |
57 } else { | |
58 messages[writePointer].setDataByte(elapsedDataBytes, input[n]); | |
59 elapsedDataBytes++; | |
60 if(elapsedDataBytes == messages[writePointer].getNumDataBytes()){ | |
61 waitingForStatus = true; | |
62 writePointer++; | |
63 if(writePointer == messages.size()){ | |
64 writePointer = 0; | |
65 } | |
66 } | |
67 } | |
68 } | |
69 return consumedBytes; | |
70 }; | |
71 | |
72 | |
20 Midi::Midi(){ | 73 Midi::Midi(){ |
21 outputPort = -1; | 74 outputPort = -1; |
22 inputPort = -1; | 75 inputPort = -1; |
76 inputParser = 0; | |
23 size_t inputBytesInitialSize = 1000; | 77 size_t inputBytesInitialSize = 1000; |
24 inputBytes.resize(inputBytesInitialSize); | 78 inputBytes.resize(inputBytesInitialSize); |
25 outputBytes.resize(inputBytesInitialSize); | 79 outputBytes.resize(inputBytesInitialSize); |
26 inputBytesWritePointer = 0; | 80 inputBytesWritePointer = 0; |
27 inputBytesReadPointer = inputBytes.size() - 1; | 81 inputBytesReadPointer = inputBytes.size() - 1; |
35 midiInputTask = BeagleRT_createAuxiliaryTask(Midi::midiInputLoop, 50, "MidiInput"); | 89 midiInputTask = BeagleRT_createAuxiliaryTask(Midi::midiInputLoop, 50, "MidiInput"); |
36 midiOutputTask = BeagleRT_createAuxiliaryTask(Midi::midiOutputLoop, 50, "MidiOutupt"); | 90 midiOutputTask = BeagleRT_createAuxiliaryTask(Midi::midiOutputLoop, 50, "MidiOutupt"); |
37 } | 91 } |
38 | 92 |
39 Midi::~Midi(){} | 93 Midi::~Midi(){} |
94 | |
95 void Midi::enableParser(bool enable){ | |
96 if(enable == true){ | |
97 delete inputParser; | |
98 inputParser = new MidiParser(); | |
99 parserEnabled = true; | |
100 } else { | |
101 delete inputParser; | |
102 parserEnabled = false; | |
103 } | |
104 } | |
105 | |
40 void Midi::midiInputLoop(){ | 106 void Midi::midiInputLoop(){ |
41 printf("Midi input loop %d\n", objAddrs[kMidiInput].size()); | 107 printf("Midi input loop %d\n", objAddrs[kMidiInput].size()); |
42 for(unsigned int n = 0; n < objAddrs[kMidiInput].size(); n++){ | 108 for(unsigned int n = 0; n < objAddrs[kMidiInput].size(); n++){ |
43 objAddrs[kMidiInput][n] -> readInputLoop(); | 109 objAddrs[kMidiInput][n] -> readInputLoop(); |
44 } | 110 } |
64 } | 130 } |
65 inputBytesWritePointer += ret; | 131 inputBytesWritePointer += ret; |
66 if(inputBytesWritePointer == inputBytes.size()){ //wrap pointer around | 132 if(inputBytesWritePointer == inputBytes.size()){ //wrap pointer around |
67 inputBytesWritePointer = 0; | 133 inputBytesWritePointer = 0; |
68 } | 134 } |
135 if(parserEnabled == true && ret > 0){ // if the parser is enabled and there is new data, send the data to it | |
136 int input; | |
137 while((input=getInput()) >= 0){ | |
138 midi_byte_t inputByte = (midi_byte_t)(input); | |
139 // printf("__0x%x\n", input); | |
140 inputParser->parse(&inputByte, 1); | |
141 } | |
142 // if(inputBytesReadPointer == inputBytesWritePointer){ | |
143 // this should never be the case, it should only happen when ret == 0 | |
144 // } else { | |
145 | |
146 // unsigned int length = (inputBytesWritePointer - inputBytesReadPointer + inputBytes.size()) | |
147 // % inputBytes.size(); | |
148 // rt_printf("inputBytes: 0x%x 0x%x 0x%x", inputBytes[inputBytesReadPointer], | |
149 // inputBytes[inputBytesReadPointer+1], inputBytes[inputBytesReadPointer+2]); | |
150 // length = inputParser->parse(&inputBytes[inputBytesReadPointer], length); | |
151 // inputBytesReadPointer += length; //if parserEnabled, the readPointer is incremented here, | |
152 // //so calls to getInput() should be avoided | |
153 // if(inputBytesReadPointer == inputBytes.size()){ | |
154 // inputBytesReadPointer = 0; | |
155 // } | |
156 // } | |
157 } | |
69 if(ret < maxBytesToRead){ //no more data to retrieve at the moment | 158 if(ret < maxBytesToRead){ //no more data to retrieve at the moment |
70 usleep(1000); | 159 usleep(1000); |
71 } // otherwise there might be more data ready to be read, so don't sleep | 160 } // otherwise there might be more data ready to be read (we were at the end of the buffer), so don't sleep |
72 } | 161 } |
73 } | 162 } |
74 | 163 |
75 void Midi::writeOutputLoop(){ | 164 void Midi::writeOutputLoop(){ |
76 while(!gShouldStop){ | 165 while(!gShouldStop){ |
83 continue; | 172 continue; |
84 } | 173 } |
85 int ret; | 174 int ret; |
86 ret = write(outputPort, &outputBytes[outputBytesReadPointer], sizeof(midi_byte_t)*length); | 175 ret = write(outputPort, &outputBytes[outputBytesReadPointer], sizeof(midi_byte_t)*length); |
87 if(ret < 0){ //error occurred | 176 if(ret < 0){ //error occurred |
88 // if(errno != EAGAIN){ // () would return EAGAIN when no data are available to read just now | |
89 // rt_printf("Error while writing midi %d\n", errno); | |
90 // } | |
91 rt_printf("error occurred while writing: %d\n", errno); | 177 rt_printf("error occurred while writing: %d\n", errno); |
92 usleep(10000); //wait before retrying | 178 usleep(10000); //wait before retrying |
93 continue; | 179 continue; |
94 } | 180 } |
95 | |
96 // inputBytesWritePointer += ret; | |
97 // if(inputBytesWritePointer == inputBytes.size()){ //wrap pointer around | |
98 // inputBytesWritePointer = 0; | |
99 // } | |
100 // if(ret < maxBytesToRead){ //no more data to retrieve at the moment | |
101 // usleep(1000); | |
102 // } // otherwise there might be more data ready to be read, so don't sleep | |
103 } | 181 } |
104 } | 182 } |
105 int Midi::readFrom(int port){ | 183 int Midi::readFrom(int port){ |
106 objAddrs[kMidiInput].push_back(this); | 184 objAddrs[kMidiInput].push_back(this); |
107 inputPort = open("/dev/midi1", O_RDONLY | O_NONBLOCK | O_NOCTTY); | 185 inputPort = open("/dev/midi1", O_RDONLY | O_NONBLOCK | O_NOCTTY); |
127 return 1; | 205 return 1; |
128 } | 206 } |
129 } | 207 } |
130 | 208 |
131 int Midi::getInput(){ | 209 int Midi::getInput(){ |
210 // if(parserEnabled == true) { | |
211 // return -3; | |
212 // } | |
132 if(inputPort < 0) | 213 if(inputPort < 0) |
133 return -2; | 214 return -2; |
134 if(inputBytesReadPointer == inputBytesWritePointer){ | 215 if(inputBytesReadPointer == inputBytesWritePointer){ |
135 return -1; // no bytes to read | 216 return -1; // no bytes to read |
136 } | 217 } |
138 if(inputBytesReadPointer == inputBytes.size()){ // wrap pointer | 219 if(inputBytesReadPointer == inputBytes.size()){ // wrap pointer |
139 inputBytesReadPointer = 0; | 220 inputBytesReadPointer = 0; |
140 } | 221 } |
141 return inputMessage; | 222 return inputMessage; |
142 } | 223 } |
224 | |
225 MidiParser* Midi::getParser(){ | |
226 if(parserEnabled == false){ | |
227 return 0; | |
228 } | |
229 return inputParser; | |
230 }; | |
143 | 231 |
144 int Midi::writeOutput(midi_byte_t byte){ | 232 int Midi::writeOutput(midi_byte_t byte){ |
145 return writeOutput(&byte, 1); | 233 return writeOutput(&byte, 1); |
146 } | 234 } |
147 | 235 |
150 if(ret < 0) | 238 if(ret < 0) |
151 return -1; | 239 return -1; |
152 else | 240 else |
153 return 1; | 241 return 1; |
154 } | 242 } |
243 | |
244 MidiChannelMessage::MidiChannelMessage(){}; | |
245 MidiChannelMessage::MidiChannelMessage(MidiMessageType type){ | |
246 setType(type); | |
247 }; | |
248 MidiChannelMessage::~MidiChannelMessage(){}; | |
249 MidiMessageType MidiChannelMessage::getType(){ | |
250 return _type; | |
251 }; | |
252 int MidiChannelMessage::getChannel(){ | |
253 return _channel; | |
254 }; | |
255 //int MidiChannelMessage::set(midi_byte_t* input); | |
256 // | |
257 //int MidiControlChangeMessage ::getValue(); | |
258 //int MidiControlChangeMessage::set(midi_byte_t* input){ | |
259 // channel = input[0]; | |
260 // number = input[1]; | |
261 // value = input[2]; | |
262 // return 3; | |
263 //} | |
264 | |
265 //int MidiNoteMessage::getNote(); | |
266 //int MidiNoteMessage::getVelocity(); | |
267 | |
268 //midi_byte_t MidiProgramChangeMessage::getProgram(); |