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