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