4 ** Copyright (C) 1994 Bernardo Innocenti
6 ** Original MOD2MIDI PC code (C) 1993 Andrew Scott
7 ** Amiga Mod2Midi port (C) 1994 Raul Sobon
9 ** Save internal data to a MIDI type 1 file.
12 #include <exec/types.h>
14 #include <clib/dos_protos.h>
16 #include <pragmas/dos_pragmas.h>
22 #define ID_MThd 0x4D546864 /* "MThd", Midi Track HeaDer */
23 #define ID_MTrk 0x4D54726B /* "MTrk", Midi TRacK */
29 /* Returns a volume in the range 0..127 */
30 #define RESTRICTVOL(v) (((v) < 0) ? 0 : (((v) > 127) ? 127 : (v)))
32 /* Convert XModule note -> MIDI note */
33 #define NOTEVALUE(n) ((n)+36)
35 #define EVOL(ie,x) (((x) + (ie)->VolShift[0]) * (ie)->VolShift[1] / (ie)->VolShift[2])
37 #define ANOTE(x) (((x) < 0) ? (-x) : NOTEVALUE(x))
39 #define ENOTE(ie,x,y) (((ie)->MidiCh > 127) ? ((ie)->MidiCh - 128) : (ANOTE(x) + (ie)->Transpose[y]))
45 UWORD unknown1; /* Set to 1 */
47 UWORD unknown2; /* Set to 192 */
54 /* SongName follows */
66 /* Local functions prototypes */
68 static UWORD ChooseChannels (struct Instrument *instr, struct InstrExtra *ie, UBYTE DrumChann);
69 static ULONG WriteTrack0Info (BPTR fp, struct SongInfo *si);
70 static UWORD WriteMIDIHeader (BPTR fp, UWORD numofchannels);
71 static LONG WriteVLQ (BPTR fp, ULONG i);
72 static ULONG StopNote (BPTR fp, struct InstrExtra *ie, UWORD channel, UWORD note, UWORD vol, ULONG timer);
73 static ULONG NoteLength (UBYTE note, ULONG lenght, UWORD beats);
77 UWORD SaveMIDI (struct SongInfo *si, BPTR fp)
79 UWORD numofchannels, err,
81 struct Instrument *instr = &si->Inst[0], *inst1;
83 BOOL tempodone = FALSE;
85 struct InstrExtra iext[MAXINSTRUMENTS], *ie1;
87 DisplayAction (MSG_CHOOSING_CHANNELS);
89 /* Setup InstrExtra structures */
90 for (i = 0; i < MAXINSTRUMENTS; i++)
92 iext[i].VolShift[0] = 0;
93 iext[i].VolShift[1] = 1;
94 iext[i].VolShift[2] = 1;
95 iext[i].Transpose[0] = 0;
96 iext[i].Transpose[1] = 0;
97 iext[i].Transpose[2] = 0;
101 /* Get required number of channels */
102 if ((numofchannels = ChooseChannels (instr, iext, DRUMCHANNEL)) > 16)
104 ShowMessage (MSG_TOO_MANY_CHANNELS);
109 if (err = WriteMIDIHeader (fp, numofchannels))
112 DisplayAction (MSG_WRITING_MIDI_TRACKS);
114 for (i = 0, inst1 = instr, ie1 = iext ; i < MAXINSTRUMENTS; inst1++, ie1++, i++)
116 ULONG count, mktrlenpos, timer, delay[MAXTRACKS];
119 if (!i || inst1->Length)
121 if (DisplayProgress (i, MAXINSTRUMENTS))
124 /* Write MIDI Track */
126 if (!FWrite (fp, &l, 4, 1)) return ERR_READWRITE;
128 /* Write chunk length (set to 0 now...) */
130 mktrlenpos = Seek (fp, 0, OFFSET_CURRENT); /* Write it later */
132 if (!FWrite (fp, &l, 4, 1)) return ERR_READWRITE;
136 if (!(count = WriteTrack0Info (fp, si)))
137 return ERR_READWRITE;
141 static UBYTE unknown[4] = {0, 255, 3, 0};
149 /* Write some unknown header */
150 unknown[3] = strlen (inst1->Name);
151 if (!FWrite (fp, unknown, 4, 1)) return ERR_READWRITE;
153 /* Write instrument name */
154 if (!FWrite (fp, inst1->Name, unknown[3], 1)) return ERR_READWRITE;
156 instrinfo.unknown_zero = 0;
157 instrinfo.channel = c = 0xC0 + ie1->MidiCh;
158 instrinfo.unknown_zero = (ie1->MidiPr > 127) ? 126 : ie1->MidiPr;
159 if (!FWrite (fp, &instrinfo, sizeof (instrinfo), 1))
160 return ERR_READWRITE;
162 count = sizeof (unknown) + sizeof (instrinfo) + unknown[3];
167 if (!i || inst1->Length)
169 UWORD bpm, ticks, l, h;
170 UBYTE sampnum, effnum, effval, lastsam[MAXTRACKS] = {0}, vol[MAXTRACKS];
173 UWORD note, lastslide, slideto;
174 UWORD n[MAXTRACKS][48][2]; /* Note data for a song position */
175 UWORD lastn[MAXTRACKS]; /* Last note on a particular channel */
177 memset (lastn, 0, MAXTRACKS * sizeof (UWORD));
178 memset (vol, 0, MAXTRACKS);
179 memset (delay, 0, MAXTRACKS * sizeof (ULONG));
181 bpm = si->GlobalTempo;
182 ticks = si->GlobalSpeed;
183 lastslide = slideto = 0;
187 for (k = MAXTRACKS; k--; )
190 for (l = 0; l < si->Length; l++)
192 struct Pattern *patt = &si->PattData[si->Sequence[l]];
196 patbreak = 1 - patbreak;
198 for (j = 0; j < patt->Lines; j++)
203 for (k = 0; k < patt->Tracks; k++)
205 n[k][0][1] = inst1->Volume;
207 sampnum = patt->Notes[k]->Inst;
208 note = patt->Notes[k]->Note;
209 effnum = patt->Notes[k]->EffNum;
210 effval = patt->Notes[k]->EffVal;
214 if ((note || sampnum) && delay[k])
216 count += StopNote (fp, ie1, c, lastn[k], vol[k], timer);
221 if (!note && sampnum == i) /* check "defaults" */
236 lastsam[k] = sampnum;
244 case 0x0: /* Arpeggio */
248 if (!i || !effval || ie1->MidiCh > 127)
256 nv = NOTEVALUE(lastn[k]);
257 n[k][47][0] = lastn[k];
258 n[k][47][1] = vol[k];
260 n[k][16][0] = -(nv + ((effval & 0xF0) >> 4));
261 n[k][16][1] = vol[k];
263 n[k][32][0] = -(nv + (effval & 0x0F));
264 n[k][32][1] = vol[k];
269 nv = NOTEVALUE(note);
271 n[k][47][1] = inst1->Volume;
273 n[k][16][0] = -(nv + ((effval & 0xF0) >> 4));
274 n[k][16][1] = inst1->Volume;
276 n[k][32][0] = -(nv + (effval & 0x0F));
277 n[k][32][1] = inst1->Volume;
282 case 0x1: /* Slide Up */
283 case 0x2: /* Slide Down */
284 if (!(effval & 0xFF) || ie1->MidiCh > 127)
295 n[k][0][0] = lastn[k] + lastslide;
299 n[k][0][0] += lastslide;
301 n[k][0][0] = 13; /* C-1 */
302 else if (n[k][0][0] > 48)
303 n[k][0][0] = 48; /* B#3 */
306 case 0x3: /* Slide To */
307 if (!note && !slideto || note == lastn[k] || ie1->MidiCh > 127)
312 lastslide = abs (lastslide);
315 if (slideto > lastn[k])
317 n[k][0][0] = lastn[k] + lastslide * (ticks-1);
319 n[k][0][0] = 13; /* C-1 */
320 if (n[k][0][0] > slideto)
321 n[k][0][0] = slideto;
325 n[k][0][0] = lastn[k] - lastslide*(ticks-1);
327 n[k][0][0] = 48; /* B#3 */
328 if (n[k][0][0] < slideto)
329 n[k][0][0] = slideto;
334 case 0x4: /* Vibrato */
335 case 0x7: /* Tremolo */
336 /* ignore these effects.. not convertable */
339 case 0x5: /* Slide To + Volume Slide */
340 if ((note || slideto) && note!=lastn[k] && ie1->MidiCh < 128)
344 if (slideto > lastn[k])
346 n[k][0][0] = lastn[k] + lastslide*(ticks-1);
348 n[k][0][0] = 13; /* C-1 */
349 if (n[k][0][0] > slideto)
350 n[k][0][0] = slideto;
354 n[k][0][0] = lastn[k] - lastslide*(ticks-1);
356 n[k][0][0] = 48; /* B#3 */
357 if (n[k][0][0] < slideto)
358 n[k][0][0] = slideto;
365 /* We do not break here: the next case block (0xA)
366 * will slide volume for us
369 case 0x6: /* Vibrato & Volume Slide */
370 /* Ignore Vibrato; do Volume Slide only */
372 case 0xA: /* Volume Slide */
380 v += (ticks-1)*(effval & 0xF0); /* Can't really slide */
381 v -= (ticks-1)*(effval & 0x0F);
390 case 0x9: /* Set offset: pretend it's retrigger */
391 if ((!n[k][0][0] || !sampnum) && delay[k])
393 n[k][0][0] = lastn[k];
398 case 0xB: /* Position Jump */
399 patbreak = 1; /* Ignore, but break anyway */
402 case 0xD: /* Pattern Break */
403 patbreak = 1 + 10 * (effval & 0xF0) + (effval & 0x0F);
406 case 0xC: /* Set Volume */
410 if (vol == 0x40) vol=0x3F;
412 n[k][0][1] = vol << 1;
416 case 0xF: /* Set Speed/Tempo */
427 // if (TempoType) /* Tempos act strangely so .. */
439 if (i) /* Only write tempo on track 0 */
442 count += 6 + WriteVLQ (fp, timer);
444 FPutC (fp, 255); /* Meta-Event */
445 FPutC (fp, 81); /* Set Tempo */
448 FPutC (fp, (x >> 8) & 0xFF);
449 FPutC (fp, x & 0xFF);
455 case 0xE: /* Extended Effects */
456 switch (effval & 0xF0)
458 case 0x10: /* Fine Slide Up */
459 if (!(effval & 0x0F) || ie1->MidiCh > 127)
467 n[k][h][0] = lastn[k] + (effval & 0x0F);
472 n[k][h][0] += effval & 0x0F;
475 case 0x020: /* Fine Slide Down */
476 if (!(effval & 0x0F) || ie1->MidiCh > 127)
482 n[k][h][0] = lastn[k] - (effval & 0x0F);
486 n[k][h][0] -= effval & 0x0F;
488 case 0x00: /* set filter on/off */
489 case 0x30: /* glissando on/off */
490 case 0x40: /* set vibrato wave */
491 case 0x50: /* set finetune */
492 case 0x60: /* pattern loop */
493 case 0x70: /* set tremolo wave */
494 case 0x80: /* un-used */
495 case 0xF0: /* invert loop */
496 /* Can't do these in MIDI.. ignore */
499 case 0x0A0: /* Fine volume slide up */
500 case 0x0B0: /* Fine volume slide down */
517 case 0x90: /* Retrigger sample */
521 if (!note && !delay[k] || !(effval & 0x0F))
528 n[k][0][0] = lastn[k];
537 n[k][c][1] = n[k][0][1];
545 case 0xC0: /* Cut sample */
549 if (!note && !delay[k])
551 a = 48 * (effval & 0x0F) / ticks;
557 n[k][a][0] = lastn[k];
562 case 0xD0: /* Delay Sample */
566 if (!note || !(effval & 0x0F))
568 a = 48 * (effval & 0x0F) / ticks;
573 n[k][a][1] = n[k][a][0];
577 case 0xE0: /* Pattern Pause */
578 pause = 48 * (effval & 0x0F);
581 } /* End Switch (E effects) */
584 /* else dunno what it does.. disbelieve it ;) */
586 } /* End switch (effnum) */
588 } /* End for (Tracks) */
589 } /* End if (!pattnreak) */
591 for (h = 0; h<48; h++)
593 for (k = 0; k < patt->Tracks; k++)
597 if (delay[k]) /* Turn off old note on same channel */
599 count += StopNote (fp, ie1, c, lastn[k], vol[k], timer);
603 lastn[k] = n[k][h][0];
606 count += 3 + WriteVLQ(fp, timer);
608 FPutC (fp, 0x90 + c); /* Note On */
609 FPutC (fp, ENOTE(ie1, lastn[k], 0));
610 FPutC (fp, RESTRICTVOL(EVOL(ie1,vol[k])));
611 if (ie1->Transpose[1])
615 FPutC (fp, 0x90 + c);
616 FPutC (fp, ENOTE(ie1, lastn[k], 1));
617 FPutC (fp, RESTRICTVOL(EVOL(ie1, vol[k])));
618 if (ie1->Transpose[2])
622 FPutC (fp, 0x90 + c);
623 FPutC (fp, ENOTE(ie1, lastn[k], 2));
624 FPutC (fp, RESTRICTVOL(EVOL(ie1, vol[k])));
627 delay[k] = NoteLength (ANOTE(lastn[k]), inst1->Length, bpm);
629 else if (delay[k]==1)
632 count += StopNote (fp, ie1, c, lastn[k], vol[k], timer);
645 patbreak = 1 - patbreak;
648 } /* End for (Lines) */
649 } /* End for (si->Length) */
651 for (k = 0; k < si->MaxTracks; k++)
654 count += StopNote (fp, ie1, c, lastn[k], vol[k], timer);
662 FPutC (fp, 0); /* Give the default 128 bpm if none done yet */
671 if(inst1->Length || !i) // RAUL addition
673 count += 3 + WriteVLQ (fp, timer);
678 /* Write total chunk length */
680 if (Seek (fp, mktrlenpos, OFFSET_BEGINNING) == -1)
681 return ERR_READWRITE;
683 if (!(FWrite (fp, &count, 4, 1)))
684 return ERR_READWRITE;
686 if (Seek (fp, 0, OFFSET_END) == -1)
687 return ERR_READWRITE;
690 } /* End for (instruments) */
697 static UWORD ChooseChannels (struct Instrument *instr, struct InstrExtra *ie, UBYTE DrumChann)
699 /* Returns: The number of different channels needed to play instruments.
700 * If that number is not greater than 16, upto 16 channels will
701 * be allocated to the samples.
704 UBYTE c, Presets[128], m, n, numchan;
706 struct Instrument *instr1, *instr2;
707 struct InstrExtra *ie1, *ie2;
709 /* Preset all presets !!! */
710 for (n = 0; n < MAXINSTRUMENTS; n++)
713 memset (Presets, 0, 128);
715 for (n = MAXINSTRUMENTS, instr1 = &instr[1], ie1 = &ie[1]; n--; instr1++, ie1++)
720 if (ie1->MidiPr > 127)
723 ie1->MidiCh = DrumChann;
726 Presets[ie1->MidiPr] = 1;
732 for (numchan = DrumUsed, n = 128; n--; numchan += Presets[n]);
737 /* Go through and set channels appropriately */
751 /* Search for other instruments with the same preset and set
752 * all them to the same MIDI channel.
757 if (ie2->MidiPr == ie1->MidiPr || !instr2->Length)
762 if (++c == DrumChann && DrumUsed)
773 static UWORD WriteMIDIHeader (BPTR fp, UWORD numofchannels)
777 /* Write MIDI header */
779 if (!FWrite (fp, &l, 4, 1)) return ERR_READWRITE;
781 /* Write chunk length */
782 l = sizeof (struct MThd);
783 if (!FWrite (fp, &l, 4, 1)) return ERR_READWRITE;
785 /* Write header chunk */
790 mthd.Tracks = numofchannels;
793 if (!FWrite (fp, &mthd, sizeof (mthd), 1)) return ERR_READWRITE;
801 static ULONG WriteTrack0Info (BPTR fp, struct SongInfo *si)
803 /* Write info for track 0.
804 * Return actual number of bytes written, or 0 for failure.
807 static UBYTE TRK0I[63] =
809 0, 255, 2, 42, 70, 105, 108, 101, 32, 67, 111, 112, 121, 114, 105, 103,
810 104, 116, 32, 40, 99, 41, 32, 49 ,57, 57, 51, 32, 65, 100, 114, 101, 110,
811 97, 108, 105, 110, 32, 83, 111, 102, 116, 119, 97, 114, 101,
812 0, 255, 88, 4, 3, 2, 24, 8,
815 }; /* standard header + copyright message */
817 struct TRKInfo trkinfo;
819 memcpy (trkinfo.unknown1, TRK0I, 63);
820 trkinfo.NameLen = strlen (si->SongName);
822 if (!FWrite (fp, &trkinfo, sizeof (trkinfo), 1))
825 if (!FWrite (fp, si->SongName, trkinfo.NameLen, 1))
828 return (sizeof (trkinfo) + trkinfo.NameLen);
833 static LONG WriteVLQ (BPTR fp, ULONG i)
835 /* Writes a stream of bytes, each with the msb (bit 7) set to 1 to mean
836 * continuation and 0 to end the byte sequnce. Note that the data is
837 * put in reverse order.
839 * Returns: # of bytes written after a variable-length-quantity equivalent
840 * of i has been written to the file f, or 0 for failure.
847 while ((i >>= 7) > 0)
848 buffer = ((buffer << 8) | 0x80) + (i & 0x7F);
851 FPutC (fp, buffer & 0xFF);
864 static ULONG StopNote (BPTR fp, struct InstrExtra *ie, UWORD channel, UWORD note, UWORD vol, ULONG timer)
868 UWORD count = 3 + WriteVLQ (fp, timer);
870 FPutC (fp, 0x80 + channel); /* note off */
871 FPutC (fp, ENOTE(ie, note, 0));
872 FPutC (fp, RESTRICTVOL(EVOL(ie, vol)));
873 if (ie->Transpose[1])
877 FPutC (fp, 0x80 + channel);
878 FPutC (fp, ENOTE(ie, note, 1));
879 FPutC (fp, RESTRICTVOL(EVOL(ie, vol)));
880 if (ie->Transpose[2])
884 FPutC (fp, 0x80 + channel);
885 FPutC (fp, ENOTE(ie, note, 2));
886 FPutC (fp, RESTRICTVOL(EVOL(ie, vol)));
895 static ULONG NoteLength (UBYTE note, ULONG lenght, UWORD beats)
900 /* Note conversion table for Sound/Noise/ProTracker */
901 static const UWORD TrackerNotes[] =
903 0x000, /* Null note */
905 0x6B0, 0x650, 0x5F5, 0x5A0, 0x54D, 0x501, /* Octave 0 */
906 0x4B9, 0x475, 0x435, 0x3F9, 0x3C1, 0x38B,
908 0x358, 0x328, 0x2FA, 0x2D0, 0x2A6, 0x280, /* Octave 1 */
909 0x25C, 0x23A, 0x21A, 0x1FC, 0x1E0, 0x1C5,
911 0x1AC, 0x194, 0x17D, 0x168, 0x153, 0x140, /* Octave 2 */
912 0x12E, 0x11d, 0x10D, 0x0FE, 0x0F0, 0x0E2,
914 0x0D6, 0x0CA, 0x0BE, 0x0B4, 0x0AA, 0x0A0, /* Octave 3 */
915 0x097, 0x08F, 0x087, 0x07F, 0x078, 0x071,
917 0x06B, 0x065, 0x05F, 0x05A, 0x055, 0x050, /* Octave 4 */
918 0x04C, 0x047, 0x043, 0x040, 0x03C, 0x039,
920 0x035, 0x032, 0x030, 0x02D, 0x02A, 0x028, /* Octave 5 */
921 0x026, 0x024, 0x022, 0x020, 0x01E, 0x01C
924 /* static float t[84] =
926 3.200e-3, 3.020e-3, 2.851e-3, 2.691e-3, 2.540e-3, 2.397e-3,
927 2.263e-3, 2.136e-3, 2.016e-3, 1.903e-3, 1.796e-3, 1.695e-3,
928 1.600e-3, 1.510e-3, 1.425e-3, 1.345e-3, 1.270e-3, 1.197e-3,
929 1.131e-3, 1.068e-3, 1.008e-3, 9.514e-4, 8.980e-4, 8.476e-4,
930 8.000e-4, 7.551e-4, 7.127e-4, 6.727e-4, 6.350e-4, 5.993e-4,
931 5.657e-4, 5.339e-4, 5.040e-4, 4.757e-4, 4.490e-4, 4.238e-4,
932 4.000e-4, 3.775e-4, 3.564e-4, 3.364e-4, 3.175e-4, 2.997e-4,
933 2.828e-4, 2.670e-4, 2.520e-4, 2.378e-4, 2.245e-4, 2.119e-4,
934 2.000e-4, 1.888e-4, 1.782e-4, 1.682e-4, 1.587e-4, 1.498e-4,
935 1.414e-4, 1.335e-4, 1.260e-4, 1.189e-4, 1.122e-4, 1.059e-4,
936 1.000e-4, 9.439e-5, 8.909e-5, 8.409e-5, 7.937e-5, 7.492e-5,
937 7.071e-5, 6.674e-5, 6.300e-5, 5.946e-5, 5.612e-5, 5.297e-5,
938 5.000e-5, 4.719e-5, 4.454e-5, 4.204e-5, 3.969e-5, 3.746e-5,
939 3.536e-5, 3.337e-5, 3.150e-5, 2.973e-5, 2.806e-5, 2.649e-5
940 }; */ /* multipliers for each pitch: 12th roots of 2 apart */
943 if (idx < 0) idx = 0;
944 if (idx > 84) idx = 84;
946 return (TrackerNotes[idx] * beats * lenght); /* better not slide out of this range :( */