2 * This source code is public domain.
4 * Authors: Olivier Lapicque <olivierl@jps.net>
7 //////////////////////////////////////////////
8 // DigiTracker (MDL) module loader //
9 //////////////////////////////////////////////
18 //#pragma warning(disable:4244)
20 typedef struct MDLSONGHEADER
22 DWORD id; // "DMDL" = 0x4C444D44
27 typedef struct MDLINFOBLOCK
41 typedef struct MDLPATTERNDATA
44 BYTE lastrow; // nrows = lastrow+1
50 void ConvertMDLCommand(MODCOMMAND *m, UINT eff, UINT data)
51 //--------------------------------------------------------
53 UINT command = 0, param = data;
56 case 0x01: command = CMD_PORTAMENTOUP; break;
57 case 0x02: command = CMD_PORTAMENTODOWN; break;
58 case 0x03: command = CMD_TONEPORTAMENTO; break;
59 case 0x04: command = CMD_VIBRATO; break;
60 case 0x05: command = CMD_ARPEGGIO; break;
61 case 0x07: command = (param < 0x20) ? CMD_SPEED : CMD_TEMPO; break;
62 case 0x08: command = CMD_PANNING8; param <<= 1; break;
63 case 0x0B: command = CMD_POSITIONJUMP; break;
64 case 0x0C: command = CMD_GLOBALVOLUME; break;
65 case 0x0D: command = CMD_PATTERNBREAK; param = (data & 0x0F) + (data>>4)*10; break;
67 command = CMD_S3MCMDEX;
70 case 0x00: command = 0; break; // What is E0x in MDL (there is a bunch) ?
71 case 0x10: if (param & 0x0F) { param |= 0xF0; command = CMD_PANNINGSLIDE; } else command = 0; break;
72 case 0x20: if (param & 0x0F) { param = (param << 4) | 0x0F; command = CMD_PANNINGSLIDE; } else command = 0; break;
73 case 0x30: param = (data & 0x0F) | 0x10; break; // glissando
74 case 0x40: param = (data & 0x0F) | 0x30; break; // vibrato waveform
75 case 0x60: param = (data & 0x0F) | 0xB0; break;
76 case 0x70: param = (data & 0x0F) | 0x40; break; // tremolo waveform
77 case 0x90: command = CMD_RETRIG; param &= 0x0F; break;
78 case 0xA0: param = (data & 0x0F) << 4; command = CMD_GLOBALVOLSLIDE; break;
79 case 0xB0: param = data & 0x0F; command = CMD_GLOBALVOLSLIDE; break;
80 case 0xF0: param = ((data >> 8) & 0x0F) | 0xA0; break;
83 case 0x0F: command = CMD_SPEED; break;
84 case 0x10: if ((param & 0xF0) != 0xE0) { command = CMD_VOLUMESLIDE; if ((param & 0xF0) == 0xF0) param = ((param << 4) | 0x0F); else param >>= 2; } break;
85 case 0x20: if ((param & 0xF0) != 0xE0) { command = CMD_VOLUMESLIDE; if ((param & 0xF0) != 0xF0) param >>= 2; } break;
86 case 0x30: command = CMD_RETRIG; break;
87 case 0x40: command = CMD_TREMOLO; break;
88 case 0x50: command = CMD_TREMOR; break;
89 case 0xEF: if (param > 0xFF) param = 0xFF; command = CMD_OFFSET; break;
99 void UnpackMDLTrack(MODCOMMAND *pat, UINT nChannels, UINT nRows, UINT nTrack, const BYTE *lpTracks)
100 //-------------------------------------------------------------------------------------------------
102 MODCOMMAND cmd, *m = pat;
103 UINT len = *((WORD *)lpTracks);
104 UINT pos = 0, row = 0, i;
106 for (UINT ntrk=1; ntrk<nTrack; ntrk++)
109 len = *((WORD *)lpTracks);
112 cmd.note = cmd.instr = 0;
113 cmd.volcmd = cmd.vol = 0;
114 cmd.command = cmd.param = 0;
115 while ((row < nRows) && (pos < len))
118 BYTE b = lpTracks[pos++];
123 for (i=0; i<=xx; i++)
125 if (row) *m = *(m-nChannels);
128 if (row >= nRows) break;
133 if (xx < row) *m = pat[nChannels*xx];
140 cmd.note = (xx & 0x01) ? lpTracks[pos++] : 0;
141 cmd.instr = (xx & 0x02) ? lpTracks[pos++] : 0;
142 cmd.volcmd = cmd.vol = 0;
143 cmd.command = cmd.param = 0;
144 if ((cmd.note < 120-12) && (cmd.note)) cmd.note += 12;
145 UINT volume = (xx & 0x04) ? lpTracks[pos++] : 0;
146 UINT commands = (xx & 0x08) ? lpTracks[pos++] : 0;
147 UINT command1 = commands & 0x0F;
148 UINT command2 = commands & 0xF0;
149 UINT param1 = (xx & 0x10) ? lpTracks[pos++] : 0;
150 UINT param2 = (xx & 0x20) ? lpTracks[pos++] : 0;
151 if ((command1 == 0x0E) && ((param1 & 0xF0) == 0xF0) && (!command2))
153 param1 = ((param1 & 0x0F) << 8) | param2;
155 command2 = param2 = 0;
159 cmd.volcmd = VOLCMD_VOLUME;
160 cmd.vol = (volume+1) >> 2;
162 ConvertMDLCommand(&cmd, command1, param1);
163 if ((cmd.command != CMD_SPEED)
164 && (cmd.command != CMD_TEMPO)
165 && (cmd.command != CMD_PATTERNBREAK))
166 ConvertMDLCommand(&cmd, command2, param2);
176 m += (xx+1)*nChannels;
177 if (row >= nRows) break;
184 BOOL CSoundFile::ReadMDL(const BYTE *lpStream, DWORD dwMemLength)
185 //---------------------------------------------------------------
187 DWORD dwMemPos, dwPos, blocklen, dwTrackPos;
188 const MDLSONGHEADER *pmsh = (const MDLSONGHEADER *)lpStream;
190 MDLPATTERNDATA *pmpd;
191 UINT i,j, norders = 0, npatterns = 0, ntracks = 0;
192 UINT ninstruments = 0, nsamples = 0;
194 WORD patterntracks[MAX_PATTERNS*32];
195 BYTE smpinfo[MAX_SAMPLES];
196 BYTE insvolenv[MAX_INSTRUMENTS];
197 BYTE inspanenv[MAX_INSTRUMENTS];
198 LPCBYTE pvolenv, ppanenv, ppitchenv;
199 UINT nvolenv, npanenv, npitchenv;
201 if ((!lpStream) || (dwMemLength < 1024)) return FALSE;
202 if ((pmsh->id != 0x4C444D44) || ((pmsh->version & 0xF0) > 0x10)) return FALSE;
203 memset(patterntracks, 0, sizeof(patterntracks));
204 memset(smpinfo, 0, sizeof(smpinfo));
205 memset(insvolenv, 0, sizeof(insvolenv));
206 memset(inspanenv, 0, sizeof(inspanenv));
209 pvolenv = ppanenv = ppitchenv = NULL;
210 nvolenv = npanenv = npitchenv = 0;
211 m_nSamples = m_nInstruments = 0;
212 while (dwMemPos+6 < dwMemLength)
214 block = *((WORD *)(lpStream+dwMemPos));
215 blocklen = *((DWORD *)(lpStream+dwMemPos+2));
217 if (dwMemPos + blocklen > dwMemLength)
219 if (dwMemPos == 11) return FALSE;
226 pmib = (MDLINFOBLOCK *)(lpStream+dwMemPos);
227 memcpy(m_szNames[0], pmib->songname, 32);
228 norders = pmib->norders;
229 if (norders > MAX_ORDERS) norders = MAX_ORDERS;
230 m_nRestartPos = pmib->repeatpos;
231 m_nDefaultGlobalVolume = pmib->globalvol;
232 m_nDefaultTempo = pmib->tempo;
233 m_nDefaultSpeed = pmib->speed;
237 ChnSettings[i].nVolume = 64;
238 ChnSettings[i].nPan = (pmib->channelinfo[i] & 0x7F) << 1;
239 if (pmib->channelinfo[i] & 0x80)
240 ChnSettings[i].dwFlags |= CHN_MUTE;
244 for (j=0; j<norders; j++) Order[j] = pmib->seq[j];
250 if (m_lpszSongComments) delete m_lpszSongComments;
251 m_lpszSongComments = new char[blocklen];
252 if (m_lpszSongComments)
254 memcpy(m_lpszSongComments, lpStream+dwMemPos, blocklen);
255 m_lpszSongComments[blocklen-1] = 0;
261 npatterns = lpStream[dwMemPos];
262 if (npatterns > MAX_PATTERNS) npatterns = MAX_PATTERNS;
263 dwPos = dwMemPos + 1;
264 for (i=0; i<npatterns; i++)
266 if (dwPos+18 >= dwMemLength) break;
267 pmpd = (MDLPATTERNDATA *)(lpStream + dwPos);
268 if (pmpd->channels > 32) break;
269 PatternSize[i] = pmpd->lastrow+1;
270 if (m_nChannels < pmpd->channels) m_nChannels = pmpd->channels;
271 dwPos += 18 + 2*pmpd->channels;
272 for (j=0; j<pmpd->channels; j++)
274 patterntracks[i*32+j] = pmpd->data[j];
280 if (dwTrackPos) break;
281 ntracks = *((WORD *)(lpStream+dwMemPos));
282 dwTrackPos = dwMemPos+2;
286 ninstruments = lpStream[dwMemPos];
288 for (i=0; i<ninstruments; i++)
290 UINT nins = lpStream[dwPos];
291 if ((nins >= MAX_INSTRUMENTS) || (!nins)) break;
292 if (m_nInstruments < nins) m_nInstruments = nins;
296 if ((Headers[nins] = new INSTRUMENTHEADER) == NULL) break;
297 INSTRUMENTHEADER *penv = Headers[nins];
298 memset(penv, 0, sizeof(INSTRUMENTHEADER));
299 memcpy(penv->name, lpStream+dwPos+2, 32);
300 penv->nGlobalVol = 64;
302 for (j=0; j<lpStream[dwPos+1]; j++)
304 const BYTE *ps = lpStream+dwPos+34+14*j;
305 while ((note < (UINT)(ps[1]+12)) && (note < 120))
307 penv->NoteMap[note] = note+1;
308 if (ps[0] < MAX_SAMPLES)
311 penv->Keyboard[note] = ps[0];
312 Ins[ismp].nVolume = ps[2];
313 Ins[ismp].nPan = ps[4] << 1;
314 Ins[ismp].nVibType = ps[11];
315 Ins[ismp].nVibSweep = ps[10];
316 Ins[ismp].nVibDepth = ps[9];
317 Ins[ismp].nVibRate = ps[8];
319 penv->nFadeOut = (ps[7] << 8) | ps[6];
320 if (penv->nFadeOut == 0xFFFF) penv->nFadeOut = 0;
323 // Use volume envelope ?
326 penv->dwFlags |= ENV_VOLUME;
327 insvolenv[nins] = (ps[3] & 0x3F) + 1;
329 // Use panning envelope ?
332 penv->dwFlags |= ENV_PANNING;
333 inspanenv[nins] = (ps[5] & 0x3F) + 1;
337 dwPos += 34 + 14*lpStream[dwPos+1];
339 for (j=1; j<=m_nInstruments; j++) if (!Headers[j])
341 Headers[j] = new INSTRUMENTHEADER;
342 if (Headers[j]) memset(Headers[j], 0, sizeof(INSTRUMENTHEADER));
345 // VE: Volume Envelope
347 if ((nvolenv = lpStream[dwMemPos]) == 0) break;
348 if (dwMemPos + nvolenv*32 + 1 <= dwMemLength) pvolenv = lpStream + dwMemPos + 1;
350 // PE: Panning Envelope
352 if ((npanenv = lpStream[dwMemPos]) == 0) break;
353 if (dwMemPos + npanenv*32 + 1 <= dwMemLength) ppanenv = lpStream + dwMemPos + 1;
355 // FE: Pitch Envelope
357 if ((npitchenv = lpStream[dwMemPos]) == 0) break;
358 if (dwMemPos + npitchenv*32 + 1 <= dwMemLength) ppitchenv = lpStream + dwMemPos + 1;
360 // IS: Sample Infoblock
362 nsamples = lpStream[dwMemPos];
364 for (i=0; i<nsamples; i++, dwPos += 59)
366 UINT nins = lpStream[dwPos];
367 if ((nins >= MAX_SAMPLES) || (!nins)) continue;
368 if (m_nSamples < nins) m_nSamples = nins;
369 MODINSTRUMENT *pins = &Ins[nins];
370 memcpy(m_szNames[nins], lpStream+dwPos+1, 32);
371 memcpy(pins->name, lpStream+dwPos+33, 8);
372 pins->nC4Speed = *((DWORD *)(lpStream+dwPos+41));
373 pins->nLength = *((DWORD *)(lpStream+dwPos+45));
374 pins->nLoopStart = *((DWORD *)(lpStream+dwPos+49));
375 pins->nLoopEnd = pins->nLoopStart + *((DWORD *)(lpStream+dwPos+53));
376 if (pins->nLoopEnd > pins->nLoopStart) pins->uFlags |= CHN_LOOP;
377 pins->nGlobalVol = 64;
378 if (lpStream[dwPos+58] & 0x01)
380 pins->uFlags |= CHN_16BIT;
382 pins->nLoopStart >>= 1;
383 pins->nLoopEnd >>= 1;
385 if (lpStream[dwPos+58] & 0x02) pins->uFlags |= CHN_PINGPONGLOOP;
386 smpinfo[nins] = (lpStream[dwPos+58] >> 2) & 3;
392 for (i=1; i<=m_nSamples; i++) if ((Ins[i].nLength) && (!Ins[i].pSample) && (smpinfo[i] != 3) && (dwPos < dwMemLength))
394 MODINSTRUMENT *pins = &Ins[i];
395 UINT flags = (pins->uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S;
398 dwPos += ReadSample(pins, flags, (LPSTR)(lpStream+dwPos), dwMemLength - dwPos);
401 DWORD dwLen = *((DWORD *)(lpStream+dwPos));
403 if ((dwPos+dwLen <= dwMemLength) && (dwLen > 4))
405 flags = (pins->uFlags & CHN_16BIT) ? RS_MDL16 : RS_MDL8;
406 ReadSample(pins, flags, (LPSTR)(lpStream+dwPos), dwLen);
413 dwMemPos += blocklen;
416 if ((dwTrackPos) && (npatterns) && (m_nChannels) && (ntracks))
418 for (UINT ipat=0; ipat<npatterns; ipat++)
420 if ((Patterns[ipat] = AllocatePattern(PatternSize[ipat], m_nChannels)) == NULL) break;
421 for (UINT chn=0; chn<m_nChannels; chn++) if ((patterntracks[ipat*32+chn]) && (patterntracks[ipat*32+chn] <= ntracks))
423 MODCOMMAND *m = Patterns[ipat] + chn;
424 UnpackMDLTrack(m, m_nChannels, PatternSize[ipat], patterntracks[ipat*32+chn], lpStream+dwTrackPos);
429 for (UINT iIns=1; iIns<=m_nInstruments; iIns++) if (Headers[iIns])
431 INSTRUMENTHEADER *penv = Headers[iIns];
432 // Setup volume envelope
433 if ((nvolenv) && (pvolenv) && (insvolenv[iIns]))
435 LPCBYTE pve = pvolenv;
436 for (UINT nve=0; nve<nvolenv; nve++, pve+=33) if (pve[0]+1 == insvolenv[iIns])
440 for (UINT iv=0; iv<15; iv++)
442 if (iv) vtick += pve[iv*2+1];
443 penv->VolPoints[iv] = vtick;
444 penv->VolEnv[iv] = pve[iv*2+2];
447 penv->nVolEnv = iv+1;
451 penv->nVolSustainBegin = penv->nVolSustainEnd = pve[31] & 0x0F;
452 if (pve[31] & 0x10) penv->dwFlags |= ENV_VOLSUSTAIN;
453 if (pve[31] & 0x20) penv->dwFlags |= ENV_VOLLOOP;
454 penv->nVolLoopStart = pve[32] & 0x0F;
455 penv->nVolLoopEnd = pve[32] >> 4;
458 // Setup panning envelope
459 if ((npanenv) && (ppanenv) && (inspanenv[iIns]))
461 LPCBYTE ppe = ppanenv;
462 for (UINT npe=0; npe<npanenv; npe++, ppe+=33) if (ppe[0]+1 == inspanenv[iIns])
466 for (UINT iv=0; iv<15; iv++)
468 if (iv) vtick += ppe[iv*2+1];
469 penv->PanPoints[iv] = vtick;
470 penv->PanEnv[iv] = ppe[iv*2+2];
473 penv->nPanEnv = iv+1;
477 if (ppe[31] & 0x10) penv->dwFlags |= ENV_PANSUSTAIN;
478 if (ppe[31] & 0x20) penv->dwFlags |= ENV_PANLOOP;
479 penv->nPanLoopStart = ppe[32] & 0x0F;
480 penv->nPanLoopEnd = ppe[32] >> 4;
484 m_dwSongFlags |= SONG_LINEARSLIDES;
485 m_nType = MOD_TYPE_MDL;
490 /////////////////////////////////////////////////////////////////////////
491 // MDL Sample Unpacking
493 // MDL Huffman ReadBits compression
494 WORD MDLReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n)
495 //-----------------------------------------------------------------
497 WORD v = (WORD)(bitbuf & ((1 << n) - 1) );
502 bitbuf |= (((DWORD)(*ibuf++)) << bitnum);