comparison src/modplug/load_dmf.cxx @ 136:6b5a52635b3b trunk

[svn] - like with so many other things, modplug is now maintained by us.
author nenolod
date Sun, 29 Oct 2006 01:04:52 -0700
parents
children 032053ca08ab 3673c7ec4ea2
comparison
equal deleted inserted replaced
135:33d24bd94ccc 136:6b5a52635b3b
1 /*
2 * This source code is public domain.
3 *
4 * Authors: Olivier Lapicque <olivierl@jps.net>
5 */
6
7 ///////////////////////////////////////////////////////
8 // DMF DELUSION DIGITAL MUSIC FILEFORMAT (X-Tracker) //
9 ///////////////////////////////////////////////////////
10 #include "stdafx.h"
11 #include "sndfile.h"
12
13 //#define DMFLOG
14
15 //#pragma warning(disable:4244)
16
17 #pragma pack(1)
18
19 typedef struct DMFHEADER
20 {
21 DWORD id; // "DDMF" = 0x464d4444
22 BYTE version; // 4
23 CHAR trackername[8]; // "XTRACKER"
24 CHAR songname[30];
25 CHAR composer[20];
26 BYTE date[3];
27 } DMFHEADER;
28
29 typedef struct DMFINFO
30 {
31 DWORD id; // "INFO"
32 DWORD infosize;
33 } DMFINFO;
34
35 typedef struct DMFSEQU
36 {
37 DWORD id; // "SEQU"
38 DWORD seqsize;
39 WORD loopstart;
40 WORD loopend;
41 WORD sequ[2];
42 } DMFSEQU;
43
44 typedef struct DMFPATT
45 {
46 DWORD id; // "PATT"
47 DWORD patsize;
48 WORD numpat; // 1-1024
49 BYTE tracks;
50 BYTE firstpatinfo;
51 } DMFPATT;
52
53 typedef struct DMFTRACK
54 {
55 BYTE tracks;
56 BYTE beat; // [hi|lo] -> hi=ticks per beat, lo=beats per measure
57 WORD ticks; // max 512
58 DWORD jmpsize;
59 } DMFTRACK;
60
61 typedef struct DMFSMPI
62 {
63 DWORD id;
64 DWORD size;
65 BYTE samples;
66 } DMFSMPI;
67
68 typedef struct DMFSAMPLE
69 {
70 DWORD len;
71 DWORD loopstart;
72 DWORD loopend;
73 WORD c3speed;
74 BYTE volume;
75 BYTE flags;
76 } DMFSAMPLE;
77
78 #pragma pack()
79
80
81 #ifdef DMFLOG
82 extern void Log(LPCSTR s, ...);
83 #endif
84
85
86 BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength)
87 //---------------------------------------------------------------
88 {
89 DMFHEADER *pfh = (DMFHEADER *)lpStream;
90 DMFINFO *psi;
91 DMFSEQU *sequ;
92 DWORD dwMemPos;
93 BYTE infobyte[32];
94 BYTE smplflags[MAX_SAMPLES];
95
96 if ((!lpStream) || (dwMemLength < 1024)) return FALSE;
97 if ((pfh->id != 0x464d4444) || (!pfh->version) || (pfh->version & 0xF0)) return FALSE;
98 dwMemPos = 66;
99 memcpy(m_szNames[0], pfh->songname, 30);
100 m_szNames[0][30] = 0;
101 m_nType = MOD_TYPE_DMF;
102 m_nChannels = 0;
103 #ifdef DMFLOG
104 Log("DMF version %d: \"%s\": %d bytes (0x%04X)\n", pfh->version, m_szNames[0], dwMemLength, dwMemLength);
105 #endif
106 while (dwMemPos + 7 < dwMemLength)
107 {
108 DWORD id = *((LPDWORD)(lpStream+dwMemPos));
109
110 switch(id)
111 {
112 // "INFO"
113 case 0x4f464e49:
114 // "CMSG"
115 case 0x47534d43:
116 psi = (DMFINFO *)(lpStream+dwMemPos);
117 if (id == 0x47534d43) dwMemPos++;
118 if ((psi->infosize > dwMemLength) || (psi->infosize + dwMemPos + 8 > dwMemLength)) goto dmfexit;
119 if ((psi->infosize >= 8) && (!m_lpszSongComments))
120 {
121 m_lpszSongComments = new char[psi->infosize]; // changed from CHAR
122 if (m_lpszSongComments)
123 {
124 for (UINT i=0; i<psi->infosize-1; i++)
125 {
126 CHAR c = lpStream[dwMemPos+8+i];
127 if ((i % 40) == 39)
128 m_lpszSongComments[i] = 0x0d;
129 else
130 m_lpszSongComments[i] = (c < ' ') ? ' ' : c;
131 }
132 m_lpszSongComments[psi->infosize-1] = 0;
133 }
134 }
135 dwMemPos += psi->infosize + 8 - 1;
136 break;
137
138 // "SEQU"
139 case 0x55514553:
140 sequ = (DMFSEQU *)(lpStream+dwMemPos);
141 if ((sequ->seqsize >= dwMemLength) || (dwMemPos + sequ->seqsize + 12 > dwMemLength)) goto dmfexit;
142 {
143 UINT nseq = sequ->seqsize >> 1;
144 if (nseq >= MAX_ORDERS-1) nseq = MAX_ORDERS-1;
145 if (sequ->loopstart < nseq) m_nRestartPos = sequ->loopstart;
146 for (UINT i=0; i<nseq; i++) Order[i] = (BYTE)sequ->sequ[i];
147 }
148 dwMemPos += sequ->seqsize + 8;
149 break;
150
151 // "PATT"
152 case 0x54544150:
153 if (!m_nChannels)
154 {
155 DMFPATT *patt = (DMFPATT *)(lpStream+dwMemPos);
156 UINT numpat;
157 DWORD dwPos = dwMemPos + 11;
158 if ((patt->patsize >= dwMemLength) || (dwMemPos + patt->patsize + 8 > dwMemLength)) goto dmfexit;
159 numpat = patt->numpat;
160 if (numpat > MAX_PATTERNS) numpat = MAX_PATTERNS;
161 m_nChannels = patt->tracks;
162 if (m_nChannels < patt->firstpatinfo) m_nChannels = patt->firstpatinfo;
163 if (m_nChannels > 32) m_nChannels = 32;
164 if (m_nChannels < 4) m_nChannels = 4;
165 for (UINT npat=0; npat<numpat; npat++)
166 {
167 DMFTRACK *pt = (DMFTRACK *)(lpStream+dwPos);
168 #ifdef DMFLOG
169 Log("Pattern #%d: %d tracks, %d rows\n", npat, pt->tracks, pt->ticks);
170 #endif
171 UINT tracks = pt->tracks;
172 if (tracks > 32) tracks = 32;
173 UINT ticks = pt->ticks;
174 if (ticks > 256) ticks = 256;
175 if (ticks < 16) ticks = 16;
176 dwPos += 8;
177 if ((pt->jmpsize >= dwMemLength) || (dwPos + pt->jmpsize + 4 >= dwMemLength)) break;
178 PatternSize[npat] = (WORD)ticks;
179 MODCOMMAND *m = AllocatePattern(PatternSize[npat], m_nChannels);
180 if (!m) goto dmfexit;
181 Patterns[npat] = m;
182 DWORD d = dwPos;
183 dwPos += pt->jmpsize;
184 UINT ttype = 1;
185 UINT tempo = 125;
186 UINT glbinfobyte = 0;
187 UINT pbeat = (pt->beat & 0xf0) ? pt->beat>>4 : 8;
188 BOOL tempochange = (pt->beat & 0xf0) ? TRUE : FALSE;
189 memset(infobyte, 0, sizeof(infobyte));
190 for (UINT row=0; row<ticks; row++)
191 {
192 MODCOMMAND *p = &m[row*m_nChannels];
193 // Parse track global effects
194 if (!glbinfobyte)
195 {
196 BYTE info = lpStream[d++];
197 BYTE infoval = 0;
198 if ((info & 0x80) && (d < dwPos)) glbinfobyte = lpStream[d++];
199 info &= 0x7f;
200 if ((info) && (d < dwPos)) infoval = lpStream[d++];
201 switch(info)
202 {
203 case 1: ttype = 0; tempo = infoval; tempochange = TRUE; break;
204 case 2: ttype = 1; tempo = infoval; tempochange = TRUE; break;
205 case 3: pbeat = infoval>>4; tempochange = ttype; break;
206 #ifdef DMFLOG
207 default: if (info) Log("GLB: %02X.%02X\n", info, infoval);
208 #endif
209 }
210 } else
211 {
212 glbinfobyte--;
213 }
214 // Parse channels
215 for (UINT i=0; i<tracks; i++) if (!infobyte[i])
216 {
217 MODCOMMAND cmd = {0,0,0,0,0,0};
218 BYTE info = lpStream[d++];
219 if (info & 0x80) infobyte[i] = lpStream[d++];
220 // Instrument
221 if (info & 0x40)
222 {
223 cmd.instr = lpStream[d++];
224 }
225 // Note
226 if (info & 0x20)
227 {
228 cmd.note = lpStream[d++];
229 if ((cmd.note) && (cmd.note < 0xfe)) cmd.note &= 0x7f;
230 if ((cmd.note) && (cmd.note < 128)) cmd.note += 24;
231 }
232 // Volume
233 if (info & 0x10)
234 {
235 cmd.volcmd = VOLCMD_VOLUME;
236 cmd.vol = (lpStream[d++]+3)>>2;
237 }
238 // Effect 1
239 if (info & 0x08)
240 {
241 BYTE efx = lpStream[d++];
242 BYTE eval = lpStream[d++];
243 switch(efx)
244 {
245 // 1: Key Off
246 case 1: if (!cmd.note) cmd.note = 0xFE; break;
247 // 2: Set Loop
248 // 4: Sample Delay
249 case 4: if (eval&0xe0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>5)|0xD0; } break;
250 // 5: Retrig
251 case 5: if (eval&0xe0) { cmd.command = CMD_RETRIG; cmd.param = (eval>>5); } break;
252 // 6: Offset
253 case 6: cmd.command = CMD_OFFSET; cmd.param = eval; break;
254 #ifdef DMFLOG
255 default: Log("FX1: %02X.%02X\n", efx, eval);
256 #endif
257 }
258 }
259 // Effect 2
260 if (info & 0x04)
261 {
262 BYTE efx = lpStream[d++];
263 BYTE eval = lpStream[d++];
264 switch(efx)
265 {
266 // 1: Finetune
267 case 1: if (eval&0xf0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>4)|0x20; } break;
268 // 2: Note Delay
269 case 2: if (eval&0xe0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>5)|0xD0; } break;
270 // 3: Arpeggio
271 case 3: if (eval) { cmd.command = CMD_ARPEGGIO; cmd.param = eval; } break;
272 // 4: Portamento Up
273 case 4: cmd.command = CMD_PORTAMENTOUP; cmd.param = (eval >= 0xe0) ? 0xdf : eval; break;
274 // 5: Portamento Down
275 case 5: cmd.command = CMD_PORTAMENTODOWN; cmd.param = (eval >= 0xe0) ? 0xdf : eval; break;
276 // 6: Tone Portamento
277 case 6: cmd.command = CMD_TONEPORTAMENTO; cmd.param = eval; break;
278 // 8: Vibrato
279 case 8: cmd.command = CMD_VIBRATO; cmd.param = eval; break;
280 // 12: Note cut
281 case 12: if (eval & 0xe0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>5)|0xc0; }
282 else if (!cmd.note) { cmd.note = 0xfe; } break;
283 #ifdef DMFLOG
284 default: Log("FX2: %02X.%02X\n", efx, eval);
285 #endif
286 }
287 }
288 // Effect 3
289 if (info & 0x02)
290 {
291 BYTE efx = lpStream[d++];
292 BYTE eval = lpStream[d++];
293 switch(efx)
294 {
295 // 1: Vol Slide Up
296 case 1: if (eval == 0xff) break;
297 eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f;
298 cmd.command = CMD_VOLUMESLIDE; cmd.param = eval<<4; break;
299 // 2: Vol Slide Down
300 case 2: if (eval == 0xff) break;
301 eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f;
302 cmd.command = CMD_VOLUMESLIDE; cmd.param = eval; break;
303 // 7: Set Pan
304 case 7: if (!cmd.volcmd) { cmd.volcmd = VOLCMD_PANNING; cmd.vol = (eval+3)>>2; }
305 else { cmd.command = CMD_PANNING8; cmd.param = eval; } break;
306 // 8: Pan Slide Left
307 case 8: eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f;
308 cmd.command = CMD_PANNINGSLIDE; cmd.param = eval<<4; break;
309 // 9: Pan Slide Right
310 case 9: eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f;
311 cmd.command = CMD_PANNINGSLIDE; cmd.param = eval; break;
312 #ifdef DMFLOG
313 default: Log("FX3: %02X.%02X\n", efx, eval);
314 #endif
315
316 }
317 }
318 // Store effect
319 if (i < m_nChannels) p[i] = cmd;
320 if (d > dwPos)
321 {
322 #ifdef DMFLOG
323 Log("Unexpected EOP: row=%d\n", row);
324 #endif
325 break;
326 }
327 } else
328 {
329 infobyte[i]--;
330 }
331
332 // Find free channel for tempo change
333 if (tempochange)
334 {
335 tempochange = FALSE;
336 UINT speed=6, modtempo=tempo;
337 UINT rpm = ((ttype) && (pbeat)) ? tempo*pbeat : (tempo+1)*15;
338 for (speed=30; speed>1; speed--)
339 {
340 modtempo = rpm*speed/24;
341 if (modtempo <= 200) break;
342 if ((speed < 6) && (modtempo < 256)) break;
343 }
344 #ifdef DMFLOG
345 Log("Tempo change: ttype=%d pbeat=%d tempo=%3d -> speed=%d tempo=%d\n",
346 ttype, pbeat, tempo, speed, modtempo);
347 #endif
348 for (UINT ich=0; ich<m_nChannels; ich++) if (!p[ich].command)
349 {
350 if (speed)
351 {
352 p[ich].command = CMD_SPEED;
353 p[ich].param = (BYTE)speed;
354 speed = 0;
355 } else
356 if ((modtempo >= 32) && (modtempo < 256))
357 {
358 p[ich].command = CMD_TEMPO;
359 p[ich].param = (BYTE)modtempo;
360 modtempo = 0;
361 } else
362 {
363 break;
364 }
365 }
366 }
367 if (d >= dwPos) break;
368 }
369 #ifdef DMFLOG
370 Log(" %d/%d bytes remaining\n", dwPos-d, pt->jmpsize);
371 #endif
372 if (dwPos + 8 >= dwMemLength) break;
373 }
374 dwMemPos += patt->patsize + 8;
375 }
376 break;
377
378 // "SMPI": Sample Info
379 case 0x49504d53:
380 {
381 DMFSMPI *pds = (DMFSMPI *)(lpStream+dwMemPos);
382 if (pds->size <= dwMemLength - dwMemPos)
383 {
384 DWORD dwPos = dwMemPos + 9;
385 m_nSamples = pds->samples;
386 if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1;
387 for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++)
388 {
389 UINT namelen = lpStream[dwPos];
390 smplflags[iSmp] = 0;
391 if (dwPos+namelen+1+sizeof(DMFSAMPLE) > dwMemPos+pds->size+8) break;
392 if (namelen)
393 {
394 UINT rlen = (namelen < 32) ? namelen : 31;
395 memcpy(m_szNames[iSmp], lpStream+dwPos+1, rlen);
396 m_szNames[iSmp][rlen] = 0;
397 }
398 dwPos += namelen + 1;
399 DMFSAMPLE *psh = (DMFSAMPLE *)(lpStream+dwPos);
400 MODINSTRUMENT *psmp = &Ins[iSmp];
401 psmp->nLength = psh->len;
402 psmp->nLoopStart = psh->loopstart;
403 psmp->nLoopEnd = psh->loopend;
404 psmp->nC4Speed = psh->c3speed;
405 psmp->nGlobalVol = 64;
406 psmp->nVolume = (psh->volume) ? ((WORD)psh->volume)+1 : (WORD)256;
407 psmp->uFlags = (psh->flags & 2) ? CHN_16BIT : 0;
408 if (psmp->uFlags & CHN_16BIT) psmp->nLength >>= 1;
409 if (psh->flags & 1) psmp->uFlags |= CHN_LOOP;
410 smplflags[iSmp] = psh->flags;
411 dwPos += (pfh->version < 8) ? 22 : 30;
412 #ifdef DMFLOG
413 Log("SMPI %d/%d: len=%d flags=0x%02X\n", iSmp, m_nSamples, psmp->nLength, psh->flags);
414 #endif
415 }
416 }
417 dwMemPos += pds->size + 8;
418 }
419 break;
420
421 // "SMPD": Sample Data
422 case 0x44504d53:
423 {
424 DWORD dwPos = dwMemPos + 8;
425 UINT ismpd = 0;
426 for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++)
427 {
428 ismpd++;
429 DWORD pksize;
430 if (dwPos + 4 >= dwMemLength)
431 {
432 #ifdef DMFLOG
433 Log("Unexpected EOF at sample %d/%d! (pos=%d)\n", iSmp, m_nSamples, dwPos);
434 #endif
435 break;
436 }
437 pksize = *((LPDWORD)(lpStream+dwPos));
438 #ifdef DMFLOG
439 Log("sample %d: pos=0x%X pksize=%d ", iSmp, dwPos, pksize);
440 Log("len=%d flags=0x%X [%08X]\n", Ins[iSmp].nLength, smplflags[ismpd], *((LPDWORD)(lpStream+dwPos+4)));
441 #endif
442 dwPos += 4;
443 if (pksize > dwMemLength - dwPos)
444 {
445 #ifdef DMFLOG
446 Log("WARNING: pksize=%d, but only %d bytes left\n", pksize, dwMemLength-dwPos);
447 #endif
448 pksize = dwMemLength - dwPos;
449 }
450 if ((pksize) && (iSmp <= m_nSamples))
451 {
452 UINT flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S;
453 if (smplflags[ismpd] & 4) flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_DMF16 : RS_DMF8;
454 ReadSample(&Ins[iSmp], flags, (LPSTR)(lpStream+dwPos), pksize);
455 }
456 dwPos += pksize;
457 }
458 dwMemPos = dwPos;
459 }
460 break;
461
462 // "ENDE": end of file
463 case 0x45444e45:
464 goto dmfexit;
465
466 // Unrecognized id, or "ENDE" field
467 default:
468 dwMemPos += 4;
469 break;
470 }
471 }
472 dmfexit:
473 if (!m_nChannels)
474 {
475 if (!m_nSamples)
476 {
477 m_nType = MOD_TYPE_NONE;
478 return FALSE;
479 }
480 m_nChannels = 4;
481 }
482 return TRUE;
483 }
484
485
486 ///////////////////////////////////////////////////////////////////////
487 // DMF Compression
488
489 #pragma pack(1)
490
491 typedef struct DMF_HNODE
492 {
493 short int left, right;
494 BYTE value;
495 } DMF_HNODE;
496
497 typedef struct DMF_HTREE
498 {
499 LPBYTE ibuf, ibufmax;
500 DWORD bitbuf;
501 UINT bitnum;
502 UINT lastnode, nodecount;
503 DMF_HNODE nodes[256];
504 } DMF_HTREE;
505
506 #pragma pack()
507
508
509 // DMF Huffman ReadBits
510 BYTE DMFReadBits(DMF_HTREE *tree, UINT nbits)
511 //-------------------------------------------
512 {
513 BYTE x = 0, bitv = 1;
514 while (nbits--)
515 {
516 if (tree->bitnum)
517 {
518 tree->bitnum--;
519 } else
520 {
521 tree->bitbuf = (tree->ibuf < tree->ibufmax) ? *(tree->ibuf++) : 0;
522 tree->bitnum = 7;
523 }
524 if (tree->bitbuf & 1) x |= bitv;
525 bitv <<= 1;
526 tree->bitbuf >>= 1;
527 }
528 return x;
529 }
530
531 //
532 // tree: [8-bit value][12-bit index][12-bit index] = 32-bit
533 //
534
535 void DMFNewNode(DMF_HTREE *tree)
536 //------------------------------
537 {
538 BYTE isleft, isright;
539 UINT actnode;
540
541 actnode = tree->nodecount;
542 if (actnode > 255) return;
543 tree->nodes[actnode].value = DMFReadBits(tree, 7);
544 isleft = DMFReadBits(tree, 1);
545 isright = DMFReadBits(tree, 1);
546 actnode = tree->lastnode;
547 if (actnode > 255) return;
548 tree->nodecount++;
549 tree->lastnode = tree->nodecount;
550 if (isleft)
551 {
552 tree->nodes[actnode].left = tree->lastnode;
553 DMFNewNode(tree);
554 } else
555 {
556 tree->nodes[actnode].left = -1;
557 }
558 tree->lastnode = tree->nodecount;
559 if (isright)
560 {
561 tree->nodes[actnode].right = tree->lastnode;
562 DMFNewNode(tree);
563 } else
564 {
565 tree->nodes[actnode].right = -1;
566 }
567 }
568
569
570 int DMFUnpack(LPBYTE psample, LPBYTE ibuf, LPBYTE ibufmax, UINT maxlen)
571 //----------------------------------------------------------------------
572 {
573 DMF_HTREE tree;
574 UINT actnode;
575 BYTE value, sign, delta = 0;
576
577 memset(&tree, 0, sizeof(tree));
578 tree.ibuf = ibuf;
579 tree.ibufmax = ibufmax;
580 DMFNewNode(&tree);
581 value = 0;
582 for (UINT i=0; i<maxlen; i++)
583 {
584 actnode = 0;
585 sign = DMFReadBits(&tree, 1);
586 do
587 {
588 if (DMFReadBits(&tree, 1))
589 actnode = tree.nodes[actnode].right;
590 else
591 actnode = tree.nodes[actnode].left;
592 if (actnode > 255) break;
593 delta = tree.nodes[actnode].value;
594 if ((tree.ibuf >= tree.ibufmax) && (!tree.bitnum)) break;
595 } while ((tree.nodes[actnode].left >= 0) && (tree.nodes[actnode].right >= 0));
596 if (sign) delta ^= 0xFF;
597 value += delta;
598 psample[i] = (i) ? value : 0;
599 }
600 #ifdef DMFLOG
601 // Log("DMFUnpack: %d remaining bytes\n", tree.ibufmax-tree.ibuf);
602 #endif
603 return tree.ibuf - ibuf;
604 }
605
606