/Chapter9/Engine/include/modplug/sndfile.cpp
C++ | 2305 lines | 1672 code | 510 blank | 123 comment | 450 complexity | 8b3b3d902c3b01a599140f4ec3bbdcc1 MD5 | raw file
- /*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>,
- * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC)
- */
- #include <math.h> //for GCCFIX
- #include "stdafx.h"
- #include "sndfile.h"
- #define MMCMP_SUPPORT
- #ifdef MMCMP_SUPPORT
- extern BOOL MMCMP_Unpack( LPCBYTE* ppMemFile, LPDWORD pdwMemLength );
- #endif
- // External decompressors
- extern void AMSUnpack( const char* psrc, UINT inputlen, char* pdest, UINT dmax, char packcharacter );
- extern WORD MDLReadBits( DWORD& bitbuf, UINT& bitnum, LPBYTE& ibuf, CHAR n );
- extern int DMFUnpack( LPBYTE psample, LPBYTE ibuf, LPBYTE ibufmax, UINT maxlen );
- extern DWORD ITReadBits( DWORD& bitbuf, UINT& bitnum, LPBYTE& ibuf, CHAR n );
- extern void ITUnpack8Bit( signed char* pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215 );
- extern void ITUnpack16Bit( signed char* pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215 );
- #define MAX_PACK_TABLES 3
- // Compression table
- static const signed char UnpackTable[MAX_PACK_TABLES][16] =
- //--------------------------------------------
- {
- // CPU-generated dynamic table
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- // u-Law table
- {
- 0, 1, 2, 4, 8, 16, 32, 64,
- -1, -2, -4, -8, -16, -32, -48, -64
- },
- // Linear table
- {
- 0, 1, 2, 3, 5, 7, 12, 19,
- -1, -2, -3, -5, -7, -12, -19, -31
- }
- };
- //////////////////////////////////////////////////////////
- // CSoundFile
- CSoundFile::CSoundFile()
- //----------------------
- {
- m_nType = MOD_TYPE_NONE;
- m_dwSongFlags = 0;
- m_nChannels = 0;
- m_nMixChannels = 0;
- m_nSamples = 0;
- m_nInstruments = 0;
- m_nPatternNames = 0;
- m_lpszPatternNames = NULL;
- m_lpszSongComments = NULL;
- m_nFreqFactor = m_nTempoFactor = 128;
- m_nMasterVolume = 128;
- m_nMinPeriod = 0x20;
- m_nMaxPeriod = 0x7FFF;
- m_nRepeatCount = 0;
- memset( Chn, 0, sizeof( Chn ) );
- memset( ChnMix, 0, sizeof( ChnMix ) );
- memset( Ins, 0, sizeof( Ins ) );
- memset( ChnSettings, 0, sizeof( ChnSettings ) );
- memset( Headers, 0, sizeof( Headers ) );
- memset( Order, 0xFF, sizeof( Order ) );
- memset( Patterns, 0, sizeof( Patterns ) );
- memset( m_szNames, 0, sizeof( m_szNames ) );
- memset( m_MixPlugins, 0, sizeof( m_MixPlugins ) );
- }
- CSoundFile::~CSoundFile()
- //-----------------------
- {
- Destroy();
- }
- BOOL CSoundFile::Create( LPCBYTE lpStream, DWORD dwMemLength )
- //----------------------------------------------------------
- {
- int i;
- m_nType = MOD_TYPE_NONE;
- m_dwSongFlags = 0;
- m_nChannels = 0;
- m_nMixChannels = 0;
- m_nSamples = 0;
- m_nInstruments = 0;
- m_nFreqFactor = m_nTempoFactor = 128;
- m_nMasterVolume = 128;
- m_nDefaultGlobalVolume = 256;
- m_nGlobalVolume = 256;
- m_nOldGlbVolSlide = 0;
- m_nDefaultSpeed = 6;
- m_nDefaultTempo = 125;
- m_nPatternDelay = 0;
- m_nFrameDelay = 0;
- m_nNextRow = 0;
- m_nRow = 0;
- m_nPattern = 0;
- m_nCurrentPattern = 0;
- m_nNextPattern = 0;
- m_nRestartPos = 0;
- m_nMinPeriod = 16;
- m_nMaxPeriod = 32767;
- m_nSongPreAmp = 0x30;
- m_nPatternNames = 0;
- m_nMaxOrderPosition = 0;
- m_lpszPatternNames = NULL;
- m_lpszSongComments = NULL;
- memset( Ins, 0, sizeof( Ins ) );
- memset( ChnMix, 0, sizeof( ChnMix ) );
- memset( Chn, 0, sizeof( Chn ) );
- memset( Headers, 0, sizeof( Headers ) );
- memset( Order, 0xFF, sizeof( Order ) );
- memset( Patterns, 0, sizeof( Patterns ) );
- memset( m_szNames, 0, sizeof( m_szNames ) );
- memset( m_MixPlugins, 0, sizeof( m_MixPlugins ) );
- ResetMidiCfg();
- for ( UINT npt = 0; npt < MAX_PATTERNS; npt++ ) { PatternSize[npt] = 64; }
- for ( UINT nch = 0; nch < MAX_BASECHANNELS; nch++ )
- {
- ChnSettings[nch].nPan = 128;
- ChnSettings[nch].nVolume = 64;
- ChnSettings[nch].dwFlags = 0;
- ChnSettings[nch].szName[0] = 0;
- }
- if ( lpStream )
- {
- #ifdef MMCMP_SUPPORT
- BOOL bMMCmp = MMCMP_Unpack( &lpStream, &dwMemLength );
- #endif
- if ( ( !ReadXM( lpStream, dwMemLength ) )
- && ( !ReadS3M( lpStream, dwMemLength ) )
- && ( !ReadIT( lpStream, dwMemLength ) )
- && ( !ReadWav( lpStream, dwMemLength ) )
- #ifndef MODPLUG_BASIC_SUPPORT
- /* Sequencer File Format Support */
- && ( !ReadABC( lpStream, dwMemLength ) )
- && ( !ReadMID( lpStream, dwMemLength ) )
- && ( !ReadPAT( lpStream, dwMemLength ) )
- && ( !ReadSTM( lpStream, dwMemLength ) )
- && ( !ReadMed( lpStream, dwMemLength ) )
- && ( !ReadMTM( lpStream, dwMemLength ) )
- && ( !ReadMDL( lpStream, dwMemLength ) )
- && ( !ReadDBM( lpStream, dwMemLength ) )
- && ( !Read669( lpStream, dwMemLength ) )
- && ( !ReadFAR( lpStream, dwMemLength ) )
- && ( !ReadAMS( lpStream, dwMemLength ) )
- && ( !ReadOKT( lpStream, dwMemLength ) )
- && ( !ReadPTM( lpStream, dwMemLength ) )
- && ( !ReadUlt( lpStream, dwMemLength ) )
- && ( !ReadDMF( lpStream, dwMemLength ) )
- && ( !ReadDSM( lpStream, dwMemLength ) )
- && ( !ReadUMX( lpStream, dwMemLength ) )
- && ( !ReadAMF( lpStream, dwMemLength ) )
- && ( !ReadPSM( lpStream, dwMemLength ) )
- && ( !ReadMT2( lpStream, dwMemLength ) )
- #endif // MODPLUG_BASIC_SUPPORT
- && ( !ReadMod( lpStream, dwMemLength ) ) ) { m_nType = MOD_TYPE_NONE; }
- #ifdef MMCMP_SUPPORT
- if ( bMMCmp )
- {
- GlobalFreePtr( lpStream );
- lpStream = NULL;
- }
- #endif
- }
- // Adjust song names
- for ( i = 0; i < MAX_SAMPLES; i++ )
- {
- LPSTR p = m_szNames[i];
- int j = 31;
- p[j] = 0;
- while ( ( j >= 0 ) && ( p[j] <= ' ' ) ) { p[j--] = 0; }
- while ( j >= 0 )
- {
- if ( ( ( BYTE )p[j] ) < ' ' ) { p[j] = ' '; }
- j--;
- }
- }
- // Adjust channels
- for ( i = 0; i < MAX_BASECHANNELS; i++ )
- {
- if ( ChnSettings[i].nVolume > 64 ) { ChnSettings[i].nVolume = 64; }
- if ( ChnSettings[i].nPan > 256 ) { ChnSettings[i].nPan = 128; }
- Chn[i].nPan = ChnSettings[i].nPan;
- Chn[i].nGlobalVol = ChnSettings[i].nVolume;
- Chn[i].dwFlags = ChnSettings[i].dwFlags;
- Chn[i].nVolume = 256;
- Chn[i].nCutOff = 0x7F;
- }
- // Checking instruments
- MODINSTRUMENT* pins = Ins;
- for ( i = 0; i < MAX_INSTRUMENTS; i++, pins++ )
- {
- if ( pins->pSample )
- {
- if ( pins->nLoopEnd > pins->nLength ) { pins->nLoopEnd = pins->nLength; }
- if ( pins->nLoopStart + 3 >= pins->nLoopEnd )
- {
- pins->nLoopStart = 0;
- pins->nLoopEnd = 0;
- }
- if ( pins->nSustainEnd > pins->nLength ) { pins->nSustainEnd = pins->nLength; }
- if ( pins->nSustainStart + 3 >= pins->nSustainEnd )
- {
- pins->nSustainStart = 0;
- pins->nSustainEnd = 0;
- }
- }
- else
- {
- pins->nLength = 0;
- pins->nLoopStart = 0;
- pins->nLoopEnd = 0;
- pins->nSustainStart = 0;
- pins->nSustainEnd = 0;
- }
- if ( !pins->nLoopEnd ) { pins->uFlags &= ~CHN_LOOP; }
- if ( !pins->nSustainEnd ) { pins->uFlags &= ~CHN_SUSTAINLOOP; }
- if ( pins->nGlobalVol > 64 ) { pins->nGlobalVol = 64; }
- }
- // Check invalid instruments
- while ( ( m_nInstruments > 0 ) && ( !Headers[m_nInstruments] ) )
- {
- m_nInstruments--;
- }
- // Set default values
- if ( m_nSongPreAmp < 0x20 ) { m_nSongPreAmp = 0x20; }
- if ( m_nDefaultTempo < 32 ) { m_nDefaultTempo = 125; }
- if ( !m_nDefaultSpeed ) { m_nDefaultSpeed = 6; }
- m_nMusicSpeed = m_nDefaultSpeed;
- m_nMusicTempo = m_nDefaultTempo;
- m_nGlobalVolume = m_nDefaultGlobalVolume;
- m_nNextPattern = 0;
- m_nCurrentPattern = 0;
- m_nPattern = 0;
- m_nBufferCount = 0;
- m_nTickCount = m_nMusicSpeed;
- m_nNextRow = 0;
- m_nRow = 0;
- if ( ( m_nRestartPos >= MAX_ORDERS ) || ( Order[m_nRestartPos] >= MAX_PATTERNS ) ) { m_nRestartPos = 0; }
- // Load plugins
- if ( gpMixPluginCreateProc )
- {
- for ( UINT iPlug = 0; iPlug < MAX_MIXPLUGINS; iPlug++ )
- {
- if ( ( m_MixPlugins[iPlug].Info.dwPluginId1 )
- || ( m_MixPlugins[iPlug].Info.dwPluginId2 ) )
- {
- gpMixPluginCreateProc( &m_MixPlugins[iPlug] );
- if ( m_MixPlugins[iPlug].pMixPlugin )
- {
- m_MixPlugins[iPlug].pMixPlugin->RestoreAllParameters();
- }
- }
- }
- }
- if ( m_nType )
- {
- UINT maxpreamp = 0x10 + ( m_nChannels * 8 );
- if ( maxpreamp > 100 ) { maxpreamp = 100; }
- if ( m_nSongPreAmp > maxpreamp ) { m_nSongPreAmp = maxpreamp; }
- return TRUE;
- }
- return FALSE;
- }
- BOOL CSoundFile::Destroy()
- //------------------------
- {
- int i;
- for ( i = 0; i < MAX_PATTERNS; i++ ) if ( Patterns[i] )
- {
- FreePattern( Patterns[i] );
- Patterns[i] = NULL;
- }
- m_nPatternNames = 0;
- if ( m_lpszPatternNames )
- {
- delete [] m_lpszPatternNames;
- m_lpszPatternNames = NULL;
- }
- if ( m_lpszSongComments )
- {
- delete [] m_lpszSongComments;
- m_lpszSongComments = NULL;
- }
- for ( i = 1; i < MAX_SAMPLES; i++ )
- {
- MODINSTRUMENT* pins = &Ins[i];
- if ( pins->pSample )
- {
- FreeSample( pins->pSample );
- pins->pSample = NULL;
- }
- }
- for ( i = 0; i < MAX_INSTRUMENTS; i++ )
- {
- if ( Headers[i] )
- {
- delete Headers[i];
- Headers[i] = NULL;
- }
- }
- for ( i = 0; i < MAX_MIXPLUGINS; i++ )
- {
- if ( ( m_MixPlugins[i].nPluginDataSize ) && ( m_MixPlugins[i].pPluginData ) )
- {
- m_MixPlugins[i].nPluginDataSize = 0;
- delete [] ( signed char* )m_MixPlugins[i].pPluginData;
- m_MixPlugins[i].pPluginData = NULL;
- }
- m_MixPlugins[i].pMixState = NULL;
- if ( m_MixPlugins[i].pMixPlugin )
- {
- m_MixPlugins[i].pMixPlugin->Release();
- m_MixPlugins[i].pMixPlugin = NULL;
- }
- }
- m_nType = MOD_TYPE_NONE;
- m_nChannels = m_nSamples = m_nInstruments = 0;
- return TRUE;
- }
- //////////////////////////////////////////////////////////////////////////
- // Memory Allocation
- MODCOMMAND* CSoundFile::AllocatePattern( UINT rows, UINT nchns )
- //------------------------------------------------------------
- {
- MODCOMMAND* p = new MODCOMMAND[rows * nchns];
- if ( p ) { memset( p, 0, rows * nchns * sizeof( MODCOMMAND ) ); }
- return p;
- }
- void CSoundFile::FreePattern( LPVOID pat )
- //--------------------------------------
- {
- if ( pat ) { delete [] ( signed char* )pat; }
- }
- signed char* CSoundFile::AllocateSample( UINT nbytes )
- //-------------------------------------------
- {
- signed char* p = ( signed char* )GlobalAllocPtr( GHND, ( nbytes + 39 ) & ~7 );
- if ( p ) { p += 16; }
- return p;
- }
- void CSoundFile::FreeSample( LPVOID p )
- //-----------------------------------
- {
- if ( p )
- {
- GlobalFreePtr( ( ( LPSTR )p ) - 16 );
- }
- }
- //////////////////////////////////////////////////////////////////////////
- // Misc functions
- void CSoundFile::ResetMidiCfg()
- //-----------------------------
- {
- memset( &m_MidiCfg, 0, sizeof( m_MidiCfg ) );
- lstrcpy( &m_MidiCfg.szMidiGlb[MIDIOUT_START * 32], "FF" );
- lstrcpy( &m_MidiCfg.szMidiGlb[MIDIOUT_STOP * 32], "FC" );
- lstrcpy( &m_MidiCfg.szMidiGlb[MIDIOUT_NOTEON * 32], "9c n v" );
- lstrcpy( &m_MidiCfg.szMidiGlb[MIDIOUT_NOTEOFF * 32], "9c n 0" );
- lstrcpy( &m_MidiCfg.szMidiGlb[MIDIOUT_PROGRAM * 32], "Cc p" );
- lstrcpy( &m_MidiCfg.szMidiSFXExt[0], "F0F000z" );
- for ( int iz = 0; iz < 16; iz++ ) { wsprintf( &m_MidiCfg.szMidiZXXExt[iz * 32], "F0F001%02X", iz * 8 ); }
- }
- UINT CSoundFile::GetNumChannels() const
- //-------------------------------------
- {
- UINT n = 0;
- for ( UINT i = 0; i < m_nChannels; i++ ) if ( ChnSettings[i].nVolume ) { n++; }
- return n;
- }
- UINT CSoundFile::GetSongComments( LPSTR s, UINT len, UINT linesize )
- //----------------------------------------------------------------
- {
- LPCSTR p = m_lpszSongComments;
- if ( !p ) { return 0; }
- UINT i = 2, ln = 0;
- if ( ( len ) && ( s ) ) { s[0] = '\x0D'; }
- if ( ( len > 1 ) && ( s ) ) { s[1] = '\x0A'; }
- while ( ( *p ) && ( i + 2 < len ) )
- {
- BYTE c = ( BYTE ) * p++;
- if ( ( c == 0x0D ) || ( ( c == ' ' ) && ( ln >= linesize ) ) )
- { if ( s ) { s[i++] = '\x0D'; s[i++] = '\x0A'; } else { i += 2; } ln = 0; }
- else if ( c >= 0x20 ) { if ( s ) { s[i++] = c; } else { i++; } ln++; }
- }
- if ( s ) { s[i] = 0; }
- return i;
- }
- UINT CSoundFile::GetRawSongComments( LPSTR s, UINT len, UINT linesize )
- //-------------------------------------------------------------------
- {
- LPCSTR p = m_lpszSongComments;
- if ( !p ) { return 0; }
- UINT i = 0, ln = 0;
- while ( ( *p ) && ( i < len - 1 ) )
- {
- BYTE c = ( BYTE ) * p++;
- if ( ( c == 0x0D ) || ( c == 0x0A ) )
- {
- if ( ln )
- {
- while ( ln < linesize ) { if ( s ) { s[i] = ' '; } i++; ln++; }
- ln = 0;
- }
- }
- else if ( ( c == ' ' ) && ( !ln ) )
- {
- UINT k = 0;
- while ( ( p[k] ) && ( p[k] >= ' ' ) ) { k++; }
- if ( k <= linesize )
- {
- if ( s ) { s[i] = ' '; }
- i++;
- ln++;
- }
- }
- else
- {
- if ( s ) { s[i] = c; }
- i++;
- ln++;
- if ( ln == linesize ) { ln = 0; }
- }
- }
- if ( ln )
- {
- while ( ( ln < linesize ) && ( i < len ) )
- {
- if ( s ) { s[i] = ' '; }
- i++;
- ln++;
- }
- }
- if ( s ) { s[i] = 0; }
- return i;
- }
- BOOL CSoundFile::SetWaveConfig( UINT nRate, UINT nBits, UINT nChannels, BOOL bMMX )
- //----------------------------------------------------------------------------
- {
- BOOL bReset = FALSE;
- DWORD d = gdwSoundSetup & ~SNDMIX_ENABLEMMX;
- if ( bMMX ) { d |= SNDMIX_ENABLEMMX; }
- if ( ( gdwMixingFreq != nRate ) || ( gnBitsPerSample != nBits ) || ( gnChannels != nChannels ) || ( d != gdwSoundSetup ) ) { bReset = TRUE; }
- gnChannels = nChannels;
- gdwSoundSetup = d;
- gdwMixingFreq = nRate;
- gnBitsPerSample = nBits;
- InitPlayer( bReset );
- return TRUE;
- }
- BOOL CSoundFile::SetMixConfig( UINT nStereoSeparation, UINT nMaxMixChannels )
- //-------------------------------------------------------------------------
- {
- if ( nMaxMixChannels < 2 ) { return FALSE; }
- m_nMaxMixChannels = nMaxMixChannels;
- m_nStereoSeparation = nStereoSeparation;
- return TRUE;
- }
- BOOL CSoundFile::SetResamplingMode( UINT nMode )
- //--------------------------------------------
- {
- DWORD d = gdwSoundSetup & ~( SNDMIX_NORESAMPLING | SNDMIX_HQRESAMPLER | SNDMIX_ULTRAHQSRCMODE );
- switch ( nMode )
- {
- case SRCMODE_NEAREST:
- d |= SNDMIX_NORESAMPLING;
- break;
- case SRCMODE_LINEAR:
- break;
- case SRCMODE_SPLINE:
- d |= SNDMIX_HQRESAMPLER;
- break;
- case SRCMODE_POLYPHASE:
- d |= ( SNDMIX_HQRESAMPLER | SNDMIX_ULTRAHQSRCMODE );
- break;
- default:
- return FALSE;
- }
- gdwSoundSetup = d;
- return TRUE;
- }
- BOOL CSoundFile::SetMasterVolume( UINT nVol, BOOL bAdjustAGC )
- //----------------------------------------------------------
- {
- if ( nVol < 1 ) { nVol = 1; }
- if ( nVol > 0x200 ) { nVol = 0x200; } // x4 maximum
- if ( ( nVol < m_nMasterVolume ) && ( nVol ) && ( gdwSoundSetup & SNDMIX_AGC ) && ( bAdjustAGC ) )
- {
- gnAGC = gnAGC * m_nMasterVolume / nVol;
- if ( gnAGC > AGC_UNITY ) { gnAGC = AGC_UNITY; }
- }
- m_nMasterVolume = nVol;
- return TRUE;
- }
- void CSoundFile::SetAGC( BOOL b )
- //-----------------------------
- {
- if ( b )
- {
- if ( !( gdwSoundSetup & SNDMIX_AGC ) )
- {
- gdwSoundSetup |= SNDMIX_AGC;
- gnAGC = AGC_UNITY;
- }
- }
- else { gdwSoundSetup &= ~SNDMIX_AGC; }
- }
- UINT CSoundFile::GetNumPatterns() const
- //-------------------------------------
- {
- UINT i = 0;
- while ( ( i < MAX_ORDERS ) && ( Order[i] < 0xFF ) ) { i++; }
- return i;
- }
- UINT CSoundFile::GetNumInstruments() const
- //----------------------------------------
- {
- UINT n = 0;
- for ( UINT i = 0; i < MAX_INSTRUMENTS; i++ ) if ( Ins[i].pSample ) { n++; }
- return n;
- }
- UINT CSoundFile::GetMaxPosition() const
- //-------------------------------------
- {
- UINT max = 0;
- UINT i = 0;
- while ( ( i < MAX_ORDERS ) && ( Order[i] != 0xFF ) )
- {
- if ( Order[i] < MAX_PATTERNS ) { max += PatternSize[Order[i]]; }
- i++;
- }
- return max;
- }
- UINT CSoundFile::GetCurrentPos() const
- //------------------------------------
- {
- UINT pos = 0;
- for ( UINT i = 0; i < m_nCurrentPattern; i++ ) if ( Order[i] < MAX_PATTERNS )
- {
- pos += PatternSize[Order[i]];
- }
- return pos + m_nRow;
- }
- void CSoundFile::SetCurrentPos( UINT nPos )
- //---------------------------------------
- {
- UINT i, nPattern;
- for ( i = 0; i < MAX_CHANNELS; i++ )
- {
- Chn[i].nNote = Chn[i].nNewNote = Chn[i].nNewIns = 0;
- Chn[i].pInstrument = NULL;
- Chn[i].pHeader = NULL;
- Chn[i].nPortamentoDest = 0;
- Chn[i].nCommand = 0;
- Chn[i].nPatternLoopCount = 0;
- Chn[i].nPatternLoop = 0;
- Chn[i].nFadeOutVol = 0;
- Chn[i].dwFlags |= CHN_KEYOFF | CHN_NOTEFADE;
- Chn[i].nTremorCount = 0;
- }
- if ( !nPos )
- {
- for ( i = 0; i < MAX_CHANNELS; i++ )
- {
- Chn[i].nPeriod = 0;
- Chn[i].nPos = Chn[i].nLength = 0;
- Chn[i].nLoopStart = 0;
- Chn[i].nLoopEnd = 0;
- Chn[i].nROfs = Chn[i].nLOfs = 0;
- Chn[i].pSample = NULL;
- Chn[i].pInstrument = NULL;
- Chn[i].pHeader = NULL;
- Chn[i].nCutOff = 0x7F;
- Chn[i].nResonance = 0;
- Chn[i].nLeftVol = Chn[i].nRightVol = 0;
- Chn[i].nNewLeftVol = Chn[i].nNewRightVol = 0;
- Chn[i].nLeftRamp = Chn[i].nRightRamp = 0;
- Chn[i].nVolume = 256;
- if ( i < MAX_BASECHANNELS )
- {
- Chn[i].dwFlags = ChnSettings[i].dwFlags;
- Chn[i].nPan = ChnSettings[i].nPan;
- Chn[i].nGlobalVol = ChnSettings[i].nVolume;
- }
- else
- {
- Chn[i].dwFlags = 0;
- Chn[i].nPan = 128;
- Chn[i].nGlobalVol = 64;
- }
- }
- m_nGlobalVolume = m_nDefaultGlobalVolume;
- m_nMusicSpeed = m_nDefaultSpeed;
- m_nMusicTempo = m_nDefaultTempo;
- }
- m_dwSongFlags &= ~( SONG_PATTERNLOOP | SONG_CPUVERYHIGH | SONG_FADINGSONG | SONG_ENDREACHED | SONG_GLOBALFADE );
- for ( nPattern = 0; nPattern < MAX_ORDERS; nPattern++ )
- {
- UINT ord = Order[nPattern];
- if ( ord == 0xFE ) { continue; }
- if ( ord == 0xFF ) { break; }
- if ( ord < MAX_PATTERNS )
- {
- if ( nPos < ( UINT )PatternSize[ord] ) { break; }
- nPos -= PatternSize[ord];
- }
- }
- // Buggy position ?
- if ( ( nPattern >= MAX_ORDERS )
- || ( Order[nPattern] >= MAX_PATTERNS )
- || ( nPos >= PatternSize[Order[nPattern]] ) )
- {
- nPos = 0;
- nPattern = 0;
- }
- UINT nRow = nPos;
- if ( ( nRow ) && ( Order[nPattern] < MAX_PATTERNS ) )
- {
- MODCOMMAND* p = Patterns[Order[nPattern]];
- if ( ( p ) && ( nRow < PatternSize[Order[nPattern]] ) )
- {
- BOOL bOk = FALSE;
- while ( ( !bOk ) && ( nRow > 0 ) )
- {
- UINT n = nRow * m_nChannels;
- for ( UINT k = 0; k < m_nChannels; k++, n++ )
- {
- if ( p[n].note )
- {
- bOk = TRUE;
- break;
- }
- }
- if ( !bOk ) { nRow--; }
- }
- }
- }
- m_nNextPattern = nPattern;
- m_nNextRow = nRow;
- m_nTickCount = m_nMusicSpeed;
- m_nBufferCount = 0;
- m_nPatternDelay = 0;
- m_nFrameDelay = 0;
- }
- void CSoundFile::SetCurrentOrder( UINT nPos )
- //-----------------------------------------
- {
- while ( ( nPos < MAX_ORDERS ) && ( Order[nPos] == 0xFE ) ) { nPos++; }
- if ( ( nPos >= MAX_ORDERS ) || ( Order[nPos] >= MAX_PATTERNS ) ) { return; }
- for ( UINT j = 0; j < MAX_CHANNELS; j++ )
- {
- Chn[j].nPeriod = 0;
- Chn[j].nNote = 0;
- Chn[j].nPortamentoDest = 0;
- Chn[j].nCommand = 0;
- Chn[j].nPatternLoopCount = 0;
- Chn[j].nPatternLoop = 0;
- Chn[j].nTremorCount = 0;
- }
- if ( !nPos )
- {
- SetCurrentPos( 0 );
- }
- else
- {
- m_nNextPattern = nPos;
- m_nRow = m_nNextRow = 0;
- m_nPattern = 0;
- m_nTickCount = m_nMusicSpeed;
- m_nBufferCount = 0;
- m_nTotalCount = 0;
- m_nPatternDelay = 0;
- m_nFrameDelay = 0;
- }
- m_dwSongFlags &= ~( SONG_PATTERNLOOP | SONG_CPUVERYHIGH | SONG_FADINGSONG | SONG_ENDREACHED | SONG_GLOBALFADE );
- }
- void CSoundFile::ResetChannels()
- //------------------------------
- {
- m_dwSongFlags &= ~( SONG_CPUVERYHIGH | SONG_FADINGSONG | SONG_ENDREACHED | SONG_GLOBALFADE );
- m_nBufferCount = 0;
- for ( UINT i = 0; i < MAX_CHANNELS; i++ )
- {
- Chn[i].nROfs = Chn[i].nLOfs = 0;
- }
- }
- void CSoundFile::LoopPattern( int nPat, int nRow )
- //----------------------------------------------
- {
- if ( ( nPat < 0 ) || ( nPat >= MAX_PATTERNS ) || ( !Patterns[nPat] ) )
- {
- m_dwSongFlags &= ~SONG_PATTERNLOOP;
- }
- else
- {
- if ( ( nRow < 0 ) || ( nRow >= PatternSize[nPat] ) ) { nRow = 0; }
- m_nPattern = nPat;
- m_nRow = m_nNextRow = nRow;
- m_nTickCount = m_nMusicSpeed;
- m_nPatternDelay = 0;
- m_nFrameDelay = 0;
- m_nBufferCount = 0;
- m_dwSongFlags |= SONG_PATTERNLOOP;
- }
- }
- UINT CSoundFile::GetBestSaveFormat() const
- //----------------------------------------
- {
- if ( ( !m_nSamples ) || ( !m_nChannels ) ) { return MOD_TYPE_NONE; }
- if ( !m_nType ) { return MOD_TYPE_NONE; }
- if ( m_nType & ( MOD_TYPE_MOD | MOD_TYPE_OKT ) )
- {
- return MOD_TYPE_MOD;
- }
- if ( m_nType & ( MOD_TYPE_S3M | MOD_TYPE_STM | MOD_TYPE_ULT | MOD_TYPE_FAR | MOD_TYPE_PTM ) )
- {
- return MOD_TYPE_S3M;
- }
- if ( m_nType & ( MOD_TYPE_XM | MOD_TYPE_MED | MOD_TYPE_MTM | MOD_TYPE_MT2 ) )
- {
- return MOD_TYPE_XM;
- }
- return MOD_TYPE_IT;
- }
- UINT CSoundFile::GetSaveFormats() const
- //-------------------------------------
- {
- UINT n = 0;
- if ( ( !m_nSamples ) || ( !m_nChannels ) || ( m_nType == MOD_TYPE_NONE ) ) { return 0; }
- switch ( m_nType )
- {
- case MOD_TYPE_MOD:
- n = MOD_TYPE_MOD;
- case MOD_TYPE_S3M:
- n = MOD_TYPE_S3M;
- }
- n |= MOD_TYPE_XM | MOD_TYPE_IT;
- if ( !m_nInstruments )
- {
- if ( m_nSamples < 32 ) { n |= MOD_TYPE_MOD; }
- n |= MOD_TYPE_S3M;
- }
- return n;
- }
- UINT CSoundFile::GetSampleName( UINT nSample, LPSTR s ) const
- //--------------------------------------------------------
- {
- char sztmp[40] = ""; // changed from CHAR
- memcpy( sztmp, m_szNames[nSample], 32 );
- sztmp[31] = 0;
- if ( s ) { strcpy( s, sztmp ); }
- return strlen( sztmp );
- }
- UINT CSoundFile::GetInstrumentName( UINT nInstr, LPSTR s ) const
- //-----------------------------------------------------------
- {
- char sztmp[40] = ""; // changed from CHAR
- if ( ( nInstr >= MAX_INSTRUMENTS ) || ( !Headers[nInstr] ) )
- {
- if ( s ) { *s = 0; }
- return 0;
- }
- INSTRUMENTHEADER* penv = Headers[nInstr];
- memcpy( sztmp, penv->name, 32 );
- sztmp[31] = 0;
- if ( s ) { strcpy( s, sztmp ); }
- return strlen( sztmp );
- }
- #ifndef NO_PACKING
- UINT CSoundFile::PackSample( int& sample, int next )
- //------------------------------------------------
- {
- UINT i = 0;
- int delta = next - sample;
- if ( delta >= 0 )
- {
- for ( i = 0; i < 7; i++ ) if ( delta <= ( int )CompressionTable[i + 1] ) { break; }
- }
- else
- {
- for ( i = 8; i < 15; i++ ) if ( delta >= ( int )CompressionTable[i + 1] ) { break; }
- }
- sample += ( int )CompressionTable[i];
- return i;
- }
- BOOL CSoundFile::CanPackSample( LPSTR pSample, UINT nLen, UINT nPacking, BYTE* result )
- //-----------------------------------------------------------------------------------
- {
- int pos, old, oldpos, besttable = 0;
- DWORD dwErr, dwTotal, dwResult;
- int i, j;
- if ( result ) { *result = 0; }
- if ( ( !pSample ) || ( nLen < 1024 ) ) { return FALSE; }
- // Try packing with different tables
- dwResult = 0;
- for ( j = 1; j < MAX_PACK_TABLES; j++ )
- {
- memcpy( CompressionTable, UnpackTable[j], 16 );
- dwErr = 0;
- dwTotal = 1;
- old = pos = oldpos = 0;
- for ( i = 0; i < ( int )nLen; i++ )
- {
- int s = ( int )pSample[i];
- PackSample( pos, s );
- dwErr += abs( pos - oldpos );
- dwTotal += abs( s - old );
- old = s;
- oldpos = pos;
- }
- dwErr = _muldiv( dwErr, 100, dwTotal );
- if ( dwErr >= dwResult )
- {
- dwResult = dwErr;
- besttable = j;
- }
- }
- memcpy( CompressionTable, UnpackTable[besttable], 16 );
- if ( result )
- {
- if ( dwResult > 100 ) { *result = 100; }
- else { *result = ( BYTE )dwResult; }
- }
- return ( dwResult >= nPacking ) ? TRUE : FALSE;
- }
- #endif // NO_PACKING
- #ifndef MODPLUG_NO_FILESAVE
- UINT CSoundFile::WriteSample( FILE* f, MODINSTRUMENT* pins, UINT nFlags, UINT nMaxLen )
- //-----------------------------------------------------------------------------------
- {
- UINT len = 0, bufcount;
- signed char buffer[4096];
- signed char* pSample = ( signed char* )pins->pSample;
- UINT nLen = pins->nLength;
- if ( ( nMaxLen ) && ( nLen > nMaxLen ) ) { nLen = nMaxLen; }
- if ( ( !pSample ) || ( f == NULL ) || ( !nLen ) ) { return 0; }
- switch ( nFlags )
- {
- #ifndef NO_PACKING
- // 3: 4-bit ADPCM data
- case RS_ADPCM4:
- {
- int pos;
- len = ( nLen + 1 ) / 2;
- fwrite( CompressionTable, 16, 1, f );
- bufcount = 0;
- pos = 0;
- for ( UINT j = 0; j < len; j++ )
- {
- BYTE b;
- // Sample #1
- b = PackSample( pos, ( int )pSample[j * 2] );
- // Sample #2
- b |= PackSample( pos, ( int )pSample[j * 2 + 1] ) << 4;
- buffer[bufcount++] = ( signed char )b;
- if ( bufcount >= sizeof( buffer ) )
- {
- fwrite( buffer, 1, bufcount, f );
- bufcount = 0;
- }
- }
- if ( bufcount ) { fwrite( buffer, 1, bufcount, f ); }
- len += 16;
- }
- break;
- #endif // NO_PACKING
- // 16-bit samples
- case RS_PCM16U:
- case RS_PCM16D:
- case RS_PCM16S:
- {
- int16_t* p = ( int16_t* )pSample;
- int s_old = 0, s_ofs;
- len = nLen * 2;
- bufcount = 0;
- s_ofs = ( nFlags == RS_PCM16U ) ? 0x8000 : 0;
- for ( UINT j = 0; j < nLen; j++ )
- {
- int s_new = *p;
- p++;
- if ( pins->uFlags & CHN_STEREO )
- {
- s_new = ( s_new + ( *p ) + 1 ) >> 1;
- p++;
- }
- if ( nFlags == RS_PCM16D )
- {
- int16_t temp = bswapLE16( ( int16_t )( s_new - s_old ) );
- *( ( int16_t* )( &buffer[bufcount] ) ) = temp;
- s_old = s_new;
- }
- else
- {
- int16_t temp = bswapLE16( ( int16_t )( s_new + s_ofs ) );
- *( ( int16_t* )( &buffer[bufcount] ) ) = temp;
- }
- bufcount += 2;
- if ( bufcount >= sizeof( buffer ) - 1 )
- {
- fwrite( buffer, 1, bufcount, f );
- bufcount = 0;
- }
- }
- if ( bufcount ) { fwrite( buffer, 1, bufcount, f ); }
- }
- break;
- // 8-bit Stereo samples (not interleaved)
- case RS_STPCM8S:
- case RS_STPCM8U:
- case RS_STPCM8D:
- {
- int s_ofs = ( nFlags == RS_STPCM8U ) ? 0x80 : 0;
- for ( UINT iCh = 0; iCh < 2; iCh++ )
- {
- signed char* p = pSample + iCh;
- int s_old = 0;
- bufcount = 0;
- for ( UINT j = 0; j < nLen; j++ )
- {
- int s_new = *p;
- p += 2;
- if ( nFlags == RS_STPCM8D )
- {
- buffer[bufcount++] = ( signed char )( s_new - s_old );
- s_old = s_new;
- }
- else
- {
- buffer[bufcount++] = ( signed char )( s_new + s_ofs );
- }
- if ( bufcount >= sizeof( buffer ) )
- {
- fwrite( buffer, 1, bufcount, f );
- bufcount = 0;
- }
- }
- if ( bufcount ) { fwrite( buffer, 1, bufcount, f ); }
- }
- }
- len = nLen * 2;
- break;
- // 16-bit Stereo samples (not interleaved)
- case RS_STPCM16S:
- case RS_STPCM16U:
- case RS_STPCM16D:
- {
- int s_ofs = ( nFlags == RS_STPCM16U ) ? 0x8000 : 0;
- for ( UINT iCh = 0; iCh < 2; iCh++ )
- {
- int16_t* p = ( ( int16_t* )pSample ) + iCh;
- int s_old = 0;
- bufcount = 0;
- for ( UINT j = 0; j < nLen; j++ )
- {
- int s_new = *p;
- p += 2;
- if ( nFlags == RS_STPCM16D )
- {
- int16_t temp = bswapLE16( ( int16_t )( s_new - s_old ) );
- *( ( int16_t* )( &buffer[bufcount] ) ) = temp;
- s_old = s_new;
- }
- else
- {
- int16_t temp = bswapLE16( ( int16_t )( s_new - s_ofs ) );
- *( ( int16_t* )( &buffer[bufcount] ) ) = temp;
- }
- bufcount += 2;
- if ( bufcount >= sizeof( buffer ) )
- {
- fwrite( buffer, 1, bufcount, f );
- bufcount = 0;
- }
- }
- if ( bufcount ) { fwrite( buffer, 1, bufcount, f ); }
- }
- }
- len = nLen * 4;
- break;
- // Stereo signed interleaved
- case RS_STIPCM8S:
- case RS_STIPCM16S:
- len = nLen * 2;
- if ( nFlags == RS_STIPCM16S ) { len *= 2; }
- fwrite( pSample, 1, len, f );
- break;
- // Default: assume 8-bit PCM data
- default:
- len = nLen;
- bufcount = 0;
- {
- signed char* p = pSample;
- int sinc = ( pins->uFlags & CHN_16BIT ) ? 2 : 1;
- int s_old = 0, s_ofs = ( nFlags == RS_PCM8U ) ? 0x80 : 0;
- if ( pins->uFlags & CHN_16BIT ) { p++; }
- for ( UINT j = 0; j < len; j++ )
- {
- int s_new = ( signed char )( *p );
- p += sinc;
- if ( pins->uFlags & CHN_STEREO )
- {
- s_new = ( s_new + ( ( int ) * p ) + 1 ) >> 1;
- p += sinc;
- }
- if ( nFlags == RS_PCM8D )
- {
- buffer[bufcount++] = ( signed char )( s_new - s_old );
- s_old = s_new;
- }
- else
- {
- buffer[bufcount++] = ( signed char )( s_new + s_ofs );
- }
- if ( bufcount >= sizeof( buffer ) )
- {
- fwrite( buffer, 1, bufcount, f );
- bufcount = 0;
- }
- }
- if ( bufcount ) { fwrite( buffer, 1, bufcount, f ); }
- }
- }
- return len;
- }
- #endif // MODPLUG_NO_FILESAVE
- // Flags:
- // 0 = signed 8-bit PCM data (default)
- // 1 = unsigned 8-bit PCM data
- // 2 = 8-bit ADPCM data with linear table
- // 3 = 4-bit ADPCM data
- // 4 = 16-bit ADPCM data with linear table
- // 5 = signed 16-bit PCM data
- // 6 = unsigned 16-bit PCM data
- UINT CSoundFile::ReadSample( MODINSTRUMENT* pIns, UINT nFlags, LPCSTR lpMemFile, DWORD dwMemLength )
- //------------------------------------------------------------------------------
- {
- UINT len = 0, mem = pIns->nLength + 6;
- // Disable >2Gb samples,(preventing buffer overflow in AllocateSample)
- if ( ( !pIns ) || ( ( int )pIns->nLength < 4 ) || ( !lpMemFile ) ) { return 0; }
- if ( pIns->nLength > MAX_SAMPLE_LENGTH ) { pIns->nLength = MAX_SAMPLE_LENGTH; }
- pIns->uFlags &= ~( CHN_16BIT | CHN_STEREO );
- if ( nFlags & RSF_16BIT )
- {
- mem *= 2;
- pIns->uFlags |= CHN_16BIT;
- }
- if ( nFlags & RSF_STEREO )
- {
- mem *= 2;
- pIns->uFlags |= CHN_STEREO;
- }
- if ( ( pIns->pSample = AllocateSample( mem ) ) == NULL )
- {
- pIns->nLength = 0;
- return 0;
- }
- switch ( nFlags )
- {
- // 1: 8-bit unsigned PCM data
- case RS_PCM8U:
- {
- len = pIns->nLength;
- if ( len > dwMemLength ) { len = pIns->nLength = dwMemLength; }
- signed char* pSample = pIns->pSample;
- for ( UINT j = 0; j < len; j++ ) { pSample[j] = ( signed char )( lpMemFile[j] - 0x80 ); }
- }
- break;
- // 2: 8-bit ADPCM data with linear table
- case RS_PCM8D:
- {
- len = pIns->nLength;
- if ( len > dwMemLength ) { break; }
- signed char* pSample = pIns->pSample;
- const signed char* p = ( const signed char* )lpMemFile;
- int delta = 0;
- for ( UINT j = 0; j < len; j++ )
- {
- delta += p[j];
- *pSample++ = ( signed char )delta;
- }
- }
- break;
- // 3: 4-bit ADPCM data
- case RS_ADPCM4:
- {
- len = ( pIns->nLength + 1 ) / 2;
- if ( len > dwMemLength - 16 ) { break; }
- memcpy( CompressionTable, lpMemFile, 16 );
- lpMemFile += 16;
- signed char* pSample = pIns->pSample;
- signed char delta = 0;
- for ( UINT j = 0; j < len; j++ )
- {
- BYTE b0 = ( BYTE )lpMemFile[j];
- BYTE b1 = ( BYTE )( lpMemFile[j] >> 4 );
- delta = ( signed char )GetDeltaValue( ( int )delta, b0 );
- pSample[0] = delta;
- delta = ( signed char )GetDeltaValue( ( int )delta, b1 );
- pSample[1] = delta;
- pSample += 2;
- }
- len += 16;
- }
- break;
- // 4: 16-bit ADPCM data with linear table
- case RS_PCM16D:
- {
- len = pIns->nLength * 2;
- if ( len > dwMemLength ) { break; }
- int16_t* pSample = ( int16_t* )pIns->pSample;
- int16_t* p = ( int16_t* )lpMemFile;
- int delta16 = 0;
- for ( UINT j = 0; j < len; j += 2 )
- {
- delta16 += bswapLE16( *p++ );
- *pSample++ = ( int16_t )delta16;
- }
- }
- break;
- // 5: 16-bit signed PCM data
- case RS_PCM16S:
- {
- len = pIns->nLength * 2;
- if ( len <= dwMemLength ) { memcpy( pIns->pSample, lpMemFile, len ); }
- int16_t* pSample = ( int16_t* )pIns->pSample;
- for ( UINT j = 0; j < len; j += 2 )
- {
- int16_t rawSample = *pSample;
- *pSample++ = bswapLE16( rawSample );
- }
- }
- break;
- // 16-bit signed mono PCM motorola byte order
- case RS_PCM16M:
- len = pIns->nLength * 2;
- if ( len > dwMemLength ) { len = dwMemLength & ~1; }
- if ( len > 1 )
- {
- signed char* pSample = ( signed char* )pIns->pSample;
- signed char* pSrc = ( signed char* )lpMemFile;
- for ( UINT j = 0; j < len; j += 2 )
- {
- // pSample[j] = pSrc[j+1];
- // pSample[j+1] = pSrc[j];
- *( ( uint16_t* )( pSample + j ) ) = bswapBE16( *( ( uint16_t* )( pSrc + j ) ) );
- }
- }
- break;
- // 6: 16-bit unsigned PCM data
- case RS_PCM16U:
- {
- len = pIns->nLength * 2;
- if ( len > dwMemLength ) { break; }
- int16_t* pSample = ( int16_t* )pIns->pSample;
- int16_t* pSrc = ( int16_t* )lpMemFile;
- for ( UINT j = 0; j < len; j += 2 ) { *pSample++ = bswapLE16( *( pSrc++ ) ) - 0x8000; }
- }
- break;
- // 16-bit signed stereo big endian
- case RS_STPCM16M:
- len = pIns->nLength * 2;
- if ( len * 2 <= dwMemLength )
- {
- signed char* pSample = ( signed char* )pIns->pSample;
- signed char* pSrc = ( signed char* )lpMemFile;
- for ( UINT j = 0; j < len; j += 2 )
- {
- // pSample[j*2] = pSrc[j+1];
- // pSample[j*2+1] = pSrc[j];
- // pSample[j*2+2] = pSrc[j+1+len];
- // pSample[j*2+3] = pSrc[j+len];
- *( ( uint16_t* )( pSample + j * 2 ) ) = bswapBE16( *( ( uint16_t* )( pSrc + j ) ) );
- *( ( uint16_t* )( pSample + j * 2 + 2 ) ) = bswapBE16( *( ( uint16_t* )( pSrc + j + len ) ) );
- }
- len *= 2;
- }
- break;
- // 8-bit stereo samples
- case RS_STPCM8S:
- case RS_STPCM8U:
- case RS_STPCM8D:
- {
- int iadd_l = 0, iadd_r = 0;
- if ( nFlags == RS_STPCM8U ) { iadd_l = iadd_r = -128; }
- len = pIns->nLength;
- signed char* psrc = ( signed char* )lpMemFile;
- signed char* pSample = ( signed char* )pIns->pSample;
- if ( len * 2 > dwMemLength ) { break; }
- for ( UINT j = 0; j < len; j++ )
- {
- pSample[j * 2] = ( signed char )( psrc[0] + iadd_l );
- pSample[j * 2 + 1] = ( signed char )( psrc[len] + iadd_r );
- psrc++;
- if ( nFlags == RS_STPCM8D )
- {
- iadd_l = pSample[j * 2];
- iadd_r = pSample[j * 2 + 1];
- }
- }
- len *= 2;
- }
- break;
- // 16-bit stereo samples
- case RS_STPCM16S:
- case RS_STPCM16U:
- case RS_STPCM16D:
- {
- int iadd_l = 0, iadd_r = 0;
- if ( nFlags == RS_STPCM16U ) { iadd_l = iadd_r = -0x8000; }
- len = pIns->nLength;
- int16_t* psrc = ( int16_t* )lpMemFile;
- int16_t* pSample = ( int16_t* )pIns->pSample;
- if ( len * 4 > dwMemLength ) { break; }
- for ( UINT j = 0; j < len; j++ )
- {
- pSample[j * 2] = ( int16_t ) ( bswapLE16( psrc[0] ) + iadd_l );
- pSample[j * 2 + 1] = ( int16_t ) ( bswapLE16( psrc[len] ) + iadd_r );
- psrc++;
- if ( nFlags == RS_STPCM16D )
- {
- iadd_l = pSample[j * 2];
- iadd_r = pSample[j * 2 + 1];
- }
- }
- len *= 4;
- }
- break;
- // IT 2.14 compressed samples
- case RS_IT2148:
- case RS_IT21416:
- case RS_IT2158:
- case RS_IT21516:
- len = dwMemLength;
- if ( len < 4 ) { break; }
- if ( ( nFlags == RS_IT2148 ) || ( nFlags == RS_IT2158 ) )
- {
- ITUnpack8Bit( pIns->pSample, pIns->nLength, ( LPBYTE )lpMemFile, dwMemLength, ( nFlags == RS_IT2158 ) );
- }
- else
- {
- ITUnpack16Bit( pIns->pSample, pIns->nLength, ( LPBYTE )lpMemFile, dwMemLength, ( nFlags == RS_IT21516 ) );
- }
- break;
- #ifndef MODPLUG_BASIC_SUPPORT
- #ifndef MODPLUG_FASTSOUNDLIB
- // 8-bit interleaved stereo samples
- case RS_STIPCM8S:
- case RS_STIPCM8U:
- {
- int iadd = 0;
- if ( nFlags == RS_STIPCM8U ) { iadd = -0x80; }
- len = pIns->nLength;
- if ( len * 2 > dwMemLength ) { len = dwMemLength >> 1; }
- LPBYTE psrc = ( LPBYTE )lpMemFile;
- LPBYTE pSample = ( LPBYTE )pIns->pSample;
- for ( UINT j = 0; j < len; j++ )
- {
- pSample[j * 2] = ( signed char )( psrc[0] + iadd );
- pSample[j * 2 + 1] = ( signed char )( psrc[1] + iadd );
- psrc += 2;
- }
- len *= 2;
- }
- break;
- // 16-bit interleaved stereo samples
- case RS_STIPCM16S:
- case RS_STIPCM16U:
- {
- int iadd = 0;
- if ( nFlags == RS_STIPCM16U ) { iadd = -32768; }
- len = pIns->nLength;
- if ( len * 4 > dwMemLength ) { len = dwMemLength >> 2; }
- int16_t* psrc = ( int16_t* )lpMemFile;
- int16_t* pSample = ( int16_t* )pIns->pSample;
- for ( UINT j = 0; j < len; j++ )
- {
- pSample[j * 2] = ( int16_t )( bswapLE16( psrc[0] ) + iadd );
- pSample[j * 2 + 1] = ( int16_t )( bswapLE16( psrc[1] ) + iadd );
- psrc += 2;
- }
- len *= 4;
- }
- break;
- // AMS compressed samples
- case RS_AMS8:
- case RS_AMS16:
- len = 9;
- if ( dwMemLength > 9 )
- {
- const char* psrc = lpMemFile;
- char packcharacter = lpMemFile[8], *pdest = ( char* )pIns->pSample;
- len += bswapLE32( *( ( LPDWORD )( lpMemFile + 4 ) ) );
- if ( len > dwMemLength ) { len = dwMemLength; }
- UINT dmax = pIns->nLength;
- if ( pIns->uFlags & CHN_16BIT ) { dmax <<= 1; }
- AMSUnpack( psrc + 9, len - 9, pdest, dmax, packcharacter );
- }
- break;
- // PTM 8bit delta to 16-bit sample
- case RS_PTM8DTO16:
- {
- len = pIns->nLength * 2;
- if ( len > dwMemLength ) { break; }
- int8_t* pSample = ( int8_t* )pIns->pSample;
- int8_t delta8 = 0;
- for ( UINT j = 0; j < len; j++ )
- {
- delta8 += lpMemFile[j];
- *pSample++ = delta8;
- }
- uint16_t* pSampleW = ( uint16_t* )pIns->pSample;
- for ( UINT j = 0; j < len; j += 2 ) // swaparoni!
- {
- uint16_t rawSample = *pSampleW;
- *pSampleW++ = bswapLE16( rawSample );
- }
- }
- break;
- // Huffman MDL compressed samples
- case RS_MDL8:
- case RS_MDL16:
- len = dwMemLength;
- if ( len >= 4 )
- {
- LPBYTE pSample = ( LPBYTE )pIns->pSample;
- LPBYTE ibuf = ( LPBYTE )lpMemFile;
- DWORD bitbuf = bswapLE32( *( ( DWORD* )ibuf ) );
- UINT bitnum = 32;
- BYTE dlt = 0, lowbyte = 0;
- ibuf += 4;
- for ( UINT j = 0; j < pIns->nLength; j++ )
- {
- BYTE hibyte;
- BYTE sign;
- if ( nFlags == RS_MDL16 ) { lowbyte = ( BYTE )MDLReadBits( bitbuf, bitnum, ibuf, 8 ); }
- sign = ( BYTE )MDLReadBits( bitbuf, bitnum, ibuf, 1 );
- if ( MDLReadBits( bitbuf, bitnum, ibuf, 1 ) )
- {
- hibyte = ( BYTE )MDLReadBits( bitbuf, bitnum, ibuf, 3 );
- }
- else
- {
- hibyte = 8;
- while ( !MDLReadBits( bitbuf, bitnum, ibuf, 1 ) ) { hibyte += 0x10; }
- hibyte += MDLReadBits( bitbuf, bitnum, ibuf, 4 );
- }
- if ( sign ) { hibyte = ~hibyte; }
- dlt += hibyte;
- if ( nFlags != RS_MDL16 )
- {
- pSample[j] = dlt;
- }
- else
- {
- pSample[j << 1] = lowbyte;
- pSample[( j << 1 ) + 1] = dlt;
- }
- }
- }
- break;
- case RS_DMF8:
- case RS_DMF16:
- len = dwMemLength;
- if ( len >= 4 )
- {
- UINT maxlen = pIns->nLength;
- if ( pIns->uFlags & CHN_16BIT ) { maxlen <<= 1; }
- LPBYTE ibuf = ( LPBYTE )lpMemFile, ibufmax = ( LPBYTE )( lpMemFile + dwMemLength );
- len = DMFUnpack( ( LPBYTE )pIns->pSample, ibuf, ibufmax, maxlen );
- }
- break;
- #ifdef MODPLUG_TRACKER
- // PCM 24-bit signed -> load sample, and normalize it to 16-bit
- case RS_PCM24S:
- case RS_PCM32S:
- len = pIns->nLength * 3;
- if ( nFlags == RS_PCM32S ) { len += pIns->nLength; }
- if ( len > dwMemLength ) { break; }
- if ( len > 4 * 8 )
- {
- UINT slsize = ( nFlags == RS_PCM32S ) ? 4 : 3;
- LPBYTE pSrc = ( LPBYTE )lpMemFile;
- LONG max = 255;
- if ( nFlags == RS_PCM32S ) { pSrc++; }
- for ( UINT j = 0; j < len; j += slsize )
- {
- LONG l = ( ( ( ( pSrc[j + 2] << 8 ) + pSrc[j + 1] ) << 8 ) + pSrc[j] ) << 8;
- l /= 256;
- if ( l > max ) { max = l; }
- if ( -l > max ) { max = -l; }
- }
- max = ( max / 128 ) + 1;
- int16_t* pDest = ( int16_t* )pIns->pSample;
- for ( UINT k = 0; k < len; k += slsize )
- {
- LONG l = ( ( ( ( pSrc[k + 2] << 8 ) + pSrc[k + 1] ) << 8 ) + pSrc[k] ) << 8;
- *pDest++ = ( uint16_t )( l / max );
- }
- }
- break;
- // Stereo PCM 24-bit signed -> load sample, and normalize it to 16-bit
- case RS_STIPCM24S:
- case RS_STIPCM32S:
- len = pIns->nLength * 6;
- if ( nFlags == RS_STIPCM32S ) { len += pIns->nLength * 2; }
- if ( len > dwMemLength ) { break; }
- if ( len > 8 * 8 )
- {
- UINT slsize = ( nFlags == RS_STIPCM32S ) ? 4 : 3;
- LPBYTE pSrc = ( LPBYTE )lpMemFile;
- LONG max = 255;
- if ( nFlags == RS_STIPCM32S ) { pSrc++; }
- for ( UINT j = 0; j < len; j += slsize )
- {
- LONG l = ( ( ( ( pSrc[j + 2] << 8 ) + pSrc[j + 1] ) << 8 ) + pSrc[j] ) << 8;
- l /= 256;
- if ( l > max ) { max = l; }
- if ( -l > max ) { max = -l; }
- }
- max = ( max / 128 ) + 1;
- int16_t* pDest = ( int16_t* )pIns->pSample;
- for ( UINT k = 0; k < len; k += slsize )
- {
- LONG lr = ( ( ( ( pSrc[k + 2] << 8 ) + pSrc[k + 1] ) << 8 ) + pSrc[k] ) << 8;
- k += slsize;
- LONG ll = ( ( ( ( pSrc[k + 2] << 8 ) + pSrc[k + 1] ) << 8 ) + pSrc[k] ) << 8;
- pDest[0] = ( int16_t )ll;
- pDest[1] = ( int16_t )lr;
- pDest += 2;
- }
- }
- break;
- // 16-bit signed big endian interleaved stereo
- case RS_STIPCM16M:
- {
- len = pIns->nLength;
- if ( len * 4 > dwMemLength ) { len = dwMemLength >> 2; }
- LPCBYTE psrc = ( LPCBYTE )lpMemFile;
- int16_t* pSample = ( int16_t* )pIns->pSample;
- for ( UINT j = 0; j < len; j++ )
- {
- pSample[j * 2] = ( int16_t )( ( ( UINT )psrc[0] << 8 ) | ( psrc[1] ) );
- pSample[j * 2 + 1] = ( int16_t )( ( ( UINT )psrc[2] << 8 ) | ( psrc[3] ) );
- psrc += 4;
- }
- len *= 4;
- }
- break;
- #endif // MODPLUG_TRACKER
- #endif // !MODPLUG_FASTSOUNDLIB
- #endif // !MODPLUG_BASIC_SUPPORT
- // Default: 8-bit signed PCM data
- default:
- len = pIns->nLength;
- if ( len > dwMemLength ) { len = pIns->nLength = dwMemLength; }
- memcpy( pIns->pSample, lpMemFile, len );
- }
- if ( len > dwMemLength )
- {
- if ( pIns->pSample )
- {
- pIns->nLength = 0;
- FreeSample( pIns->pSample );
- pIns->pSample = NULL;
- }
- return 0;
- }
- AdjustSampleLoop( pIns );
- return len;
- }
- void CSoundFile::AdjustSampleLoop( MODINSTRUMENT* pIns )
- //----------------------------------------------------
- {
- if ( !pIns->pSample ) { return; }
- if ( pIns->nLoopEnd > pIns->nLength ) { pIns->nLoopEnd = pIns->nLength; }
- if ( pIns->nLoopStart + 2 >= pIns->nLoopEnd )
- {
- pIns->nLoopStart = pIns->nLoopEnd = 0;
- pIns->uFlags &= ~CHN_LOOP;
- }
- UINT len = pIns->nLength;
- if ( pIns->uFlags & CHN_16BIT )
- {
- int16_t* pSample = ( int16_t* )pIns->pSample;
- // Adjust end of sample
- if ( pIns->uFlags & CHN_STEREO )
- {
- pSample[len * 2 + 6] = pSample[len * 2 + 4] = pSample[len * 2 + 2] = pSample[len * 2] = 0;
- pSample[len * 2 + 7] = pSample[len * 2 + 5] = pSample[len * 2 + 3] = pSample[len * 2 + 1] = 0;
- }
- else
- {
- pSample[len + 4] = pSample[len + 3] = pSample[len + 2] = pSample[len + 1] = pSample[len] = 0;
- }
- if ( ( pIns->uFlags & ( CHN_LOOP | CHN_PINGPONGLOOP | CHN_STEREO ) ) == CHN_LOOP )
- {
- // Fix bad loops
- if ( ( pIns->nLoopEnd + 3 >= pIns->nLength ) || ( m_nType & MOD_TYPE_S3M ) )
- {
- pSample[pIns->nLoopEnd] = pSample[pIns->nLoopStart];
- pSample[pIns->nLoopEnd + 1] = pSample[pIns->nLoopStart + 1];
- pSample[pIns->nLoopEnd + 2] = pSample[pIns->nLoopStart + 2];
- pSample[pIns->nLoopEnd + 3] = pSample[pIns->nLoopStart + 3];
- pSample[pIns->nLoopEnd + 4] = pSample[pIns->nLoopStart + 4];
- }
- }
- }
- else
- {
- signed char* pSample = pIns->pSample;
- #ifndef MODPLUG_FASTSOUNDLIB
- // Crappy samples (except chiptunes) ?
- if ( ( pIns->nLength > 0x100 ) && ( m_nType & ( MOD_TYPE_MOD | MOD_TYPE_S3M ) )
- && ( !( pIns->uFlags & CHN_STEREO ) ) )
- {
- int smpend = pSample[pIns->nLength - 1], smpfix = 0, kscan;
- for ( kscan = pIns->nLength - 1; kscan > 0; kscan-- )
- {
- smpfix = pSample[kscan - 1];
- if ( smpfix != smpend ) { break; }
- }
- int delta = smpfix - smpend;
- if ( ( ( !( pIns->uFlags & CHN_LOOP ) ) || ( kscan > ( int )pIns->nLoopEnd ) )
- && ( ( delta < -8 ) || ( delta > 8 ) ) )
- {
- while ( kscan < ( int )pIns->nLength )
- {
- if ( !( kscan & 7 ) )
- {
- if ( smpfix > 0 ) { smpfix--; }
- if ( smpfix < 0 ) { smpfix++; }
- }
- pSample[kscan] = ( signed char )smpfix;
- kscan++;
- }
- }
- }
- #endif
- // Adjust end of sample
- if ( pIns->uFlags & CHN_STEREO )
- {
- pSample[len * 2 + 6] = pSample[len * 2 + 4] = pSample[len * 2 + 2] = pSample[len * 2] = 0;
- pSample[len * 2 + 7] = pSample[len * 2 + 5] = pSample[len * 2 + 3] = pSample[len * 2 + 1] = 0;
- }
- else
- {
- pSample[len + 4] = pSample[len + 3] = pSample[len + 2] = pSample[len + 1] = pSample[len] = 0;
- }
- if ( ( pIns->uFlags & ( CHN_LOOP | CHN_PINGPONGLOOP | CHN_STEREO ) ) == CHN_LOOP )
- {
- if ( ( pIns->nLoopEnd + 3 >= pIns->nLength ) || ( m_nType & ( MOD_TYPE_MOD | MOD_TYPE_S3M ) ) )
- {
- pSample[pIns->nLoopEnd] = pSample[pIns->nLoopStart];
- pSample[pIns->nLoopEnd + 1] = pSample[pIns->nLoopStart + 1];
- pSample[pIns->nLoopEnd + 2] = pSample[pIns->nLoopStart + 2];
- pSample[pIns->nLoopEnd + 3] = pSample[pIns->nLoopStart + 3];
- pSample[pIns->nLoopEnd + 4] = pSample[pIns->nLoopStart + 4];
- }
- }
- }
- }
- /////////////////////////////////////////////////////////////
- // Transpose <-> Frequency conversions
- // returns 8363*2^((transp*128+ftune)/(12*128))
- DWORD CSoundFile::TransposeToFrequency( int transp, int ftune )
- //-----------------------------------------------------------
- {
- #ifdef MSC_VER
- const float _fbase = 8363;
- const float _factor = 1.0f / ( 12.0f * 128.0f );
- int result;
- DWORD freq;
- transp = ( transp << 7 ) + ftune;
- _asm
- {
- fild transp
- fld _factor
- fmulp st( 1 ), st( 0 )
- fist result
- fisub result
- f2xm1
- fild result
- fld _fbase
- fscale
- fstp st( 1 )
- fmul st( 1 ), st( 0 )
- faddp st( 1 ), st( 0 )
- fistp freq
- }
- UINT derr = freq % 11025;
- if ( derr <= 8 ) { freq -= derr; }
- if ( derr >= 11015 ) { freq += 11025 - derr; }
- derr = freq % 1000;
- if ( derr <= 5 ) { freq -= derr; }
- if ( derr >= 995 ) { freq += 1000 - derr; }
- return freq;
- #else
- //---GCCFIX: Removed assembly.
- return ( DWORD )( 8363 * pow( 2, ( double )( transp * 128 + ftune ) / ( 1536 ) ) );
- #endif
- }
- // returns 12*128*log2(freq/8363)
- int CSoundFile::FrequencyToTranspose( DWORD freq )
- //----------------------------------------------
- {
- #ifdef MSC_VER
- const float _f1_8363 = 1.0f / 8363.0f;
- const float _factor = 128 * 12;
- LONG result;
- if ( !freq ) { return 0; }
- _asm
- {
- fld _factor
- fild freq
- fld _f1_8363
- fmulp st( 1 ), st( 0 )
- fyl2x
- fistp result
- }
- return result;
- #else
- //---GCCFIX: Removed assembly.
- return int( 1536 * ( log( freq / 8363.0 ) / log( 2.0 ) ) );
- #endif
- }
- void CSoundFile::FrequencyToTranspose( MODINSTRUMENT* psmp )
- //--------------------------------------------------------
- {
- int f2t = FrequencyToTranspose( psmp->nC4Speed );
- int transp = f2t >> 7;
- int ftune = f2t & 0x7F;
- if ( ftune > 80 )
- {
- transp++;
- ftune -= 128;
- }
- if ( transp > 127 ) { transp = 127; }
- if ( transp < -127 ) { transp = -127; }
- psmp->RelativeTone = transp;
- psmp->nFineTune = ftune;
- }
- void CSoundFile::CheckCPUUsage( UINT nCPU )
- //---------------------------------------
- {
- if ( nCPU > 100 ) { nCPU = 100; }
- gnCPUUsage = nCPU;
- if ( nCPU < 90 )
- {
- m_dwSongFlags &= ~SONG_CPUVERYHIGH;
- }
- else if ( ( m_dwSongFlags & SONG_CPUVERYHIGH ) && ( nCPU >= 94 ) )
- {
- UINT i = MAX_CHANNELS;
- while ( i >= 8 )
- {
- i--;
- if ( Chn[i].nLength )
- {
- Chn[i].nLength = Chn[i].nPos = 0;
- nCPU -= 2;
- if ( nCPU < 94 ) { break; }
- }
- }
- }
- else if ( nCPU > 90 )
- {
- m_dwSongFlags |= SONG_CPUVERYHIGH;
- }
- }
- BOOL CSoundFile::SetPatternName( UINT nPat, LPCSTR lpszName )
- //---------------------------------------------------------
- {
- char szName[MAX_PATTERNNAME] = ""; // changed from CHAR
- if ( nPat >= MAX_PATTERNS ) { return FALSE; }
- if ( lpszName ) { lstrcpyn( szName, lpszName, MAX_PATTERNNAME ); }
- szName[MAX_PATTERNNAME - 1] = 0;
- if ( !m_lpszPatternNames ) { m_nPatternNames = 0; }
- if ( nPat >= m_nPatternNames )
- {
- if ( !lpszName[0] ) { return TRUE; }
- UINT len = ( nPat + 1 ) * MAX_PATTERNNAME;
- char* p = new char[len]; // changed from CHAR
- if ( !p ) { return FALSE; }
- memset( p, 0, len );
- if ( m_lpszPatternNames )
- {
- memcpy( p, m_lpszPatternNames, m_nPatternNames * MAX_PATTERNNAME );
- delete [] m_lpszPatternNames;
- m_lpszPatternNames = NULL;
- }
- m_lpszPatternNames = p;
- m_nPatternNames = nPat + 1;
- }
- memcpy( m_lpszPatternNames + nPat * MAX_PATTERNNAME, szName, MAX_PATTERNNAME );
- return TRUE;
- }
- BOOL CSoundFile::GetPatternName( UINT nPat, LPSTR lpszName, UINT cbSize ) const
- //---------------------------------------------------------------------------
- {
- if ( ( !lpszName ) || ( !cbSize ) ) { return FALSE; }
- lpszName[0] = 0;
- if ( cbSize > MAX_PATTERNNAME ) { cbSize = MAX_PATTERNNAME; }
- if ( ( m_lpszPatternNames ) && ( nPat < m_nPatternNames ) )
- {
- memcpy( lpszName, m_lpszPatternNames + nPat * MAX_PATTERNNAME, cbSize );
- lpszName[cbSize - 1] = 0;
- return TRUE;
- }
- return FALSE;
- }
- #ifndef MODPLUG_FASTSOUNDLIB
- UINT CSoundFile::DetectUnusedSamples( BOOL* pbIns )
- //-----------------------------------------------
- {
- UINT nExt = 0;
- if ( !pbIns ) { return 0; }
- if ( m_nInstruments )
- {
- memset( pbIns, 0, MAX_SAMPLES * sizeof( BOOL ) );
- for ( UINT ipat = 0; ipat < MAX_PATTERNS; ipat++ )
- {
- MODCOMMAND* p = Patterns[ipat];
- if ( p )
- {
- UINT jmax = PatternSize[ipat] * m_nChannels;
- for ( UINT j = 0; j < jmax; j++, p++ )
- {
- if ( ( p->note ) && ( p->note <= NOTE_MAX ) )
- {
- if ( ( p->instr ) && ( p->instr < MAX_INSTRUMENTS ) )
- {
- INSTRUMENTHEADER* penv = Headers[p->instr];
- if ( penv )
- {
- UINT n = penv->Keyboard[p->note - 1];
- if ( n < MAX_SAMPLES ) { pbIns[n] = TRUE; }
- }
- }
- else
- {
- for ( UINT k = 1; k <= m_nInstruments; k++ )
- {
- INSTRUMENTHEADER* penv = Headers[k];
- if ( penv )
- {
- UINT n = penv->Keyboard[p->note - 1];
- if ( n < MAX_SAMPLES ) { pbIns[n] = TRUE; }
- }
- }
- }
- }
- }
- }
- }
- for ( UINT ichk = 1; ichk <= m_nSamples; ichk++ )
- {
- if ( ( !pbIns[ichk] ) && ( Ins[ichk].pSample ) ) { nExt++; }
- }
- }
- return nExt;
- }
- BOOL CSoundFile::RemoveSelectedSamples( BOOL* pbIns )
- //-------------------------------------------------
- {
- if ( !pbIns ) { return FALSE; }
- for ( UINT j = 1; j < MAX_SAMPLES; j++ )
- {
- if ( ( !pbIns[j] ) && ( Ins[j].pSample ) )
- {
- DestroySample( j );
- if ( ( j == m_nSamples ) && ( j > 1 ) ) { m_nSamples--; }
- }
- }
- return TRUE;
- }
- BOOL CSoundFile::DestroySample( UINT nSample )
- //------------------------------------------
- {
- if ( ( !nSample ) || ( nSample >= MAX_SAMPLES ) ) { return FALSE; }
- if ( !Ins[nSample].pSample ) { return TRUE; }
- MODINSTRUMENT* pins = &Ins[nSample];
- signed char* pSample = pins->pSample;
- pins->pSample = NULL;
- pins->nLength = 0;
- pins->uFlags &= ~( CHN_16BIT );
- for ( UINT i = 0; i < MAX_CHANNELS; i++ )
- {
- if ( Chn[i].pSample == pSample )
- {
- Chn[i].nPos = Chn[i].nLength = 0;
- Chn[i].pSample = Chn[i].pCurrentSample = NULL;
- }
- }
- FreeSample( pSample );
- return TRUE;
- }
- #endif // MODPLU