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 "log.h"
28 #include "fmt.h"
29
30 #include "sndfile.h"
31
32 /* --------------------------------------------------------------------- */
33
34 int fmt_imf_read_info(dmoz_file_t *file, const uint8_t *data, size_t length)
35 {
36 if (!(length > 64 && memcmp(data + 60, "IM10", 4) == 0))
37 return 0;
38
39 file->description = "Imago Orpheus";
40 /*file->extension = str_dup("imf");*/
41 file->title = strn_dup((const char *)data, 32);
42 file->type = TYPE_MODULE_IT;
43 return 1;
do_test_fetch_max_bytes(void)44 }
45
46 /* --------------------------------------------------------------------------------------------------------- */
47
48 #pragma pack(push, 1)
49 struct imf_channel {
50 char name[12]; /* Channelname (ASCIIZ-String, max 11 chars) */
51 uint8_t chorus; /* Default chorus */
52 uint8_t reverb; /* Default reverb */
53 uint8_t panning; /* Pan positions 00-FF */
54 uint8_t status; /* Channel status: 0 = enabled, 1 = mute, 2 = disabled (ignore effects!) */
55 };
56
57
58 struct imf_header {
59 char title[32]; /* Songname (ASCIIZ-String, max. 31 chars) */
60 uint16_t ordnum; /* Number of orders saved */
61 uint16_t patnum; /* Number of patterns saved */
62 uint16_t insnum; /* Number of instruments saved */
63 uint16_t flags; /* Module flags (&1 => linear) */
64 uint8_t unused1[8];
65 uint8_t tempo; /* Default tempo (Axx, 1..255) */
66 uint8_t bpm; /* Default beats per minute (BPM) (Txx, 32..255) */
67 uint8_t master; /* Default mastervolume (Vxx, 0..64) */
68 uint8_t amp; /* Amplification factor (mixing volume, 4..127) */
69 uint8_t unused2[8];
70 char im10[4]; /* 'IM10' */
71 struct imf_channel channels[32]; /* Channel settings */
72 uint8_t orderlist[256]; /* Order list (0xff = +++; blank out anything beyond ordnum) */
73 };
74
75 enum {
76 IMF_ENV_VOL = 0,
77 IMF_ENV_PAN = 1,
78 IMF_ENV_FILTER = 2,
79 };
80
81 struct imf_env {
82 uint8_t points; /* Number of envelope points */
83 uint8_t sustain; /* Envelope sustain point */
84 uint8_t loop_start; /* Envelope loop start point */
85 uint8_t loop_end; /* Envelope loop end point */
86 uint8_t flags; /* Envelope flags */
87 uint8_t unused[3];
88 };
89
90 struct imf_envnodes {
91 uint16_t tick;
92 uint16_t value;
93 };
94
95 struct imf_instrument {
96 char name[32]; /* Inst. name (ASCIIZ-String, max. 31 chars) */
97 uint8_t map[120]; /* Multisample settings */
98 uint8_t unused[8];
99 struct imf_envnodes nodes[3][16];
100 struct imf_env env[3];
101 uint16_t fadeout; /* Fadeout rate (0...0FFFH) */
102 uint16_t smpnum; /* Number of samples in instrument */
103 char ii10[4]; /* 'II10' */
104 };
105
106 struct imf_sample {
107 char name[13]; /* Sample filename (12345678.ABC) */
108 uint8_t unused1[3];
109 uint32_t length; /* Length */
110 uint32_t loop_start; /* Loop start */
111 uint32_t loop_end; /* Loop end */
112 uint32_t c5speed; /* Samplerate */
113 uint8_t volume; /* Default volume (0..64) */
114 uint8_t panning; /* Default pan (00h = Left / 80h = Middle) */
115 uint8_t unused2[14];
116 uint8_t flags; /* Sample flags */
117 uint8_t unused3[5];
118 uint16_t ems; /* Reserved for internal usage */
119 uint32_t dram; /* Reserved for internal usage */
120 char is10[4]; /* 'IS10' */
121 };
122 #pragma pack(pop)
123
main_0082_fetch_max_bytes(int argc,char ** argv)124
125 static uint8_t imf_efftrans[] = {
126 FX_NONE,
127 FX_SPEED, // 0x01 1xx Set Tempo
128 FX_TEMPO, // 0x02 2xx Set BPM
129 FX_TONEPORTAMENTO, // 0x03 3xx Tone Portamento (*)
130 FX_TONEPORTAVOL, // 0x04 4xy Tone Portamento + Volume Slide (*)
131 FX_VIBRATO, // 0x05 5xy Vibrato (*)
132 FX_VIBRATOVOL, // 0x06 6xy Vibrato + Volume Slide (*)
133 FX_FINEVIBRATO, // 0x07 7xy Fine Vibrato (*)
134 FX_TREMOLO, // 0x08 8xy Tremolo (*)
135 FX_ARPEGGIO, // 0x09 9xy Arpeggio (*)
136 FX_PANNING, // 0x0A Axx Set Pan Position
137 FX_PANNINGSLIDE, // 0x0B Bxy Pan Slide (*)
138 FX_VOLUME, // 0x0C Cxx Set Volume
139 FX_VOLUMESLIDE, // 0x0D Dxy Volume Slide (*)
140 FX_VOLUMESLIDE, // 0x0E Exy Fine Volume Slide (*)
141 FX_SPECIAL, // 0x0F Fxx Set Finetune
142 FX_NOTESLIDEUP, // 0x10 Gxy Note Slide Up (*)
143 FX_NOTESLIDEDOWN, // 0x11 Hxy Note Slide Down (*)
144 FX_PORTAMENTOUP, // 0x12 Ixx Slide Up (*)
145 FX_PORTAMENTODOWN, // 0x13 Jxx Slide Down (*)
146 FX_PORTAMENTOUP, // 0x14 Kxx Fine Slide Up (*)
147 FX_PORTAMENTODOWN, // 0x15 Lxx Fine Slide Down (*)
148 FX_MIDI, // 0x16 Mxx Set Filter Cutoff - XXX
149 FX_NONE, // 0x17 Nxy Filter Slide + Resonance - XXX
150 FX_OFFSET, // 0x18 Oxx Set Sample Offset (*)
151 FX_NONE, // 0x19 Pxx Set Fine Sample Offset - XXX
152 FX_KEYOFF, // 0x1A Qxx Key Off
153 FX_RETRIG, // 0x1B Rxy Retrig (*)
154 FX_TREMOR, // 0x1C Sxy Tremor (*)
155 FX_POSITIONJUMP, // 0x1D Txx Position Jump
156 FX_PATTERNBREAK, // 0x1E Uxx Pattern Break
157 FX_GLOBALVOLUME, // 0x1F Vxx Set Mastervolume
158 FX_GLOBALVOLSLIDE, // 0x20 Wxy Mastervolume Slide (*)
159 FX_SPECIAL, // 0x21 Xxx Extended Effect
160 // X1x Set Filter
161 // X3x Glissando
162 // X5x Vibrato Waveform
163 // X8x Tremolo Waveform
164 // XAx Pattern Loop
165 // XBx Pattern Delay
166 // XCx Note Cut
167 // XDx Note Delay
168 // XEx Ignore Envelope
169 // XFx Invert Loop
170 FX_NONE, // 0x22 Yxx Chorus - XXX
171 FX_NONE, // 0x23 Zxx Reverb - XXX
172 };
173
174 static void import_imf_effect(song_note_t *note)
175 {
176 uint8_t n;
177 // fix some of them
178 switch (note->effect) {
179 case 0xe: // fine volslide
180 // hackaround to get almost-right behavior for fine slides (i think!)
181 if (note->param == 0)
182 /* nothing */;
183 else if (note->param == 0xf0)
184 note->param = 0xef;
185 else if (note->param == 0x0f)
186 note->param = 0xfe;
187 else if (note->param & 0xf0)
188 note->param |= 0xf;
189 else
190 note->param |= 0xf0;
191 break;
192 case 0xf: // set finetune
193 // we don't implement this, but let's at least import the value
194 note->param = 0x20 | MIN(note->param >> 4, 0xf);
195 break;
196 case 0x14: // fine slide up
197 case 0x15: // fine slide down
198 // this is about as close as we can do...
199 if (note->param >> 4)
200 note->param = 0xf0 | MIN(note->param >> 4, 0xf);
201 else
202 note->param |= 0xe0;
203 break;
204 case 0x16: // filter
205 note->param = (255 - note->param) / 2; // TODO: cutoff range in IMF is 125...8000 Hz
206 break;
207 case 0x1f: // set global volume
208 note->param = MIN(note->param << 1, 0xff);
209 break;
210 case 0x21:
211 n = 0;
212 switch (note->param >> 4) {
213 case 0:
214 /* undefined, but since S0x does nothing in IT anyway, we won't care.
215 this is here to allow S00 to pick up the previous value (assuming IMF
216 even does that -- I haven't actually tried it) */
217 break;
218 default: // undefined
219 case 0x1: // set filter
220 case 0xf: // invert loop
221 note->effect = 0;
222 break;
223 case 0x3: // glissando
224 n = 0x20;
225 break;
226 case 0x5: // vibrato waveform
227 n = 0x30;
228 break;
229 case 0x8: // tremolo waveform
230 n = 0x40;
231 break;
232 case 0xa: // pattern loop
233 n = 0xb0;
234 break;
235 case 0xb: // pattern delay
236 n = 0xe0;
237 break;
238 case 0xc: // note cut
239 case 0xd: // note delay
240 // no change
241 break;
242 case 0xe: // ignore envelope
243 /* predicament: we can only disable one envelope at a time.
244 volume is probably most noticeable, so let's go with that.
245 (... actually, orpheus doesn't even seem to implement this at all) */
246 note->param = 0x77;
247 break;
248 case 0x18: // sample offset
249 // O00 doesn't pick up the previous value
250 if (!note->param)
251 note->effect = 0;
252 break;
253 }
254 if (n)
255 note->param = n | (note->param & 0xf);
256 break;
257 }
258 note->effect = (note->effect < 0x24) ? imf_efftrans[note->effect] : FX_NONE;
259 if (note->effect == FX_VOLUME && note->voleffect == VOLFX_NONE) {
260 note->voleffect = VOLFX_VOLUME;
261 note->volparam = note->param;
262 note->effect = FX_NONE;
263 note->param = 0;
264 }
265 }
266
267 /* return: number of lost effects */
268 static int load_imf_pattern(song_t *song, int pat, uint32_t ignore_channels, slurp_t *fp)
269 {
270 uint16_t length, nrows;
271 uint8_t mask, channel;
272 int row;
273 unsigned int lostfx = 0;
274 song_note_t *row_data, *note, junk_note;
275
276 //int startpos = slurp_tell(fp);
277
278 slurp_read(fp, &length, 2);
279 length = bswapLE16(length);
280 slurp_read(fp, &nrows, 2);
281 nrows = bswapLE16(nrows);
282
283 row_data = song->patterns[pat] = csf_allocate_pattern(nrows);
284 song->pattern_size[pat] = song->pattern_alloc_size[pat] = nrows;
285
286 row = 0;
287 while (row < nrows) {
288 mask = slurp_getc(fp);
289 if (mask == 0) {
290 row++;
291 row_data += MAX_CHANNELS;
292 continue;
293 }
294
295 channel = mask & 0x1f;
296
297 if (ignore_channels & (1 << channel)) {
298 /* should do this better, i.e. not go through the whole process of deciding
299 what to do with the effects since they're just being thrown out */
300 //printf("disabled channel %d contains data\n", channel + 1);
301 note = &junk_note;
302 } else {
303 note = row_data + channel;
304 }
305
306 if (mask & 0x20) {
307 /* read note/instrument */
308 note->note = slurp_getc(fp);
309 note->instrument = slurp_getc(fp);
310 if (note->note == 160) {
311 note->note = NOTE_OFF; /* ??? */
312 } else if (note->note == 255) {
313 note->note = NOTE_NONE; /* ??? */
314 } else {
315 note->note = (note->note >> 4) * 12 + (note->note & 0xf) + 12 + 1;
316 if (!NOTE_IS_NOTE(note->note)) {
317 //printf("%d.%d.%d: funny note 0x%02x\n",
318 // pat, row, channel, fp->data[fp->pos - 1]);
319 note->note = NOTE_NONE;
320 }
321 }
322 }
323 if ((mask & 0xc0) == 0xc0) {
324 uint8_t e1c, e1d, e2c, e2d;
325
326 /* read both effects and figure out what to do with them */
327 e1c = slurp_getc(fp);
328 e1d = slurp_getc(fp);
329 e2c = slurp_getc(fp);
330 e2d = slurp_getc(fp);
331 if (e1c == 0xc) {
332 note->volparam = MIN(e1d, 0x40);
333 note->voleffect = VOLFX_VOLUME;
334 note->effect = e2c;
335 note->param = e2d;
336 } else if (e2c == 0xc) {
337 note->volparam = MIN(e2d, 0x40);
338 note->voleffect = VOLFX_VOLUME;
339 note->effect = e1c;
340 note->param = e1d;
341 } else if (e1c == 0xa) {
342 note->volparam = e1d * 64 / 255;
343 note->voleffect = VOLFX_PANNING;
344 note->effect = e2c;
345 note->param = e2d;
346 } else if (e2c == 0xa) {
347 note->volparam = e2d * 64 / 255;
348 note->voleffect = VOLFX_PANNING;
349 note->effect = e1c;
350 note->param = e1d;
351 } else {
352 /* check if one of the effects is a 'global' effect
353 -- if so, put it in some unused channel instead.
354 otherwise pick the most important effect. */
355 lostfx++;
356 note->effect = e2c;
357 note->param = e2d;
358 }
359 } else if (mask & 0xc0) {
360 /* there's one effect, just stick it in the effect column */
361 note->effect = slurp_getc(fp);
362 note->param = slurp_getc(fp);
363 }
364 if (note->effect)
365 import_imf_effect(note);
366 }
367
368 return lostfx;
369 }
370
371
372 static unsigned int envflags[3][3] = {
373 {ENV_VOLUME, ENV_VOLSUSTAIN, ENV_VOLLOOP},
374 {ENV_PANNING, ENV_PANSUSTAIN, ENV_PANLOOP},
375 {ENV_PITCH | ENV_FILTER, ENV_PITCHSUSTAIN, ENV_PITCHLOOP},
376 };
377
378 static void load_imf_envelope(song_instrument_t *ins, song_envelope_t *env, struct imf_instrument *imfins, int e)
379 {
380 int n, t, v;
381 int min = 0; // minimum tick value for next node
382 int shift = (e == IMF_ENV_VOL ? 0 : 2);
383
384 env->nodes = CLAMP(imfins->env[e].points, 2, 25);
385 env->loop_start = imfins->env[e].loop_start;
386 env->loop_end = imfins->env[e].loop_end;
387 env->sustain_start = env->sustain_end = imfins->env[e].sustain;
388
389 for (n = 0; n < env->nodes; n++) {
390 t = bswapLE16(imfins->nodes[e][n].tick);
391 v = bswapLE16(imfins->nodes[e][n].value) >> shift;
392 env->ticks[n] = MAX(min, t);
393 env->values[n] = v = MIN(v, 64);
394 min = t + 1;
395 }
396 // this would be less retarded if the envelopes all had their own flags...
397 if (imfins->env[e].flags & 1)
398 ins->flags |= envflags[e][0];
399 if (imfins->env[e].flags & 2)
400 ins->flags |= envflags[e][1];
401 if (imfins->env[e].flags & 4)
402 ins->flags |= envflags[e][2];
403 }
404
405
406 int fmt_imf_load_song(song_t *song, slurp_t *fp, UNUSED unsigned int lflags)
407 {
408 struct imf_header hdr;
409 int n, s;
410 song_sample_t *sample = song->samples + 1;
411 int firstsample = 1; // first sample for the current instrument
412 uint32_t ignore_channels = 0; /* bit set for each channel that's completely disabled */
413 int lostfx = 0;
414
415 slurp_read(fp, &hdr, sizeof(hdr));
416 hdr.ordnum = bswapLE16(hdr.ordnum);
417 hdr.patnum = bswapLE16(hdr.patnum);
418 hdr.insnum = bswapLE16(hdr.insnum);
419 hdr.flags = bswapLE16(hdr.flags);
420
421 if (memcmp(hdr.im10, "IM10", 4) != 0)
422 return LOAD_UNSUPPORTED;
423
424 if (hdr.ordnum > MAX_ORDERS || hdr.patnum > MAX_PATTERNS || hdr.insnum > MAX_INSTRUMENTS)
425 return LOAD_FORMAT_ERROR;
426
427 memcpy(song->title, hdr.title, 25);
428 song->title[25] = 0;
429 strcpy(song->tracker_id, "Imago Orpheus");
430
431 if (hdr.flags & 1)
432 song->flags |= SONG_LINEARSLIDES;
433 song->flags |= SONG_INSTRUMENTMODE;
434 song->initial_speed = hdr.tempo;
435 song->initial_tempo = hdr.bpm;
436 song->initial_global_volume = 2 * hdr.master;
437 song->mixing_volume = hdr.amp;
438
439 for (n = 0; n < 32; n++) {
440 song->channels[n].panning = hdr.channels[n].panning * 64 / 255;
441 song->channels[n].panning *= 4; //mphack
442 /* TODO: reverb/chorus??? */
443 switch (hdr.channels[n].status) {
444 case 0: /* enabled; don't worry about it */
445 break;
446 case 1: /* mute */
447 song->channels[n].flags |= CHN_MUTE;
448 break;
449 case 2: /* disabled */
450 song->channels[n].flags |= CHN_MUTE;
451 ignore_channels |= (1 << n);
452 break;
453 default: /* uhhhh.... freak out */
454 //fprintf(stderr, "imf: channel %d has unknown status %d\n", n, hdr.channels[n].status);
455 return LOAD_FORMAT_ERROR;
456 }
457 }
458 for (; n < MAX_CHANNELS; n++)
459 song->channels[n].flags |= CHN_MUTE;
460 /* From mikmod: work around an Orpheus bug */
461 if (hdr.channels[0].status == 0) {
462 for (n = 1; n < 16; n++)
463 if (hdr.channels[n].status != 1)
464 break;
465 if (n == 16)
466 for (n = 1; n < 16; n++)
467 song->channels[n].flags &= ~CHN_MUTE;
468 }
469
470 for (n = 0; n < hdr.ordnum; n++)
471 song->orderlist[n] = ((hdr.orderlist[n] == 0xff) ? ORDER_SKIP : hdr.orderlist[n]);
472
473 for (n = 0; n < hdr.patnum; n++)
474 lostfx += load_imf_pattern(song, n, ignore_channels, fp);
475
476 if (lostfx)
477 log_appendf(4, " Warning: %d effect%s dropped", lostfx, lostfx == 1 ? "" : "s");
478
479 for (n = 0; n < hdr.insnum; n++) {
480 // read the ins header
481 struct imf_instrument imfins;
482 song_instrument_t *ins;
483 slurp_read(fp, &imfins, sizeof(imfins));
484
485 imfins.smpnum = bswapLE16(imfins.smpnum);
486 imfins.fadeout = bswapLE16(imfins.fadeout);
487
488 ins = song->instruments[n + 1] = csf_allocate_instrument();
489 strncpy(ins->name, imfins.name, 25);
490 ins->name[25] = 0;
491
492 if (imfins.smpnum) {
493 for (s = 12; s < 120; s++) {
494 ins->note_map[s] = s + 1;
495 ins->sample_map[s] = firstsample + imfins.map[s - 12];
496 }
497 }
498
499 /* Fadeout:
500 IT1 - 64
501 IT2 - 256
502 FT2 - 4095
503 IMF - 4095
504 MPT - god knows what, all the loaders are inconsistent
505 Schism - 256 presented; 8192? internal
506
507 IMF and XM have the same range and modplug's XM loader doesn't do any bit shifting with it,
508 so I'll do the same here for now. I suppose I should get this nonsense straightened
509 out at some point, though. */
510 ins->fadeout = imfins.fadeout;
511 ins->global_volume = 128;
512
513 load_imf_envelope(ins, &ins->vol_env, &imfins, IMF_ENV_VOL);
514 load_imf_envelope(ins, &ins->pan_env, &imfins, IMF_ENV_PAN);
515 load_imf_envelope(ins, &ins->pitch_env, &imfins, IMF_ENV_FILTER);
516
517 /* I'm not sure if XM's envelope hacks apply here or not, but Orpheus *does* at least stop
518 samples upon note-off when no envelope is active. Whether or not this depends on the fadeout
519 value, I don't know, and since the fadeout doesn't even seem to be implemented in the gui,
520 I might never find out. :P */
521 if (!(ins->flags & ENV_VOLUME)) {
522 ins->vol_env.ticks[0] = 0;
523 ins->vol_env.ticks[1] = 1;
524 ins->vol_env.values[0] = 64;
525 ins->vol_env.values[1] = 0;
526 ins->vol_env.nodes = 2;
527 ins->vol_env.sustain_start = ins->vol_env.sustain_end = 0;
528 ins->flags |= ENV_VOLUME | ENV_VOLSUSTAIN;
529 }
530
531 for (s = 0; s < imfins.smpnum; s++) {
532 struct imf_sample imfsmp;
533 uint32_t blen, sflags = SF_LE | SF_M | SF_PCMS;
534
535 slurp_read(fp, &imfsmp, sizeof(imfsmp));
536
537 if (memcmp(imfsmp.is10, "IS10", 4) != 0) {
538 //printf("is10 says %02x %02x %02x %02x!\n",
539 // imfsmp.is10[0], imfsmp.is10[1], imfsmp.is10[2], imfsmp.is10[3]);
540 return LOAD_FORMAT_ERROR;
541 }
542
543 strncpy(sample->filename, imfsmp.name, 12);
544 sample->filename[12] = 0;
545 strcpy(sample->name, sample->filename);
546 blen = sample->length = bswapLE32(imfsmp.length);
547 sample->loop_start = bswapLE32(imfsmp.loop_start);
548 sample->loop_end = bswapLE32(imfsmp.loop_end);
549 sample->c5speed = bswapLE32(imfsmp.c5speed);
550 sample->volume = imfsmp.volume * 4; //mphack
551 sample->panning = imfsmp.panning; //mphack (IT uses 0-64, IMF uses the full 0-255)
552 if (imfsmp.flags & 1)
553 sample->flags |= CHN_LOOP;
554 if (imfsmp.flags & 2)
555 sample->flags |= CHN_PINGPONGLOOP;
556 if (imfsmp.flags & 4) {
557 sflags |= SF_16;
558 sample->length >>= 1;
559 sample->loop_start >>= 1;
560 sample->loop_end >>= 1;
561 } else {
562 sflags |= SF_8;
563 }
564 if (imfsmp.flags & 8)
565 sample->flags |= CHN_PANNING;
566
567 if (blen && !(lflags & LOAD_NOSAMPLES))
568 csf_read_sample(sample, sflags, fp->data + fp->pos, fp->length - fp->pos);
569 slurp_seek(fp, blen, SEEK_CUR);
570
571 sample++;
572 }
573 firstsample += imfins.smpnum;
574 }
575
576 // Fix the MIDI settings, because IMF files might include Zxx effects
577 memset(&song->midi_config, 0, sizeof(song->midi_config));
578 strcpy(song->midi_config.sfx[0], "F0F000z");
579 song->flags |= SONG_EMBEDMIDICFG;
580
581 return LOAD_SUCCESS;
582 }
583
584