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