00001 #include "stdafx.h"
00002 #include "sndfile.h"
00003
00004
00005
00006 #pragma pack(1)
00007
00008 typedef struct _MT2FILEHEADER
00009 {
00010 DWORD dwMT20;
00011 DWORD dwSpecial;
00012 WORD wVersion;
00013 CHAR szTrackerName[32];
00014 CHAR szSongName[64];
00015 WORD nOrders;
00016 WORD wRestart;
00017 WORD wPatterns;
00018 WORD wChannels;
00019 WORD wSamplesPerTick;
00020 BYTE bTicksPerLine;
00021 BYTE bLinesPerBeat;
00022 DWORD fulFlags;
00023 WORD wInstruments;
00024 WORD wSamples;
00025 BYTE Orders[256];
00026 } Q_PACKED MT2FILEHEADER;
00027
00028 typedef struct _MT2PATTERN
00029 {
00030 WORD wLines;
00031 DWORD wDataLen;
00032 } Q_PACKED MT2PATTERN;
00033
00034 typedef struct _MT2COMMAND
00035 {
00036 BYTE note;
00037 BYTE instr;
00038 BYTE vol;
00039 BYTE pan;
00040 BYTE fxcmd;
00041 BYTE fxparam1;
00042 BYTE fxparam2;
00043 } Q_PACKED MT2COMMAND;
00044
00045 typedef struct _MT2DRUMSDATA
00046 {
00047 WORD wDrumPatterns;
00048 WORD wDrumSamples[8];
00049 BYTE DrumPatternOrder[256];
00050 } Q_PACKED MT2DRUMSDATA;
00051
00052 typedef struct _MT2AUTOMATION
00053 {
00054 DWORD dwFlags;
00055 DWORD dwEffectId;
00056 DWORD nEnvPoints;
00057 } Q_PACKED MT2AUTOMATION;
00058
00059 typedef struct _MT2INSTRUMENT
00060 {
00061 CHAR szName[32];
00062 DWORD dwDataLen;
00063 WORD wSamples;
00064 BYTE GroupsMapping[96];
00065 BYTE bVibType;
00066 BYTE bVibSweep;
00067 BYTE bVibDepth;
00068 BYTE bVibRate;
00069 WORD wFadeOut;
00070 WORD wNNA;
00071 WORD wInstrFlags;
00072 WORD wEnvFlags1;
00073 WORD wEnvFlags2;
00074 } Q_PACKED MT2INSTRUMENT;
00075
00076 typedef struct _MT2ENVELOPE
00077 {
00078 BYTE nFlags;
00079 BYTE nPoints;
00080 BYTE nSustainPos;
00081 BYTE nLoopStart;
00082 BYTE nLoopEnd;
00083 BYTE bReserved[3];
00084 BYTE EnvData[64];
00085 } Q_PACKED MT2ENVELOPE;
00086
00087 typedef struct _MT2SYNTH
00088 {
00089 BYTE nSynthId;
00090 BYTE nFxId;
00091 WORD wCutOff;
00092 BYTE nResonance;
00093 BYTE nAttack;
00094 BYTE nDecay;
00095 BYTE bReserved[25];
00096 } Q_PACKED MT2SYNTH;
00097
00098 typedef struct _MT2SAMPLE
00099 {
00100 CHAR szName[32];
00101 DWORD dwDataLen;
00102 DWORD dwLength;
00103 DWORD dwFrequency;
00104 BYTE nQuality;
00105 BYTE nChannels;
00106 BYTE nFlags;
00107 BYTE nLoop;
00108 DWORD dwLoopStart;
00109 DWORD dwLoopEnd;
00110 WORD wVolume;
00111 BYTE nPan;
00112 BYTE nBaseNote;
00113 WORD wSamplesPerBeat;
00114 } Q_PACKED MT2SAMPLE;
00115
00116 typedef struct _MT2GROUP
00117 {
00118 BYTE nSmpNo;
00119 BYTE nVolume;
00120 BYTE nFinePitch;
00121 BYTE Reserved[5];
00122 } Q_PACKED MT2GROUP;
00123
00124 #pragma pack()
00125
00126
00127 static VOID ConvertMT2Command(CSoundFile *that, MODCOMMAND *m, MT2COMMAND *p)
00128
00129 {
00130
00131 m->note = 0;
00132 if (p->note) m->note = (p->note > 96) ? 0xFF : p->note+12;
00133
00134 m->instr = p->instr;
00135
00136 if ((p->vol >= 0x10) && (p->vol <= 0x90))
00137 {
00138 m->volcmd = VOLCMD_VOLUME;
00139 m->vol = (p->vol - 0x10) >> 1;
00140 } else
00141 if ((p->vol >= 0xA0) && (p->vol <= 0xAF))
00142 {
00143 m->volcmd = VOLCMD_VOLSLIDEDOWN;
00144 m->vol = (p->vol & 0x0f);
00145 } else
00146 if ((p->vol >= 0xB0) && (p->vol <= 0xBF))
00147 {
00148 m->volcmd = VOLCMD_VOLSLIDEUP;
00149 m->vol = (p->vol & 0x0f);
00150 } else
00151 if ((p->vol >= 0xC0) && (p->vol <= 0xCF))
00152 {
00153 m->volcmd = VOLCMD_FINEVOLDOWN;
00154 m->vol = (p->vol & 0x0f);
00155 } else
00156 if ((p->vol >= 0xD0) && (p->vol <= 0xDF))
00157 {
00158 m->volcmd = VOLCMD_FINEVOLUP;
00159 m->vol = (p->vol & 0x0f);
00160 } else
00161 {
00162 m->volcmd = 0;
00163 m->vol = 0;
00164 }
00165
00166 m->command = 0;
00167 m->param = 0;
00168 if ((p->fxcmd) || (p->fxparam1) || (p->fxparam2))
00169 {
00170 if (!p->fxcmd)
00171 {
00172 m->command = p->fxparam2;
00173 m->param = p->fxparam1;
00174 that->ConvertModCommand(m);
00175 } else
00176 {
00177
00178 }
00179 }
00180 }
00181
00182
00183 BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength)
00184
00185 {
00186 MT2FILEHEADER *pfh = (MT2FILEHEADER *)lpStream;
00187 DWORD dwMemPos, dwDrumDataPos, dwExtraDataPos;
00188 UINT nDrumDataLen, nExtraDataLen;
00189 MT2DRUMSDATA *pdd;
00190 MT2INSTRUMENT *InstrMap[255];
00191 MT2SAMPLE *SampleMap[256];
00192
00193 if ((!lpStream) || (dwMemLength < sizeof(MT2FILEHEADER))
00194 || (pfh->dwMT20 != 0x3032544D)
00195 || (pfh->wVersion < 0x0200) || (pfh->wVersion >= 0x0300)
00196 || (pfh->wChannels < 4) || (pfh->wChannels > 64)) return FALSE;
00197 pdd = NULL;
00198 m_nType = MOD_TYPE_MT2;
00199 m_nChannels = pfh->wChannels;
00200 m_nRestartPos = pfh->wRestart;
00201 m_nDefaultSpeed = pfh->bTicksPerLine;
00202 m_nDefaultTempo = 125;
00203 if ((pfh->wSamplesPerTick > 100) && (pfh->wSamplesPerTick < 5000))
00204 {
00205 m_nDefaultTempo = 110250 / pfh->wSamplesPerTick;
00206 }
00207 for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++)
00208 {
00209 Order[iOrd] = (BYTE)((iOrd < pfh->nOrders) ? pfh->Orders[iOrd] : 0xFF);
00210 }
00211 memcpy(m_szNames[0], pfh->szSongName, 32);
00212 m_szNames[0][31] = 0;
00213 dwMemPos = sizeof(MT2FILEHEADER);
00214 nDrumDataLen = *(WORD *)(lpStream + dwMemPos);
00215 dwDrumDataPos = dwMemPos + 2;
00216 if (nDrumDataLen >= 2) pdd = (MT2DRUMSDATA *)(lpStream+dwDrumDataPos);
00217 dwMemPos += 2 + nDrumDataLen;
00218 #ifdef MT2DEBUG
00219
00220 Log("MT2 v%03X: \"%s\" (flags=%04X)\n", pfh->wVersion, m_szNames[0], pfh->fulFlags);
00221 Log("%d Channels, %d Patterns, %d Instruments, %d Samples\n", pfh->wChannels, pfh->wPatterns, pfh->wInstruments, pfh->wSamples);
00222 Log("Drum Data: %d bytes @%04X\n", nDrumDataLen, dwDrumDataPos);
00223 #endif
00224 if (dwMemPos >= dwMemLength-12) return TRUE;
00225 if (!*(DWORD *)(lpStream+dwMemPos)) dwMemPos += 4;
00226 if (!*(DWORD *)(lpStream+dwMemPos)) dwMemPos += 4;
00227 nExtraDataLen = *(DWORD *)(lpStream+dwMemPos);
00228 dwExtraDataPos = dwMemPos + 4;
00229 dwMemPos += 4;
00230 #ifdef MT2DEBUG
00231 Log("Extra Data: %d bytes @%04X\n", nExtraDataLen, dwExtraDataPos);
00232 #endif
00233 if (dwMemPos + nExtraDataLen >= dwMemLength) return TRUE;
00234 while (dwMemPos+8 < dwExtraDataPos + nExtraDataLen)
00235 {
00236 DWORD dwId = *(DWORD *)(lpStream+dwMemPos);
00237 DWORD dwLen = *(DWORD *)(lpStream+dwMemPos+4);
00238 dwMemPos += 8;
00239 if (dwMemPos + dwLen > dwMemLength) return TRUE;
00240 #ifdef MT2DEBUG
00241 CHAR s[5];
00242 memcpy(s, &dwId, 4);
00243 s[4] = 0;
00244 Log("pos=0x%04X: %s: %d bytes\n", dwMemPos-8, s, dwLen);
00245 #endif
00246 switch(dwId)
00247 {
00248
00249 case 0x0047534D:
00250 if ((dwLen > 3) && (!m_lpszSongComments))
00251 {
00252 DWORD nTxtLen = dwLen;
00253 if (nTxtLen > 32000) nTxtLen = 32000;
00254 m_lpszSongComments = new char[nTxtLen];
00255 if (m_lpszSongComments)
00256 {
00257 memcpy(m_lpszSongComments, lpStream+dwMemPos+1, nTxtLen-1);
00258 m_lpszSongComments[nTxtLen-1] = 0;
00259 }
00260 }
00261 break;
00262
00263
00264
00265 case 0x534b5254:
00266 break;
00267 }
00268 dwMemPos += dwLen;
00269 }
00270
00271 dwMemPos = dwExtraDataPos + nExtraDataLen;
00272 for (UINT iPat=0; iPat<pfh->wPatterns; iPat++) if (dwMemPos < dwMemLength-6)
00273 {
00274 MT2PATTERN *pmp = (MT2PATTERN *)(lpStream+dwMemPos);
00275 UINT wDataLen = (pmp->wDataLen + 1) & ~1;
00276 dwMemPos += 6;
00277 if (dwMemPos + wDataLen > dwMemLength) break;
00278 UINT nLines = pmp->wLines;
00279 if ((iPat < MAX_PATTERNS) && (nLines > 0) && (nLines <= 256))
00280 {
00281 #ifdef MT2DEBUG
00282 Log("Pattern #%d @%04X: %d lines, %d bytes\n", iPat, dwMemPos-6, nLines, pmp->wDataLen);
00283 #endif
00284 PatternSize[iPat] = nLines;
00285 Patterns[iPat] = AllocatePattern(nLines, m_nChannels);
00286 if (!Patterns[iPat]) return TRUE;
00287 MODCOMMAND *m = Patterns[iPat];
00288 UINT len = wDataLen;
00289 if (pfh->fulFlags & 1)
00290 {
00291 BYTE *p = (BYTE *)(lpStream+dwMemPos);
00292 UINT pos = 0, row=0, ch=0;
00293 while (pos < len)
00294 {
00295 MT2COMMAND cmd;
00296 UINT infobyte = p[pos++];
00297 UINT rptcount = 0;
00298 if (infobyte == 0xff)
00299 {
00300 rptcount = p[pos++];
00301 infobyte = p[pos++];
00302 #if 0
00303 Log("(%d.%d) FF(%02X).%02X\n", row, ch, rptcount, infobyte);
00304 } else
00305 {
00306 Log("(%d.%d) %02X\n", row, ch, infobyte);
00307 #endif
00308 }
00309 if (infobyte & 0x7f)
00310 {
00311 UINT patpos = row*m_nChannels+ch;
00312 cmd.note = cmd.instr = cmd.vol = cmd.pan = cmd.fxcmd = cmd.fxparam1 = cmd.fxparam2 = 0;
00313 if (infobyte & 1) cmd.note = p[pos++];
00314 if (infobyte & 2) cmd.instr = p[pos++];
00315 if (infobyte & 4) cmd.vol = p[pos++];
00316 if (infobyte & 8) cmd.pan = p[pos++];
00317 if (infobyte & 16) cmd.fxcmd = p[pos++];
00318 if (infobyte & 32) cmd.fxparam1 = p[pos++];
00319 if (infobyte & 64) cmd.fxparam2 = p[pos++];
00320 #ifdef MT2DEBUG
00321 if (cmd.fxcmd)
00322 {
00323 Log("(%d.%d) MT2 FX=%02X.%02X.%02X\n", row, ch, cmd.fxcmd, cmd.fxparam1, cmd.fxparam2);
00324 }
00325 #endif
00326 ConvertMT2Command(this, &m[patpos], &cmd);
00327 }
00328 row += rptcount+1;
00329 while (row >= nLines) { row-=nLines; ch++; }
00330 if (ch >= m_nChannels) break;
00331 }
00332 } else
00333 {
00334 MT2COMMAND *p = (MT2COMMAND *)(lpStream+dwMemPos);
00335 UINT n = 0;
00336 while ((len > sizeof(MT2COMMAND)) && (n < m_nChannels*nLines))
00337 {
00338 ConvertMT2Command(this, m, p);
00339 len -= sizeof(MT2COMMAND);
00340 n++;
00341 p++;
00342 m++;
00343 }
00344 }
00345 }
00346 dwMemPos += wDataLen;
00347 }
00348
00349 if (pdd)
00350 {
00351 #ifdef MT2DEBUG
00352 Log("%d Drum Patterns at offset 0x%08X\n", pdd->wDrumPatterns, dwMemPos);
00353 #endif
00354 for (UINT iDrm=0; iDrm<pdd->wDrumPatterns; iDrm++)
00355 {
00356 if (dwMemPos > dwMemLength-2) return TRUE;
00357 UINT nLines = *(WORD *)(lpStream+dwMemPos);
00358 #ifdef MT2DEBUG
00359 if (nLines != 64) Log("Drum Pattern %d: %d Lines @%04X\n", iDrm, nLines, dwMemPos);
00360 #endif
00361 dwMemPos += 2 + nLines * 32;
00362 }
00363 }
00364
00365 if (pfh->fulFlags & 2)
00366 {
00367 #ifdef MT2DEBUG
00368 Log("Automation at offset 0x%08X\n", dwMemPos);
00369 #endif
00370 UINT nAutoCount = m_nChannels;
00371 if (pfh->fulFlags & 0x10) nAutoCount++;
00372 if ((pfh->fulFlags & 0x08) && (pdd)) nAutoCount += 8;
00373 nAutoCount *= pfh->wPatterns;
00374 for (UINT iAuto=0; iAuto<nAutoCount; iAuto++)
00375 {
00376 if (dwMemPos+12 >= dwMemLength) return TRUE;
00377 MT2AUTOMATION *pma = (MT2AUTOMATION *)(lpStream+dwMemPos);
00378 dwMemPos += (pfh->wVersion <= 0x201) ? 4 : 8;
00379 for (UINT iEnv=0; iEnv<14; iEnv++)
00380 {
00381 if (pma->dwFlags & (1 << iEnv))
00382 {
00383 #ifdef MT2DEBUG
00384 UINT nPoints = *(DWORD *)(lpStream+dwMemPos);
00385 Log(" Env[%d/%d] %04X @%04X: %d points\n", iAuto, nAutoCount, 1 << iEnv, dwMemPos-8, nPoints);
00386 #endif
00387 dwMemPos += 260;
00388 }
00389 }
00390 }
00391 }
00392
00393 #ifdef MT2DEBUG
00394 Log("Loading instruments at offset 0x%08X\n", dwMemPos);
00395 #endif
00396 memset(InstrMap, 0, sizeof(InstrMap));
00397 m_nInstruments = (pfh->wInstruments < MAX_INSTRUMENTS) ? pfh->wInstruments : MAX_INSTRUMENTS-1;
00398 for (UINT iIns=1; iIns<=255; iIns++)
00399 {
00400 if (dwMemPos+36 > dwMemLength) return TRUE;
00401 MT2INSTRUMENT *pmi = (MT2INSTRUMENT *)(lpStream+dwMemPos);
00402 INSTRUMENTHEADER *penv = NULL;
00403 if (iIns <= m_nInstruments)
00404 {
00405 penv = new INSTRUMENTHEADER;
00406 Headers[iIns] = penv;
00407 if (penv)
00408 {
00409 memset(penv, 0, sizeof(INSTRUMENTHEADER));
00410 memcpy(penv->name, pmi->szName, 32);
00411 penv->nGlobalVol = 64;
00412 penv->nPan = 128;
00413 for (UINT i=0; i<120; i++)
00414 {
00415 penv->NoteMap[i] = i+1;
00416 }
00417 }
00418 }
00419 #ifdef MT2DEBUG
00420 if (iIns <= pfh->wInstruments) Log(" Instrument #%d at offset %04X: %d bytes\n", iIns, dwMemPos, pmi->dwDataLen);
00421 #endif
00422 if (((LONG)pmi->dwDataLen > 0) && (dwMemPos + pmi->dwDataLen + 40 <= dwMemLength))
00423 {
00424 InstrMap[iIns-1] = pmi;
00425 if (penv)
00426 {
00427 penv->nFadeOut = pmi->wFadeOut;
00428 penv->nNNA = pmi->wNNA & 3;
00429 penv->nDCT = (pmi->wNNA>>8) & 3;
00430 penv->nDNA = (pmi->wNNA>>12) & 3;
00431 MT2ENVELOPE *pehdr[4];
00432 WORD *pedata[4];
00433 if (pfh->wVersion <= 0x201)
00434 {
00435 DWORD dwEnvPos = dwMemPos + sizeof(MT2INSTRUMENT) - 4;
00436 pehdr[0] = (MT2ENVELOPE *)(lpStream+dwEnvPos);
00437 pehdr[1] = (MT2ENVELOPE *)(lpStream+dwEnvPos+8);
00438 pehdr[2] = pehdr[3] = NULL;
00439 pedata[0] = (WORD *)(lpStream+dwEnvPos+16);
00440 pedata[1] = (WORD *)(lpStream+dwEnvPos+16+64);
00441 pedata[2] = pedata[3] = NULL;
00442 } else
00443 {
00444 DWORD dwEnvPos = dwMemPos + sizeof(MT2INSTRUMENT);
00445 for (UINT i=0; i<4; i++)
00446 {
00447 if (pmi->wEnvFlags1 & (1<<i))
00448 {
00449 pehdr[i] = (MT2ENVELOPE *)(lpStream+dwEnvPos);
00450 pedata[i] = (WORD *)pehdr[i]->EnvData;
00451 dwEnvPos += sizeof(MT2ENVELOPE);
00452 } else
00453 {
00454 pehdr[i] = NULL;
00455 pedata[i] = NULL;
00456 }
00457 }
00458 }
00459
00460 for (UINT iEnv=0; iEnv<4; iEnv++) if (pehdr[iEnv])
00461 {
00462 MT2ENVELOPE *pme = pehdr[iEnv];
00463 WORD *pEnvPoints = NULL;
00464 BYTE *pEnvData = NULL;
00465 #ifdef MT2DEBUG
00466 Log(" Env %d.%d @%04X: %d points\n", iIns, iEnv, (UINT)(((BYTE *)pme)-lpStream), pme->nPoints);
00467 #endif
00468 switch(iEnv)
00469 {
00470
00471 case 0:
00472 if (pme->nFlags & 1) penv->dwFlags |= ENV_VOLUME;
00473 if (pme->nFlags & 2) penv->dwFlags |= ENV_VOLSUSTAIN;
00474 if (pme->nFlags & 4) penv->dwFlags |= ENV_VOLLOOP;
00475 penv->nVolEnv = (pme->nPoints > 16) ? 16 : pme->nPoints;
00476 penv->nVolSustainBegin = penv->nVolSustainEnd = pme->nSustainPos;
00477 penv->nVolLoopStart = pme->nLoopStart;
00478 penv->nVolLoopEnd = pme->nLoopEnd;
00479 pEnvPoints = penv->VolPoints;
00480 pEnvData = penv->VolEnv;
00481 break;
00482
00483
00484 case 1:
00485 if (pme->nFlags & 1) penv->dwFlags |= ENV_PANNING;
00486 if (pme->nFlags & 2) penv->dwFlags |= ENV_PANSUSTAIN;
00487 if (pme->nFlags & 4) penv->dwFlags |= ENV_PANLOOP;
00488 penv->nPanEnv = (pme->nPoints > 16) ? 16 : pme->nPoints;
00489 penv->nPanSustainBegin = penv->nPanSustainEnd = pme->nSustainPos;
00490 penv->nPanLoopStart = pme->nLoopStart;
00491 penv->nPanLoopEnd = pme->nLoopEnd;
00492 pEnvPoints = penv->PanPoints;
00493 pEnvData = penv->PanEnv;
00494 break;
00495
00496
00497 default:
00498 if (pme->nFlags & 1) penv->dwFlags |= (iEnv==3) ? (ENV_PITCH|ENV_FILTER) : ENV_PITCH;
00499 if (pme->nFlags & 2) penv->dwFlags |= ENV_PITCHSUSTAIN;
00500 if (pme->nFlags & 4) penv->dwFlags |= ENV_PITCHLOOP;
00501 penv->nPitchEnv = (pme->nPoints > 16) ? 16 : pme->nPoints;
00502 penv->nPitchSustainBegin = penv->nPitchSustainEnd = pme->nSustainPos;
00503 penv->nPitchLoopStart = pme->nLoopStart;
00504 penv->nPitchLoopEnd = pme->nLoopEnd;
00505 pEnvPoints = penv->PitchPoints;
00506 pEnvData = penv->PitchEnv;
00507 }
00508
00509 if ((pEnvPoints) && (pEnvData) && (pedata[iEnv]))
00510 {
00511 WORD *psrc = pedata[iEnv];
00512 for (UINT i=0; i<16; i++)
00513 {
00514 pEnvPoints[i] = psrc[i*2];
00515 pEnvData[i] = (BYTE)psrc[i*2+1];
00516 }
00517 }
00518 }
00519 }
00520 dwMemPos += pmi->dwDataLen + 36;
00521 if (pfh->wVersion > 0x201) dwMemPos += 4;
00522 } else
00523 {
00524 dwMemPos += 36;
00525 }
00526 }
00527 #ifdef MT2DEBUG
00528 Log("Loading samples at offset 0x%08X\n", dwMemPos);
00529 #endif
00530 memset(SampleMap, 0, sizeof(SampleMap));
00531 m_nSamples = (pfh->wSamples < MAX_SAMPLES) ? pfh->wSamples : MAX_SAMPLES-1;
00532 for (UINT iSmp=1; iSmp<=256; iSmp++)
00533 {
00534 if (dwMemPos+36 > dwMemLength) return TRUE;
00535 MT2SAMPLE *pms = (MT2SAMPLE *)(lpStream+dwMemPos);
00536 #ifdef MT2DEBUG
00537 if (iSmp <= m_nSamples) Log(" Sample #%d at offset %04X: %d bytes\n", iSmp, dwMemPos, pms->dwDataLen);
00538 #endif
00539 if (iSmp < MAX_SAMPLES)
00540 {
00541 memcpy(m_szNames[iSmp], pms->szName, 32);
00542 }
00543 if (pms->dwDataLen > 0)
00544 {
00545 SampleMap[iSmp-1] = pms;
00546 if (iSmp < MAX_SAMPLES)
00547 {
00548 MODINSTRUMENT *psmp = &Ins[iSmp];
00549 psmp->nGlobalVol = 64;
00550 psmp->nVolume = (pms->wVolume >> 7);
00551 psmp->nPan = (pms->nPan == 0x80) ? 128 : (pms->nPan^0x80);
00552 psmp->nLength = pms->dwLength;
00553 psmp->nC4Speed = pms->dwFrequency;
00554 psmp->nLoopStart = pms->dwLoopStart;
00555 psmp->nLoopEnd = pms->dwLoopEnd;
00556 FrequencyToTranspose(psmp);
00557 psmp->RelativeTone -= pms->nBaseNote - 49;
00558 psmp->nC4Speed = TransposeToFrequency(psmp->RelativeTone, psmp->nFineTune);
00559 if (pms->nQuality == 2) { psmp->uFlags |= CHN_16BIT; psmp->nLength >>= 1; }
00560 if (pms->nChannels == 2) { psmp->nLength >>= 1; }
00561 if (pms->nLoop == 1) psmp->uFlags |= CHN_LOOP;
00562 if (pms->nLoop == 2) psmp->uFlags |= CHN_LOOP|CHN_PINGPONGLOOP;
00563 }
00564 dwMemPos += pms->dwDataLen + 36;
00565 } else
00566 {
00567 dwMemPos += 36;
00568 }
00569 }
00570 #ifdef MT2DEBUG
00571 Log("Loading groups at offset 0x%08X\n", dwMemPos);
00572 #endif
00573 for (UINT iMap=0; iMap<255; iMap++) if (InstrMap[iMap])
00574 {
00575 if (dwMemPos+8 > dwMemLength) return TRUE;
00576 MT2INSTRUMENT *pmi = InstrMap[iMap];
00577 INSTRUMENTHEADER *penv = NULL;
00578 if (iMap<m_nInstruments) penv = Headers[iMap+1];
00579 for (UINT iGrp=0; iGrp<pmi->wSamples; iGrp++)
00580 {
00581 if (penv)
00582 {
00583 MT2GROUP *pmg = (MT2GROUP *)(lpStream+dwMemPos);
00584 for (UINT i=0; i<96; i++)
00585 {
00586 if (pmi->GroupsMapping[i] == iGrp)
00587 {
00588 UINT nSmp = pmg->nSmpNo+1;
00589 penv->Keyboard[i+12] = (BYTE)nSmp;
00590 if (nSmp <= m_nSamples)
00591 {
00592 Ins[nSmp].nVibType = pmi->bVibType;
00593 Ins[nSmp].nVibSweep = pmi->bVibSweep;
00594 Ins[nSmp].nVibDepth = pmi->bVibDepth;
00595 Ins[nSmp].nVibRate = pmi->bVibRate;
00596 }
00597 }
00598 }
00599 }
00600 dwMemPos += 8;
00601 }
00602 }
00603 #ifdef MT2DEBUG
00604 Log("Loading sample data at offset 0x%08X\n", dwMemPos);
00605 #endif
00606 for (UINT iData=0; iData<256; iData++) if ((iData < m_nSamples) && (SampleMap[iData]))
00607 {
00608 MT2SAMPLE *pms = SampleMap[iData];
00609 MODINSTRUMENT *psmp = &Ins[iData+1];
00610 if (!(pms->nFlags & 5))
00611 {
00612 if (psmp->nLength > 0)
00613 {
00614 #ifdef MT2DEBUG
00615 Log(" Reading sample #%d at offset 0x%04X (len=%d)\n", iData+1, dwMemPos, psmp->nLength);
00616 #endif
00617 UINT rsflags;
00618
00619 if (pms->nChannels == 2)
00620 rsflags = (psmp->uFlags & CHN_16BIT) ? RS_STPCM16D : RS_STPCM8D;
00621 else
00622 rsflags = (psmp->uFlags & CHN_16BIT) ? RS_PCM16D : RS_PCM8D;
00623
00624 dwMemPos += ReadSample(psmp, rsflags, (LPCSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos);
00625 }
00626 } else
00627 if (dwMemPos+4 < dwMemLength)
00628 {
00629 UINT nNameLen = *(DWORD *)(lpStream+dwMemPos);
00630 dwMemPos += nNameLen + 16;
00631 }
00632 if (dwMemPos+4 >= dwMemLength) break;
00633 }
00634 return TRUE;
00635 }