1 /*
2 midiplayback : SMF MIDI File player suitable for 8 - 32bit targets
3 Copyright (c) 2004-2016 Adrian M. Gin
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License v2 as published by
7 the Free Software Foundation;
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18 The above copyright notice and this permission notice shall be
19 included in all copies or substantial portions of the Software.
20
21 */
22
23
24
25 #include "audio_stack.h"
26 #include "midiplayback.h"
27 #include "midiparser.h"
28 #include <stdint.h>
29 #include "linkedlist.h"
30
31
32 #include "MIDICodes.h"
33 #include "MIDIDebug.h"
34 #include "MIDIUtils.h"
35
36 #include <stdio.h>
37 #include <string.h>
38
39 void* MPBarray[sizeof(void*) * MPB_EVENT_STACK_SIZE];
40 STACK_t MPBStack = { MPBarray, 0, 0, MPB_EVENT_STACK_SIZE };
41
42 FILE* midifile;
43
MIDI_Tx(uint8_t byte)44 void MIDI_Tx(uint8_t byte)
45 {
46 // printf("0x%X, \n", byte);
47 }
48
MPB_ResetMIDI(void)49 void MPB_ResetMIDI(void)
50 {
51
52 /*MIDI_Tx(MIDI_SYSEX_START);
53 MIDI_Tx(0x7E);
54 MIDI_Tx(0x7F);
55 MIDI_Tx(0x09);
56 MIDI_Tx(0x01);
57 MIDI_Tx(MIDI_SYSEX_STOP);*/
58
59 MPB_StopAllSounds();
60
61 _clearEventBuffer();
62 }
63
MPB_StopAllSounds(void)64 void MPB_StopAllSounds(void)
65 {
66 MIDI_EVENT_t event;
67 uint8_t i;
68 for (i = 0; i < MIDI_MAX_CHANNELS; i++)
69 {
70 event.event.eventType = MIDI_CONTROL_CHANGE | i;
71 event.event.chanEvent.parameter1 = ALL_NOTES_OFF;
72 event.event.chanEvent.parameter2 = 0;
73 MPB_PlayEvent(&event, MPB_PB_ALL_ON);
74
75 event.event.chanEvent.parameter1 = SUSTAIN;
76 event.event.chanEvent.parameter2 = 0x00;
77 MPB_PlayEvent(&event, MPB_PB_ALL_ON);
78 }
79 }
80
81 //returns the number of seconds.
MPB_CurrentTimePosition(MIDI_HEADER_CHUNK_t * MIDIHdr)82 uint16_t MPB_CurrentTimePosition(MIDI_HEADER_CHUNK_t* MIDIHdr)
83 {
84
85 uint32_t currentPosition = MIDIHdr->currentState.tickTime + ((uint32_t) ((MIDIHdr->masterClock - MIDIHdr->currentState.lastTempoChange) * 60) / MIDIHdr->currentState.BPM);
86 currentPosition = currentPosition / MIDIHdr->PPQ;
87 return currentPosition;
88 }
89
MPB_CurrentBarPosition(MIDI_HEADER_CHUNK_t * MIDIHdr)90 uint16_t MPB_CurrentBarPosition(MIDI_HEADER_CHUNK_t* MIDIHdr)
91 {
92 return (MIDIHdr->masterClock / MIDIHdr->PPQ) >> 2;
93 }
94
95 //Finds out which MIDI channels are used in the MIDI file
96 //So later the FindEvent can be used to find all the On_Notes
97 //for a particular channel.
98 //We determine the instrument based off the MIDI_PROGRAM_CHANGE bytes.
99 //Should also keep track of number of Notes for each track.
MPB_BuildChannelStats(MIDI_HEADER_CHUNK_t * MIDIHdr,MIDI_EVENT_t * event)100 void MPB_BuildChannelStats(MIDI_HEADER_CHUNK_t* MIDIHdr, MIDI_EVENT_t* event)
101 {
102 if ((event->event.eventType & MIDI_MSG_TYPE_MASK) == MIDI_NOTE_ON && (event->event.chanEvent.parameter2 != 0))
103 {
104 uint8_t channel;
105 channel = event->event.eventType & MIDI_CHANNEL_MASK;
106 MIDIHdr->channelStateBitmap |= (1 << channel);
107 MIDIHdr->channelStats[channel].noteCount++;
108 }
109
110 if ((event->event.eventType & MIDI_MSG_TYPE_MASK) == MIDI_PROGRAM_CHANGE)
111 {
112 uint8_t channel;
113 channel = event->event.eventType & MIDI_CHANNEL_MASK;
114 MIDIHdr->channelStats[channel].programNumber = event->event.chanEvent.parameter1;
115 }
116
117 }
118
MPB_DetermineMIDIFileStats(MIDI_HEADER_CHUNK_t * MIDIHdr)119 void MPB_DetermineMIDIFileStats(MIDI_HEADER_CHUNK_t* MIDIHdr)
120 {
121 uint16_t i;
122 uint32_t* maxLength;
123
124 //Determine the MIDI channel constitution.
125 MPB_SetPlaybackState(MIDIHdr, STATE_TRACK_BUILDING);
126
127 MIDIHdr->masterClock = 0xFFFFFFFF;
128 while (MPB_ContinuePlay(MIDIHdr, MPB_PB_ALL_OFF) != MPB_FILE_FINISHED)
129 {
130 if (MIDIHdr->trackCount == 0)
131 {
132 break;
133 }
134 }
135 maxLength = &MIDIHdr->currentState.maxLength;
136 for (i = 0; i < MIDIHdr->trackCount; i++)
137 {
138 if (MIDIHdr->Track[i].trackClock > *maxLength)
139 {
140 *maxLength = MIDIHdr->Track[i].trackClock;
141 }
142 }
143
144 if (MIDIHdr->currentState.BPM == 0)
145 {
146 MIDIHdr->currentState.BPM = MPB_DEFAULT_TEMPO;
147 }
148
149 if (MIDIHdr->PPQ == 0)
150 {
151 MIDIHdr->PPQ = MPB_DEFAULT_PPQ;
152 }
153
154 MIDIHdr->NoteOnTime = MIDIHdr->PPQ / 8;
155
156 MIDIHdr->currentState.tickTime = MIDIHdr->currentState.tickTime + ((uint32_t) ((*maxLength - MIDIHdr->currentState.lastTempoChange) * 60) / MIDIHdr->currentState.BPM);
157
158 MIDIHdr->currentState.trackLengthSecs = MIDIHdr->currentState.tickTime / MIDIHdr->PPQ;
159 MIDI_Printf("Min: ", MIDIHdr->currentState.trackLengthSecs / 60);
160 MIDI_Printf("Sec: ", MIDIHdr->currentState.trackLengthSecs % 60);
161 MIDI_Printf("MaxLength: ", *maxLength >> 16);
162 MIDI_Printf("MaxLength: ", *maxLength);
163
164 for (i = 0; i < MIDI_MAX_CHANNELS; i++)
165 {
166 if (MIDIHdr->channelStateBitmap & (1 << i))
167 {
168 MIDI_Printf("Channel %d::ACTIVE\n", i);
169 //MIDI_Printf("Patch::%s\n", MIDIUtils_GetInstrumentName(MIDIHdr->channelStats[i].programNumber));
170 MIDI_Printf("NoteCount %d::\n", MIDIHdr->channelStats[i].noteCount);
171 }
172 else
173 {
174 MIDI_Printf("Channel %d::DISABLED\n", i);
175 }
176 }
177
178 }
179
MPB_PlayMIDIFile(MIDI_HEADER_CHUNK_t * MIDIHdr,char * filename)180 uint8_t MPB_PlayMIDIFile(MIDI_HEADER_CHUNK_t* MIDIHdr, char* filename)
181 {
182 uint8_t ret;
183 ret = MPB_OpenFile(filename);
184 if (ret)
185 {
186 return ret;
187 }
188
189 memset(MIDIHdr, 0, sizeof(MIDI_HEADER_CHUNK_t));
190 MPB_ResetMIDITracks(MIDIHdr);
191 //Need to reset the MIDI Tracks twice, one for Initialisation
192 //Another time because determining file stats requires a complete
193 //run through the file.
194 MPB_DetermineMIDIFileStats(MIDIHdr);
195 MPB_ResetMIDITracks(MIDIHdr);
196 MPB_SetPlaybackState(MIDIHdr, STATE_ACTIVE);
197
198 return 0;
199 }
200
MPB_EnablePlayback(MIDI_HEADER_CHUNK_t * MIDIHdr)201 void MPB_EnablePlayback(MIDI_HEADER_CHUNK_t* MIDIHdr)
202 {
203 MIDIHdr->playbackState = STATE_ACTIVE;
204 }
205
MPB_PausePlayback(MIDI_HEADER_CHUNK_t * MIDIHdr)206 void MPB_PausePlayback(MIDI_HEADER_CHUNK_t* MIDIHdr)
207 {
208 MIDIHdr->playbackState = STATE_INACTIVE;
209 }
210
MPB_SetPlaybackState(MIDI_HEADER_CHUNK_t * MIDIHdr,MidiPlaybackState_t state)211 void MPB_SetPlaybackState(MIDI_HEADER_CHUNK_t* MIDIHdr, MidiPlaybackState_t state)
212 {
213 MIDIHdr->playbackState = state;
214 }
215
MPB_GetPlaybackState(MIDI_HEADER_CHUNK_t * MIDIHdr)216 MidiPlaybackState_t MPB_GetPlaybackState(MIDI_HEADER_CHUNK_t* MIDIHdr)
217 {
218 return MIDIHdr->playbackState;
219 }
220
MPB_TogglePlayback(MIDI_HEADER_CHUNK_t * MIDIHdr)221 void MPB_TogglePlayback(MIDI_HEADER_CHUNK_t* MIDIHdr)
222 {
223 if( MIDIHdr->playbackState == STATE_INACTIVE )
224 {
225 MIDIHdr->playbackState = STATE_ACTIVE;
226 }
227 else if( MIDIHdr->playbackState == STATE_ACTIVE )
228 {
229 MIDIHdr->playbackState = STATE_INACTIVE;
230 }
231
232 }
233
MPB_ResetMIDITracks(MIDI_HEADER_CHUNK_t * MIDIHdr)234 void MPB_ResetMIDITracks(MIDI_HEADER_CHUNK_t* MIDIHdr)
235 {
236 uint16_t i;
237 uint8_t* position = 0;
238 uint8_t* buf;
239 uint8_t* ptr;
240
241 buf = (uint8_t*) &MIDIHdr->Track[0].buffer;
242 MPB_ReadToBuffer(position, buf);
243
244 ptr = (uint8_t*)findSubString((char*) buf, MIDI_HEADER_STRING, MIDI_TRACK_BUFFER_SIZE);
245 if (ptr)
246 {
247 if ((ptr - buf + MIDI_HEADER_SIZE) > MIDI_TRACK_BUFFER_SIZE)
248 {
249 MPB_ReadToBuffer( (uint8_t*)(ptr - buf), buf);
250 position = (uint8_t*)(ptr - buf);
251 ptr = buf;
252 }
253 }
254
255 position = position + MIDIParse_Header(MIDIHdr, buf, MIDI_TRACK_BUFFER_SIZE);
256 position = position + MIDI_HEADER_SIZE;
257
258 for (i = 0; i < MIDIHdr->trackCount; i++)
259 {
260 MPB_ReadToBuffer( position, buf);
261 position = (uint8_t*)MIDIPopulate_HeaderTrack(MIDIHdr, i, position, buf, MIDI_TRACK_BUFFER_SIZE);
262 MIDIHdr->Track[i].eventCount = MPB_NEW_DATA;
263 MIDIHdr->Track[i].trackIndex = i;
264 MIDIHdr->Track[i].trackClock = 0;
265 }
266
267 MIDIHdr->currentState.trackState = 0;
268 }
269
MPB_RePosition(MIDI_HEADER_CHUNK_t * MIDIHdr,uint32_t position,MIDI_PB_MODE mode)270 uint8_t MPB_RePosition(MIDI_HEADER_CHUNK_t* MIDIHdr, uint32_t position, MIDI_PB_MODE mode)
271 {
272 MPB_ResetMIDITracks(MIDIHdr);
273 MIDIHdr->masterClock = position;
274 return MPB_ContinuePlay(MIDIHdr, mode);
275 }
276
277 //Finds the next 'MIDI Command' from the given position.
278 //
MPB_FastFwd_ToEvent(MIDI_HEADER_CHUNK_t * MIDIHdr,uint32_t position,MIDI_PB_MODE mode,MIDI_CHAN_EVENT_t * event,MPB_FF_MODE_t ffMode)279 uint8_t MPB_FastFwd_ToEvent(MIDI_HEADER_CHUNK_t* MIDIHdr, uint32_t position, MIDI_PB_MODE mode, MIDI_CHAN_EVENT_t* event, MPB_FF_MODE_t ffMode)
280 {
281 MPB_RePosition(MIDIHdr, position, MPB_PB_ALL_OFF);
282
283 MIDIHdr->FastFwd_Status.foundEventStatus = FAST_FW_FIND_NULL;
284 MIDIHdr->FastFwd_Status.foundEventFlag = FAST_FWD_ACTIVE;
285 MIDIHdr->FastFwd_Status.searchMode = ffMode;
286
287 MIDIHdr->FastFwd_Event.eventType = event->eventType;
288 MIDIHdr->FastFwd_Event.parameter1 = event->parameter1;
289 MIDIHdr->FastFwd_Event.parameter2 = event->parameter2; //A non zero velocity.
290
291 while (MIDIHdr->FastFwd_Status.foundEventFlag)
292 {
293 MIDIHdr->masterClock++;
294 if (MPB_ContinuePlay(MIDIHdr, MPB_PB_ALL_OFF) == MPB_FILE_FINISHED)
295 {
296 break;
297 }
298 }
299
300 //Need to minus some position, so that when play resumes
301 //the message is picked up.
302 if (MIDIHdr->FastFwd_Status.foundEventFlag == 0)
303 {
304 position = MIDIHdr->masterClock - 1;
305 }
306
307 if (position == 0)
308 {
309 position = 1;
310 }
311
312 MPB_RePosition(MIDIHdr, position - 1, mode);
313
314 return MIDIHdr->FastFwd_Status.foundEventStatus;
315 }
316
MPB_FastFwd_TestEvent(MIDI_HEADER_CHUNK_t * MIDIHdr,MIDI_EVENT_t * event)317 void MPB_FastFwd_TestEvent(MIDI_HEADER_CHUNK_t* MIDIHdr, MIDI_EVENT_t* event)
318 {
319
320 MPB_FastFwd_t* fastFwd_Status;
321 MIDI_CHAN_EVENT_t* fastFwd_Event;
322
323 fastFwd_Status = &MIDIHdr->FastFwd_Status;
324 fastFwd_Event = &MIDIHdr->FastFwd_Event;
325
326 if (event->event.eventType >= MIDI_NOTE_OFF && event->event.eventType <= MIDI_PITCH_CHANGE)
327 {
328 if (fastFwd_Event->eventType == event->event.chanEvent.eventType)
329 {
330 fastFwd_Status->foundEventStatus = FAST_FWD_FIND_COMMAND;
331
332 if ((fastFwd_Event->parameter1 == event->event.chanEvent.parameter1) || (fastFwd_Event->parameter1 == FAST_FWD_IGNORE_PARAM1))
333 {
334 fastFwd_Status->foundEventStatus = FAST_FWD_FIND_PARAM1;
335
336 if ((fastFwd_Event->parameter2 == event->event.chanEvent.parameter2) || (fastFwd_Event->parameter2 == FAST_FWD_IGNORE_PARAM2) || ((fastFwd_Event->parameter2 == FAST_FWD_NON_ZERO_PARAM2) && (event->event.chanEvent.parameter2 != 0)))
337 {
338 fastFwd_Status->foundEventStatus = FAST_FWD_FIND_PARAM2;
339 }
340 }
341
342 }
343
344 if (fastFwd_Status->searchMode == fastFwd_Status->foundEventStatus)
345 {
346 fastFwd_Status->foundEventFlag = 0;
347 }
348 }
349 }
350
MPB_RePositionTime(MIDI_HEADER_CHUNK_t * MIDIHdr,uint16_t timePosSec,MIDI_PB_MODE mode)351 uint8_t MPB_RePositionTime(MIDI_HEADER_CHUNK_t* MIDIHdr, uint16_t timePosSec, MIDI_PB_MODE mode)
352 {
353 uint16_t currentPos;
354 uint32_t myMasterClock;
355 uint32_t myMaxLength = MIDIHdr->currentState.maxLength;
356 uint16_t i;
357 MPB_ResetMIDITracks(MIDIHdr);
358
359 for (i = 0; i < 30000; i++)
360 {
361 MPB_ContinuePlay(MIDIHdr, mode);
362 currentPos = MPB_CurrentTimePosition(MIDIHdr);
363
364 if (currentPos >= timePosSec)
365 {
366 break;
367 }
368
369 if (currentPos < timePosSec)
370 {
371 myMasterClock = myMasterClock + (MIDIHdr->PPQ << 2);
372 MIDIHdr->masterClock = myMasterClock;
373 }
374
375 if (myMasterClock > myMaxLength)
376 {
377 MIDIHdr->masterClock = myMaxLength;
378 break;
379 }
380 }
381
382 MIDI_Printf("Min: ", MPB_CurrentTimePosition(MIDIHdr) / 60);
383 MIDI_Printf("Sec: ", MPB_CurrentTimePosition(MIDIHdr) % 60);
384 MIDI_Printf("Iter: ", i);
385 return 0;
386 }
387
MPB_ContinuePlay(MIDI_HEADER_CHUNK_t * MIDIHdr,MIDI_PB_MODE mode)388 uint8_t MPB_ContinuePlay(MIDI_HEADER_CHUNK_t* MIDIHdr, MIDI_PB_MODE mode)
389 {
390 uint16_t i;
391 uint8_t ret = 0;
392
393 for (i = 0; i < MIDIHdr->trackCount; i++)
394 {
395 ret = 0;
396 if ((MIDIHdr->Track[i].eventCount != MPB_TRACK_STOPPED))
397 {
398 while (1)
399 {
400 ret = MPB_PlayTrack(MIDIHdr, &MIDIHdr->Track[i], mode);
401 if (ret == MPB_REPOSITION_EVENT)
402 {
403 break;
404 }
405 else if (ret == MPB_TRACK_STOPPED)
406 {
407 MIDIHdr->currentState.trackState++;
408 if (MIDIHdr->currentState.trackState >= MIDIHdr->trackCount)
409 {
410 return MPB_FILE_FINISHED;
411 }
412 break;
413 }
414 else
415 {
416
417 }
418 }
419 }
420 }
421
422 if (MIDIHdr->trackCount == 0)
423 {
424 return MPB_FILE_FINISHED;
425 }
426
427 return MPB_FILE_STILL_PLAYING;
428 }
429
430 #define MPB_ON_TIME (1)
MPB_ProcessGenericEvent(MIDI_HEADER_CHUNK_t * MIDIHdr,MIDI_TRACK_CHUNK_t * track,MIDI_EVENT_t * event,MIDI_PB_MODE mode)431 void MPB_ProcessGenericEvent(MIDI_HEADER_CHUNK_t* MIDIHdr, MIDI_TRACK_CHUNK_t* track, MIDI_EVENT_t* event, MIDI_PB_MODE mode)
432 {
433 uint8_t midiChannel;
434
435 MPB_ApplyTranspose(event, MIDIHdr->transpose);
436 MPB_PlayEvent(event, mode);
437 track->eventCount = MPB_PLAY_NEXT_EVENT;
438
439 midiChannel = (event->event.eventType & 0x0F);
440
441 if (MIDIHdr->FastFwd_Status.foundEventFlag)
442 {
443 MPB_FastFwd_TestEvent(MIDIHdr, event);
444 }
445
446 if (MIDIHdr->playbackState == STATE_TRACK_BUILDING)
447 {
448 MPB_BuildChannelStats(MIDIHdr, event);
449 }
450
451 //Keep track of polyphony here
452 if ((event->event.eventType & 0xF0) == MIDI_NOTE_ON)
453 {
454 //A note on with a velocity of 0, can be NOTE_OFFs.
455 if (event->event.chanEvent.parameter2 == 0)
456 {
457 if (MIDIHdr->channelPolyphony[midiChannel])
458 {
459 MIDIHdr->channelPolyphony[midiChannel]--;
460 }
461 if (MIDIHdr->totalPolyphony)
462 {
463 MIDIHdr->totalPolyphony--;
464 }
465 }
466 else
467 {
468 MIDIHdr->channelPolyphony[midiChannel]++;
469 MIDIHdr->totalPolyphony++;
470 }
471 //The drum channel has an exception because sometimes there
472 //might not be any offnotes. etc
473 if (midiChannel == MIDI_DRUM_CHANNEL)
474 {
475 MIDIHdr->NoteOnTimer[event->event.chanEvent.parameter1] = MIDIHdr->NoteOnTime;
476 }
477 }
478 else if ((event->event.eventType & 0xF0) == MIDI_NOTE_OFF)
479 {
480 if (MIDIHdr->channelPolyphony[midiChannel])
481 {
482 MIDIHdr->channelPolyphony[midiChannel]--;
483 }
484 if (MIDIHdr->totalPolyphony)
485 {
486 MIDIHdr->totalPolyphony--;
487 }
488 //If however we receive a Note Off before the timer has
489 //elapsed, then reset it all.
490 if (midiChannel == MIDI_DRUM_CHANNEL)
491 {
492 MIDIHdr->NoteOnTimer[event->event.chanEvent.parameter1] = 0;
493 }
494 //Turn off the respective LED.
495 //LEDArray_SetLED(0, 0, 0, 0);
496 }
497
498 if (event->event.eventType == MIDI_META_MSG)
499 {
500 MPB_ProcessMetaEvent(MIDIHdr, track, event);
501 }
502 }
503
MPB_PlayTrack(MIDI_HEADER_CHUNK_t * MIDIHdr,MIDI_TRACK_CHUNK_t * track,MIDI_PB_MODE mode)504 uint8_t MPB_PlayTrack(MIDI_HEADER_CHUNK_t* MIDIHdr, MIDI_TRACK_CHUNK_t* track, MIDI_PB_MODE mode)
505 {
506 uint8_t* position = (uint8_t*)track->startPtr;
507 uint8_t* oldPosition;
508 uint8_t* readPtr = &track->buffer[0] + track->bufferOffset;
509 uint8_t* originPtr = &track->buffer[0];
510 MIDI_EVENT_t* event = &track->trackEvent;
511
512 if (track->eventCount == MPB_TRACK_STOPPED)
513 {
514 return MPB_TRACK_STOPPED;
515 }
516
517 if (track->eventCount == MPB_NEW_DATA)
518 {
519 }
520 else
521 {
522 if (track->trackClock <= MIDIHdr->masterClock)
523 {
524 MPB_ProcessGenericEvent(MIDIHdr, track, event, mode);
525 }
526 else
527 {
528 //Not yet time to play;
529 //event->deltaTime--;
530 return MPB_REPOSITION_EVENT;
531 }
532 }
533
534 while ((track->eventCount != MPB_TRACK_STOPPED))
535 {
536 //If the buffer doesn't contain enough information for a full parse
537 //Or if we are requested for new data.
538 if ((track->eventCount == MPB_NEW_DATA) || ((track->bufferOffset + 6) > MIDI_TRACK_BUFFER_SIZE))
539 {
540 MPB_ReadToBuffer(track->startPtr, &track->buffer[0]);
541 originPtr = &track->buffer[0];
542 readPtr = originPtr;
543 track->bufferOffset = 0;
544 }
545
546 oldPosition = readPtr;
547 //MIDI Parse Event returns the ptr to the next event.
548 readPtr = (uint8_t*)MIDIParse_Event(track, event, readPtr);
549 track->bufferOffset = readPtr - originPtr;
550
551 //On successful parse, we save the position.
552 if (track->bufferOffset <= MIDI_TRACK_BUFFER_SIZE)
553 {
554 position = position + (readPtr - oldPosition);
555 track->startPtr = (position);
556 if (event->deltaTime)
557 {
558 track->trackClock = track->trackClock + event->deltaTime;
559 track->eventCount = MPB_QUEUED_EVENT;
560
561 //event->deltaTime--;
562 return MPB_QUEUED_EVENT;
563 }
564 else
565 {
566 MPB_ProcessGenericEvent(MIDIHdr, track, event, mode);
567 }
568 }
569 else
570 {
571 //If the parse was not fully completed due to incomplete read data,
572 //We must read it again.
573 track->eventCount = MPB_NEW_DATA;
574 //We skip if the lengths are too long
575 if (event->event.eventType == MIDI_META_MSG)
576 {
577 if (event->event.metaEvent.length > (MIDI_TRACK_BUFFER_SIZE - 6))
578 {
579 MPB_ProcessMetaEvent(MIDIHdr, track, event);
580 position = position + (readPtr - oldPosition);
581 track->startPtr = position;
582 }
583 }
584 if (event->event.eventType == MIDI_SYSEX_START)
585 {
586 if (event->event.sysExEvent.length > (MIDI_TRACK_BUFFER_SIZE - 6))
587 {
588 position = position + (readPtr - oldPosition);
589 track->startPtr = position;
590 }
591 }
592 //Need to put in a check here since some events could be
593 //larger than the buffer size, in which case we shall ignore.
594 }
595 }
596
597 return track->eventCount;
598 }
599
MPB_AddEvent(MIDI_EVENT_t * event)600 uint8_t MPB_AddEvent(MIDI_EVENT_t* event)
601 {
602 uint8_t ret;
603 ret = STACK_PushData(&MPBStack, event);
604 return ret;
605 }
606
MPB_GetNextEvent(void)607 MIDI_EVENT_t* MPB_GetNextEvent(void)
608 {
609 MIDI_EVENT_t* event;
610 event = (MIDI_EVENT_t*)FIFO_PeekData(&MPBStack);
611 return event;
612 }
613
MPB_ConfirmEventTx(void)614 MIDI_EVENT_t* MPB_ConfirmEventTx(void)
615 {
616 MIDI_EVENT_t* event;
617 event = (MIDI_EVENT_t*)FIFO_PopData(&MPBStack);
618 return event;
619 }
620
621 #define MIN_PPQ (48)
622 #define MIN_BMP (20)
623 #define MIN_BMP_PPQ_PRODUCT (MIN_BMP*MIN_PPQ)
624 #define MIN_BMP_PPQ_PRESCALER (64)
MPB_SetTickRate(uint16_t bpm,uint16_t PPQ)625 uint16_t MPB_SetTickRate(uint16_t bpm, uint16_t PPQ)
626 {
627 //*to send a Timing signal we need to send 24 0xF8's per quarter note
628 uint16_t usPerTick;
629 //Use a 1x prescaler.
630 usPerTick = ((US_PER_MINUTE) / (bpm) / PPQ);
631
632 //Use a 64x prescaler if the speed is too slow
633 if ((bpm * PPQ) < MIN_BMP_PPQ_PRODUCT)
634 {
635 usPerTick = ((US_PER_MINUTE / MIN_BMP_PPQ_PRESCALER) / (bpm) / PPQ);
636 //SET_TIMER_PRESCALER(64);
637 }
638 else
639 {
640 //SET_TIMER_PRESCALER(1);
641 }
642 //SET_TIMER_INTERVAL(usPerTick);
643
644 //PR1 = 41*usPerTick;
645 //T1CONbits.TCKPS0 = 0;
646 //T1CONbits.TCKPS1 = 1;
647 MIDI_Printf("BPM: ", bpm);
648 MIDI_Printf("PPQ: ", PPQ);
649 MIDI_Printf("usPerTick: ", usPerTick);
650 return usPerTick;
651 }
652
MPB_ProcessMetaEvent(MIDI_HEADER_CHUNK_t * MIDIHdr,MIDI_TRACK_CHUNK_t * track,MIDI_EVENT_t * event)653 void MPB_ProcessMetaEvent(MIDI_HEADER_CHUNK_t* MIDIHdr, MIDI_TRACK_CHUNK_t* track, MIDI_EVENT_t* event)
654 {
655
656 uint8_t length = TRACK_MAX_NAME_LENGTH;
657 uint16_t existingBPM;
658 if ( TRACK_MAX_NAME_LENGTH > event->event.metaEvent.length)
659 {
660 length = event->event.metaEvent.length;
661 }
662
663 switch (event->event.metaEvent.metaType)
664 {
665 case MIDI_META_TRACK_NAME:
666 memcpy(&track->name, event->event.metaEvent.data, length);
667 MIDI_Printf("Track ", 0);
668 MIDI_Printf("", track->trackIndex);
669 //MIDI_Printfn((char*)&track->name, length);
670 MIDI_Printf("\n", 0);
671 break;
672
673 case MIDI_META_TEMPO:
674 existingBPM = MIDIHdr->currentState.BPM;
675 reverseOrder((char*) event->event.metaEvent.data, event->event.metaEvent.length);
676 memcpy(&MIDIHdr->currentState.BPM, event->event.metaEvent.data, event->event.metaEvent.length); //*bpmptr;
677
678 MIDIHdr->currentState.BPM = BPM(MIDIHdr->currentState.BPM);
679 MPB_SetTickRate(MIDIHdr->currentState.BPM, MIDIHdr->PPQ);
680
681 if ((existingBPM != MIDIHdr->currentState.BPM) && existingBPM)
682 {
683 MIDIHdr->currentState.tickTime += ((track->trackClock - MIDIHdr->currentState.lastTempoChange) * 60) / (existingBPM);
684 MIDIHdr->currentState.lastTempoChange = track->trackClock;
685 }
686
687 break;
688
689 case MIDI_META_LYRICS:
690 //Lyrics parsed in play events.
691 //MIDI_Printfn(event->event.metaEvent.data, event->event.metaEvent.length);
692 break;
693
694 case MIDI_META_TIME_SIG:
695 MIDIHdr->currentState.timeSignature = 0;
696 MIDIHdr->currentState.timeSignature |= event->event.metaEvent.data[0] << 4;
697 MIDIHdr->currentState.timeSignature |= 1 << event->event.metaEvent.data[1];
698 MIDI_Printf("Numerator: ", MIDIHdr->currentState.timeSignature >> 4);
699 MIDI_Printf("Denominator: ", MIDIHdr->currentState.timeSignature & 0x0F);
700 break;
701
702 case MIDI_META_KEY_SIG:
703 MIDIHdr->currentState.keySignature = event->event.metaEvent.data[0];
704 //The major or minor scale
705 MIDIHdr->currentState.keyScale = event->event.metaEvent.data[1];
706 MIDI_Printf("Key Signature: ", 0);
707 MIDI_Printf(MIDIParse_KeySignature(MIDIHdr->currentState.keySignature, MIDIHdr->currentState.keyScale), 0);
708 MIDI_Printf("\n", 0);
709 break;
710
711 case MIDI_META_TRACKEND:
712 MIDI_Printf("TrackFinished: ", track->trackIndex);
713 track->eventCount = MPB_TRACK_STOPPED;
714 break;
715
716 default:
717 break;
718 }
719 }
720
MPB_SetTranspose(MIDI_HEADER_CHUNK_t * MIDIHdr,int8_t transpose)721 void MPB_SetTranspose(MIDI_HEADER_CHUNK_t* MIDIHdr, int8_t transpose)
722 {
723 MIDIHdr->transpose = transpose;
724 }
725
MPB_ApplyTranspose(MIDI_EVENT_t * event,int8_t transpose)726 void MPB_ApplyTranspose(MIDI_EVENT_t* event, int8_t transpose)
727 {
728 //Apply transpose here
729 if (((event->event.eventType & 0xF0) == MIDI_NOTE_ON) || ((event->event.eventType & 0xF0) == MIDI_NOTE_OFF))
730 {
731 uint8_t chan;
732 chan = event->event.eventType & 0x0F;
733 if (chan != MIDI_DRUM_CHANNEL)
734 {
735 event->event.chanEvent.parameter1 += transpose;
736 }
737 }
738
739 }
740
MPB_PlayEvent(MIDI_EVENT_t * event,MIDI_PB_MODE mode)741 void MPB_PlayEvent(MIDI_EVENT_t* event, MIDI_PB_MODE mode)
742 {
743 if (mode == MPB_PB_ALL_OFF)
744 {
745 return;
746 }
747
748 switch (event->event.eventType)
749 {
750 uint32_t i;
751 case MIDI_SYSEX_START:
752 MIDI_Tx(MIDI_SYSEX_START);
753 //MIXI_TxDump(event->event.sysExEvent.data, event->event.sysExEvent.length);
754 MIDI_Printf("MIDISYSX FOUND:", event->event.sysExEvent.length);
755
756 for (i = 0; i < event->event.sysExEvent.length; i++)
757 {
758 MIDI_Tx(event->event.sysExEvent.data[i]);
759 MIDI_Printf("B:", event->event.sysExEvent.data[i]);
760 }
761
762 //MIDI_Printfn(event->event.sysExEvent.data, event->event.sysExEvent.length);
763
764 break;
765
766 case MIDI_META_MSG:
767
768 if (mode == MPB_PB_NO_NOTES)
769 {
770 break;
771 }
772
773 switch (event->event.metaEvent.metaType)
774 {
775 case MIDI_META_TEXT:
776 case MIDI_META_LYRICS:
777
778 //replace_char( (char*)event->event.metaEvent.data, '\\', '\n');
779 //replace_char( (char*)event->event.metaEvent.data, '/', '\n');
780
781 //MIDI_Printfn(event->event.metaEvent.data, event->event.metaEvent.length);
782 //MIDI_Printf(event->event.metaEvent.data, event->event.metaEvent.length);
783
784 break;
785 }
786
787 break;
788
789 default:
790 //MIDI_PrintEventInfo(event);
791
792 if( mode == MPB_PB_NO_VOL )
793 {
794 if (((event->event.eventType & 0xF0) == MIDI_CONTROL_CHANGE) && ((event->event.chanEvent.parameter1 & 0x7F) == CHANNEL_VOLUME))
795 {
796 break;
797 }
798 }
799
800
801 if (mode == MPB_PB_NO_NOTES)
802 {
803 if (((event->event.eventType & 0xF0) == MIDI_NOTE_ON) || ((event->event.eventType & 0xF0) == MIDI_NOTE_OFF))
804 {
805 break;
806 }
807 }
808 else if (mode == MPB_PB_SAVE_MIDI_STATUS)
809 {
810 if (((event->event.eventType & 0xF0) >= MIDI_AFTERTOUCH) && ((event->event.eventType & 0xF0) < MIDI_SYSEX_START))
811 {
812 MPB_SaveMIDIStatus(&event->event.chanEvent);
813 }
814 break;
815 }
816
817 SendMIDIEvent(&event->event.chanEvent);
818 MPB_OutputMIDIChanEvent(&event->event.chanEvent);
819
820 break;
821 }
822 }
823
MPB_OutputMIDIChanEvent(MIDI_CHAN_EVENT_t * chanEvent)824 void MPB_OutputMIDIChanEvent(MIDI_CHAN_EVENT_t* chanEvent)
825 {
826 static uint8_t runningStatus = 0x00;
827 if (chanEvent->eventType == runningStatus)
828 {
829
830 }
831 else
832 {
833 runningStatus = chanEvent->eventType;
834 MIDI_Tx(chanEvent->eventType);
835 }
836 MIDI_Tx(chanEvent->parameter1);
837 if (MIDI_CommandSize(chanEvent->eventType & 0xF0) == 3)
838 {
839 MIDI_Tx(chanEvent->parameter2);
840 }
841 }
842
843 #define MPB_IGNORE_BYTE (0xFF)
844 #define MPB_SAVE_BUFFER_SIZE (16)
845
846 //#define MPB_STATUS_BUFFER_ARRAY
847
848 #ifdef MPB_STATUS_BUFFER_ARRAY
849 MIDI_CHAN_EVENT_t StatusBuffer[MIDI_MAX_CHANNELS][MPB_SAVE_BUFFER_SIZE];
850 #else
851 LINKED_LIST_t StatusBuffer[MIDI_MAX_CHANNELS];
852 #endif
853
854 uint16_t StatusBufferCount[MIDI_MAX_CHANNELS];
855
856 //Saves the channel event. Does not save Note On / Offs
MPB_SaveMIDIStatus(MIDI_CHAN_EVENT_t * chanEvent)857 void MPB_SaveMIDIStatus(MIDI_CHAN_EVENT_t* chanEvent)
858 {
859
860 /* MIDI_AFTERTOUCH = 0xA0,
861 MIDI_CONTROL_CHANGE = 0xB0,
862 MIDI_PROGRAM_CHANGE = 0xC0,
863 MIDI_CHANNEL_PRESSURE = 0xD0,
864 MIDI_PITCH_CHANGE = 0xE0,*/
865
866 MIDI_CHAN_EVENT_t* foundEvent = NULL;
867
868 //All messages are channel specific.
869 switch (chanEvent->eventType & 0xF0)
870 {
871
872 case MIDI_AFTERTOUCH:
873 case MIDI_CONTROL_CHANGE:
874 foundEvent = _findChanEventInBuffer(chanEvent->eventType, chanEvent->parameter1);
875 if (foundEvent)
876 {
877 foundEvent->parameter2 = chanEvent->parameter2;
878 }
879 break;
880
881 case MIDI_PROGRAM_CHANGE:
882 case MIDI_CHANNEL_PRESSURE:
883 case MIDI_PITCH_CHANGE:
884 foundEvent = _findChanEventInBuffer(chanEvent->eventType, MPB_IGNORE_BYTE);
885 if (foundEvent)
886 {
887 foundEvent->parameter1 = chanEvent->parameter1;
888 foundEvent->parameter2 = chanEvent->parameter2;
889 }
890 break;
891
892 default:
893 foundEvent = NULL;
894 break;
895 }
896
897 if (foundEvent == NULL)
898 {
899 _addEventToBuffer(chanEvent);
900 }
901
902 }
903
MPB_ReplayStatusBuffer(void)904 void MPB_ReplayStatusBuffer(void)
905 {
906 int i, j;
907 int bufferCount;
908
909 MIDI_CHAN_EVENT_t* chanEvent;
910
911 for (bufferCount = 0, j = 0; j < MIDI_MAX_CHANNELS; j++)
912 {
913 for (i = 0; i < StatusBufferCount[j]; i++)
914 {
915 chanEvent = _getEventFromBuffer(j, i);
916 if (chanEvent)
917 {
918 MPB_OutputMIDIChanEvent(chanEvent);
919 }
920 }
921 bufferCount = bufferCount + StatusBufferCount[j];
922 }
923
924 MIDI_Printf("TotalStatusCount=", bufferCount);
925 }
926
_addEventToBuffer(MIDI_CHAN_EVENT_t * chanEvent)927 void _addEventToBuffer(MIDI_CHAN_EVENT_t* chanEvent)
928 {
929
930 uint8_t channel;
931 MIDI_CHAN_EVENT_t* newChanEvent;
932
933 channel = chanEvent->eventType & 0x0F;
934
935 #ifdef MPB_STATUS_BUFFER_ARRAY
936 if( StatusBufferCount[channel] < MPB_SAVE_BUFFER_SIZE)
937 {
938 memcpy(&StatusBuffer[channel][StatusBufferCount[channel]], chanEvent, sizeof(MIDI_CHAN_EVENT_t));
939 StatusBufferCount[channel]++;
940 }
941 #else
942 newChanEvent = (MIDI_CHAN_EVENT_t*)LL_Malloc(sizeof(MIDI_CHAN_EVENT_t));
943 memcpy(newChanEvent, chanEvent, sizeof(MIDI_CHAN_EVENT_t));
944 LL_AppendData(&StatusBuffer[channel], (void*) newChanEvent);
945 StatusBufferCount[channel]++;
946 #endif
947
948 }
949
_getEventFromBuffer(uint8_t channel,uint16_t index)950 MIDI_CHAN_EVENT_t* _getEventFromBuffer(uint8_t channel, uint16_t index)
951 {
952 #ifdef MPB_STATUS_BUFFER_ARRAY
953 return &StatusBuffer[channel][index];
954 #else
955 return (MIDI_CHAN_EVENT_t*) LL_ReturnNodeDataFromIndex(&StatusBuffer[channel], index);
956 #endif
957 }
958
_clearEventBuffer(void)959 void _clearEventBuffer(void)
960 {
961 int i;
962
963 #ifdef MPB_STATUS_BUFFER_ARRAY
964 for( i = 0; i < MIDI_MAX_CHANNELS; i++)
965 {
966 memset(&StatusBuffer[i], 0, sizeof(MIDI_CHAN_EVENT_t)*MPB_SAVE_BUFFER_SIZE);
967 StatusBufferCount[i] = 0;
968 }
969
970 #else
971 for (i = 0; i < MIDI_MAX_CHANNELS; i++)
972 {
973 LL_DeleteListAndData(&StatusBuffer[i]);
974 StatusBufferCount[i] = 0;
975 }
976 #endif
977 }
978
_findChanEventInBuffer(uint8_t firstByte,uint8_t secondByte)979 MIDI_CHAN_EVENT_t* _findChanEventInBuffer(uint8_t firstByte, uint8_t secondByte)
980 {
981 int i;
982 MIDI_CHAN_EVENT_t* foundEvent;
983 uint8_t channel;
984
985 channel = firstByte & 0x0F;
986
987 for (i = 0; i < StatusBufferCount[channel]; i++)
988 {
989 foundEvent = _getEventFromBuffer(channel, i);
990 if (foundEvent->eventType == firstByte)
991 {
992 if (secondByte == MPB_IGNORE_BYTE)
993 {
994 return foundEvent;
995 }
996 else
997 {
998 if (foundEvent->parameter1 == secondByte)
999 {
1000 return foundEvent;
1001 }
1002 }
1003 }
1004 }
1005
1006 return NULL;
1007 }
1008
_MIDI_fileopen(char * filename)1009 uint8_t _MIDI_fileopen(char* filename)
1010 {
1011 midifile = fopen(filename, "rb");
1012 return 0;
1013 }
1014
_MIDI_fileclose(void)1015 void _MIDI_fileclose(void)
1016 {
1017 fclose(midifile);
1018 }
1019
_MIDI_readbuf(uint8_t * position,uint8_t * buf,uint16_t size)1020 void _MIDI_readbuf(uint8_t* position, uint8_t* buf, uint16_t size)
1021 {
1022 fseek(midifile, (long long) position, 0);
1023 size_t a = fread(buf, 1, size, midifile);
1024 }
1025