1 /*
2     MIDIParser : SMF MIDI File parser 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 #ifdef __cplusplus
25 extern "C" {
26 #endif
27 
28 
29 
30 
31 #ifndef MIDI_PARSER_H
32 #define MIDI_PARSER_H
33 
34 #include <stddef.h>
35 #include <stdint.h>
36 #include <stddef.h>
37 #include "MIDICodes.h"
38 
39 #define MIDI_HEADER_STRING   "MThd"
40 #define MIDI_TRACK_STRING    "MTrk"
41 
42 //MIDI Header / Track byte offsets
43 #define MIDI_HEADER_FMT          (0x08)
44 #define MIDI_HEADER_TRACK_COUNT  (0x0A)
45 #define MIDI_HEADER_PPQ          (0x0C)
46 
47 #define MIDI_HEADER_SIZE         (0x0E)
48 #define MIDI_TRACK_HEADER_SIZE   (0x08)
49 #define MIDI_TRACK_LENGTH        (0x04)
50 
51 #define MIDI_META_MSG            (0xFF)
52 #define MIDI_META_SEQUENCE       (0x00)
53 #define MIDI_META_TEXT           (0x01)
54 #define MIDI_META_COPY_WRITE     (0x02)
55 #define MIDI_META_TRACK_NAME     (0x03)
56 #define MIDI_META_INSTNAME       (0x04)
57 #define MIDI_META_LYRICS         (0x05)
58 #define MIDI_META_MARKER         (0x06)
59 #define MIDI_META_CUEPOINT       (0x07)
60 #define MIDI_META_CHANPREFIX     (0x20)
61 #define MIDI_META_TRACKEND       (0x2F)
62 #define MIDI_META_TEMPO          (0x51)
63 #define MIDI_META_SMPTE          (0x54)
64 #define MIDI_META_TIME_SIG       (0x58)
65 #define MIDI_META_KEY_SIG        (0x59)
66 #define MIDI_META_SEQ_SPEC       (0x7F)
67 
68 #define US_PER_MINUTE            (60000000)
69 #define BPM(x)                   (US_PER_MINUTE/(x))
70 
71 #define MIDI_TRACK_BUFFER_SIZE   (32)
72 #define MAX_MIDI_TRACKS          (50)
73 
74 #define TRACK_MAX_NAME_LENGTH    (32)
75 #define TRACK_EVENT_BUFFER_SIZE  (2)
76 
77 
78 
79 #define PROGRAM_CHAR const char
80 #define PROGRAM_SPACE
81 #define FLASH_GET_PGM_BYTE
82 
83 typedef enum
84 {
85     STATE_INACTIVE = 0,
86     STATE_ACTIVE = 1,
87     STATE_FAST_FWD,
88     STATE_TRACK_BUILDING,
89 } MidiPlaybackState_t;
90 
91 
92 
93 enum
94 {
95     MAJOR_KEY = 0,
96     MINOR_KEY,
97 };
98 
99 #define MIDI_MAJOR_SCALE_OFFSET (1)
100 #define MIDI_MINOR_SCALE_OFFSET (4)
101 #define MIDI_CIRCLE_ELEMENTS    (7)
102 
103 typedef struct {
104 
105    uint8_t MIDI_Commands;
106    PROGRAM_CHAR* MIDI_CommandString;
107    uint8_t MIDI_MsgSize;
108 
109 } MidiLookup_t;
110 
111 
112 typedef struct
113 {
114   uint8_t   eventType;
115     uint8_t   parameter1;
116     uint8_t   parameter2;
117 } MIDI_CHAN_EVENT_t;
118 
119 typedef struct
120 {
121   uint8_t   eventType;
122     uint32_t  length;
123     uint8_t*  data;
124 } MIDI_SYSEX_EVENT_t;
125 
126 typedef struct
127 {
128   uint8_t   eventType;
129     uint8_t   metaType;
130     uint32_t  length;
131     uint8_t*  data;
132 } MIDI_META_EVENT_t;
133 
134 typedef struct
135 {
136     uint32_t  deltaTime;
137     union
138     {
139       uint8_t   eventType;
140       MIDI_CHAN_EVENT_t  chanEvent;
141       MIDI_SYSEX_EVENT_t sysExEvent;
142          MIDI_META_EVENT_t  metaEvent;
143     } event;
144 
145 } MIDI_EVENT_t;
146 
147 
148 typedef struct
149 {
150     uint8_t* startPtr;
151     uint32_t length;
152     uint32_t position;
153     uint32_t trackClock;
154     MIDI_EVENT_t trackEvent;
155     uint8_t  eventCount;
156     uint8_t  trackIndex;
157     uint8_t  bufferOffset;
158     uint8_t  runningStatus;
159     uint8_t  name[TRACK_MAX_NAME_LENGTH];
160     uint8_t  buffer[MIDI_TRACK_BUFFER_SIZE];
161 
162 } MIDI_TRACK_CHUNK_t;
163 
164 typedef struct
165 {
166     uint32_t maxLength;
167     uint32_t tickTime;
168     uint32_t lastTempoChange;
169     uint32_t BPM;
170     uint32_t trackLengthSecs;
171     uint16_t trackState; //represents which tracks are active
172     uint8_t  timeSignature; //BCD 4bit. (high4=numerator)
173     int8_t   keySignature; //BCD 4bit. high4=major/minor, low4=-7 -> +7
174     uint8_t  keyScale;
175 } MIDI_CURRENT_TRACK_STATE_t;
176 
177 #define FAST_FWD_ACTIVE  (0x1)
178 #define FAST_FWD_STATUS_MASK (0x07)
179 
180 #define FAST_FWD_IGNORE_CHANNEL_MASK    (0x80)
181 
182 #define FAST_FWD_IGNORE_PARAM1    (0xFF)
183 #define FAST_FWD_IGNORE_PARAM2    (0xFF)
184 #define FAST_FWD_NON_ZERO_PARAM2  (FAST_FWD_IGNORE_PARAM2-1)
185 
186 typedef enum {
187    FAST_FW_FIND_NULL = 0,
188   FAST_FWD_FIND_COMMAND = 1,
189   FAST_FWD_FIND_PARAM1,
190   FAST_FWD_FIND_PARAM2,
191 } MPB_FF_MODE_t;
192 
193 typedef struct
194 {
195   MPB_FF_MODE_t foundEventStatus :3; //MPB_FF_MODE_t type
196   MPB_FF_MODE_t searchMode :3; //MPB_FF_MODE_t type
197   uint8_t foundEventFlag   :2;
198 } MPB_FastFwd_t;
199 
200 typedef struct
201 {
202   //Number of notes per track
203   uint16_t noteCount;
204   //Even with multiple program changes, it records the first one
205   uint8_t   programNumber;
206 } MIDI_CHANNEL_STATS_t;
207 
208 #define MIDI_MAX_FILENAME (32)
209 #define MIDI_MAX_POLYPHONY (32)
210 typedef struct
211 {
212     uint16_t format;
213     uint16_t trackCount;
214     uint16_t PPQ;
215     uint32_t masterClock;
216     //uint32_t maxLength;
217     uint8_t  fileName[MIDI_MAX_FILENAME];
218     MIDI_TRACK_CHUNK_t Track[MAX_MIDI_TRACKS];
219     MIDI_CURRENT_TRACK_STATE_t currentState;
220 
221     //This is for the drum track.
222     //Once a drum is hit, it will stay on for a set period of time.
223     uint16_t  NoteOnTimer[MIDI_MAX_KEY+1];
224 
225     //TimeOn = PPQ / NoteOnDivisor.
226     uint16_t  NoteOnTime;
227     //Just for the drum track.
228     uint8_t  NoteOnList[MIDI_MAX_POLYPHONY];
229     uint8_t  channelPolyphony[MIDI_MAX_CHANNELS];
230     uint8_t  totalPolyphony;
231 
232     MidiPlaybackState_t playbackState;
233     int8_t transpose;
234 
235     MPB_FastFwd_t   FastFwd_Status;
236     MIDI_CHAN_EVENT_t FastFwd_Event;
237 
238     uint16_t channelStateBitmap;
239     MIDI_CHANNEL_STATS_t channelStats[MIDI_MAX_CHANNELS];
240 
241 } MIDI_HEADER_CHUNK_t;
242 
243 
244 
245 
246 void rawDump(uint8_t* data, uint16_t len);
247 void rawDumpStr(uint8_t* data, uint16_t len);
248 
249 
250 char* MIDIParse_KeySignature(int8_t keySig, uint8_t keyScale);
251 
252 size_t MIDIParse_Header(MIDI_HEADER_CHUNK_t* header, void* data, uint32_t size);
253 uint8_t* MIDIPopulate_HeaderTrack(MIDI_HEADER_CHUNK_t* header, uint8_t trackNo, uint8_t* filePos, void* data, uint32_t size);
254 void* MIDIParse_Track(MIDI_TRACK_CHUNK_t* track, void* data, uint32_t size);
255 void* MIDIParse_Event(MIDI_TRACK_CHUNK_t* track, MIDI_EVENT_t* event, uint8_t* data);
256 
257 void MIDI_PrintEventInfo(MIDI_EVENT_t* event);
258 
259 uint8_t MIDI_CommandSize(uint8_t command);
260 //Returns the length of the variable length field
261 uint8_t midiparse_variableLength(uint8_t* data, uint32_t* retValue);
262 
263 
264 void reverseOrder(char* array, uint8_t len);
265 void* findSubString(char* data, const char* string, uint32_t numBytes);
266 
267 
268 
269 
270 
271 
272 #endif
273 
274 
275 
276 #ifdef __cplusplus
277 }
278 #endif
279