1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 Stepan Moskovchenko
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
25 struct Track
* readTrack(int file
);
28 struct MIDIfile midi_file IBSS_ATTR
;
30 struct MIDIfile
* loadFile(const char * filename
)
32 struct MIDIfile
* mfload
;
33 int file
= rb
->open (filename
, O_RDONLY
);
37 midi_debug("Could not open file");
43 rb
->memset(mfload
, 0, sizeof(struct MIDIfile
));
45 int fileID
= readID(file
);
50 midi_debug("Detected RMID file");
51 midi_debug("Looking for MThd header");
53 rb
->read(file
, &dummy
, 16);
54 if(readID(file
) != ID_MTHD
)
57 midi_debug("Invalid MIDI header within RIFF.");
64 midi_debug("Invalid file header chunk.");
69 if(readFourBytes(file
)!=6)
72 midi_debug("Header chunk size invalid.");
76 if(readTwoBytes(file
)==2)
79 midi_debug("MIDI file type 2 not supported");
83 mfload
->numTracks
= readTwoBytes(file
);
84 mfload
->div
= readTwoBytes(file
);
88 midi_debug("File has %d tracks.", mfload
->numTracks
);
90 while(! eof(file
) && track
< mfload
->numTracks
)
92 unsigned char id
= readID(file
);
97 if(mfload
->numTracks
!= track
)
99 midi_debug("Warning: file claims to have %d tracks. I only see %d here.", mfload
->numTracks
, track
);
100 mfload
->numTracks
= track
;
108 mfload
->tracks
[track
] = readTrack(file
);
112 midi_debug("SKIPPING TRACK");
113 int len
= readFourBytes(file
);
124 /* Global again. Not static. What if track 1 ends on a running status event
125 * and then track 2 starts loading */
128 /* Returns 0 if done, 1 if keep going */
129 static int readEvent(int file
, void * dest
)
132 struct Event
* ev
= (struct Event
*) dest
;
135 ev
= &dummy
; /* If we are just counting events instead of loading them */
137 ev
->delta
= readVarData(file
);
140 int t
=readChar(file
);
142 if((t
&0x80) == 0x80) /* if not a running status event */
147 ev
->d1
= readChar(file
);
148 ev
->len
= readVarData(file
);
150 /* Allocate and read in the data block */
153 /* Null-terminate for text events */
154 ev
->evData
= malloc(ev
->len
+1); /* Extra byte for the null termination */
156 rb
->read(file
, ev
->evData
, ev
->len
);
157 ev
->evData
[ev
->len
] = 0;
161 case 0x01: /* Generic text */
163 midi_debug("Text: %s", ev
->evData
);
167 case 0x02: /* A copyright string within the file */
169 midi_debug("Copyright: %s", ev
->evData
);
173 case 0x03: /* Sequence of track name */
175 midi_debug("Name: %s", ev
->evData
);
179 case 0x04: /* Instrument (synth) name */
181 midi_debug("Instrument: %s", ev
->evData
);
185 case 0x05: /* Lyrics. These appear on the tracks at the right times */
186 { /* Usually only a small 'piece' of the lyrics. */
187 /* Maybe the sequencer should print these at play time? */
188 midi_debug("Lyric: %s", ev
->evData
);
192 case 0x06: /* Text marker */
194 midi_debug("Marker: %s", ev
->evData
);
199 case 0x07: /* Cue point */
201 midi_debug("Cue point: %s", ev
->evData
);
205 case 0x08: /* Program name */
207 midi_debug("Patch: %s", ev
->evData
);
212 case 0x09: /* Device name. Very much irrelevant here, though. */
214 midi_debug("Port: %s", ev
->evData
);
222 * Don't allocate anything, just see how much it would take
223 * To make memory usage efficient
226 for(a
=0; a
<ev
->len
; a
++)
227 readChar(file
); //Skip skip
232 return 0; /* Termination meta-event */
234 } else /* If part of a running status event */
238 ev
->d1
= readChar(file
);
240 if ( ((t
& 0xF0) != 0xD0) && ((t
& 0xF0) != 0xC0) && ((t
& 0xF0) > 0x40) )
242 ev
->d2
= readChar(file
);
246 } else /* Running Status */
248 ev
->status
= rStatus
;
250 if ( ((rStatus
& 0xF0) != 0xD0) && ((rStatus
& 0xF0) != 0xC0) && ((rStatus
& 0xF0) > 0x40) )
252 ev
->d2
= readChar(file
);
260 struct Track tracks
[48] IBSS_ATTR
;
262 struct Track
* readTrack(int file
)
264 struct Track
* trk
= &tracks
[curr_track
++];
265 rb
->memset(trk
, 0, sizeof(struct Track
));
267 trk
->size
= readFourBytes(file
);
273 int pos
= rb
->lseek(file
, 0, SEEK_CUR
);
275 while(readEvent(file
, NULL
)) /* Memory saving technique */
276 numEvents
++; /* Attempt to read in events, count how many */
277 /* THEN allocate memory and read them in */
278 rb
->lseek(file
, pos
, SEEK_SET
);
280 int trackSize
= (numEvents
+1) * sizeof(struct Event
);
281 void * dataPtr
= malloc(trackSize
);
282 trk
->dataBlock
= dataPtr
;
286 while(readEvent(file
, dataPtr
))
288 if(trackSize
< dataPtr
-trk
->dataBlock
)
290 midi_debug("Track parser memory out of bounds");
293 dataPtr
+=sizeof(struct Event
);
296 trk
->numEvents
= numEvents
;
308 id
[a
]=readChar(file
);
311 midi_debug("End of file reached.");
314 if(rb
->strcmp(id
, "MThd")==0)
316 if(rb
->strcmp(id
, "MTrk")==0)
318 if(rb
->strcmp(id
, "RIFF")==0)
324 int readFourBytes(int file
)
329 data
=(data
<<8)+readChar(file
);
333 int readTwoBytes(int file
)
335 int data
=(readChar(file
)<<8)+readChar(file
);
339 /* This came from the MIDI file format guide */
340 int readVarData(int file
)
344 if ( (value
= readChar(file
)) & 0x80 )
349 value
= (value
<< 7) + ((c
= readChar(file
)) & 0x7F);
357 void unloadFile(struct MIDIfile * mf)
363 for(a=0; a<mf->numTracks; a++)
367 if(mf->tracks[a] != NULL)
368 for(b=0; b<mf->tracks[a]->numEvents; b++)
370 if(((struct Event*)((mf->tracks[a]->dataBlock)+b*sizeof(struct Event)))->evData!=NULL)
371 free(((struct Event*)((mf->tracks[a]->dataBlock)+b*sizeof(struct Event)))->evData);
374 if(mf->tracks[a]!=NULL && mf->tracks[a]->dataBlock != NULL)
375 free(mf->tracks[a]->dataBlock); //Unload the event block
377 if(mf->tracks[a]!=NULL)
378 free(mf->tracks[a]); //Unload the track structure itself
380 free(mf); //Unload the main struct