00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
00013 #include "stdafx.h"
00014 #include "sndfile.h"
00015
00016
00017
00018 typedef struct MDLSONGHEADER
00019 {
00020 DWORD id;
00021 BYTE version;
00022 } Q_PACKED MDLSONGHEADER;
00023
00024
00025 typedef struct MDLINFOBLOCK
00026 {
00027 CHAR songname[32];
00028 CHAR composer[20];
00029 WORD norders;
00030 WORD repeatpos;
00031 BYTE globalvol;
00032 BYTE speed;
00033 BYTE tempo;
00034 BYTE channelinfo[32];
00035 BYTE seq[256];
00036 } Q_PACKED MDLINFOBLOCK;
00037
00038
00039 typedef struct MDLPATTERNDATA
00040 {
00041 BYTE channels;
00042 BYTE lastrow;
00043 CHAR name[16];
00044 WORD data[1];
00045 } Q_PACKED MDLPATTERNDATA;
00046
00047
00048 void ConvertMDLCommand(MODCOMMAND *m, UINT eff, UINT data)
00049
00050 {
00051 UINT command = 0, param = data;
00052 switch(eff)
00053 {
00054 case 0x01: command = CMD_PORTAMENTOUP; break;
00055 case 0x02: command = CMD_PORTAMENTODOWN; break;
00056 case 0x03: command = CMD_TONEPORTAMENTO; break;
00057 case 0x04: command = CMD_VIBRATO; break;
00058 case 0x05: command = CMD_ARPEGGIO; break;
00059 case 0x07: command = (param < 0x20) ? CMD_SPEED : CMD_TEMPO; break;
00060 case 0x08: command = CMD_PANNING8; param <<= 1; break;
00061 case 0x0B: command = CMD_POSITIONJUMP; break;
00062 case 0x0C: command = CMD_GLOBALVOLUME; break;
00063 case 0x0D: command = CMD_PATTERNBREAK; param = (data & 0x0F) + (data>>4)*10; break;
00064 case 0x0E:
00065 command = CMD_S3MCMDEX;
00066 switch(data & 0xF0)
00067 {
00068 case 0x00: command = 0; break;
00069 case 0x10: if (param & 0x0F) { param |= 0xF0; command = CMD_PANNINGSLIDE; } else command = 0; break;
00070 case 0x20: if (param & 0x0F) { param = (param << 4) | 0x0F; command = CMD_PANNINGSLIDE; } else command = 0; break;
00071 case 0x30: param = (data & 0x0F) | 0x10; break;
00072 case 0x40: param = (data & 0x0F) | 0x30; break;
00073 case 0x60: param = (data & 0x0F) | 0xB0; break;
00074 case 0x70: param = (data & 0x0F) | 0x40; break;
00075 case 0x90: command = CMD_RETRIG; param &= 0x0F; break;
00076 case 0xA0: param = (data & 0x0F) << 4; command = CMD_GLOBALVOLSLIDE; break;
00077 case 0xB0: param = data & 0x0F; command = CMD_GLOBALVOLSLIDE; break;
00078 case 0xF0: param = ((data >> 8) & 0x0F) | 0xA0; break;
00079 }
00080 break;
00081 case 0x0F: command = CMD_SPEED; break;
00082 case 0x10: if ((param & 0xF0) != 0xE0) { command = CMD_VOLUMESLIDE; if ((param & 0xF0) == 0xF0) param = ((param << 4) | 0x0F); else param >>= 2; } break;
00083 case 0x20: if ((param & 0xF0) != 0xE0) { command = CMD_VOLUMESLIDE; if ((param & 0xF0) != 0xF0) param >>= 2; } break;
00084 case 0x30: command = CMD_RETRIG; break;
00085 case 0x40: command = CMD_TREMOLO; break;
00086 case 0x50: command = CMD_TREMOR; break;
00087 case 0xEF: if (param > 0xFF) param = 0xFF; command = CMD_OFFSET; break;
00088 }
00089 if (command)
00090 {
00091 m->command = command;
00092 m->param = param;
00093 }
00094 }
00095
00096
00097 void UnpackMDLTrack(MODCOMMAND *pat, UINT nChannels, UINT nRows, UINT nTrack, const BYTE *lpTracks)
00098
00099 {
00100 MODCOMMAND cmd, *m = pat;
00101 UINT len = *((WORD *)lpTracks);
00102 UINT pos = 0, row = 0, i;
00103 lpTracks += 2;
00104 for (UINT ntrk=1; ntrk<nTrack; ntrk++)
00105 {
00106 lpTracks += len;
00107 len = *((WORD *)lpTracks);
00108 lpTracks += 2;
00109 }
00110 cmd.note = cmd.instr = 0;
00111 cmd.volcmd = cmd.vol = 0;
00112 cmd.command = cmd.param = 0;
00113 while ((row < nRows) && (pos < len))
00114 {
00115 UINT xx;
00116 BYTE b = lpTracks[pos++];
00117 xx = b >> 2;
00118 switch(b & 0x03)
00119 {
00120 case 0x01:
00121 for (i=0; i<=xx; i++)
00122 {
00123 if (row) *m = *(m-nChannels);
00124 m += nChannels;
00125 row++;
00126 if (row >= nRows) break;
00127 }
00128 break;
00129
00130 case 0x02:
00131 if (xx < row) *m = pat[nChannels*xx];
00132 m += nChannels;
00133 row++;
00134 break;
00135
00136 case 0x03:
00137 {
00138 cmd.note = (xx & 0x01) ? lpTracks[pos++] : 0;
00139 cmd.instr = (xx & 0x02) ? lpTracks[pos++] : 0;
00140 cmd.volcmd = cmd.vol = 0;
00141 cmd.command = cmd.param = 0;
00142 if ((cmd.note < 120-12) && (cmd.note)) cmd.note += 12;
00143 UINT volume = (xx & 0x04) ? lpTracks[pos++] : 0;
00144 UINT commands = (xx & 0x08) ? lpTracks[pos++] : 0;
00145 UINT command1 = commands & 0x0F;
00146 UINT command2 = commands & 0xF0;
00147 UINT param1 = (xx & 0x10) ? lpTracks[pos++] : 0;
00148 UINT param2 = (xx & 0x20) ? lpTracks[pos++] : 0;
00149 if ((command1 == 0x0E) && ((param1 & 0xF0) == 0xF0) && (!command2))
00150 {
00151 param1 = ((param1 & 0x0F) << 8) | param2;
00152 command1 = 0xEF;
00153 command2 = param2 = 0;
00154 }
00155 if (volume)
00156 {
00157 cmd.volcmd = VOLCMD_VOLUME;
00158 cmd.vol = (volume+1) >> 2;
00159 }
00160 ConvertMDLCommand(&cmd, command1, param1);
00161 if ((cmd.command != CMD_SPEED)
00162 && (cmd.command != CMD_TEMPO)
00163 && (cmd.command != CMD_PATTERNBREAK))
00164 ConvertMDLCommand(&cmd, command2, param2);
00165 *m = cmd;
00166 m += nChannels;
00167 row++;
00168 }
00169 break;
00170
00171
00172 default:
00173 row += xx+1;
00174 m += (xx+1)*nChannels;
00175 if (row >= nRows) break;
00176 }
00177 }
00178 }
00179
00180
00181
00182 BOOL CSoundFile::ReadMDL(const BYTE *lpStream, DWORD dwMemLength)
00183
00184 {
00185 DWORD dwMemPos, dwPos, blocklen, dwTrackPos;
00186 const MDLSONGHEADER *pmsh = (const MDLSONGHEADER *)lpStream;
00187 MDLINFOBLOCK *pmib;
00188 MDLPATTERNDATA *pmpd;
00189 UINT i,j, norders = 0, npatterns = 0, ntracks = 0;
00190 UINT ninstruments = 0, nsamples = 0;
00191 WORD block;
00192 WORD patterntracks[MAX_PATTERNS*32];
00193 BYTE smpinfo[MAX_SAMPLES];
00194 BYTE insvolenv[MAX_INSTRUMENTS];
00195 BYTE inspanenv[MAX_INSTRUMENTS];
00196 LPCBYTE pvolenv, ppanenv, ppitchenv;
00197 UINT nvolenv, npanenv, npitchenv;
00198
00199 if ((!lpStream) || (dwMemLength < 1024)) return FALSE;
00200 if ((pmsh->id != 0x4C444D44) || ((pmsh->version & 0xF0) > 0x10)) return FALSE;
00201 memset(patterntracks, 0, sizeof(patterntracks));
00202 memset(smpinfo, 0, sizeof(smpinfo));
00203 memset(insvolenv, 0, sizeof(insvolenv));
00204 memset(inspanenv, 0, sizeof(inspanenv));
00205 dwMemPos = 5;
00206 dwTrackPos = 0;
00207 pvolenv = ppanenv = ppitchenv = NULL;
00208 nvolenv = npanenv = npitchenv = 0;
00209 m_nSamples = m_nInstruments = 0;
00210 while (dwMemPos+6 < dwMemLength)
00211 {
00212 block = *((WORD *)(lpStream+dwMemPos));
00213 blocklen = *((DWORD *)(lpStream+dwMemPos+2));
00214 dwMemPos += 6;
00215 if (dwMemPos + blocklen > dwMemLength)
00216 {
00217 if (dwMemPos == 11) return FALSE;
00218 break;
00219 }
00220 switch(block)
00221 {
00222
00223 case 0x4E49:
00224 pmib = (MDLINFOBLOCK *)(lpStream+dwMemPos);
00225 memcpy(m_szNames[0], pmib->songname, 32);
00226 norders = pmib->norders;
00227 if (norders > MAX_ORDERS) norders = MAX_ORDERS;
00228 m_nRestartPos = pmib->repeatpos;
00229 m_nDefaultGlobalVolume = pmib->globalvol;
00230 m_nDefaultTempo = pmib->tempo;
00231 m_nDefaultSpeed = pmib->speed;
00232 m_nChannels = 4;
00233 for (i=0; i<32; i++)
00234 {
00235 ChnSettings[i].nVolume = 64;
00236 ChnSettings[i].nPan = (pmib->channelinfo[i] & 0x7F) << 1;
00237 if (pmib->channelinfo[i] & 0x80)
00238 ChnSettings[i].dwFlags |= CHN_MUTE;
00239 else
00240 m_nChannels = i+1;
00241 }
00242 for (j=0; j<norders; j++) Order[j] = pmib->seq[j];
00243 break;
00244
00245 case 0x454D:
00246 if (blocklen)
00247 {
00248 if (m_lpszSongComments) delete m_lpszSongComments;
00249 m_lpszSongComments = new char[blocklen];
00250 if (m_lpszSongComments)
00251 {
00252 memcpy(m_lpszSongComments, lpStream+dwMemPos, blocklen);
00253 m_lpszSongComments[blocklen-1] = 0;
00254 }
00255 }
00256 break;
00257
00258 case 0x4150:
00259 npatterns = lpStream[dwMemPos];
00260 if (npatterns > MAX_PATTERNS) npatterns = MAX_PATTERNS;
00261 dwPos = dwMemPos + 1;
00262 for (i=0; i<npatterns; i++)
00263 {
00264 if (dwPos+18 >= dwMemLength) break;
00265 pmpd = (MDLPATTERNDATA *)(lpStream + dwPos);
00266 if (pmpd->channels > 32) break;
00267 PatternSize[i] = pmpd->lastrow+1;
00268 if (m_nChannels < pmpd->channels) m_nChannels = pmpd->channels;
00269 dwPos += 18 + 2*pmpd->channels;
00270 for (j=0; j<pmpd->channels; j++)
00271 {
00272 patterntracks[i*32+j] = pmpd->data[j];
00273 }
00274 }
00275 break;
00276
00277 case 0x5254:
00278 if (dwTrackPos) break;
00279 ntracks = *((WORD *)(lpStream+dwMemPos));
00280 dwTrackPos = dwMemPos+2;
00281 break;
00282
00283 case 0x4949:
00284 ninstruments = lpStream[dwMemPos];
00285 dwPos = dwMemPos+1;
00286 for (i=0; i<ninstruments; i++)
00287 {
00288 UINT nins = lpStream[dwPos];
00289 if ((nins >= MAX_INSTRUMENTS) || (!nins)) break;
00290 if (m_nInstruments < nins) m_nInstruments = nins;
00291 if (!Headers[nins])
00292 {
00293 UINT note = 12;
00294 if ((Headers[nins] = new INSTRUMENTHEADER) == NULL) break;
00295 INSTRUMENTHEADER *penv = Headers[nins];
00296 memset(penv, 0, sizeof(INSTRUMENTHEADER));
00297 memcpy(penv->name, lpStream+dwPos+2, 32);
00298 penv->nGlobalVol = 64;
00299 penv->nPPC = 5*12;
00300 for (j=0; j<lpStream[dwPos+1]; j++)
00301 {
00302 const BYTE *ps = lpStream+dwPos+34+14*j;
00303 while ((note < (UINT)(ps[1]+12)) && (note < 120))
00304 {
00305 penv->NoteMap[note] = note+1;
00306 if (ps[0] < MAX_SAMPLES)
00307 {
00308 int ismp = ps[0];
00309 penv->Keyboard[note] = ps[0];
00310 Ins[ismp].nVolume = ps[2];
00311 Ins[ismp].nPan = ps[4] << 1;
00312 Ins[ismp].nVibType = ps[11];
00313 Ins[ismp].nVibSweep = ps[10];
00314 Ins[ismp].nVibDepth = ps[9];
00315 Ins[ismp].nVibRate = ps[8];
00316 }
00317 penv->nFadeOut = (ps[7] << 8) | ps[6];
00318 if (penv->nFadeOut == 0xFFFF) penv->nFadeOut = 0;
00319 note++;
00320 }
00321
00322 if (ps[3] & 0x80)
00323 {
00324 penv->dwFlags |= ENV_VOLUME;
00325 insvolenv[nins] = (ps[3] & 0x3F) + 1;
00326 }
00327
00328 if (ps[5] & 0x80)
00329 {
00330 penv->dwFlags |= ENV_PANNING;
00331 inspanenv[nins] = (ps[5] & 0x3F) + 1;
00332 }
00333 }
00334 }
00335 dwPos += 34 + 14*lpStream[dwPos+1];
00336 }
00337 for (j=1; j<=m_nInstruments; j++) if (!Headers[j])
00338 {
00339 Headers[j] = new INSTRUMENTHEADER;
00340 if (Headers[j]) memset(Headers[j], 0, sizeof(INSTRUMENTHEADER));
00341 }
00342 break;
00343
00344 case 0x4556:
00345 if ((nvolenv = lpStream[dwMemPos]) == 0) break;
00346 if (dwMemPos + nvolenv*32 + 1 <= dwMemLength) pvolenv = lpStream + dwMemPos + 1;
00347 break;
00348
00349 case 0x4550:
00350 if ((npanenv = lpStream[dwMemPos]) == 0) break;
00351 if (dwMemPos + npanenv*32 + 1 <= dwMemLength) ppanenv = lpStream + dwMemPos + 1;
00352 break;
00353
00354 case 0x4546:
00355 if ((npitchenv = lpStream[dwMemPos]) == 0) break;
00356 if (dwMemPos + npitchenv*32 + 1 <= dwMemLength) ppitchenv = lpStream + dwMemPos + 1;
00357 break;
00358
00359 case 0x5349:
00360 nsamples = lpStream[dwMemPos];
00361 dwPos = dwMemPos+1;
00362 for (i=0; i<nsamples; i++, dwPos += 59)
00363 {
00364 UINT nins = lpStream[dwPos];
00365 if ((nins >= MAX_SAMPLES) || (!nins)) continue;
00366 if (m_nSamples < nins) m_nSamples = nins;
00367 MODINSTRUMENT *pins = &Ins[nins];
00368 memcpy(m_szNames[nins], lpStream+dwPos+1, 32);
00369 memcpy(pins->name, lpStream+dwPos+33, 8);
00370 pins->nC4Speed = *((DWORD *)(lpStream+dwPos+41));
00371 pins->nLength = *((DWORD *)(lpStream+dwPos+45));
00372 pins->nLoopStart = *((DWORD *)(lpStream+dwPos+49));
00373 pins->nLoopEnd = pins->nLoopStart + *((DWORD *)(lpStream+dwPos+53));
00374 if (pins->nLoopEnd > pins->nLoopStart) pins->uFlags |= CHN_LOOP;
00375 pins->nGlobalVol = 64;
00376 if (lpStream[dwPos+58] & 0x01)
00377 {
00378 pins->uFlags |= CHN_16BIT;
00379 pins->nLength >>= 1;
00380 pins->nLoopStart >>= 1;
00381 pins->nLoopEnd >>= 1;
00382 }
00383 if (lpStream[dwPos+58] & 0x02) pins->uFlags |= CHN_PINGPONGLOOP;
00384 smpinfo[nins] = (lpStream[dwPos+58] >> 2) & 3;
00385 }
00386 break;
00387
00388 case 0x4153:
00389 dwPos = dwMemPos;
00390 for (i=1; i<=m_nSamples; i++) if ((Ins[i].nLength) && (!Ins[i].pSample) && (smpinfo[i] != 3) && (dwPos < dwMemLength))
00391 {
00392 MODINSTRUMENT *pins = &Ins[i];
00393 UINT flags = (pins->uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S;
00394 if (!smpinfo[i])
00395 {
00396 dwPos += ReadSample(pins, flags, (LPSTR)(lpStream+dwPos), dwMemLength - dwPos);
00397 } else
00398 {
00399 DWORD dwLen = *((DWORD *)(lpStream+dwPos));
00400 dwPos += 4;
00401 if ((dwPos+dwLen <= dwMemLength) && (dwLen > 4))
00402 {
00403 flags = (pins->uFlags & CHN_16BIT) ? RS_MDL16 : RS_MDL8;
00404 ReadSample(pins, flags, (LPSTR)(lpStream+dwPos), dwLen);
00405 }
00406 dwPos += dwLen;
00407 }
00408 }
00409 break;
00410 }
00411 dwMemPos += blocklen;
00412 }
00413
00414 if ((dwTrackPos) && (npatterns) && (m_nChannels) && (ntracks))
00415 {
00416 for (UINT ipat=0; ipat<npatterns; ipat++)
00417 {
00418 if ((Patterns[ipat] = AllocatePattern(PatternSize[ipat], m_nChannels)) == NULL) break;
00419 for (UINT chn=0; chn<m_nChannels; chn++) if ((patterntracks[ipat*32+chn]) && (patterntracks[ipat*32+chn] <= ntracks))
00420 {
00421 MODCOMMAND *m = Patterns[ipat] + chn;
00422 UnpackMDLTrack(m, m_nChannels, PatternSize[ipat], patterntracks[ipat*32+chn], lpStream+dwTrackPos);
00423 }
00424 }
00425 }
00426
00427 for (UINT iIns=1; iIns<=m_nInstruments; iIns++) if (Headers[iIns])
00428 {
00429 INSTRUMENTHEADER *penv = Headers[iIns];
00430
00431 if ((nvolenv) && (pvolenv) && (insvolenv[iIns]))
00432 {
00433 LPCBYTE pve = pvolenv;
00434 for (UINT nve=0; nve<nvolenv; nve++, pve+=33) if (pve[0]+1 == insvolenv[iIns])
00435 {
00436 WORD vtick = 1;
00437 penv->nVolEnv = 15;
00438 for (UINT iv=0; iv<15; iv++)
00439 {
00440 if (iv) vtick += pve[iv*2+1];
00441 penv->VolPoints[iv] = vtick;
00442 penv->VolEnv[iv] = pve[iv*2+2];
00443 if (!pve[iv*2+1])
00444 {
00445 penv->nVolEnv = iv+1;
00446 break;
00447 }
00448 }
00449 penv->nVolSustainBegin = penv->nVolSustainEnd = pve[31] & 0x0F;
00450 if (pve[31] & 0x10) penv->dwFlags |= ENV_VOLSUSTAIN;
00451 if (pve[31] & 0x20) penv->dwFlags |= ENV_VOLLOOP;
00452 penv->nVolLoopStart = pve[32] & 0x0F;
00453 penv->nVolLoopEnd = pve[32] >> 4;
00454 }
00455 }
00456
00457 if ((npanenv) && (ppanenv) && (inspanenv[iIns]))
00458 {
00459 LPCBYTE ppe = ppanenv;
00460 for (UINT npe=0; npe<npanenv; npe++, ppe+=33) if (ppe[0]+1 == inspanenv[iIns])
00461 {
00462 WORD vtick = 1;
00463 penv->nPanEnv = 15;
00464 for (UINT iv=0; iv<15; iv++)
00465 {
00466 if (iv) vtick += ppe[iv*2+1];
00467 penv->PanPoints[iv] = vtick;
00468 penv->PanEnv[iv] = ppe[iv*2+2];
00469 if (!ppe[iv*2+1])
00470 {
00471 penv->nPanEnv = iv+1;
00472 break;
00473 }
00474 }
00475 if (ppe[31] & 0x10) penv->dwFlags |= ENV_PANSUSTAIN;
00476 if (ppe[31] & 0x20) penv->dwFlags |= ENV_PANLOOP;
00477 penv->nPanLoopStart = ppe[32] & 0x0F;
00478 penv->nPanLoopEnd = ppe[32] >> 4;
00479 }
00480 }
00481 }
00482 m_dwSongFlags |= SONG_LINEARSLIDES;
00483 m_nType = MOD_TYPE_MDL;
00484 return TRUE;
00485 }
00486
00487
00489
00490
00491
00492 WORD MDLReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n)
00493
00494 {
00495 WORD v = (WORD)(bitbuf & ((1 << n) - 1) );
00496 bitbuf >>= n;
00497 bitnum -= n;
00498 if (bitnum <= 24)
00499 {
00500 bitbuf |= (((DWORD)(*ibuf++)) << bitnum);
00501 bitnum += 8;
00502 }
00503 return v;
00504 }
00505
00506