Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

load_it.cpp

Go to the documentation of this file.
00001 /*
00002  * This program is  free software; you can redistribute it  and modify it
00003  * under the terms of the GNU  General Public License as published by the
00004  * Free Software Foundation; either version 2  of the license or (at your
00005  * option) any later version.
00006  *
00007  * Authors: Olivier Lapicque <olivierl@jps.net>,
00008  *          Adam Goode       <adam@evdebs.org> (endian and char fixes for PPC)
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 // Impulse Tracker IT file support (import only)
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                 // Volume Envelope 
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                 // Panning Envelope 
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                 // Pitch Envelope 
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                 // Envelopes Data
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         // Global Volume
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         // Reading Channels Pan Positions
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         // Reading Song Message
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         // Reading orders
00227         UINT nordsize = pifh.ordnum;
00228         if (nordsize > MAX_ORDERS) nordsize = MAX_ORDERS;
00229         memcpy(Order, lpStream+dwMemPos, nordsize);
00230         dwMemPos += pifh.ordnum;
00231         // Reading Instrument Offsets
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         // Reading Samples Offsets
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         // Reading Patterns Offsets
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         // Reading IT Extra Info
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         // Reading Midi Output & Macros
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         // Read pattern names: "PNAM"
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         // 4-channels minimum
00297         m_nChannels = 4;
00298         // Read channel names: "CNAM"
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         // Read mix plugins information
00316         if (dwMemPos + 8 < dwMemLength) 
00317         {
00318                 dwMemPos += LoadMixPlugins(lpStream+dwMemPos, dwMemLength-dwMemPos);
00319         }
00320         // Checking for unused channels
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                         // Channel used
00351                         if (chnmask[ch] & 0x0F)
00352                         {
00353                                 if ((ch >= m_nChannels) && (ch < 64)) m_nChannels = ch+1;
00354                         }
00355                         // Note
00356                         if (chnmask[ch] & 1) i++;
00357                         // Instrument
00358                         if (chnmask[ch] & 2) i++;
00359                         // Volume
00360                         if (chnmask[ch] & 4) i++;
00361                         // Effect
00362                         if (chnmask[ch] & 8) i += 2;
00363                         if (i >= len) break;
00364                 }
00365         }
00366         // Reading Instruments
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         // Reading Samples
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                                         // IT 2.14 16-bit packed sample ?
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                                         // IT 2.14 8-bit packed sample ?
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         // Reading Patterns
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)    // Note
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                                         // 0-64: Set Volume
00534                                         if (vol <= 64) { m[ch].volcmd = VOLCMD_VOLUME; m[ch].vol = vol; } else
00535                                         // 128-192: Set Panning
00536                                         if ((vol >= 128) && (vol <= 192)) { m[ch].volcmd = VOLCMD_PANNING; m[ch].vol = vol - 128; } else
00537                                         // 65-74: Fine Volume Up
00538                                         if (vol < 75) { m[ch].volcmd = VOLCMD_FINEVOLUP; m[ch].vol = vol - 65; } else
00539                                         // 75-84: Fine Volume Down
00540                                         if (vol < 85) { m[ch].volcmd = VOLCMD_FINEVOLDOWN; m[ch].vol = vol - 75; } else
00541                                         // 85-94: Volume Slide Up
00542                                         if (vol < 95) { m[ch].volcmd = VOLCMD_VOLSLIDEUP; m[ch].vol = vol - 85; } else
00543                                         // 95-104: Volume Slide Down
00544                                         if (vol < 105) { m[ch].volcmd = VOLCMD_VOLSLIDEDOWN; m[ch].vol = vol - 95; } else
00545                                         // 105-114: Pitch Slide Up
00546                                         if (vol < 115) { m[ch].volcmd = VOLCMD_PORTADOWN; m[ch].vol = vol - 105; } else
00547                                         // 115-124: Pitch Slide Down
00548                                         if (vol < 125) { m[ch].volcmd = VOLCMD_PORTAUP; m[ch].vol = vol - 115; } else
00549                                         // 193-202: Portamento To
00550                                         if ((vol >= 193) && (vol <= 202)) { m[ch].volcmd = VOLCMD_TONEPORTAMENTO; m[ch].vol = vol - 193; } else
00551                                         // 203-212: Vibrato
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                         // Reading command/param
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 //#define SAVEITTIMESTAMP
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         // Writing Header
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         // Channel Pan and Volume
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; // Time Stamp
00666 #endif
00667         if (m_dwSongFlags & SONG_EMBEDMIDICFG)
00668         {
00669                 header.flags |= 0x80;
00670                 header.special |= 0x08;
00671                 dwExtra += sizeof(MODMIDICFG);
00672         }
00673         // Pattern Names
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         // Mix Plugins
00682         dwExtra += SaveMixPlugins(NULL, TRUE);
00683         // Comments
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         // Write file header
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         // Writing editor history information
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, &timestamp[0], &timestamp[1]);
00708                 fwrite(timestamp, 1, 8, f);
00709 #else
00710                 WORD nInfoEx = 0;
00711                 fwrite(&nInfoEx, 1, 2, f);
00712 #endif
00713         }
00714         // Writing midi cfg
00715         if (header.flags & 0x80)
00716         {
00717                 fwrite(&m_MidiCfg, 1, sizeof(MODMIDICFG), f);
00718         }
00719         // Writing pattern names
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         // Writing channel Names
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         // Writing mix plugins info
00740         SaveMixPlugins(f, FALSE);
00741         // Writing song message
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         // Writing instruments
00749         for (UINT nins=1; nins<=header.insnum; nins++)
00750         {
00751                 memset(&iti, 0, sizeof(iti));
00752                 iti.id = 0x49504D49;    // "IMPI"
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                         // Writing Volume envelope
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                         // Writing Panning envelope
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                         // Writing Pitch Envelope
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                         // Writing Envelopes data
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                 // Save Empty Instrument
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                 // Writing instrument
00843                 inspos[nins-1] = dwPos;
00844                 dwPos += sizeof(ITINSTRUMENT);
00845                 fwrite(&iti, 1, sizeof(ITINSTRUMENT), f);
00846         }
00847         // Writing sample headers
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         // Writing Patterns
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                 // Check for empty pattern
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, &param, TRUE);
00923                                         if (command) b |= 8;
00924                                 }
00925                                 // Packing information
00926                                 if (b)
00927                                 {
00928                                         // Same note ?
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                                         // Same instrument ?
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                                         // Same volume column byte ?
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                                         // Same command / param ?
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         // Writing Sample Data
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         // Updating offsets
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 // IT 2.14 compression
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                 // Unpacking
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                 // Move On
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                 // Unpacking
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                 // Move On
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; // plugininfo+4 (datalen)
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 

Generated on Sat Nov 5 16:15:39 2005 for OPIE by  doxygen 1.4.2