diff options
Diffstat (limited to 'apps/plugins/midi/midifile.c')
-rw-r--r-- | apps/plugins/midi/midifile.c | 427 |
1 files changed, 212 insertions, 215 deletions
diff --git a/apps/plugins/midi/midifile.c b/apps/plugins/midi/midifile.c index c786b8e5a6..412cc6104d 100644 --- a/apps/plugins/midi/midifile.c +++ b/apps/plugins/midi/midifile.c | |||
@@ -26,233 +26,232 @@ void bail(const char *); | |||
26 | 26 | ||
27 | struct MIDIfile * loadFile(char * filename) | 27 | struct MIDIfile * loadFile(char * filename) |
28 | { | 28 | { |
29 | struct MIDIfile * mf; | 29 | struct MIDIfile * mf; |
30 | int file = rb->open (filename, O_RDONLY); | 30 | int file = rb->open (filename, O_RDONLY); |
31 | 31 | ||
32 | if(file==0) | 32 | if(file==-1) |
33 | { | 33 | { |
34 | bail("Could not open file\n"); | 34 | bail("Could not open file\n"); |
35 | } | 35 | } |
36 | 36 | ||
37 | mf = (struct MIDIfile*)allocate(sizeof(struct MIDIfile)); | 37 | mf = (struct MIDIfile*)allocate(sizeof(struct MIDIfile)); |
38 | 38 | ||
39 | if(mf==NULL) | 39 | if(mf==NULL) |
40 | { | 40 | { |
41 | rb->close(file); | 41 | rb->close(file); |
42 | bail("Could not allocate memory for MIDIfile struct\n"); | 42 | bail("Could not allocate memory for MIDIfile struct\n"); |
43 | } | 43 | } |
44 | 44 | ||
45 | rb->memset(mf, 0, sizeof(struct MIDIfile)); | 45 | rb->memset(mf, 0, sizeof(struct MIDIfile)); |
46 | 46 | ||
47 | if(readID(file) != ID_MTHD) | 47 | if(readID(file) != ID_MTHD) |
48 | { | 48 | { |
49 | rb->close(file); | 49 | rb->close(file); |
50 | bail("Invalid file header chunk."); | 50 | bail("Invalid file header chunk."); |
51 | } | 51 | } |
52 | 52 | ||
53 | if(readFourBytes(file)!=6) | 53 | if(readFourBytes(file)!=6) |
54 | { | 54 | { |
55 | rb->close(file); | 55 | rb->close(file); |
56 | bail("Header chunk size invalid."); | 56 | bail("Header chunk size invalid."); |
57 | } | 57 | } |
58 | 58 | ||
59 | if(readTwoBytes(file)==2) | 59 | if(readTwoBytes(file)==2) |
60 | { | 60 | { |
61 | rb->close(file); | 61 | rb->close(file); |
62 | bail("MIDI file type not supported"); | 62 | bail("MIDI file type not supported"); |
63 | } | 63 | } |
64 | 64 | ||
65 | mf->numTracks = readTwoBytes(file); | 65 | mf->numTracks = readTwoBytes(file); |
66 | mf->div = readTwoBytes(file); | 66 | mf->div = readTwoBytes(file); |
67 | 67 | ||
68 | int track=0; | 68 | int track=0; |
69 | 69 | ||
70 | printf("\nnumTracks=%d div=%d\nBegin reading track data\n", mf->numTracks, mf->div); | 70 | printf("\nnumTracks=%d div=%d\nBegin reading track data\n", mf->numTracks, mf->div); |
71 | 71 | ||
72 | // return; | 72 | |
73 | 73 | while(! eof(file) && track < mf->numTracks) | |
74 | 74 | { | |
75 | while(! eof(file) && track < mf->numTracks) | 75 | unsigned char id = readID(file); |
76 | { | 76 | |
77 | unsigned char id = readID(file); | 77 | |
78 | 78 | if(id == ID_EOF) | |
79 | 79 | { | |
80 | if(id == ID_EOF) | 80 | if(mf->numTracks != track) |
81 | { | 81 | { |
82 | if(mf->numTracks != track) | 82 | printf("\nError: file claims to have %d tracks.\n I only see %d here.\n", mf->numTracks, track); |
83 | { | 83 | mf->numTracks = track; |
84 | printf("\nError: file claims to have %d tracks.\n I only see %d here.\n", mf->numTracks, track); | 84 | } |
85 | mf->numTracks = track; | 85 | return mf; |
86 | } | 86 | } |
87 | return mf; | 87 | |
88 | } | 88 | if(id == ID_MTRK) |
89 | 89 | { | |
90 | if(id == ID_MTRK) | 90 | mf->tracks[track] = readTrack(file); |
91 | { | 91 | //exit(0); |
92 | mf->tracks[track] = readTrack(file); | 92 | track++; |
93 | //exit(0); | 93 | } else |
94 | track++; | 94 | { |
95 | } else | 95 | printf("\n SKIPPING TRACK"); |
96 | { | 96 | int len = readFourBytes(file); |
97 | printf("\n SKIPPING TRACK"); | 97 | while(--len) |
98 | int len = readFourBytes(file); | 98 | readChar(file); |
99 | while(--len) | 99 | } |
100 | readChar(file); | 100 | } |
101 | } | 101 | return mf; |
102 | } | ||
103 | return mf; | ||
104 | 102 | ||
105 | } | 103 | } |
106 | 104 | ||
107 | 105 | ||
108 | int rStatus = 0; | 106 | int rStatus = 0; |
109 | 107 | ||
110 | //Returns 0 if done, 1 if keep going | 108 | /* Returns 0 if done, 1 if keep going */ |
111 | int readEvent(int file, void * dest) | 109 | int readEvent(int file, void * dest) |
112 | { | 110 | { |
113 | struct Event dummy; | 111 | struct Event dummy; |
114 | struct Event * ev = (struct Event *) dest; | 112 | struct Event * ev = (struct Event *) dest; |
115 | 113 | ||
116 | if(ev == NULL) | 114 | if(ev == NULL) |
117 | ev = &dummy; //If we are just counting events instead of loading them | 115 | ev = &dummy; /* If we are just counting events instead of loading them */ |
118 | 116 | ||
119 | ev->delta = readVarData(file); | 117 | ev->delta = readVarData(file); |
120 | 118 | ||
121 | 119 | ||
122 | int t=readChar(file); | 120 | int t=readChar(file); |
123 | 121 | ||
124 | if((t&0x80) == 0x80) //if not a running status event | 122 | if((t&0x80) == 0x80) /* if not a running status event */ |
125 | { | 123 | { |
126 | ev->status = t; | 124 | ev->status = t; |
127 | if(t == 0xFF) | 125 | if(t == 0xFF) |
128 | { | 126 | { |
129 | ev->d1 = readChar(file); | 127 | ev->d1 = readChar(file); |
130 | ev->len = readVarData(file); | 128 | ev->len = readVarData(file); |
131 | 129 | ||
132 | //Allocate and read in the data block | 130 | /* Allocate and read in the data block */ |
133 | if(dest != NULL) | 131 | if(dest != NULL) |
134 | { | 132 | { |
135 | ev->evData = readData(file, ev->len); | 133 | ev->evData = readData(file, ev->len); |
136 | printf("\nDATA: <%s>", ev->evData); | 134 | printf("\nDATA: <%s>", ev->evData); |
137 | } | 135 | } |
138 | else | 136 | else |
139 | { | 137 | { |
140 | //Don't allocate anything, just see how much it would tale | 138 | /* |
141 | //To make memory usage efficient | 139 | * Don't allocate anything, just see how much it would tale |
142 | 140 | * To make memory usage efficient | |
143 | int a=0; | 141 | */ |
144 | for(a=0; a<ev->len; a++) | 142 | unsigned int a=0; |
145 | readChar(file); //Skip skip | 143 | for(a=0; a<ev->len; a++) |
146 | } | 144 | readChar(file); //Skip skip |
147 | 145 | } | |
148 | if(ev->d1 == 0x2F) | 146 | |
149 | { | 147 | if(ev->d1 == 0x2F) |
150 | return 0; //Termination meta-event | 148 | { |
151 | } | 149 | return 0; /* Termination meta-event */ |
152 | } else //If part of a running status event | 150 | } |
153 | { | 151 | } else /* If part of a running status event */ |
154 | rStatus = t; | 152 | { |
155 | ev->status = t; | 153 | rStatus = t; |
156 | ev->d1 = readChar(file); | 154 | ev->status = t; |
157 | 155 | ev->d1 = readChar(file); | |
158 | if ( ((t & 0xF0) != 0xD0) && ((t & 0xF0) != 0xC0) && ((t & 0xF0) > 0x40) ) | 156 | |
159 | { | 157 | if ( ((t & 0xF0) != 0xD0) && ((t & 0xF0) != 0xC0) && ((t & 0xF0) > 0x40) ) |
160 | ev->d2 = readChar(file); | 158 | { |
161 | } else | 159 | ev->d2 = readChar(file); |
162 | ev->d2 = 127; | 160 | } else |
163 | } | 161 | ev->d2 = 127; |
164 | } else //Running Status | 162 | } |
165 | { | 163 | } else /* Running Status */ |
166 | ev->status = rStatus; | 164 | { |
167 | ev->d1 = t; | 165 | ev->status = rStatus; |
168 | if ( ((rStatus & 0xF0) != 0xD0) && ((rStatus & 0xF0) != 0xC0) && ((rStatus & 0xF0) > 0x40) ) | 166 | ev->d1 = t; |
169 | { | 167 | if ( ((rStatus & 0xF0) != 0xD0) && ((rStatus & 0xF0) != 0xC0) && ((rStatus & 0xF0) > 0x40) ) |
170 | ev->d2 = readChar(file); | 168 | { |
171 | } else | 169 | ev->d2 = readChar(file); |
172 | ev->d2 = 127; | 170 | } else |
173 | } | 171 | ev->d2 = 127; |
174 | return 1; | 172 | } |
173 | return 1; | ||
175 | } | 174 | } |
176 | 175 | ||
177 | 176 | ||
178 | 177 | ||
179 | struct Track * readTrack(int file) | 178 | struct Track * readTrack(int file) |
180 | { | 179 | { |
181 | struct Track * trk = (struct Track *)allocate(sizeof(struct Track)); | 180 | struct Track * trk = (struct Track *)allocate(sizeof(struct Track)); |
182 | rb->memset(trk, 0, sizeof(struct Track)); | 181 | rb->memset(trk, 0, sizeof(struct Track)); |
183 | 182 | ||
184 | trk->size = readFourBytes(file); | 183 | trk->size = readFourBytes(file); |
185 | trk->pos = 0; | 184 | trk->pos = 0; |
186 | trk->delta = 0; | 185 | trk->delta = 0; |
187 | 186 | ||
188 | int numEvents=0; | 187 | int numEvents=0; |
189 | 188 | ||
190 | int pos = rb->lseek(file, 0, SEEK_CUR); | 189 | int pos = rb->lseek(file, 0, SEEK_CUR); |
191 | 190 | ||
192 | while(readEvent(file, NULL)) //Memory saving technique | 191 | while(readEvent(file, NULL)) /* Memory saving technique */ |
193 | numEvents++; //Attempt to read in events, count how many | 192 | numEvents++; /* Attempt to read in events, count how many */ |
194 | //THEN allocate memory and read them in | 193 | /* THEN allocate memory and read them in */ |
195 | rb->lseek(file, pos, SEEK_SET); | 194 | rb->lseek(file, pos, SEEK_SET); |
196 | 195 | ||
197 | int trackSize = (numEvents+1) * sizeof(struct Event); | 196 | int trackSize = (numEvents+1) * sizeof(struct Event); |
198 | void * dataPtr = allocate(trackSize); | 197 | void * dataPtr = allocate(trackSize); |
199 | trk->dataBlock = dataPtr; | 198 | trk->dataBlock = dataPtr; |
200 | 199 | ||
201 | numEvents=0; | 200 | numEvents=0; |
202 | 201 | ||
203 | while(readEvent(file, dataPtr)) | 202 | while(readEvent(file, dataPtr)) |
204 | { | 203 | { |
205 | if(trackSize < dataPtr-trk->dataBlock) | 204 | if(trackSize < dataPtr-trk->dataBlock) |
206 | { | 205 | { |
207 | printf("\nTrack parser memory out of bounds"); | 206 | printf("\nTrack parser memory out of bounds"); |
208 | exit(1); | 207 | exit(1); |
209 | } | 208 | } |
210 | dataPtr+=sizeof(struct Event); | 209 | dataPtr+=sizeof(struct Event); |
211 | numEvents++; | 210 | numEvents++; |
212 | } | 211 | } |
213 | trk->numEvents = numEvents; | 212 | trk->numEvents = numEvents; |
214 | 213 | ||
215 | return trk; | 214 | return trk; |
216 | } | 215 | } |
217 | 216 | ||
218 | 217 | ||
219 | int readID(int file) | 218 | int readID(int file) |
220 | { | 219 | { |
221 | char id[5]; | 220 | char id[5]; |
222 | id[4]=0; | 221 | id[4]=0; |
223 | BYTE a; | 222 | BYTE a; |
224 | 223 | ||
225 | for(a=0; a<4; a++) | 224 | for(a=0; a<4; a++) |
226 | id[a]=readChar(file); | 225 | id[a]=readChar(file); |
227 | if(eof(file)) | 226 | if(eof(file)) |
228 | { | 227 | { |
229 | printf("\End of file reached."); | 228 | printf("\End of file reached."); |
230 | return ID_EOF; | 229 | return ID_EOF; |
231 | } | 230 | } |
232 | if(rb->strcmp(id, "MThd")==0) | 231 | if(rb->strcmp(id, "MThd")==0) |
233 | return ID_MTHD; | 232 | return ID_MTHD; |
234 | if(rb->strcmp(id, "MTrk")==0) | 233 | if(rb->strcmp(id, "MTrk")==0) |
235 | return ID_MTRK; | 234 | return ID_MTRK; |
236 | return ID_UNKNOWN; | 235 | return ID_UNKNOWN; |
237 | } | 236 | } |
238 | 237 | ||
239 | 238 | ||
240 | int readFourBytes(int file) | 239 | int readFourBytes(int file) |
241 | { | 240 | { |
242 | int data=0; | 241 | int data=0; |
243 | BYTE a=0; | 242 | BYTE a=0; |
244 | for(a=0; a<4; a++) | 243 | for(a=0; a<4; a++) |
245 | data=(data<<8)+readChar(file); | 244 | data=(data<<8)+readChar(file); |
246 | return data; | 245 | return data; |
247 | } | 246 | } |
248 | 247 | ||
249 | int readTwoBytes(int file) | 248 | int readTwoBytes(int file) |
250 | { | 249 | { |
251 | int data=(readChar(file)<<8)+readChar(file); | 250 | int data=(readChar(file)<<8)+readChar(file); |
252 | return data; | 251 | return data; |
253 | } | 252 | } |
254 | 253 | ||
255 | //This came from the MIDI file format guide | 254 | /* This came from the MIDI file format guide */ |
256 | int readVarData(int file) | 255 | int readVarData(int file) |
257 | { | 256 | { |
258 | unsigned int value; | 257 | unsigned int value; |
@@ -270,37 +269,35 @@ int readVarData(int file) | |||
270 | 269 | ||
271 | 270 | ||
272 | /* | 271 | /* |
273 | //This function should not be needed because we | ||
274 | //can just release the whole memory buffer at once | ||
275 | void unloadFile(struct MIDIfile * mf) | 272 | void unloadFile(struct MIDIfile * mf) |
276 | { | 273 | { |
277 | if(mf == NULL) | 274 | if(mf == NULL) |
278 | return; | 275 | return; |
279 | int a=0; | 276 | int a=0; |
280 | //Unload each track | 277 | //Unload each track |
281 | for(a=0; a<mf->numTracks; a++) | 278 | for(a=0; a<mf->numTracks; a++) |
282 | { | 279 | { |
283 | int b=0; | 280 | int b=0; |
284 | 281 | ||
285 | if(mf->tracks[a] != NULL) | 282 | if(mf->tracks[a] != NULL) |
286 | for(b=0; b<mf->tracks[a]->numEvents; b++) | 283 | for(b=0; b<mf->tracks[a]->numEvents; b++) |
287 | { | 284 | { |
288 | if(((struct Event*)((mf->tracks[a]->dataBlock)+b*sizeof(struct Event)))->evData!=NULL) | 285 | if(((struct Event*)((mf->tracks[a]->dataBlock)+b*sizeof(struct Event)))->evData!=NULL) |
289 | free(((struct Event*)((mf->tracks[a]->dataBlock)+b*sizeof(struct Event)))->evData); | 286 | free(((struct Event*)((mf->tracks[a]->dataBlock)+b*sizeof(struct Event)))->evData); |
290 | } | 287 | } |
291 | 288 | ||
292 | if(mf->tracks[a]!=NULL && mf->tracks[a]->dataBlock != NULL) | 289 | if(mf->tracks[a]!=NULL && mf->tracks[a]->dataBlock != NULL) |
293 | free(mf->tracks[a]->dataBlock); //Unload the event block | 290 | free(mf->tracks[a]->dataBlock); //Unload the event block |
294 | 291 | ||
295 | if(mf->tracks[a]!=NULL) | 292 | if(mf->tracks[a]!=NULL) |
296 | free(mf->tracks[a]); //Unload the track structure itself | 293 | free(mf->tracks[a]); //Unload the track structure itself |
297 | } | 294 | } |
298 | free(mf); //Unload the main struct | 295 | free(mf); //Unload the main struct |
299 | } | 296 | } |
300 | */ | 297 | */ |
301 | void bail(const char * err) | 298 | void bail(const char * err) |
302 | { | 299 | { |
303 | rb->splash(HZ*3, true, err); | 300 | rb->splash(HZ*3, true, err); |
304 | exit(0); | 301 | exit(0); |
305 | } | 302 | } |
306 | 303 | ||