Mercurial > audlegacy-plugins
comparison src/modplug/load_mt2.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 #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 } MT2FILEHEADER; | |
27 | |
28 typedef struct _MT2PATTERN | |
29 { | |
30 WORD wLines; | |
31 DWORD wDataLen; | |
32 } 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 } MT2COMMAND; | |
44 | |
45 typedef struct _MT2DRUMSDATA | |
46 { | |
47 WORD wDrumPatterns; | |
48 WORD wDrumSamples[8]; | |
49 BYTE DrumPatternOrder[256]; | |
50 } MT2DRUMSDATA; | |
51 | |
52 typedef struct _MT2AUTOMATION | |
53 { | |
54 DWORD dwFlags; | |
55 DWORD dwEffectId; | |
56 DWORD nEnvPoints; | |
57 } 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 } 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 } 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 } 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 } MT2SAMPLE; | |
115 | |
116 typedef struct _MT2GROUP | |
117 { | |
118 BYTE nSmpNo; | |
119 BYTE nVolume; // 0-128 | |
120 BYTE nFinePitch; | |
121 BYTE Reserved[5]; | |
122 } 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 } |