00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "stdafx.h"
00012 #include "sndfile.h"
00013 #include "it_defs.h"
00014
00015 #ifdef WIN32
00016 #pragma warning(disable:4244)
00017 #endif
00018
00019 const BYTE autovibit2xm[8] =
00020 { 0, 3, 1, 4, 2, 0, 0, 0 };
00021
00022 const BYTE autovibxm2it[8] =
00023 { 0, 2, 4, 1, 3, 0, 0, 0 };
00024
00026
00027
00028
00029 static inline UINT ConvertVolParam(UINT value)
00030
00031 {
00032 return (value > 9) ? 9 : value;
00033 }
00034
00035
00036 BOOL CSoundFile::ITInstrToMPT(const void *p, INSTRUMENTHEADER *penv, UINT trkvers)
00037
00038 {
00039 if (trkvers < 0x0200)
00040 {
00041 const ITOLDINSTRUMENT *pis = (const ITOLDINSTRUMENT *)p;
00042 memcpy(penv->name, pis->name, 26);
00043 memcpy(penv->filename, pis->filename, 12);
00044 penv->nFadeOut = bswapLE16(pis->fadeout) << 6;
00045 penv->nGlobalVol = 64;
00046 for (UINT j=0; j<120; j++)
00047 {
00048 UINT note = pis->keyboard[j*2];
00049 UINT ins = pis->keyboard[j*2+1];
00050 if (ins < MAX_SAMPLES) penv->Keyboard[j] = ins;
00051 if (note < 128) penv->NoteMap[j] = note+1;
00052 else if (note >= 0xFE) penv->NoteMap[j] = note;
00053 }
00054 if (pis->flags & 0x01) penv->dwFlags |= ENV_VOLUME;
00055 if (pis->flags & 0x02) penv->dwFlags |= ENV_VOLLOOP;
00056 if (pis->flags & 0x04) penv->dwFlags |= ENV_VOLSUSTAIN;
00057 penv->nVolLoopStart = pis->vls;
00058 penv->nVolLoopEnd = pis->vle;
00059 penv->nVolSustainBegin = pis->sls;
00060 penv->nVolSustainEnd = pis->sle;
00061 penv->nVolEnv = 25;
00062 for (UINT ev=0; ev<25; ev++)
00063 {
00064 if ((penv->VolPoints[ev] = pis->nodes[ev*2]) == 0xFF)
00065 {
00066 penv->nVolEnv = ev;
00067 break;
00068 }
00069 penv->VolEnv[ev] = pis->nodes[ev*2+1];
00070 }
00071 penv->nNNA = pis->nna;
00072 penv->nDCT = pis->dnc;
00073 penv->nPan = 0x80;
00074 } else
00075 {
00076 const ITINSTRUMENT *pis = (const ITINSTRUMENT *)p;
00077 memcpy(penv->name, pis->name, 26);
00078 memcpy(penv->filename, pis->filename, 12);
00079 penv->nMidiProgram = pis->mpr;
00080 penv->nMidiChannel = pis->mch;
00081 penv->wMidiBank = bswapLE16(pis->mbank);
00082 penv->nFadeOut = bswapLE16(pis->fadeout) << 5;
00083 penv->nGlobalVol = pis->gbv >> 1;
00084 if (penv->nGlobalVol > 64) penv->nGlobalVol = 64;
00085 for (UINT j=0; j<120; j++)
00086 {
00087 UINT note = pis->keyboard[j*2];
00088 UINT ins = pis->keyboard[j*2+1];
00089 if (ins < MAX_SAMPLES) penv->Keyboard[j] = ins;
00090 if (note < 128) penv->NoteMap[j] = note+1;
00091 else if (note >= 0xFE) penv->NoteMap[j] = note;
00092 }
00093
00094 if (pis->volenv.flags & 1) penv->dwFlags |= ENV_VOLUME;
00095 if (pis->volenv.flags & 2) penv->dwFlags |= ENV_VOLLOOP;
00096 if (pis->volenv.flags & 4) penv->dwFlags |= ENV_VOLSUSTAIN;
00097 if (pis->volenv.flags & 8) penv->dwFlags |= ENV_VOLCARRY;
00098 penv->nVolEnv = pis->volenv.num;
00099 if (penv->nVolEnv > 25) penv->nVolEnv = 25;
00100
00101 penv->nVolLoopStart = pis->volenv.lpb;
00102 penv->nVolLoopEnd = pis->volenv.lpe;
00103 penv->nVolSustainBegin = pis->volenv.slb;
00104 penv->nVolSustainEnd = pis->volenv.sle;
00105
00106 if (pis->panenv.flags & 1) penv->dwFlags |= ENV_PANNING;
00107 if (pis->panenv.flags & 2) penv->dwFlags |= ENV_PANLOOP;
00108 if (pis->panenv.flags & 4) penv->dwFlags |= ENV_PANSUSTAIN;
00109 if (pis->panenv.flags & 8) penv->dwFlags |= ENV_PANCARRY;
00110 penv->nPanEnv = pis->panenv.num;
00111 if (penv->nPanEnv > 25) penv->nPanEnv = 25;
00112 penv->nPanLoopStart = pis->panenv.lpb;
00113 penv->nPanLoopEnd = pis->panenv.lpe;
00114 penv->nPanSustainBegin = pis->panenv.slb;
00115 penv->nPanSustainEnd = pis->panenv.sle;
00116
00117 if (pis->pitchenv.flags & 1) penv->dwFlags |= ENV_PITCH;
00118 if (pis->pitchenv.flags & 2) penv->dwFlags |= ENV_PITCHLOOP;
00119 if (pis->pitchenv.flags & 4) penv->dwFlags |= ENV_PITCHSUSTAIN;
00120 if (pis->pitchenv.flags & 8) penv->dwFlags |= ENV_PITCHCARRY;
00121 if (pis->pitchenv.flags & 0x80) penv->dwFlags |= ENV_FILTER;
00122 penv->nPitchEnv = pis->pitchenv.num;
00123 if (penv->nPitchEnv > 25) penv->nPitchEnv = 25;
00124 penv->nPitchLoopStart = pis->pitchenv.lpb;
00125 penv->nPitchLoopEnd = pis->pitchenv.lpe;
00126 penv->nPitchSustainBegin = pis->pitchenv.slb;
00127 penv->nPitchSustainEnd = pis->pitchenv.sle;
00128
00129 for (UINT ev=0; ev<25; ev++)
00130 {
00131 penv->VolEnv[ev] = pis->volenv.data[ev*3];
00132 penv->VolPoints[ev] = (pis->volenv.data[ev*3+2] << 8) | (pis->volenv.data[ev*3+1]);
00133 penv->PanEnv[ev] = pis->panenv.data[ev*3] + 32;
00134 penv->PanPoints[ev] = (pis->panenv.data[ev*3+2] << 8) | (pis->panenv.data[ev*3+1]);
00135 penv->PitchEnv[ev] = pis->pitchenv.data[ev*3] + 32;
00136 penv->PitchPoints[ev] = (pis->pitchenv.data[ev*3+2] << 8) | (pis->pitchenv.data[ev*3+1]);
00137 }
00138 penv->nNNA = pis->nna;
00139 penv->nDCT = pis->dct;
00140 penv->nDNA = pis->dca;
00141 penv->nPPS = pis->pps;
00142 penv->nPPC = pis->ppc;
00143 penv->nIFC = pis->ifc;
00144 penv->nIFR = pis->ifr;
00145 penv->nVolSwing = pis->rv;
00146 penv->nPanSwing = pis->rp;
00147 penv->nPan = (pis->dfp & 0x7F) << 2;
00148 if (penv->nPan > 256) penv->nPan = 128;
00149 if (pis->dfp < 0x80) penv->dwFlags |= ENV_SETPANNING;
00150 }
00151 if ((penv->nVolLoopStart >= 25) || (penv->nVolLoopEnd >= 25)) penv->dwFlags &= ~ENV_VOLLOOP;
00152 if ((penv->nVolSustainBegin >= 25) || (penv->nVolSustainEnd >= 25)) penv->dwFlags &= ~ENV_VOLSUSTAIN;
00153 return TRUE;
00154 }
00155
00156
00157 BOOL CSoundFile::ReadIT(const BYTE *lpStream, DWORD dwMemLength)
00158
00159 {
00160 ITFILEHEADER pifh = *(ITFILEHEADER *)lpStream;
00161 DWORD dwMemPos = sizeof(ITFILEHEADER);
00162 DWORD inspos[MAX_INSTRUMENTS];
00163 DWORD smppos[MAX_SAMPLES];
00164 DWORD patpos[MAX_PATTERNS];
00165 BYTE chnmask[64], channels_used[64];
00166 MODCOMMAND lastvalue[64];
00167
00168 pifh.id = bswapLE32(pifh.id);
00169 pifh.reserved1 = bswapLE16(pifh.reserved1);
00170 pifh.ordnum = bswapLE16(pifh.ordnum);
00171 pifh.insnum = bswapLE16(pifh.insnum);
00172 pifh.smpnum = bswapLE16(pifh.smpnum);
00173 pifh.patnum = bswapLE16(pifh.patnum);
00174 pifh.cwtv = bswapLE16(pifh.cwtv);
00175 pifh.cmwt = bswapLE16(pifh.cmwt);
00176 pifh.flags = bswapLE16(pifh.flags);
00177 pifh.special = bswapLE16(pifh.special);
00178 pifh.msglength = bswapLE16(pifh.msglength);
00179 pifh.msgoffset = bswapLE32(pifh.msgoffset);
00180 pifh.reserved2 = bswapLE32(pifh.reserved2);
00181
00182 if ((!lpStream) || (dwMemLength < 0x100)) return FALSE;
00183 if ((pifh.id != 0x4D504D49) || (pifh.insnum >= MAX_INSTRUMENTS)
00184 || (!pifh.smpnum) || (pifh.smpnum >= MAX_INSTRUMENTS) || (!pifh.ordnum)) return FALSE;
00185 if (dwMemPos + pifh.ordnum + pifh.insnum*4
00186 + pifh.smpnum*4 + pifh.patnum*4 > dwMemLength) return FALSE;
00187 m_nType = MOD_TYPE_IT;
00188 if (pifh.flags & 0x08) m_dwSongFlags |= SONG_LINEARSLIDES;
00189 if (pifh.flags & 0x10) m_dwSongFlags |= SONG_ITOLDEFFECTS;
00190 if (pifh.flags & 0x20) m_dwSongFlags |= SONG_ITCOMPATMODE;
00191 if (pifh.flags & 0x80) m_dwSongFlags |= SONG_EMBEDMIDICFG;
00192 if (pifh.flags & 0x1000) m_dwSongFlags |= SONG_EXFILTERRANGE;
00193 memcpy(m_szNames[0], pifh.songname, 26);
00194 m_szNames[0][26] = 0;
00195
00196 if (pifh.globalvol)
00197 {
00198 m_nDefaultGlobalVolume = pifh.globalvol << 1;
00199 if (!m_nDefaultGlobalVolume) m_nDefaultGlobalVolume = 256;
00200 if (m_nDefaultGlobalVolume > 256) m_nDefaultGlobalVolume = 256;
00201 }
00202 if (pifh.speed) m_nDefaultSpeed = pifh.speed;
00203 if (pifh.tempo) m_nDefaultTempo = pifh.tempo;
00204 m_nSongPreAmp = pifh.mv & 0x7F;
00205
00206 for (int ipan=0; ipan<64; ipan++) if (pifh.chnpan[ipan] != 0xFF)
00207 {
00208 ChnSettings[ipan].nVolume = pifh.chnvol[ipan];
00209 ChnSettings[ipan].nPan = 128;
00210 if (pifh.chnpan[ipan] & 0x80) ChnSettings[ipan].dwFlags |= CHN_MUTE;
00211 UINT n = pifh.chnpan[ipan] & 0x7F;
00212 if (n <= 64) ChnSettings[ipan].nPan = n << 2;
00213 if (n == 100) ChnSettings[ipan].dwFlags |= CHN_SURROUND;
00214 }
00215 if (m_nChannels < 4) m_nChannels = 4;
00216
00217 if ((pifh.special & 0x01) && (pifh.msglength) && (pifh.msgoffset + pifh.msglength < dwMemLength))
00218 {
00219 m_lpszSongComments = new char[pifh.msglength+1];
00220 if (m_lpszSongComments)
00221 {
00222 memcpy(m_lpszSongComments, lpStream+pifh.msgoffset, pifh.msglength);
00223 m_lpszSongComments[pifh.msglength] = 0;
00224 }
00225 }
00226
00227 UINT nordsize = pifh.ordnum;
00228 if (nordsize > MAX_ORDERS) nordsize = MAX_ORDERS;
00229 memcpy(Order, lpStream+dwMemPos, nordsize);
00230 dwMemPos += pifh.ordnum;
00231
00232 memset(inspos, 0, sizeof(inspos));
00233 UINT inspossize = pifh.insnum;
00234 if (inspossize > MAX_INSTRUMENTS) inspossize = MAX_INSTRUMENTS;
00235 inspossize <<= 2;
00236 memcpy(inspos, lpStream+dwMemPos, inspossize);
00237 for (UINT j=0; j < (inspossize>>2); j++)
00238 {
00239 inspos[j] = bswapLE32(inspos[j]);
00240 }
00241 dwMemPos += pifh.insnum * 4;
00242
00243 memset(smppos, 0, sizeof(smppos));
00244 UINT smppossize = pifh.smpnum;
00245 if (smppossize > MAX_SAMPLES) smppossize = MAX_SAMPLES;
00246 smppossize <<= 2;
00247 memcpy(smppos, lpStream+dwMemPos, smppossize);
00248 for (UINT j=0; j < (smppossize>>2); j++)
00249 {
00250 smppos[j] = bswapLE32(smppos[j]);
00251 }
00252 dwMemPos += pifh.smpnum * 4;
00253
00254 memset(patpos, 0, sizeof(patpos));
00255 UINT patpossize = pifh.patnum;
00256 if (patpossize > MAX_PATTERNS) patpossize = MAX_PATTERNS;
00257 patpossize <<= 2;
00258 memcpy(patpos, lpStream+dwMemPos, patpossize);
00259 for (UINT j=0; j < (patpossize>>2); j++)
00260 {
00261 patpos[j] = bswapLE32(patpos[j]);
00262 }
00263 dwMemPos += pifh.patnum * 4;
00264
00265 if (dwMemPos + 2 < dwMemLength)
00266 {
00267 UINT nflt = bswapLE16(*((WORD *)(lpStream + dwMemPos)));
00268 dwMemPos += 2;
00269 if (dwMemPos + nflt * 8 < dwMemLength) dwMemPos += nflt * 8;
00270 }
00271
00272 if (m_dwSongFlags & SONG_EMBEDMIDICFG)
00273 {
00274 if (dwMemPos + sizeof(MODMIDICFG) < dwMemLength)
00275 {
00276 memcpy(&m_MidiCfg, lpStream+dwMemPos, sizeof(MODMIDICFG));
00277 dwMemPos += sizeof(MODMIDICFG);
00278 }
00279 }
00280
00281 if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e50))
00282 {
00283 UINT len = bswapLE32(*((DWORD *)(lpStream+dwMemPos+4)));
00284 dwMemPos += 8;
00285 if ((dwMemPos + len <= dwMemLength) && (len <= MAX_PATTERNS*MAX_PATTERNNAME) && (len >= MAX_PATTERNNAME))
00286 {
00287 m_lpszPatternNames = new char[len];
00288 if (m_lpszPatternNames)
00289 {
00290 m_nPatternNames = len / MAX_PATTERNNAME;
00291 memcpy(m_lpszPatternNames, lpStream+dwMemPos, len);
00292 }
00293 dwMemPos += len;
00294 }
00295 }
00296
00297 m_nChannels = 4;
00298
00299 if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e43))
00300 {
00301 UINT len = bswapLE32(*((DWORD *)(lpStream+dwMemPos+4)));
00302 dwMemPos += 8;
00303 if ((dwMemPos + len <= dwMemLength) && (len <= 64*MAX_CHANNELNAME))
00304 {
00305 UINT n = len / MAX_CHANNELNAME;
00306 if (n > m_nChannels) m_nChannels = n;
00307 for (UINT i=0; i<n; i++)
00308 {
00309 memcpy(ChnSettings[i].szName, (lpStream+dwMemPos+i*MAX_CHANNELNAME), MAX_CHANNELNAME);
00310 ChnSettings[i].szName[MAX_CHANNELNAME-1] = 0;
00311 }
00312 dwMemPos += len;
00313 }
00314 }
00315
00316 if (dwMemPos + 8 < dwMemLength)
00317 {
00318 dwMemPos += LoadMixPlugins(lpStream+dwMemPos, dwMemLength-dwMemPos);
00319 }
00320
00321 UINT npatterns = pifh.patnum;
00322 if (npatterns > MAX_PATTERNS) npatterns = MAX_PATTERNS;
00323 for (UINT patchk=0; patchk<npatterns; patchk++)
00324 {
00325 memset(chnmask, 0, sizeof(chnmask));
00326 if ((!patpos[patchk]) || ((DWORD)patpos[patchk] + 4 >= dwMemLength)) continue;
00327 UINT len = bswapLE16(*((WORD *)(lpStream+patpos[patchk])));
00328 UINT rows = bswapLE16(*((WORD *)(lpStream+patpos[patchk]+2)));
00329 if ((rows < 4) || (rows > 256)) continue;
00330 if (patpos[patchk]+8+len > dwMemLength) continue;
00331 UINT i = 0;
00332 const BYTE *p = lpStream+patpos[patchk]+8;
00333 UINT nrow = 0;
00334 while (nrow<rows)
00335 {
00336 if (i >= len) break;
00337 BYTE b = p[i++];
00338 if (!b)
00339 {
00340 nrow++;
00341 continue;
00342 }
00343 UINT ch = b & 0x7F;
00344 if (ch) ch = (ch - 1) & 0x3F;
00345 if (b & 0x80)
00346 {
00347 if (i >= len) break;
00348 chnmask[ch] = p[i++];
00349 }
00350
00351 if (chnmask[ch] & 0x0F)
00352 {
00353 if ((ch >= m_nChannels) && (ch < 64)) m_nChannels = ch+1;
00354 }
00355
00356 if (chnmask[ch] & 1) i++;
00357
00358 if (chnmask[ch] & 2) i++;
00359
00360 if (chnmask[ch] & 4) i++;
00361
00362 if (chnmask[ch] & 8) i += 2;
00363 if (i >= len) break;
00364 }
00365 }
00366
00367 m_nInstruments = 0;
00368 if (pifh.flags & 0x04) m_nInstruments = pifh.insnum;
00369 if (m_nInstruments >= MAX_INSTRUMENTS) m_nInstruments = MAX_INSTRUMENTS-1;
00370 for (UINT nins=0; nins<m_nInstruments; nins++)
00371 {
00372 if ((inspos[nins] > 0) && (inspos[nins] < dwMemLength - sizeof(ITOLDINSTRUMENT)))
00373 {
00374 INSTRUMENTHEADER *penv = new INSTRUMENTHEADER;
00375 if (!penv) continue;
00376 Headers[nins+1] = penv;
00377 memset(penv, 0, sizeof(INSTRUMENTHEADER));
00378 ITInstrToMPT(lpStream + inspos[nins], penv, pifh.cmwt);
00379 }
00380 }
00381
00382 m_nSamples = pifh.smpnum;
00383 if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1;
00384 for (UINT nsmp=0; nsmp<pifh.smpnum; nsmp++) if ((smppos[nsmp]) && (smppos[nsmp] + sizeof(ITSAMPLESTRUCT) <= dwMemLength))
00385 {
00386 ITSAMPLESTRUCT pis = *(ITSAMPLESTRUCT *)(lpStream+smppos[nsmp]);
00387 pis.id = bswapLE32(pis.id);
00388 pis.length = bswapLE32(pis.length);
00389 pis.loopbegin = bswapLE32(pis.loopbegin);
00390 pis.loopend = bswapLE32(pis.loopend);
00391 pis.C5Speed = bswapLE32(pis.C5Speed);
00392 pis.susloopbegin = bswapLE32(pis.susloopbegin);
00393 pis.susloopend = bswapLE32(pis.susloopend);
00394 pis.samplepointer = bswapLE32(pis.samplepointer);
00395
00396 if (pis.id == 0x53504D49)
00397 {
00398 MODINSTRUMENT *pins = &Ins[nsmp+1];
00399 memcpy(pins->name, pis.filename, 12);
00400 pins->uFlags = 0;
00401 pins->nLength = 0;
00402 pins->nLoopStart = pis.loopbegin;
00403 pins->nLoopEnd = pis.loopend;
00404 pins->nSustainStart = pis.susloopbegin;
00405 pins->nSustainEnd = pis.susloopend;
00406 pins->nC4Speed = pis.C5Speed;
00407 if (!pins->nC4Speed) pins->nC4Speed = 8363;
00408 if (pis.C5Speed < 256) pins->nC4Speed = 256;
00409 pins->nVolume = pis.vol << 2;
00410 if (pins->nVolume > 256) pins->nVolume = 256;
00411 pins->nGlobalVol = pis.gvl;
00412 if (pins->nGlobalVol > 64) pins->nGlobalVol = 64;
00413 if (pis.flags & 0x10) pins->uFlags |= CHN_LOOP;
00414 if (pis.flags & 0x20) pins->uFlags |= CHN_SUSTAINLOOP;
00415 if (pis.flags & 0x40) pins->uFlags |= CHN_PINGPONGLOOP;
00416 if (pis.flags & 0x80) pins->uFlags |= CHN_PINGPONGSUSTAIN;
00417 pins->nPan = (pis.dfp & 0x7F) << 2;
00418 if (pins->nPan > 256) pins->nPan = 256;
00419 if (pis.dfp & 0x80) pins->uFlags |= CHN_PANNING;
00420 pins->nVibType = autovibit2xm[pis.vit & 7];
00421 pins->nVibRate = pis.vis;
00422 pins->nVibDepth = pis.vid & 0x7F;
00423 pins->nVibSweep = (pis.vir + 3) / 4;
00424 if ((pis.samplepointer) && (pis.samplepointer < dwMemLength) && (pis.length))
00425 {
00426 pins->nLength = pis.length;
00427 if (pins->nLength > MAX_SAMPLE_LENGTH) pins->nLength = MAX_SAMPLE_LENGTH;
00428 UINT flags = (pis.cvt & 1) ? RS_PCM8S : RS_PCM8U;
00429 if (pis.flags & 2)
00430 {
00431 flags += 5;
00432 if (pis.flags & 4) flags |= RSF_STEREO;
00433 pins->uFlags |= CHN_16BIT;
00434
00435 if (pis.flags & 8) flags = ((pifh.cmwt >= 0x215) && (pis.cvt & 4)) ? RS_IT21516 : RS_IT21416;
00436 } else
00437 {
00438 if (pis.flags & 4) flags |= RSF_STEREO;
00439 if (pis.cvt == 0xFF) flags = RS_ADPCM4; else
00440
00441 if (pis.flags & 8) flags = ((pifh.cmwt >= 0x215) && (pis.cvt & 4)) ? RS_IT2158 : RS_IT2148;
00442 }
00443 ReadSample(&Ins[nsmp+1], flags, (LPSTR)(lpStream+pis.samplepointer), dwMemLength - pis.samplepointer);
00444 }
00445 }
00446 memcpy(m_szNames[nsmp+1], pis.name, 26);
00447 }
00448
00449 for (UINT npat=0; npat<npatterns; npat++)
00450 {
00451 if ((!patpos[npat]) || ((DWORD)patpos[npat] + 4 >= dwMemLength))
00452 {
00453 PatternSize[npat] = 64;
00454 Patterns[npat] = AllocatePattern(64, m_nChannels);
00455 continue;
00456 }
00457
00458 UINT len = bswapLE16(*((WORD *)(lpStream+patpos[npat])));
00459 UINT rows = bswapLE16(*((WORD *)(lpStream+patpos[npat]+2)));
00460 if ((rows < 4) || (rows > 256)) continue;
00461 if (patpos[npat]+8+len > dwMemLength) continue;
00462 PatternSize[npat] = rows;
00463 if ((Patterns[npat] = AllocatePattern(rows, m_nChannels)) == NULL) continue;
00464 memset(lastvalue, 0, sizeof(lastvalue));
00465 memset(chnmask, 0, sizeof(chnmask));
00466 MODCOMMAND *m = Patterns[npat];
00467 UINT i = 0;
00468 const BYTE *p = lpStream+patpos[npat]+8;
00469 UINT nrow = 0;
00470 while (nrow<rows)
00471 {
00472 if (i >= len) break;
00473 BYTE b = p[i++];
00474 if (!b)
00475 {
00476 nrow++;
00477 m+=m_nChannels;
00478 continue;
00479 }
00480 UINT ch = b & 0x7F;
00481 if (ch) ch = (ch - 1) & 0x3F;
00482 if (b & 0x80)
00483 {
00484 if (i >= len) break;
00485 chnmask[ch] = p[i++];
00486 }
00487 if ((chnmask[ch] & 0x10) && (ch < m_nChannels))
00488 {
00489 m[ch].note = lastvalue[ch].note;
00490 }
00491 if ((chnmask[ch] & 0x20) && (ch < m_nChannels))
00492 {
00493 m[ch].instr = lastvalue[ch].instr;
00494 }
00495 if ((chnmask[ch] & 0x40) && (ch < m_nChannels))
00496 {
00497 m[ch].volcmd = lastvalue[ch].volcmd;
00498 m[ch].vol = lastvalue[ch].vol;
00499 }
00500 if ((chnmask[ch] & 0x80) && (ch < m_nChannels))
00501 {
00502 m[ch].command = lastvalue[ch].command;
00503 m[ch].param = lastvalue[ch].param;
00504 }
00505 if (chnmask[ch] & 1)
00506 {
00507 if (i >= len) break;
00508 UINT note = p[i++];
00509 if (ch < m_nChannels)
00510 {
00511 if (note < 0x80) note++;
00512 m[ch].note = note;
00513 lastvalue[ch].note = note;
00514 channels_used[ch] = TRUE;
00515 }
00516 }
00517 if (chnmask[ch] & 2)
00518 {
00519 if (i >= len) break;
00520 UINT instr = p[i++];
00521 if (ch < m_nChannels)
00522 {
00523 m[ch].instr = instr;
00524 lastvalue[ch].instr = instr;
00525 }
00526 }
00527 if (chnmask[ch] & 4)
00528 {
00529 if (i >= len) break;
00530 UINT vol = p[i++];
00531 if (ch < m_nChannels)
00532 {
00533
00534 if (vol <= 64) { m[ch].volcmd = VOLCMD_VOLUME; m[ch].vol = vol; } else
00535
00536 if ((vol >= 128) && (vol <= 192)) { m[ch].volcmd = VOLCMD_PANNING; m[ch].vol = vol - 128; } else
00537
00538 if (vol < 75) { m[ch].volcmd = VOLCMD_FINEVOLUP; m[ch].vol = vol - 65; } else
00539
00540 if (vol < 85) { m[ch].volcmd = VOLCMD_FINEVOLDOWN; m[ch].vol = vol - 75; } else
00541
00542 if (vol < 95) { m[ch].volcmd = VOLCMD_VOLSLIDEUP; m[ch].vol = vol - 85; } else
00543
00544 if (vol < 105) { m[ch].volcmd = VOLCMD_VOLSLIDEDOWN; m[ch].vol = vol - 95; } else
00545
00546 if (vol < 115) { m[ch].volcmd = VOLCMD_PORTADOWN; m[ch].vol = vol - 105; } else
00547
00548 if (vol < 125) { m[ch].volcmd = VOLCMD_PORTAUP; m[ch].vol = vol - 115; } else
00549
00550 if ((vol >= 193) && (vol <= 202)) { m[ch].volcmd = VOLCMD_TONEPORTAMENTO; m[ch].vol = vol - 193; } else
00551
00552 if ((vol >= 203) && (vol <= 212)) { m[ch].volcmd = VOLCMD_VIBRATOSPEED; m[ch].vol = vol - 203; }
00553 lastvalue[ch].volcmd = m[ch].volcmd;
00554 lastvalue[ch].vol = m[ch].vol;
00555 }
00556 }
00557
00558 if (chnmask[ch] & 8)
00559 {
00560 if (i > len - 2) break;
00561 UINT cmd = p[i++];
00562 UINT param = p[i++];
00563 if (ch < m_nChannels)
00564 {
00565 if (cmd)
00566 {
00567 m[ch].command = cmd;
00568 m[ch].param = param;
00569 S3MConvert(&m[ch], TRUE);
00570 lastvalue[ch].command = m[ch].command;
00571 lastvalue[ch].param = m[ch].param;
00572 }
00573 }
00574 }
00575 }
00576 }
00577 for (UINT ncu=0; ncu<MAX_BASECHANNELS; ncu++)
00578 {
00579 if (ncu>=m_nChannels)
00580 {
00581 ChnSettings[ncu].nVolume = 64;
00582 ChnSettings[ncu].dwFlags &= ~CHN_MUTE;
00583 }
00584 }
00585 m_nMinPeriod = 8;
00586 m_nMaxPeriod = 0xF000;
00587 return TRUE;
00588 }
00589
00590
00591 #ifndef MODPLUG_NO_FILESAVE
00592
00593 #pragma warning(disable:4100)
00594
00595 BOOL CSoundFile::SaveIT(LPCSTR lpszFileName, UINT nPacking)
00596
00597 {
00598 DWORD dwPatNamLen, dwChnNamLen;
00599 ITFILEHEADER header;
00600 ITINSTRUMENT iti;
00601 ITSAMPLESTRUCT itss;
00602 BYTE smpcount[MAX_SAMPLES];
00603 DWORD inspos[MAX_INSTRUMENTS];
00604 DWORD patpos[MAX_PATTERNS];
00605 DWORD smppos[MAX_SAMPLES];
00606 DWORD dwPos = 0, dwHdrPos = 0, dwExtra = 2;
00607 WORD patinfo[4];
00608 BYTE chnmask[64];
00609 BYTE buf[512];
00610 MODCOMMAND lastvalue[64];
00611 FILE *f;
00612
00613
00614 if ((!lpszFileName) || ((f = fopen(lpszFileName, "wb")) == NULL)) return FALSE;
00615 memset(inspos, 0, sizeof(inspos));
00616 memset(patpos, 0, sizeof(patpos));
00617 memset(smppos, 0, sizeof(smppos));
00618
00619 memset(&header, 0, sizeof(header));
00620 dwPatNamLen = 0;
00621 dwChnNamLen = 0;
00622 header.id = 0x4D504D49;
00623 lstrcpyn(header.songname, m_szNames[0], 27);
00624 header.reserved1 = 0x1004;
00625 header.ordnum = 0;
00626 while ((header.ordnum < MAX_ORDERS) && (Order[header.ordnum] < 0xFF)) header.ordnum++;
00627 if (header.ordnum < MAX_ORDERS) Order[header.ordnum++] = 0xFF;
00628 header.insnum = m_nInstruments;
00629 header.smpnum = m_nSamples;
00630 header.patnum = MAX_PATTERNS;
00631 while ((header.patnum > 0) && (!Patterns[header.patnum-1])) header.patnum--;
00632 header.cwtv = 0x217;
00633 header.cmwt = 0x200;
00634 header.flags = 0x0001;
00635 header.special = 0x0006;
00636 if (m_nInstruments) header.flags |= 0x04;
00637 if (m_dwSongFlags & SONG_LINEARSLIDES) header.flags |= 0x08;
00638 if (m_dwSongFlags & SONG_ITOLDEFFECTS) header.flags |= 0x10;
00639 if (m_dwSongFlags & SONG_ITCOMPATMODE) header.flags |= 0x20;
00640 if (m_dwSongFlags & SONG_EXFILTERRANGE) header.flags |= 0x1000;
00641 header.globalvol = m_nDefaultGlobalVolume >> 1;
00642 header.mv = m_nSongPreAmp;
00643 if (header.mv < 0x20) header.mv = 0x20;
00644 if (header.mv > 0x7F) header.mv = 0x7F;
00645 header.speed = m_nDefaultSpeed;
00646 header.tempo = m_nDefaultTempo;
00647 header.sep = 128;
00648 dwHdrPos = sizeof(header) + header.ordnum;
00649
00650 memset(header.chnpan, 0xFF, 64);
00651 memset(header.chnvol, 64, 64);
00652 for (UINT ich=0; ich<m_nChannels; ich++)
00653 {
00654 header.chnpan[ich] = ChnSettings[ich].nPan >> 2;
00655 if (ChnSettings[ich].dwFlags & CHN_SURROUND) header.chnpan[ich] = 100;
00656 header.chnvol[ich] = ChnSettings[ich].nVolume;
00657 if (ChnSettings[ich].dwFlags & CHN_MUTE) header.chnpan[ich] |= 0x80;
00658 if (ChnSettings[ich].szName[0])
00659 {
00660 dwChnNamLen = (ich+1) * MAX_CHANNELNAME;
00661 }
00662 }
00663 if (dwChnNamLen) dwExtra += dwChnNamLen + 8;
00664 #ifdef SAVEITTIMESTAMP
00665 dwExtra += 8;
00666 #endif
00667 if (m_dwSongFlags & SONG_EMBEDMIDICFG)
00668 {
00669 header.flags |= 0x80;
00670 header.special |= 0x08;
00671 dwExtra += sizeof(MODMIDICFG);
00672 }
00673
00674 if ((m_nPatternNames) && (m_lpszPatternNames))
00675 {
00676 dwPatNamLen = m_nPatternNames * MAX_PATTERNNAME;
00677 while ((dwPatNamLen >= MAX_PATTERNNAME) && (!m_lpszPatternNames[dwPatNamLen-MAX_PATTERNNAME])) dwPatNamLen -= MAX_PATTERNNAME;
00678 if (dwPatNamLen < MAX_PATTERNNAME) dwPatNamLen = 0;
00679 if (dwPatNamLen) dwExtra += dwPatNamLen + 8;
00680 }
00681
00682 dwExtra += SaveMixPlugins(NULL, TRUE);
00683
00684 if (m_lpszSongComments)
00685 {
00686 header.special |= 1;
00687 header.msglength = strlen(m_lpszSongComments)+1;
00688 header.msgoffset = dwHdrPos + dwExtra + header.insnum*4 + header.patnum*4 + header.smpnum*4;
00689 }
00690
00691 fwrite(&header, 1, sizeof(header), f);
00692 fwrite(Order, 1, header.ordnum, f);
00693 if (header.insnum) fwrite(inspos, 4, header.insnum, f);
00694 if (header.smpnum) fwrite(smppos, 4, header.smpnum, f);
00695 if (header.patnum) fwrite(patpos, 4, header.patnum, f);
00696
00697 {
00698 #ifdef SAVEITTIMESTAMP
00699 SYSTEMTIME systime;
00700 FILETIME filetime;
00701 WORD timestamp[4];
00702 WORD nInfoEx = 1;
00703 memset(timestamp, 0, sizeof(timestamp));
00704 fwrite(&nInfoEx, 1, 2, f);
00705 GetSystemTime(&systime);
00706 SystemTimeToFileTime(&systime, &filetime);
00707 FileTimeToDosDateTime(&filetime, ×tamp[0], ×tamp[1]);
00708 fwrite(timestamp, 1, 8, f);
00709 #else
00710 WORD nInfoEx = 0;
00711 fwrite(&nInfoEx, 1, 2, f);
00712 #endif
00713 }
00714
00715 if (header.flags & 0x80)
00716 {
00717 fwrite(&m_MidiCfg, 1, sizeof(MODMIDICFG), f);
00718 }
00719
00720 if (dwPatNamLen)
00721 {
00722 DWORD d = 0x4d414e50;
00723 fwrite(&d, 1, 4, f);
00724 fwrite(&dwPatNamLen, 1, 4, f);
00725 fwrite(m_lpszPatternNames, 1, dwPatNamLen, f);
00726 }
00727
00728 if (dwChnNamLen)
00729 {
00730 DWORD d = 0x4d414e43;
00731 fwrite(&d, 1, 4, f);
00732 fwrite(&dwChnNamLen, 1, 4, f);
00733 UINT nChnNames = dwChnNamLen / MAX_CHANNELNAME;
00734 for (UINT inam=0; inam<nChnNames; inam++)
00735 {
00736 fwrite(ChnSettings[inam].szName, 1, MAX_CHANNELNAME, f);
00737 }
00738 }
00739
00740 SaveMixPlugins(f, FALSE);
00741
00742 dwPos = dwHdrPos + dwExtra + (header.insnum + header.smpnum + header.patnum) * 4;
00743 if (header.special & 1)
00744 {
00745 dwPos += strlen(m_lpszSongComments) + 1;
00746 fwrite(m_lpszSongComments, 1, strlen(m_lpszSongComments)+1, f);
00747 }
00748
00749 for (UINT nins=1; nins<=header.insnum; nins++)
00750 {
00751 memset(&iti, 0, sizeof(iti));
00752 iti.id = 0x49504D49;
00753 iti.trkvers = 0x211;
00754 if (Headers[nins])
00755 {
00756 INSTRUMENTHEADER *penv = Headers[nins];
00757 memset(smpcount, 0, sizeof(smpcount));
00758 memcpy(iti.filename, penv->filename, 12);
00759 memcpy(iti.name, penv->name, 26);
00760 iti.mbank = penv->wMidiBank;
00761 iti.mpr = penv->nMidiProgram;
00762 iti.mch = penv->nMidiChannel;
00763 iti.nna = penv->nNNA;
00764 iti.dct = penv->nDCT;
00765 iti.dca = penv->nDNA;
00766 iti.fadeout = penv->nFadeOut >> 5;
00767 iti.pps = penv->nPPS;
00768 iti.ppc = penv->nPPC;
00769 iti.gbv = (BYTE)(penv->nGlobalVol << 1);
00770 iti.dfp = (BYTE)penv->nPan >> 2;
00771 if (!(penv->dwFlags & ENV_SETPANNING)) iti.dfp |= 0x80;
00772 iti.rv = penv->nVolSwing;
00773 iti.rp = penv->nPanSwing;
00774 iti.ifc = penv->nIFC;
00775 iti.ifr = penv->nIFR;
00776 iti.nos = 0;
00777 for (UINT i=0; i<120; i++) if (penv->Keyboard[i] < MAX_SAMPLES)
00778 {
00779 UINT smp = penv->Keyboard[i];
00780 if ((smp) && (!smpcount[smp]))
00781 {
00782 smpcount[smp] = 1;
00783 iti.nos++;
00784 }
00785 iti.keyboard[i*2] = penv->NoteMap[i] - 1;
00786 iti.keyboard[i*2+1] = smp;
00787 }
00788
00789 if (penv->dwFlags & ENV_VOLUME) iti.volenv.flags |= 0x01;
00790 if (penv->dwFlags & ENV_VOLLOOP) iti.volenv.flags |= 0x02;
00791 if (penv->dwFlags & ENV_VOLSUSTAIN) iti.volenv.flags |= 0x04;
00792 if (penv->dwFlags & ENV_VOLCARRY) iti.volenv.flags |= 0x08;
00793 iti.volenv.num = (BYTE)penv->nVolEnv;
00794 iti.volenv.lpb = (BYTE)penv->nVolLoopStart;
00795 iti.volenv.lpe = (BYTE)penv->nVolLoopEnd;
00796 iti.volenv.slb = penv->nVolSustainBegin;
00797 iti.volenv.sle = penv->nVolSustainEnd;
00798
00799 if (penv->dwFlags & ENV_PANNING) iti.panenv.flags |= 0x01;
00800 if (penv->dwFlags & ENV_PANLOOP) iti.panenv.flags |= 0x02;
00801 if (penv->dwFlags & ENV_PANSUSTAIN) iti.panenv.flags |= 0x04;
00802 if (penv->dwFlags & ENV_PANCARRY) iti.panenv.flags |= 0x08;
00803 iti.panenv.num = (BYTE)penv->nPanEnv;
00804 iti.panenv.lpb = (BYTE)penv->nPanLoopStart;
00805 iti.panenv.lpe = (BYTE)penv->nPanLoopEnd;
00806 iti.panenv.slb = penv->nPanSustainBegin;
00807 iti.panenv.sle = penv->nPanSustainEnd;
00808
00809 if (penv->dwFlags & ENV_PITCH) iti.pitchenv.flags |= 0x01;
00810 if (penv->dwFlags & ENV_PITCHLOOP) iti.pitchenv.flags |= 0x02;
00811 if (penv->dwFlags & ENV_PITCHSUSTAIN) iti.pitchenv.flags |= 0x04;
00812 if (penv->dwFlags & ENV_PITCHCARRY) iti.pitchenv.flags |= 0x08;
00813 if (penv->dwFlags & ENV_FILTER) iti.pitchenv.flags |= 0x80;
00814 iti.pitchenv.num = (BYTE)penv->nPitchEnv;
00815 iti.pitchenv.lpb = (BYTE)penv->nPitchLoopStart;
00816 iti.pitchenv.lpe = (BYTE)penv->nPitchLoopEnd;
00817 iti.pitchenv.slb = (BYTE)penv->nPitchSustainBegin;
00818 iti.pitchenv.sle = (BYTE)penv->nPitchSustainEnd;
00819
00820 for (UINT ev=0; ev<25; ev++)
00821 {
00822 iti.volenv.data[ev*3] = penv->VolEnv[ev];
00823 iti.volenv.data[ev*3+1] = penv->VolPoints[ev] & 0xFF;
00824 iti.volenv.data[ev*3+2] = penv->VolPoints[ev] >> 8;
00825 iti.panenv.data[ev*3] = penv->PanEnv[ev] - 32;
00826 iti.panenv.data[ev*3+1] = penv->PanPoints[ev] & 0xFF;
00827 iti.panenv.data[ev*3+2] = penv->PanPoints[ev] >> 8;
00828 iti.pitchenv.data[ev*3] = penv->PitchEnv[ev] - 32;
00829 iti.pitchenv.data[ev*3+1] = penv->PitchPoints[ev] & 0xFF;
00830 iti.pitchenv.data[ev*3+2] = penv->PitchPoints[ev] >> 8;
00831 }
00832 } else
00833
00834 {
00835 for (UINT i=0; i<120; i++) iti.keyboard[i*2] = i;
00836 iti.ppc = 5*12;
00837 iti.gbv = 128;
00838 iti.dfp = 0x20;
00839 iti.ifc = 0xFF;
00840 }
00841 if (!iti.nos) iti.trkvers = 0;
00842
00843 inspos[nins-1] = dwPos;
00844 dwPos += sizeof(ITINSTRUMENT);
00845 fwrite(&iti, 1, sizeof(ITINSTRUMENT), f);
00846 }
00847
00848 memset(&itss, 0, sizeof(itss));
00849 for (UINT hsmp=0; hsmp<header.smpnum; hsmp++)
00850 {
00851 smppos[hsmp] = dwPos;
00852 dwPos += sizeof(ITSAMPLESTRUCT);
00853 fwrite(&itss, 1, sizeof(ITSAMPLESTRUCT), f);
00854 }
00855
00856 for (UINT npat=0; npat<header.patnum; npat++)
00857 {
00858 DWORD dwPatPos = dwPos;
00859 UINT len;
00860 if (!Patterns[npat]) continue;
00861 patpos[npat] = dwPos;
00862 patinfo[0] = 0;
00863 patinfo[1] = PatternSize[npat];
00864 patinfo[2] = 0;
00865 patinfo[3] = 0;
00866
00867 if (PatternSize[npat] == 64)
00868 {
00869 MODCOMMAND *pzc = Patterns[npat];
00870 UINT nz = PatternSize[npat] * m_nChannels;
00871 for (UINT iz=0; iz<nz; iz++)
00872 {
00873 if ((pzc[iz].note) || (pzc[iz].instr)
00874 || (pzc[iz].volcmd) || (pzc[iz].command)) break;
00875 }
00876 if (iz == nz)
00877 {
00878 patpos[npat] = 0;
00879 continue;
00880 }
00881 }
00882 fwrite(patinfo, 8, 1, f);
00883 dwPos += 8;
00884 memset(chnmask, 0xFF, sizeof(chnmask));
00885 memset(lastvalue, 0, sizeof(lastvalue));
00886 MODCOMMAND *m = Patterns[npat];
00887 for (UINT row=0; row<PatternSize[npat]; row++)
00888 {
00889 len = 0;
00890 for (UINT ch=0; ch<m_nChannels; ch++, m++)
00891 {
00892 BYTE b = 0;
00893 UINT command = m->command;
00894 UINT param = m->param;
00895 UINT vol = 0xFF;
00896 UINT note = m->note;
00897 if (note) b |= 1;
00898 if ((note) && (note < 0xFE)) note--;
00899 if (m->instr) b |= 2;
00900 if (m->volcmd)
00901 {
00902 UINT volcmd = m->volcmd;
00903 switch(volcmd)
00904 {
00905 case VOLCMD_VOLUME: vol = m->vol; if (vol > 64) vol = 64; break;
00906 case VOLCMD_PANNING: vol = m->vol + 128; if (vol > 192) vol = 192; break;
00907 case VOLCMD_VOLSLIDEUP: vol = 85 + ConvertVolParam(m->vol); break;
00908 case VOLCMD_VOLSLIDEDOWN: vol = 95 + ConvertVolParam(m->vol); break;
00909 case VOLCMD_FINEVOLUP: vol = 65 + ConvertVolParam(m->vol); break;
00910 case VOLCMD_FINEVOLDOWN: vol = 75 + ConvertVolParam(m->vol); break;
00911 case VOLCMD_VIBRATO: vol = 203; break;
00912 case VOLCMD_VIBRATOSPEED: vol = 203 + ConvertVolParam(m->vol); break;
00913 case VOLCMD_TONEPORTAMENTO: vol = 193 + ConvertVolParam(m->vol); break;
00914 case VOLCMD_PORTADOWN: vol = 105 + ConvertVolParam(m->vol); break;
00915 case VOLCMD_PORTAUP: vol = 115 + ConvertVolParam(m->vol); break;
00916 default: vol = 0xFF;
00917 }
00918 }
00919 if (vol != 0xFF) b |= 4;
00920 if (command)
00921 {
00922 S3MSaveConvert(&command, ¶m, TRUE);
00923 if (command) b |= 8;
00924 }
00925
00926 if (b)
00927 {
00928
00929 if (b & 1)
00930 {
00931 if ((note == lastvalue[ch].note) && (lastvalue[ch].volcmd & 1))
00932 {
00933 b &= ~1;
00934 b |= 0x10;
00935 } else
00936 {
00937 lastvalue[ch].note = note;
00938 lastvalue[ch].volcmd |= 1;
00939 }
00940 }
00941
00942 if (b & 2)
00943 {
00944 if ((m->instr == lastvalue[ch].instr) && (lastvalue[ch].volcmd & 2))
00945 {
00946 b &= ~2;
00947 b |= 0x20;
00948 } else
00949 {
00950 lastvalue[ch].instr = m->instr;
00951 lastvalue[ch].volcmd |= 2;
00952 }
00953 }
00954
00955 if (b & 4)
00956 {
00957 if ((vol == lastvalue[ch].vol) && (lastvalue[ch].volcmd & 4))
00958 {
00959 b &= ~4;
00960 b |= 0x40;
00961 } else
00962 {
00963 lastvalue[ch].vol = vol;
00964 lastvalue[ch].volcmd |= 4;
00965 }
00966 }
00967
00968 if (b & 8)
00969 {
00970 if ((command == lastvalue[ch].command) && (param == lastvalue[ch].param) && (lastvalue[ch].volcmd & 8))
00971 {
00972 b &= ~8;
00973 b |= 0x80;
00974 } else
00975 {
00976 lastvalue[ch].command = command;
00977 lastvalue[ch].param = param;
00978 lastvalue[ch].volcmd |= 8;
00979 }
00980 }
00981 if (b != chnmask[ch])
00982 {
00983 chnmask[ch] = b;
00984 buf[len++] = (ch+1) | 0x80;
00985 buf[len++] = b;
00986 } else
00987 {
00988 buf[len++] = ch+1;
00989 }
00990 if (b & 1) buf[len++] = note;
00991 if (b & 2) buf[len++] = m->instr;
00992 if (b & 4) buf[len++] = vol;
00993 if (b & 8)
00994 {
00995 buf[len++] = command;
00996 buf[len++] = param;
00997 }
00998 }
00999 }
01000 buf[len++] = 0;
01001 dwPos += len;
01002 patinfo[0] += len;
01003 fwrite(buf, 1, len, f);
01004 }
01005 fseek(f, dwPatPos, SEEK_SET);
01006 fwrite(patinfo, 8, 1, f);
01007 fseek(f, dwPos, SEEK_SET);
01008 }
01009
01010 for (UINT nsmp=1; nsmp<=header.smpnum; nsmp++)
01011 {
01012 MODINSTRUMENT *psmp = &Ins[nsmp];
01013 memset(&itss, 0, sizeof(itss));
01014 memcpy(itss.filename, psmp->name, 12);
01015 memcpy(itss.name, m_szNames[nsmp], 26);
01016 itss.id = 0x53504D49;
01017 itss.gvl = (BYTE)psmp->nGlobalVol;
01018 if (m_nInstruments)
01019 {
01020 for (UINT iu=1; iu<=m_nInstruments; iu++) if (Headers[iu])
01021 {
01022 INSTRUMENTHEADER *penv = Headers[iu];
01023 for (UINT ju=0; ju<128; ju++) if (penv->Keyboard[ju] == nsmp)
01024 {
01025 itss.flags = 0x01;
01026 break;
01027 }
01028 }
01029 } else
01030 {
01031 itss.flags = 0x01;
01032 }
01033 if (psmp->uFlags & CHN_LOOP) itss.flags |= 0x10;
01034 if (psmp->uFlags & CHN_SUSTAINLOOP) itss.flags |= 0x20;
01035 if (psmp->uFlags & CHN_PINGPONGLOOP) itss.flags |= 0x40;
01036 if (psmp->uFlags & CHN_PINGPONGSUSTAIN) itss.flags |= 0x80;
01037 itss.C5Speed = psmp->nC4Speed;
01038 if (!itss.C5Speed) itss.C5Speed = 8363;
01039 itss.length = psmp->nLength;
01040 itss.loopbegin = psmp->nLoopStart;
01041 itss.loopend = psmp->nLoopEnd;
01042 itss.susloopbegin = psmp->nSustainStart;
01043 itss.susloopend = psmp->nSustainEnd;
01044 itss.vol = psmp->nVolume >> 2;
01045 itss.dfp = psmp->nPan >> 2;
01046 itss.vit = autovibxm2it[psmp->nVibType & 7];
01047 itss.vis = psmp->nVibRate;
01048 itss.vid = psmp->nVibDepth;
01049 itss.vir = (psmp->nVibSweep < 64) ? psmp->nVibSweep * 4 : 255;
01050 if (psmp->uFlags & CHN_PANNING) itss.dfp |= 0x80;
01051 if ((psmp->pSample) && (psmp->nLength)) itss.cvt = 0x01;
01052 UINT flags = RS_PCM8S;
01053 #ifndef NO_PACKING
01054 if (nPacking)
01055 {
01056 if ((!(psmp->uFlags & (CHN_16BIT|CHN_STEREO)))
01057 && (CanPackSample(psmp->pSample, psmp->nLength, nPacking)))
01058 {
01059 flags = RS_ADPCM4;
01060 itss.cvt = 0xFF;
01061 }
01062 } else
01063 #endif // NO_PACKING
01064 {
01065 if (psmp->uFlags & CHN_STEREO)
01066 {
01067 flags = RS_STPCM8S;
01068 itss.flags |= 0x04;
01069 }
01070 if (psmp->uFlags & CHN_16BIT)
01071 {
01072 itss.flags |= 0x02;
01073 flags = (psmp->uFlags & CHN_STEREO) ? RS_STPCM16S : RS_PCM16S;
01074 }
01075 }
01076 itss.samplepointer = dwPos;
01077 fseek(f, smppos[nsmp-1], SEEK_SET);
01078 fwrite(&itss, 1, sizeof(ITSAMPLESTRUCT), f);
01079 fseek(f, dwPos, SEEK_SET);
01080 if ((psmp->pSample) && (psmp->nLength))
01081 {
01082 dwPos += WriteSample(f, psmp, flags);
01083 }
01084 }
01085
01086 fseek(f, dwHdrPos, SEEK_SET);
01087 if (header.insnum) fwrite(inspos, 4, header.insnum, f);
01088 if (header.smpnum) fwrite(smppos, 4, header.smpnum, f);
01089 if (header.patnum) fwrite(patpos, 4, header.patnum, f);
01090 fclose(f);
01091 return TRUE;
01092 }
01093
01094 #pragma warning(default:4100)
01095 #endif // MODPLUG_NO_FILESAVE
01096
01098
01099
01100 DWORD ITReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n)
01101
01102 {
01103 DWORD retval = 0;
01104 UINT i = n;
01105
01106 if (n > 0)
01107 {
01108 do
01109 {
01110 if (!bitnum)
01111 {
01112 bitbuf = *ibuf++;
01113 bitnum = 8;
01114 }
01115 retval >>= 1;
01116 retval |= bitbuf << 31;
01117 bitbuf >>= 1;
01118 bitnum--;
01119 i--;
01120 } while (i);
01121 i = n;
01122 }
01123 return (retval >> (32-i));
01124 }
01125
01126 #define IT215_SUPPORT
01127 void ITUnpack8Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215)
01128
01129 {
01130 signed char *pDst = pSample;
01131 LPBYTE pSrc = lpMemFile;
01132 DWORD wHdr = 0;
01133 DWORD wCount = 0;
01134 DWORD bitbuf = 0;
01135 UINT bitnum = 0;
01136 BYTE bLeft = 0, bTemp = 0, bTemp2 = 0;
01137
01138 while (dwLen)
01139 {
01140 if (!wCount)
01141 {
01142 wCount = 0x8000;
01143 wHdr = bswapLE16(*((LPWORD)pSrc));
01144 pSrc += 2;
01145 bLeft = 9;
01146 bTemp = bTemp2 = 0;
01147 bitbuf = bitnum = 0;
01148 }
01149 DWORD d = wCount;
01150 if (d > dwLen) d = dwLen;
01151
01152 DWORD dwPos = 0;
01153 do
01154 {
01155 WORD wBits = (WORD)ITReadBits(bitbuf, bitnum, pSrc, bLeft);
01156 if (bLeft < 7)
01157 {
01158 DWORD i = 1 << (bLeft-1);
01159 DWORD j = wBits & 0xFFFF;
01160 if (i != j) goto UnpackByte;
01161 wBits = (WORD)(ITReadBits(bitbuf, bitnum, pSrc, 3) + 1) & 0xFF;
01162 bLeft = ((BYTE)wBits < bLeft) ? (BYTE)wBits : (BYTE)((wBits+1) & 0xFF);
01163 goto Next;
01164 }
01165 if (bLeft < 9)
01166 {
01167 WORD i = (0xFF >> (9 - bLeft)) + 4;
01168 WORD j = i - 8;
01169 if ((wBits <= j) || (wBits > i)) goto UnpackByte;
01170 wBits -= j;
01171 bLeft = ((BYTE)(wBits & 0xFF) < bLeft) ? (BYTE)(wBits & 0xFF) : (BYTE)((wBits+1) & 0xFF);
01172 goto Next;
01173 }
01174 if (bLeft >= 10) goto SkipByte;
01175 if (wBits >= 256)
01176 {
01177 bLeft = (BYTE)(wBits + 1) & 0xFF;
01178 goto Next;
01179 }
01180 UnpackByte:
01181 if (bLeft < 8)
01182 {
01183 BYTE shift = 8 - bLeft;
01184 signed char c = (signed char)(wBits << shift);
01185 c >>= shift;
01186 wBits = (WORD)c;
01187 }
01188 wBits += bTemp;
01189 bTemp = (BYTE)wBits;
01190 bTemp2 += bTemp;
01191 #ifdef IT215_SUPPORT
01192 pDst[dwPos] = (b215) ? bTemp2 : bTemp;
01193 #else
01194 pDst[dwPos] = bTemp;
01195 #endif
01196 SkipByte:
01197 dwPos++;
01198 Next:
01199 if (pSrc >= lpMemFile+dwMemLength+1) return;
01200 } while (dwPos < d);
01201
01202 wCount -= d;
01203 dwLen -= d;
01204 pDst += d;
01205 }
01206 }
01207
01208
01209 void ITUnpack16Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215)
01210
01211 {
01212 signed short *pDst = (signed short *)pSample;
01213 LPBYTE pSrc = lpMemFile;
01214 DWORD wHdr = 0;
01215 DWORD wCount = 0;
01216 DWORD bitbuf = 0;
01217 UINT bitnum = 0;
01218 BYTE bLeft = 0;
01219 signed short wTemp = 0, wTemp2 = 0;
01220
01221 while (dwLen)
01222 {
01223 if (!wCount)
01224 {
01225 wCount = 0x4000;
01226 wHdr = bswapLE16(*((LPWORD)pSrc));
01227 pSrc += 2;
01228 bLeft = 17;
01229 wTemp = wTemp2 = 0;
01230 bitbuf = bitnum = 0;
01231 }
01232 DWORD d = wCount;
01233 if (d > dwLen) d = dwLen;
01234
01235 DWORD dwPos = 0;
01236 do
01237 {
01238 DWORD dwBits = ITReadBits(bitbuf, bitnum, pSrc, bLeft);
01239 if (bLeft < 7)
01240 {
01241 DWORD i = 1 << (bLeft-1);
01242 DWORD j = dwBits;
01243 if (i != j) goto UnpackByte;
01244 dwBits = ITReadBits(bitbuf, bitnum, pSrc, 4) + 1;
01245 bLeft = ((BYTE)(dwBits & 0xFF) < bLeft) ? (BYTE)(dwBits & 0xFF) : (BYTE)((dwBits+1) & 0xFF);
01246 goto Next;
01247 }
01248 if (bLeft < 17)
01249 {
01250 DWORD i = (0xFFFF >> (17 - bLeft)) + 8;
01251 DWORD j = (i - 16) & 0xFFFF;
01252 if ((dwBits <= j) || (dwBits > (i & 0xFFFF))) goto UnpackByte;
01253 dwBits -= j;
01254 bLeft = ((BYTE)(dwBits & 0xFF) < bLeft) ? (BYTE)(dwBits & 0xFF) : (BYTE)((dwBits+1) & 0xFF);
01255 goto Next;
01256 }
01257 if (bLeft >= 18) goto SkipByte;
01258 if (dwBits >= 0x10000)
01259 {
01260 bLeft = (BYTE)(dwBits + 1) & 0xFF;
01261 goto Next;
01262 }
01263 UnpackByte:
01264 if (bLeft < 16)
01265 {
01266 BYTE shift = 16 - bLeft;
01267 signed short c = (signed short)(dwBits << shift);
01268 c >>= shift;
01269 dwBits = (DWORD)c;
01270 }
01271 dwBits += wTemp;
01272 wTemp = (signed short)dwBits;
01273 wTemp2 += wTemp;
01274 #ifdef IT215_SUPPORT
01275 pDst[dwPos] = (b215) ? wTemp2 : wTemp;
01276 #else
01277 pDst[dwPos] = wTemp;
01278 #endif
01279 SkipByte:
01280 dwPos++;
01281 Next:
01282 if (pSrc >= lpMemFile+dwMemLength+1) return;
01283 } while (dwPos < d);
01284
01285 wCount -= d;
01286 dwLen -= d;
01287 pDst += d;
01288 if (pSrc >= lpMemFile+dwMemLength) break;
01289 }
01290 }
01291
01292
01293 UINT CSoundFile::SaveMixPlugins(FILE *f, BOOL bUpdate)
01294
01295 {
01296 DWORD chinfo[64];
01297 CHAR s[32];
01298 DWORD nPluginSize;
01299 UINT nTotalSize = 0;
01300 UINT nChInfo = 0;
01301
01302 for (UINT i=0; i<MAX_MIXPLUGINS; i++)
01303 {
01304 PSNDMIXPLUGIN p = &m_MixPlugins[i];
01305 if ((p->Info.dwPluginId1) || (p->Info.dwPluginId2))
01306 {
01307 nPluginSize = sizeof(SNDMIXPLUGININFO)+4;
01308 if ((p->pMixPlugin) && (bUpdate))
01309 {
01310 p->pMixPlugin->SaveAllParameters();
01311 }
01312 if (p->pPluginData)
01313 {
01314 nPluginSize += p->nPluginDataSize;
01315 }
01316 if (f)
01317 {
01318 s[0] = 'F';
01319 s[1] = 'X';
01320 s[2] = '0' + (i/10);
01321 s[3] = '0' + (i%10);
01322 fwrite(s, 1, 4, f);
01323 fwrite(&nPluginSize, 1, 4, f);
01324 fwrite(&p->Info, 1, sizeof(SNDMIXPLUGININFO), f);
01325 fwrite(&m_MixPlugins[i].nPluginDataSize, 1, 4, f);
01326 if (m_MixPlugins[i].pPluginData)
01327 {
01328 fwrite(m_MixPlugins[i].pPluginData, 1, m_MixPlugins[i].nPluginDataSize, f);
01329 }
01330 }
01331 nTotalSize += nPluginSize + 8;
01332 }
01333 }
01334 for (UINT j=0; j<m_nChannels; j++)
01335 {
01336 if (j < 64)
01337 {
01338 if ((chinfo[j] = ChnSettings[j].nMixPlugin) != 0)
01339 {
01340 nChInfo = j+1;
01341 }
01342 }
01343 }
01344 if (nChInfo)
01345 {
01346 if (f)
01347 {
01348 nPluginSize = 0x58464843;
01349 fwrite(&nPluginSize, 1, 4, f);
01350 nPluginSize = nChInfo*4;
01351 fwrite(&nPluginSize, 1, 4, f);
01352 fwrite(chinfo, 1, nPluginSize, f);
01353 }
01354 nTotalSize += nChInfo*4 + 8;
01355 }
01356 return nTotalSize;
01357 }
01358
01359
01360 UINT CSoundFile::LoadMixPlugins(const void *pData, UINT nLen)
01361
01362 {
01363 const BYTE *p = (const BYTE *)pData;
01364 UINT nPos = 0;
01365
01366 while (nPos+8 < nLen)
01367 {
01368 DWORD nPluginSize;
01369 UINT nPlugin;
01370
01371 nPluginSize = bswapLE32(*(DWORD *)(p+nPos+4));
01372 if (nPluginSize > nLen-nPos-8) break;;
01373 if ((bswapLE32(*(DWORD *)(p+nPos))) == 0x58464843)
01374 {
01375 for (UINT ch=0; ch<64; ch++) if (ch*4 < nPluginSize)
01376 {
01377 ChnSettings[ch].nMixPlugin = bswapLE32(*(DWORD *)(p+nPos+8+ch*4));
01378 }
01379 } else
01380 {
01381 if ((p[nPos] != 'F') || (p[nPos+1] != 'X')
01382 || (p[nPos+2] < '0') || (p[nPos+3] < '0'))
01383 {
01384 break;
01385 }
01386 nPlugin = (p[nPos+2]-'0')*10 + (p[nPos+3]-'0');
01387 if ((nPlugin < MAX_MIXPLUGINS) && (nPluginSize >= sizeof(SNDMIXPLUGININFO)+4))
01388 {
01389 DWORD dwExtra = bswapLE32(*(DWORD *)(p+nPos+8+sizeof(SNDMIXPLUGININFO)));
01390 m_MixPlugins[nPlugin].Info = *(const SNDMIXPLUGININFO *)(p+nPos+8);
01391 m_MixPlugins[nPlugin].Info.dwPluginId1 = bswapLE32(m_MixPlugins[nPlugin].Info.dwPluginId1);
01392 m_MixPlugins[nPlugin].Info.dwPluginId2 = bswapLE32(m_MixPlugins[nPlugin].Info.dwPluginId2);
01393 m_MixPlugins[nPlugin].Info.dwInputRouting = bswapLE32(m_MixPlugins[nPlugin].Info.dwInputRouting);
01394 m_MixPlugins[nPlugin].Info.dwOutputRouting = bswapLE32(m_MixPlugins[nPlugin].Info.dwOutputRouting);
01395 for (UINT j=0; j<4; j++)
01396 {
01397 m_MixPlugins[nPlugin].Info.dwReserved[j] = bswapLE32(m_MixPlugins[nPlugin].Info.dwReserved[j]);
01398 }
01399 if ((dwExtra) && (dwExtra <= nPluginSize-sizeof(SNDMIXPLUGININFO)-4))
01400 {
01401 m_MixPlugins[nPlugin].nPluginDataSize = 0;
01402 m_MixPlugins[nPlugin].pPluginData = new signed char [dwExtra];
01403 if (m_MixPlugins[nPlugin].pPluginData)
01404 {
01405 m_MixPlugins[nPlugin].nPluginDataSize = dwExtra;
01406 memcpy(m_MixPlugins[nPlugin].pPluginData, p+nPos+8+sizeof(SNDMIXPLUGININFO)+4, dwExtra);
01407 }
01408 }
01409 }
01410 }
01411 nPos += nPluginSize + 8;
01412 }
01413 return nPos;
01414 }
01415