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();