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

load_mod.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 
00014 //#pragma warning(disable:4244)
00015 
00016 extern WORD ProTrackerPeriodTable[6*12];
00017 
00019 // ProTracker / NoiseTracker MOD/NST file support
00020 
00021 void CSoundFile::ConvertModCommand(MODCOMMAND *m) const
00022 //-----------------------------------------------------
00023 {
00024         UINT command = m->command, param = m->param;
00025 
00026         switch(command)
00027         {
00028         case 0x00:      if (param) command = CMD_ARPEGGIO; break;
00029         case 0x01:      command = CMD_PORTAMENTOUP; break;
00030         case 0x02:      command = CMD_PORTAMENTODOWN; break;
00031         case 0x03:      command = CMD_TONEPORTAMENTO; break;
00032         case 0x04:      command = CMD_VIBRATO; break;
00033         case 0x05:      command = CMD_TONEPORTAVOL; if (param & 0xF0) param &= 0xF0; break;
00034         case 0x06:      command = CMD_VIBRATOVOL; if (param & 0xF0) param &= 0xF0; break;
00035         case 0x07:      command = CMD_TREMOLO; break;
00036         case 0x08:      command = CMD_PANNING8; break;
00037         case 0x09:      command = CMD_OFFSET; break;
00038         case 0x0A:      command = CMD_VOLUMESLIDE; if (param & 0xF0) param &= 0xF0; break;
00039         case 0x0B:      command = CMD_POSITIONJUMP; break;
00040         case 0x0C:      command = CMD_VOLUME; break;
00041         case 0x0D:      command = CMD_PATTERNBREAK; param = ((param >> 4) * 10) + (param & 0x0F); break;
00042         case 0x0E:      command = CMD_MODCMDEX; break;
00043         case 0x0F:      command = (param <= (UINT)((m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) ? 0x1F : 0x20)) ? CMD_SPEED : CMD_TEMPO;
00044                                 if ((param == 0xFF) && (m_nSamples == 15)) command = 0; break;
00045         // Extension for XM extended effects
00046         case 'G' - 55:  command = CMD_GLOBALVOLUME; break;
00047         case 'H' - 55:  command = CMD_GLOBALVOLSLIDE; if (param & 0xF0) param &= 0xF0; break;
00048         case 'K' - 55:  command = CMD_KEYOFF; break;
00049         case 'L' - 55:  command = CMD_SETENVPOSITION; break;
00050         case 'M' - 55:  command = CMD_CHANNELVOLUME; break;
00051         case 'N' - 55:  command = CMD_CHANNELVOLSLIDE; break;
00052         case 'P' - 55:  command = CMD_PANNINGSLIDE; if (param & 0xF0) param &= 0xF0; break;
00053         case 'R' - 55:  command = CMD_RETRIG; break;
00054         case 'T' - 55:  command = CMD_TREMOR; break;
00055         case 'X' - 55:  command = CMD_XFINEPORTAUPDOWN; break;
00056         case 'Y' - 55:  command = CMD_PANBRELLO; break;
00057         case 'Z' - 55:  command = CMD_MIDI;     break;
00058         default:        command = 0;
00059         }
00060         m->command = command;
00061         m->param = param;
00062 }
00063 
00064 
00065 WORD CSoundFile::ModSaveCommand(const MODCOMMAND *m, BOOL bXM) const
00066 //------------------------------------------------------------------
00067 {
00068         UINT command = m->command & 0x3F, param = m->param;
00069 
00070         switch(command)
00071         {
00072         case 0:                                         command = param = 0; break;
00073         case CMD_ARPEGGIO:                      command = 0; break;
00074         case CMD_PORTAMENTOUP:
00075                 if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM))
00076                 {
00077                         if ((param & 0xF0) == 0xE0) { command=0x0E; param=((param & 0x0F) >> 2)|0x10; break; }
00078                         else if ((param & 0xF0) == 0xF0) { command=0x0E; param &= 0x0F; param|=0x10; break; }
00079                 }
00080                 command = 0x01;
00081                 break;
00082         case CMD_PORTAMENTODOWN:
00083                 if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM))
00084                 {
00085                         if ((param & 0xF0) == 0xE0) { command=0x0E; param=((param & 0x0F) >> 2)|0x20; break; }
00086                         else if ((param & 0xF0) == 0xF0) { command=0x0E; param &= 0x0F; param|=0x20; break; }
00087                 }
00088                 command = 0x02;
00089                 break;
00090         case CMD_TONEPORTAMENTO:        command = 0x03; break;
00091         case CMD_VIBRATO:                       command = 0x04; break;
00092         case CMD_TONEPORTAVOL:          command = 0x05; break;
00093         case CMD_VIBRATOVOL:            command = 0x06; break;
00094         case CMD_TREMOLO:                       command = 0x07; break;
00095         case CMD_PANNING8:                      
00096                 command = 0x08;
00097                 if (bXM)
00098                 {
00099                         if ((m_nType != MOD_TYPE_IT) && (m_nType != MOD_TYPE_XM) && (param <= 0x80))
00100                         {
00101                                 param <<= 1;
00102                                 if (param > 255) param = 255;
00103                         }
00104                 } else
00105                 {
00106                         if ((m_nType == MOD_TYPE_IT) || (m_nType == MOD_TYPE_XM)) param >>= 1;
00107                 }
00108                 break;
00109         case CMD_OFFSET:                        command = 0x09; break;
00110         case CMD_VOLUMESLIDE:           command = 0x0A; break;
00111         case CMD_POSITIONJUMP:          command = 0x0B; break;
00112         case CMD_VOLUME:                        command = 0x0C; break;
00113         case CMD_PATTERNBREAK:          command = 0x0D; param = ((param / 10) << 4) | (param % 10); break;
00114         case CMD_MODCMDEX:                      command = 0x0E; break;
00115         case CMD_SPEED:                         command = 0x0F; if (param > 0x20) param = 0x20; break;
00116         case CMD_TEMPO:                         if (param > 0x20) { command = 0x0F; break; }
00117         case CMD_GLOBALVOLUME:          command = 'G' - 55; break;
00118         case CMD_GLOBALVOLSLIDE:        command = 'H' - 55; break;
00119         case CMD_KEYOFF:                        command = 'K' - 55; break;
00120         case CMD_SETENVPOSITION:        command = 'L' - 55; break;
00121         case CMD_CHANNELVOLUME:         command = 'M' - 55; break;
00122         case CMD_CHANNELVOLSLIDE:       command = 'N' - 55; break;
00123         case CMD_PANNINGSLIDE:          command = 'P' - 55; break;
00124         case CMD_RETRIG:                        command = 'R' - 55; break;
00125         case CMD_TREMOR:                        command = 'T' - 55; break;
00126         case CMD_XFINEPORTAUPDOWN:      command = 'X' - 55; break;
00127         case CMD_PANBRELLO:                     command = 'Y' - 55; break;
00128         case CMD_MIDI:                          command = 'Z' - 55; break;
00129         case CMD_S3MCMDEX:
00130                 switch(param & 0xF0)
00131                 {
00132                 case 0x10:      command = 0x0E; param = (param & 0x0F) | 0x30; break;
00133                 case 0x20:      command = 0x0E; param = (param & 0x0F) | 0x50; break;
00134                 case 0x30:      command = 0x0E; param = (param & 0x0F) | 0x40; break;
00135                 case 0x40:      command = 0x0E; param = (param & 0x0F) | 0x70; break;
00136                 case 0x90:      command = 'X' - 55; break;
00137                 case 0xB0:      command = 0x0E; param = (param & 0x0F) | 0x60; break;
00138                 case 0xA0:
00139                 case 0x50:
00140                 case 0x70:
00141                 case 0x60:      command = param = 0; break;
00142                 default:        command = 0x0E; break;
00143                 }
00144                 break;
00145         default:                command = param = 0;
00146         }
00147         return (WORD)((command << 8) | (param));
00148 }
00149 
00150 
00151 #pragma pack(1)
00152 
00153 typedef struct _MODSAMPLE
00154 {
00155         CHAR name[22];
00156         WORD length;
00157         BYTE finetune;
00158         BYTE volume;
00159         WORD loopstart;
00160         WORD looplen;
00161 } Q_PACKED MODSAMPLE, *PMODSAMPLE;
00162 
00163 typedef struct _MODMAGIC
00164 {
00165         BYTE nOrders;
00166         BYTE nRestartPos;
00167         BYTE Orders[128];
00168         char Magic[4];          // changed from CHAR
00169 } Q_PACKED MODMAGIC, *PMODMAGIC;
00170 
00171 #pragma pack()
00172 
00173 BOOL IsMagic(LPCSTR s1, LPCSTR s2)
00174 {
00175         return ((*(DWORD *)s1) == (*(DWORD *)s2)) ? TRUE : FALSE;
00176 }
00177 
00178 
00179 BOOL CSoundFile::ReadMod(const BYTE *lpStream, DWORD dwMemLength)
00180 //---------------------------------------------------------------
00181 {
00182         char s[1024];          // changed from CHAR
00183         DWORD dwMemPos, dwTotalSampleLen;
00184         PMODMAGIC pMagic;
00185         UINT nErr;
00186 
00187         if ((!lpStream) || (dwMemLength < 0x600)) return FALSE;
00188         dwMemPos = 20;
00189         m_nSamples = 31;
00190         m_nChannels = 4;
00191         pMagic = (PMODMAGIC)(lpStream+dwMemPos+sizeof(MODSAMPLE)*31);
00192         // Check Mod Magic
00193         memcpy(s, pMagic->Magic, 4);
00194         if ((IsMagic(s, "M.K.")) || (IsMagic(s, "M!K!"))
00195          || (IsMagic(s, "M&K!")) || (IsMagic(s, "N.T."))) m_nChannels = 4; else
00196         if ((IsMagic(s, "CD81")) || (IsMagic(s, "OKTA"))) m_nChannels = 8; else
00197         if ((s[0]=='F') && (s[1]=='L') && (s[2]=='T') && (s[3]>='4') && (s[3]<='9')) m_nChannels = s[3] - '0'; else
00198         if ((s[0]>='4') && (s[0]<='9') && (s[1]=='C') && (s[2]=='H') && (s[3]=='N')) m_nChannels = s[0] - '0'; else
00199         if ((s[0]=='1') && (s[1]>='0') && (s[1]<='9') && (s[2]=='C') && (s[3]=='H')) m_nChannels = s[1] - '0' + 10; else
00200         if ((s[0]=='2') && (s[1]>='0') && (s[1]<='9') && (s[2]=='C') && (s[3]=='H')) m_nChannels = s[1] - '0' + 20; else
00201         if ((s[0]=='3') && (s[1]>='0') && (s[1]<='2') && (s[2]=='C') && (s[3]=='H')) m_nChannels = s[1] - '0' + 30; else
00202         if ((s[0]=='T') && (s[1]=='D') && (s[2]=='Z') && (s[3]>='4') && (s[3]<='9')) m_nChannels = s[3] - '0'; else
00203         if (IsMagic(s,"16CN")) m_nChannels = 16; else
00204         if (IsMagic(s,"32CN")) m_nChannels = 32; else m_nSamples = 15;
00205         // Load Samples
00206         nErr = 0;
00207         dwTotalSampleLen = 0;
00208         for     (UINT i=1; i<=m_nSamples; i++)
00209         {
00210                 PMODSAMPLE pms = (PMODSAMPLE)(lpStream+dwMemPos);
00211                 MODINSTRUMENT *psmp = &Ins[i];
00212                 UINT loopstart, looplen;
00213 
00214                 memcpy(m_szNames[i], pms->name, 22);
00215                 m_szNames[i][22] = 0;
00216                 psmp->uFlags = 0;
00217                 psmp->nLength = bswapBE16(pms->length)*2;
00218                 dwTotalSampleLen += psmp->nLength;
00219                 psmp->nFineTune = MOD2XMFineTune(pms->finetune & 0x0F);
00220                 psmp->nVolume = 4*pms->volume;
00221                 if (psmp->nVolume > 256) { psmp->nVolume = 256; nErr++; }
00222                 psmp->nGlobalVol = 64;
00223                 psmp->nPan = 128;
00224                 loopstart = bswapBE16(pms->loopstart)*2;
00225                 looplen = bswapBE16(pms->looplen)*2;
00226                 // Fix loops
00227                 if ((looplen > 2) && (loopstart+looplen > psmp->nLength)
00228                  && (loopstart/2+looplen <= psmp->nLength))
00229                 {
00230                         loopstart /= 2;
00231                 }
00232                 psmp->nLoopStart = loopstart;
00233                 psmp->nLoopEnd = loopstart + looplen;
00234                 if (psmp->nLength < 4) psmp->nLength = 0;
00235                 if (psmp->nLength)
00236                 {
00237                         UINT derr = 0;
00238                         if (psmp->nLoopStart >= psmp->nLength) { psmp->nLoopStart = psmp->nLength-1; derr|=1; }
00239                         if (psmp->nLoopEnd > psmp->nLength) { psmp->nLoopEnd = psmp->nLength; derr |= 1; }
00240                         if (psmp->nLoopStart > psmp->nLoopEnd) derr |= 1;
00241                         if ((psmp->nLoopStart > psmp->nLoopEnd) || (psmp->nLoopEnd <= 8)
00242                          || (psmp->nLoopEnd - psmp->nLoopStart <= 4))
00243                         {
00244                                 psmp->nLoopStart = 0;
00245                                 psmp->nLoopEnd = 0;
00246                         }
00247                         if (psmp->nLoopEnd > psmp->nLoopStart)
00248                         {
00249                                 psmp->uFlags |= CHN_LOOP;
00250                         }
00251                 }
00252                 dwMemPos += sizeof(MODSAMPLE);
00253         }
00254         if ((m_nSamples == 15) && (dwTotalSampleLen > dwMemLength * 4)) return FALSE;
00255         pMagic = (PMODMAGIC)(lpStream+dwMemPos);
00256         dwMemPos += sizeof(MODMAGIC);
00257         if (m_nSamples == 15) dwMemPos -= 4;
00258         memset(Order, 0,sizeof(Order));
00259         memcpy(Order, pMagic->Orders, 128);
00260 
00261         UINT nbp, nbpbuggy, nbpbuggy2, norders;
00262 
00263         norders = pMagic->nOrders;
00264         if ((!norders) || (norders > 0x80))
00265         {
00266                 norders = 0x80;
00267                 while ((norders > 1) && (!Order[norders-1])) norders--;
00268         }
00269         nbpbuggy = 0;
00270         nbpbuggy2 = 0;
00271         nbp = 0;
00272         for (UINT iord=0; iord<128; iord++)
00273         {
00274                 UINT i = Order[iord];
00275                 if ((i < 0x80) && (nbp <= i))
00276                 {
00277                         nbp = i+1;
00278                         if (iord<norders) nbpbuggy = nbp;
00279                 }
00280                 if (i >= nbpbuggy2) nbpbuggy2 = i+1;
00281         }
00282         for (UINT iend=norders; iend<MAX_ORDERS; iend++) Order[iend] = 0xFF;
00283         norders--;
00284         m_nRestartPos = pMagic->nRestartPos;
00285         if (m_nRestartPos >= 0x78) m_nRestartPos = 0;
00286         if (m_nRestartPos + 1 >= (UINT)norders) m_nRestartPos = 0;
00287         if (!nbp) return FALSE;
00288         DWORD dwWowTest = dwTotalSampleLen+dwMemPos;
00289         if ((IsMagic(pMagic->Magic, "M.K.")) && (dwWowTest + nbp*8*256 == dwMemLength)) m_nChannels = 8;
00290         if ((nbp != nbpbuggy) && (dwWowTest + nbp*m_nChannels*256 != dwMemLength))
00291         {
00292                 if (dwWowTest + nbpbuggy*m_nChannels*256 == dwMemLength) nbp = nbpbuggy;
00293                 else nErr += 8;
00294         } else
00295         if ((nbpbuggy2 > nbp) && (dwWowTest + nbpbuggy2*m_nChannels*256 == dwMemLength))
00296         {
00297                 nbp = nbpbuggy2;
00298         }
00299         if ((dwWowTest < 0x600) || (dwWowTest > dwMemLength)) nErr += 8;
00300         if ((m_nSamples == 15) && (nErr >= 16)) return FALSE;
00301         // Default settings     
00302         m_nType = MOD_TYPE_MOD;
00303         m_nDefaultSpeed = 6;
00304         m_nDefaultTempo = 125;
00305         m_nMinPeriod = 14 << 2;
00306         m_nMaxPeriod = 3424 << 2;
00307         memcpy(m_szNames, lpStream, 20);
00308         // Setting channels pan
00309         for (UINT ich=0; ich<m_nChannels; ich++)
00310         {
00311                 ChnSettings[ich].nVolume = 64;
00312                 if (gdwSoundSetup & SNDMIX_MAXDEFAULTPAN)
00313                         ChnSettings[ich].nPan = (((ich&3)==1) || ((ich&3)==2)) ? 256 : 0;
00314                 else
00315                         ChnSettings[ich].nPan = (((ich&3)==1) || ((ich&3)==2)) ? 0xC0 : 0x40;
00316         }
00317         // Reading channels
00318         for (UINT ipat=0; ipat<nbp; ipat++)
00319         {
00320                 if (ipat < MAX_PATTERNS)
00321                 {
00322                         if ((Patterns[ipat] = AllocatePattern(64, m_nChannels)) == NULL) break;
00323                         PatternSize[ipat] = 64;
00324                         if (dwMemPos + m_nChannels*256 >= dwMemLength) break;
00325                         MODCOMMAND *m = Patterns[ipat];
00326                         LPCBYTE p = lpStream + dwMemPos;
00327                         for (UINT j=m_nChannels*64; j; m++,p+=4,j--)
00328                         {
00329                                 BYTE A0=p[0], A1=p[1], A2=p[2], A3=p[3];
00330                                 UINT n = ((((UINT)A0 & 0x0F) << 8) | (A1));
00331                                 if ((n) && (n != 0xFFF)) m->note = GetNoteFromPeriod(n << 2);
00332                                 m->instr = ((UINT)A2 >> 4) | (A0 & 0x10);
00333                                 m->command = A2 & 0x0F;
00334                                 m->param = A3;
00335                                 if ((m->command) || (m->param)) ConvertModCommand(m);
00336                         }
00337                 }
00338                 dwMemPos += m_nChannels*256;
00339         }
00340         // Reading instruments
00341         DWORD dwErrCheck = 0;
00342         for (UINT ismp=1; ismp<=m_nSamples; ismp++) if (Ins[ismp].nLength)
00343         {
00344                 LPSTR p = (LPSTR)(lpStream+dwMemPos);
00345                 UINT flags = 0;
00346                 if (dwMemPos + 5 >= dwMemLength) break;
00347                 if (!strnicmp(p, "ADPCM", 5))
00348                 {
00349                         flags = 3;
00350                         p += 5;
00351                         dwMemPos += 5;
00352                 }
00353                 DWORD dwSize = ReadSample(&Ins[ismp], flags, p, dwMemLength - dwMemPos);
00354                 if (dwSize)
00355                 {
00356                         dwMemPos += dwSize;
00357                         dwErrCheck++;
00358                 }
00359         }
00360 #ifdef MODPLUG_TRACKER
00361         return TRUE;
00362 #else
00363         return (dwErrCheck) ? TRUE : FALSE;
00364 #endif
00365 }
00366 
00367 
00368 #ifndef MODPLUG_NO_FILESAVE
00369 #pragma warning(disable:4100)
00370 
00371 BOOL CSoundFile::SaveMod(LPCSTR lpszFileName, UINT nPacking)
00372 //----------------------------------------------------------
00373 {
00374         BYTE insmap[32];
00375         UINT inslen[32];
00376         BYTE bTab[32];
00377         BYTE ord[128];
00378         FILE *f;
00379 
00380         if ((!m_nChannels) || (!lpszFileName)) return FALSE;
00381         if ((f = fopen(lpszFileName, "wb")) == NULL) return FALSE;
00382         memset(ord, 0, sizeof(ord));
00383         memset(inslen, 0, sizeof(inslen));
00384         if (m_nInstruments)
00385         {
00386                 memset(insmap, 0, sizeof(insmap));
00387                 for (UINT i=1; i<32; i++) if (Headers[i])
00388                 {
00389                         for (UINT j=0; j<128; j++) if (Headers[i]->Keyboard[j])
00390                         {
00391                                 insmap[i] = Headers[i]->Keyboard[j];
00392                                 break;
00393                         }
00394                 }
00395         } else
00396         {
00397                 for (UINT i=0; i<32; i++) insmap[i] = (BYTE)i;
00398         }
00399         // Writing song name
00400         fwrite(m_szNames, 20, 1, f);
00401         // Writing instrument definition
00402         for (UINT iins=1; iins<=31; iins++)
00403         {
00404                 MODINSTRUMENT *pins = &Ins[insmap[iins]];
00405                 memcpy(bTab, m_szNames[iins],22);
00406                 inslen[iins] = pins->nLength;
00407                 if (inslen[iins] > 0x1fff0) inslen[iins] = 0x1fff0;
00408                 bTab[22] = inslen[iins] >> 9;
00409                 bTab[23] = inslen[iins] >> 1;
00410                 if (pins->RelativeTone < 0) bTab[24] = 0x08; else
00411                 if (pins->RelativeTone > 0) bTab[24] = 0x07; else
00412                 bTab[24] = (BYTE)XM2MODFineTune(pins->nFineTune);
00413                 bTab[25] = pins->nVolume >> 2;
00414                 bTab[26] = pins->nLoopStart >> 9;
00415                 bTab[27] = pins->nLoopStart >> 1;
00416                 bTab[28] = (pins->nLoopEnd - pins->nLoopStart) >> 9;
00417                 bTab[29] = (pins->nLoopEnd - pins->nLoopStart) >> 1;
00418                 fwrite(bTab, 30, 1, f);
00419         }
00420         // Writing number of patterns
00421         UINT nbp=0, norders=128;
00422         for (UINT iord=0; iord<128; iord++)
00423         {
00424                 if (Order[iord] == 0xFF)
00425                 {
00426                         norders = iord;
00427                         break;
00428                 }
00429                 if ((Order[iord] < 0x80) && (nbp<=Order[iord])) nbp = Order[iord]+1;
00430         }
00431         bTab[0] = norders;
00432         bTab[1] = m_nRestartPos;
00433         fwrite(bTab, 2, 1, f);
00434         // Writing pattern list
00435         if (norders) memcpy(ord, Order, norders);
00436         fwrite(ord, 128, 1, f);
00437         // Writing signature
00438         if (m_nChannels == 4)
00439                 lstrcpy((LPSTR)&bTab, "M.K.");
00440         else
00441                 wsprintf((LPSTR)&bTab, "%luCHN", m_nChannels);
00442         fwrite(bTab, 4, 1, f);
00443         // Writing patterns
00444         for (UINT ipat=0; ipat<nbp; ipat++) if (Patterns[ipat])
00445         {
00446                 BYTE s[64*4];
00447                 MODCOMMAND *m = Patterns[ipat];
00448                 for (UINT i=0; i<64; i++) if (i < PatternSize[ipat])
00449                 {
00450                         LPBYTE p=s;
00451                         for (UINT c=0; c<m_nChannels; c++,p+=4,m++)
00452                         {
00453                                 UINT param = ModSaveCommand(m, FALSE);
00454                                 UINT command = param >> 8;
00455                                 param &= 0xFF;
00456                                 if (command > 0x0F) command = param = 0;
00457                                 if ((m->vol >= 0x10) && (m->vol <= 0x50) && (!command) && (!param)) { command = 0x0C; param = m->vol - 0x10; }
00458                                 UINT period = m->note;
00459                                 if (period)
00460                                 {
00461                                         if (period < 37) period = 37;
00462                                         period -= 37;
00463                                         if (period >= 6*12) period = 6*12-1;
00464                                         period = ProTrackerPeriodTable[period];
00465                                 }
00466                                 UINT instr = (m->instr > 31) ? 0 : m->instr;
00467                                 p[0] = ((period >> 8) & 0x0F) | (instr & 0x10);
00468                                 p[1] = period & 0xFF;
00469                                 p[2] = ((instr & 0x0F) << 4) | (command & 0x0F);
00470                                 p[3] = param;
00471                         }
00472                         fwrite(s, m_nChannels, 4, f);
00473                 } else
00474                 {
00475                         memset(s, 0, m_nChannels*4);
00476                         fwrite(s, m_nChannels, 4, f);
00477                 }
00478         }
00479         // Writing instruments
00480         for (UINT ismpd=1; ismpd<=31; ismpd++) if (inslen[ismpd])
00481         {
00482                 MODINSTRUMENT *pins = &Ins[insmap[ismpd]];
00483                 UINT flags = RS_PCM8S;
00484 #ifndef NO_PACKING
00485                 if (!(pins->uFlags & (CHN_16BIT|CHN_STEREO)))
00486                 {
00487                         if ((nPacking) && (CanPackSample(pins->pSample, inslen[ismpd], nPacking)))
00488                         {
00489                                 fwrite("ADPCM", 1, 5, f);
00490                                 flags = RS_ADPCM4;
00491                         }
00492                 }
00493 #endif
00494                 WriteSample(f, pins, flags, inslen[ismpd]);
00495         }
00496         fclose(f);
00497         return TRUE;
00498 }
00499 
00500 #pragma warning(default:4100)
00501 #endif // MODPLUG_NO_FILESAVE

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