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, &note, 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, &note, 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