Diffstat (limited to 'core/multimedia/opieplayer/modplug/load_mt2.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/multimedia/opieplayer/modplug/load_mt2.cpp | 635 |
1 files changed, 635 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/modplug/load_mt2.cpp b/core/multimedia/opieplayer/modplug/load_mt2.cpp new file mode 100644 index 0000000..afa20d5 --- a/dev/null +++ b/core/multimedia/opieplayer/modplug/load_mt2.cpp | |||
@@ -0,0 +1,635 @@ | |||
1 | #include "stdafx.h" | ||
2 | #include "sndfile.h" | ||
3 | |||
4 | //#define MT2DEBUG | ||
5 | |||
6 | #pragma pack(1) | ||
7 | |||
8 | typedef struct _MT2FILEHEADER | ||
9 | { | ||
10 | DWORD dwMT20;// 0x3032544D "MT20" | ||
11 | DWORD dwSpecial; | ||
12 | WORD wVersion; | ||
13 | CHAR szTrackerName[32];// "MadTracker 2.0" | ||
14 | CHAR szSongName[64]; | ||
15 | WORD nOrders; | ||
16 | WORD wRestart; | ||
17 | WORD wPatterns; | ||
18 | WORD wChannels; | ||
19 | WORD wSamplesPerTick; | ||
20 | BYTE bTicksPerLine; | ||
21 | BYTE bLinesPerBeat; | ||
22 | DWORD fulFlags; // b0=packed patterns | ||
23 | WORD wInstruments; | ||
24 | WORD wSamples; | ||
25 | BYTE Orders[256]; | ||
26 | } Q_PACKED MT2FILEHEADER; | ||
27 | |||
28 | typedef struct _MT2PATTERN | ||
29 | { | ||
30 | WORD wLines; | ||
31 | DWORD wDataLen; | ||
32 | } Q_PACKED MT2PATTERN; | ||
33 | |||
34 | typedef struct _MT2COMMAND | ||
35 | { | ||
36 | BYTE note;// 0=nothing, 97=note off | ||
37 | BYTE instr; | ||
38 | BYTE vol; | ||
39 | BYTE pan; | ||
40 | BYTE fxcmd; | ||
41 | BYTE fxparam1; | ||
42 | BYTE fxparam2; | ||
43 | } Q_PACKED MT2COMMAND; | ||
44 | |||
45 | typedef struct _MT2DRUMSDATA | ||
46 | { | ||
47 | WORD wDrumPatterns; | ||
48 | WORD wDrumSamples[8]; | ||
49 | BYTE DrumPatternOrder[256]; | ||
50 | } Q_PACKED MT2DRUMSDATA; | ||
51 | |||
52 | typedef struct _MT2AUTOMATION | ||
53 | { | ||
54 | DWORD dwFlags; | ||
55 | DWORD dwEffectId; | ||
56 | DWORD nEnvPoints; | ||
57 | } Q_PACKED MT2AUTOMATION; | ||
58 | |||
59 | typedef struct _MT2INSTRUMENT | ||
60 | { | ||
61 | CHAR szName[32]; | ||
62 | DWORD dwDataLen; | ||
63 | WORD wSamples; | ||
64 | BYTE GroupsMapping[96]; | ||
65 | BYTE bVibType; | ||
66 | BYTE bVibSweep; | ||
67 | BYTE bVibDepth; | ||
68 | BYTE bVibRate; | ||
69 | WORD wFadeOut; | ||
70 | WORD wNNA; | ||
71 | WORD wInstrFlags; | ||
72 | WORD wEnvFlags1; | ||
73 | WORD wEnvFlags2; | ||
74 | } Q_PACKED MT2INSTRUMENT; | ||
75 | |||
76 | typedef struct _MT2ENVELOPE | ||
77 | { | ||
78 | BYTE nFlags; | ||
79 | BYTE nPoints; | ||
80 | BYTE nSustainPos; | ||
81 | BYTE nLoopStart; | ||
82 | BYTE nLoopEnd; | ||
83 | BYTE bReserved[3]; | ||
84 | BYTE EnvData[64]; | ||
85 | } Q_PACKED MT2ENVELOPE; | ||
86 | |||
87 | typedef struct _MT2SYNTH | ||
88 | { | ||
89 | BYTE nSynthId; | ||
90 | BYTE nFxId; | ||
91 | WORD wCutOff; | ||
92 | BYTE nResonance; | ||
93 | BYTE nAttack; | ||
94 | BYTE nDecay; | ||
95 | BYTE bReserved[25]; | ||
96 | } Q_PACKED MT2SYNTH; | ||
97 | |||
98 | typedef struct _MT2SAMPLE | ||
99 | { | ||
100 | CHAR szName[32]; | ||
101 | DWORD dwDataLen; | ||
102 | DWORD dwLength; | ||
103 | DWORD dwFrequency; | ||
104 | BYTE nQuality; | ||
105 | BYTE nChannels; | ||
106 | BYTE nFlags; | ||
107 | BYTE nLoop; | ||
108 | DWORD dwLoopStart; | ||
109 | DWORD dwLoopEnd; | ||
110 | WORD wVolume; | ||
111 | BYTE nPan; | ||
112 | BYTE nBaseNote; | ||
113 | WORD wSamplesPerBeat; | ||
114 | } Q_PACKED MT2SAMPLE; | ||
115 | |||
116 | typedef struct _MT2GROUP | ||
117 | { | ||
118 | BYTE nSmpNo; | ||
119 | BYTE nVolume;// 0-128 | ||
120 | BYTE nFinePitch; | ||
121 | BYTE Reserved[5]; | ||
122 | } Q_PACKED MT2GROUP; | ||
123 | |||
124 | #pragma pack() | ||
125 | |||
126 | |||
127 | static VOID ConvertMT2Command(CSoundFile *that, MODCOMMAND *m, MT2COMMAND *p) | ||
128 | //--------------------------------------------------------------------------- | ||
129 | { | ||
130 | // Note | ||
131 | m->note = 0; | ||
132 | if (p->note) m->note = (p->note > 96) ? 0xFF : p->note+12; | ||
133 | // Instrument | ||
134 | m->instr = p->instr; | ||
135 | // Volume Column | ||
136 | if ((p->vol >= 0x10) && (p->vol <= 0x90)) | ||
137 | { | ||
138 | m->volcmd = VOLCMD_VOLUME; | ||
139 | m->vol = (p->vol - 0x10) >> 1; | ||
140 | } else | ||
141 | if ((p->vol >= 0xA0) && (p->vol <= 0xAF)) | ||
142 | { | ||
143 | m->volcmd = VOLCMD_VOLSLIDEDOWN; | ||
144 | m->vol = (p->vol & 0x0f); | ||
145 | } else | ||
146 | if ((p->vol >= 0xB0) && (p->vol <= 0xBF)) | ||
147 | { | ||
148 | m->volcmd = VOLCMD_VOLSLIDEUP; | ||
149 | m->vol = (p->vol & 0x0f); | ||
150 | } else | ||
151 | if ((p->vol >= 0xC0) && (p->vol <= 0xCF)) | ||
152 | { | ||
153 | m->volcmd = VOLCMD_FINEVOLDOWN; | ||
154 | m->vol = (p->vol & 0x0f); | ||
155 | } else | ||
156 | if ((p->vol >= 0xD0) && (p->vol <= 0xDF)) | ||
157 | { | ||
158 | m->volcmd = VOLCMD_FINEVOLUP; | ||
159 | m->vol = (p->vol & 0x0f); | ||
160 | } else | ||
161 | { | ||
162 | m->volcmd = 0; | ||
163 | m->vol = 0; | ||
164 | } | ||
165 | // Effects | ||
166 | m->command = 0; | ||
167 | m->param = 0; | ||
168 | if ((p->fxcmd) || (p->fxparam1) || (p->fxparam2)) | ||
169 | { | ||
170 | if (!p->fxcmd) | ||
171 | { | ||
172 | m->command = p->fxparam2; | ||
173 | m->param = p->fxparam1; | ||
174 | that->ConvertModCommand(m); | ||
175 | } else | ||
176 | { | ||
177 | // TODO: MT2 Effects | ||
178 | } | ||
179 | } | ||
180 | } | ||
181 | |||
182 | |||
183 | BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength) | ||
184 | //----------------------------------------------------------- | ||
185 | { | ||
186 | MT2FILEHEADER *pfh = (MT2FILEHEADER *)lpStream; | ||
187 | DWORD dwMemPos, dwDrumDataPos, dwExtraDataPos; | ||
188 | UINT nDrumDataLen, nExtraDataLen; | ||
189 | MT2DRUMSDATA *pdd; | ||
190 | MT2INSTRUMENT *InstrMap[255]; | ||
191 | MT2SAMPLE *SampleMap[256]; | ||
192 | |||
193 | if ((!lpStream) || (dwMemLength < sizeof(MT2FILEHEADER)) | ||
194 | || (pfh->dwMT20 != 0x3032544D) | ||
195 | || (pfh->wVersion < 0x0200) || (pfh->wVersion >= 0x0300) | ||
196 | || (pfh->wChannels < 4) || (pfh->wChannels > 64)) return FALSE; | ||
197 | pdd = NULL; | ||
198 | m_nType = MOD_TYPE_MT2; | ||
199 | m_nChannels = pfh->wChannels; | ||
200 | m_nRestartPos = pfh->wRestart; | ||
201 | m_nDefaultSpeed = pfh->bTicksPerLine; | ||
202 | m_nDefaultTempo = 125; | ||
203 | if ((pfh->wSamplesPerTick > 100) && (pfh->wSamplesPerTick < 5000)) | ||
204 | { | ||
205 | m_nDefaultTempo = 110250 / pfh->wSamplesPerTick; | ||
206 | } | ||
207 | for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++) | ||
208 | { | ||
209 | Order[iOrd] = (BYTE)((iOrd < pfh->nOrders) ? pfh->Orders[iOrd] : 0xFF); | ||
210 | } | ||
211 | memcpy(m_szNames[0], pfh->szSongName, 32); | ||
212 | m_szNames[0][31] = 0; | ||
213 | dwMemPos = sizeof(MT2FILEHEADER); | ||
214 | nDrumDataLen = *(WORD *)(lpStream + dwMemPos); | ||
215 | dwDrumDataPos = dwMemPos + 2; | ||
216 | if (nDrumDataLen >= 2) pdd = (MT2DRUMSDATA *)(lpStream+dwDrumDataPos); | ||
217 | dwMemPos += 2 + nDrumDataLen; | ||
218 | #ifdef MT2DEBUG | ||
219 | |||
220 | Log("MT2 v%03X: \"%s\" (flags=%04X)\n", pfh->wVersion, m_szNames[0], pfh->fulFlags); | ||
221 | Log("%d Channels, %d Patterns, %d Instruments, %d Samples\n", pfh->wChannels, pfh->wPatterns, pfh->wInstruments, pfh->wSamples); | ||
222 | Log("Drum Data: %d bytes @%04X\n", nDrumDataLen, dwDrumDataPos); | ||
223 | #endif | ||
224 | if (dwMemPos >= dwMemLength-12) return TRUE; | ||
225 | if (!*(DWORD *)(lpStream+dwMemPos)) dwMemPos += 4; | ||
226 | if (!*(DWORD *)(lpStream+dwMemPos)) dwMemPos += 4; | ||
227 | nExtraDataLen = *(DWORD *)(lpStream+dwMemPos); | ||
228 | dwExtraDataPos = dwMemPos + 4; | ||
229 | dwMemPos += 4; | ||
230 | #ifdef MT2DEBUG | ||
231 | Log("Extra Data: %d bytes @%04X\n", nExtraDataLen, dwExtraDataPos); | ||
232 | #endif | ||
233 | if (dwMemPos + nExtraDataLen >= dwMemLength) return TRUE; | ||
234 | while (dwMemPos+8 < dwExtraDataPos + nExtraDataLen) | ||
235 | { | ||
236 | DWORD dwId = *(DWORD *)(lpStream+dwMemPos); | ||
237 | DWORD dwLen = *(DWORD *)(lpStream+dwMemPos+4); | ||
238 | dwMemPos += 8; | ||
239 | if (dwMemPos + dwLen > dwMemLength) return TRUE; | ||
240 | #ifdef MT2DEBUG | ||
241 | CHAR s[5]; | ||
242 | memcpy(s, &dwId, 4); | ||
243 | s[4] = 0; | ||
244 | Log("pos=0x%04X: %s: %d bytes\n", dwMemPos-8, s, dwLen); | ||
245 | #endif | ||
246 | switch(dwId) | ||
247 | { | ||
248 | // MSG | ||
249 | case 0x0047534D: | ||
250 | if ((dwLen > 3) && (!m_lpszSongComments)) | ||
251 | { | ||
252 | DWORD nTxtLen = dwLen; | ||
253 | if (nTxtLen > 32000) nTxtLen = 32000; | ||
254 | m_lpszSongComments = new char[nTxtLen]; // changed from CHAR | ||
255 | if (m_lpszSongComments) | ||
256 | { | ||
257 | memcpy(m_lpszSongComments, lpStream+dwMemPos+1, nTxtLen-1); | ||
258 | m_lpszSongComments[nTxtLen-1] = 0; | ||
259 | } | ||
260 | } | ||
261 | break; | ||
262 | // SUM -> author name (or "Unregistered") | ||
263 | // TMAP | ||
264 | // TRKS | ||
265 | case 0x534b5254: | ||
266 | break; | ||
267 | } | ||
268 | dwMemPos += dwLen; | ||
269 | } | ||
270 | // Load Patterns | ||
271 | dwMemPos = dwExtraDataPos + nExtraDataLen; | ||
272 | for (UINT iPat=0; iPat<pfh->wPatterns; iPat++) if (dwMemPos < dwMemLength-6) | ||
273 | { | ||
274 | MT2PATTERN *pmp = (MT2PATTERN *)(lpStream+dwMemPos); | ||
275 | UINT wDataLen = (pmp->wDataLen + 1) & ~1; | ||
276 | dwMemPos += 6; | ||
277 | if (dwMemPos + wDataLen > dwMemLength) break; | ||
278 | UINT nLines = pmp->wLines; | ||
279 | if ((iPat < MAX_PATTERNS) && (nLines > 0) && (nLines <= 256)) | ||
280 | { | ||
281 | #ifdef MT2DEBUG | ||
282 | Log("Pattern #%d @%04X: %d lines, %d bytes\n", iPat, dwMemPos-6, nLines, pmp->wDataLen); | ||
283 | #endif | ||
284 | PatternSize[iPat] = nLines; | ||
285 | Patterns[iPat] = AllocatePattern(nLines, m_nChannels); | ||
286 | if (!Patterns[iPat]) return TRUE; | ||
287 | MODCOMMAND *m = Patterns[iPat]; | ||
288 | UINT len = wDataLen; | ||
289 | if (pfh->fulFlags & 1) // Packed Patterns | ||
290 | { | ||
291 | BYTE *p = (BYTE *)(lpStream+dwMemPos); | ||
292 | UINT pos = 0, row=0, ch=0; | ||
293 | while (pos < len) | ||
294 | { | ||
295 | MT2COMMAND cmd; | ||
296 | UINT infobyte = p[pos++]; | ||
297 | UINT rptcount = 0; | ||
298 | if (infobyte == 0xff) | ||
299 | { | ||
300 | rptcount = p[pos++]; | ||
301 | infobyte = p[pos++]; | ||
302 | #if 0 | ||
303 | Log("(%d.%d) FF(%02X).%02X\n", row, ch, rptcount, infobyte); | ||
304 | } else | ||
305 | { | ||
306 | Log("(%d.%d) %02X\n", row, ch, infobyte); | ||
307 | #endif | ||
308 | } | ||
309 | if (infobyte & 0x7f) | ||
310 | { | ||
311 | UINT patpos = row*m_nChannels+ch; | ||
312 | cmd.note = cmd.instr = cmd.vol = cmd.pan = cmd.fxcmd = cmd.fxparam1 = cmd.fxparam2 = 0; | ||
313 | if (infobyte & 1) cmd.note = p[pos++]; | ||
314 | if (infobyte & 2) cmd.instr = p[pos++]; | ||
315 | if (infobyte & 4) cmd.vol = p[pos++]; | ||
316 | if (infobyte & 8) cmd.pan = p[pos++]; | ||
317 | if (infobyte & 16) cmd.fxcmd = p[pos++]; | ||
318 | if (infobyte & 32) cmd.fxparam1 = p[pos++]; | ||
319 | if (infobyte & 64) cmd.fxparam2 = p[pos++]; | ||
320 | #ifdef MT2DEBUG | ||
321 | if (cmd.fxcmd) | ||
322 | { | ||
323 | Log("(%d.%d) MT2 FX=%02X.%02X.%02X\n", row, ch, cmd.fxcmd, cmd.fxparam1, cmd.fxparam2); | ||
324 | } | ||
325 | #endif | ||
326 | ConvertMT2Command(this, &m[patpos], &cmd); | ||
327 | } | ||
328 | row += rptcount+1; | ||
329 | while (row >= nLines) { row-=nLines; ch++; } | ||
330 | if (ch >= m_nChannels) break; | ||
331 | } | ||
332 | } else | ||
333 | { | ||
334 | MT2COMMAND *p = (MT2COMMAND *)(lpStream+dwMemPos); | ||
335 | UINT n = 0; | ||
336 | while ((len > sizeof(MT2COMMAND)) && (n < m_nChannels*nLines)) | ||
337 | { | ||
338 | ConvertMT2Command(this, m, p); | ||
339 | len -= sizeof(MT2COMMAND); | ||
340 | n++; | ||
341 | p++; | ||
342 | m++; | ||
343 | } | ||
344 | } | ||
345 | } | ||
346 | dwMemPos += wDataLen; | ||
347 | } | ||
348 | // Skip Drum Patterns | ||
349 | if (pdd) | ||
350 | { | ||
351 | #ifdef MT2DEBUG | ||
352 | Log("%d Drum Patterns at offset 0x%08X\n", pdd->wDrumPatterns, dwMemPos); | ||
353 | #endif | ||
354 | for (UINT iDrm=0; iDrm<pdd->wDrumPatterns; iDrm++) | ||
355 | { | ||
356 | if (dwMemPos > dwMemLength-2) return TRUE; | ||
357 | UINT nLines = *(WORD *)(lpStream+dwMemPos); | ||
358 | #ifdef MT2DEBUG | ||
359 | if (nLines != 64) Log("Drum Pattern %d: %d Lines @%04X\n", iDrm, nLines, dwMemPos); | ||
360 | #endif | ||
361 | dwMemPos += 2 + nLines * 32; | ||
362 | } | ||
363 | } | ||
364 | // Automation | ||
365 | if (pfh->fulFlags & 2) | ||
366 | { | ||
367 | #ifdef MT2DEBUG | ||
368 | Log("Automation at offset 0x%08X\n", dwMemPos); | ||
369 | #endif | ||
370 | UINT nAutoCount = m_nChannels; | ||
371 | if (pfh->fulFlags & 0x10) nAutoCount++; // Master Automation | ||
372 | if ((pfh->fulFlags & 0x08) && (pdd)) nAutoCount += 8; // Drums Automation | ||
373 | nAutoCount *= pfh->wPatterns; | ||
374 | for (UINT iAuto=0; iAuto<nAutoCount; iAuto++) | ||
375 | { | ||
376 | if (dwMemPos+12 >= dwMemLength) return TRUE; | ||
377 | MT2AUTOMATION *pma = (MT2AUTOMATION *)(lpStream+dwMemPos); | ||
378 | dwMemPos += (pfh->wVersion <= 0x201) ? 4 : 8; | ||
379 | for (UINT iEnv=0; iEnv<14; iEnv++) | ||
380 | { | ||
381 | if (pma->dwFlags & (1 << iEnv)) | ||
382 | { | ||
383 | #ifdef MT2DEBUG | ||
384 | UINT nPoints = *(DWORD *)(lpStream+dwMemPos); | ||
385 | Log(" Env[%d/%d] %04X @%04X: %d points\n", iAuto, nAutoCount, 1 << iEnv, dwMemPos-8, nPoints); | ||
386 | #endif | ||
387 | dwMemPos += 260; | ||
388 | } | ||
389 | } | ||
390 | } | ||
391 | } | ||
392 | // Load Instruments | ||
393 | #ifdef MT2DEBUG | ||
394 | Log("Loading instruments at offset 0x%08X\n", dwMemPos); | ||
395 | #endif | ||
396 | memset(InstrMap, 0, sizeof(InstrMap)); | ||
397 | m_nInstruments = (pfh->wInstruments < MAX_INSTRUMENTS) ? pfh->wInstruments : MAX_INSTRUMENTS-1; | ||
398 | for (UINT iIns=1; iIns<=255; iIns++) | ||
399 | { | ||
400 | if (dwMemPos+36 > dwMemLength) return TRUE; | ||
401 | MT2INSTRUMENT *pmi = (MT2INSTRUMENT *)(lpStream+dwMemPos); | ||
402 | INSTRUMENTHEADER *penv = NULL; | ||
403 | if (iIns <= m_nInstruments) | ||
404 | { | ||
405 | penv = new INSTRUMENTHEADER; | ||
406 | Headers[iIns] = penv; | ||
407 | if (penv) | ||
408 | { | ||
409 | memset(penv, 0, sizeof(INSTRUMENTHEADER)); | ||
410 | memcpy(penv->name, pmi->szName, 32); | ||
411 | penv->nGlobalVol = 64; | ||
412 | penv->nPan = 128; | ||
413 | for (UINT i=0; i<120; i++) | ||
414 | { | ||
415 | penv->NoteMap[i] = i+1; | ||
416 | } | ||
417 | } | ||
418 | } | ||
419 | #ifdef MT2DEBUG | ||
420 | if (iIns <= pfh->wInstruments) Log(" Instrument #%d at offset %04X: %d bytes\n", iIns, dwMemPos, pmi->dwDataLen); | ||
421 | #endif | ||
422 | if (((LONG)pmi->dwDataLen > 0) && (dwMemPos + pmi->dwDataLen + 40 <= dwMemLength)) | ||
423 | { | ||
424 | InstrMap[iIns-1] = pmi; | ||
425 | if (penv) | ||
426 | { | ||
427 | penv->nFadeOut = pmi->wFadeOut; | ||
428 | penv->nNNA = pmi->wNNA & 3; | ||
429 | penv->nDCT = (pmi->wNNA>>8) & 3; | ||
430 | penv->nDNA = (pmi->wNNA>>12) & 3; | ||
431 | MT2ENVELOPE *pehdr[4]; | ||
432 | WORD *pedata[4]; | ||
433 | if (pfh->wVersion <= 0x201) | ||
434 | { | ||
435 | DWORD dwEnvPos = dwMemPos + sizeof(MT2INSTRUMENT) - 4; | ||
436 | pehdr[0] = (MT2ENVELOPE *)(lpStream+dwEnvPos); | ||
437 | pehdr[1] = (MT2ENVELOPE *)(lpStream+dwEnvPos+8); | ||
438 | pehdr[2] = pehdr[3] = NULL; | ||
439 | pedata[0] = (WORD *)(lpStream+dwEnvPos+16); | ||
440 | pedata[1] = (WORD *)(lpStream+dwEnvPos+16+64); | ||
441 | pedata[2] = pedata[3] = NULL; | ||
442 | } else | ||
443 | { | ||
444 | DWORD dwEnvPos = dwMemPos + sizeof(MT2INSTRUMENT); | ||
445 | for (UINT i=0; i<4; i++) | ||
446 | { | ||
447 | if (pmi->wEnvFlags1 & (1<<i)) | ||
448 | { | ||
449 | pehdr[i] = (MT2ENVELOPE *)(lpStream+dwEnvPos); | ||
450 | pedata[i] = (WORD *)pehdr[i]->EnvData; | ||
451 | dwEnvPos += sizeof(MT2ENVELOPE); | ||
452 | } else | ||
453 | { | ||
454 | pehdr[i] = NULL; | ||
455 | pedata[i] = NULL; | ||
456 | } | ||
457 | } | ||
458 | } | ||
459 | // Load envelopes | ||
460 | for (UINT iEnv=0; iEnv<4; iEnv++) if (pehdr[iEnv]) | ||
461 | { | ||
462 | MT2ENVELOPE *pme = pehdr[iEnv]; | ||
463 | WORD *pEnvPoints = NULL; | ||
464 | BYTE *pEnvData = NULL; | ||
465 | #ifdef MT2DEBUG | ||
466 | Log(" Env %d.%d @%04X: %d points\n", iIns, iEnv, (UINT)(((BYTE *)pme)-lpStream), pme->nPoints); | ||
467 | #endif | ||
468 | switch(iEnv) | ||
469 | { | ||
470 | // Volume Envelope | ||
471 | case 0: | ||
472 | if (pme->nFlags & 1) penv->dwFlags |= ENV_VOLUME; | ||
473 | if (pme->nFlags & 2) penv->dwFlags |= ENV_VOLSUSTAIN; | ||
474 | if (pme->nFlags & 4) penv->dwFlags |= ENV_VOLLOOP; | ||
475 | penv->nVolEnv = (pme->nPoints > 16) ? 16 : pme->nPoints; | ||
476 | penv->nVolSustainBegin = penv->nVolSustainEnd = pme->nSustainPos; | ||
477 | penv->nVolLoopStart = pme->nLoopStart; | ||
478 | penv->nVolLoopEnd = pme->nLoopEnd; | ||
479 | pEnvPoints = penv->VolPoints; | ||
480 | pEnvData = penv->VolEnv; | ||
481 | break; | ||
482 | |||
483 | // Panning Envelope | ||
484 | case 1: | ||
485 | if (pme->nFlags & 1) penv->dwFlags |= ENV_PANNING; | ||
486 | if (pme->nFlags & 2) penv->dwFlags |= ENV_PANSUSTAIN; | ||
487 | if (pme->nFlags & 4) penv->dwFlags |= ENV_PANLOOP; | ||
488 | penv->nPanEnv = (pme->nPoints > 16) ? 16 : pme->nPoints; | ||
489 | penv->nPanSustainBegin = penv->nPanSustainEnd = pme->nSustainPos; | ||
490 | penv->nPanLoopStart = pme->nLoopStart; | ||
491 | penv->nPanLoopEnd = pme->nLoopEnd; | ||
492 | pEnvPoints = penv->PanPoints; | ||
493 | pEnvData = penv->PanEnv; | ||
494 | break; | ||
495 | |||
496 | // Pitch/Filter envelope | ||
497 | default: | ||
498 | if (pme->nFlags & 1) penv->dwFlags |= (iEnv==3) ? (ENV_PITCH|ENV_FILTER) : ENV_PITCH; | ||
499 | if (pme->nFlags & 2) penv->dwFlags |= ENV_PITCHSUSTAIN; | ||
500 | if (pme->nFlags & 4) penv->dwFlags |= ENV_PITCHLOOP; | ||
501 | penv->nPitchEnv = (pme->nPoints > 16) ? 16 : pme->nPoints; | ||
502 | penv->nPitchSustainBegin = penv->nPitchSustainEnd = pme->nSustainPos; | ||
503 | penv->nPitchLoopStart = pme->nLoopStart; | ||
504 | penv->nPitchLoopEnd = pme->nLoopEnd; | ||
505 | pEnvPoints = penv->PitchPoints; | ||
506 | pEnvData = penv->PitchEnv; | ||
507 | } | ||
508 | // Envelope data | ||
509 | if ((pEnvPoints) && (pEnvData) && (pedata[iEnv])) | ||
510 | { | ||
511 | WORD *psrc = pedata[iEnv]; | ||
512 | for (UINT i=0; i<16; i++) | ||
513 | { | ||
514 | pEnvPoints[i] = psrc[i*2]; | ||
515 | pEnvData[i] = (BYTE)psrc[i*2+1]; | ||
516 | } | ||
517 | } | ||
518 | } | ||
519 | } | ||
520 | dwMemPos += pmi->dwDataLen + 36; | ||
521 | if (pfh->wVersion > 0x201) dwMemPos += 4; // ? | ||
522 | } else | ||
523 | { | ||
524 | dwMemPos += 36; | ||
525 | } | ||
526 | } | ||
527 | #ifdef MT2DEBUG | ||
528 | Log("Loading samples at offset 0x%08X\n", dwMemPos); | ||
529 | #endif | ||
530 | memset(SampleMap, 0, sizeof(SampleMap)); | ||
531 | m_nSamples = (pfh->wSamples < MAX_SAMPLES) ? pfh->wSamples : MAX_SAMPLES-1; | ||
532 | for (UINT iSmp=1; iSmp<=256; iSmp++) | ||
533 | { | ||
534 | if (dwMemPos+36 > dwMemLength) return TRUE; | ||
535 | MT2SAMPLE *pms = (MT2SAMPLE *)(lpStream+dwMemPos); | ||
536 | #ifdef MT2DEBUG | ||
537 | if (iSmp <= m_nSamples) Log(" Sample #%d at offset %04X: %d bytes\n", iSmp, dwMemPos, pms->dwDataLen); | ||
538 | #endif | ||
539 | if (iSmp < MAX_SAMPLES) | ||
540 | { | ||
541 | memcpy(m_szNames[iSmp], pms->szName, 32); | ||
542 | } | ||
543 | if (pms->dwDataLen > 0) | ||
544 | { | ||
545 | SampleMap[iSmp-1] = pms; | ||
546 | if (iSmp < MAX_SAMPLES) | ||
547 | { | ||
548 | MODINSTRUMENT *psmp = &Ins[iSmp]; | ||
549 | psmp->nGlobalVol = 64; | ||
550 | psmp->nVolume = (pms->wVolume >> 7); | ||
551 | psmp->nPan = (pms->nPan == 0x80) ? 128 : (pms->nPan^0x80); | ||
552 | psmp->nLength = pms->dwLength; | ||
553 | psmp->nC4Speed = pms->dwFrequency; | ||
554 | psmp->nLoopStart = pms->dwLoopStart; | ||
555 | psmp->nLoopEnd = pms->dwLoopEnd; | ||
556 | FrequencyToTranspose(psmp); | ||
557 | psmp->RelativeTone -= pms->nBaseNote - 49; | ||
558 | psmp->nC4Speed = TransposeToFrequency(psmp->RelativeTone, psmp->nFineTune); | ||
559 | if (pms->nQuality == 2) { psmp->uFlags |= CHN_16BIT; psmp->nLength >>= 1; } | ||
560 | if (pms->nChannels == 2) { psmp->nLength >>= 1; } | ||
561 | if (pms->nLoop == 1) psmp->uFlags |= CHN_LOOP; | ||
562 | if (pms->nLoop == 2) psmp->uFlags |= CHN_LOOP|CHN_PINGPONGLOOP; | ||
563 | } | ||
564 | dwMemPos += pms->dwDataLen + 36; | ||
565 | } else | ||
566 | { | ||
567 | dwMemPos += 36; | ||
568 | } | ||
569 | } | ||
570 | #ifdef MT2DEBUG | ||
571 | Log("Loading groups at offset 0x%08X\n", dwMemPos); | ||
572 | #endif | ||
573 | for (UINT iMap=0; iMap<255; iMap++) if (InstrMap[iMap]) | ||
574 | { | ||
575 | if (dwMemPos+8 > dwMemLength) return TRUE; | ||
576 | MT2INSTRUMENT *pmi = InstrMap[iMap]; | ||
577 | INSTRUMENTHEADER *penv = NULL; | ||
578 | if (iMap<m_nInstruments) penv = Headers[iMap+1]; | ||
579 | for (UINT iGrp=0; iGrp<pmi->wSamples; iGrp++) | ||
580 | { | ||
581 | if (penv) | ||
582 | { | ||
583 | MT2GROUP *pmg = (MT2GROUP *)(lpStream+dwMemPos); | ||
584 | for (UINT i=0; i<96; i++) | ||
585 | { | ||
586 | if (pmi->GroupsMapping[i] == iGrp) | ||
587 | { | ||
588 | UINT nSmp = pmg->nSmpNo+1; | ||
589 | penv->Keyboard[i+12] = (BYTE)nSmp; | ||
590 | if (nSmp <= m_nSamples) | ||
591 | { | ||
592 | Ins[nSmp].nVibType = pmi->bVibType; | ||
593 | Ins[nSmp].nVibSweep = pmi->bVibSweep; | ||
594 | Ins[nSmp].nVibDepth = pmi->bVibDepth; | ||
595 | Ins[nSmp].nVibRate = pmi->bVibRate; | ||
596 | } | ||
597 | } | ||
598 | } | ||
599 | } | ||
600 | dwMemPos += 8; | ||
601 | } | ||
602 | } | ||
603 | #ifdef MT2DEBUG | ||
604 | Log("Loading sample data at offset 0x%08X\n", dwMemPos); | ||
605 | #endif | ||
606 | for (UINT iData=0; iData<256; iData++) if ((iData < m_nSamples) && (SampleMap[iData])) | ||
607 | { | ||
608 | MT2SAMPLE *pms = SampleMap[iData]; | ||
609 | MODINSTRUMENT *psmp = &Ins[iData+1]; | ||
610 | if (!(pms->nFlags & 5)) | ||
611 | { | ||
612 | if (psmp->nLength > 0) | ||
613 | { | ||
614 | #ifdef MT2DEBUG | ||
615 | Log(" Reading sample #%d at offset 0x%04X (len=%d)\n", iData+1, dwMemPos, psmp->nLength); | ||
616 | #endif | ||
617 | UINT rsflags; | ||
618 | |||
619 | if (pms->nChannels == 2) | ||
620 | rsflags = (psmp->uFlags & CHN_16BIT) ? RS_STPCM16D : RS_STPCM8D; | ||
621 | else | ||
622 | rsflags = (psmp->uFlags & CHN_16BIT) ? RS_PCM16D : RS_PCM8D; | ||
623 | |||
624 | dwMemPos += ReadSample(psmp, rsflags, (LPCSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos); | ||
625 | } | ||
626 | } else | ||
627 | if (dwMemPos+4 < dwMemLength) | ||
628 | { | ||
629 | UINT nNameLen = *(DWORD *)(lpStream+dwMemPos); | ||
630 | dwMemPos += nNameLen + 16; | ||
631 | } | ||
632 | if (dwMemPos+4 >= dwMemLength) break; | ||
633 | } | ||
634 | return TRUE; | ||
635 | } | ||