1 /*
2 * Schism Tracker - a cross-platform Impulse Tracker clone
3 * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com>
4 * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org>
5 * copyright (c) 2009 Storlek & Mrs. Brisby
6 * copyright (c) 2010-2012 Storlek
7 * URL: http://schismtracker.org/
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 #define NEED_BYTESWAP
25 #include "headers.h"
26 #include "slurp.h"
27 #include "fmt.h"
28 #include "log.h"
29
30 #include "sndfile.h"
31
32 /*
33 some thoughts...
34
35 really, we don't even need to adhere to the same channel numbering -- the notes
36 could go pretty much anywhere, as long as note-off events are handled properly.
37 but it'd be nice to have the channels at least sort of resemble the midi file,
38 whether it's arranged by track or by midi channel.
39
40 - try to allocate channels that aren't in use when possible, to avoid stomping on playing notes
41 - set instrument NNA to continue with dupe cut (or note off?)
42 */
43
44 /* --------------------------------------------------------------------------------------------------------- */
45 // structs, local defines, etc.
46
47 #define MID_ROWS_PER_PATTERN 200
48
49 // Pulse/row calculations are done in fixed point for better accuracy
50 #define FRACBITS 12
51 #define FRACMASK ((1 << FRACBITS) - 1)
52
53
54 #pragma pack(push, 1)
55 struct mthd {
56 //char tag[4]; // MThd <read separately>
57 uint32_t header_length;
58 uint16_t format; // 0 = single-track, 1 = multi-track, 2 = multi-song
59 uint16_t num_tracks; // number of track chunks
60 uint16_t division; // delta timing value: positive = units/beat; negative = smpte compatible units (?)
61 };
62 struct mtrk {
63 char tag[4]; // MTrk
64 uint32_t length; // number of bytes of track data following
65 };
66 #pragma pack(pop)
67
68
69 struct event {
70 unsigned int pulse; // the PPQN-tick, counting from zero, when this midi-event happens
71 uint8_t chan; // target channel (0-based!)
72 song_note_t note; // the note data (new data will overwrite old data in same channel+row)
73 struct event *next;
74 };
75
alloc_event(unsigned int pulse,uint8_t chan,const song_note_t * note,struct event * next)76 static struct event *alloc_event(unsigned int pulse, uint8_t chan, const song_note_t *note, struct event *next)
77 {
78 struct event *ev = malloc(sizeof(struct event));
79 if (!ev) {
80 perror("malloc");
81 return NULL;
82 }
83 ev->pulse = pulse;
84 ev->chan = chan;
85 ev->note = *note;
86 ev->next = next;
87 return ev;
88 }
89
90 /* --------------------------------------------------------------------------------------------------------- */
91 // support functions
92
read_varlen(slurp_t * fp)93 static unsigned int read_varlen(slurp_t *fp)
94 {
95 int b;
96 unsigned int v = 0;
97
98 // This will fail tremendously if a value overflows. I don't care.
99 do {
100 b = slurp_getc(fp);
101 if (b == EOF)
102 return 0; // truncated?!
103 v <<= 7;
104 v |= b & 0x7f;
105 } while (b & 0x80);
106 return v;
107 }
108
109 /* --------------------------------------------------------------------------------------------------------- */
110 // info (this is ultra lame)
111
fmt_mid_read_info(dmoz_file_t * file,const uint8_t * data,size_t length)112 int fmt_mid_read_info(dmoz_file_t *file, const uint8_t *data, size_t length)
113 {
114 slurp_t fp = {.length = length, .data = (uint8_t *) data, .pos = 0};
115 song_t *tmpsong = csf_allocate();
116
117 if (!tmpsong)
118 return 0; // wahhhh
119 if (fmt_mid_load_song(tmpsong, &fp, LOAD_NOSAMPLES | LOAD_NOPATTERNS) == LOAD_SUCCESS) {
120 file->description = "Standard MIDI File";
121 file->title = strdup(tmpsong->title);
122 file->type = TYPE_MODULE_MOD;
123 csf_free(tmpsong);
124 return 1;
125 }
126 csf_free(tmpsong);
127 return 0;
128 }
129
130 /* --------------------------------------------------------------------------------------------------------- */
131 // load
132
fmt_mid_load_song(song_t * song,slurp_t * fp,unsigned int lflags)133 int fmt_mid_load_song(song_t *song, slurp_t *fp, unsigned int lflags)
134 {
135 struct mthd mthd;
136 struct mtrk mtrk;
137 unsigned char buf[32];
138 song_note_t note;
139 struct event *event_queue, *cur, *prev, *new;
140 struct {
141 uint8_t fg_note;
142 uint8_t bg_note; // really just used as a boolean...
143 uint8_t instrument;
144 } midich[16] = {{NOTE_NONE, NOTE_NONE, 0}};
145 char *message_cur = song->message;
146 unsigned int message_left = MAX_MESSAGE;
147 unsigned int pulse = 0; // cumulative time from start of track
148 uint8_t patch_samples[128] = {0};
149 uint8_t nsmp = 1; // Next free sample
150
151 slurp_read(fp, buf, 4);
152 if (memcmp(buf, "RIFF", 4) == 0) {
153 // Stupid MS crap.
154 slurp_seek(fp, 16, SEEK_CUR);
155 slurp_read(fp, buf, 4);
156 }
157 if (memcmp(buf, "MThd", 4) != 0 || slurp_read(fp, &mthd, sizeof(mthd)) != sizeof(mthd)) {
158 return LOAD_UNSUPPORTED;
159 }
160 mthd.header_length = bswapBE32(mthd.header_length);
161 // don't care about format, either there's one track or more than one track. whoop de doo.
162 // (format 2 MIDs will probably be hilariously broken, but I don't have any and also don't care)
163 mthd.format = bswapBE16(mthd.format);
164 mthd.num_tracks = bswapBE16(mthd.num_tracks);
165 mthd.division = bswapBE16(mthd.division);
166 slurp_seek(fp, mthd.header_length - 6, SEEK_CUR); // account for potential weirdness
167
168 song->title[0] = '\0'; // should be already, but to be sure...
169
170 /* We'll count by "pulses" here, which are basically MIDI-speak for ticks, except that there are a heck
171 of a lot more of them. (480 pulses/quarter is fairly common, that's like A78, if the tempo could be
172 adjusted high enough to make practical use of that speed)
173 Also, we'll use a 32-bit value and hopefully not overflow -- which is unlikely anyway, as it'd either
174 require PPQN to be very ridiculously high, or a file that's several *hours* long.
175
176 Stuff a useless event at the start of the event queue. */
177 note = (song_note_t) {.note = NOTE_NONE};
178 event_queue = alloc_event(0, 0, ¬e, NULL);
179
180 for (int trknum = 0; trknum < mthd.num_tracks; trknum++) {
181 unsigned int delta; // time since last event (read from file)
182 unsigned int vlen; // some other generic varlen number
183 int rs = 0; // running status byte
184 int status; // THIS status byte (as opposed to rs)
185 unsigned char hi, lo, cn, x, y;
186 unsigned int bpm; // stupid
187 int found_end = 0;
188 long nextpos;
189
190 cur = event_queue->next;
191 prev = event_queue;
192 pulse = 0;
193
194 if (slurp_read(fp, &mtrk, sizeof(mtrk)) != sizeof(mtrk)) {
195 log_appendf(4, " Warning: Short read on track header (truncated?)");
196 break;
197 }
198 if (memcmp(mtrk.tag, "MTrk", 4) != 0) {
199 log_appendf(4, " Warning: Invalid track header (corrupt file?)");
200 break;
201 }
202 mtrk.length = bswapBE32(mtrk.length);
203 nextpos = slurp_tell(fp) + mtrk.length; // where this track is supposed to end
204
205 while (!found_end && slurp_tell(fp) < nextpos) {
206 delta = read_varlen(fp); // delta-time
207 pulse += delta; // 'real' pulse count
208
209 // get status byte, if there is one
210 if (fp->data[fp->pos] & 0x80) {
211 status = slurp_getc(fp);
212 } else if (rs & 0x80) {
213 status = rs;
214 } else {
215 // garbage?
216 continue;
217 }
218
219 note = (song_note_t) {.note = NOTE_NONE};
220 hi = status >> 4;
221 lo = status & 0xf;
222 cn = lo; //or: trknum * CHANNELS_PER_TRACK + lo % CHANNELS_PER_TRACK;
223
224 switch (hi) {
225 case 0x8: // note off - x, y
226 rs = status;
227 x = slurp_getc(fp); // note
228 y = slurp_getc(fp); // release velocity
229 x = CLAMP(x + NOTE_FIRST, NOTE_FIRST, NOTE_LAST); // clamp is wrong, but whatever
230 // if the last note in the channel is the same as this note, just write ===
231 // otherwise, if there is a note playing, assume our note got backgrounded
232 // and write S71 (past note off)
233 if (midich[cn].fg_note == x) {
234 note = (song_note_t) {.note = NOTE_OFF};
235 midich[cn].fg_note = NOTE_NONE;
236 } else {
237 // S71, past note off
238 note = (song_note_t) {.effect = FX_SPECIAL, .param = 0x71};
239 midich[cn].bg_note = NOTE_NONE;
240 }
241 break;
242 case 0x9: // note on - x, y (velocity zero = note off)
243 rs = status;
244 x = slurp_getc(fp); // note
245 y = slurp_getc(fp); // attack velocity
246 x = CLAMP(x + NOTE_FIRST, NOTE_FIRST, NOTE_LAST); // see note off above.
247
248 if (lo == 9) {
249 // ignore percussion for now
250 } else if (y == 0) {
251 // this is actually another note-off, see above
252 // (maybe that stuff should be split into a function or blahblah)
253 if (midich[cn].fg_note == x) {
254 note = (song_note_t) {.note = NOTE_OFF};
255 midich[cn].fg_note = NOTE_NONE;
256 } else {
257 // S71, past note off
258 note = (song_note_t) {.effect = FX_SPECIAL, .param = 0x71};
259 midich[cn].bg_note = NOTE_NONE;
260 }
261 } else {
262 if (nsmp == 1 && !(lflags & LOAD_NOSAMPLES)) {
263 // no samples defined yet - fake a program change
264 patch_samples[0] = 1;
265 adlib_patch_apply(song->samples + 1, 0);
266 nsmp++;
267 }
268
269 note = (song_note_t) {
270 .note = x,
271 .instrument = patch_samples[midich[cn].instrument],
272 .voleffect = VOLFX_VOLUME,
273 .volparam = (y & 0x7f) * 64 / 127,
274 };
275 midich[cn].fg_note = x;
276 midich[cn].bg_note = midich[cn].fg_note;
277 }
278 break;
279 case 0xa: // polyphonic key pressure (aftertouch) - x, y
280 rs = status;
281 x = slurp_getc(fp);
282 y = slurp_getc(fp);
283 // TODO polyphonic aftertouch channel=lo note=x pressure=y
284 continue;
285 case 0xb: // controller OR channel mode - x, y
286 rs = status;
287 // controller if first data byte 0-119
288 // channel mode if first data byte 120-127
289 x = slurp_getc(fp);
290 y = slurp_getc(fp);
291 // TODO controller change channel=lo controller=x value=y
292 continue;
293 case 0xc: // program change - x (instrument/voice selection)
294 rs = status;
295 x = slurp_getc(fp);
296 midich[cn].instrument = x;
297 // look familiar? this was copied from the .mus loader
298 if (!patch_samples[x] && !(lflags & LOAD_NOSAMPLES)) {
299 if (nsmp < MAX_SAMPLES) {
300 // New sample!
301 patch_samples[x] = nsmp;
302 adlib_patch_apply(song->samples + nsmp, x);
303 nsmp++;
304 } else {
305 log_appendf(4, " Warning: Too many samples");
306 }
307 }
308 note = (song_note_t) {.instrument = patch_samples[x]};
309 break;
310 case 0xd: // channel pressure (aftertouch) - x
311 rs = status;
312 x = slurp_getc(fp);
313 // TODO channel aftertouch channel=lo pressure=x
314 continue;
315 case 0xe: // pitch bend - x, y
316 rs = status;
317 x = slurp_getc(fp);
318 y = slurp_getc(fp);
319 // TODO pitch bend channel=lo lsb=x msb=y
320 continue;
321 case 0xf: // system messages
322 switch (lo) {
323 case 0xf: // meta-event (text and stuff)
324 x = slurp_getc(fp); // type
325 vlen = read_varlen(fp); // value length
326 switch (x) {
327 case 0x1: // text
328 case 0x2: // copyright
329 case 0x3: // track name
330 case 0x4: // instrument name
331 case 0x5: // lyric
332 case 0x6: // marker
333 case 0x7: // cue point
334 y = MIN(vlen, message_left ? message_left - 1 : 0);
335 slurp_read(fp, message_cur, y);
336 if (x == 3 && y && !song->title[0]) {
337 strncpy(song->title, message_cur, MIN(y, 25));
338 song->title[25] = '\0';
339 }
340 message_cur += y;
341 message_left -= y;
342 if (y && message_cur[-1] != '\n') {
343 *message_cur++ = '\n';
344 message_left--;
345 }
346 vlen -= y;
347 if (vlen)
348 slurp_seek(fp, vlen, SEEK_CUR);
349 continue;
350
351 case 0x20: // MIDI channel (FF 20 len* cc)
352 // specifies which midi-channel sysexes are assigned to
353 case 0x21: // MIDI port (FF 21 len* pp)
354 // specifies which port/bus this track's events are routed to
355 continue;
356
357 case 0x2f:
358 found_end = 1;
359 break;
360 case 0x51: // set tempo
361 // read another stupid kind of variable length number
362 // hopefully this fits into 4 bytes - if not, too bad!
363 // (what is this? friggin' magic?)
364 memset(buf, 0, 4);
365 y = MIN(vlen, 4);
366 slurp_read(fp, buf + (4 - y), y);
367 bpm = buf[0] << 24 | (buf[1] << 16) | (buf[2] << 8) | buf[3];
368 bpm = CLAMP(60000000 / (bpm ?: 1), 0x20, 0xff);
369 note = (song_note_t) {.effect = FX_TEMPO, .param = bpm};
370 vlen -= y;
371 break;
372 case 0x54: // SMPTE offset (what time in the song this track starts)
373 // (what?!)
374 continue;
375 case 0x58: // time signature (FF 58 len* nn dd cc bb)
376 case 0x59: // key signature (FF 59 len* sf mi)
377 // TODO care? don't care?
378 continue;
379 case 0x7f: // some proprietary crap
380 continue;
381
382 default:
383 // some mystery crap
384 log_appendf(2, " Unknown meta-event FF %02X", x);
385 continue;
386 }
387 slurp_seek(fp, vlen, SEEK_CUR);
388 break;
389 case 0x0: // sysex
390 case 0x1 ... 0x7: // syscommon
391 rs = 0; // clear running status
392 case 0x8 ... 0xe: // sysrt
393 // 0xf0 - sysex
394 // 0xf1-0xf7 - common
395 // 0xf8-0xff - sysrt
396 // sysex and common cancel running status
397 // TODO handle these, or at least skip them coherently
398 continue;
399 }
400 }
401
402 // skip past any events with a lower pulse count (from other channels)
403 while (cur && pulse > cur->pulse) {
404 prev = cur;
405 cur = cur->next;
406 }
407 // and now, cur is either NULL or has a higher timestamp, so insert before it
408 new = alloc_event(pulse, cn, ¬e, cur);
409 prev->next = new;
410 prev = prev->next;
411 }
412 if (slurp_tell(fp) != nextpos) {
413 log_appendf(2, " Track %d ended %ld bytes from boundary",
414 trknum, slurp_tell(fp) - nextpos);
415 slurp_seek(fp, nextpos, SEEK_SET);
416 }
417 }
418
419 song->initial_speed = 3;
420 song->initial_tempo = 120;
421
422 prev = NULL;
423 cur = event_queue;
424
425 if (lflags & LOAD_NOPATTERNS) {
426 while (cur) {
427 prev = cur;
428 cur = cur->next;
429 free(prev);
430 }
431 return LOAD_SUCCESS;
432 }
433
434 // okey doke! now let's write this crap out to the patterns
435 song_note_t *pattern = NULL, *rowdata;
436 int row = MID_ROWS_PER_PATTERN; // what row of the pattern rowdata is pointing to (fixed point)
437 int rowfrac = 0; // how much is left over
438 int pat = 0; // next pattern number to create
439 pulse = 0; // PREVIOUS event pulse.
440
441 while (cur) {
442 /* calculate pulse delta from previous event
443 * calculate row count from the pulse count using ppqn (assuming 1 row = 1/32nd note? 1/64?)
444 * advance the row as required
445 it'd be nice to aim for the "middle" of ticks instead of the start of them, that way if an
446 event is just barely off, it won't end up shifted way ahead.
447 */
448 unsigned int delta = cur->pulse - pulse;
449
450 if (delta) {
451 // Increment position
452 row <<= FRACBITS;
453 row += 8 * (delta << FRACBITS) / mthd.division; // times 8 -> 32nd notes
454 row += rowfrac;
455 rowfrac = row & FRACMASK;
456 row >>= FRACBITS;
457 }
458 pulse = cur->pulse;
459
460 while (row >= MID_ROWS_PER_PATTERN) {
461 // New pattern time!
462 if(pat >= MAX_PATTERNS) {
463 log_appendf(4, " Warning: Too many patterns, song is truncated");
464 return LOAD_SUCCESS;
465 }
466 pattern = song->patterns[pat] = csf_allocate_pattern(MID_ROWS_PER_PATTERN);
467 song->pattern_size[pat] = song->pattern_alloc_size[pat] = MID_ROWS_PER_PATTERN;
468 song->orderlist[pat] = pat;
469 pat++;
470 row -= MID_ROWS_PER_PATTERN;
471 }
472 rowdata = pattern + 64 * row;
473 if (cur->note.note) {
474 rowdata[cur->chan].note = cur->note.note;
475 rowdata[cur->chan].instrument = cur->note.instrument;
476 }
477 if (cur->note.voleffect) {
478 rowdata[cur->chan].voleffect = cur->note.voleffect;
479 rowdata[cur->chan].volparam = cur->note.volparam;
480 }
481 if (cur->note.effect) {
482 rowdata[cur->chan].effect = cur->note.effect;
483 rowdata[cur->chan].param = cur->note.param;
484 }
485
486 prev = cur;
487 cur = cur->next;
488 free(prev);
489 }
490
491 return LOAD_SUCCESS;
492 }
493
494