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

sndfile.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 <math.h>       //for GCCFIX
00012 #include "stdafx.h"
00013 #include "sndfile.h"
00014 
00015 #define MMCMP_SUPPORT
00016 
00017 #ifdef MMCMP_SUPPORT
00018 extern BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength);
00019 #endif
00020 
00021 // External decompressors
00022 extern void AMSUnpack(const char *psrc, UINT inputlen, char *pdest, UINT dmax, char packcharacter);
00023 extern WORD MDLReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n);
00024 extern int DMFUnpack(LPBYTE psample, LPBYTE ibuf, LPBYTE ibufmax, UINT maxlen);
00025 extern DWORD ITReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n);
00026 extern void ITUnpack8Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215);
00027 extern void ITUnpack16Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215);
00028 
00029 
00030 #define MAX_PACK_TABLES         3
00031 
00032 
00033 // Compression table
00034 static const signed char UnpackTable[MAX_PACK_TABLES][16] = 
00035 //--------------------------------------------
00036 {
00037         // CPU-generated dynamic table
00038         {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
00039         // u-Law table
00040         {0, 1, 2, 4, 8, 16, 32, 64,
00041         -1, -2, -4, -8, -16, -32, -48, -64},
00042         // Linear table
00043         {0, 1, 2, 3, 5, 7, 12, 19,
00044         -1, -2, -3, -5, -7, -12, -19, -31}
00045 };
00046 
00047 
00049 // CSoundFile
00050 
00051 CSoundFile::CSoundFile()
00052 //----------------------
00053 {
00054         m_nType = MOD_TYPE_NONE;
00055         m_dwSongFlags = 0;
00056         m_nChannels = 0;
00057         m_nMixChannels = 0;
00058         m_nSamples = 0;
00059         m_nInstruments = 0;
00060         m_nPatternNames = 0;
00061         m_lpszPatternNames = NULL;
00062         m_lpszSongComments = NULL;
00063         m_nFreqFactor = m_nTempoFactor = 128;
00064         m_nMasterVolume = 128;
00065         m_nMinPeriod = 0x20;
00066         m_nMaxPeriod = 0x7FFF;
00067         m_nRepeatCount = 0;
00068         memset(Chn, 0, sizeof(Chn));
00069         memset(ChnMix, 0, sizeof(ChnMix));
00070         memset(Ins, 0, sizeof(Ins));
00071         memset(ChnSettings, 0, sizeof(ChnSettings));
00072         memset(Headers, 0, sizeof(Headers));
00073         memset(Order, 0xFF, sizeof(Order));
00074         memset(Patterns, 0, sizeof(Patterns));
00075         memset(m_szNames, 0, sizeof(m_szNames));
00076         memset(m_MixPlugins, 0, sizeof(m_MixPlugins));
00077 }
00078 
00079 
00080 CSoundFile::~CSoundFile()
00081 //-----------------------
00082 {       
00083         Destroy();
00084 }
00085 
00086 
00087 BOOL CSoundFile::Create(LPCBYTE lpStream, DWORD dwMemLength)
00088 //----------------------------------------------------------
00089 {
00090         int i;
00091 
00092         m_nType = MOD_TYPE_NONE;
00093         m_dwSongFlags = 0;
00094         m_nChannels = 0;
00095         m_nMixChannels = 0;
00096         m_nSamples = 0;
00097         m_nInstruments = 0;
00098         m_nFreqFactor = m_nTempoFactor = 128;
00099         m_nMasterVolume = 128;
00100         m_nDefaultGlobalVolume = 256;
00101         m_nGlobalVolume = 256;
00102         m_nOldGlbVolSlide = 0;
00103         m_nDefaultSpeed = 6;
00104         m_nDefaultTempo = 125;
00105         m_nPatternDelay = 0;
00106         m_nFrameDelay = 0;
00107         m_nNextRow = 0;
00108         m_nRow = 0;
00109         m_nPattern = 0;
00110         m_nCurrentPattern = 0;
00111         m_nNextPattern = 0;
00112         m_nRestartPos = 0;
00113         m_nMinPeriod = 16;
00114         m_nMaxPeriod = 32767;
00115         m_nSongPreAmp = 0x30;
00116         m_nPatternNames = 0;
00117         m_nMaxOrderPosition = 0;
00118         m_lpszPatternNames = NULL;
00119         m_lpszSongComments = NULL;
00120         memset(Ins, 0, sizeof(Ins));
00121         memset(ChnMix, 0, sizeof(ChnMix));
00122         memset(Chn, 0, sizeof(Chn));
00123         memset(Headers, 0, sizeof(Headers));
00124         memset(Order, 0xFF, sizeof(Order));
00125         memset(Patterns, 0, sizeof(Patterns));
00126         memset(m_szNames, 0, sizeof(m_szNames));
00127         memset(m_MixPlugins, 0, sizeof(m_MixPlugins));
00128         ResetMidiCfg();
00129         for (UINT npt=0; npt<MAX_PATTERNS; npt++) PatternSize[npt] = 64;
00130         for (UINT nch=0; nch<MAX_BASECHANNELS; nch++)
00131         {
00132                 ChnSettings[nch].nPan = 128;
00133                 ChnSettings[nch].nVolume = 64;
00134                 ChnSettings[nch].dwFlags = 0;
00135                 ChnSettings[nch].szName[0] = 0;
00136         }
00137         if (lpStream)
00138         {
00139 #ifdef MMCMP_SUPPORT
00140                 BOOL bMMCmp = MMCMP_Unpack(&lpStream, &dwMemLength);
00141 #endif
00142                 if ((!ReadXM(lpStream, dwMemLength))
00143                  && (!ReadIT(lpStream, dwMemLength))
00144                  && (!ReadS3M(lpStream, dwMemLength))
00145 //               && (!ReadWav(lpStream, dwMemLength))
00146 #ifndef MODPLUG_BASIC_SUPPORT
00147                  && (!ReadSTM(lpStream, dwMemLength))
00148                  && (!ReadMed(lpStream, dwMemLength))
00149                  && (!ReadMTM(lpStream, dwMemLength))
00150                  && (!ReadMDL(lpStream, dwMemLength))
00151                  && (!ReadDBM(lpStream, dwMemLength))
00152                  && (!Read669(lpStream, dwMemLength))
00153                  && (!ReadFAR(lpStream, dwMemLength))
00154                  && (!ReadAMS(lpStream, dwMemLength))
00155                  && (!ReadOKT(lpStream, dwMemLength))
00156                  && (!ReadPTM(lpStream, dwMemLength))
00157                  && (!ReadUlt(lpStream, dwMemLength))
00158                  && (!ReadDMF(lpStream, dwMemLength))
00159                  && (!ReadDSM(lpStream, dwMemLength))
00160                  && (!ReadUMX(lpStream, dwMemLength))
00161                  && (!ReadAMF(lpStream, dwMemLength))
00162                  && (!ReadPSM(lpStream, dwMemLength))
00163                  && (!ReadMT2(lpStream, dwMemLength))
00164 #endif // MODPLUG_BASIC_SUPPORT
00165                  && (!ReadMod(lpStream, dwMemLength))) m_nType = MOD_TYPE_NONE;
00166 #ifdef MMCMP_SUPPORT
00167                 if (bMMCmp)
00168                 {
00169                         GlobalFreePtr(lpStream);
00170                         lpStream = NULL;
00171                 }
00172 #endif
00173         }
00174         // Adjust song names
00175         for (i=0; i<MAX_SAMPLES; i++)
00176         {
00177                 LPSTR p = m_szNames[i];
00178                 int j = 31;
00179                 p[j] = 0;
00180                 while ((j>=0) && (p[j]<=' ')) p[j--] = 0;
00181                 while (j>=0)
00182                 {
00183                         if (((BYTE)p[j]) < ' ') p[j] = ' ';
00184                         j--;
00185                 }
00186         }
00187         // Adjust channels
00188         for (i=0; i<MAX_BASECHANNELS; i++)
00189         {
00190                 if (ChnSettings[i].nVolume > 64) ChnSettings[i].nVolume = 64;
00191                 if (ChnSettings[i].nPan > 256) ChnSettings[i].nPan = 128;
00192                 Chn[i].nPan = ChnSettings[i].nPan;
00193                 Chn[i].nGlobalVol = ChnSettings[i].nVolume;
00194                 Chn[i].dwFlags = ChnSettings[i].dwFlags;
00195                 Chn[i].nVolume = 256;
00196                 Chn[i].nCutOff = 0x7F;
00197         }
00198         // Checking instruments
00199         MODINSTRUMENT *pins = Ins;
00200 
00201         for (i=0; i<MAX_INSTRUMENTS; i++, pins++)
00202         {
00203                 if (pins->pSample)
00204                 {
00205                         if (pins->nLoopEnd > pins->nLength) pins->nLoopEnd = pins->nLength;
00206                         if (pins->nLoopStart + 3 >= pins->nLoopEnd)
00207                         {
00208                                 pins->nLoopStart = 0;
00209                                 pins->nLoopEnd = 0;
00210                         }
00211                         if (pins->nSustainEnd > pins->nLength) pins->nSustainEnd = pins->nLength;
00212                         if (pins->nSustainStart + 3 >= pins->nSustainEnd)
00213                         {
00214                                 pins->nSustainStart = 0;
00215                                 pins->nSustainEnd = 0;
00216                         }
00217                 } else
00218                 {
00219                         pins->nLength = 0;
00220                         pins->nLoopStart = 0;
00221                         pins->nLoopEnd = 0;
00222                         pins->nSustainStart = 0;
00223                         pins->nSustainEnd = 0;
00224                 }
00225                 if (!pins->nLoopEnd) pins->uFlags &= ~CHN_LOOP;
00226                 if (!pins->nSustainEnd) pins->uFlags &= ~CHN_SUSTAINLOOP;
00227                 if (pins->nGlobalVol > 64) pins->nGlobalVol = 64;
00228         }
00229         // Check invalid instruments
00230         while ((m_nInstruments > 0) && (!Headers[m_nInstruments])) m_nInstruments--;
00231         // Set default values
00232         if (m_nSongPreAmp < 0x20) m_nSongPreAmp = 0x20;
00233         if (m_nDefaultTempo < 32) m_nDefaultTempo = 125;
00234         if (!m_nDefaultSpeed) m_nDefaultSpeed = 6;
00235         m_nMusicSpeed = m_nDefaultSpeed;
00236         m_nMusicTempo = m_nDefaultTempo;
00237         m_nGlobalVolume = m_nDefaultGlobalVolume;
00238         m_nNextPattern = 0;
00239         m_nCurrentPattern = 0;
00240         m_nPattern = 0;
00241         m_nBufferCount = 0;
00242         m_nTickCount = m_nMusicSpeed;
00243         m_nNextRow = 0;
00244         m_nRow = 0;
00245         if ((m_nRestartPos >= MAX_ORDERS) || (Order[m_nRestartPos] >= MAX_PATTERNS)) m_nRestartPos = 0;
00246         // Load plugins
00247         if (gpMixPluginCreateProc)
00248         {
00249                 for (UINT iPlug=0; iPlug<MAX_MIXPLUGINS; iPlug++)
00250                 {
00251                         if ((m_MixPlugins[iPlug].Info.dwPluginId1)
00252                          || (m_MixPlugins[iPlug].Info.dwPluginId2))
00253                         {
00254                                 gpMixPluginCreateProc(&m_MixPlugins[iPlug]);
00255                                 if (m_MixPlugins[iPlug].pMixPlugin)
00256                                 {
00257                                         m_MixPlugins[iPlug].pMixPlugin->RestoreAllParameters();
00258                                 }
00259                         }
00260                 }
00261         }
00262         if (m_nType)
00263         {
00264                 UINT maxpreamp = 0x10+(m_nChannels*8);
00265                 if (maxpreamp > 100) maxpreamp = 100;
00266                 if (m_nSongPreAmp > maxpreamp) m_nSongPreAmp = maxpreamp;
00267                 return TRUE;
00268         }
00269         return FALSE;
00270 }
00271 
00272 
00273 BOOL CSoundFile::Destroy()
00274 
00275 //------------------------
00276 {
00277         int i;
00278         for (i=0; i<MAX_PATTERNS; i++) if (Patterns[i])
00279         {
00280                 FreePattern(Patterns[i]);
00281                 Patterns[i] = NULL;
00282         }
00283         m_nPatternNames = 0;
00284         if (m_lpszPatternNames)
00285         {
00286                 delete m_lpszPatternNames;
00287                 m_lpszPatternNames = NULL;
00288         }
00289         if (m_lpszSongComments)
00290         {
00291                 delete m_lpszSongComments;
00292                 m_lpszSongComments = NULL;
00293         }
00294         for (i=1; i<MAX_SAMPLES; i++)
00295         {
00296                 MODINSTRUMENT *pins = &Ins[i];
00297                 if (pins->pSample)
00298                 {
00299                         FreeSample(pins->pSample);
00300                         pins->pSample = NULL;
00301                 }
00302         }
00303         for (i=0; i<MAX_INSTRUMENTS; i++)
00304         {
00305                 if (Headers[i])
00306                 {
00307                         delete Headers[i];
00308                         Headers[i] = NULL;
00309                 }
00310         }
00311         for (i=0; i<MAX_MIXPLUGINS; i++)
00312         {
00313                 if ((m_MixPlugins[i].nPluginDataSize) && (m_MixPlugins[i].pPluginData))
00314                 {
00315                         m_MixPlugins[i].nPluginDataSize = 0;
00316                         delete [] (signed char*)m_MixPlugins[i].pPluginData;
00317                         m_MixPlugins[i].pPluginData = NULL;
00318                 }
00319                 m_MixPlugins[i].pMixState = NULL;
00320                 if (m_MixPlugins[i].pMixPlugin)
00321                 {
00322                         m_MixPlugins[i].pMixPlugin->Release();
00323                         m_MixPlugins[i].pMixPlugin = NULL;
00324                 }
00325         }
00326         m_nType = MOD_TYPE_NONE;
00327         m_nChannels = m_nSamples = m_nInstruments = 0;
00328         return TRUE;
00329 }
00330 
00331 
00333 // Memory Allocation
00334 
00335 MODCOMMAND *CSoundFile::AllocatePattern(UINT rows, UINT nchns)
00336 //------------------------------------------------------------
00337 {
00338         MODCOMMAND *p = new MODCOMMAND[rows*nchns];
00339         if (p) memset(p, 0, rows*nchns*sizeof(MODCOMMAND));
00340         return p;
00341 }
00342 
00343 
00344 void CSoundFile::FreePattern(LPVOID pat)
00345 //--------------------------------------
00346 {
00347         if (pat) delete [] (signed char*)pat;
00348 }
00349 
00350 
00351 signed char* CSoundFile::AllocateSample(UINT nbytes)
00352 //-------------------------------------------
00353 {
00354         signed char * p = (signed char *)GlobalAllocPtr(GHND, (nbytes+39) & ~7);
00355         if (p) p += 16;
00356         return p;
00357 }
00358 
00359 
00360 void CSoundFile::FreeSample(LPVOID p)
00361 //-----------------------------------
00362 {
00363         if (p)
00364         {
00365                 GlobalFreePtr(((LPSTR)p)-16);
00366         }
00367 }
00368 
00369 
00371 // Misc functions
00372 
00373 void CSoundFile::ResetMidiCfg()
00374 //-----------------------------
00375 {
00376         memset(&m_MidiCfg, 0, sizeof(m_MidiCfg));
00377         lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_START*32], "FF");
00378         lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_STOP*32], "FC");
00379         lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_NOTEON*32], "9c n v");
00380         lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_NOTEOFF*32], "9c n 0");
00381         lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_PROGRAM*32], "Cc p");
00382         lstrcpy(&m_MidiCfg.szMidiSFXExt[0], "F0F000z");
00383         for (int iz=0; iz<16; iz++) wsprintf(&m_MidiCfg.szMidiZXXExt[iz*32], "F0F001%02X", iz*8);
00384 }
00385 
00386 
00387 UINT CSoundFile::GetNumChannels() const
00388 //-------------------------------------
00389 {
00390         UINT n = 0;
00391         for (UINT i=0; i<m_nChannels; i++) if (ChnSettings[i].nVolume) n++;
00392         return n;
00393 }
00394 
00395 
00396 UINT CSoundFile::GetSongComments(LPSTR s, UINT len, UINT linesize)
00397 //----------------------------------------------------------------
00398 {
00399         LPCSTR p = m_lpszSongComments;
00400         if (!p) return 0;
00401         UINT i = 2, ln=0;
00402         if ((len) && (s)) s[0] = '\x0D';
00403         if ((len > 1) && (s)) s[1] = '\x0A';
00404         while ((*p)     && (i+2 < len))
00405         {
00406                 BYTE c = (BYTE)*p++;
00407                 if ((c == 0x0D) || ((c == ' ') && (ln >= linesize)))
00408                         { if (s) { s[i++] = '\x0D'; s[i++] = '\x0A'; } else i+= 2; ln=0; }
00409                 else
00410                 if (c >= 0x20) { if (s) s[i++] = c; else i++; ln++; }
00411         }
00412         if (s) s[i] = 0;
00413         return i;
00414 }
00415 
00416 
00417 UINT CSoundFile::GetRawSongComments(LPSTR s, UINT len, UINT linesize)
00418 //-------------------------------------------------------------------
00419 {
00420         LPCSTR p = m_lpszSongComments;
00421         if (!p) return 0;
00422         UINT i = 0, ln=0;
00423         while ((*p)     && (i < len-1))
00424         {
00425                 BYTE c = (BYTE)*p++;
00426                 if ((c == 0x0D) || (c == 0x0A))
00427                 {
00428                         if (ln) 
00429                         {
00430                                 while (ln < linesize) { if (s) s[i] = ' '; i++; ln++; }
00431                                 ln = 0;
00432                         }
00433                 } else
00434                 if ((c == ' ') && (!ln))
00435                 {
00436                         UINT k=0;
00437                         while ((p[k]) && (p[k] >= ' ')) k++;
00438                         if (k <= linesize)
00439                         {
00440                                 if (s) s[i] = ' ';
00441                                 i++;
00442                                 ln++;
00443                         }
00444                 } else
00445                 {
00446                         if (s) s[i] = c;
00447                         i++;
00448                         ln++;
00449                         if (ln == linesize) ln = 0;
00450                 }
00451         }
00452         if (ln)
00453         {
00454                 while ((ln < linesize) && (i < len))
00455                 {
00456                         if (s) s[i] = ' ';
00457                         i++;
00458                         ln++;
00459                 }
00460         }
00461         if (s) s[i] = 0;
00462         return i;
00463 }
00464 
00465 
00466 BOOL CSoundFile::SetWaveConfig(UINT nRate,UINT nBits,UINT nChannels,BOOL bMMX)
00467 //----------------------------------------------------------------------------
00468 {
00469         BOOL bReset = FALSE;
00470         DWORD d = gdwSoundSetup & ~SNDMIX_ENABLEMMX;
00471         if (bMMX) d |= SNDMIX_ENABLEMMX;
00472         if ((gdwMixingFreq != nRate) || (gnBitsPerSample != nBits) || (gnChannels != nChannels) || (d != gdwSoundSetup)) bReset = TRUE;
00473         gnChannels = nChannels;
00474         gdwSoundSetup = d;
00475         gdwMixingFreq = nRate;
00476         gnBitsPerSample = nBits;
00477         InitPlayer(bReset);
00478         return TRUE;
00479 }
00480 
00481 
00482 BOOL CSoundFile::SetResamplingMode(UINT nMode)
00483 //--------------------------------------------
00484 {
00485         DWORD d = gdwSoundSetup & ~(SNDMIX_NORESAMPLING|SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE);
00486         switch(nMode)
00487         {
00488         case SRCMODE_NEAREST:   d |= SNDMIX_NORESAMPLING; break;
00489         case SRCMODE_LINEAR:    break;
00490         case SRCMODE_SPLINE:    d |= SNDMIX_HQRESAMPLER; break;
00491         case SRCMODE_POLYPHASE: d |= (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE); break;
00492         default:
00493                 return FALSE;
00494         }
00495         gdwSoundSetup = d;
00496         return TRUE;
00497 }
00498 
00499 
00500 BOOL CSoundFile::SetMasterVolume(UINT nVol, BOOL bAdjustAGC)
00501 //----------------------------------------------------------
00502 {
00503         if (nVol < 1) nVol = 1;
00504         if (nVol > 0x200) nVol = 0x200; // x4 maximum
00505         if ((nVol < m_nMasterVolume) && (nVol) && (gdwSoundSetup & SNDMIX_AGC) && (bAdjustAGC))
00506         {
00507                 gnAGC = gnAGC * m_nMasterVolume / nVol;
00508                 if (gnAGC > AGC_UNITY) gnAGC = AGC_UNITY;
00509         }
00510         m_nMasterVolume = nVol;
00511         return TRUE;
00512 }
00513 
00514 
00515 void CSoundFile::SetAGC(BOOL b)
00516 //-----------------------------
00517 {
00518         if (b)
00519         {
00520                 if (!(gdwSoundSetup & SNDMIX_AGC))
00521                 {
00522                         gdwSoundSetup |= SNDMIX_AGC;
00523                         gnAGC = AGC_UNITY;
00524                 }
00525         } else gdwSoundSetup &= ~SNDMIX_AGC;
00526 }
00527 
00528 
00529 UINT CSoundFile::GetNumPatterns() const
00530 //-------------------------------------
00531 {
00532         UINT i = 0;
00533         while ((i < MAX_ORDERS) && (Order[i] < 0xFF)) i++;
00534         return i;
00535 }
00536 
00537 
00538 UINT CSoundFile::GetNumInstruments() const
00539 //----------------------------------------
00540 {
00541         UINT n=0;
00542         for (UINT i=0; i<MAX_INSTRUMENTS; i++) if (Ins[i].pSample) n++;
00543         return n;
00544 }
00545 
00546 
00547 UINT CSoundFile::GetMaxPosition() const
00548 //-------------------------------------
00549 {
00550         UINT max = 0;
00551         UINT i = 0;
00552 
00553         while ((i < MAX_ORDERS) && (Order[i] != 0xFF))
00554         {
00555                 if (Order[i] < MAX_PATTERNS) max += PatternSize[Order[i]];
00556                 i++;
00557         }
00558         return max;
00559 }
00560 
00561 
00562 UINT CSoundFile::GetCurrentPos() const
00563 //------------------------------------
00564 {
00565         UINT pos = 0;
00566 
00567         for (UINT i=0; i<m_nCurrentPattern; i++) if (Order[i] < MAX_PATTERNS)
00568                 pos += PatternSize[Order[i]];
00569         return pos + m_nRow; 
00570 }
00571 
00572 
00573 void CSoundFile::SetCurrentPos(UINT nPos)
00574 //---------------------------------------
00575 {
00576         UINT i, nPattern;
00577 
00578         for (i=0; i<MAX_CHANNELS; i++)
00579         {
00580                 Chn[i].nNote = Chn[i].nNewNote = Chn[i].nNewIns = 0;
00581                 Chn[i].pInstrument = NULL;
00582                 Chn[i].pHeader = NULL;
00583                 Chn[i].nPortamentoDest = 0;
00584                 Chn[i].nCommand = 0;
00585                 Chn[i].nPatternLoopCount = 0;
00586                 Chn[i].nPatternLoop = 0;
00587                 Chn[i].nFadeOutVol = 0;
00588                 Chn[i].dwFlags |= CHN_KEYOFF|CHN_NOTEFADE;
00589                 Chn[i].nTremorCount = 0;
00590         }
00591         if (!nPos)
00592         {
00593                 for (i=0; i<MAX_CHANNELS; i++)
00594                 {
00595                         Chn[i].nPeriod = 0;
00596                         Chn[i].nPos = Chn[i].nLength = 0;
00597                         Chn[i].nLoopStart = 0;
00598                         Chn[i].nLoopEnd = 0;
00599                         Chn[i].nROfs = Chn[i].nLOfs = 0;
00600                         Chn[i].pSample = NULL;
00601                         Chn[i].pInstrument = NULL;
00602                         Chn[i].pHeader = NULL;
00603                         Chn[i].nCutOff = 0x7F;
00604                         Chn[i].nResonance = 0;
00605                         Chn[i].nLeftVol = Chn[i].nRightVol = 0;
00606                         Chn[i].nNewLeftVol = Chn[i].nNewRightVol = 0;
00607                         Chn[i].nLeftRamp = Chn[i].nRightRamp = 0;
00608                         Chn[i].nVolume = 256;
00609                         if (i < MAX_BASECHANNELS)
00610                         {
00611                                 Chn[i].dwFlags = ChnSettings[i].dwFlags;
00612                                 Chn[i].nPan = ChnSettings[i].nPan;
00613                                 Chn[i].nGlobalVol = ChnSettings[i].nVolume;
00614                         } else
00615                         {
00616                                 Chn[i].dwFlags = 0;
00617                                 Chn[i].nPan = 128;
00618                                 Chn[i].nGlobalVol = 64;
00619                         }
00620                 }
00621                 m_nGlobalVolume = m_nDefaultGlobalVolume;
00622                 m_nMusicSpeed = m_nDefaultSpeed;
00623                 m_nMusicTempo = m_nDefaultTempo;
00624         }
00625         m_dwSongFlags &= ~(SONG_PATTERNLOOP|SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE);
00626         for (nPattern = 0; nPattern < MAX_ORDERS; nPattern++)
00627         {
00628                 UINT ord = Order[nPattern];
00629                 if (ord == 0xFE) continue;
00630                 if (ord == 0xFF) break;
00631                 if (ord < MAX_PATTERNS)
00632                 {
00633                         if (nPos < (UINT)PatternSize[ord]) break;
00634                         nPos -= PatternSize[ord];
00635                 }
00636         }
00637         // Buggy position ?
00638         if ((nPattern >= MAX_ORDERS)
00639          || (Order[nPattern] >= MAX_PATTERNS)
00640          || (nPos >= PatternSize[Order[nPattern]]))
00641         {
00642                 nPos = 0;
00643                 nPattern = 0;
00644         }
00645         UINT nRow = nPos;
00646         if ((nRow) && (Order[nPattern] < MAX_PATTERNS))
00647         {
00648                 MODCOMMAND *p = Patterns[Order[nPattern]];
00649                 if ((p) && (nRow < PatternSize[Order[nPattern]]))
00650                 {
00651                         BOOL bOk = FALSE;
00652                         while ((!bOk) && (nRow > 0))
00653                         {
00654                                 UINT n = nRow * m_nChannels;
00655                                 for (UINT k=0; k<m_nChannels; k++, n++)
00656                                 {
00657                                         if (p[n].note)
00658                                         {
00659                                                 bOk = TRUE;
00660                                                 break;
00661                                         }
00662                                 }
00663                                 if (!bOk) nRow--;
00664                         }
00665                 }
00666         }
00667         m_nNextPattern = nPattern;
00668         m_nNextRow = nRow;
00669         m_nTickCount = m_nMusicSpeed;
00670         m_nBufferCount = 0;
00671         m_nPatternDelay = 0;
00672         m_nFrameDelay = 0;
00673 }
00674 
00675 
00676 void CSoundFile::SetCurrentOrder(UINT nPos)
00677 //-----------------------------------------
00678 {
00679         while ((nPos < MAX_ORDERS) && (Order[nPos] == 0xFE)) nPos++;
00680         if ((nPos >= MAX_ORDERS) || (Order[nPos] >= MAX_PATTERNS)) return;
00681         for (UINT j=0; j<MAX_CHANNELS; j++)
00682         {
00683                 Chn[j].nPeriod = 0;
00684                 Chn[j].nNote = 0;
00685                 Chn[j].nPortamentoDest = 0;
00686                 Chn[j].nCommand = 0;
00687                 Chn[j].nPatternLoopCount = 0;
00688                 Chn[j].nPatternLoop = 0;
00689                 Chn[j].nTremorCount = 0;
00690         }
00691         if (!nPos)
00692         {
00693                 SetCurrentPos(0);
00694         } else
00695         {
00696                 m_nNextPattern = nPos;
00697                 m_nRow = m_nNextRow = 0;
00698                 m_nPattern = 0;
00699                 m_nTickCount = m_nMusicSpeed;
00700                 m_nBufferCount = 0;
00701                 m_nTotalCount = 0;
00702                 m_nPatternDelay = 0;
00703                 m_nFrameDelay = 0;
00704         }
00705         m_dwSongFlags &= ~(SONG_PATTERNLOOP|SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE);
00706 }
00707 
00708 
00709 void CSoundFile::ResetChannels()
00710 //------------------------------
00711 {
00712         m_dwSongFlags &= ~(SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE);
00713         m_nBufferCount = 0;
00714         for (UINT i=0; i<MAX_CHANNELS; i++)
00715         {
00716                 Chn[i].nROfs = Chn[i].nLOfs = 0;
00717         }
00718 }
00719 
00720 
00721 void CSoundFile::LoopPattern(int nPat, int nRow)
00722 //----------------------------------------------
00723 {
00724         if ((nPat < 0) || (nPat >= MAX_PATTERNS) || (!Patterns[nPat]))
00725         {
00726                 m_dwSongFlags &= ~SONG_PATTERNLOOP;
00727         } else
00728         {
00729                 if ((nRow < 0) || (nRow >= PatternSize[nPat])) nRow = 0;
00730                 m_nPattern = nPat;
00731                 m_nRow = m_nNextRow = nRow;
00732                 m_nTickCount = m_nMusicSpeed;
00733                 m_nPatternDelay = 0;
00734                 m_nFrameDelay = 0;
00735                 m_nBufferCount = 0;
00736                 m_dwSongFlags |= SONG_PATTERNLOOP;
00737         }
00738 }
00739 
00740 
00741 UINT CSoundFile::GetBestSaveFormat() const
00742 //----------------------------------------
00743 {
00744         if ((!m_nSamples) || (!m_nChannels)) return MOD_TYPE_NONE;
00745         if (!m_nType) return MOD_TYPE_NONE;
00746         if (m_nType & (MOD_TYPE_MOD|MOD_TYPE_OKT))
00747                 return MOD_TYPE_MOD;
00748         if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_STM|MOD_TYPE_ULT|MOD_TYPE_FAR|MOD_TYPE_PTM))
00749                 return MOD_TYPE_S3M;
00750         if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MED|MOD_TYPE_MTM|MOD_TYPE_MT2))
00751                 return MOD_TYPE_XM;
00752         return MOD_TYPE_IT;
00753 }
00754 
00755 
00756 UINT CSoundFile::GetSaveFormats() const
00757 //-------------------------------------
00758 {
00759         UINT n = 0;
00760         if ((!m_nSamples) || (!m_nChannels) || (m_nType == MOD_TYPE_NONE)) return 0;
00761         switch(m_nType)
00762         {
00763         case MOD_TYPE_MOD:      n = MOD_TYPE_MOD;
00764         case MOD_TYPE_S3M:      n = MOD_TYPE_S3M;
00765         }
00766         n |= MOD_TYPE_XM | MOD_TYPE_IT;
00767         if (!m_nInstruments)
00768         {
00769                 if (m_nSamples < 32) n |= MOD_TYPE_MOD;
00770                 n |= MOD_TYPE_S3M;
00771         }
00772         return n;
00773 }
00774 
00775 
00776 UINT CSoundFile::GetSampleName(UINT nSample,LPSTR s) const
00777 //--------------------------------------------------------
00778 {
00779         char sztmp[40] = "";      // changed from CHAR
00780         memcpy(sztmp, m_szNames[nSample],32);
00781         sztmp[31] = 0;
00782         if (s) strcpy(s, sztmp);
00783         return strlen(sztmp);
00784 }
00785 
00786 
00787 UINT CSoundFile::GetInstrumentName(UINT nInstr,LPSTR s) const
00788 //-----------------------------------------------------------
00789 {
00790         char sztmp[40] = "";  // changed from CHAR
00791         if ((nInstr >= MAX_INSTRUMENTS) || (!Headers[nInstr]))
00792         {
00793                 if (s) *s = 0;
00794                 return 0;
00795         }
00796         INSTRUMENTHEADER *penv = Headers[nInstr];
00797         memcpy(sztmp, penv->name, 32);
00798         sztmp[31] = 0;
00799         if (s) strcpy(s, sztmp);
00800         return strlen(sztmp);
00801 }
00802 
00803 
00804 #ifndef NO_PACKING
00805 UINT CSoundFile::PackSample(int &sample, int next)
00806 //------------------------------------------------
00807 {
00808         UINT i = 0;
00809         int delta = next - sample;
00810         if (delta >= 0)
00811         {
00812                 for (i=0; i<7; i++) if (delta <= (int)CompressionTable[i+1]) break;
00813         } else
00814         {
00815                 for (i=8; i<15; i++) if (delta >= (int)CompressionTable[i+1]) break;
00816         }
00817         sample += (int)CompressionTable[i];
00818         return i;
00819 }
00820 
00821 
00822 BOOL CSoundFile::CanPackSample(LPSTR pSample, UINT nLen, UINT nPacking, BYTE *result)
00823 //-----------------------------------------------------------------------------------
00824 {
00825         int pos, old, oldpos, besttable = 0;
00826         DWORD dwErr, dwTotal, dwResult;
00827         int i,j;
00828         
00829         if (result) *result = 0;
00830         if ((!pSample) || (nLen < 1024)) return FALSE;
00831         // Try packing with different tables
00832         dwResult = 0;
00833         for (j=1; j<MAX_PACK_TABLES; j++)
00834         {
00835                 memcpy(CompressionTable, UnpackTable[j], 16);
00836                 dwErr = 0;
00837                 dwTotal = 1;
00838                 old = pos = oldpos = 0;
00839                 for (i=0; i<(int)nLen; i++)
00840                 {
00841                         int s = (int)pSample[i];
00842                         PackSample(pos, s);
00843                         dwErr += abs(pos - oldpos);
00844                         dwTotal += abs(s - old);
00845                         old = s;
00846                         oldpos = pos;
00847                 }
00848                 dwErr = _muldiv(dwErr, 100, dwTotal);
00849                 if (dwErr >= dwResult)
00850                 {
00851                         dwResult = dwErr;
00852                         besttable = j;
00853                 }
00854         }
00855         memcpy(CompressionTable, UnpackTable[besttable], 16);
00856         if (result)
00857         {
00858                 if (dwResult > 100) *result     = 100; else *result = (BYTE)dwResult;
00859         }
00860         return (dwResult >= nPacking) ? TRUE : FALSE;
00861 }
00862 #endif // NO_PACKING
00863 
00864 #ifndef MODPLUG_NO_FILESAVE
00865 
00866 UINT CSoundFile::WriteSample(FILE *f, MODINSTRUMENT *pins, UINT nFlags, UINT nMaxLen)
00867 //-----------------------------------------------------------------------------------
00868 {
00869         UINT len = 0, bufcount;
00870         signed char buffer[4096];
00871         signed char *pSample = (signed char *)pins->pSample;
00872         UINT nLen = pins->nLength;
00873         
00874         if ((nMaxLen) && (nLen > nMaxLen)) nLen = nMaxLen;
00875         if ((!pSample) || (f == NULL) || (!nLen)) return 0;
00876         switch(nFlags)
00877         {
00878 #ifndef NO_PACKING
00879         // 3: 4-bit ADPCM data
00880         case RS_ADPCM4:
00881                 {
00882                         int pos; 
00883                         len = (nLen + 1) / 2;
00884                         fwrite(CompressionTable, 16, 1, f);
00885                         bufcount = 0;
00886                         pos = 0;
00887                         for (UINT j=0; j<len; j++)
00888                         {
00889                                 BYTE b;
00890                                 // Sample #1
00891                                 b = PackSample(pos, (int)pSample[j*2]);
00892                                 // Sample #2
00893                                 b |= PackSample(pos, (int)pSample[j*2+1]) << 4;
00894                                 buffer[bufcount++] = (signed char)b;
00895                                 if (bufcount >= sizeof(buffer))
00896                                 {
00897                                         fwrite(buffer, 1, bufcount, f);
00898                                         bufcount = 0;
00899                                 }
00900                         }
00901                         if (bufcount) fwrite(buffer, 1, bufcount, f);
00902                         len += 16;
00903                 }
00904                 break;
00905 #endif // NO_PACKING
00906 
00907         // 16-bit samples
00908         case RS_PCM16U:
00909         case RS_PCM16D:
00910         case RS_PCM16S:
00911                 {
00912                         short int *p = (short int *)pSample;
00913                         int s_old = 0, s_ofs;
00914                         len = nLen * 2;
00915                         bufcount = 0;
00916                         s_ofs = (nFlags == RS_PCM16U) ? 0x8000 : 0;
00917                         for (UINT j=0; j<nLen; j++)
00918                         {
00919                                 int s_new = *p;
00920                                 p++;
00921                                 if (pins->uFlags & CHN_STEREO)
00922                                 {
00923                                         s_new = (s_new + (*p) + 1) >> 1;
00924                                         p++;
00925                                 }
00926                                 if (nFlags == RS_PCM16D)
00927                                 {
00928                                         *((short *)(&buffer[bufcount])) = (short)(s_new - s_old);
00929                                         s_old = s_new;
00930                                 } else
00931                                 {
00932                                         *((short *)(&buffer[bufcount])) = (short)(s_new + s_ofs);
00933                                 }
00934                                 bufcount += 2;
00935                                 if (bufcount >= sizeof(buffer) - 1)
00936                                 {
00937                                         fwrite(buffer, 1, bufcount, f);
00938                                         bufcount = 0;
00939                                 }
00940                         }
00941                         if (bufcount) fwrite(buffer, 1, bufcount, f);
00942                 }
00943                 break;
00944 
00945 
00946         // 8-bit Stereo samples (not interleaved)
00947         case RS_STPCM8S:
00948         case RS_STPCM8U:
00949         case RS_STPCM8D:
00950                 {
00951                         int s_ofs = (nFlags == RS_STPCM8U) ? 0x80 : 0;
00952                         for (UINT iCh=0; iCh<2; iCh++)
00953                         {
00954                                 signed char *p = pSample + iCh;
00955                                 int s_old = 0;
00956 
00957                                 bufcount = 0;
00958                                 for (UINT j=0; j<nLen; j++)
00959                                 {
00960                                         int s_new = *p;
00961                                         p += 2;
00962                                         if (nFlags == RS_STPCM8D)
00963                                         {
00964                                                 buffer[bufcount++] = (signed char)(s_new - s_old);
00965                                                 s_old = s_new;
00966                                         } else
00967                                         {
00968                                                 buffer[bufcount++] = (signed char)(s_new + s_ofs);
00969                                         }
00970                                         if (bufcount >= sizeof(buffer))
00971                                         {
00972                                                 fwrite(buffer, 1, bufcount, f);
00973                                                 bufcount = 0;
00974                                         }
00975                                 }
00976                                 if (bufcount) fwrite(buffer, 1, bufcount, f);
00977                         }
00978                 }
00979                 len = nLen * 2;
00980                 break;
00981 
00982         // 16-bit Stereo samples (not interleaved)
00983         case RS_STPCM16S:
00984         case RS_STPCM16U:
00985         case RS_STPCM16D:
00986                 {
00987                         int s_ofs = (nFlags == RS_STPCM16U) ? 0x8000 : 0;
00988                         for (UINT iCh=0; iCh<2; iCh++)
00989                         {
00990                                 signed short *p = ((signed short *)pSample) + iCh;
00991                                 int s_old = 0;
00992 
00993                                 bufcount = 0;
00994                                 for (UINT j=0; j<nLen; j++)
00995                                 {
00996                                         int s_new = *p;
00997                                         p += 2;
00998                                         if (nFlags == RS_STPCM16D)
00999                                         {
01000                                                 *((short *)(&buffer[bufcount])) = (short)(s_new - s_old);
01001                                                 s_old = s_new;
01002                                         } else
01003                                         {
01004                                                 *((short *)(&buffer[bufcount])) = (short)(s_new + s_ofs);
01005                                         }
01006                                         bufcount += 2;
01007                                         if (bufcount >= sizeof(buffer))
01008                                         {
01009                                                 fwrite(buffer, 1, bufcount, f);
01010                                                 bufcount = 0;
01011                                         }
01012                                 }
01013                                 if (bufcount) fwrite(buffer, 1, bufcount, f);
01014                         }
01015                 }
01016                 len = nLen*4;
01017                 break;
01018 
01019         //      Stereo signed interleaved
01020         case RS_STIPCM8S:
01021         case RS_STIPCM16S:
01022                 len = nLen * 2;
01023                 if (nFlags == RS_STIPCM16S) len *= 2;
01024                 fwrite(pSample, 1, len, f);
01025                 break;
01026 
01027         // Default: assume 8-bit PCM data
01028         default:
01029                 len = nLen;
01030                 bufcount = 0;
01031                 {
01032                         signed char *p = pSample;
01033                         int sinc = (pins->uFlags & CHN_16BIT) ? 2 : 1;
01034                         int s_old = 0, s_ofs = (nFlags == RS_PCM8U) ? 0x80 : 0;
01035                         if (pins->uFlags & CHN_16BIT) p++;
01036                         for (UINT j=0; j<len; j++)
01037                         {
01038                                 int s_new = (signed char)(*p);
01039                                 p += sinc;
01040                                 if (pins->uFlags & CHN_STEREO)
01041                                 {
01042                                         s_new = (s_new + ((int)*p) + 1) >> 1;
01043                                         p += sinc;
01044                                 }
01045                                 if (nFlags == RS_PCM8D)
01046                                 {
01047                                         buffer[bufcount++] = (signed char)(s_new - s_old);
01048                                         s_old = s_new;
01049                                 } else
01050                                 {
01051                                         buffer[bufcount++] = (signed char)(s_new + s_ofs);
01052                                 }
01053                                 if (bufcount >= sizeof(buffer))
01054                                 {
01055                                         fwrite(buffer, 1, bufcount, f);
01056                                         bufcount = 0;
01057                                 }
01058                         }
01059                         if (bufcount) fwrite(buffer, 1, bufcount, f);
01060                 }
01061         }
01062         return len;
01063 }
01064 
01065 #endif // MODPLUG_NO_FILESAVE
01066 
01067 
01068 // Flags:
01069 //      0 = signed 8-bit PCM data (default)
01070 //      1 = unsigned 8-bit PCM data
01071 //      2 = 8-bit ADPCM data with linear table
01072 //      3 = 4-bit ADPCM data
01073 //      4 = 16-bit ADPCM data with linear table
01074 //      5 = signed 16-bit PCM data
01075 //      6 = unsigned 16-bit PCM data
01076 
01077 
01078 UINT CSoundFile::ReadSample(MODINSTRUMENT *pIns, UINT nFlags, LPCSTR lpMemFile, DWORD dwMemLength)
01079 //------------------------------------------------------------------------------------------------
01080 {
01081         UINT len = 0, mem = pIns->nLength+6;
01082 
01083         if ((!pIns) || (pIns->nLength < 4) || (!lpMemFile)) return 0;
01084         if (pIns->nLength > MAX_SAMPLE_LENGTH) pIns->nLength = MAX_SAMPLE_LENGTH;
01085         pIns->uFlags &= ~(CHN_16BIT|CHN_STEREO);
01086         if (nFlags & RSF_16BIT)
01087         {
01088                 mem *= 2;
01089                 pIns->uFlags |= CHN_16BIT;
01090         }
01091         if (nFlags & RSF_STEREO)
01092         {
01093                 mem *= 2;
01094                 pIns->uFlags |= CHN_STEREO;
01095         }
01096         if ((pIns->pSample = AllocateSample(mem)) == NULL)
01097         {
01098                 pIns->nLength = 0;
01099                 return 0;
01100         }
01101         switch(nFlags)
01102         {
01103         // 1: 8-bit unsigned PCM data
01104         case RS_PCM8U:
01105                 {
01106                         len = pIns->nLength;
01107                         if (len > dwMemLength) len = pIns->nLength = dwMemLength;
01108                         signed char *pSample = pIns->pSample;
01109                         for (UINT j=0; j<len; j++) pSample[j] = (signed char)(lpMemFile[j] - 0x80);
01110                 }
01111                 break;
01112 
01113         // 2: 8-bit ADPCM data with linear table
01114         case RS_PCM8D:
01115                 {
01116                         len = pIns->nLength;
01117                         if (len > dwMemLength) break;
01118                         signed char *pSample = pIns->pSample;
01119                         const signed char *p = (const signed char *)lpMemFile;
01120                         int delta = 0;
01121 
01122                         for (UINT j=0; j<len; j++)
01123                         {
01124                                 delta += p[j];
01125                                 *pSample++ = (signed char)delta;
01126                         }
01127                 }
01128                 break;
01129 
01130         // 3: 4-bit ADPCM data
01131         case RS_ADPCM4:
01132                 {
01133                         len = (pIns->nLength + 1) / 2;
01134                         if (len > dwMemLength - 16) break;
01135                         memcpy(CompressionTable, lpMemFile, 16);
01136                         lpMemFile += 16;
01137                         signed char *pSample = pIns->pSample;
01138                         signed char delta = 0;
01139                         for (UINT j=0; j<len; j++)
01140                         {
01141                                 BYTE b0 = (BYTE)lpMemFile[j];
01142                                 BYTE b1 = (BYTE)(lpMemFile[j] >> 4);
01143                                 delta = (signed char)GetDeltaValue((int)delta, b0);
01144                                 pSample[0] = delta;
01145                                 delta = (signed char)GetDeltaValue((int)delta, b1);
01146                                 pSample[1] = delta;
01147                                 pSample += 2;
01148                         }
01149                         len += 16;
01150                 }
01151                 break;
01152 
01153         // 4: 16-bit ADPCM data with linear table
01154         case RS_PCM16D:
01155                 {
01156                         len = pIns->nLength * 2;
01157                         if (len > dwMemLength) break;
01158                         short int *pSample = (short int *)pIns->pSample;
01159                         short int *p = (short int *)lpMemFile;
01160                         int delta16 = 0;
01161                         for (UINT j=0; j<len; j+=2)
01162                         {
01163                                 delta16 += bswapLE16(*p++);
01164                                 *pSample++ = (short int)delta16;
01165                         }
01166                 }
01167                 break;
01168 
01169         // 5: 16-bit signed PCM data
01170         case RS_PCM16S:
01171                 {
01172                 len = pIns->nLength * 2;
01173                 if (len <= dwMemLength) memcpy(pIns->pSample, lpMemFile, len);
01174                         short int *pSample = (short int *)pIns->pSample;
01175                         for (UINT j=0; j<len; j+=2)
01176                         {
01177                                 *pSample++ = bswapLE16(*pSample);
01178                         }
01179                 }
01180                 break;
01181 
01182         // 16-bit signed mono PCM motorola byte order
01183         case RS_PCM16M:
01184                 len = pIns->nLength * 2;
01185                 if (len > dwMemLength) len = dwMemLength & ~1;
01186                 if (len > 1)
01187                 {
01188                         signed char *pSample = (signed char *)pIns->pSample;
01189                         signed char *pSrc = (signed char *)lpMemFile;
01190                         for (UINT j=0; j<len; j+=2)
01191                         {
01192                                 // pSample[j] = pSrc[j+1];
01193                                 // pSample[j+1] = pSrc[j];
01194                                 *((unsigned short *)(pSample+j)) = bswapBE16(*((unsigned short *)(pSrc+j)));
01195                         }
01196                 }
01197                 break;
01198 
01199         // 6: 16-bit unsigned PCM data
01200         case RS_PCM16U:
01201                 {
01202                         len = pIns->nLength * 2;
01203                         if (len > dwMemLength) break;
01204                         short int *pSample = (short int *)pIns->pSample;
01205                         short int *pSrc = (short int *)lpMemFile;
01206                         for (UINT j=0; j<len; j+=2) *pSample++ = bswapLE16(*(pSrc++)) - 0x8000;
01207                 }
01208                 break;
01209 
01210         // 16-bit signed stereo big endian
01211         case RS_STPCM16M:
01212                 len = pIns->nLength * 2;
01213                 if (len*2 <= dwMemLength)
01214                 {
01215                         signed char *pSample = (signed char *)pIns->pSample;
01216                         signed char *pSrc = (signed char *)lpMemFile;
01217                         for (UINT j=0; j<len; j+=2)
01218                         {
01219                                 // pSample[j*2] = pSrc[j+1];
01220                                 // pSample[j*2+1] = pSrc[j];
01221                                 // pSample[j*2+2] = pSrc[j+1+len];
01222                                 // pSample[j*2+3] = pSrc[j+len];
01223                                 *((unsigned short *)(pSample+j*2)) = bswapBE16(*((unsigned short *)(pSrc+j)));
01224                                 *((unsigned short *)(pSample+j*2+2)) = bswapBE16(*((unsigned short *)(pSrc+j+len)));
01225                         }
01226                         len *= 2;
01227                 }
01228                 break;
01229 
01230         // 8-bit stereo samples
01231         case RS_STPCM8S:
01232         case RS_STPCM8U:
01233         case RS_STPCM8D:
01234                 {
01235                         int iadd_l = 0, iadd_r = 0;
01236                         if (nFlags == RS_STPCM8U) { iadd_l = iadd_r = -128; }
01237                         len = pIns->nLength;
01238                         signed char *psrc = (signed char *)lpMemFile;
01239                         signed char *pSample = (signed char *)pIns->pSample;
01240                         if (len*2 > dwMemLength) break;
01241                         for (UINT j=0; j<len; j++)
01242                         {
01243                                 pSample[j*2] = (signed char)(psrc[0] + iadd_l);
01244                                 pSample[j*2+1] = (signed char)(psrc[len] + iadd_r);
01245                                 psrc++;
01246                                 if (nFlags == RS_STPCM8D)
01247                                 {
01248                                         iadd_l = pSample[j*2];
01249                                         iadd_r = pSample[j*2+1];
01250                                 }
01251                         }
01252                         len *= 2;
01253                 }
01254                 break;
01255 
01256         // 16-bit stereo samples
01257         case RS_STPCM16S:
01258         case RS_STPCM16U:
01259         case RS_STPCM16D:
01260                 {
01261                         int iadd_l = 0, iadd_r = 0;
01262                         if (nFlags == RS_STPCM16U) { iadd_l = iadd_r = -0x8000; }
01263                         len = pIns->nLength;
01264                         short int *psrc = (short int *)lpMemFile;
01265                         short int *pSample = (short int *)pIns->pSample;
01266                         if (len*4 > dwMemLength) break;
01267                         for (UINT j=0; j<len; j++)
01268                         {
01269                                 pSample[j*2] = (short int) (bswapLE16(psrc[0]) + iadd_l);
01270                                 pSample[j*2+1] = (short int) (bswapLE16(psrc[len]) + iadd_r);
01271                                 psrc++;
01272                                 if (nFlags == RS_STPCM16D)
01273                                 {
01274                                         iadd_l = pSample[j*2];
01275                                         iadd_r = pSample[j*2+1];
01276                                 }
01277                         }
01278                         len *= 4;
01279                 }
01280                 break;
01281 
01282         // IT 2.14 compressed samples
01283         case RS_IT2148:
01284         case RS_IT21416:
01285         case RS_IT2158:
01286         case RS_IT21516:
01287                 len = dwMemLength;
01288                 if (len < 4) break;
01289                 if ((nFlags == RS_IT2148) || (nFlags == RS_IT2158))
01290                         ITUnpack8Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, (nFlags == RS_IT2158));
01291                 else
01292                         ITUnpack16Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, (nFlags == RS_IT21516));
01293                 break;
01294 
01295 #ifndef MODPLUG_BASIC_SUPPORT
01296 #ifndef FASTSOUNDLIB
01297         // 8-bit interleaved stereo samples
01298         case RS_STIPCM8S:
01299         case RS_STIPCM8U:
01300                 {
01301                         int iadd = 0;
01302                         if (nFlags == RS_STIPCM8U) { iadd = -0x80; }
01303                         len = pIns->nLength;
01304                         if (len*2 > dwMemLength) len = dwMemLength >> 1;
01305                         LPBYTE psrc = (LPBYTE)lpMemFile;
01306                         LPBYTE pSample = (LPBYTE)pIns->pSample;
01307                         for (UINT j=0; j<len; j++)
01308                         {
01309                                 pSample[j*2] = (signed char)(psrc[0] + iadd);
01310                                 pSample[j*2+1] = (signed char)(psrc[1] + iadd);
01311                                 psrc+=2;
01312                         }
01313                         len *= 2;
01314                 }
01315                 break;
01316 
01317         // 16-bit interleaved stereo samples
01318         case RS_STIPCM16S:
01319         case RS_STIPCM16U:
01320                 {
01321                         int iadd = 0;
01322                         if (nFlags == RS_STIPCM16U) iadd = -32768;
01323                         len = pIns->nLength;
01324                         if (len*4 > dwMemLength) len = dwMemLength >> 2;
01325                         short int *psrc = (short int *)lpMemFile;
01326                         short int *pSample = (short int *)pIns->pSample;
01327                         for (UINT j=0; j<len; j++)
01328                         {
01329                                 pSample[j*2] = (short int)(bswapLE16(psrc[0]) + iadd);
01330                                 pSample[j*2+1] = (short int)(bswapLE16(psrc[1]) + iadd);
01331                                 psrc += 2;
01332                         }
01333                         len *= 4;
01334                 }
01335                 break;
01336 
01337         // AMS compressed samples
01338         case RS_AMS8:
01339         case RS_AMS16:
01340                 len = 9;
01341                 if (dwMemLength > 9)
01342                 {
01343                         const char *psrc = lpMemFile;
01344                         char packcharacter = lpMemFile[8], *pdest = (char *)pIns->pSample;
01345                         len += bswapLE32(*((LPDWORD)(lpMemFile+4)));
01346                         if (len > dwMemLength) len = dwMemLength;
01347                         UINT dmax = pIns->nLength;
01348                         if (pIns->uFlags & CHN_16BIT) dmax <<= 1;
01349                         AMSUnpack(psrc+9, len-9, pdest, dmax, packcharacter);
01350                 }
01351                 break;
01352 
01353         // PTM 8bit delta to 16-bit sample
01354         case RS_PTM8DTO16:
01355                 {
01356                         len = pIns->nLength * 2;
01357                         if (len > dwMemLength) break;
01358                         signed char *pSample = (signed char *)pIns->pSample;
01359                         signed char delta8 = 0;
01360                         for (UINT j=0; j<len; j++)
01361                         {
01362                                 delta8 += lpMemFile[j];
01363                                 *pSample++ = delta8;
01364                         }
01365                         WORD *pSampleW = (WORD *)pIns->pSample;
01366                         for (UINT j=0; j<len; j+=2)   // swaparoni!
01367                         {
01368                                 *pSampleW++ = bswapLE16(*pSampleW);
01369                         }
01370                 }
01371                 break;
01372 
01373         // Huffman MDL compressed samples
01374         case RS_MDL8:
01375         case RS_MDL16:
01376                 len = dwMemLength;
01377                 if (len >= 4)
01378                 {
01379                         LPBYTE pSample = (LPBYTE)pIns->pSample;
01380                         LPBYTE ibuf = (LPBYTE)lpMemFile;
01381                         DWORD bitbuf = bswapLE32(*((DWORD *)ibuf));
01382                         UINT bitnum = 32;
01383                         BYTE dlt = 0, lowbyte = 0;
01384                         ibuf += 4;
01385                         for (UINT j=0; j<pIns->nLength; j++)
01386                         {
01387                                 BYTE hibyte;
01388                                 BYTE sign;
01389                                 if (nFlags == RS_MDL16) lowbyte = (BYTE)MDLReadBits(bitbuf, bitnum, ibuf, 8);
01390                                 sign = (BYTE)MDLReadBits(bitbuf, bitnum, ibuf, 1);
01391                                 if (MDLReadBits(bitbuf, bitnum, ibuf, 1))
01392                                 {
01393                                         hibyte = (BYTE)MDLReadBits(bitbuf, bitnum, ibuf, 3);
01394                                 } else
01395                                 {
01396                                         hibyte = 8;
01397                                         while (!MDLReadBits(bitbuf, bitnum, ibuf, 1)) hibyte += 0x10;
01398                                         hibyte += MDLReadBits(bitbuf, bitnum, ibuf, 4);
01399                                 }
01400                                 if (sign) hibyte = ~hibyte;
01401                                 dlt += hibyte;
01402                                 if (nFlags != RS_MDL16)
01403                                         pSample[j] = dlt;
01404                                 else
01405                                 {
01406                                         pSample[j<<1] = lowbyte;
01407                                         pSample[(j<<1)+1] = dlt;
01408                                 }
01409                         }
01410                 }
01411                 break;
01412 
01413         case RS_DMF8:
01414         case RS_DMF16:
01415                 len = dwMemLength;
01416                 if (len >= 4)
01417                 {
01418                         UINT maxlen = pIns->nLength;
01419                         if (pIns->uFlags & CHN_16BIT) maxlen <<= 1;
01420                         LPBYTE ibuf = (LPBYTE)lpMemFile, ibufmax = (LPBYTE)(lpMemFile+dwMemLength);
01421                         len = DMFUnpack((LPBYTE)pIns->pSample, ibuf, ibufmax, maxlen);
01422                 }
01423                 break;
01424 
01425 #ifdef MODPLUG_TRACKER
01426         // PCM 24-bit signed -> load sample, and normalize it to 16-bit
01427         case RS_PCM24S:
01428         case RS_PCM32S:
01429                 len = pIns->nLength * 3;
01430                 if (nFlags == RS_PCM32S) len += pIns->nLength;
01431                 if (len > dwMemLength) break;
01432                 if (len > 4*8)
01433                 {
01434                         UINT slsize = (nFlags == RS_PCM32S) ? 4 : 3;
01435                         LPBYTE pSrc = (LPBYTE)lpMemFile;
01436                         LONG max = 255;
01437                         if (nFlags == RS_PCM32S) pSrc++;
01438                         for (UINT j=0; j<len; j+=slsize)
01439                         {
01440                                 LONG l = ((((pSrc[j+2] << 8) + pSrc[j+1]) << 8) + pSrc[j]) << 8;
01441                                 l /= 256;
01442                                 if (l > max) max = l;
01443                                 if (-l > max) max = -l;
01444                         }
01445                         max = (max / 128) + 1;
01446                         signed short *pDest = (signed short *)pIns->pSample;
01447                         for (UINT k=0; k<len; k+=slsize)
01448                         {
01449                                 LONG l = ((((pSrc[k+2] << 8) + pSrc[k+1]) << 8) + pSrc[k]) << 8;
01450                                 *pDest++ = (signed short)(l / max);
01451                         }
01452                 }
01453                 break;
01454 
01455         // Stereo PCM 24-bit signed -> load sample, and normalize it to 16-bit
01456         case RS_STIPCM24S:
01457         case RS_STIPCM32S:
01458                 len = pIns->nLength * 6;
01459                 if (nFlags == RS_STIPCM32S) len += pIns->nLength * 2;
01460                 if (len > dwMemLength) break;
01461                 if (len > 8*8)
01462                 {
01463                         UINT slsize = (nFlags == RS_STIPCM32S) ? 4 : 3;
01464                         LPBYTE pSrc = (LPBYTE)lpMemFile;
01465                         LONG max = 255;
01466                         if (nFlags == RS_STIPCM32S) pSrc++;
01467                         for (UINT j=0; j<len; j+=slsize)
01468                         {
01469                                 LONG l = ((((pSrc[j+2] << 8) + pSrc[j+1]) << 8) + pSrc[j]) << 8;
01470                                 l /= 256;
01471                                 if (l > max) max = l;
01472                                 if (-l > max) max = -l;
01473                         }
01474                         max = (max / 128) + 1;
01475                         signed short *pDest = (signed short *)pIns->pSample;
01476                         for (UINT k=0; k<len; k+=slsize)
01477                         {
01478                                 LONG lr = ((((pSrc[k+2] << 8) + pSrc[k+1]) << 8) + pSrc[k]) << 8;
01479                                 k += slsize;
01480                                 LONG ll = ((((pSrc[k+2] << 8) + pSrc[k+1]) << 8) + pSrc[k]) << 8;
01481                                 pDest[0] = (signed short)ll;
01482                                 pDest[1] = (signed short)lr;
01483                                 pDest += 2;
01484                         }
01485                 }
01486                 break;
01487 
01488         // 16-bit signed big endian interleaved stereo
01489         case RS_STIPCM16M:
01490                 {
01491                         len = pIns->nLength;
01492                         if (len*4 > dwMemLength) len = dwMemLength >> 2;
01493                         LPCBYTE psrc = (LPCBYTE)lpMemFile;
01494                         short int *pSample = (short int *)pIns->pSample;
01495                         for (UINT j=0; j<len; j++)
01496                         {
01497                                 pSample[j*2] = (signed short)(((UINT)psrc[0] << 8) | (psrc[1]));
01498                                 pSample[j*2+1] = (signed short)(((UINT)psrc[2] << 8) | (psrc[3]));
01499                                 psrc += 4;
01500                         }
01501                         len *= 4;
01502                 }
01503                 break;
01504 
01505 #endif // MODPLUG_TRACKER
01506 #endif // !FASTSOUNDLIB
01507 #endif // !MODPLUG_BASIC_SUPPORT
01508 
01509         // Default: 8-bit signed PCM data
01510         default:
01511                 len = pIns->nLength;
01512                 if (len > dwMemLength) len = pIns->nLength = dwMemLength;
01513                 memcpy(pIns->pSample, lpMemFile, len);
01514         }
01515         if (len > dwMemLength)
01516         {
01517                 if (pIns->pSample)
01518                 {
01519                         pIns->nLength = 0;
01520                         FreeSample(pIns->pSample);
01521                         pIns->pSample = NULL;
01522                 }
01523                 return 0;
01524         }
01525         AdjustSampleLoop(pIns);
01526         return len;
01527 }
01528 
01529 
01530 void CSoundFile::AdjustSampleLoop(MODINSTRUMENT *pIns)
01531 //----------------------------------------------------
01532 {
01533         if (!pIns->pSample) return;
01534         if (pIns->nLoopEnd > pIns->nLength) pIns->nLoopEnd = pIns->nLength;
01535         if (pIns->nLoopStart+2 >= pIns->nLoopEnd)
01536         {
01537                 pIns->nLoopStart = pIns->nLoopEnd = 0;
01538                 pIns->uFlags &= ~CHN_LOOP;
01539         }
01540         UINT len = pIns->nLength;
01541         if (pIns->uFlags & CHN_16BIT)
01542         {
01543                 short int *pSample = (short int *)pIns->pSample;
01544                 // Adjust end of sample
01545                 if (pIns->uFlags & CHN_STEREO)
01546                 {
01547                         pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = pSample[len*2-2];
01548                         pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = pSample[len*2-1];
01549                 } else
01550                 {
01551                         pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = pSample[len-1];
01552                 }
01553                 if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP)
01554                 {
01555                         // Fix bad loops
01556                         if ((pIns->nLoopEnd+3 >= pIns->nLength) || (m_nType & MOD_TYPE_S3M))
01557                         {
01558                                 pSample[pIns->nLoopEnd] = pSample[pIns->nLoopStart];
01559                                 pSample[pIns->nLoopEnd+1] = pSample[pIns->nLoopStart+1];
01560                                 pSample[pIns->nLoopEnd+2] = pSample[pIns->nLoopStart+2];
01561                                 pSample[pIns->nLoopEnd+3] = pSample[pIns->nLoopStart+3];
01562                                 pSample[pIns->nLoopEnd+4] = pSample[pIns->nLoopStart+4];
01563                         }
01564                 }
01565         } else
01566         {
01567                 signed char *pSample = pIns->pSample;
01568 #ifndef FASTSOUNDLIB
01569                 // Crappy samples (except chiptunes) ?
01570                 if ((pIns->nLength > 0x100) && (m_nType & (MOD_TYPE_MOD|MOD_TYPE_S3M))
01571                  && (!(pIns->uFlags & CHN_STEREO)))
01572                 {
01573                         int smpend = pSample[pIns->nLength-1], smpfix = 0, kscan;
01574                         for (kscan=pIns->nLength-1; kscan>0; kscan--)
01575                         {
01576                                 smpfix = pSample[kscan-1];
01577                                 if (smpfix != smpend) break;
01578                         }
01579                         int delta = smpfix - smpend;
01580                         if (((!(pIns->uFlags & CHN_LOOP)) || (kscan > (int)pIns->nLoopEnd))
01581                          && ((delta < -8) || (delta > 8)))
01582                         {
01583                                 while (kscan<(int)pIns->nLength)
01584                                 {
01585                                         if (!(kscan & 7))
01586                                         {
01587                                                 if (smpfix > 0) smpfix--;
01588                                                 if (smpfix < 0) smpfix++;
01589                                         }
01590                                         pSample[kscan] = (signed char)smpfix;
01591                                         kscan++;
01592                                 }
01593                         }
01594                 }
01595 #endif
01596                 // Adjust end of sample
01597                 if (pIns->uFlags & CHN_STEREO)
01598                 {
01599                         pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = pSample[len*2-2];
01600                         pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = pSample[len*2-1];
01601                 } else
01602                 {
01603                         pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = pSample[len-1];
01604                 }
01605                 if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP)
01606                 {
01607                         if ((pIns->nLoopEnd+3 >= pIns->nLength) || (m_nType & (MOD_TYPE_MOD|MOD_TYPE_S3M)))
01608                         {
01609                                 pSample[pIns->nLoopEnd] = pSample[pIns->nLoopStart];
01610                                 pSample[pIns->nLoopEnd+1] = pSample[pIns->nLoopStart+1];
01611                                 pSample[pIns->nLoopEnd+2] = pSample[pIns->nLoopStart+2];
01612                                 pSample[pIns->nLoopEnd+3] = pSample[pIns->nLoopStart+3];
01613                                 pSample[pIns->nLoopEnd+4] = pSample[pIns->nLoopStart+4];
01614                         }
01615                 }
01616         }
01617 }
01618 
01619 
01621 // Transpose <-> Frequency conversions
01622 
01623 // returns 8363*2^((transp*128+ftune)/(12*128))
01624 DWORD CSoundFile::TransposeToFrequency(int transp, int ftune)
01625 //-----------------------------------------------------------
01626 {
01627         //---GCCFIX:  Removed assembly.
01628         return (DWORD)(8363*pow(2, (transp*128+ftune)/(1536)));
01629         
01630 #ifdef WIN32
01631         const float _fbase = 8363;
01632         const float _factor = 1.0f/(12.0f*128.0f);
01633         int result;
01634         DWORD freq;
01635 
01636         transp = (transp << 7) + ftune;
01637         _asm {
01638         fild transp
01639         fld _factor
01640         fmulp st(1), st(0)
01641         fist result
01642         fisub result
01643         f2xm1
01644         fild result
01645         fld _fbase
01646         fscale
01647         fstp st(1)
01648         fmul st(1), st(0)
01649         faddp st(1), st(0)
01650         fistp freq
01651         }
01652         UINT derr = freq % 11025;
01653         if (derr <= 8) freq -= derr;
01654         if (derr >= 11015) freq += 11025-derr;
01655         derr = freq % 1000;
01656         if (derr <= 5) freq -= derr;
01657         if (derr >= 995) freq += 1000-derr;
01658         return freq;
01659 #endif
01660 }
01661 
01662 
01663 // returns 12*128*log2(freq/8363)
01664 int CSoundFile::FrequencyToTranspose(DWORD freq)
01665 //----------------------------------------------
01666 {
01667         //---GCCFIX:  Removed assembly.
01668         return int(1536*(log(freq/8363)/log(2)));
01669         
01670 #ifdef WIN32
01671         const float _f1_8363 = 1.0f / 8363.0f;
01672         const float _factor = 128 * 12;
01673         LONG result;
01674         
01675         if (!freq) return 0;
01676         _asm {
01677         fld _factor
01678         fild freq
01679         fld _f1_8363
01680         fmulp st(1), st(0)
01681         fyl2x
01682         fistp result
01683         }
01684         return result;
01685 #endif
01686 }
01687 
01688 
01689 void CSoundFile::FrequencyToTranspose(MODINSTRUMENT *psmp)
01690 //--------------------------------------------------------
01691 {
01692         int f2t = FrequencyToTranspose(psmp->nC4Speed);
01693         int transp = f2t >> 7;
01694         int ftune = f2t & 0x7F;
01695         if (ftune > 80)
01696         {
01697                 transp++;
01698                 ftune -= 128;
01699         }
01700         if (transp > 127) transp = 127;
01701         if (transp < -127) transp = -127;
01702         psmp->RelativeTone = transp;
01703         psmp->nFineTune = ftune;
01704 }
01705 
01706 
01707 void CSoundFile::CheckCPUUsage(UINT nCPU)
01708 //---------------------------------------
01709 {
01710         if (nCPU > 100) nCPU = 100;
01711         gnCPUUsage = nCPU;
01712         if (nCPU < 90)
01713         {
01714                 m_dwSongFlags &= ~SONG_CPUVERYHIGH;
01715         } else
01716         if ((m_dwSongFlags & SONG_CPUVERYHIGH) && (nCPU >= 94))
01717         {
01718                 UINT i=MAX_CHANNELS;
01719                 while (i >= 8)
01720                 {
01721                         i--;
01722                         if (Chn[i].nLength)
01723                         {
01724                                 Chn[i].nLength = Chn[i].nPos = 0;
01725                                 nCPU -= 2;
01726                                 if (nCPU < 94) break;
01727                         }
01728                 }
01729         } else
01730         if (nCPU > 90)
01731         {
01732                 m_dwSongFlags |= SONG_CPUVERYHIGH;
01733         }
01734 }
01735 
01736 
01737 BOOL CSoundFile::SetPatternName(UINT nPat, LPCSTR lpszName)
01738 //---------------------------------------------------------
01739 {
01740         char szName[MAX_PATTERNNAME] = "";   // changed from CHAR
01741         if (nPat >= MAX_PATTERNS) return FALSE;
01742         if (lpszName) lstrcpyn(szName, lpszName, MAX_PATTERNNAME);
01743         szName[MAX_PATTERNNAME-1] = 0;
01744         if (!m_lpszPatternNames) m_nPatternNames = 0;
01745         if (nPat >= m_nPatternNames)
01746         {
01747                 if (!lpszName[0]) return TRUE;
01748                 UINT len = (nPat+1)*MAX_PATTERNNAME;
01749                 char *p = new char[len];   // changed from CHAR
01750                 if (!p) return FALSE;
01751                 memset(p, 0, len);
01752                 if (m_lpszPatternNames)
01753                 {
01754                         memcpy(p, m_lpszPatternNames, m_nPatternNames * MAX_PATTERNNAME);
01755                         delete m_lpszPatternNames;
01756                         m_lpszPatternNames = NULL;
01757                 }
01758                 m_lpszPatternNames = p;
01759                 m_nPatternNames = nPat + 1;
01760         }
01761         memcpy(m_lpszPatternNames + nPat * MAX_PATTERNNAME, szName, MAX_PATTERNNAME);
01762         return TRUE;
01763 }
01764 
01765 
01766 BOOL CSoundFile::GetPatternName(UINT nPat, LPSTR lpszName, UINT cbSize) const
01767 //---------------------------------------------------------------------------
01768 {
01769         if ((!lpszName) || (!cbSize)) return FALSE;
01770         lpszName[0] = 0;
01771         if (cbSize > MAX_PATTERNNAME) cbSize = MAX_PATTERNNAME;
01772         if ((m_lpszPatternNames) && (nPat < m_nPatternNames))
01773         {
01774                 memcpy(lpszName, m_lpszPatternNames + nPat * MAX_PATTERNNAME, cbSize);
01775                 lpszName[cbSize-1] = 0;
01776                 return TRUE;
01777         }
01778         return FALSE;
01779 }
01780 
01781 
01782 #ifndef FASTSOUNDLIB
01783 
01784 UINT CSoundFile::DetectUnusedSamples(BOOL *pbIns)
01785 //-----------------------------------------------
01786 {
01787         UINT nExt = 0;
01788 
01789         if (!pbIns) return 0;
01790         if (m_nInstruments)
01791         {
01792                 memset(pbIns, 0, MAX_SAMPLES * sizeof(BOOL));
01793                 for (UINT ipat=0; ipat<MAX_PATTERNS; ipat++)
01794                 {
01795                         MODCOMMAND *p = Patterns[ipat];
01796                         if (p)
01797                         {
01798                                 UINT jmax = PatternSize[ipat] * m_nChannels;
01799                                 for (UINT j=0; j<jmax; j++, p++)
01800                                 {
01801                                         if ((p->note) && (p->note <= 120))
01802                                         {
01803                                                 if ((p->instr) && (p->instr < MAX_INSTRUMENTS))
01804                                                 {
01805                                                         INSTRUMENTHEADER *penv = Headers[p->instr];
01806                                                         if (penv)
01807                                                         {
01808                                                                 UINT n = penv->Keyboard[p->note-1];
01809                                                                 if (n < MAX_SAMPLES) pbIns[n] = TRUE;
01810                                                         }
01811                                                 } else
01812                                                 {
01813                                                         for (UINT k=1; k<=m_nInstruments; k++)
01814                                                         {
01815                                                                 INSTRUMENTHEADER *penv = Headers[k];
01816                                                                 if (penv)
01817                                                                 {
01818                                                                         UINT n = penv->Keyboard[p->note-1];
01819                                                                         if (n < MAX_SAMPLES) pbIns[n] = TRUE;
01820                                                                 }
01821                                                         }
01822                                                 }
01823                                         }
01824                                 }
01825                         }
01826                 }
01827                 for (UINT ichk=1; ichk<=m_nSamples; ichk++)
01828                 {
01829                         if ((!pbIns[ichk]) && (Ins[ichk].pSample)) nExt++;
01830                 }
01831         }
01832         return nExt;
01833 }
01834 
01835 
01836 BOOL CSoundFile::RemoveSelectedSamples(BOOL *pbIns)
01837 //-------------------------------------------------
01838 {
01839         if (!pbIns) return FALSE;
01840         for (UINT j=1; j<MAX_SAMPLES; j++)
01841         {
01842                 if ((!pbIns[j]) && (Ins[j].pSample))
01843                 {
01844                         DestroySample(j);
01845                         if ((j == m_nSamples) && (j > 1)) m_nSamples--;
01846                 }
01847         }
01848         return TRUE;
01849 }
01850 
01851 
01852 BOOL CSoundFile::DestroySample(UINT nSample)
01853 //------------------------------------------
01854 {
01855         if ((!nSample) || (nSample >= MAX_SAMPLES)) return FALSE;
01856         if (!Ins[nSample].pSample) return TRUE;
01857         MODINSTRUMENT *pins = &Ins[nSample];
01858         signed char *pSample = pins->pSample;
01859         pins->pSample = NULL;
01860         pins->nLength = 0;
01861         pins->uFlags &= ~(CHN_16BIT);
01862         for (UINT i=0; i<MAX_CHANNELS; i++)
01863         {
01864                 if (Chn[i].pSample == pSample)
01865                 {
01866                         Chn[i].nPos = Chn[i].nLength = 0;
01867                         Chn[i].pSample = Chn[i].pCurrentSample = NULL;
01868                 }
01869         }
01870         FreeSample(pSample);
01871         return TRUE;
01872 }
01873 
01874 #endif // FASTSOUNDLIB
01875 

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