123
This commit is contained in:
558
CrySoundSystem/ADPCMDecoder.cpp
Normal file
558
CrySoundSystem/ADPCMDecoder.cpp
Normal file
@@ -0,0 +1,558 @@
|
||||
#include "StdAfx.h"
|
||||
#include <CrySizer.h>
|
||||
#include <ISound.h>
|
||||
#include <ISystem.h>
|
||||
#include <ICryPak.h>
|
||||
#include "AdpcmDecoder.h"
|
||||
|
||||
template< typename T, typename S >
|
||||
inline void lsbshortldi( T& x, S& p )
|
||||
{
|
||||
x = (T) ( (int) p[ 0 ] + ( (int) p[ 1 ] << 8 ) );
|
||||
p += 2;
|
||||
}
|
||||
|
||||
static const int stepAdjustTable[] =
|
||||
{
|
||||
230, 230, 230, 230, 307, 409, 512, 614,
|
||||
768, 614, 512, 409, 307, 230, 230, 230
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CADPCMDecoder::CADPCMDecoder(IMusicSystem *pMusicSystem) : m_bOpen(false)
|
||||
{
|
||||
m_pMusicSystem=pMusicSystem;
|
||||
ISystem *pSystem=m_pMusicSystem->GetSystem();
|
||||
ASSERT(pSystem);
|
||||
m_pPak=pSystem->GetIPak();
|
||||
ASSERT(m_pPak);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline CADPCMDecoder::~CADPCMDecoder()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
inline const bool CADPCMDecoder::IsOpen()const
|
||||
{
|
||||
return m_bOpen;
|
||||
}
|
||||
|
||||
inline FILE* CADPCMDecoder::GetNewFileHandle()
|
||||
{
|
||||
FILE *pNewFile = m_pPak->FOpen(m_szFilename.c_str(), "rb");
|
||||
if (!pNewFile)
|
||||
return NULL;
|
||||
return pNewFile;
|
||||
}
|
||||
|
||||
inline void CADPCMDecoder::CloseFileHandle(FILE*& pFile)
|
||||
{
|
||||
if (pFile)
|
||||
{
|
||||
m_pPak->FClose(pFile);
|
||||
pFile=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
inline void CADPCMDecoder::SetFileInfo(const unsigned int cuiSampleCount, const bool cbIs44KHz)
|
||||
{
|
||||
m_FileInfo.nSamples = cuiSampleCount;//already doubled up
|
||||
m_b44KHz = cbIs44KHz;
|
||||
m_bOpen = true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline bool CADPCMDecoder::Open(const char *pszFilename)
|
||||
{
|
||||
m_FileInfo.sFilename = pszFilename;
|
||||
m_szFilename = pszFilename;//damn it, but how can i get a const char* from the other string type, why do we have an own?
|
||||
m_FileInfo.nHeaderSize = scuiSizeOfWavHeader;
|
||||
return m_bOpen;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline bool CADPCMDecoder::Close()
|
||||
{
|
||||
m_bOpen = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline const char* CADPCMDecoder::FileName() const
|
||||
{
|
||||
return m_szFilename.c_str();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline bool CADPCMDecoder::GetFileInfo(SMusicPatternFileInfo &FileInfo)
|
||||
{
|
||||
FileInfo=m_FileInfo;
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline void CADPCMDecoder::GetMemoryUsage(class ICrySizer* pSizer)
|
||||
{
|
||||
if (!pSizer->Add(*this))
|
||||
return;
|
||||
}
|
||||
|
||||
inline int CADPCMDecoder::AdpcmDecode( int c, MsState& rState, int sample1, int sample2 )
|
||||
{
|
||||
// Compute next step value
|
||||
int step( rState.step );
|
||||
|
||||
int nstep( ( stepAdjustTable[ c ] * step ) >> 8 );
|
||||
rState.step = ( nstep < 16 ) ? 16 : nstep;
|
||||
|
||||
// make linear prediction for next sample
|
||||
int vlin( ( ( sample1 * rState.sCoef0 ) + ( sample2 * rState.sCoef1 ) ) >> 8 );
|
||||
|
||||
// then add the code * step adjustment
|
||||
c -= ( c & 0x08 ) << 1;
|
||||
int sample( ( c * step ) + vlin );
|
||||
|
||||
if( sample > 0x7fff )
|
||||
sample = 0x7fff;
|
||||
else if( sample < -0x8000 )
|
||||
sample = -0x8000;
|
||||
|
||||
return( sample );
|
||||
}
|
||||
|
||||
void CADPCMDecoder::AdpcmBlockExpandI( int nCoef, const short* iCoef, const unsigned char* ibuff, short* obuff, int n )
|
||||
{
|
||||
MsState state[ 2 ]; // One decompressor state for each channel
|
||||
|
||||
// Read the four-byte header for each channel
|
||||
const unsigned char* ip( ibuff );
|
||||
unsigned char bpred( *ip++ );
|
||||
state[ 0 ].sCoef0 = iCoef[ (int) bpred * 2 + 0 ];
|
||||
state[ 0 ].sCoef1 = iCoef[ (int) bpred * 2 + 1 ];
|
||||
bpred = ( *ip++ );
|
||||
state[ 1 ].sCoef0 = iCoef[ (int) bpred * 2 + 0 ];
|
||||
state[ 1 ].sCoef1 = iCoef[ (int) bpred * 2 + 1 ];
|
||||
|
||||
lsbshortldi( state[0].step, ip );
|
||||
lsbshortldi( state[1].step, ip );
|
||||
// sample1's directly into obuff
|
||||
|
||||
lsbshortldi( obuff[ 2 ], ip );
|
||||
lsbshortldi( obuff[ 2 + 1 ], ip );
|
||||
|
||||
// sample2's directly into obuff
|
||||
lsbshortldi( obuff[ 0 ], ip );
|
||||
lsbshortldi( obuff[ 1 ], ip );
|
||||
|
||||
// already have 1st 2 samples from block-header
|
||||
short* op( obuff + 2 * 2 );
|
||||
short* top( obuff + n * 2 );
|
||||
{
|
||||
while( op < top )
|
||||
{
|
||||
unsigned char b( *ip++ );
|
||||
short* tmp( op );
|
||||
*op++ = AdpcmDecode( b >> 4, state[0], tmp[ -2 ], tmp[ -2 * 2 ] );
|
||||
tmp = op;
|
||||
*op++ = AdpcmDecode( b & 0x0f, state[1], tmp[ -2 ], tmp[ -2 * 2 ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline IMusicPatternDecoderInstance* CADPCMDecoder::CreateInstance()
|
||||
{
|
||||
return new CADPCMDecoderInstance(this);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
/*** INSTANCE ***/
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline CADPCMDecoderInstance::CADPCMDecoderInstance(CADPCMDecoder *pDecoder)
|
||||
: m_iFilePos(0), m_pFile(NULL),m_nPos(0), m_uiDataStartPos(0),m_uiNumSamples(0),m_sCoefs(7),m_psSamplePtr(NULL),
|
||||
m_bInitialized(false), m_bCopyFromLastFrame(false),m_uiCurrentBlockSize(scuiBlockSize),m_uiCurrentSamplesPerBlock(scuiSamplesPerBlock)
|
||||
{
|
||||
assert(pDecoder);
|
||||
assert(pDecoder->m_pPak);
|
||||
|
||||
m_pDecoder = pDecoder;
|
||||
//init wav stream
|
||||
if(!InitStreamWAV())
|
||||
{
|
||||
m_bInitialized = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
CADPCMDecoderInstance::~CADPCMDecoderInstance()
|
||||
{
|
||||
Close();//let the filehandle be released
|
||||
}
|
||||
|
||||
inline void CADPCMDecoderInstance::Close()
|
||||
{
|
||||
if (m_pFile)
|
||||
{
|
||||
m_pDecoder->CloseFileHandle(m_pFile);
|
||||
}
|
||||
m_bInitialized = false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline bool CADPCMDecoderInstance::Seek0(int nDelay)
|
||||
{
|
||||
m_nPos=-nDelay; //new sample pos
|
||||
m_bCopyFromLastFrame = false;
|
||||
if (!m_pFile || m_uiDataStartPos == 0)
|
||||
return false;
|
||||
m_pDecoder->m_pPak->FSeek(m_pFile,m_uiDataStartPos,SEEK_SET);
|
||||
m_iFilePos = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline const unsigned int CADPCMDecoderInstance::Samples()
|
||||
{
|
||||
return m_uiNumSamples;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline int CADPCMDecoderInstance::GetPos()
|
||||
{
|
||||
if (!m_pFile)
|
||||
return -1;
|
||||
return m_nPos;
|
||||
}
|
||||
|
||||
const bool CADPCMDecoderInstance::InitStreamWAV()
|
||||
{
|
||||
memset(m_aEncodedBlock,0,scuiBlockSize);
|
||||
SADPCMWaveHdr adpcmHeader; //adpcm secific header
|
||||
//get file handle
|
||||
if(!m_pFile)
|
||||
{
|
||||
m_pFile = m_pDecoder->GetNewFileHandle();
|
||||
if(!m_pFile)
|
||||
return false;
|
||||
}
|
||||
ICryPak& pPak = *m_pDecoder->m_pPak; //get reference to pak file
|
||||
//retrieve total size of file
|
||||
pPak.FRead(&adpcmHeader,1, sizeof(SADPCMWaveHdr),m_pFile);
|
||||
pPak.FRead(&m_sCoefs, 1, sizeof(short), m_pFile);
|
||||
if(adpcmHeader.FormatTag == WAVE_FORMAT_PCM)
|
||||
{
|
||||
#ifdef LOG_MUSICFILES
|
||||
m_pDecoder->m_pMusicSystem->LogMsg( "Uncompressed pcm data, use pcm decoder %s\n", m_pDecoder->FileName());
|
||||
#else
|
||||
TRACE("uncompressed pcm data, use pcm decoder %s\n", m_pDecoder->FileName());
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
if(adpcmHeader.FormatTag != WAVE_FORMAT_ADPCM || adpcmHeader.wChnls != 2)
|
||||
{
|
||||
#ifdef LOG_MUSICFILES
|
||||
m_pDecoder->m_pMusicSystem->LogMsg("No stereo adpcm file: %s\n", m_pDecoder->FileName());
|
||||
#else
|
||||
TRACE("no stereo adpcm file: %s\n", m_pDecoder->FileName());
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
//set block alignments
|
||||
m_uiCurrentBlockSize = adpcmHeader.wBlkAlign;
|
||||
m_uiCurrentSamplesPerBlock = adpcmHeader.SamplesPerBlock;
|
||||
if(m_sCoefs != scuiNumberOfCoefs || m_uiCurrentSamplesPerBlock > scuiSamplesPerBlock || m_uiCurrentBlockSize > scuiBlockSize)
|
||||
{
|
||||
#ifdef LOG_MUSICFILES
|
||||
m_pDecoder->m_pMusicSystem->LogMsg("Unsupported adpcm format %s\n", m_pDecoder->FileName());
|
||||
#else
|
||||
TRACE("unsupported adpcm format %s\n", m_pDecoder->FileName());
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
pPak.FRead(m_aCoefs, 1, m_sCoefs/*7*/ * 2/*stereo->2 channels*/ * sizeof(short), m_pFile);
|
||||
//now seek to start position (next to "data")
|
||||
unsigned int uiDataLeft = 0;
|
||||
for(;;)
|
||||
{
|
||||
char pcMagic[ 4 ];
|
||||
pPak.FRead( pcMagic, 1, sizeof( unsigned char ) * 4, m_pFile );
|
||||
|
||||
if(0 != pPak.FEof( m_pFile ))
|
||||
return false;
|
||||
pPak.FRead( &uiDataLeft, 1, sizeof( unsigned int ), m_pFile );
|
||||
if( 0 == strncmp( "data", pcMagic, 4 ) )
|
||||
break;
|
||||
pPak.FSeek( m_pFile, uiDataLeft, SEEK_CUR);
|
||||
}
|
||||
m_uiDataStartPos = m_pDecoder->m_pPak->FTell(m_pFile);//to make seek0 work properly, data start position
|
||||
//compute number of samples contained
|
||||
int m = (uiDataLeft % m_uiCurrentBlockSize);
|
||||
m_uiNumSamples = (uiDataLeft / m_uiCurrentBlockSize) * m_uiCurrentSamplesPerBlock;//usually block aligned and not necessary
|
||||
m -= scuiNumberOfCoefs * 2; // bytes beyond block-header
|
||||
m += 2; // nibbles / channels + 2 in header
|
||||
if(m > 0) //there are some samples contained in an unaligned block
|
||||
{
|
||||
if( m > (int)m_uiCurrentSamplesPerBlock )
|
||||
{
|
||||
m = (int)m_uiCurrentSamplesPerBlock;
|
||||
}
|
||||
m_uiNumSamples += m;
|
||||
}
|
||||
Seek0();
|
||||
//since the total sample count is not known by the decoder, tell him
|
||||
const bool cbIs44KHz = (adpcmHeader.dwSRate == 44100);
|
||||
if(!cbIs44KHz)
|
||||
m_uiNumSamples *= 2;
|
||||
m_pDecoder->SetFileInfo(m_uiNumSamples, cbIs44KHz);
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CADPCMDecoderInstance::GetPCMData(signed long *pDataOut, int nSamples, bool bLoop)
|
||||
{
|
||||
//prevent any asynchonisation in terms of file opening
|
||||
if (!m_pFile || !m_bInitialized)
|
||||
{
|
||||
//try it again
|
||||
if(m_pDecoder->IsOpen())
|
||||
{
|
||||
if(!InitStreamWAV())
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
int nOfs=0;
|
||||
if (m_nPos<0)
|
||||
{
|
||||
if (-m_nPos >= nSamples)
|
||||
{
|
||||
memset(pDataOut, 0, nSamples*m_pDecoder->m_pMusicSystem->GetBytesPerSample());
|
||||
m_nPos+=nSamples;
|
||||
return true;
|
||||
}else
|
||||
{
|
||||
nOfs=-m_nPos;
|
||||
m_nPos=0;
|
||||
Seek0();//set back to start
|
||||
nSamples-=nOfs;
|
||||
memset(pDataOut, 0, nOfs*m_pDecoder->m_pMusicSystem->GetBytesPerSample());
|
||||
}
|
||||
}
|
||||
int nSamplesToRead;
|
||||
for (;;)
|
||||
{
|
||||
if ((m_nPos+nSamples) > (int)m_uiNumSamples)
|
||||
{
|
||||
nSamplesToRead = m_uiNumSamples - m_nPos;
|
||||
}
|
||||
else
|
||||
nSamplesToRead=nSamples;
|
||||
if(m_pDecoder->Is44KHz())
|
||||
{
|
||||
if (!FillPCMBuffer(&(pDataOut[nOfs]), nSamplesToRead))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!FillPCMBuffer22KHz(&(pDataOut[nOfs]), nSamplesToRead))
|
||||
return false;
|
||||
}
|
||||
m_nPos+=nSamplesToRead;
|
||||
if (nSamplesToRead==nSamples)
|
||||
break;
|
||||
nOfs+=nSamplesToRead;
|
||||
if (!bLoop)
|
||||
{
|
||||
memset(&(pDataOut[nOfs]), 0, (nSamples-nSamplesToRead)*m_pDecoder->m_pMusicSystem->GetBytesPerSample());
|
||||
break;
|
||||
}
|
||||
nSamples-=nSamplesToRead;
|
||||
Seek0();
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
|
||||
// AdpcmReadBlock - Grab and decode complete block of samples
|
||||
inline unsigned short CADPCMDecoderInstance::AdpcmReadBlock(short* pDest)
|
||||
{
|
||||
//read block
|
||||
unsigned short bytesRead( (unsigned short) m_pDecoder->m_pPak->FRead( m_aEncodedBlock, 1, m_uiCurrentBlockSize, m_pFile ) );
|
||||
m_iFilePos += bytesRead; //internal file pos counter, counted from m_uiDataStartPos on
|
||||
unsigned int samplesThisBlock = m_uiCurrentSamplesPerBlock;
|
||||
if( bytesRead < m_uiCurrentBlockSize )
|
||||
{
|
||||
//this shouldnt be the case, but handle it just in case (most programs do block align)
|
||||
samplesThisBlock = 0;
|
||||
unsigned int m = bytesRead;
|
||||
//more data found than just coefs
|
||||
if( m >= (unsigned int) ( scuiNumberOfCoefs * 2 ) )
|
||||
{
|
||||
samplesThisBlock = m - scuiNumberOfCoefs * 2 + 2;// bytes beyond block-header
|
||||
}
|
||||
else
|
||||
return( 0 );
|
||||
}
|
||||
//now decode read stuff
|
||||
if(pDest == NULL)
|
||||
CADPCMDecoder::AdpcmBlockExpandI( m_sCoefs, m_aCoefs, m_aEncodedBlock, m_aDecodedBlock, samplesThisBlock );
|
||||
else
|
||||
CADPCMDecoder::AdpcmBlockExpandI( m_sCoefs, m_aCoefs, m_aEncodedBlock, pDest, samplesThisBlock );
|
||||
return( samplesThisBlock );
|
||||
}
|
||||
|
||||
const bool CADPCMDecoderInstance::FillPCMBuffer(signed long *pBuffer, int nSamples)
|
||||
{
|
||||
//since there get always complete blocks read, fill buffer with already compressed samples
|
||||
const unsigned int cuiModulo = m_nPos % m_uiCurrentSamplesPerBlock;
|
||||
if(cuiModulo != 0 && m_iFilePos > 0)//to not let break anything
|
||||
{ //we are not on a block boundary
|
||||
unsigned int uiLeft = min((unsigned int)nSamples, (m_uiCurrentSamplesPerBlock - cuiModulo));
|
||||
if(uiLeft != 0)//read as many sampels as left decompressed and not more than requested
|
||||
{
|
||||
//copy decompressed data
|
||||
signed long *pslDecompressed = reinterpret_cast<signed long*>(m_aDecodedBlock) + cuiModulo;
|
||||
for(unsigned int i=0; i<uiLeft;i++)
|
||||
{
|
||||
*pBuffer++ = *pslDecompressed++;
|
||||
}
|
||||
//set new number of remaining samples
|
||||
nSamples -= uiLeft;
|
||||
}
|
||||
}
|
||||
short *pCurrentDest = reinterpret_cast<short*>(pBuffer); //need a short buffer to decode each channel indivually (remember: 16 bit)
|
||||
if(nSamples > 0)
|
||||
{
|
||||
while(nSamples > 0)
|
||||
{
|
||||
//read as many blocks as necessary
|
||||
//write straight to output buffer if complete block has to read in
|
||||
if(nSamples >= (int)m_uiCurrentSamplesPerBlock)
|
||||
{
|
||||
bool bEndOfFile = (AdpcmReadBlock( pCurrentDest ) != m_uiCurrentSamplesPerBlock);
|
||||
if(bEndOfFile) //shouldnt happen
|
||||
return false;
|
||||
nSamples -= m_uiCurrentSamplesPerBlock;
|
||||
pCurrentDest += m_uiCurrentSamplesPerBlock * 2;//two channels decoded
|
||||
}
|
||||
else
|
||||
{
|
||||
//decompress to static buffer
|
||||
unsigned int uiReadSamples = AdpcmReadBlock();
|
||||
if(uiReadSamples != m_uiCurrentSamplesPerBlock)
|
||||
{
|
||||
//we are supposed to be on the end of the file, fill with 0's
|
||||
memset(m_aDecodedBlock + uiReadSamples * 2/*stereo*/, 0, m_uiCurrentSamplesPerBlock - uiReadSamples);
|
||||
}
|
||||
//read requested samples
|
||||
pBuffer = reinterpret_cast<signed long*>(pCurrentDest);
|
||||
signed long *pDecoded = reinterpret_cast<signed long*>(m_aDecodedBlock);
|
||||
//if for bad reason not enough samples have been read, it will get automatically filled with 0's
|
||||
for(int i=0; i<nSamples;i++)
|
||||
{
|
||||
*pBuffer++ = *pDecoded++;
|
||||
}
|
||||
nSamples = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const bool CADPCMDecoderInstance::FillPCMBuffer22KHz(signed long *pBuffer, int nSamples)
|
||||
{
|
||||
unsigned uStartPos = (m_nPos/2/*22KHz*/);
|
||||
//first check for copying some data from last frame (if not at starting position)
|
||||
if(m_bCopyFromLastFrame && m_iFilePos > 0)/*22KHz*/
|
||||
{
|
||||
*pBuffer++ = m_lLastSample;//contains sample to start with from last encoding
|
||||
nSamples -= 1;
|
||||
m_bCopyFromLastFrame = false;
|
||||
uStartPos++;
|
||||
}
|
||||
//since there get always complete blocks read, fill buffer with already compressed samples
|
||||
const unsigned int cuiModulo = uStartPos % m_uiCurrentSamplesPerBlock;
|
||||
unsigned int uiLeft = 0;
|
||||
if(cuiModulo != 0 && m_iFilePos > 0)//to not let break anything
|
||||
{ //we are not on a block boundary
|
||||
uiLeft = min((unsigned int)nSamples/2, (m_uiCurrentSamplesPerBlock - cuiModulo));/*22KHz*/
|
||||
signed long *pslDecompressed = reinterpret_cast<signed long*>(m_aDecodedBlock) + cuiModulo;
|
||||
if(uiLeft != 0)//read as many sampels as left decompressed and not more than requested
|
||||
{
|
||||
//copy decompressed data
|
||||
for(unsigned int i=0; i<uiLeft;i++)
|
||||
{
|
||||
*pBuffer++ = *pslDecompressed;/*22KHz*/
|
||||
*pBuffer++ = *pslDecompressed++;
|
||||
}
|
||||
//set new number of remaining samples
|
||||
nSamples -= 2*uiLeft;
|
||||
}
|
||||
if(nSamples == 1)/*22KHz*/
|
||||
{
|
||||
//there is one sample left
|
||||
m_bCopyFromLastFrame = true;
|
||||
*pBuffer++ = m_lLastSample = *pslDecompressed; //remember last sample, has to start with in next request
|
||||
nSamples = 0;
|
||||
}
|
||||
}
|
||||
short *pCurrentDest = reinterpret_cast<short*>(pBuffer); //need a short buffer to decode each channel indivually (remember: 16 bit)
|
||||
if(nSamples > 0)
|
||||
{
|
||||
while(nSamples > 0)
|
||||
{
|
||||
//read as many blocks as necessary
|
||||
//write straight to output buffer if complete block has to read in
|
||||
if(nSamples >= (int)m_uiCurrentSamplesPerBlock*2)
|
||||
{
|
||||
bool bEndOfFile = (AdpcmReadBlock() != m_uiCurrentSamplesPerBlock);
|
||||
if(bEndOfFile) //shouldnt happen
|
||||
{
|
||||
memset(pBuffer, 0, nSamples*4);//fill with 0's
|
||||
return false;
|
||||
}
|
||||
pBuffer = reinterpret_cast<signed long*>(pCurrentDest);
|
||||
signed long *pDecoded = reinterpret_cast<signed long*>(m_aDecodedBlock);
|
||||
//if for bad reason not enough samples have been read, it will get automatically filled with 0's
|
||||
for(unsigned int i=0; i<m_uiCurrentSamplesPerBlock;i++)
|
||||
{
|
||||
*pBuffer++ = *pDecoded;
|
||||
*pBuffer++ = *pDecoded++;
|
||||
}
|
||||
nSamples -= 2*m_uiCurrentSamplesPerBlock; /*22KHz*/
|
||||
pCurrentDest = reinterpret_cast<short*>(pBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
//decompress to static buffer
|
||||
unsigned int uiReadSamples = AdpcmReadBlock();
|
||||
if(uiReadSamples != m_uiCurrentSamplesPerBlock)
|
||||
{
|
||||
//we are supposed to be on the end of the file, fill with 0's
|
||||
memset(m_aDecodedBlock + uiReadSamples * 2/*stereo*/, 0, m_uiCurrentSamplesPerBlock - uiReadSamples);
|
||||
}
|
||||
//read requested samples
|
||||
pBuffer = reinterpret_cast<signed long*>(pCurrentDest);
|
||||
signed long *pDecoded = reinterpret_cast<signed long*>(m_aDecodedBlock);
|
||||
//if for some bad reason not enough samples have been read, it will get automatically filled with 0's
|
||||
for(int i=0; i<nSamples/2;i++)
|
||||
{
|
||||
*pBuffer++ = *pDecoded;
|
||||
*pBuffer++ = *pDecoded++;
|
||||
}
|
||||
m_bCopyFromLastFrame = false; //just to make sure
|
||||
if(nSamples & 0x1)
|
||||
{
|
||||
m_bCopyFromLastFrame = true;
|
||||
//read one sample more
|
||||
*pBuffer++ = m_lLastSample = *pDecoded; //remember last sample, has to start with in next request
|
||||
}
|
||||
nSamples = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
141
CrySoundSystem/ADPCMDecoder.h
Normal file
141
CrySoundSystem/ADPCMDecoder.h
Normal file
@@ -0,0 +1,141 @@
|
||||
#pragma once
|
||||
|
||||
#include "PatternDecoder.h"
|
||||
#include <string>
|
||||
|
||||
struct IMusicSystem;
|
||||
class CADPCMDecoderInstance;
|
||||
struct ICryPak;
|
||||
|
||||
//specific header struct for ADPCM, data stored in a slidely different manner than usual wav
|
||||
typedef struct SADPCMWaveHdr
|
||||
{
|
||||
char RIFF[4]; // "RIFF" tag, identifies it as WAV
|
||||
unsigned long dwSize; // Size of data to follow (filesize-8)
|
||||
char WAVE[4]; // "WAVE" tag
|
||||
char fmt_[4]; // "fmt " tag
|
||||
unsigned long dw16; // 16
|
||||
unsigned short FormatTag; // should be WAVE_FORMAT_ADPCM=2
|
||||
unsigned short wChnls; // Number of Channels (1 for mono, 2 for stereo), should be always 2
|
||||
unsigned long dwSRate; // Sample Rate
|
||||
unsigned long BytesPerSec; // Bytes per second
|
||||
unsigned short wBlkAlign; // Block align, usually 2048
|
||||
unsigned short BitsPerSample; // Bits Per Sample, usually 4
|
||||
unsigned short wExtSize; // not important
|
||||
unsigned short SamplesPerBlock; // samples per block, usually 2036
|
||||
//followed by number of coeficients and coeficients themselves
|
||||
} SADPCMWaveHdr;
|
||||
|
||||
struct MsState
|
||||
{
|
||||
int step;
|
||||
short sCoef0;
|
||||
short sCoef1;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CADPCMDecoder : public IMusicPatternDecoder
|
||||
{
|
||||
public:
|
||||
static const unsigned int scuiSizeOfWavHeader = sizeof(SWaveHdr); //need to hardcode here since SADPCMWaveHdr is not complined with usual header
|
||||
|
||||
CADPCMDecoder(IMusicSystem *pMusicSystem);
|
||||
void Release() { delete this; }
|
||||
//! Open a music-pattern-file, does actually just store filename
|
||||
bool Open(const char *pszFilename);
|
||||
//! Close a music-pattern-file.
|
||||
bool Close();
|
||||
//! Retrieve file-info
|
||||
bool GetFileInfo(SMusicPatternFileInfo &FileInfo);
|
||||
//! Retrieve mem-info
|
||||
void GetMemoryUsage(class ICrySizer* pSizer);
|
||||
//! Create instance.
|
||||
IMusicPatternDecoderInstance* CreateInstance();
|
||||
//! returns new file handle
|
||||
FILE* GetNewFileHandle();
|
||||
//! returns new file handle
|
||||
void CloseFileHandle(FILE*& pFile);
|
||||
//! retreieves file name
|
||||
const char* FileName() const;
|
||||
//! decode function for one block
|
||||
static void AdpcmBlockExpandI( int nCoef, const short* iCoef, const unsigned char* ibuff, short* obuff, int n );
|
||||
const bool IsOpen()const;
|
||||
//! retrieves frequency encoding
|
||||
const bool Is44KHz() const {return m_b44KHz;}
|
||||
|
||||
protected:
|
||||
bool m_b44KHz; //keeps track of encoded frequency
|
||||
|
||||
//! decode function for one sample, called exclusively by AdpcmBlockExpandI
|
||||
static int CADPCMDecoder::AdpcmDecode( int c, MsState& rState, int sample1, int sample2 );
|
||||
void SetFileInfo(const unsigned int cuiSampleCount, const bool cbIs44KHz = true);
|
||||
|
||||
virtual ~CADPCMDecoder();
|
||||
|
||||
IMusicSystem *m_pMusicSystem;
|
||||
ICryPak *m_pPak;
|
||||
SMusicPatternFileInfo m_FileInfo;
|
||||
string m_szFilename;
|
||||
bool m_bOpen; //keeps track for an open command
|
||||
|
||||
friend class CADPCMDecoderInstance;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CADPCMDecoderInstance : public IMusicPatternDecoderInstance
|
||||
{
|
||||
public:
|
||||
//hardcoded constants, can be changed when using a different format
|
||||
static const unsigned int scuiBlockSize = 2048; //constant value in 44 KHz Microsoft format, half the size for 22KHz
|
||||
static const unsigned int scuiSamplesPerBlock = 2036; //constant value in 44 KHz Microsoft format, half the size for 22KHz
|
||||
static const unsigned int scuiNumberOfCoefs = 7; //constant number of coefs
|
||||
|
||||
CADPCMDecoderInstance(CADPCMDecoder *pDecoder); //initializes as well
|
||||
void Release() { Close(); delete this; }
|
||||
//! Seek to beginning of pattern (if nDelay is set it will wait nDelay-samples before starting playback).
|
||||
bool Seek0(int nDelay=0);
|
||||
//! Retrieve the current position in the file (in samples)
|
||||
int GetPos();
|
||||
//! Decode and retrieve pcm-data (stereo/16bit).
|
||||
bool GetPCMData(signed long *pDataOut, int nSamples, bool bLoop=true);
|
||||
//! closes all
|
||||
void Close();
|
||||
//! retrieves number of total contained samples
|
||||
const unsigned int Samples();
|
||||
|
||||
protected:
|
||||
CADPCMDecoder *m_pDecoder; // one decoder per file
|
||||
int m_nPos; // current position in samples
|
||||
FILE *m_pFile; // own File handle for now
|
||||
int m_iFilePos; // current file pos corresponding to right file seek pos (counted from m_uiDataStartPos)
|
||||
bool m_bInitialized; // functionality not available if false
|
||||
bool m_bCopyFromLastFrame; // indicates some copying from last frame (due to odd sample count request)
|
||||
signed long m_lLastSample; // sample to reuse for next frame
|
||||
|
||||
unsigned int m_uiCurrentBlockSize; // block size in file, always less than static allocated buffer
|
||||
unsigned int m_uiCurrentSamplesPerBlock;// sampels per block in file(usually m_uiCurrentBlockSize-12), always less than static allocated buffer
|
||||
|
||||
//ADPCM specific stuff
|
||||
unsigned char m_aEncodedBlock[scuiBlockSize]; //static allocated encoded block
|
||||
short m_aDecodedBlock[scuiSamplesPerBlock*2]; //static allocated decoded block, 2 per channel (1:4)
|
||||
short m_aCoefs[scuiNumberOfCoefs * 2/*2 per channel, stereo assumed*/]; //static allocated coeficients
|
||||
|
||||
unsigned int m_uiDataStartPos; // usually at position 90, set by InitStreamWav
|
||||
unsigned int m_uiNumSamples; // total sample count
|
||||
unsigned short m_sCoefs; // ADPCM: number of coef sets
|
||||
short* m_psSamplePtr; // Pointer to current sample
|
||||
int m_iState[ 16 ]; // step-size info for *ADPCM writes
|
||||
|
||||
protected:
|
||||
//! fills a dest buffer with uncompressed data
|
||||
const bool FillPCMBuffer(signed long *pBuffer, int nSamples);
|
||||
//! fills a dest buffer from 22KHz compressed data
|
||||
const bool FillPCMBuffer22KHz(signed long *pBuffer, int nSamples);
|
||||
|
||||
const bool InitStreamWAV(); // for now has every instance its own file handle
|
||||
unsigned short AdpcmReadBlock(short* pDest = NULL); // decoded one block, if dest not specified, default static buffer is chosen
|
||||
|
||||
virtual ~CADPCMDecoderInstance(); // to hit right destructor
|
||||
};
|
||||
|
||||
90
CrySoundSystem/CrySoundSystem.cpp
Normal file
90
CrySoundSystem/CrySoundSystem.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
// CrySoundSystem.cpp : Defines the entry point for the DLL application.
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#ifdef USING_CRY_MEMORY_MANAGER
|
||||
#ifndef _XBOX
|
||||
_ACCESS_POOL;
|
||||
#endif //_XBOX
|
||||
#else //USING_CRY_MEMORY_MANAGER
|
||||
//! Structre filled by call to CryModuleGetMemoryInfo()
|
||||
struct CryModuleMemoryInfo
|
||||
{
|
||||
//! Total Ammount of memory allocated.
|
||||
int allocated;
|
||||
//! Total Ammount of memory freed.
|
||||
int freed;
|
||||
//! Total number of memory allocations.
|
||||
int num_allocations;
|
||||
};
|
||||
extern "C" __declspec(dllexport) void CryModuleGetMemoryInfo( CryModuleMemoryInfo *pMemInfo )
|
||||
{
|
||||
#if (defined CS_VERSION_372) || (defined CS_VERSION_361)
|
||||
unsigned int nCurrentAlloced;
|
||||
unsigned int nMaxAlloced;
|
||||
#else
|
||||
size_t nCurrentAlloced;
|
||||
size_t nMaxAlloced;
|
||||
#endif
|
||||
CS_GetMemoryStats(&nCurrentAlloced, &nMaxAlloced);
|
||||
pMemInfo->allocated = nMaxAlloced;
|
||||
pMemInfo->freed = 0;
|
||||
pMemInfo->num_allocations = 0;
|
||||
};
|
||||
#endif //USING_CRY_MEMORY_MANAGER
|
||||
|
||||
#include "DummySound.h"
|
||||
#include <Cry_Camera.h>
|
||||
#include "SoundSystem.h"
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// dll interface
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Pointer to Global ISystem.
|
||||
static ISystem* gISystem = 0;
|
||||
ISystem* GetISystem()
|
||||
{
|
||||
return gISystem;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////
|
||||
extern "C" ISoundSystem* CreateSoundSystem(struct ISystem* pISystem, void* pInitData)
|
||||
{
|
||||
gISystem = pISystem;
|
||||
//create a brand new sound system
|
||||
#ifndef _XBOX
|
||||
CSoundSystem* pSoundSystem = new CSoundSystem(pISystem, (HWND)pInitData);
|
||||
|
||||
if (!pSoundSystem || !pSoundSystem->IsOK())
|
||||
{
|
||||
//if the sound system cannot be created or initialized,
|
||||
//create the dummy sound system (NULL sound system, same as for
|
||||
//dedicated server)
|
||||
|
||||
if (pSoundSystem)
|
||||
pSoundSystem->Release();
|
||||
#endif
|
||||
|
||||
CDummySoundSystem *pDummySound=new CDummySoundSystem(pISystem, (HWND)pInitData);
|
||||
return pDummySound;
|
||||
|
||||
#ifndef _XBOX
|
||||
}
|
||||
|
||||
return pSoundSystem;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef __MWERKS__
|
||||
#ifndef _XBOX
|
||||
///////////////////////////////////////////////
|
||||
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
#endif //_XBOX
|
||||
#endif
|
||||
|
||||
#include <CrtDebugStats.h>
|
||||
605
CrySoundSystem/CrySoundSystem.vcproj
Normal file
605
CrySoundSystem/CrySoundSystem.vcproj
Normal file
@@ -0,0 +1,605 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="CrySoundSystem"
|
||||
ProjectGUID="{FD988D8E-914A-4463-A458-4568120E258C}"
|
||||
SccProjectName="Perforce Project"
|
||||
SccAuxPath=""
|
||||
SccLocalPath="."
|
||||
SccProvider="MSSCCI:Perforce SCM">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="D:\Games\FC\Bin32"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="2"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
FavorSizeOrSpeed="2"
|
||||
OmitFramePointers="TRUE"
|
||||
EnableFiberSafeOptimizations="FALSE"
|
||||
OptimizeForProcessor="2"
|
||||
AdditionalIncludeDirectories="..\CryCommon;OggVorbisInclude\"
|
||||
PreprocessorDefinitions="_RELEASE;WIN32;NDEBUG;_WINDOWS;_USRDLL;CRYSOUNDSYSTEM_EXPORTS"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="2"
|
||||
BufferSecurityCheck="FALSE"
|
||||
EnableFunctionLevelLinking="FALSE"
|
||||
EnableEnhancedInstructionSet="0"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderFile=".\Release/CrySoundSystem.pch"
|
||||
AssemblerListingLocation=".\Release/"
|
||||
ObjectFile=".\Release/"
|
||||
ProgramDataBaseFileName=".\Release/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/MACHINE:I386"
|
||||
AdditionalDependencies="ogg_static.lib vorbis_static.lib vorbisfile_static.lib"
|
||||
OutputFile=".\Release/CrySoundSystem.dll"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
ProgramDatabaseFile=".\Release/CrySoundSystem.pdb"
|
||||
ImportLibrary="$(IntDir)/$(TargetName).lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
MkTypLibCompatible="TRUE"
|
||||
SuppressStartupBanner="TRUE"
|
||||
TargetEnvironment="1"
|
||||
TypeLibraryName=".\Release/CrySoundSystem.tlb"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Profile|Win32"
|
||||
OutputDirectory="D:\Games\FC\Bin32"
|
||||
IntermediateDirectory="Profile"
|
||||
ConfigurationType="2"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
FavorSizeOrSpeed="2"
|
||||
OmitFramePointers="TRUE"
|
||||
EnableFiberSafeOptimizations="FALSE"
|
||||
OptimizeForProcessor="2"
|
||||
AdditionalIncludeDirectories="..\CryCommon;OggVorbisInclude\"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;CRYSOUNDSYSTEM_EXPORTS"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="2"
|
||||
BufferSecurityCheck="FALSE"
|
||||
EnableFunctionLevelLinking="FALSE"
|
||||
EnableEnhancedInstructionSet="0"
|
||||
UsePrecompiledHeader="3"
|
||||
PrecompiledHeaderFile=".\Profile/CrySoundSystem.pch"
|
||||
AssemblerListingLocation=".\Profile/"
|
||||
ObjectFile=".\Profile/"
|
||||
ProgramDataBaseFileName=".\Profile/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/MACHINE:I386"
|
||||
AdditionalDependencies="ogg_static.lib vorbis_static.lib vorbisfile_static.lib"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
GenerateDebugInformation="TRUE"
|
||||
BaseAddress="0x36000000"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
MkTypLibCompatible="TRUE"
|
||||
SuppressStartupBanner="TRUE"
|
||||
TargetEnvironment="1"
|
||||
TypeLibraryName=".\Profile/CrySoundSystem.tlb"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="D:\Games\FC\Bin32"
|
||||
IntermediateDirectory=".\Debug"
|
||||
ConfigurationType="2"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
OptimizeForProcessor="0"
|
||||
AdditionalIncludeDirectories="..\CryCommon;OggVorbisInclude\"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;CRYSOUNDSYSTEM_EXPORTS"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
BufferSecurityCheck="TRUE"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderFile=".\Debug/CrySoundSystem.pch"
|
||||
AssemblerListingLocation=".\Debug/"
|
||||
ObjectFile=".\Debug/"
|
||||
ProgramDataBaseFileName=".\Debug/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/MACHINE:I386"
|
||||
AdditionalDependencies="ogg_static.lib vorbis_static.lib vorbisfile_static.lib"
|
||||
LinkIncremental="2"
|
||||
SuppressStartupBanner="TRUE"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ImportLibrary="$(IntDir)/$(TargetName).lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
MkTypLibCompatible="TRUE"
|
||||
SuppressStartupBanner="TRUE"
|
||||
TargetEnvironment="1"
|
||||
TypeLibraryName=".\Debug/CrySoundSystem.tlb"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug64|Win32"
|
||||
OutputDirectory="D:\Games\FC\Bin32"
|
||||
IntermediateDirectory="Debug64"
|
||||
ConfigurationType="2"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\CryCommon;OggVorbisInclude\"
|
||||
PreprocessorDefinitions="WIN64;WIN32;_DEBUG;_WINDOWS;_USRDLL;CRYSOUNDSYSTEM_EXPORTS"
|
||||
BasicRuntimeChecks="0"
|
||||
RuntimeLibrary="1"
|
||||
BufferSecurityCheck="FALSE"
|
||||
UsePrecompiledHeader="3"
|
||||
PrecompiledHeaderFile="$(IntDir)/$(ProjectName).pch"
|
||||
AssemblerListingLocation="$(IntDir)/"
|
||||
ObjectFile="$(IntDir)/"
|
||||
ProgramDataBaseFileName="$(IntDir)/$(ProjectName).pdb"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/MACHINE:AMD64"
|
||||
AdditionalDependencies="ogg_static_d64.lib vorbis_static_d64.lib vorbisfile_static_d64.lib crysound64d.lib ../CryCommon/fSinCos64.lib"
|
||||
OutputFile="$(OutDir)/$(ProjectName).dll"
|
||||
LinkIncremental="2"
|
||||
SuppressStartupBanner="TRUE"
|
||||
IgnoreDefaultLibraryNames=""
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"
|
||||
SubSystem="2"
|
||||
LargeAddressAware="2"
|
||||
ImportLibrary="$(OutDir)/$(ProjectName).lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
MkTypLibCompatible="TRUE"
|
||||
SuppressStartupBanner="TRUE"
|
||||
TargetEnvironment="1"
|
||||
TypeLibraryName=".\Debug/CrySoundSystem.tlb"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release64|Win32"
|
||||
OutputDirectory="D:\Games\FC\Bin32"
|
||||
IntermediateDirectory="Release64"
|
||||
ConfigurationType="2"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
AdditionalIncludeDirectories="..\CryCommon;OggVorbisInclude\"
|
||||
PreprocessorDefinitions="_RELEASE;NDEBUG;WIN64;WIN32;_AMD64_;_WINDOWS;_USRDLL;CRYSOUNDSYSTEM_EXPORTS"
|
||||
BasicRuntimeChecks="0"
|
||||
RuntimeLibrary="2"
|
||||
BufferSecurityCheck="FALSE"
|
||||
UsePrecompiledHeader="3"
|
||||
PrecompiledHeaderFile="$(IntDir)/$(ProjectName).pch"
|
||||
AssemblerListingLocation="$(IntDir)/"
|
||||
ObjectFile="$(IntDir)/"
|
||||
ProgramDataBaseFileName="$(IntDir)/$(ProjectName).pdb"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/MACHINE:AMD64"
|
||||
AdditionalDependencies="ogg_static_r64.lib vorbis_static_r64.lib vorbisfile_static_r64.lib crysound64.lib ../CryCommon/fSinCos64.lib"
|
||||
OutputFile="$(OutDir)/$(ProjectName).dll"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
IgnoreDefaultLibraryNames=""
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"
|
||||
LargeAddressAware="2"
|
||||
ImportLibrary="$(OutDir)/$(ProjectName).lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
MkTypLibCompatible="TRUE"
|
||||
SuppressStartupBanner="TRUE"
|
||||
TargetEnvironment="1"
|
||||
TypeLibraryName=".\Debug/CrySoundSystem.tlb"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
|
||||
<File
|
||||
RelativePath=".\CrySoundSystem.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="2"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Sound.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="2"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="SoundBuffer.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="2"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\SoundSystem.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="2"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="SoundSystemCommon.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="2"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\StdAfx.cpp">
|
||||
<FileConfiguration
|
||||
Name="Profile|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug64|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release64|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl">
|
||||
<File
|
||||
RelativePath=".\DummySound.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="MusicLoadSink.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Sound.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="SoundBuffer.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\SoundSystem.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="SoundSystemCommon.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\StdAfx.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="DynamicMusic"
|
||||
Filter="">
|
||||
<Filter
|
||||
Name="Pattern"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="MusicPattern.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="MusicPattern.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="MusicPatternInstance.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="MusicPatternInstance.h">
|
||||
</File>
|
||||
<Filter
|
||||
Name="Decoder"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="PatternDecoder.h">
|
||||
</File>
|
||||
<Filter
|
||||
Name="WAV"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="PCMDecoder.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="PCMDecoder.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="OGG"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="OGGDecoder.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="OGGDecoder.h">
|
||||
</File>
|
||||
<Filter
|
||||
Name="OggVorbisInclude"
|
||||
Filter="">
|
||||
<Filter
|
||||
Name="Ogg"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="OggVorbisInclude\ogg\ogg.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="OggVorbisInclude\ogg\os_types.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Vorbis"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="OggVorbisInclude\vorbis\codec.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="OggVorbisInclude\vorbis\vorbisenc.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="OggVorbisInclude\vorbis\vorbisfile.h">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="ADPCM"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\ADPCMDecoder.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ADPCMDecoder.h">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="System"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="MusicSystem.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="MusicSystem.h">
|
||||
</File>
|
||||
<Filter
|
||||
Name="Dummy"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="DummyMusic.h">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="RandGen"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="RandGen.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="RandGen.h">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath="crysound.lib">
|
||||
<FileConfiguration
|
||||
Name="Debug64|Win32"
|
||||
ExcludedFromBuild="TRUE">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release64|Win32"
|
||||
ExcludedFromBuild="TRUE">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
10
CrySoundSystem/CrySoundSystem.vcproj.vspscc
Normal file
10
CrySoundSystem/CrySoundSystem.vcproj.vspscc
Normal file
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"FILE_VERSION" = "9237"
|
||||
"ENLISTMENT_CHOICE" = "NEVER"
|
||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
||||
"ORIGINAL_PROJECT_FILE_PATH" = "file:F:\\Crytek\\CrySoundSystem\\CrySoundSystem.vcproj"
|
||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT"
|
||||
}
|
||||
227
CrySoundSystem/CrySoundSystem_XBox.vcproj
Normal file
227
CrySoundSystem/CrySoundSystem_XBox.vcproj
Normal file
@@ -0,0 +1,227 @@
|
||||
<?xml version="1.0" encoding = "windows-1251"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.00"
|
||||
Name="CrySoundSystem_XBox"
|
||||
SccProjectName=""$/Game01/CrySoundSystem", VQEBAAAA"
|
||||
SccAuxPath=""
|
||||
SccLocalPath="."
|
||||
SccProvider="MSSCCI:Microsoft Visual SourceSafe">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Xbox"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Release|Xbox"
|
||||
OutputDirectory="Release_XBox"
|
||||
IntermediateDirectory="Release_XBox"
|
||||
ConfigurationType="4"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="TRUE"
|
||||
AdditionalIncludeDirectories="..\CrySoundSystem\OggVorbisInclude;..\CryCommon"
|
||||
PreprocessorDefinitions="_RELEASE;NDEBUG;_XBOX;_LIB"
|
||||
StringPooling="FALSE"
|
||||
RuntimeLibrary="4"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderFile="$(OutDir)/CrySoundSystem.pch"
|
||||
AssemblerListingLocation="$(OutDir)/"
|
||||
ObjectFile="$(OutDir)/"
|
||||
ProgramDataBaseFileName="$(OutDir)/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="2"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/CrySoundSystem.lib"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Profile|Xbox"
|
||||
OutputDirectory="Profile"
|
||||
IntermediateDirectory="Profile"
|
||||
ConfigurationType="4"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="TRUE"
|
||||
AdditionalIncludeDirectories="..\CrySoundSystem\OggVorbisInclude;..\CryCommon"
|
||||
PreprocessorDefinitions="NDEBUG;_XBOX;_LIB"
|
||||
StringPooling="TRUE"
|
||||
BufferSecurityCheck="FALSE"
|
||||
UsePrecompiledHeader="3"
|
||||
PrecompiledHeaderFile=".\Profile/CrySoundSystem.pch"
|
||||
AssemblerListingLocation=".\Profile/"
|
||||
ObjectFile=".\Profile/"
|
||||
ProgramDataBaseFileName=".\Profile/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/CrySoundSystem.lib"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|Xbox"
|
||||
OutputDirectory="Debug_XBox"
|
||||
IntermediateDirectory="Debug_XBox"
|
||||
ConfigurationType="4"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\CrySoundSystem\OggVorbisInclude;..\CryCommon"
|
||||
PreprocessorDefinitions="_DEBUG;_XBOX;_LIB"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="5"
|
||||
BufferSecurityCheck="TRUE"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderFile=".\Debug_XBox/CrySoundSystem.pch"
|
||||
AssemblerListingLocation=".\Debug_XBox/"
|
||||
ObjectFile=".\Debug_XBox/"
|
||||
ProgramDataBaseFileName=".\Debug_XBox/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/CrySoundSystem.lib"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
|
||||
<File
|
||||
RelativePath=".\CrySoundSystem.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Sound.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\SoundSystem.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="SoundSystemCommon.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="SoundSystemCommon.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\StdAfx.cpp">
|
||||
<FileConfiguration
|
||||
Name="Profile|Xbox">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl">
|
||||
<File
|
||||
RelativePath=".\DummySound.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Sound.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\SoundSystem.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\StdAfx.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="DynamicMusic"
|
||||
Filter="">
|
||||
<Filter
|
||||
Name="Pattern"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="MusicPattern.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="MusicPattern.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="MusicPatternInstance.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="MusicPatternInstance.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="System"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="MusicSystem.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="MusicSystem.h">
|
||||
</File>
|
||||
<Filter
|
||||
Name="Dummy"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="DummyMusic.h">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath="crysound.lib">
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
10
CrySoundSystem/CrySoundSystem_XBox.vcproj.vspscc
Normal file
10
CrySoundSystem/CrySoundSystem_XBox.vcproj.vspscc
Normal file
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"FILE_VERSION" = "9237"
|
||||
"ENLISTMENT_CHOICE" = "NEVER"
|
||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
||||
"ORIGINAL_PROJECT_FILE_PATH" = "file:F:\\Crytek\\CrySoundSystem\\CrySoundSystem_XBox.vcproj"
|
||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT"
|
||||
}
|
||||
46
CrySoundSystem/DummyMusic.h
Normal file
46
CrySoundSystem/DummyMusic.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
#include <isound.h>
|
||||
|
||||
class CDummyMusicSystem : public IMusicSystem
|
||||
{
|
||||
protected:
|
||||
ISystem *m_pSystem;
|
||||
public:
|
||||
CDummyMusicSystem(ISystem *pSystem) { m_pSystem=pSystem; }
|
||||
virtual ~CDummyMusicSystem() {}
|
||||
void Release() { delete this; }
|
||||
ISystem* GetSystem() { return m_pSystem; }
|
||||
int GetBytesPerSample() { return 4; }
|
||||
IMusicSystemSink* SetSink(IMusicSystemSink *pSink) { return NULL; }
|
||||
bool SetData(struct SMusicData *pMusicData,bool bNoRelease=false) {return true;};
|
||||
void Unload() {}
|
||||
void Pause(bool bPause) {}
|
||||
void EnableEventProcessing(bool bEnable) {}
|
||||
bool ResetThemeOverride() { return true; }
|
||||
bool SetTheme(const char *pszTheme, bool bOverride=false) { return true; }
|
||||
const char* GetTheme() { return ""; }
|
||||
bool SetMood(const char *pszMood) { return true; }
|
||||
bool SetDefaultMood(const char *pszMood) { return true; }
|
||||
const char* GetMood() { return ""; }
|
||||
IStringItVec* GetThemes() { return NULL; }
|
||||
IStringItVec* GetMoods(const char *pszTheme) { return NULL; }
|
||||
bool AddMusicMoodEvent(const char *pszMood, float fTimeout) { return true; }
|
||||
void Update() {}
|
||||
SMusicSystemStatus* GetStatus() { return NULL; }
|
||||
void GetMemoryUsage(class ICrySizer* pSizer) {}
|
||||
bool LoadMusicDataFromLUA(IScriptSystem* pScriptSystem, const char *pszFilename){return true;}
|
||||
bool StreamOGG() {return true;}
|
||||
void LogMsg( const char *pszFormat, ... ) {}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Editing support.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void RenamePattern( const char *sOldName,const char *sNewName ) {};
|
||||
virtual void UpdateTheme( SMusicTheme *pTheme ) {};
|
||||
virtual void UpdateMood( SMusicMood *pMood ) {};
|
||||
virtual void UpdatePattern( SPatternDef *pPattern ) {};
|
||||
virtual void PlayPattern( const char *sPattern,bool bStopPrevious ) {};
|
||||
virtual void DeletePattern( const char *sPattern ) {};
|
||||
virtual void Silence() {};
|
||||
virtual bool LoadFromXML( const char *sFilename,bool bAddData ) { return true; };
|
||||
};
|
||||
183
CrySoundSystem/DummySound.h
Normal file
183
CrySoundSystem/DummySound.h
Normal file
@@ -0,0 +1,183 @@
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CrySound Source Code
|
||||
//
|
||||
// File: DummySound.h
|
||||
// Description: DummySound interface implementation.
|
||||
//
|
||||
// History:
|
||||
// -June 06,2001:Implemented by Marco Corbetta
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _DUMMY_SOUND_H_
|
||||
#define _DUMMY_SOUND_H_
|
||||
|
||||
#include "SoundSystemCommon.h"
|
||||
#include "DummyMusic.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
class CDummySound : public ISound
|
||||
{
|
||||
public:
|
||||
CDummySound()
|
||||
{
|
||||
m_refCount = 0;
|
||||
}
|
||||
|
||||
~CDummySound(){}
|
||||
|
||||
//// ISound //////////////////////////////////////////////////////
|
||||
bool IsPlaying(){ return false; }
|
||||
bool IsPlayingVirtual(){ return false; }
|
||||
bool IsLoaded() { return true; };
|
||||
bool IsLoading() { return false; };
|
||||
void Play(float fVolumeScale=1.0f, bool bForceActiveState=true, bool bSetRatio=true){}
|
||||
void PlayFadeUnderwater(float fVolumeScale=1.0f, bool bForceActiveState=true, bool bSetRatio=true) {};
|
||||
void Stop(){}
|
||||
void SetName(const char *szName){}
|
||||
const char *GetName(){return "dummy sound";}
|
||||
const int GetId(){return 0; }
|
||||
void SetLoopMode(bool bLoop){}
|
||||
unsigned int GetCurrentSamplePos(){return 0;}
|
||||
void SetPitching(float fPitching){}
|
||||
void SetBaseFrequency(int nFreq){}
|
||||
int GetBaseFrequency(int nFreq){return 44100;}
|
||||
void SetFrequency(int nFreq){}
|
||||
void SetMinMaxDistance(float fMinDist, float fMaxDist){}
|
||||
void SetAttrib(int nVolume, int nPan=127, int nFreq=1000, bool bSetRatio=true){}
|
||||
void SetAttrib(const Vec3d &pos, const Vec3d &speed){}
|
||||
void SetRatio(float fRatio){}
|
||||
void SetPosition(const Vec3d &pos){}
|
||||
const bool GetPosition(Vec3d &vPos){return (false);}
|
||||
void SetSpeed(const Vec3d &speed){}
|
||||
const Vec3d& GetSpeed(){return m_vDummy;}
|
||||
void SetLooping(bool bLooping) {}
|
||||
void AddToScaleGroup(int nGroup) {}
|
||||
void RemoveFromScaleGroup(int nGroup) {}
|
||||
void SetScaleGroup(unsigned int nGroupBits) {}
|
||||
int GetFrequency() { return (0);}
|
||||
void SetPitch(int nValue) {}
|
||||
void SetPan(int nPan) {}
|
||||
void SetMaxSoundDistance(float fMaxSoundDistance) {}
|
||||
void SetMinMaxDistance(float,float,float) {}
|
||||
void SetConeAngles(float,float) {}
|
||||
void SetVolume(int) {}
|
||||
int GetVolume() { return(0); }
|
||||
void SetVelocity(const Vec3d &vVel) {}
|
||||
Vec3d GetVelocity() {return (Vec3d(0,0,0));}
|
||||
void SetDirection(const Vec3d &vDir) {}
|
||||
Vec3d GetDirection() {return (Vec3d(0,0,0));}
|
||||
void SetLoopPoints(const int iLoopStart, const int iLoopEnd) { };
|
||||
bool IsRelative() const { return false; };
|
||||
bool RegisterInIndoor() { return(false); };
|
||||
void SetSoundPriority(unsigned char nSoundPriority) {} ;
|
||||
bool Preload() { return true; }
|
||||
// Sets certain sound properties
|
||||
void SetSoundProperties(float fFadingValue) {} ;
|
||||
|
||||
void AddFlags(int nFlags) {}
|
||||
int AddRef() { return ++m_refCount; };
|
||||
int Release()
|
||||
{
|
||||
int ref = --m_refCount;
|
||||
return ref;
|
||||
};
|
||||
|
||||
//! enable fx effects for this sound
|
||||
//! must be called after each play
|
||||
void FXEnable(int nEffectNumber) {}
|
||||
void FXSetParamEQ(float fCenter,float fBandwidth,float fGain) {}
|
||||
|
||||
//! retrieves the currently played sample-pos, in milliseconds or bytes
|
||||
unsigned int GetCurrentSamplePos(bool bMilliSeconds=false) { return (0);}
|
||||
//! set the currently played sample-pos in bytes or milliseconds
|
||||
void SetCurrentSamplePos(unsigned int nPos,bool bMilliSeconds) {}
|
||||
|
||||
//! returns the size of the stream in ms
|
||||
int GetLengthMs() { return(0); }
|
||||
|
||||
//! returns the size of the stream in bytes
|
||||
int GetLength() { return(0); }
|
||||
void AddEventListener( ISoundEventListener *pListener ) {};
|
||||
void RemoveEventListener( ISoundEventListener *pListener ) {};
|
||||
|
||||
private:
|
||||
Vec3d m_vDummy;
|
||||
int m_refCount;
|
||||
};
|
||||
|
||||
#ifdef WIN64
|
||||
#undef PlaySound
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
class CDummySoundSystem : public CSoundSystemCommon
|
||||
{
|
||||
public:
|
||||
CDummySoundSystem(ISystem* pSystem, HWND hWnd) : CSoundSystemCommon(pSystem) {}
|
||||
~CDummySoundSystem()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool IsOK() { return true; }
|
||||
|
||||
//// ISoundSystem ///////////////////////////////////////////////
|
||||
void Release(){}
|
||||
void Update(){}
|
||||
IMusicSystem* CreateMusicSystem() { return new CDummyMusicSystem(NULL); }
|
||||
ISound* LoadSound(const char *szFile, int nFlags) { return &m_sndDummy; }
|
||||
void RemoveSound(int nSoundID){}
|
||||
ISound* GetSound(int nSoundID){ return &m_sndDummy;}
|
||||
void SetMasterVolume(unsigned char nVol) { }
|
||||
void SetMasterVolumeScale(float fScale, bool bForceRecalc=false){}
|
||||
void AddSoundFlags(int nSoundID,int nFlags){}
|
||||
|
||||
void PlaySound(int nSoundID){}
|
||||
//void SetListener(const Vec3d &vPos,const Vec3d &vVel,const Vec3d& vAngles) {}
|
||||
void SetListener(const CCamera &cCam, const Vec3d &vVel) {}
|
||||
Vec3d GetListenerPos() {return(Vec3d(0,0,0));}
|
||||
|
||||
bool PlayMusic(const char *szFileName) { return (false); }
|
||||
void StopMusic() {}
|
||||
void Silence() {}
|
||||
void Pause(bool bPause,bool bResetVolume=false) {}
|
||||
void Mute(bool bMute) {}
|
||||
|
||||
//! Check for EAX support.
|
||||
bool IsEAX(int version) { return(false); }
|
||||
//! Set EAX listener environment.
|
||||
bool SetEaxListenerEnvironment(int nPreset,CS_REVERB_PROPERTIES *pProps=NULL, int nFlags=0) { return(false); }
|
||||
//! Gets current EAX listener environment.
|
||||
bool GetCurrentEaxEnvironment(int &nPreset, CS_REVERB_PROPERTIES &Props) { nPreset=0;return (true);}
|
||||
bool SetGroupScale(int nGroup, float fScale) { return true; }
|
||||
void RecomputeSoundOcclusion(bool bRecomputeListener,bool bForceRecompute,bool bReset) {}
|
||||
|
||||
//! get memory usage info
|
||||
void GetSoundMemoryUsageInfo(size_t &nCurrentMemory,size_t &nMaxMemory)
|
||||
{
|
||||
nCurrentMemory=nMaxMemory=0;
|
||||
}
|
||||
|
||||
int GetUsedVoices() { return 0; }
|
||||
float GetCPUUsage() { return 0.0f; }
|
||||
float GetMusicVolume() { return 0.0f; }
|
||||
void CalcDirectionalAttenuation(Vec3d &Pos, Vec3d &Dir, float fConeInRadians) {}
|
||||
float GetDirectionalAttenuationMaxScale() { return 0.0f; }
|
||||
bool UsingDirectionalAttenuation() { return false; }
|
||||
void GetMemoryUsage(class ICrySizer* pSizer) {}
|
||||
//! get the current area the listener is in
|
||||
IVisArea *GetListenerArea() { return(NULL); }
|
||||
int SetMinSoundPriority( int nPriority ) { return 0; };
|
||||
|
||||
void LockResources() {};
|
||||
void UnlockResources() {};
|
||||
|
||||
private:
|
||||
CDummySound m_sndDummy;
|
||||
};
|
||||
|
||||
|
||||
#endif //_DUMMY_SOUND_H_
|
||||
5
CrySoundSystem/MSSCCPRJ.SCC
Normal file
5
CrySoundSystem/MSSCCPRJ.SCC
Normal file
@@ -0,0 +1,5 @@
|
||||
SCC = This is a source code control file
|
||||
|
||||
[CrySoundSystem.vcproj]
|
||||
SCC_Aux_Path = "P4SCC#perforce:1666##marcoc_code##PC018"
|
||||
SCC_Project_Name = Perforce Project
|
||||
291
CrySoundSystem/MusicLoadSink.h
Normal file
291
CrySoundSystem/MusicLoadSink.h
Normal file
@@ -0,0 +1,291 @@
|
||||
#include "IScriptSystem.h"
|
||||
#include <StlUtils.h>
|
||||
|
||||
#define MUSICLOAD_MODE_BASE 0
|
||||
#define MUSICLOAD_MODE_PATTERNS 1
|
||||
#define MUSICLOAD_MODE_THEMES 2
|
||||
#define MUSICLOAD_MODE_MOODS 3
|
||||
#define MUSICLOAD_MODE_MOODLAYERS 4
|
||||
#define MUSICLOAD_MODE_BRIDGES 5
|
||||
#define MUSICLOAD_MODE_FADEPOS 6
|
||||
#define MUSICLOAD_MODE_DEFAULTMOOD 7
|
||||
#define MUSICLOAD_MODE_PATTERNSET 8
|
||||
|
||||
class CMusicLoadSink : public IScriptObjectDumpSink
|
||||
{
|
||||
private:
|
||||
SMusicData *m_pMusicData;
|
||||
IScriptSystem *m_pScriptSystem;
|
||||
_SmartScriptObject *m_pObj;
|
||||
int m_nMode;
|
||||
SMusicTheme *m_pTheme;
|
||||
SMusicMood *m_pMood;
|
||||
SMusicPatternSet *m_pPatternSet;
|
||||
SPatternDef *m_pPattern;
|
||||
int m_nLayer;
|
||||
|
||||
typedef std::map<string,SPatternDef*,stl::less_stricmp<string> > TPatternsMap;
|
||||
TPatternsMap m_patternsMap;
|
||||
public:
|
||||
CMusicLoadSink(SMusicData *pMusicData, IScriptSystem *pScriptSystem, _SmartScriptObject *pObj, int nMode=MUSICLOAD_MODE_BASE, SPatternDef *pPattern=NULL, SMusicTheme *pTheme=NULL, SMusicMood *pMood=NULL, SMusicPatternSet *pPatternSet=NULL, int nLayer=MUSICLAYER_MAIN)
|
||||
{
|
||||
m_pMusicData=pMusicData;
|
||||
m_pScriptSystem=pScriptSystem;
|
||||
m_pObj=pObj;
|
||||
m_nMode=nMode;
|
||||
m_pTheme=pTheme;
|
||||
m_pMood=pMood;
|
||||
m_pPatternSet=pPatternSet;
|
||||
m_pPattern=pPattern;
|
||||
m_nLayer=nLayer;
|
||||
|
||||
if (nMode == MUSICLOAD_MODE_MOODLAYERS)
|
||||
{
|
||||
// Make map of patterns.
|
||||
for (int i = 0; i < (int)m_pMusicData->vecPatternDef.size(); i++)
|
||||
{
|
||||
SPatternDef *ptrn = m_pMusicData->vecPatternDef[i];
|
||||
m_patternsMap[ptrn->sName.c_str()] = ptrn;
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
void OnElementFound(const char *sName, ScriptVarType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case svtObject:
|
||||
{
|
||||
_SmartScriptObject pObj(m_pScriptSystem, true);
|
||||
if (!(*m_pObj)->GetValue(sName, pObj))
|
||||
break;
|
||||
switch (m_nMode)
|
||||
{
|
||||
case MUSICLOAD_MODE_BASE:
|
||||
{
|
||||
if (strcmp("Patterns", sName)==0)
|
||||
{
|
||||
CMusicLoadSink Sink(m_pMusicData, m_pScriptSystem, &pObj, MUSICLOAD_MODE_PATTERNS);
|
||||
pObj->Dump(&Sink);
|
||||
}else
|
||||
if (strcmp("Themes", sName)==0)
|
||||
{
|
||||
CMusicLoadSink Sink(m_pMusicData, m_pScriptSystem, &pObj, MUSICLOAD_MODE_THEMES);
|
||||
pObj->Dump(&Sink);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MUSICLOAD_MODE_PATTERNS:
|
||||
{
|
||||
SPatternDef *pPatternDef=new SPatternDef();
|
||||
const char *pszFilename;
|
||||
if (!pObj->GetValue("File", pszFilename))
|
||||
break;
|
||||
_SmartScriptObject pSubObj(m_pScriptSystem, true);
|
||||
if (!pObj->GetValue("FadePos", pSubObj))
|
||||
break;
|
||||
if (!pObj->GetValue("LayeringVolume", pPatternDef->nLayeringVolume))
|
||||
pPatternDef->nLayeringVolume=255;
|
||||
pPatternDef->sName=sName;
|
||||
pPatternDef->sFilename=pszFilename;
|
||||
CMusicLoadSink FadePosSink(m_pMusicData, m_pScriptSystem, &pSubObj, MUSICLOAD_MODE_FADEPOS, pPatternDef);
|
||||
pSubObj->Dump(&FadePosSink);
|
||||
m_pMusicData->vecPatternDef.push_back(pPatternDef);
|
||||
break;
|
||||
}
|
||||
case MUSICLOAD_MODE_THEMES:
|
||||
{
|
||||
_SmartScriptObject pSubObj(m_pScriptSystem, true);
|
||||
SMusicTheme *pTheme=new SMusicTheme();
|
||||
pTheme->sName=sName;
|
||||
if (pObj->GetValue("DefaultMood", pSubObj))
|
||||
{
|
||||
const char *pszDefaultMood;
|
||||
if (pSubObj->GetValue("Mood", pszDefaultMood))
|
||||
pTheme->sDefaultMood=pszDefaultMood;
|
||||
else
|
||||
pTheme->sDefaultMood="";
|
||||
pSubObj->GetValue("Timeout", pTheme->fDefaultMoodTimeout);
|
||||
}
|
||||
if (pObj->GetValue("Moods", pSubObj))
|
||||
{
|
||||
CMusicLoadSink MoodsSink(m_pMusicData, m_pScriptSystem, &pSubObj, MUSICLOAD_MODE_MOODS, NULL, pTheme);
|
||||
pSubObj->Dump(&MoodsSink);
|
||||
}
|
||||
if (pObj->GetValue("Bridges", pSubObj))
|
||||
{
|
||||
CMusicLoadSink BridgesSink(m_pMusicData, m_pScriptSystem, &pSubObj, MUSICLOAD_MODE_BRIDGES, NULL, pTheme);
|
||||
pSubObj->Dump(&BridgesSink);
|
||||
}
|
||||
m_pMusicData->mapThemes.insert(TThemeMapIt::value_type(sName, pTheme));
|
||||
break;
|
||||
}
|
||||
case MUSICLOAD_MODE_MOODS:
|
||||
{
|
||||
if (!m_pTheme)
|
||||
break;
|
||||
SMusicMood *pMood=new SMusicMood();
|
||||
pMood->sName=sName;
|
||||
if (!pObj->GetValue("Priority", pMood->nPriority))
|
||||
pMood->nPriority=0; // default priority
|
||||
if (!pObj->GetValue("FadeOutTime", pMood->fFadeOutTime))
|
||||
pMood->fFadeOutTime=DEFAULT_CROSSFADE_TIME;
|
||||
if (!pObj->GetValue("PlaySingle", pMood->bPlaySingle))
|
||||
pMood->bPlaySingle=false;
|
||||
_SmartScriptObject pSubObj(m_pScriptSystem, true);
|
||||
if (pObj->GetValue("PatternSet", pSubObj))
|
||||
{
|
||||
CMusicLoadSink Sink(m_pMusicData, m_pScriptSystem, &pSubObj, MUSICLOAD_MODE_PATTERNSET, NULL, m_pTheme, pMood);
|
||||
pSubObj->Dump(&Sink);
|
||||
}
|
||||
m_pTheme->mapMoods.insert(TMoodMapIt::value_type(sName, pMood));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case svtString:
|
||||
case svtNumber:
|
||||
{
|
||||
switch (m_nMode)
|
||||
{
|
||||
case MUSICLOAD_MODE_BRIDGES:
|
||||
{
|
||||
if (!m_pTheme)
|
||||
break;
|
||||
const char *pszPattern;
|
||||
if (!(*m_pObj)->GetValue(sName, pszPattern))
|
||||
break;
|
||||
m_pTheme->mapBridges.insert(TThemeBridgeMapIt::value_type(sName, pszPattern));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void OnElementFound(int nIdx, ScriptVarType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case svtObject:
|
||||
{
|
||||
switch (m_nMode)
|
||||
{
|
||||
case MUSICLOAD_MODE_PATTERNSET:
|
||||
{
|
||||
if (!m_pMood)
|
||||
break;
|
||||
SMusicPatternSet *pPatternSet=new SMusicPatternSet();
|
||||
_SmartScriptObject pObj(m_pScriptSystem, true);
|
||||
if (!(*m_pObj)->GetAt(nIdx, pObj))
|
||||
break;
|
||||
if (!pObj->GetValue("MinTimeout", pPatternSet->fMinTimeout))
|
||||
pPatternSet->fMinTimeout=60.0f;
|
||||
if (!pObj->GetValue("MaxTimeout", pPatternSet->fMaxTimeout))
|
||||
pPatternSet->fMaxTimeout=120.0f;
|
||||
_SmartScriptObject pSubObj(m_pScriptSystem, true);
|
||||
pPatternSet->fTotalMainPatternProbability=0.0f;
|
||||
if (pObj->GetValue("MainLayer", pSubObj))
|
||||
{
|
||||
_SmartScriptObject pPatternsSubObj(m_pScriptSystem, true);
|
||||
if (pSubObj->GetValue("Patterns", pPatternsSubObj))
|
||||
{
|
||||
CMusicLoadSink Sink(m_pMusicData, m_pScriptSystem, &pPatternsSubObj, MUSICLOAD_MODE_MOODLAYERS, NULL, m_pTheme, m_pMood, pPatternSet, MUSICLAYER_MAIN);
|
||||
pPatternsSubObj->Dump(&Sink);
|
||||
}
|
||||
}
|
||||
pPatternSet->fTotalRhythmicPatternProbability=0.0f;
|
||||
if (pObj->GetValue("RhythmicLayer", pSubObj))
|
||||
{
|
||||
if (!pSubObj->GetValue("Probability", pPatternSet->fRhythmicLayerProbability))
|
||||
pPatternSet->fRhythmicLayerProbability=100.0f;
|
||||
if (!pSubObj->GetValue("MaxSimultaneousPatterns", pPatternSet->nMaxSimultaneousRhythmicPatterns))
|
||||
pPatternSet->nMaxSimultaneousRhythmicPatterns=1;
|
||||
_SmartScriptObject pPatternsSubObj(m_pScriptSystem, true);
|
||||
if (pSubObj->GetValue("Patterns", pPatternsSubObj))
|
||||
{
|
||||
CMusicLoadSink Sink(m_pMusicData, m_pScriptSystem, &pPatternsSubObj, MUSICLOAD_MODE_MOODLAYERS, NULL, m_pTheme, m_pMood, pPatternSet, MUSICLAYER_RHYTHMIC);
|
||||
pPatternsSubObj->Dump(&Sink);
|
||||
}
|
||||
}
|
||||
pPatternSet->fTotalIncidentalPatternProbability=0.0f;
|
||||
if (pObj->GetValue("IncidentalLayer", pSubObj))
|
||||
{
|
||||
if (!pSubObj->GetValue("Probability", pPatternSet->fIncidentalLayerProbability))
|
||||
pPatternSet->fIncidentalLayerProbability=100.0f;
|
||||
if (!pSubObj->GetValue("MaxSimultaneousPatterns", pPatternSet->nMaxSimultaneousIncidentalPatterns))
|
||||
pPatternSet->nMaxSimultaneousIncidentalPatterns=1;
|
||||
_SmartScriptObject pPatternsSubObj(m_pScriptSystem, true);
|
||||
if (pSubObj->GetValue("Patterns", pPatternsSubObj))
|
||||
{
|
||||
CMusicLoadSink Sink(m_pMusicData, m_pScriptSystem, &pPatternsSubObj, MUSICLOAD_MODE_MOODLAYERS, NULL, m_pTheme, m_pMood, pPatternSet, MUSICLAYER_INCIDENTAL);
|
||||
pPatternsSubObj->Dump(&Sink);
|
||||
}
|
||||
}
|
||||
m_pMood->vecPatternSets.push_back(pPatternSet);
|
||||
break;
|
||||
}
|
||||
case MUSICLOAD_MODE_MOODLAYERS:
|
||||
{
|
||||
if (!m_pPatternSet)
|
||||
break;
|
||||
_SmartScriptObject pSubObj(m_pScriptSystem, true);
|
||||
if (!(*m_pObj)->GetAt(nIdx, pSubObj))
|
||||
break;
|
||||
// read attributes
|
||||
string sPatternName;
|
||||
float fProbability = 0;
|
||||
const char *pszPatternName;
|
||||
if (!pSubObj->GetValue("Pattern", pszPatternName))
|
||||
break;
|
||||
sPatternName = pszPatternName;
|
||||
pSubObj->GetValue("Probability", fProbability);
|
||||
|
||||
SPatternDef *pPattern = stl::find_in_map( m_patternsMap,sPatternName, (SPatternDef *)NULL );
|
||||
if (pPattern)
|
||||
{
|
||||
pPattern->fProbability = fProbability;
|
||||
|
||||
switch (m_nLayer)
|
||||
{
|
||||
case MUSICLAYER_MAIN:
|
||||
m_pPatternSet->vecMainPatterns.push_back(pPattern);
|
||||
m_pPatternSet->fTotalMainPatternProbability+=fProbability;
|
||||
break;
|
||||
case MUSICLAYER_RHYTHMIC:
|
||||
m_pPatternSet->vecRhythmicPatterns.push_back(pPattern);
|
||||
m_pPatternSet->fTotalRhythmicPatternProbability+=fProbability;
|
||||
break;
|
||||
case MUSICLAYER_INCIDENTAL:
|
||||
m_pPatternSet->vecIncidentalPatterns.push_back(pPattern);
|
||||
m_pPatternSet->fTotalIncidentalPatternProbability+=fProbability;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case svtString:
|
||||
case svtNumber:
|
||||
{
|
||||
switch (m_nMode)
|
||||
{
|
||||
case MUSICLOAD_MODE_FADEPOS:
|
||||
{
|
||||
if (!m_pPattern)
|
||||
break;
|
||||
int nFadePos;
|
||||
if (!(*m_pObj)->GetAt(nIdx, nFadePos))
|
||||
break;
|
||||
m_pPattern->vecFadePoints.push_back(nFadePos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
296
CrySoundSystem/MusicPattern.cpp
Normal file
296
CrySoundSystem/MusicPattern.cpp
Normal file
@@ -0,0 +1,296 @@
|
||||
#include "StdAfx.h"
|
||||
#include <algorithm>
|
||||
#include <CrySizer.h>
|
||||
#include <ICryPak.h>
|
||||
#include "musicpattern.h"
|
||||
#include "PCMDecoder.h"
|
||||
#include "OGGDecoder.h"
|
||||
#include "ADPCMDecoder.h"
|
||||
|
||||
//#define TEST
|
||||
|
||||
CMusicPattern::CMusicPattern(IMusicSystem *pMusicSystem, const char *pszName,const char *pszFilename)
|
||||
{
|
||||
m_pMusicSystem=pMusicSystem;
|
||||
m_pDecoder=NULL;
|
||||
m_vecFadePoints.clear();
|
||||
m_nLayeringVolume=255;
|
||||
m_sName=pszName;
|
||||
m_sFilename = pszFilename;
|
||||
m_numPatternInstances = 0;
|
||||
m_nSamples = 0;
|
||||
}
|
||||
|
||||
CMusicPattern::~CMusicPattern()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
static bool inline
|
||||
FindFile( ICryPak* pPak, const char* pszFilename )
|
||||
{
|
||||
bool bRet( false );
|
||||
FILE* pFile( pPak->FOpen( pszFilename, "rb" ) ) ;
|
||||
if( 0 != pFile )
|
||||
{
|
||||
bRet = true;
|
||||
pPak->FClose( pFile );
|
||||
}
|
||||
return( bRet );
|
||||
}
|
||||
|
||||
bool CMusicPattern::Open( const char* pszFilename )
|
||||
{
|
||||
// no valid filename
|
||||
if( 0 == pszFilename || strlen( pszFilename ) < 5 )
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
|
||||
if( 0 != m_pDecoder )
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
ISystem* pSystem( m_pMusicSystem->GetSystem() );
|
||||
ICryPak* pPak( pSystem->GetIPak() );
|
||||
assert( 0 != pPak );
|
||||
|
||||
string strFilename( pszFilename );
|
||||
if( 0 != stricmp( strFilename.c_str() + strFilename.size() - 4, ".ogg" ) )
|
||||
{
|
||||
strFilename = strFilename.substr( 0, strFilename.size() - 4 ) + ".ogg";
|
||||
}
|
||||
|
||||
bool bWaveFallback( false != m_pMusicSystem->StreamOGG() && false == FindFile( pPak, strFilename.c_str() ) );
|
||||
if( false == m_pMusicSystem->StreamOGG() || false != bWaveFallback )
|
||||
{
|
||||
if( false != bWaveFallback )
|
||||
{
|
||||
#ifdef LOG_MUSICFILES
|
||||
m_pMusicSystem->LogMsg( "OGG file %s not found... trying .wav", strFilename.c_str() );
|
||||
#endif
|
||||
}
|
||||
|
||||
// use (AD)PCM files for music streaming
|
||||
strFilename = strFilename.substr( 0, strFilename.size() - 4 ) + ".wav";
|
||||
|
||||
FILE* pFile( pPak->FOpen( strFilename.c_str(), "rb" ) );
|
||||
if( 0 != pFile )
|
||||
{
|
||||
// check encoding and spawn PCM or ADPCM decoder accordingly
|
||||
SWaveHdr header;
|
||||
pPak->FRead( &header, sizeof( SWaveHdr ), 1, pFile );
|
||||
if( header.dwSize < ( 90 - 8 + 12 ) )
|
||||
{
|
||||
// not enough data, not even one sample
|
||||
return( false );
|
||||
}
|
||||
if( WAVE_FORMAT_ADPCM == header.wOne_0 )
|
||||
{
|
||||
m_pDecoder = new CADPCMDecoder( m_pMusicSystem );
|
||||
m_pDecoder->Open( strFilename.c_str() );// returns always true, just use here to really open it
|
||||
// since we actually do not know in advance how many samples are contained, we need to create a temp instance
|
||||
IMusicPatternDecoderInstance* pTempInstance( m_pDecoder->CreateInstance() );
|
||||
pTempInstance->Release();
|
||||
#ifdef LOG_MUSICFILES
|
||||
m_pMusicSystem->LogMsg( "Initialized ADPCM Decoder for %s", strFilename.c_str() );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
if( WAVE_FORMAT_PCM == header.wOne_0 )
|
||||
{
|
||||
m_pDecoder = new CPCMDecoder( m_pMusicSystem );
|
||||
#ifdef LOG_MUSICFILES
|
||||
m_pMusicSystem->LogMsg( "Initialized PCM Decoder for %s", strFilename.c_str() );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef LOG_MUSICFILES
|
||||
m_pMusicSystem->LogMsg( "AD(PCM) expected... failed to initialize %s", strFilename.c_str() );
|
||||
#endif
|
||||
return( false );
|
||||
}
|
||||
pPak->FClose( pFile );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// use OGG files for music streaming
|
||||
if( 0 != stricmp( strFilename.c_str() + strFilename.size() - 4, ".ogg" ) )
|
||||
{
|
||||
strFilename = strFilename.substr( 0, strFilename.size() - 4 ) + ".ogg";
|
||||
}
|
||||
|
||||
m_pDecoder = new COGGDecoder( m_pMusicSystem );
|
||||
#ifdef LOG_MUSICFILES
|
||||
m_pMusicSystem->LogMsg( "Initialized OGG Decoder for %s", strFilename.c_str() );
|
||||
#endif
|
||||
}
|
||||
|
||||
if( 0 != m_pDecoder )
|
||||
{
|
||||
if( false == m_pDecoder->Open( strFilename.c_str() ) )
|
||||
{
|
||||
m_pDecoder->Release();
|
||||
m_pDecoder=NULL;
|
||||
return( false );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
|
||||
SMusicPatternFileInfo fileInfo;
|
||||
if( false != m_pDecoder->GetFileInfo( fileInfo ) )
|
||||
{
|
||||
m_nSamples = fileInfo.nSamples;
|
||||
#ifdef TEST
|
||||
signed long *pDat = new signed long[m_nSamples];
|
||||
signed long *pDataLength = new signed long[m_nSamples];
|
||||
signed long *pData = pDat;
|
||||
IMusicPatternDecoderInstance* pTempInstance = m_pDecoder->CreateInstance();
|
||||
unsigned int c = m_nSamples;
|
||||
pTempInstance->GetPCMData(pDataLength,m_nSamples);
|
||||
pTempInstance->Seek0();
|
||||
|
||||
while(c >= 11025)
|
||||
{
|
||||
pTempInstance->GetPCMData(pData,11025);
|
||||
pData += 11025;
|
||||
c -= 11025;
|
||||
}
|
||||
if(c > 0)
|
||||
{
|
||||
pTempInstance->GetPCMData(pData,c);
|
||||
}
|
||||
SWaveHdr header;
|
||||
FILE *pOrig = fopen("MUSIC/Original.wav","rb");
|
||||
FILE *pTest = fopen("MUSIC/Test.wav","wb");
|
||||
fread(&header, sizeof(SWaveHdr), 1, pOrig);
|
||||
fwrite(&header, 1, sizeof(SWaveHdr), pTest);
|
||||
fwrite(pDat, 1, m_nSamples*4, pTest);
|
||||
fclose(pTest);
|
||||
fclose(pOrig);
|
||||
pTempInstance->Release();
|
||||
for(int i=0;i<m_nSamples;i++)
|
||||
{
|
||||
if(pDat[i] != pDataLength[i])
|
||||
{
|
||||
signed long sl0 = pDat[i];
|
||||
signed long sl1 = pDataLength[i];
|
||||
int ivo=0;
|
||||
}
|
||||
}
|
||||
delete [] pDat;
|
||||
delete [] pDataLength;
|
||||
#endif
|
||||
}
|
||||
|
||||
m_sFilename = strFilename;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMusicPattern::Close()
|
||||
{
|
||||
if (!m_pDecoder)
|
||||
return false;
|
||||
m_pDecoder->Close();
|
||||
m_pDecoder->Release();
|
||||
m_pDecoder=NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMusicPattern::AddFadePoint(int nFadePos)
|
||||
{
|
||||
/*
|
||||
SMusicPatternFileInfo FileInfo;
|
||||
if (nFadePos<=0)
|
||||
{
|
||||
if (!GetFileInfo(FileInfo))
|
||||
return false;
|
||||
nFadePos = FileInfo.nSamples+nFadePos;
|
||||
}
|
||||
*/
|
||||
TMarkerVecIt It=std::find(m_vecFadePoints.begin(), m_vecFadePoints.end(), nFadePos);
|
||||
if (It!=m_vecFadePoints.end()) // already in list ?
|
||||
return true;
|
||||
m_vecFadePoints.push_back(nFadePos);
|
||||
std::sort(m_vecFadePoints.begin(), m_vecFadePoints.end());
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMusicPattern::ClearFadePoints()
|
||||
{
|
||||
m_vecFadePoints.clear();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IMusicPatternDecoderInstance* CMusicPattern::CreateDecoderInstance()
|
||||
{
|
||||
if (!m_pDecoder)
|
||||
return NULL;
|
||||
return m_pDecoder->CreateInstance();
|
||||
}
|
||||
|
||||
CMusicPatternInstance* CMusicPattern::CreateInstance()
|
||||
{
|
||||
if (!m_pDecoder)
|
||||
{
|
||||
// Make new decoder.
|
||||
if (!Open( m_sFilename.c_str() ))
|
||||
{
|
||||
m_pMusicSystem->LogMsg( "ERROR: Music file %s failed to load",m_sFilename.c_str() );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!m_pDecoder)
|
||||
return NULL;
|
||||
m_numPatternInstances++;
|
||||
return new CMusicPatternInstance(this);
|
||||
}
|
||||
|
||||
void CMusicPattern::ReleaseInstance( CMusicPatternInstance* pInstance )
|
||||
{
|
||||
m_numPatternInstances--;
|
||||
if (m_numPatternInstances <= 0)
|
||||
{
|
||||
// Can release decoder.
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
bool CMusicPattern::GetFileInfo(SMusicPatternFileInfo &FileInfo)
|
||||
{
|
||||
if (!m_pDecoder)
|
||||
{
|
||||
// Make new decoder.
|
||||
if (!Open( m_sFilename.c_str() ))
|
||||
{
|
||||
m_pMusicSystem->LogMsg( "ERROR: Music file %s failed to load",m_sFilename.c_str() );
|
||||
return false;
|
||||
}
|
||||
bool bRes = false;
|
||||
if (m_pDecoder)
|
||||
bRes = m_pDecoder->GetFileInfo(FileInfo);
|
||||
Close();
|
||||
return bRes;
|
||||
}
|
||||
else
|
||||
return m_pDecoder->GetFileInfo(FileInfo);
|
||||
}
|
||||
|
||||
void CMusicPattern::GetMemoryUsage(class ICrySizer* pSizer)
|
||||
{
|
||||
if (!pSizer->Add(*this))
|
||||
return;
|
||||
if (m_pDecoder)
|
||||
m_pDecoder->GetMemoryUsage(pSizer);
|
||||
}
|
||||
43
CrySoundSystem/MusicPattern.h
Normal file
43
CrySoundSystem/MusicPattern.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "MusicPatternInstance.h"
|
||||
|
||||
struct IMusicSystem;
|
||||
struct SMusicPatternFileInfo;
|
||||
struct IMusicPatternDecoder;
|
||||
|
||||
typedef std::vector<int> TMarkerVec;
|
||||
typedef TMarkerVec::iterator TMarkerVecIt;
|
||||
|
||||
class CMusicPattern
|
||||
{
|
||||
protected:
|
||||
IMusicSystem *m_pMusicSystem;
|
||||
IMusicPatternDecoder *m_pDecoder;
|
||||
string m_sName;
|
||||
string m_sFilename;
|
||||
TMarkerVec m_vecFadePoints;
|
||||
int m_nLayeringVolume;
|
||||
friend class CMusicPatternInstance;
|
||||
int m_numPatternInstances;
|
||||
int m_nSamples; //!< Number of Samples in pattern.
|
||||
private:
|
||||
IMusicPatternDecoderInstance* CreateDecoderInstance();
|
||||
public:
|
||||
CMusicPattern(IMusicSystem *pMusicSystem, const char *pszName,const char *pszFilename);
|
||||
~CMusicPattern();
|
||||
bool Open(const char *pszFilename);
|
||||
bool Close();
|
||||
bool AddFadePoint(int nFadePos);
|
||||
void ClearFadePoints();
|
||||
void SetLayeringVolume(int nVol) { m_nLayeringVolume=nVol; }
|
||||
int GetLayeringVolume() { return m_nLayeringVolume; }
|
||||
CMusicPatternInstance* CreateInstance();
|
||||
void ReleaseInstance( CMusicPatternInstance* pInstance );
|
||||
void SetFilename( const char *sFilename ) { m_sFilename = sFilename; };
|
||||
const char* GetName() { return m_sName.c_str(); }
|
||||
const char* GetFilename() { return m_sFilename.c_str(); }
|
||||
bool GetFileInfo(SMusicPatternFileInfo &FileInfo);
|
||||
void GetMemoryUsage(class ICrySizer* pSizer);
|
||||
};
|
||||
76
CrySoundSystem/MusicPatternInstance.cpp
Normal file
76
CrySoundSystem/MusicPatternInstance.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#include "StdAfx.h"
|
||||
#include "musicpatterninstance.h"
|
||||
#include "MusicPattern.h"
|
||||
#include "PatternDecoder.h"
|
||||
|
||||
CMusicPatternInstance::CMusicPatternInstance(CMusicPattern *pPattern)
|
||||
{
|
||||
m_nRefs=0;
|
||||
m_pPattern=pPattern;
|
||||
if (m_pPattern)
|
||||
m_pDecoderInstance=m_pPattern->CreateDecoderInstance();
|
||||
else
|
||||
m_pDecoderInstance=NULL;
|
||||
}
|
||||
|
||||
CMusicPatternInstance::~CMusicPatternInstance()
|
||||
{
|
||||
if (m_pDecoderInstance)
|
||||
m_pDecoderInstance->Release();
|
||||
m_pPattern->ReleaseInstance( this );
|
||||
}
|
||||
|
||||
bool CMusicPatternInstance::Seek0(int nDelay)
|
||||
{
|
||||
if (!m_pDecoderInstance)
|
||||
return false;
|
||||
return m_pDecoderInstance->Seek0(nDelay);
|
||||
}
|
||||
|
||||
bool CMusicPatternInstance::GetPCMData(signed long *pDataOut, int nSamples, bool bLoop)
|
||||
{
|
||||
if (!m_pDecoderInstance)
|
||||
return false;
|
||||
return m_pDecoderInstance->GetPCMData(pDataOut, nSamples, bLoop);
|
||||
}
|
||||
|
||||
int CMusicPatternInstance::GetSamplesToNextFadePoint()
|
||||
{
|
||||
if (!m_pDecoderInstance)
|
||||
return false;
|
||||
int nPos=m_pDecoderInstance->GetPos();
|
||||
for (TMarkerVecIt It=m_pPattern->m_vecFadePoints.begin();It!=m_pPattern->m_vecFadePoints.end();++It)
|
||||
{
|
||||
int nFadePos=(*It);
|
||||
if (nFadePos <= 0)
|
||||
{
|
||||
nFadePos = m_pPattern->m_nSamples + nFadePos;
|
||||
}
|
||||
if (nFadePos>nPos)
|
||||
return nFadePos-nPos;
|
||||
}
|
||||
return GetSamplesToEnd();
|
||||
}
|
||||
|
||||
int CMusicPatternInstance::GetSamplesToLastFadePoint()
|
||||
{
|
||||
if (!m_pDecoderInstance)
|
||||
return false;
|
||||
int nPos=m_pDecoderInstance->GetPos();
|
||||
if (m_pPattern->m_vecFadePoints.empty())
|
||||
return GetSamplesToEnd();
|
||||
|
||||
int nFadePos = (*(m_pPattern->m_vecFadePoints.end()-1));
|
||||
if (nFadePos <= 0)
|
||||
{
|
||||
nFadePos = m_pPattern->m_nSamples + nFadePos;
|
||||
}
|
||||
return nFadePos - nPos;
|
||||
}
|
||||
|
||||
int CMusicPatternInstance::GetSamplesToEnd()
|
||||
{
|
||||
if (m_pDecoderInstance != NULL && m_pPattern != NULL)
|
||||
return m_pPattern->m_nSamples - m_pDecoderInstance->GetPos();
|
||||
return -1;
|
||||
}
|
||||
34
CrySoundSystem/MusicPatternInstance.h
Normal file
34
CrySoundSystem/MusicPatternInstance.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <SmartPtr.h>
|
||||
|
||||
class CMusicPattern;
|
||||
struct IMusicPatternDecoderInstance;
|
||||
|
||||
class CMusicPatternInstance
|
||||
{
|
||||
protected:
|
||||
int m_nRefs;
|
||||
CMusicPattern *m_pPattern;
|
||||
IMusicPatternDecoderInstance *m_pDecoderInstance;
|
||||
public:
|
||||
CMusicPatternInstance(CMusicPattern *pPattern);
|
||||
virtual ~CMusicPatternInstance();
|
||||
void AddRef()
|
||||
{
|
||||
m_nRefs++;
|
||||
}
|
||||
void Release()
|
||||
{
|
||||
m_nRefs--;
|
||||
if (m_nRefs<=0)
|
||||
delete this;
|
||||
}
|
||||
CMusicPattern* GetPattern() { return m_pPattern; }
|
||||
//! Seek to beginning of pattern (if nDelay is set it will wait nDelay-samples before starting playback).
|
||||
bool Seek0(int nDelay=0);
|
||||
bool GetPCMData(signed long *pDataOut, int nSamples, bool bLoop=true);
|
||||
int GetSamplesToNextFadePoint();
|
||||
int GetSamplesToLastFadePoint();
|
||||
int GetSamplesToEnd();
|
||||
};
|
||||
1775
CrySoundSystem/MusicSystem.cpp
Normal file
1775
CrySoundSystem/MusicSystem.cpp
Normal file
File diff suppressed because it is too large
Load Diff
291
CrySoundSystem/MusicSystem.h
Normal file
291
CrySoundSystem/MusicSystem.h
Normal file
@@ -0,0 +1,291 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <isound.h>
|
||||
#include <itimer.h>
|
||||
#include <SmartPtr.h>
|
||||
#include "MusicPattern.h"
|
||||
#include "RandGen.h"
|
||||
|
||||
//#define TRACE_MUSIC
|
||||
|
||||
#ifdef TRACE_MUSIC
|
||||
#define MTRACE TRACE
|
||||
#else
|
||||
#define MTRACE __noop
|
||||
#endif
|
||||
|
||||
#define PATTERNSET_CHANGE_FADETIME 2.0
|
||||
|
||||
// Forward declarations
|
||||
struct ISystem;
|
||||
|
||||
// Smart Pattern-Ptr
|
||||
typedef _smart_ptr<CMusicPatternInstance> TPatternInstancePtr;
|
||||
|
||||
// Type of blending
|
||||
enum EBlendingType
|
||||
{
|
||||
EBlend_FadeOut,
|
||||
EBlend_ToEnd,
|
||||
EBlend_Stop
|
||||
};
|
||||
|
||||
// Info-Structure for automated fading
|
||||
struct SMusicPatternPlayInfo
|
||||
{
|
||||
SMusicPatternPlayInfo()
|
||||
{
|
||||
nLayer=MUSICLAYER_MAIN;
|
||||
pPatternInstance=NULL;
|
||||
eBlendType=EBlend_ToEnd;
|
||||
pRefCount=NULL;
|
||||
fPhase=1.0;
|
||||
fFadeTime=0.0; // use default fade time...
|
||||
bRefCountAdjusted=false;
|
||||
}
|
||||
~SMusicPatternPlayInfo()
|
||||
{
|
||||
pPatternInstance=NULL;
|
||||
}
|
||||
TPatternInstancePtr pPatternInstance;
|
||||
int nLayer;
|
||||
EBlendingType eBlendType;
|
||||
int *pRefCount;
|
||||
// internal
|
||||
double fPhase; // phase for fading (0-1)
|
||||
double fFadeTime; // time in seconds to fade
|
||||
bool bRefCountAdjusted;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// A couple of typedefs for various stl-containers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef std::map<string,CMusicPattern*,stl::less_stricmp<string> > TPatternMap;
|
||||
typedef TPatternMap::iterator TPatternMapIt;
|
||||
|
||||
typedef std::vector<string> TStringVec;
|
||||
typedef TStringVec::iterator TStringVecIt;
|
||||
|
||||
typedef std::vector<SMusicPatternPlayInfo> TPatternPlayInfoVec;
|
||||
typedef TPatternPlayInfoVec::iterator TPatternPlayInfoVecIt;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Structure to collect/handle mood-events
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct SMoodEventInfo
|
||||
{
|
||||
bool operator<(const SMoodEventInfo &b) const
|
||||
{
|
||||
if (stricmp(sMood.c_str(),b.sMood.c_str()) < 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
string sMood;// name of mood
|
||||
float fTime; // time of consecutive event-occurance
|
||||
};
|
||||
|
||||
typedef std::set<SMoodEventInfo> TMoodEventSet;
|
||||
typedef TMoodEventSet::iterator TMoodEventSetIt;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// The MusicSystem itself
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CMusicSystem : public IMusicSystem
|
||||
{
|
||||
protected:
|
||||
CRITICAL_SECTION m_CS;
|
||||
// system pointers
|
||||
ISystem *m_pSystem;
|
||||
ITimer *m_pTimer;
|
||||
ILog *m_pLog;
|
||||
ISoundSystem *m_pSoundSystem;
|
||||
// random generator
|
||||
CPseudoRandGen m_RandGen;
|
||||
// notification sink
|
||||
IMusicSystemSink *m_pSink;
|
||||
// current data (allocated externally)
|
||||
SMusicData *m_pDataPtr;
|
||||
bool m_bOwnMusicData;
|
||||
// sound-playback params
|
||||
float m_fMasterVolume;
|
||||
int m_nSampleRate;
|
||||
float m_fLatency;
|
||||
// bytes/sample in output stream
|
||||
int m_nBytesPerSample;
|
||||
// fmod stream data
|
||||
CS_STREAM *m_pStream;
|
||||
int m_nChannel;
|
||||
// states
|
||||
bool m_bDataLoaded;
|
||||
bool m_bPause;
|
||||
bool m_bPlaying;
|
||||
bool m_bBridging; // bridging in progress
|
||||
bool m_bCurrPatternIsBridge;
|
||||
bool m_bForcePatternChange; // change pattern asap (next fadepoint), do not play to the end (last fadepoint)
|
||||
// status
|
||||
SMusicSystemStatus m_Status;
|
||||
// all patterns
|
||||
TPatternMap m_mapPatterns;
|
||||
// current patterns
|
||||
TPatternInstancePtr m_pCurrPattern;
|
||||
TPatternInstancePtr m_pNextPattern;
|
||||
int m_nLayeredRhythmicPatterns;
|
||||
int m_nLayeredIncidentalPatterns;
|
||||
// temporary mix-buffer
|
||||
void *m_pMixBuffer;
|
||||
// array of currently playing patterns
|
||||
TPatternPlayInfoVec m_vecPlayingPatterns;
|
||||
// all themes (moods inside)
|
||||
TThemeMap m_mapThemes;
|
||||
// current theme/mood
|
||||
SMusicTheme *m_pThemeOverride; // overriding theme (eg. for vehicle)
|
||||
SMusicTheme *m_pCurrTheme;
|
||||
SMusicTheme *m_pNextTheme; // in case a theme change occured, this is the new theme... NULL otherwise
|
||||
SMusicMood *m_pCurrMood;
|
||||
SMusicMood *m_pNextMood;
|
||||
// mood event arrays
|
||||
TMoodEventSet m_setMoodEvents; // active mood events
|
||||
TMoodEventSet m_setFrameMoodEvents; // mood events arrived last frame
|
||||
// default mood
|
||||
//SMusicMood *m_pDefaultMood;
|
||||
float m_fDefaultMoodTime; // current time 'till default-mood-timeout
|
||||
string m_sDefaultMood; // override of theme-specific default-mood (set by SetDefaultMood); set to "" to use theme-specific
|
||||
// fading
|
||||
double m_fCurrCrossfadeTime;
|
||||
// logging
|
||||
TStringVec m_vecLog;
|
||||
bool m_bEnableEventProcessing;
|
||||
ICVar *m_pCVarDebugMusic;
|
||||
ICVar *m_pCVarMusicEnable;
|
||||
ICVar *m_pCVarMusicMaxSimultaniousPatterns;
|
||||
ICVar *m_pCVarMusicStreamedData;
|
||||
int m_musicEnable;
|
||||
protected:
|
||||
virtual ~CMusicSystem();
|
||||
bool Init();
|
||||
void Shutdown();
|
||||
void FlushLog();
|
||||
CMusicPattern* AddPattern(const char *pszName, const char *pszFilename);
|
||||
bool FlushPatterns();
|
||||
bool StartPlaying();
|
||||
bool StopPlaying();
|
||||
SMusicMood* GetMood(SMusicTheme *pTheme, const char *pszMood);
|
||||
bool SetTheme(SMusicTheme *pNewTheme, bool bOverride);
|
||||
bool SetMood(SMusicMood *pNewMood);
|
||||
SMusicMood* GetDefaultMood(SMusicTheme *pTheme);
|
||||
void PushPatternToMixList(SMusicPatternPlayInfo &PlayInfo);
|
||||
void EnterDefaultMood();
|
||||
void Silence();
|
||||
void AdjustMixStreamsRefCount(int nSamples);
|
||||
void MixStreams(void *pBuffer, int nLength);
|
||||
bool FadeStream(SMusicPatternPlayInfo &PlayInfo, signed short *pBuffer, int nSamples);
|
||||
void FadeOutAllSecondaryLayers(double fFadeTime);
|
||||
CMusicPatternInstance* GetPatternInstance(const char *pszPattern);
|
||||
bool UpdateCurrentPatternSet(SMusicMood *pMood, int nSamples, bool bAllowChange);
|
||||
bool ChoosePatternSet(SMusicMood *pMood);
|
||||
CMusicPatternInstance* ChooseBridge(SMusicTheme *pCurrTheme, SMusicTheme *pNewTheme);
|
||||
CMusicPatternInstance* ChoosePattern(SMusicMood *pMood, int nLayer=MUSICLAYER_MAIN);
|
||||
signed char StreamingCallback(CS_STREAM *pStream, void *pBuffer, int nLength);
|
||||
//friend signed char __cdecl _StreamingCallback(CS_STREAM *pStream, void *pBuffer, int nLength, INT_PTR nParam);
|
||||
#ifndef CS_VERSION_372
|
||||
#ifdef CS_VERSION_361
|
||||
friend signed char F_CALLBACKAPI _StreamingCallback(CS_STREAM *pStream, void *pBuffer, int nLength, int nParam);
|
||||
#else
|
||||
friend signed char F_CALLBACKAPI _StreamingCallback(CS_STREAM *pStream, void *pBuffer, int nLength, INT_PTR nParam);
|
||||
#endif
|
||||
#else
|
||||
friend signed char F_CALLBACKAPI _StreamingCallback(CS_STREAM *pStream, void *pBuffer, int nLength, void * nParam);
|
||||
#endif
|
||||
friend class CMusicLoadSink;
|
||||
public:
|
||||
CMusicSystem(ISystem *pSystem);
|
||||
void Release();
|
||||
ISystem* GetSystem() { return m_pSystem; }
|
||||
int GetBytesPerSample() { return m_nBytesPerSample; }
|
||||
IMusicSystemSink* SetSink(IMusicSystemSink *pSink);
|
||||
bool SetData(struct SMusicData *pMusicData,bool bNoRelease=false);
|
||||
void ReleaseData();
|
||||
void Unload();
|
||||
void Pause(bool bPause);
|
||||
void EnableEventProcessing(bool bEnable) { m_bEnableEventProcessing=bEnable; }
|
||||
bool ResetThemeOverride();
|
||||
bool SetTheme(const char *pszTheme, bool bOverride=false);
|
||||
const char* GetTheme() { if (m_pCurrTheme) return m_pCurrTheme->sName.c_str(); return ""; }
|
||||
bool SetMood(const char *pszMood);
|
||||
bool SetDefaultMood(const char *pszMood);
|
||||
const char* GetMood() { if (m_pCurrMood) return m_pCurrMood->sName.c_str(); return ""; }
|
||||
IStringItVec* GetThemes();
|
||||
IStringItVec* GetMoods(const char *pszTheme);
|
||||
bool AddMusicMoodEvent(const char *pszMood, float fTimeout);
|
||||
void Update();
|
||||
SMusicSystemStatus* GetStatus(); // retrieve status of music-system... dont keep returning pointer !
|
||||
//! compute memory-consumption
|
||||
void GetMemoryUsage(class ICrySizer* pSizer);
|
||||
bool LoadMusicDataFromLUA(IScriptSystem* pScriptSystem, const char *pszFilename);
|
||||
bool StreamOGG();
|
||||
void LogMsg( const char *pszFormat, ... );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Load music data from XML.
|
||||
//! @param bAddAdata if true data from XML will be added to currently loaded music data.
|
||||
bool LoadFromXML( const char *sFilename,bool bAddData );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Editing support.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void UpdateTheme( SMusicTheme *pTheme );
|
||||
virtual void UpdateMood( SMusicMood *pMood );
|
||||
virtual void UpdatePattern( SPatternDef *pPattern );
|
||||
virtual void RenamePattern( const char *sOldName,const char *sNewName );
|
||||
virtual void PlayPattern( const char *sPattern,bool bStopPrevious );
|
||||
virtual void DeletePattern( const char *sPattern );
|
||||
|
||||
private:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Loading.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void LoadPatternFromXML( XmlNodeRef node,SPatternDef *pPattern );
|
||||
void LoadMoodFromXML( XmlNodeRef &node,SMusicMood *pMood );
|
||||
void LoadThemeFromXML( XmlNodeRef &node,SMusicTheme *pTheme );
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// String-vector-class to iterate data from other DLLs
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CStringItVec : public IStringItVec
|
||||
{
|
||||
public:
|
||||
CStringItVec(TStringVec &Vec)
|
||||
{
|
||||
m_nRefCount=0;
|
||||
m_Vec=Vec;
|
||||
MoveFirst();
|
||||
};
|
||||
bool IsEnd() { return (m_itVec==m_Vec.end()); };
|
||||
const char* Next() { return IsEnd() ? "" : (*m_itVec++).c_str(); };
|
||||
void MoveFirst() { m_itVec = m_Vec.begin(); };
|
||||
void AddRef() { m_nRefCount++; }
|
||||
void Release() { --m_nRefCount; if (m_nRefCount<=0) { delete this; } };
|
||||
protected:
|
||||
int m_nRefCount;
|
||||
TStringVec m_Vec;
|
||||
TStringVecIt m_itVec;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SmartCriticalSection-class to make things easier
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CSmartCriticalSection
|
||||
{
|
||||
private:
|
||||
CRITICAL_SECTION *m_pCS;
|
||||
public:
|
||||
CSmartCriticalSection(CRITICAL_SECTION &CS) { m_pCS=&CS; EnterCriticalSection(m_pCS); }
|
||||
~CSmartCriticalSection() { LeaveCriticalSection(m_pCS); }
|
||||
};
|
||||
263
CrySoundSystem/OGGDecoder.cpp
Normal file
263
CrySoundSystem/OGGDecoder.cpp
Normal file
@@ -0,0 +1,263 @@
|
||||
#include "StdAfx.h"
|
||||
#include <CrySizer.h>
|
||||
#include <ISound.h>
|
||||
#include <ISystem.h>
|
||||
#include <ICryPak.h>
|
||||
#include "oggdecoder.h"
|
||||
#include "MusicSystem.h"
|
||||
|
||||
COGGDecoder::COGGDecoder(IMusicSystem *pMusicSystem)
|
||||
{
|
||||
m_pMusicSystem=pMusicSystem;
|
||||
ISystem *pSystem=m_pMusicSystem->GetSystem();
|
||||
ASSERT(pSystem);
|
||||
m_FileAccess.pPak=pSystem->GetIPak();
|
||||
ASSERT(m_FileAccess.pPak);
|
||||
}
|
||||
|
||||
COGGDecoder::~COGGDecoder()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void getTicks(int64* pnTime)
|
||||
{
|
||||
#ifdef WIN64
|
||||
*pnTime = __rdtsc();
|
||||
#else
|
||||
__asm {
|
||||
mov ebx, pnTime
|
||||
rdtsc
|
||||
mov [ebx], eax
|
||||
mov [ebx+4], edx
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool COGGDecoder::Open(const char *pszFilename)
|
||||
{
|
||||
if (m_FileAccess.pFile)
|
||||
return false;
|
||||
m_FileAccess.pFile=m_FileAccess.pPak->FOpen(pszFilename, "rb");
|
||||
if (!m_FileAccess.pFile)
|
||||
return false;
|
||||
OggVorbis_File TestOVFile;
|
||||
ov_callbacks Callbacks;
|
||||
Callbacks.read_func=COGGDecoderInstance::ReadFile;
|
||||
Callbacks.seek_func=COGGDecoderInstance::SeekFile;
|
||||
Callbacks.close_func=COGGDecoderInstance::CloseFile;
|
||||
Callbacks.tell_func=COGGDecoderInstance::TellFile;
|
||||
if (ov_open_callbacks(&m_FileAccess, &TestOVFile, NULL, 0, Callbacks)!=0)
|
||||
return false;
|
||||
int nSeekable=ov_seekable(&TestOVFile);
|
||||
m_FileInfo.sFilename=pszFilename;
|
||||
m_FileInfo.nHeaderSize=0;
|
||||
m_FileInfo.nSamples=(int)ov_pcm_total(&TestOVFile, -1);
|
||||
// Throw the comments plus a few lines about the bitstream we're decoding
|
||||
MTRACE("File-information of %s...", m_FileInfo.sFilename.c_str());
|
||||
vorbis_comment *pComment=ov_comment(&TestOVFile, -1);
|
||||
vorbis_info *pInfo=ov_info(&TestOVFile, -1);
|
||||
char **pPtr=pComment->user_comments;
|
||||
while (*pPtr)
|
||||
{
|
||||
MTRACE(" %s", *pPtr);
|
||||
pPtr++;
|
||||
}
|
||||
MTRACE(" Bitstream is %d channel, %ld Hz, %d kbit/s", pInfo->channels, pInfo->rate, pInfo->bitrate_nominal/1000);
|
||||
MTRACE(" Encoded by: %s", pComment->vendor);
|
||||
if (pInfo->rate!=44100)
|
||||
{
|
||||
MTRACE("Warning: [COGGDecoder::Open()] Cannot load file %s, due to unsupported samplerate (%d Hz found; 44100 Hz needed) !", m_FileInfo.sFilename.c_str(), pInfo->rate);
|
||||
return false;
|
||||
}
|
||||
if (pInfo->channels!=2)
|
||||
{
|
||||
MTRACE("Warning: [COGGDecoder::Open()] Cannot load file %s, due to unsupported channel-number (%d channels found; 2 channels needed) !", m_FileInfo.sFilename.c_str(), pInfo->channels);
|
||||
return false;
|
||||
}
|
||||
if (ov_clear(&TestOVFile)!=0)
|
||||
return false;
|
||||
if (!nSeekable)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool COGGDecoder::Close()
|
||||
{
|
||||
if (!m_FileAccess.pFile)
|
||||
return false;
|
||||
m_FileAccess.pPak->FClose(m_FileAccess.pFile);
|
||||
m_FileAccess.pFile=NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool COGGDecoder::GetFileInfo(SMusicPatternFileInfo &FileInfo)
|
||||
{
|
||||
if (!m_FileAccess.pFile)
|
||||
return false;
|
||||
FileInfo=m_FileInfo;
|
||||
return true;
|
||||
}
|
||||
|
||||
void COGGDecoder::GetMemoryUsage(class ICrySizer* pSizer)
|
||||
{
|
||||
if (!pSizer->Add(*this))
|
||||
return;
|
||||
}
|
||||
|
||||
IMusicPatternDecoderInstance* COGGDecoder::CreateInstance()
|
||||
{
|
||||
return new COGGDecoderInstance(this);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
/*** INSTANCE ***/
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t COGGDecoderInstance::ReadFile(void *ptr, size_t size, size_t nmemb, void *datasource)
|
||||
{
|
||||
SFileAccess *pFileAccess=(SFileAccess*)datasource;
|
||||
return pFileAccess->pPak->FRead(ptr, size, nmemb, pFileAccess->pFile);
|
||||
}
|
||||
|
||||
int COGGDecoderInstance::SeekFile(void *datasource, ogg_int64_t offset, int whence)
|
||||
{
|
||||
SFileAccess *pFileAccess=(SFileAccess*)datasource;
|
||||
return pFileAccess->pPak->FSeek(pFileAccess->pFile, (long)offset, whence);
|
||||
}
|
||||
|
||||
int COGGDecoderInstance::CloseFile(void *datasource)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
long COGGDecoderInstance::TellFile(void *datasource)
|
||||
{
|
||||
SFileAccess *pFileAccess=(SFileAccess*)datasource;
|
||||
return pFileAccess->pPak->FTell(pFileAccess->pFile);
|
||||
}
|
||||
|
||||
COGGDecoderInstance::COGGDecoderInstance(COGGDecoder *pDecoder)
|
||||
{
|
||||
// int64 nStartTime, nEndTime;
|
||||
// getTicks(&nStartTime);
|
||||
ASSERT(pDecoder);
|
||||
m_pDecoder=pDecoder;
|
||||
m_pDecoder->m_FileAccess.pPak->FSeek(m_pDecoder->m_FileAccess.pFile, 0, SEEK_SET);
|
||||
ov_callbacks Callbacks;
|
||||
Callbacks.read_func=ReadFile;
|
||||
Callbacks.seek_func=SeekFile;
|
||||
Callbacks.close_func=CloseFile;
|
||||
Callbacks.tell_func=TellFile;
|
||||
if (ov_open_callbacks(&(m_pDecoder->m_FileAccess), &m_OVFile, NULL, 0, Callbacks)!=0)
|
||||
MTRACE("Warning: [COGGDecoderInstance::c_tor()] ov_open() failed !");
|
||||
// Seek0 is quite expensive for OGGs so we do a simpler version here instead...
|
||||
m_nPos=0;
|
||||
m_nPosBytes=m_pDecoder->m_FileAccess.pPak->FTell(m_pDecoder->m_FileAccess.pFile); // store current file-cursor
|
||||
// getTicks(&nEndTime);
|
||||
// MTRACE("Info: [COGGDecoderInstance::c_tor()] It took %d cycles to initialize ogg-decoder-instance of %s.", (long)(nEndTime-nStartTime), m_pDecoder->m_FileInfo.sFilename.c_str());
|
||||
}
|
||||
|
||||
COGGDecoderInstance::~COGGDecoderInstance()
|
||||
{
|
||||
if (ov_clear(&m_OVFile)!=0)
|
||||
MTRACE("Warning: [COGGDecoderInstance::d_tor()] ov_clear() failed !");
|
||||
}
|
||||
|
||||
bool COGGDecoderInstance::Seek0(int nDelay)
|
||||
{
|
||||
int nOldPos=m_nPos;
|
||||
m_nPos=-nDelay;
|
||||
if (nOldPos>0) // only seek if it is really necessary, since it takes some time on OGGs...
|
||||
{
|
||||
if (ov_pcm_seek(&m_OVFile, 0)!=0)
|
||||
return false;
|
||||
m_nPosBytes=m_pDecoder->m_FileAccess.pPak->FTell(m_pDecoder->m_FileAccess.pFile); // store current file-cursor
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int COGGDecoderInstance::GetPos()
|
||||
{
|
||||
if (!m_pDecoder->m_FileAccess.pFile)
|
||||
return -1;
|
||||
return m_nPos;
|
||||
}
|
||||
|
||||
bool COGGDecoderInstance::GetPCMData(signed long *pDataOut, int nSamples, bool bLoop)
|
||||
{
|
||||
if (!m_pDecoder->m_FileAccess.pFile)
|
||||
return false;
|
||||
int nOfs=0;
|
||||
if (m_nPos<0)
|
||||
{
|
||||
if (-m_nPos>=nSamples)
|
||||
{
|
||||
memset(pDataOut, 0, nSamples*m_pDecoder->m_pMusicSystem->GetBytesPerSample());
|
||||
m_nPos+=nSamples;
|
||||
return true;
|
||||
}else
|
||||
{
|
||||
nOfs=-m_nPos;
|
||||
m_nPos=0;
|
||||
nSamples-=nOfs;
|
||||
memset(pDataOut, 0, nOfs*m_pDecoder->m_pMusicSystem->GetBytesPerSample());
|
||||
}
|
||||
}
|
||||
// prepare file-cursor
|
||||
m_pDecoder->m_FileAccess.pPak->FSeek(m_pDecoder->m_FileAccess.pFile, m_nPosBytes, SEEK_SET);
|
||||
int nSamplesToRead;
|
||||
for (;;)
|
||||
{
|
||||
if ((m_nPos+nSamples)>m_pDecoder->m_FileInfo.nSamples)
|
||||
nSamplesToRead=m_pDecoder->m_FileInfo.nSamples-m_nPos;
|
||||
else
|
||||
nSamplesToRead=nSamples;
|
||||
if (!FillPCMBuffer(&(pDataOut[nOfs]), nSamplesToRead))
|
||||
return false;
|
||||
m_nPos+=nSamplesToRead;
|
||||
if (nSamplesToRead==nSamples)
|
||||
break;
|
||||
nOfs+=nSamplesToRead;
|
||||
if (!bLoop)
|
||||
{
|
||||
memset(&(pDataOut[nOfs]), 0, (nSamples-nSamplesToRead)*m_pDecoder->m_pMusicSystem->GetBytesPerSample());
|
||||
break;
|
||||
}
|
||||
nSamples-=nSamplesToRead;
|
||||
Seek0();
|
||||
}
|
||||
// store file-cursor
|
||||
m_nPosBytes=m_pDecoder->m_FileAccess.pPak->FTell(m_pDecoder->m_FileAccess.pFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool COGGDecoderInstance::FillPCMBuffer(signed long *pBuffer, int nSamples)
|
||||
{
|
||||
int nBytesToRead=nSamples*m_pDecoder->m_pMusicSystem->GetBytesPerSample();
|
||||
int nBytesRead=0;
|
||||
while (nBytesToRead>nBytesRead)
|
||||
{
|
||||
int nCurrStream=0;
|
||||
long nRet=ov_read(&m_OVFile, &((char*)pBuffer)[nBytesRead], nBytesToRead-nBytesRead, 0, 2, 1, &nCurrStream);
|
||||
if (nRet==OV_HOLE)
|
||||
{
|
||||
MTRACE("Warning: [COGGDecoderInstance::FillPCMBuffer] Hole found in stream %s !", m_pDecoder->m_FileInfo.sFilename.c_str());
|
||||
return false;
|
||||
}else
|
||||
if (nRet==OV_EBADLINK)
|
||||
{
|
||||
MTRACE("Warning: [COGGDecoderInstance::FillPCMBuffer] Bad link found in stream %s !", m_pDecoder->m_FileInfo.sFilename.c_str());
|
||||
return false;
|
||||
}else
|
||||
if (nRet==0)
|
||||
{
|
||||
MTRACE("Warning: [COGGDecoderInstance::FillPCMBuffer] Unexpected end of stream %s !", m_pDecoder->m_FileInfo.sFilename.c_str());
|
||||
return false;
|
||||
}else
|
||||
{
|
||||
nBytesRead+=nRet;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
74
CrySoundSystem/OGGDecoder.h
Normal file
74
CrySoundSystem/OGGDecoder.h
Normal file
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include "PatternDecoder.h"
|
||||
#include <vorbis/vorbisfile.h>
|
||||
|
||||
struct IMusicSystem;
|
||||
class COGGDecoderInstance;
|
||||
|
||||
struct SFileAccess
|
||||
{
|
||||
SFileAccess()
|
||||
{
|
||||
pPak=NULL;
|
||||
pFile=NULL;
|
||||
}
|
||||
SFileAccess(ICryPak *_pPak, FILE *_pFile)
|
||||
{
|
||||
pPak=_pPak;
|
||||
pFile=_pFile;
|
||||
}
|
||||
ICryPak *pPak;
|
||||
FILE *pFile;
|
||||
};
|
||||
|
||||
class COGGDecoder : public IMusicPatternDecoder
|
||||
{
|
||||
protected:
|
||||
IMusicSystem *m_pMusicSystem;
|
||||
SFileAccess m_FileAccess;
|
||||
SMusicPatternFileInfo m_FileInfo;
|
||||
friend class COGGDecoderInstance;
|
||||
protected:
|
||||
virtual ~COGGDecoder();
|
||||
public:
|
||||
COGGDecoder(IMusicSystem *pMusicSystem);
|
||||
void Release() { delete this; }
|
||||
//! Open a music-pattern-file.
|
||||
bool Open(const char *pszFilename);
|
||||
//! Close a music-pattern-file.
|
||||
bool Close();
|
||||
//! Retrieve file-info
|
||||
bool GetFileInfo(SMusicPatternFileInfo &FileInfo);
|
||||
//! Retrieve mem-info
|
||||
void GetMemoryUsage(class ICrySizer* pSizer);
|
||||
//! Create instance.
|
||||
IMusicPatternDecoderInstance* CreateInstance();
|
||||
};
|
||||
|
||||
class COGGDecoderInstance : public IMusicPatternDecoderInstance
|
||||
{
|
||||
protected:
|
||||
COGGDecoder *m_pDecoder;
|
||||
int m_nPos; // position in samples
|
||||
int m_nPosBytes;
|
||||
OggVorbis_File m_OVFile;
|
||||
private:
|
||||
bool FillPCMBuffer(signed long *pBuffer, int nSamples);
|
||||
public:
|
||||
static size_t ReadFile(void *ptr, size_t size, size_t nmemb, void *datasource);
|
||||
static int SeekFile(void *datasource, ogg_int64_t offset, int whence);
|
||||
static int CloseFile(void *datasource);
|
||||
static long TellFile(void *datasource);
|
||||
protected:
|
||||
virtual ~COGGDecoderInstance();
|
||||
public:
|
||||
COGGDecoderInstance(COGGDecoder *pDecoder);
|
||||
void Release() { delete this; }
|
||||
//! Seek to beginning of pattern (if nDelay is set it will wait nDelay-samples before starting playback).
|
||||
bool Seek0(int nDelay=0);
|
||||
//! Retrieve the current position in the file (in samples)
|
||||
int GetPos();
|
||||
//! Decode and retrieve pcm-data (stereo/16bit).
|
||||
bool GetPCMData(signed long *pDataOut, int nSamples, bool bLoop=true);
|
||||
};
|
||||
184
CrySoundSystem/OggVorbisInclude/ogg/ogg.h
Normal file
184
CrySoundSystem/OggVorbisInclude/ogg/ogg.h
Normal file
@@ -0,0 +1,184 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: toplevel libogg include
|
||||
last mod: $Id: ogg.h,v 1.18 2002/07/13 10:28:33 giles Exp $
|
||||
|
||||
********************************************************************/
|
||||
#ifndef _OGG_H
|
||||
#define _OGG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <ogg/os_types.h>
|
||||
|
||||
typedef struct {
|
||||
long endbyte;
|
||||
int endbit;
|
||||
|
||||
unsigned char *buffer;
|
||||
unsigned char *ptr;
|
||||
long storage;
|
||||
} oggpack_buffer;
|
||||
|
||||
/* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/
|
||||
|
||||
typedef struct {
|
||||
unsigned char *header;
|
||||
long header_len;
|
||||
unsigned char *body;
|
||||
long body_len;
|
||||
} ogg_page;
|
||||
|
||||
/* ogg_stream_state contains the current encode/decode state of a logical
|
||||
Ogg bitstream **********************************************************/
|
||||
|
||||
typedef struct {
|
||||
unsigned char *body_data; /* bytes from packet bodies */
|
||||
long body_storage; /* storage elements allocated */
|
||||
long body_fill; /* elements stored; fill mark */
|
||||
long body_returned; /* elements of fill returned */
|
||||
|
||||
|
||||
int *lacing_vals; /* The values that will go to the segment table */
|
||||
ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact
|
||||
this way, but it is simple coupled to the
|
||||
lacing fifo */
|
||||
long lacing_storage;
|
||||
long lacing_fill;
|
||||
long lacing_packet;
|
||||
long lacing_returned;
|
||||
|
||||
unsigned char header[282]; /* working space for header encode */
|
||||
int header_fill;
|
||||
|
||||
int e_o_s; /* set when we have buffered the last packet in the
|
||||
logical bitstream */
|
||||
int b_o_s; /* set after we've written the initial page
|
||||
of a logical bitstream */
|
||||
long serialno;
|
||||
long pageno;
|
||||
ogg_int64_t packetno; /* sequence number for decode; the framing
|
||||
knows where there's a hole in the data,
|
||||
but we need coupling so that the codec
|
||||
(which is in a seperate abstraction
|
||||
layer) also knows about the gap */
|
||||
ogg_int64_t granulepos;
|
||||
|
||||
} ogg_stream_state;
|
||||
|
||||
/* ogg_packet is used to encapsulate the data and metadata belonging
|
||||
to a single raw Ogg/Vorbis packet *************************************/
|
||||
|
||||
typedef struct {
|
||||
unsigned char *packet;
|
||||
long bytes;
|
||||
long b_o_s;
|
||||
long e_o_s;
|
||||
|
||||
ogg_int64_t granulepos;
|
||||
|
||||
ogg_int64_t packetno; /* sequence number for decode; the framing
|
||||
knows where there's a hole in the data,
|
||||
but we need coupling so that the codec
|
||||
(which is in a seperate abstraction
|
||||
layer) also knows about the gap */
|
||||
} ogg_packet;
|
||||
|
||||
typedef struct {
|
||||
unsigned char *data;
|
||||
int storage;
|
||||
int fill;
|
||||
int returned;
|
||||
|
||||
int unsynced;
|
||||
int headerbytes;
|
||||
int bodybytes;
|
||||
} ogg_sync_state;
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/
|
||||
|
||||
extern void oggpack_writeinit(oggpack_buffer *b);
|
||||
extern void oggpack_writetrunc(oggpack_buffer *b,long bits);
|
||||
extern void oggpack_writealign(oggpack_buffer *b);
|
||||
extern void oggpack_writecopy(oggpack_buffer *b,void *source,long bits);
|
||||
extern void oggpack_reset(oggpack_buffer *b);
|
||||
extern void oggpack_writeclear(oggpack_buffer *b);
|
||||
extern void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
|
||||
extern void oggpack_write(oggpack_buffer *b,unsigned long value,int bits);
|
||||
extern long oggpack_look(oggpack_buffer *b,int bits);
|
||||
extern long oggpack_look1(oggpack_buffer *b);
|
||||
extern void oggpack_adv(oggpack_buffer *b,int bits);
|
||||
extern void oggpack_adv1(oggpack_buffer *b);
|
||||
extern long oggpack_read(oggpack_buffer *b,int bits);
|
||||
extern long oggpack_read1(oggpack_buffer *b);
|
||||
extern long oggpack_bytes(oggpack_buffer *b);
|
||||
extern long oggpack_bits(oggpack_buffer *b);
|
||||
extern unsigned char *oggpack_get_buffer(oggpack_buffer *b);
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: encoding **************************/
|
||||
|
||||
extern int ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op);
|
||||
extern int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og);
|
||||
extern int ogg_stream_flush(ogg_stream_state *os, ogg_page *og);
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: decoding **************************/
|
||||
|
||||
extern int ogg_sync_init(ogg_sync_state *oy);
|
||||
extern int ogg_sync_clear(ogg_sync_state *oy);
|
||||
extern int ogg_sync_reset(ogg_sync_state *oy);
|
||||
extern int ogg_sync_destroy(ogg_sync_state *oy);
|
||||
|
||||
extern char *ogg_sync_buffer(ogg_sync_state *oy, long size);
|
||||
extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes);
|
||||
extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og);
|
||||
extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og);
|
||||
extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og);
|
||||
extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op);
|
||||
extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op);
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: general ***************************/
|
||||
|
||||
extern int ogg_stream_init(ogg_stream_state *os,int serialno);
|
||||
extern int ogg_stream_clear(ogg_stream_state *os);
|
||||
extern int ogg_stream_reset(ogg_stream_state *os);
|
||||
extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno);
|
||||
extern int ogg_stream_destroy(ogg_stream_state *os);
|
||||
extern int ogg_stream_eos(ogg_stream_state *os);
|
||||
|
||||
extern void ogg_page_checksum_set(ogg_page *og);
|
||||
|
||||
extern int ogg_page_version(ogg_page *og);
|
||||
extern int ogg_page_continued(ogg_page *og);
|
||||
extern int ogg_page_bos(ogg_page *og);
|
||||
extern int ogg_page_eos(ogg_page *og);
|
||||
extern ogg_int64_t ogg_page_granulepos(ogg_page *og);
|
||||
extern int ogg_page_serialno(ogg_page *og);
|
||||
extern long ogg_page_pageno(ogg_page *og);
|
||||
extern int ogg_page_packets(ogg_page *og);
|
||||
|
||||
extern void ogg_packet_clear(ogg_packet *op);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _OGG_H */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
84
CrySoundSystem/OggVorbisInclude/ogg/os_types.h
Normal file
84
CrySoundSystem/OggVorbisInclude/ogg/os_types.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: #ifdef jail to whip a few platforms into the UNIX ideal.
|
||||
last mod: $Id: os_types.h,v 1.11 2002/07/19 08:25:51 msmith Exp $
|
||||
|
||||
********************************************************************/
|
||||
#ifndef _OS_TYPES_H
|
||||
#define _OS_TYPES_H
|
||||
|
||||
/* make it easy on the folks that want to compile the libs with a
|
||||
different malloc than stdlib */
|
||||
#define _ogg_malloc malloc
|
||||
#define _ogg_calloc calloc
|
||||
#define _ogg_realloc realloc
|
||||
#define _ogg_free free
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
# ifndef __GNUC__
|
||||
/* MSVC/Borland */
|
||||
typedef __int64 ogg_int64_t;
|
||||
typedef __int32 ogg_int32_t;
|
||||
typedef unsigned __int32 ogg_uint32_t;
|
||||
typedef __int16 ogg_int16_t;
|
||||
# else
|
||||
/* Cygwin */
|
||||
#include <_G_config.h>
|
||||
typedef _G_int64_t ogg_int64_t;
|
||||
typedef _G_int32_t ogg_int32_t;
|
||||
typedef _G_uint32_t ogg_uint32_t;
|
||||
typedef _G_int16_t ogg_int16_t;
|
||||
# endif
|
||||
|
||||
#elif defined(__MACOS__)
|
||||
|
||||
# include <sys/types.h>
|
||||
typedef SInt16 ogg_int16_t;
|
||||
typedef SInt32 ogg_int32_t;
|
||||
typedef UInt32 ogg_uint32_t;
|
||||
typedef SInt64 ogg_int64_t;
|
||||
|
||||
#elif defined(__MACOSX__) /* MacOS X Framework build */
|
||||
|
||||
# include <sys/types.h>
|
||||
typedef int16_t ogg_int16_t;
|
||||
typedef int32_t ogg_int32_t;
|
||||
typedef u_int32_t ogg_uint32_t;
|
||||
typedef int64_t ogg_int64_t;
|
||||
|
||||
#elif defined(__BEOS__)
|
||||
|
||||
/* Be */
|
||||
# include <inttypes.h>
|
||||
typedef int16_t ogg_int16_t;
|
||||
typedef int32_t ogg_int32_t;
|
||||
typedef u_int32_t ogg_uint32_t;
|
||||
typedef int64_t ogg_int64_t;
|
||||
|
||||
#elif defined (__EMX__)
|
||||
|
||||
/* OS/2 GCC */
|
||||
typedef short ogg_int16_t;
|
||||
typedef int ogg_int32_t;
|
||||
typedef unsigned int ogg_uint32_t;
|
||||
typedef long long ogg_int64_t;
|
||||
|
||||
#else
|
||||
|
||||
# include <sys/types.h>
|
||||
# include <ogg/config_types.h>
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _OS_TYPES_H */
|
||||
233
CrySoundSystem/OggVorbisInclude/vorbis/codec.h
Normal file
233
CrySoundSystem/OggVorbisInclude/vorbis/codec.h
Normal file
@@ -0,0 +1,233 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
|
||||
* by the XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
|
||||
********************************************************************
|
||||
|
||||
function: libvorbis codec headers
|
||||
last mod: $Id: codec.h,v 1.40 2002/02/28 04:12:47 xiphmont Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _vorbis_codec_h_
|
||||
#define _vorbis_codec_h_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include <ogg/ogg.h>
|
||||
|
||||
typedef struct vorbis_info{
|
||||
int version;
|
||||
int channels;
|
||||
long rate;
|
||||
|
||||
/* The below bitrate declarations are *hints*.
|
||||
Combinations of the three values carry the following implications:
|
||||
|
||||
all three set to the same value:
|
||||
implies a fixed rate bitstream
|
||||
only nominal set:
|
||||
implies a VBR stream that averages the nominal bitrate. No hard
|
||||
upper/lower limit
|
||||
upper and or lower set:
|
||||
implies a VBR bitstream that obeys the bitrate limits. nominal
|
||||
may also be set to give a nominal rate.
|
||||
none set:
|
||||
the coder does not care to speculate.
|
||||
*/
|
||||
|
||||
long bitrate_upper;
|
||||
long bitrate_nominal;
|
||||
long bitrate_lower;
|
||||
long bitrate_window;
|
||||
|
||||
void *codec_setup;
|
||||
} vorbis_info;
|
||||
|
||||
/* vorbis_dsp_state buffers the current vorbis audio
|
||||
analysis/synthesis state. The DSP state belongs to a specific
|
||||
logical bitstream ****************************************************/
|
||||
typedef struct vorbis_dsp_state{
|
||||
int analysisp;
|
||||
vorbis_info *vi;
|
||||
|
||||
float **pcm;
|
||||
float **pcmret;
|
||||
int pcm_storage;
|
||||
int pcm_current;
|
||||
int pcm_returned;
|
||||
|
||||
int preextrapolate;
|
||||
int eofflag;
|
||||
|
||||
long lW;
|
||||
long W;
|
||||
long nW;
|
||||
long centerW;
|
||||
|
||||
ogg_int64_t granulepos;
|
||||
ogg_int64_t sequence;
|
||||
|
||||
ogg_int64_t glue_bits;
|
||||
ogg_int64_t time_bits;
|
||||
ogg_int64_t floor_bits;
|
||||
ogg_int64_t res_bits;
|
||||
|
||||
void *backend_state;
|
||||
} vorbis_dsp_state;
|
||||
|
||||
typedef struct vorbis_block{
|
||||
/* necessary stream state for linking to the framing abstraction */
|
||||
float **pcm; /* this is a pointer into local storage */
|
||||
oggpack_buffer opb;
|
||||
|
||||
long lW;
|
||||
long W;
|
||||
long nW;
|
||||
int pcmend;
|
||||
int mode;
|
||||
|
||||
int eofflag;
|
||||
ogg_int64_t granulepos;
|
||||
ogg_int64_t sequence;
|
||||
vorbis_dsp_state *vd; /* For read-only access of configuration */
|
||||
|
||||
/* local storage to avoid remallocing; it's up to the mapping to
|
||||
structure it */
|
||||
void *localstore;
|
||||
long localtop;
|
||||
long localalloc;
|
||||
long totaluse;
|
||||
struct alloc_chain *reap;
|
||||
|
||||
/* bitmetrics for the frame */
|
||||
long glue_bits;
|
||||
long time_bits;
|
||||
long floor_bits;
|
||||
long res_bits;
|
||||
|
||||
void *internal;
|
||||
|
||||
} vorbis_block;
|
||||
|
||||
/* vorbis_block is a single block of data to be processed as part of
|
||||
the analysis/synthesis stream; it belongs to a specific logical
|
||||
bitstream, but is independant from other vorbis_blocks belonging to
|
||||
that logical bitstream. *************************************************/
|
||||
|
||||
struct alloc_chain{
|
||||
void *ptr;
|
||||
struct alloc_chain *next;
|
||||
};
|
||||
|
||||
/* vorbis_info contains all the setup information specific to the
|
||||
specific compression/decompression mode in progress (eg,
|
||||
psychoacoustic settings, channel setup, options, codebook
|
||||
etc). vorbis_info and substructures are in backends.h.
|
||||
*********************************************************************/
|
||||
|
||||
/* the comments are not part of vorbis_info so that vorbis_info can be
|
||||
static storage */
|
||||
typedef struct vorbis_comment{
|
||||
/* unlimited user comment fields. libvorbis writes 'libvorbis'
|
||||
whatever vendor is set to in encode */
|
||||
char **user_comments;
|
||||
int *comment_lengths;
|
||||
int comments;
|
||||
char *vendor;
|
||||
|
||||
} vorbis_comment;
|
||||
|
||||
|
||||
/* libvorbis encodes in two abstraction layers; first we perform DSP
|
||||
and produce a packet (see docs/analysis.txt). The packet is then
|
||||
coded into a framed OggSquish bitstream by the second layer (see
|
||||
docs/framing.txt). Decode is the reverse process; we sync/frame
|
||||
the bitstream and extract individual packets, then decode the
|
||||
packet back into PCM audio.
|
||||
|
||||
The extra framing/packetizing is used in streaming formats, such as
|
||||
files. Over the net (such as with UDP), the framing and
|
||||
packetization aren't necessary as they're provided by the transport
|
||||
and the streaming layer is not used */
|
||||
|
||||
/* Vorbis PRIMITIVES: general ***************************************/
|
||||
|
||||
extern void vorbis_info_init(vorbis_info *vi);
|
||||
extern void vorbis_info_clear(vorbis_info *vi);
|
||||
extern int vorbis_info_blocksize(vorbis_info *vi,int zo);
|
||||
extern void vorbis_comment_init(vorbis_comment *vc);
|
||||
extern void vorbis_comment_add(vorbis_comment *vc, char *comment);
|
||||
extern void vorbis_comment_add_tag(vorbis_comment *vc,
|
||||
char *tag, char *contents);
|
||||
extern char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count);
|
||||
extern int vorbis_comment_query_count(vorbis_comment *vc, char *tag);
|
||||
extern void vorbis_comment_clear(vorbis_comment *vc);
|
||||
|
||||
extern int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb);
|
||||
extern int vorbis_block_clear(vorbis_block *vb);
|
||||
extern void vorbis_dsp_clear(vorbis_dsp_state *v);
|
||||
|
||||
/* Vorbis PRIMITIVES: analysis/DSP layer ****************************/
|
||||
|
||||
extern int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi);
|
||||
extern int vorbis_commentheader_out(vorbis_comment *vc, ogg_packet *op);
|
||||
extern int vorbis_analysis_headerout(vorbis_dsp_state *v,
|
||||
vorbis_comment *vc,
|
||||
ogg_packet *op,
|
||||
ogg_packet *op_comm,
|
||||
ogg_packet *op_code);
|
||||
extern float **vorbis_analysis_buffer(vorbis_dsp_state *v,int vals);
|
||||
extern int vorbis_analysis_wrote(vorbis_dsp_state *v,int vals);
|
||||
extern int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb);
|
||||
extern int vorbis_analysis(vorbis_block *vb,ogg_packet *op);
|
||||
|
||||
extern int vorbis_bitrate_addblock(vorbis_block *vb);
|
||||
extern int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd,
|
||||
ogg_packet *op);
|
||||
|
||||
/* Vorbis PRIMITIVES: synthesis layer *******************************/
|
||||
extern int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,
|
||||
ogg_packet *op);
|
||||
|
||||
extern int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi);
|
||||
extern int vorbis_synthesis(vorbis_block *vb,ogg_packet *op);
|
||||
extern int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op);
|
||||
extern int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb);
|
||||
extern int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm);
|
||||
extern int vorbis_synthesis_read(vorbis_dsp_state *v,int samples);
|
||||
extern long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op);
|
||||
|
||||
/* Vorbis ERRORS and return codes ***********************************/
|
||||
|
||||
#define OV_FALSE -1
|
||||
#define OV_EOF -2
|
||||
#define OV_HOLE -3
|
||||
|
||||
#define OV_EREAD -128
|
||||
#define OV_EFAULT -129
|
||||
#define OV_EIMPL -130
|
||||
#define OV_EINVAL -131
|
||||
#define OV_ENOTVORBIS -132
|
||||
#define OV_EBADHEADER -133
|
||||
#define OV_EVERSION -134
|
||||
#define OV_ENOTAUDIO -135
|
||||
#define OV_EBADPACKET -136
|
||||
#define OV_EBADLINK -137
|
||||
#define OV_ENOSEEK -138
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
|
||||
93
CrySoundSystem/OggVorbisInclude/vorbis/vorbisenc.h
Normal file
93
CrySoundSystem/OggVorbisInclude/vorbis/vorbisenc.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
|
||||
* by the XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: vorbis encode-engine setup
|
||||
last mod: $Id: vorbisenc.h,v 1.10 2002/07/01 11:20:10 xiphmont Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _OV_ENC_H_
|
||||
#define _OV_ENC_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include "codec.h"
|
||||
|
||||
extern int vorbis_encode_init(vorbis_info *vi,
|
||||
long channels,
|
||||
long rate,
|
||||
|
||||
long max_bitrate,
|
||||
long nominal_bitrate,
|
||||
long min_bitrate);
|
||||
|
||||
extern int vorbis_encode_setup_managed(vorbis_info *vi,
|
||||
long channels,
|
||||
long rate,
|
||||
|
||||
long max_bitrate,
|
||||
long nominal_bitrate,
|
||||
long min_bitrate);
|
||||
|
||||
extern int vorbis_encode_setup_vbr(vorbis_info *vi,
|
||||
long channels,
|
||||
long rate,
|
||||
|
||||
float /* quality level from 0. (lo) to 1. (hi) */
|
||||
);
|
||||
|
||||
extern int vorbis_encode_init_vbr(vorbis_info *vi,
|
||||
long channels,
|
||||
long rate,
|
||||
|
||||
float base_quality /* quality level from 0. (lo) to 1. (hi) */
|
||||
);
|
||||
|
||||
extern int vorbis_encode_setup_init(vorbis_info *vi);
|
||||
|
||||
extern int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg);
|
||||
|
||||
#define OV_ECTL_RATEMANAGE_GET 0x10
|
||||
|
||||
#define OV_ECTL_RATEMANAGE_SET 0x11
|
||||
#define OV_ECTL_RATEMANAGE_AVG 0x12
|
||||
#define OV_ECTL_RATEMANAGE_HARD 0x13
|
||||
|
||||
#define OV_ECTL_LOWPASS_GET 0x20
|
||||
#define OV_ECTL_LOWPASS_SET 0x21
|
||||
|
||||
#define OV_ECTL_IBLOCK_GET 0x30
|
||||
#define OV_ECTL_IBLOCK_SET 0x31
|
||||
|
||||
struct ovectl_ratemanage_arg {
|
||||
int management_active;
|
||||
|
||||
long bitrate_hard_min;
|
||||
long bitrate_hard_max;
|
||||
double bitrate_hard_window;
|
||||
|
||||
long bitrate_av_lo;
|
||||
long bitrate_av_hi;
|
||||
double bitrate_av_window;
|
||||
double bitrate_av_window_center;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
133
CrySoundSystem/OggVorbisInclude/vorbis/vorbisfile.h
Normal file
133
CrySoundSystem/OggVorbisInclude/vorbis/vorbisfile.h
Normal file
@@ -0,0 +1,133 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
|
||||
* by the XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: stdio-based convenience library for opening/seeking/decoding
|
||||
last mod: $Id: vorbisfile.h,v 1.17 2002/03/07 03:41:03 xiphmont Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _OV_FILE_H_
|
||||
#define _OV_FILE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "codec.h"
|
||||
|
||||
/* The function prototypes for the callbacks are basically the same as for
|
||||
* the stdio functions fread, fseek, fclose, ftell.
|
||||
* The one difference is that the FILE * arguments have been replaced with
|
||||
* a void * - this is to be used as a pointer to whatever internal data these
|
||||
* functions might need. In the stdio case, it's just a FILE * cast to a void *
|
||||
*
|
||||
* If you use other functions, check the docs for these functions and return
|
||||
* the right values. For seek_func(), you *MUST* return -1 if the stream is
|
||||
* unseekable
|
||||
*/
|
||||
typedef struct {
|
||||
size_t (*read_func) (void *ptr, size_t size, size_t nmemb, void *datasource);
|
||||
int (*seek_func) (void *datasource, ogg_int64_t offset, int whence);
|
||||
int (*close_func) (void *datasource);
|
||||
long (*tell_func) (void *datasource);
|
||||
} ov_callbacks;
|
||||
|
||||
#define NOTOPEN 0
|
||||
#define PARTOPEN 1
|
||||
#define OPENED 2
|
||||
#define STREAMSET 3
|
||||
#define INITSET 4
|
||||
|
||||
typedef struct OggVorbis_File {
|
||||
void *datasource; /* Pointer to a FILE *, etc. */
|
||||
int seekable;
|
||||
ogg_int64_t offset;
|
||||
ogg_int64_t end;
|
||||
ogg_sync_state oy;
|
||||
|
||||
/* If the FILE handle isn't seekable (eg, a pipe), only the current
|
||||
stream appears */
|
||||
int links;
|
||||
ogg_int64_t *offsets;
|
||||
ogg_int64_t *dataoffsets;
|
||||
long *serialnos;
|
||||
ogg_int64_t *pcmlengths; /* overloaded to maintain binary
|
||||
compatability; x2 size, stores both
|
||||
beginning and end values */
|
||||
vorbis_info *vi;
|
||||
vorbis_comment *vc;
|
||||
|
||||
/* Decoding working state local storage */
|
||||
ogg_int64_t pcm_offset;
|
||||
int ready_state;
|
||||
long current_serialno;
|
||||
int current_link;
|
||||
|
||||
double bittrack;
|
||||
double samptrack;
|
||||
|
||||
ogg_stream_state os; /* take physical pages, weld into a logical
|
||||
stream of packets */
|
||||
vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
|
||||
vorbis_block vb; /* local working space for packet->PCM decode */
|
||||
|
||||
ov_callbacks callbacks;
|
||||
|
||||
} OggVorbis_File;
|
||||
|
||||
extern int ov_clear(OggVorbis_File *vf);
|
||||
extern int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes);
|
||||
extern int ov_open_callbacks(void *datasource, OggVorbis_File *vf,
|
||||
char *initial, long ibytes, ov_callbacks callbacks);
|
||||
|
||||
extern int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes);
|
||||
extern int ov_test_callbacks(void *datasource, OggVorbis_File *vf,
|
||||
char *initial, long ibytes, ov_callbacks callbacks);
|
||||
extern int ov_test_open(OggVorbis_File *vf);
|
||||
|
||||
extern long ov_bitrate(OggVorbis_File *vf,int i);
|
||||
extern long ov_bitrate_instant(OggVorbis_File *vf);
|
||||
extern long ov_streams(OggVorbis_File *vf);
|
||||
extern long ov_seekable(OggVorbis_File *vf);
|
||||
extern long ov_serialnumber(OggVorbis_File *vf,int i);
|
||||
|
||||
extern ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i);
|
||||
extern ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i);
|
||||
extern double ov_time_total(OggVorbis_File *vf,int i);
|
||||
|
||||
extern int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos);
|
||||
extern int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos);
|
||||
extern int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos);
|
||||
extern int ov_time_seek(OggVorbis_File *vf,double pos);
|
||||
extern int ov_time_seek_page(OggVorbis_File *vf,double pos);
|
||||
|
||||
extern ogg_int64_t ov_raw_tell(OggVorbis_File *vf);
|
||||
extern ogg_int64_t ov_pcm_tell(OggVorbis_File *vf);
|
||||
extern double ov_time_tell(OggVorbis_File *vf);
|
||||
|
||||
extern vorbis_info *ov_info(OggVorbis_File *vf,int link);
|
||||
extern vorbis_comment *ov_comment(OggVorbis_File *vf,int link);
|
||||
|
||||
extern long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int samples,
|
||||
int *bitstream);
|
||||
extern long ov_read(OggVorbis_File *vf,char *buffer,int length,
|
||||
int bigendianp,int word,int sgned,int *bitstream);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
280
CrySoundSystem/PCMDecoder.cpp
Normal file
280
CrySoundSystem/PCMDecoder.cpp
Normal file
@@ -0,0 +1,280 @@
|
||||
#include "StdAfx.h"
|
||||
#include <CrySizer.h>
|
||||
#include <ISound.h>
|
||||
#include <ISystem.h>
|
||||
#include <ICryPak.h>
|
||||
#include "pcmdecoder.h"
|
||||
|
||||
CPCMDecoder::CPCMDecoder(IMusicSystem *pMusicSystem) : m_b44KHz(true)
|
||||
{
|
||||
m_pMusicSystem=pMusicSystem;
|
||||
ISystem *pSystem=m_pMusicSystem->GetSystem();
|
||||
ASSERT(pSystem);
|
||||
m_pPak=pSystem->GetIPak();
|
||||
ASSERT(m_pPak);
|
||||
m_pFile=NULL;
|
||||
}
|
||||
|
||||
CPCMDecoder::~CPCMDecoder()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
int CPCMDecoder::ReadFile(void *pBuf, int nSize, int nCount, int *pNewFilePos)
|
||||
{
|
||||
if (!m_pFile)
|
||||
return false;
|
||||
int nBytesRead=m_pPak->FRead(pBuf, nSize, nCount, m_pFile);
|
||||
if (nBytesRead!=nCount)
|
||||
{
|
||||
m_nPosBytes=m_pPak->FTell(m_pFile);
|
||||
if (pNewFilePos)
|
||||
*pNewFilePos=m_nPosBytes;
|
||||
return 0;
|
||||
}
|
||||
m_nPosBytes+=nSize*nCount;
|
||||
if (pNewFilePos)
|
||||
*pNewFilePos=m_nPosBytes;
|
||||
return nBytesRead;
|
||||
}
|
||||
|
||||
bool CPCMDecoder::InitStreamWAV()
|
||||
{
|
||||
if (!m_pFile)
|
||||
return false;
|
||||
SWaveHdr WaveHeader;
|
||||
if (!ReadFile(&WaveHeader, sizeof(SWaveHdr), 1))
|
||||
return false;
|
||||
if (WaveHeader.dwDSize==0)
|
||||
{
|
||||
TRACE("Warning: [CPCMDecoder::InitStreamWAV()] Cannot load file %s, due to zero-data-size !", m_FileInfo.sFilename.c_str());
|
||||
return false;
|
||||
}
|
||||
/* if (WaveHeader.dwSRate!=44100)
|
||||
{
|
||||
TRACE("Warning: [CPCMDecoder::InitStreamWAV()] Cannot load file %s, due to unsupported samplerate (%d Hz found; 44100 Hz needed) !", m_FileInfo.sFilename.c_str(), WaveHeader.dwSRate);
|
||||
return false;
|
||||
}
|
||||
*/ if (WaveHeader.wChnls!=2)
|
||||
{
|
||||
TRACE("Warning: [CPCMDecoder::InitStreamWAV()] Cannot load file %s, due to unsupported channel-number (%d channels found; 2 channels needed) !", m_FileInfo.sFilename.c_str(), WaveHeader.wChnls);
|
||||
return false;
|
||||
}
|
||||
if (WaveHeader.BitsPerSample!=16)
|
||||
{
|
||||
TRACE("Warning: [CPCMDecoder::InitStreamWAV()] Cannot load file %s, due to unsupported resolution (%d bits/sample found; 16 bits/sample needed) !", m_FileInfo.sFilename.c_str(), WaveHeader.BitsPerSample);
|
||||
return false;
|
||||
}
|
||||
m_PCMFileInfo.nBytesPerSample=WaveHeader.BitsPerSample/8*WaveHeader.wChnls;
|
||||
m_FileInfo.nHeaderSize=sizeof(SWaveHdr);
|
||||
m_FileInfo.nSamples=WaveHeader.dwDSize/m_PCMFileInfo.nBytesPerSample;
|
||||
if(WaveHeader.dwSRate == 22050)
|
||||
{
|
||||
m_FileInfo.nSamples *= 2; //correct number if different in 22 KHz mode due to different file size
|
||||
m_b44KHz = false;
|
||||
}
|
||||
else
|
||||
m_b44KHz = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPCMDecoder::Open(const char *pszFilename)
|
||||
{
|
||||
if (m_pFile)
|
||||
return false;
|
||||
m_pFile=m_pPak->FOpen(pszFilename, "rb");
|
||||
if (!m_pFile)
|
||||
return false;
|
||||
m_nPosBytes=0;
|
||||
m_FileInfo.sFilename=pszFilename;
|
||||
if (!InitStreamWAV())
|
||||
{
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPCMDecoder::Close()
|
||||
{
|
||||
if (!m_pFile)
|
||||
return false;
|
||||
m_pPak->FClose(m_pFile);
|
||||
m_pFile=NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPCMDecoder::GetFileInfo(SMusicPatternFileInfo &FileInfo)
|
||||
{
|
||||
if (!m_pFile)
|
||||
return false;
|
||||
FileInfo=m_FileInfo;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CPCMDecoder::GetMemoryUsage(class ICrySizer* pSizer)
|
||||
{
|
||||
if (!pSizer->Add(*this))
|
||||
return;
|
||||
}
|
||||
|
||||
IMusicPatternDecoderInstance* CPCMDecoder::CreateInstance()
|
||||
{
|
||||
return new CPCMDecoderInstance(this);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
/*** INSTANCE ***/
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CPCMDecoderInstance::CPCMDecoderInstance(CPCMDecoder *pDecoder) : m_bCopyFromLastFrame(false)
|
||||
{
|
||||
m_pDecoder=pDecoder;
|
||||
Seek0();
|
||||
}
|
||||
|
||||
CPCMDecoderInstance::~CPCMDecoderInstance()
|
||||
{
|
||||
}
|
||||
|
||||
bool CPCMDecoderInstance::SeekBytes(int nBytes)
|
||||
{
|
||||
if (!m_pDecoder->m_pFile)
|
||||
return false;
|
||||
m_nPosBytes=nBytes;
|
||||
if (m_pDecoder->m_nPosBytes==nBytes)
|
||||
return true;
|
||||
if (m_pDecoder->m_pPak->FSeek(m_pDecoder->m_pFile, nBytes, SEEK_SET)!=0)
|
||||
return false;
|
||||
m_pDecoder->m_nPosBytes=nBytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPCMDecoderInstance::Seek0(int nDelay)
|
||||
{
|
||||
m_nPos=-nDelay;
|
||||
m_bCopyFromLastFrame = false;
|
||||
return SeekBytes(m_pDecoder->m_FileInfo.nHeaderSize);
|
||||
}
|
||||
|
||||
int CPCMDecoderInstance::GetPos()
|
||||
{
|
||||
if (!m_pDecoder->m_pFile)
|
||||
return -1;
|
||||
return m_nPos;
|
||||
}
|
||||
|
||||
bool CPCMDecoderInstance::GetPCMData(signed long *pDataOut, int nSamples, bool bLoop)
|
||||
{
|
||||
if (!m_pDecoder->m_pFile)
|
||||
return false;
|
||||
int nOfs=0;
|
||||
if (m_nPos<0)
|
||||
{
|
||||
if (-m_nPos>=nSamples)
|
||||
{
|
||||
memset(pDataOut, 0, nSamples*m_pDecoder->m_pMusicSystem->GetBytesPerSample());
|
||||
m_nPos+=nSamples;
|
||||
return true;
|
||||
}else
|
||||
{
|
||||
nOfs=-m_nPos;
|
||||
m_nPos=0;
|
||||
nSamples-=nOfs;
|
||||
memset(pDataOut, 0, nOfs*m_pDecoder->m_pMusicSystem->GetBytesPerSample());
|
||||
}
|
||||
}
|
||||
if (!SeekBytes(m_nPosBytes))
|
||||
return false;
|
||||
int nSamplesToRead;
|
||||
for (;;)
|
||||
{
|
||||
if ((m_nPos+nSamples)>m_pDecoder->m_FileInfo.nSamples)
|
||||
nSamplesToRead=m_pDecoder->m_FileInfo.nSamples-m_nPos;
|
||||
else
|
||||
nSamplesToRead=nSamples;
|
||||
if(m_pDecoder->Is44KHz())
|
||||
{
|
||||
if (!m_pDecoder->ReadFile(&(pDataOut[nOfs]), m_pDecoder->m_PCMFileInfo.nBytesPerSample, nSamplesToRead, &m_nPosBytes))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//decode for 44 KHz
|
||||
if (!FillPCMBuffer22KHz(&(pDataOut[nOfs]), nSamplesToRead))
|
||||
return false;
|
||||
}
|
||||
// FIXME: conversation of samplerate might be needed here
|
||||
m_nPos+=nSamplesToRead;
|
||||
if (nSamplesToRead==nSamples)
|
||||
break;
|
||||
nOfs+=nSamplesToRead;
|
||||
if (!bLoop)
|
||||
{
|
||||
memset(&(pDataOut[nOfs]), 0, (nSamples-nSamplesToRead)*m_pDecoder->m_pMusicSystem->GetBytesPerSample());
|
||||
break;
|
||||
}
|
||||
nSamples-=nSamplesToRead;
|
||||
Seek0();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//! fills a dest buffer with uncompressed data
|
||||
const bool CPCMDecoderInstance::FillPCMBuffer22KHz(signed long *pBuffer, int nSamples)
|
||||
{
|
||||
//first check for copying some data from last frame (if not at starting position)
|
||||
if(m_bCopyFromLastFrame && m_nPos != 0)
|
||||
{
|
||||
*pBuffer++ = m_lLastSample;//contains sample to start with from last encoding
|
||||
nSamples -= 1;
|
||||
m_bCopyFromLastFrame = false;
|
||||
}
|
||||
const unsigned int cuiSamplesPerBlock = scuiEncodedBlockSize / m_pDecoder->m_PCMFileInfo.nBytesPerSample;//number of samples to read per block (according to allocated static array)
|
||||
const unsigned int cuiBlocks = nSamples / (cuiSamplesPerBlock*2); //blocks to read, remember samples will be doubled
|
||||
for(unsigned int i=0; i<cuiBlocks;i++)
|
||||
{
|
||||
if (!m_pDecoder->ReadFile(m_aEncodedBlock, m_pDecoder->m_PCMFileInfo.nBytesPerSample, cuiSamplesPerBlock, &m_nPosBytes))
|
||||
return false;
|
||||
//now double up interleaved samples
|
||||
const signed long *pEncodedData = reinterpret_cast<signed long*>(&m_aEncodedBlock[0]);
|
||||
for(unsigned int j=0; j<cuiSamplesPerBlock;j++)
|
||||
{
|
||||
*pBuffer++ = *pEncodedData; //double up samples
|
||||
*pBuffer++ = *pEncodedData++;
|
||||
}
|
||||
nSamples -= (2*cuiSamplesPerBlock);
|
||||
}
|
||||
if(nSamples > 0)
|
||||
{
|
||||
//differentiate between a left odd and even sample count
|
||||
if(nSamples & 0x1)
|
||||
{
|
||||
m_bCopyFromLastFrame = true;
|
||||
//read one sample more
|
||||
if (!m_pDecoder->ReadFile(m_aEncodedBlock, m_pDecoder->m_PCMFileInfo.nBytesPerSample, (nSamples/2)+1, &m_nPosBytes))
|
||||
return false;
|
||||
const signed long *pEncodedData = reinterpret_cast<signed long*>(&m_aEncodedBlock[0]);
|
||||
for(int j=0; j<nSamples/2;j++)
|
||||
{
|
||||
*pBuffer++ = *pEncodedData; //double up samples
|
||||
*pBuffer++ = *pEncodedData++;
|
||||
}
|
||||
*pBuffer++ = m_lLastSample = *pEncodedData; //remember last sample, has to start with in next request
|
||||
}
|
||||
else
|
||||
{
|
||||
//even count, no special treatment
|
||||
m_bCopyFromLastFrame = false;
|
||||
if (!m_pDecoder->ReadFile(m_aEncodedBlock, m_pDecoder->m_PCMFileInfo.nBytesPerSample, (nSamples/2), &m_nPosBytes))
|
||||
return false;
|
||||
const signed long *pEncodedData = reinterpret_cast<signed long*>(&m_aEncodedBlock[0]);
|
||||
for(int j=0; j<nSamples/2;j++)
|
||||
{
|
||||
*pBuffer++ = *pEncodedData; //double up samples
|
||||
*pBuffer++ = *pEncodedData++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
79
CrySoundSystem/PCMDecoder.h
Normal file
79
CrySoundSystem/PCMDecoder.h
Normal file
@@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
|
||||
#include "PatternDecoder.h"
|
||||
|
||||
struct IMusicSystem;
|
||||
class CPCMDecoderInstance;
|
||||
struct ICryPak;
|
||||
|
||||
struct SPCMFileInfo
|
||||
{
|
||||
SPCMFileInfo()
|
||||
{
|
||||
nBytesPerSample=0;
|
||||
}
|
||||
int nBytesPerSample;
|
||||
};
|
||||
|
||||
class CPCMDecoder : public IMusicPatternDecoder
|
||||
{
|
||||
protected:
|
||||
IMusicSystem *m_pMusicSystem;
|
||||
ICryPak *m_pPak;
|
||||
FILE *m_pFile;
|
||||
int m_nPosBytes; // current position (in bytes) in the file to reduce seeking-overhead
|
||||
SMusicPatternFileInfo m_FileInfo;
|
||||
SPCMFileInfo m_PCMFileInfo;
|
||||
friend class CPCMDecoderInstance;
|
||||
private:
|
||||
bool m_b44KHz; //keeps track of encoded frequency
|
||||
|
||||
int ReadFile(void *pBuf, int nSize, int nCount, int *pNewFilePos=NULL);
|
||||
bool InitStreamWAV();
|
||||
protected:
|
||||
virtual ~CPCMDecoder();
|
||||
public:
|
||||
CPCMDecoder(IMusicSystem *pMusicSystem);
|
||||
void Release() { delete this; }
|
||||
//! Open a music-pattern-file.
|
||||
bool Open(const char *pszFilename);
|
||||
//! Close a music-pattern-file.
|
||||
bool Close();
|
||||
//! Retrieve file-info
|
||||
bool GetFileInfo(SMusicPatternFileInfo &FileInfo);
|
||||
//! Retrieve mem-info
|
||||
void GetMemoryUsage(class ICrySizer* pSizer);
|
||||
//! Create instance.
|
||||
IMusicPatternDecoderInstance* CreateInstance();
|
||||
//! retrieves frequency encoding
|
||||
const bool Is44KHz() const {return m_b44KHz;}
|
||||
};
|
||||
|
||||
class CPCMDecoderInstance : public IMusicPatternDecoderInstance
|
||||
{
|
||||
static const unsigned int scuiEncodedBlockSize = 2048; //block size for static allocation
|
||||
|
||||
protected:
|
||||
CPCMDecoder *m_pDecoder;
|
||||
int m_nPos; // position in samples
|
||||
int m_nPosBytes; // file position in bytes
|
||||
bool m_bCopyFromLastFrame; // indicates some copying from last frame (due to odd sample count request)
|
||||
signed long m_lLastSample; // sample to reuse for next frame
|
||||
private:
|
||||
bool SeekBytes(int nBytes);
|
||||
protected:
|
||||
unsigned int m_aEncodedBlock[scuiEncodedBlockSize]; //static allocated encoded block, only needed for 22 kHz mode
|
||||
//! fills a dest buffer with uncompressed data
|
||||
const bool FillPCMBuffer22KHz(signed long *pBuffer, int nSamples);
|
||||
|
||||
virtual ~CPCMDecoderInstance();
|
||||
public:
|
||||
CPCMDecoderInstance(CPCMDecoder *pDecoder);
|
||||
void Release() { delete this; }
|
||||
//! Seek to beginning of pattern (if nDelay is set it will wait nDelay-samples before starting playback).
|
||||
bool Seek0(int nDelay=0);
|
||||
//! Retrieve the current position in the file (in samples)
|
||||
int GetPos();
|
||||
//! Decode and retrieve pcm-data (stereo/16bit).
|
||||
bool GetPCMData(signed long *pDataOut, int nSamples, bool bLoop=true);
|
||||
};
|
||||
65
CrySoundSystem/PatternDecoder.h
Normal file
65
CrySoundSystem/PatternDecoder.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#define LOG_MUSICFILES
|
||||
|
||||
struct SMusicPatternFileInfo
|
||||
{
|
||||
SMusicPatternFileInfo()
|
||||
{
|
||||
sFilename="";
|
||||
nHeaderSize=0;
|
||||
nSamples=0;
|
||||
}
|
||||
string sFilename;
|
||||
int nHeaderSize;
|
||||
int nSamples;
|
||||
};
|
||||
|
||||
struct SWaveHdr
|
||||
{
|
||||
char RIFF[4]; // "RIFF" tag
|
||||
unsigned long dwSize; // Size of data to follow
|
||||
char WAVE[4]; // "WAVE" tag
|
||||
char fmt_[4]; // "fmt " tag
|
||||
unsigned long dw16; // 16
|
||||
unsigned short wOne_0; // 1
|
||||
unsigned short wChnls; // Number of Channels
|
||||
unsigned long dwSRate; // Sample Rate
|
||||
unsigned long BytesPerSec; // Bytes per second
|
||||
unsigned short wBlkAlign; // Block align
|
||||
unsigned short BitsPerSample; // Sample size
|
||||
char DATA[4]; // "DATA"
|
||||
unsigned long dwDSize; // Number of Samples
|
||||
};
|
||||
|
||||
enum EWaveFormatIDs
|
||||
{
|
||||
WAVE_FORMAT_PCM = 0x0001,
|
||||
WAVE_FORMAT_ADPCM = 0x0002,
|
||||
};
|
||||
|
||||
struct IMusicPatternDecoderInstance
|
||||
{
|
||||
virtual void Release()=0;
|
||||
//! Seek to beginning of pattern (if nDelay is set it will wait nDelay-samples before starting playback).
|
||||
virtual bool Seek0(int nDelay=0)=0;
|
||||
//! Retrieve the current position in the file (in samples).
|
||||
virtual int GetPos()=0;
|
||||
//! Decode and retrieve pcm-data (stereo/16bit).
|
||||
virtual bool GetPCMData(signed long *pDataOut, int nSamples, bool bLoop=true)=0;
|
||||
};
|
||||
|
||||
struct IMusicPatternDecoder
|
||||
{
|
||||
virtual void Release()=0;
|
||||
//! Open a music-pattern-file.
|
||||
virtual bool Open(const char *pszFilename)=0;
|
||||
//! Close a music-pattern-file.
|
||||
virtual bool Close()=0;
|
||||
//! Retrieve file-info.
|
||||
virtual bool GetFileInfo(SMusicPatternFileInfo &FileInfo)=0;
|
||||
//! Retrieve mem-info.
|
||||
virtual void GetMemoryUsage(class ICrySizer* pSizer)=0;
|
||||
//! Create instance.
|
||||
virtual IMusicPatternDecoderInstance* CreateInstance()=0;
|
||||
};
|
||||
116
CrySoundSystem/RandGen.cpp
Normal file
116
CrySoundSystem/RandGen.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
#include "StdAfx.h"
|
||||
#include "randgen.h"
|
||||
|
||||
#define M (397) // a period parameter
|
||||
#define K (0x9908B0DFU) // a magic constant
|
||||
#define hiBit(u) ((u) & 0x80000000U) // mask all but highest bit of u
|
||||
#define loBit(u) ((u) & 0x00000001U) // mask all but lowest bit of u
|
||||
#define loBits(u) ((u) & 0x7FFFFFFFU) // mask the highest bit of u
|
||||
#define mixBits(u, v) (hiBit(u)|loBits(v)) // move hi bit of u to hi bit of v
|
||||
|
||||
CPseudoRandGen::CPseudoRandGen()
|
||||
{
|
||||
left=-1;
|
||||
}
|
||||
|
||||
CPseudoRandGen::~CPseudoRandGen()
|
||||
{
|
||||
}
|
||||
|
||||
void CPseudoRandGen::Seed(uint32 seed)
|
||||
{
|
||||
//
|
||||
// We initialize state[0..(N-1)] via the generator
|
||||
//
|
||||
// x_new = (69069 * x_old) mod 2^32
|
||||
//
|
||||
// from Line 15 of Table 1, p. 106, Sec. 3.3.4 of Knuth's
|
||||
// _The Art of Computer Programming_, Volume 2, 3rd ed.
|
||||
//
|
||||
// Notes (SJC): I do not know what the initial state requirements
|
||||
// of the Mersenne Twister are, but it seems this seeding generator
|
||||
// could be better. It achieves the maximum period for its modulus
|
||||
// (2^30) iff x_initial is odd (p. 20-21, Sec. 3.2.1.2, Knuth); if
|
||||
// x_initial can be even, you have sequences like 0, 0, 0, ...;
|
||||
// 2^31, 2^31, 2^31, ...; 2^30, 2^30, 2^30, ...; 2^29, 2^29 + 2^31,
|
||||
// 2^29, 2^29 + 2^31, ..., etc. so I force seed to be odd below.
|
||||
//
|
||||
// Even if x_initial is odd, if x_initial is 1 mod 4 then
|
||||
//
|
||||
// the lowest bit of x is always 1,
|
||||
// the next-to-lowest bit of x is always 0,
|
||||
// the 2nd-from-lowest bit of x alternates ... 0 1 0 1 0 1 0 1 ... ,
|
||||
// the 3rd-from-lowest bit of x 4-cycles ... 0 1 1 0 0 1 1 0 ... ,
|
||||
// the 4th-from-lowest bit of x has the 8-cycle ... 0 0 0 1 1 1 1 0 ... ,
|
||||
// ...
|
||||
//
|
||||
// and if x_initial is 3 mod 4 then
|
||||
//
|
||||
// the lowest bit of x is always 1,
|
||||
// the next-to-lowest bit of x is always 1,
|
||||
// the 2nd-from-lowest bit of x alternates ... 0 1 0 1 0 1 0 1 ... ,
|
||||
// the 3rd-from-lowest bit of x 4-cycles ... 0 0 1 1 0 0 1 1 ... ,
|
||||
// the 4th-from-lowest bit of x has the 8-cycle ... 0 0 1 1 1 1 0 0 ... ,
|
||||
// ...
|
||||
//
|
||||
// The generator's potency (min. s>=0 with (69069-1)^s = 0 mod 2^32) is
|
||||
// 16, which seems to be alright by p. 25, Sec. 3.2.1.3 of Knuth. It
|
||||
// also does well in the dimension 2..5 spectral tests, but it could be
|
||||
// better in dimension 6 (Line 15, Table 1, p. 106, Sec. 3.3.4, Knuth).
|
||||
//
|
||||
// Note that the random number user does not see the values generated
|
||||
// here directly since reloadMT() will always munge them first, so maybe
|
||||
// none of all of this matters. In fact, the seed values made here could
|
||||
// even be extra-special desirable if the Mersenne Twister theory says
|
||||
// so-- that's why the only change I made is to restrict to odd seeds.
|
||||
//
|
||||
|
||||
register uint32 x = (seed | 1U) & 0xFFFFFFFFU, *s = state;
|
||||
register int j;
|
||||
for(left=0, *s++=x, j=N; --j;
|
||||
*s++ = (x*=69069U) & 0xFFFFFFFFU);
|
||||
}
|
||||
|
||||
uint32 CPseudoRandGen::Rand()
|
||||
{
|
||||
uint32 y;
|
||||
|
||||
if(--left < 0)
|
||||
return(Reload());
|
||||
|
||||
y = *next++;
|
||||
y ^= (y >> 11);
|
||||
y ^= (y << 7) & 0x9D2C5680U;
|
||||
y ^= (y << 15) & 0xEFC60000U;
|
||||
return(y ^ (y >> 18));
|
||||
}
|
||||
|
||||
float CPseudoRandGen::Rand(float fMin, float fMax)
|
||||
{
|
||||
static double _1overFFFFFFFF=2.3283064370807973754314699618685e-10;
|
||||
float fVal=(float)((double)Rand()*_1overFFFFFFFF*(double)(fMax-fMin)+(double)fMin);
|
||||
return fVal;
|
||||
}
|
||||
|
||||
uint32 CPseudoRandGen::Reload()
|
||||
{
|
||||
register uint32 *p0=state, *p2=state+2, *pM=state+M, s0, s1;
|
||||
register int j;
|
||||
|
||||
if(left < -1)
|
||||
Seed(4357U);
|
||||
|
||||
left=N-1, next=state+1;
|
||||
|
||||
for(s0=state[0], s1=state[1], j=N-M+1; --j; s0=s1, s1=*p2++)
|
||||
*p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
|
||||
|
||||
for(pM=state, j=M; --j; s0=s1, s1=*p2++)
|
||||
*p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
|
||||
|
||||
s1=state[0], *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
|
||||
s1 ^= (s1 >> 11);
|
||||
s1 ^= (s1 << 7) & 0x9D2C5680U;
|
||||
s1 ^= (s1 << 15) & 0xEFC60000U;
|
||||
return(s1 ^ (s1 >> 18));
|
||||
}
|
||||
23
CrySoundSystem/RandGen.h
Normal file
23
CrySoundSystem/RandGen.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef WIN64
|
||||
typedef unsigned int uint32;
|
||||
#endif
|
||||
|
||||
#define N (624) // length of state vector
|
||||
|
||||
class CPseudoRandGen
|
||||
{
|
||||
private:
|
||||
uint32 state[N+1]; // state vector + 1 extra to not violate ANSI C
|
||||
uint32 *next; // next random value is computed from here
|
||||
int left; // can *next++ this many times before reloading
|
||||
private:
|
||||
uint32 Reload();
|
||||
public:
|
||||
CPseudoRandGen();
|
||||
virtual ~CPseudoRandGen();
|
||||
void Seed(uint32 seed);
|
||||
uint32 Rand();
|
||||
float Rand(float fMin, float fMax);
|
||||
};
|
||||
1259
CrySoundSystem/Sound.cpp
Normal file
1259
CrySoundSystem/Sound.cpp
Normal file
File diff suppressed because it is too large
Load Diff
264
CrySoundSystem/Sound.h
Normal file
264
CrySoundSystem/Sound.h
Normal file
@@ -0,0 +1,264 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CrySound Source Code
|
||||
//
|
||||
// File: Sound.h
|
||||
// Description: ISound interface implementation.
|
||||
//
|
||||
// History:
|
||||
// -June 06,2001:Implemented by Marco Corbetta
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CRYSOUND_SOUND_H
|
||||
#define CRYSOUND_SOUND_H
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include "Cry_Math.h"
|
||||
#include "SoundSystem.h"
|
||||
#include <IStreamEngine.h>
|
||||
|
||||
struct CS_STREAM;
|
||||
struct CS_SAMPLE;
|
||||
struct IVisArea;
|
||||
struct ITimer;
|
||||
|
||||
#define SOUND_PRELOAD_DISTANCE 15 // start preloading this amount of meters before the sound is potentially hearable (max_radius)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// A sound...
|
||||
class CSound : public ISound
|
||||
{
|
||||
protected:
|
||||
virtual ~CSound();
|
||||
public:
|
||||
CSound(class CSoundSystem *pSSys,const char *szFile);
|
||||
|
||||
//// ISound //////////////////////////////////////////////////////
|
||||
bool IsPlayingOnChannel(); // returns true if a voice is used to play the sound and have channel allocated.
|
||||
bool IsPlaying(); // returns true if a voice is used to play the sound
|
||||
bool IsPlayingVirtual(); // returns true if the sound is looping and not stopped. it might be too far (clipped) so it will not use a physical voice nor is it audioable
|
||||
void Play(float fVolumeScale=1.0f, bool bForceActiveState=true, bool bSetRatio=true);
|
||||
void PlayFadeUnderwater(float fVolumeScale=1.0f, bool bForceActiveState=true, bool bSetRatio=true);
|
||||
void Stop();
|
||||
//! Frees fmod channel, also stop hearable sound playback
|
||||
void FreeChannel();
|
||||
//void SetName(const char *szName);
|
||||
|
||||
//! Get name of sound file.
|
||||
const char *GetName();
|
||||
|
||||
//! Get uniq id of sound.
|
||||
const int GetId();
|
||||
|
||||
//! Set looping mode of sound.
|
||||
void SetLoopMode(bool bLoop);
|
||||
|
||||
//! retrieves the currently played sample-pos, in milliseconds or bytes
|
||||
unsigned int GetCurrentSamplePos(bool bMilliSeconds);
|
||||
//! set the currently played sample-pos in bytes or milliseconds
|
||||
void SetCurrentSamplePos(unsigned int nPos,bool bMilliSeconds);
|
||||
|
||||
//! sets automatic pitching amount (0-1000)
|
||||
void SetPitching(float fPitching);
|
||||
|
||||
void SetBaseFrequency(int nFreq);
|
||||
|
||||
//! Return frequency of sound.
|
||||
int GetBaseFrequency(int nFreq);
|
||||
|
||||
void SetFrequency(int nFreq);
|
||||
//! Set Minimal/Maximal distances for sound.
|
||||
//! Sound is not attenuated below minimal distance and not heared outside of max distance.
|
||||
void SetMinMaxDistance(float fMinDist, float fMaxDist);
|
||||
void SetAttrib(int nVolume, float fRatio, int nPan=127, int nFreq=1000, bool bSetRatio=true);
|
||||
void SetAttrib(const Vec3d &pos, const Vec3d &speed);
|
||||
void SetRatio(float fRatio);
|
||||
|
||||
//! Update the position (called when directional-attenuation-parameters change)
|
||||
void UpdatePosition();
|
||||
|
||||
//! Set sound source position.
|
||||
void SetPosition(const Vec3d &pos);
|
||||
|
||||
//! Get sound source position.
|
||||
//@return false if it is not a 3d sound
|
||||
const bool GetPosition(Vec3d &vPos);
|
||||
|
||||
void SetLooping(bool bLooping) {}
|
||||
int GetFrequency()
|
||||
{
|
||||
if (m_pSound)
|
||||
return (m_pSound->GetBaseFreq());
|
||||
return (0);
|
||||
}
|
||||
|
||||
//! Set sound pitch.
|
||||
//! 1000 is default pitch.
|
||||
void SetPitch(int nValue);
|
||||
|
||||
//! Set sound pan
|
||||
void SetPan(int nPan);
|
||||
|
||||
//! Define sound code.
|
||||
//! Angles are in degrees, in range 0-360.
|
||||
void SetConeAngles(float fInnerAngle,float fOuterAngle);
|
||||
|
||||
//! Set sound volume.
|
||||
//! Range: 0-100
|
||||
void SetVolume(int);
|
||||
|
||||
//! Get sound volume.
|
||||
int GetVolume() { return(m_nVolume); }
|
||||
|
||||
//! Set sound source velocity.
|
||||
void SetVelocity(const Vec3d &vVel);
|
||||
|
||||
//! Get sound source velocity.
|
||||
Vec3_tpl<float> GetVelocity( void ) { return (m_speed); }
|
||||
|
||||
//! Set orientation of sound.
|
||||
//! Only relevant when cone angles are specified.
|
||||
void SetDirection(const Vec3d &vDir);
|
||||
Vec3_tpl<float> GetDirection() {return (m_orient);}
|
||||
|
||||
void SetLoopPoints(const int iLoopStart, const int iLoopEnd);
|
||||
|
||||
//! compute fmod flags from crysound-flags
|
||||
int GetFModFlags();
|
||||
//! load the sound only when it is played
|
||||
bool Preload();
|
||||
|
||||
bool IsRelative() const
|
||||
{
|
||||
if (m_nFlags & FLAG_SOUND_RELATIVE)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sets certain sound properties
|
||||
void SetSoundProperties(float fFadingValue);
|
||||
|
||||
// Add/remove sounds.
|
||||
int AddRef() { return ++m_refCount; };
|
||||
int Release();
|
||||
|
||||
//! enable fx effects for this sound
|
||||
//! _ust be called after each play
|
||||
void FXEnable(int nEffectNumber);
|
||||
|
||||
void FXSetParamEQ(float fCenter,float fBandwidth,float fGain);
|
||||
|
||||
void AddToScaleGroup(int nGroup) { m_nSoundScaleGroups|=(1<<nGroup); }
|
||||
void RemoveFromScaleGroup(int nGroup) { m_nSoundScaleGroups&=~(1<<nGroup); }
|
||||
void SetScaleGroup(unsigned int nGroupBits) { m_nSoundScaleGroups=nGroupBits; }
|
||||
|
||||
//! set the maximum distance / the sound will be stopped if the
|
||||
//! distance from the listener and this sound is bigger than this max distance
|
||||
// void SetMaxSoundDistance(float fMaxSoundDistance);
|
||||
|
||||
//! returns the size of the stream in ms
|
||||
int GetLengthMs();
|
||||
|
||||
//! returns the size of the stream
|
||||
int GetLength();
|
||||
|
||||
//! set sound priority (0-255)
|
||||
void SetSoundPriority(unsigned char nSoundPriority);
|
||||
|
||||
void ChangeVolume(int nVolume);
|
||||
|
||||
int CalcSoundVolume(int nSoundValue,float fVolumeScale);
|
||||
|
||||
bool FadeIn();
|
||||
bool FadeOut();
|
||||
|
||||
void AddEventListener( ISoundEventListener *pListener );
|
||||
void RemoveEventListener( ISoundEventListener *pListener );
|
||||
//! Fires event for all listeners to this sound.
|
||||
void OnEvent( ESoundCallbackEvent event );
|
||||
|
||||
void OnBufferLoaded();
|
||||
void OnBufferLoadFailed();
|
||||
|
||||
void GetMemoryUsage(class ICrySizer* pSizer);
|
||||
|
||||
//! Check if sound now loading (not yet played).
|
||||
bool IsLoading();
|
||||
bool IsLoaded();
|
||||
bool IsUsingChannel();
|
||||
|
||||
bool IsPlayLengthExpired( float fCurrTime );
|
||||
|
||||
public:
|
||||
|
||||
int m_nChannel;
|
||||
int m_nFxChannel;
|
||||
//int m_nLastId;
|
||||
//int m_nFadeType;
|
||||
int m_nStartOffset;
|
||||
|
||||
CSoundBufferPtr m_pSound;
|
||||
|
||||
float m_fLastPlayTime;
|
||||
float m_fChannelPlayTime;
|
||||
float m_fSoundLengthSec;
|
||||
|
||||
unsigned int m_nSoundScaleGroups;
|
||||
|
||||
ESoundActiveState m_State;
|
||||
|
||||
int m_nMaxVolume;
|
||||
int m_nVolume;
|
||||
int m_nPlayingVolume;
|
||||
int m_nPan;
|
||||
float m_fPitching; // relative random pitching of sound (to avoid flanging if multiple sounds are played simultaneously)
|
||||
int m_nCurrPitch;
|
||||
//int m_nBaseFreq;
|
||||
int m_nRelativeFreq;
|
||||
bool m_bLoop;
|
||||
bool m_bPlaying;
|
||||
float m_fRatio;
|
||||
|
||||
Vec3_tpl<float> m_position;
|
||||
Vec3_tpl<float> m_orient;
|
||||
Vec3_tpl<float> m_speed;
|
||||
int m_refCount;
|
||||
int m_nFlags;
|
||||
Vec3_tpl<float> m_RealPos; // this is the position the sound is currently at (may differ from m_position, because for example the directional attenuation will virtually "move" the sound)
|
||||
|
||||
//string m_strName;
|
||||
|
||||
float m_fMaxRadius2; //used to skip playing of sounds if using sound's sphere
|
||||
float m_fMinRadius2; //used to skip playing of sounds if using sound's sphere
|
||||
float m_fDiffRadius2; //used to calculate volume ratio when inside the sound's sphere
|
||||
float m_fPreloadRadius2; // used to start preloading
|
||||
float m_fMinDist,m_fMaxDist;
|
||||
/// float m_fMaxSoundDistance2; //keep it squared
|
||||
|
||||
class CSoundSystem* m_pSSys;
|
||||
ITimer *m_pTimer;
|
||||
|
||||
//short m_nSectorId,m_nBuildingId;
|
||||
IVisArea *m_pArea;
|
||||
float m_fFadingValue,m_fCurrentFade;
|
||||
|
||||
bool m_bPlayAfterLoad;
|
||||
float m_fPostLoadRatio;
|
||||
bool m_bPostLoadForceActiveState;
|
||||
bool m_bPostLoadSetRatio;
|
||||
bool m_bAutoStop;
|
||||
bool m_bAlreadyLoaded;
|
||||
|
||||
unsigned char m_nSoundPriority;
|
||||
|
||||
static int m_PlayingChannels;
|
||||
|
||||
typedef std::set<ISoundEventListener*> Listeners;
|
||||
Listeners m_listeners;
|
||||
};
|
||||
|
||||
#endif // CRYSOUND_SOUND_H
|
||||
387
CrySoundSystem/SoundBuffer.cpp
Normal file
387
CrySoundSystem/SoundBuffer.cpp
Normal file
@@ -0,0 +1,387 @@
|
||||
#include "StdAfx.h"
|
||||
#include <algorithm>
|
||||
#include "SoundBuffer.h"
|
||||
#include "SoundSystem.h"
|
||||
#include "Sound.h"
|
||||
#include <IGame.h>
|
||||
|
||||
CSoundBuffer::CSoundBuffer(CSoundSystem *pSoundSystem, SSoundBufferProps &Props) : m_Props(Props)
|
||||
{
|
||||
m_pSoundSystem=pSoundSystem;
|
||||
m_Data.m_pData=NULL;
|
||||
m_Type=btNONE;
|
||||
m_nRef=0;
|
||||
m_nBaseFreq=44100;
|
||||
m_fLength=0.0f;
|
||||
m_pReadStream=NULL;
|
||||
m_bLoadFailure=false;
|
||||
m_bLooping=false;
|
||||
m_bCallbackIteration=false;
|
||||
m_vecLoadReq.clear();
|
||||
m_vecLoadReqToRemove.clear();
|
||||
m_vecLoadReqToAdd.clear();
|
||||
}
|
||||
|
||||
CSoundBuffer::~CSoundBuffer()
|
||||
{
|
||||
if (m_pReadStream!=NULL)
|
||||
{
|
||||
m_pReadStream->Abort();
|
||||
m_pReadStream=NULL;
|
||||
}
|
||||
DestroyData();
|
||||
}
|
||||
|
||||
int CSoundBuffer::AddRef()
|
||||
{
|
||||
return ++m_nRef;
|
||||
}
|
||||
|
||||
int CSoundBuffer::Release()
|
||||
{
|
||||
--m_nRef;
|
||||
if(m_nRef<=0)
|
||||
{
|
||||
m_pSoundSystem->RemoveBuffer(m_Props);
|
||||
delete this;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(_DEBUG) && defined(WIN64)
|
||||
static __int64 g_numSBSetSample = 0;
|
||||
#endif
|
||||
|
||||
|
||||
void CSoundBuffer::SetSample(CS_SAMPLE *pPtr)
|
||||
{
|
||||
#if defined(_DEBUG) && defined(WIN64)
|
||||
++g_numSBSetSample;
|
||||
#endif
|
||||
|
||||
if (pPtr && (!m_Data.m_pSample))
|
||||
{
|
||||
m_pSoundSystem->BufferLoaded(this);
|
||||
}
|
||||
else
|
||||
if ((!pPtr) && m_Data.m_pSample)
|
||||
{
|
||||
m_pSoundSystem->BufferUnloaded(this);
|
||||
}
|
||||
m_Data.m_pSample=pPtr;
|
||||
m_Type=(pPtr!=NULL) ? btSAMPLE : btNONE;
|
||||
}
|
||||
|
||||
void CSoundBuffer::SetStream(CS_STREAM *pPtr)
|
||||
{
|
||||
GUARD_HEAP;
|
||||
|
||||
if (pPtr && (!m_Data.m_pStream))
|
||||
m_pSoundSystem->BufferLoaded(this);
|
||||
else
|
||||
if ((!pPtr) && m_Data.m_pStream)
|
||||
m_pSoundSystem->BufferUnloaded(this);
|
||||
m_Data.m_pStream=pPtr;
|
||||
m_Type=(pPtr!=NULL) ? btSTREAM : btNONE;
|
||||
}
|
||||
|
||||
void CSoundBuffer::UpdateCallbacks()
|
||||
{
|
||||
if (m_bCallbackIteration)
|
||||
return;
|
||||
GUARD_HEAP;
|
||||
for (TBufferLoadReqVecIt It=m_vecLoadReqToRemove.begin();It!=m_vecLoadReqToRemove.end();++It)
|
||||
{
|
||||
TBufferLoadReqVecIt RemIt=std::find(m_vecLoadReq.begin(), m_vecLoadReq.end(), *It);
|
||||
if (RemIt!=m_vecLoadReq.end())
|
||||
m_vecLoadReq.erase(RemIt);
|
||||
}
|
||||
m_vecLoadReqToRemove.clear();
|
||||
for (TBufferLoadReqVecIt It=m_vecLoadReqToAdd.begin();It!=m_vecLoadReqToAdd.end();++It)
|
||||
{
|
||||
m_vecLoadReq.push_back(*It);
|
||||
}
|
||||
m_vecLoadReqToAdd.clear();
|
||||
}
|
||||
|
||||
#define CALLBACK_FUNC(_func) \
|
||||
m_bCallbackIteration=true; \
|
||||
for (TBufferLoadReqVecIt It=m_vecLoadReq.begin();It!=m_vecLoadReq.end();++It) \
|
||||
{ \
|
||||
(*It)->_func(); \
|
||||
} \
|
||||
m_vecLoadReq.clear(); \
|
||||
m_bCallbackIteration=false; \
|
||||
UpdateCallbacks();
|
||||
|
||||
void CSoundBuffer::SoundLoaded()
|
||||
{
|
||||
//TRACE("Sound-Streaming for %s SUCCEEDED.", m_Props.sName.c_str());
|
||||
//FUNCTION_PROFILER( m_pSoundSystem->GetSystem(),PROFILE_SOUND );
|
||||
switch (m_Type)
|
||||
{
|
||||
case btSAMPLE:
|
||||
{
|
||||
GUARD_HEAP;
|
||||
//get the base frequence
|
||||
CS_Sample_GetDefaults(m_Data.m_pSample, &m_nBaseFreq, NULL, NULL, NULL);
|
||||
// set default values: ignore volume and pan, but sets frequency and priority
|
||||
CS_Sample_SetDefaults(m_Data.m_pSample, m_nBaseFreq, -1, -1, 0);
|
||||
m_fLength=(float)CS_Sample_GetLength(m_Data.m_pSample)/(float)m_nBaseFreq;
|
||||
break;
|
||||
}
|
||||
case btSTREAM:
|
||||
{
|
||||
GUARD_HEAP;
|
||||
m_fLength=(float)CS_Stream_GetLengthMs(m_Data.m_pStream)/1000.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_pReadStream=NULL;
|
||||
if (m_pSoundSystem->m_pCVarDebugSound->GetIVal()==3)
|
||||
m_pSoundSystem->m_pILog->Log("file %s, loaded \n", m_Props.sName.c_str());
|
||||
// broadcast OnBufferLoaded
|
||||
GUARD_HEAP;
|
||||
CALLBACK_FUNC(OnBufferLoaded);
|
||||
/* m_bCallbackIteration=true;
|
||||
for (TBufferLoadReqVecIt It=m_vecLoadReq.begin();It!=m_vecLoadReq.end();++It)
|
||||
{
|
||||
CSound *pSound=(*It);
|
||||
pSound->OnBufferLoaded();
|
||||
}
|
||||
m_vecLoadReq.clear();
|
||||
m_bCallbackIteration=false;
|
||||
UpdateCallbacks();*/
|
||||
}
|
||||
|
||||
void CSoundBuffer::LoadFailed()
|
||||
{
|
||||
m_pSoundSystem->GetSystem()->Warning( VALIDATOR_MODULE_SOUNDSYSTEM,VALIDATOR_WARNING,VALIDATOR_FLAG_SOUND,"Sound %s failed to load", m_Props.sName.c_str() );
|
||||
m_pReadStream=NULL;
|
||||
|
||||
// broadcast OnBufferLoadFailed
|
||||
CALLBACK_FUNC(OnBufferLoadFailed);
|
||||
/* m_bCallbackIteration=true;
|
||||
int n;
|
||||
for (TBufferLoadReqVecIt It=m_vecLoadReq.begin();It!=m_vecLoadReq.end();++It)
|
||||
{
|
||||
CSound *pSound=(*It);
|
||||
pSound->OnBufferLoadFailed();
|
||||
}
|
||||
m_vecLoadReq.clear();
|
||||
m_bCallbackIteration=false;
|
||||
UpdateCallbacks();*/
|
||||
}
|
||||
|
||||
void CSoundBuffer::RemoveFromLoadReqList(CSound *pSound)
|
||||
{
|
||||
GUARD_HEAP;
|
||||
m_vecLoadReqToRemove.push_back(pSound);
|
||||
UpdateCallbacks();
|
||||
}
|
||||
|
||||
bool CSoundBuffer::Load(bool bLooping, CSound *pSound)
|
||||
{
|
||||
GUARD_HEAP;
|
||||
FUNCTION_PROFILER( m_pSoundSystem->GetSystem(),PROFILE_SOUND );
|
||||
if (m_Data.m_pData)
|
||||
{
|
||||
if (pSound)
|
||||
pSound->OnBufferLoaded();
|
||||
return true; // already loaded
|
||||
}
|
||||
if (LoadFailure())
|
||||
{
|
||||
if (pSound)
|
||||
pSound->OnBufferLoadFailed();
|
||||
return false; //already tried to open the file before
|
||||
}
|
||||
m_vecLoadReqToAdd.push_back(pSound);
|
||||
UpdateCallbacks();
|
||||
if (!NotLoaded())
|
||||
return true;
|
||||
if (m_Props.sName.empty())
|
||||
return false;
|
||||
m_bLooping=bLooping;
|
||||
//priority for streaming files
|
||||
if (m_Props.nFlags & FLAG_SOUND_STREAM)
|
||||
{
|
||||
// add the game path since this file is not opened via the pak
|
||||
// file system
|
||||
GUARD_HEAP;
|
||||
CS_STREAM *pSoundStream=NULL;
|
||||
|
||||
// check for a MOD first
|
||||
const char *szPrefix=NULL;
|
||||
#ifndef _ISNOTFARCRY
|
||||
IGameMods *pMods=m_pSoundSystem->GetSystem()->GetIGame()->GetModsInterface();
|
||||
if (pMods)
|
||||
szPrefix=pMods->GetModPath(m_Props.sName.c_str());
|
||||
#endif
|
||||
|
||||
if (szPrefix)
|
||||
{
|
||||
#ifndef CS_VERSION_372
|
||||
pSoundStream=CS_Stream_OpenFile(szPrefix, GetFModFlags(m_bLooping), 0);
|
||||
#else
|
||||
// for 3.7
|
||||
pSoundStream=CS_Stream_Open(szPrefix, GetFModFlags(m_bLooping), 0,0);
|
||||
#endif
|
||||
if (!pSoundStream)
|
||||
{
|
||||
// if not found in the MOD folder, fallback to the default one and
|
||||
// try to open it from there
|
||||
|
||||
// for 3.7 support
|
||||
const char * pFileName = m_Props.sName.c_str();
|
||||
#ifndef CS_VERSION_372
|
||||
pSoundStream=CS_Stream_OpenFile(pFileName, GetFModFlags(m_bLooping), 0);
|
||||
#else
|
||||
pSoundStream=CS_Stream_Open(pFileName, GetFModFlags(m_bLooping), 0,0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// no MOD folder
|
||||
// 3.7 changes
|
||||
const char * pFileName = m_Props.sName.c_str();
|
||||
int fmf = GetFModFlags(m_bLooping);
|
||||
#ifndef CS_VERSION_372
|
||||
pSoundStream=CS_Stream_OpenFile(pFileName, fmf, 0);
|
||||
#else
|
||||
pSoundStream=CS_Stream_Open(m_Props.sName.c_str(), GetFModFlags(m_bLooping), 0,0);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!pSoundStream)
|
||||
{
|
||||
//cannot be loaded
|
||||
m_pSoundSystem->m_pILog->LogToFile("Warning: Cannot load streaming sound %s\n", m_Props.sName.c_str());
|
||||
m_bLoadFailure=true;
|
||||
return false;
|
||||
}
|
||||
//set the sound buffer
|
||||
SetStream(pSoundStream);
|
||||
SoundLoaded();
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(m_pSoundSystem->m_pStreamEngine);
|
||||
//TRACE("Starting Sound-Streaming for %s.", m_Props.sName.c_str());
|
||||
m_pReadStream=m_pSoundSystem->m_pStreamEngine->StartRead("SoundSystem", m_Props.sName.c_str(), this);
|
||||
if (pSound->m_nFlags & FLAG_SOUND_LOAD_SYNCHRONOUSLY)
|
||||
{
|
||||
if (m_pReadStream)
|
||||
m_pReadStream->Wait();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_pReadStream->IsFinished())
|
||||
m_pReadStream=NULL;
|
||||
}
|
||||
|
||||
// Placeholder sound.
|
||||
if (m_pSoundSystem->m_pCVarDebugSound->GetIVal() == 2)
|
||||
{
|
||||
if (m_pReadStream)
|
||||
m_pReadStream->Wait();
|
||||
if (m_bLoadFailure)
|
||||
{
|
||||
m_pReadStream = NULL;
|
||||
m_bLoadFailure = false;
|
||||
m_Props.sName = "Sounds/error.wav";
|
||||
return Load( m_bLooping,pSound );
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CSoundBuffer::WaitForLoad()
|
||||
{
|
||||
GUARD_HEAP;
|
||||
if (!Loading())
|
||||
return true;
|
||||
m_pReadStream->Wait();
|
||||
return !LoadFailure();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSoundBuffer::AbortLoading()
|
||||
{
|
||||
if (m_pReadStream!=NULL)
|
||||
{
|
||||
m_pReadStream->Abort();
|
||||
m_pReadStream=NULL;
|
||||
LoadFailed();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSoundBuffer::DestroyData()
|
||||
{
|
||||
GUARD_HEAP;
|
||||
if (m_Data.m_pData)
|
||||
{
|
||||
FUNCTION_PROFILER( m_pSoundSystem->GetSystem(),PROFILE_SOUND );
|
||||
switch (m_Type)
|
||||
{
|
||||
case btSAMPLE: CS_Sample_Free(m_Data.m_pSample); SetSample(NULL); break;
|
||||
case btSTREAM: CS_Stream_Close(m_Data.m_pStream); SetStream(NULL); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CSoundBuffer::GetFModFlags(bool bLooping)
|
||||
{
|
||||
int nFModFlags=0;
|
||||
if (m_Props.nFlags & FLAG_SOUND_3D)
|
||||
nFModFlags|=CS_HW3D;
|
||||
if (m_Props.nFlags & FLAG_SOUND_STEREO)
|
||||
nFModFlags|=CS_STEREO;
|
||||
if (m_Props.nFlags & FLAG_SOUND_16BITS)
|
||||
nFModFlags|=CS_16BITS;
|
||||
if (m_Props.nFlags & FLAG_SOUND_2D)
|
||||
nFModFlags|=CS_2D;
|
||||
//if not flag specified or if a streaming sound, set default flags
|
||||
if ((!nFModFlags) || (m_Props.nFlags & FLAG_SOUND_STREAM))
|
||||
nFModFlags|=CS_2D | CS_STEREO;
|
||||
nFModFlags|=(bLooping) ? CS_LOOP_NORMAL : CS_LOOP_OFF;
|
||||
return nFModFlags;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSoundBuffer::StreamOnComplete(IReadStream *pStream, unsigned nError)
|
||||
{
|
||||
GUARD_HEAP;
|
||||
FUNCTION_PROFILER( m_pSoundSystem->GetSystem(),PROFILE_SOUND );
|
||||
if (nError)
|
||||
{
|
||||
m_bLoadFailure=true;
|
||||
LoadFailed();
|
||||
return;
|
||||
}
|
||||
//use unmanaged channels/indexes, any other type creates problems
|
||||
#ifndef CS_VERSION_372
|
||||
CS_SAMPLE *pSample=CS_Sample_Load(CS_UNMANAGED, (const char*)pStream->GetBuffer(), GetFModFlags(m_bLooping) | CS_LOADMEMORY, pStream->GetBytesRead());
|
||||
#else
|
||||
// 3.7
|
||||
CS_SAMPLE *pSample=CS_Sample_Load(CS_UNMANAGED, (const char*)pStream->GetBuffer(), GetFModFlags(m_bLooping) | CS_LOADMEMORY, 0, pStream->GetBytesRead());
|
||||
#endif
|
||||
if (!pSample)
|
||||
{
|
||||
m_pSoundSystem->m_pILog->LogToFile("Warning: Cannot load sample sound %s\n", m_Props.sName.c_str());
|
||||
m_bLoadFailure=true;
|
||||
LoadFailed();
|
||||
return;
|
||||
}
|
||||
//set the sound source
|
||||
SetSample(pSample);
|
||||
//CS_Sample_SetMode(pSample, m_bLooping ? CS_LOOP_NORMAL : CS_LOOP_OFF);
|
||||
CS_Sample_SetMode(pSample, GetFModFlags(m_bLooping));
|
||||
SoundLoaded();
|
||||
//TRACE("Sound-Streaming for %s finished.", m_Props.sName.c_str());
|
||||
}
|
||||
100
CrySoundSystem/SoundBuffer.h
Normal file
100
CrySoundSystem/SoundBuffer.h
Normal file
@@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
|
||||
#include <ISound.h>
|
||||
#include <IStreamEngine.h>
|
||||
#include <smartptr.h>
|
||||
|
||||
class CSoundSystem;
|
||||
|
||||
enum BufferType
|
||||
{
|
||||
btNONE,
|
||||
btSAMPLE,
|
||||
btSTREAM
|
||||
};
|
||||
|
||||
struct SSoundBufferProps
|
||||
{
|
||||
SSoundBufferProps(const char *_pszName, int _nFlags) : sName(_pszName)
|
||||
{
|
||||
nFlags=_nFlags & SOUNDBUFFER_FLAG_MASK;
|
||||
}
|
||||
SSoundBufferProps(const SSoundBufferProps &Props) : sName(Props.sName)
|
||||
{
|
||||
nFlags=Props.nFlags;
|
||||
}
|
||||
bool operator<(const SSoundBufferProps &Props) const
|
||||
{
|
||||
if (nFlags<Props.nFlags)
|
||||
return true;
|
||||
if (nFlags!=Props.nFlags)
|
||||
return false;
|
||||
return (stricmp(sName.c_str(), Props.sName.c_str())<0);
|
||||
}
|
||||
string sName;
|
||||
int nFlags;
|
||||
};
|
||||
|
||||
class CSound;
|
||||
|
||||
typedef std::vector<CSound*> TBufferLoadReqVec;
|
||||
typedef TBufferLoadReqVec::iterator TBufferLoadReqVecIt;
|
||||
|
||||
class CSoundBuffer : IStreamCallback
|
||||
{
|
||||
private:
|
||||
union tagData
|
||||
{
|
||||
void *m_pData;
|
||||
CS_SAMPLE *m_pSample;
|
||||
CS_STREAM *m_pStream;
|
||||
};
|
||||
protected:
|
||||
CSoundSystem *m_pSoundSystem;
|
||||
int m_nRef;
|
||||
BufferType m_Type;
|
||||
tagData m_Data;
|
||||
SSoundBufferProps m_Props;
|
||||
int m_nBaseFreq;
|
||||
float m_fLength;
|
||||
IReadStreamPtr m_pReadStream;
|
||||
bool m_bLoadFailure;
|
||||
bool m_bLooping;
|
||||
bool m_bCallbackIteration;
|
||||
TBufferLoadReqVec m_vecLoadReq;
|
||||
TBufferLoadReqVec m_vecLoadReqToRemove;
|
||||
TBufferLoadReqVec m_vecLoadReqToAdd;
|
||||
protected:
|
||||
virtual ~CSoundBuffer();
|
||||
virtual void StreamOnComplete(IReadStream *pStream, unsigned nError);
|
||||
void SoundLoaded();
|
||||
void LoadFailed();
|
||||
void UpdateCallbacks();
|
||||
public:
|
||||
int GetFModFlags(bool bLooping);
|
||||
CSoundBuffer(CSoundSystem *pSoundSystem, SSoundBufferProps &Props);
|
||||
const char *GetName() { return(m_Props.sName.c_str());}
|
||||
int AddRef();
|
||||
int Release();
|
||||
void RemoveFromLoadReqList(CSound *pSound);
|
||||
bool Load(bool bLooping, CSound *pSound);
|
||||
bool WaitForLoad();
|
||||
void AbortLoading();
|
||||
void DestroyData();
|
||||
void SetSample(CS_SAMPLE *pPtr);
|
||||
void SetStream(CS_STREAM *pPtr);
|
||||
SSoundBufferProps GetProps() { return (m_Props); }
|
||||
CS_SAMPLE* GetSample() { return (m_Type==btSAMPLE) ? m_Data.m_pSample : NULL; }
|
||||
CS_STREAM* GetStream() { return (m_Type==btSTREAM) ? m_Data.m_pStream : NULL; }
|
||||
BufferType GetType() { return m_Type; }
|
||||
float GetLengthInSeconds() { return m_fLength; }
|
||||
int GetBaseFreq() { return m_nBaseFreq; }
|
||||
//void AddFlags(int nFlags) { m_Props.nFlags|=nFlags; }
|
||||
//void RemoveFlags(int nFlags) { m_Props.nFlags&=~nFlags; }
|
||||
bool NotLoaded() { return (m_Data.m_pData==NULL) && (m_pReadStream==NULL); }
|
||||
bool Loaded() { return (m_Data.m_pData!=NULL) && (m_pReadStream==NULL); }
|
||||
bool Loading() { return (m_Data.m_pData==NULL) && (m_pReadStream!=NULL); }
|
||||
bool LoadFailure() { return m_bLoadFailure; }
|
||||
};
|
||||
|
||||
typedef _smart_ptr<CSoundBuffer> CSoundBufferPtr;
|
||||
2003
CrySoundSystem/SoundSystem.cpp
Normal file
2003
CrySoundSystem/SoundSystem.cpp
Normal file
File diff suppressed because it is too large
Load Diff
351
CrySoundSystem/SoundSystem.h
Normal file
351
CrySoundSystem/SoundSystem.h
Normal file
@@ -0,0 +1,351 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek (C) 2001
|
||||
//
|
||||
// CrySound Source Code
|
||||
//
|
||||
// File: SoundSystem.h
|
||||
// Description: Sound system interface.
|
||||
//
|
||||
// History:
|
||||
// -June 06,2001:Implemented by Marco Corbetta
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CRYSOUND_SOUNDSYSTEM_H
|
||||
#define CRYSOUND_SOUNDSYSTEM_H
|
||||
|
||||
#include "SoundSystemCommon.h"
|
||||
#include "SoundBuffer.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class CSound;
|
||||
struct ICVar;
|
||||
class CCamera;
|
||||
struct SoundBuffer;
|
||||
struct ITimer;
|
||||
struct IStreamEngine;
|
||||
|
||||
#define MAX_VIS_AREAS 256 // absolute maximum
|
||||
#define MAX_ACTIVE_SOUNDSPOTS 16
|
||||
|
||||
#define SETSCALEBIT(bit) (1<<bit)
|
||||
|
||||
#include <Cry_Camera.h>
|
||||
#define CSSPEAKERCONFIG_5POINT1 0x00000001
|
||||
#define CSSPEAKERCONFIG_HEADPHONE 0x00000002
|
||||
#define CSSPEAKERCONFIG_MONO 0x00000003
|
||||
#define CSSPEAKERCONFIG_QUAD 0x00000004
|
||||
#define CSSPEAKERCONFIG_STEREO 0x00000005
|
||||
#define CSSPEAKERCONFIG_SURROUND 0x00000006
|
||||
|
||||
#define SFXFILTER_PRIORITY CS_DSP_DEFAULTPRIORITY_SFXUNIT+1
|
||||
|
||||
struct SEAXProps
|
||||
{
|
||||
CS_REVERB_PROPERTIES EAX;
|
||||
int nPreset;
|
||||
};
|
||||
|
||||
enum ESoundActiveState
|
||||
{
|
||||
eSoundState_None,
|
||||
eSoundState_Active,
|
||||
eSoundState_Inactive
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
struct string_nocase_lt
|
||||
{
|
||||
bool operator()( const string &s1,const string &s2 ) const
|
||||
{
|
||||
return stricmp(s1.c_str(),s2.c_str()) < 0;
|
||||
}
|
||||
};
|
||||
/*
|
||||
struct SoundName
|
||||
{
|
||||
SoundName(const char *_name,bool _b3d)
|
||||
{
|
||||
name=_name;
|
||||
b3d=_b3d;
|
||||
}
|
||||
SoundName(const SoundName& o)
|
||||
{
|
||||
name=o.name;
|
||||
b3d=o.b3d;
|
||||
}
|
||||
bool operator<(const SoundName& o)const
|
||||
{
|
||||
if(b3d!=o.b3d)
|
||||
{
|
||||
if (b3d)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
return (stricmp(name.c_str(),o.name.c_str())<0);
|
||||
}
|
||||
string name;
|
||||
bool b3d;
|
||||
};*/
|
||||
|
||||
typedef std::map<SSoundBufferProps, CSoundBuffer*> SoundBufferPropsMap;
|
||||
typedef SoundBufferPropsMap::iterator SoundBufferPropsMapItor;
|
||||
|
||||
typedef std::vector<CSound*> SoundVec;
|
||||
typedef SoundVec::iterator SoundVecItor;
|
||||
|
||||
typedef std::set<CSound*> SoundList;
|
||||
typedef SoundList::iterator SoundListItor;
|
||||
|
||||
#ifdef WIN64
|
||||
#undef PlaySound
|
||||
#endif
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Sound system interface
|
||||
class CSoundSystem : public CSoundSystemCommon
|
||||
{
|
||||
protected:
|
||||
virtual ~CSoundSystem();
|
||||
public:
|
||||
CSoundSystem(ISystem* pSystem, HWND hWnd);
|
||||
|
||||
ISystem* GetSystem() const { return m_pISystem; };
|
||||
|
||||
//! DSP unit callback for sfx-lowpass filter
|
||||
void* DSPUnit_SFXFilter_Callback(void *pOriginalBuffer, void *pNewBuffer, int nLength);
|
||||
|
||||
//! retrieve sfx-filter dsp unit
|
||||
CS_DSPUNIT* GetDSPUnitFilter() { return m_pDSPUnitSFXFilter; }
|
||||
|
||||
bool IsOK() { return m_bOK; }
|
||||
|
||||
//! Release the sound
|
||||
void Release();
|
||||
|
||||
//! Update the sound
|
||||
void Update();
|
||||
|
||||
/*! Create a music-system. You should only create one music-system at a time.
|
||||
*/
|
||||
IMusicSystem* CreateMusicSystem();
|
||||
|
||||
void SetSoundActiveState(CSound *pSound, ESoundActiveState State);
|
||||
|
||||
//! Register new playing sound that should be auto stoped when it ends.
|
||||
void RegisterAutoStopSound( CSound *pSound );
|
||||
void UnregisterAutoStopSound( CSound *pSound );
|
||||
|
||||
|
||||
/*! Load a sound from disk
|
||||
@param szfile filename
|
||||
@param nFlags sound flags combination
|
||||
@return sound interface
|
||||
*/
|
||||
ISound* LoadSound(const char *szFile, int nFlags);
|
||||
|
||||
/*! Remove a sound from the sound system
|
||||
@param nSoundId sound id
|
||||
*/
|
||||
void RemoveSound(int nSoundID);
|
||||
|
||||
/*! Add sound flags (OR)
|
||||
@param nSoundId sound id
|
||||
@param nFlags additional flags
|
||||
*/
|
||||
void AddSoundFlags(int nSoundID,int nFlags);
|
||||
|
||||
/*! SetMasterVolume
|
||||
@param nVol volume (0-255)
|
||||
*/
|
||||
void SetMasterVolume(unsigned char nVol)
|
||||
{
|
||||
GUARD_HEAP;
|
||||
CS_SetSFXMasterVolume(nVol);
|
||||
}
|
||||
/*! Set the volume scale for all sounds with FLAG_SOUND_SCALABLE
|
||||
@param fScale volume scale (default 1.0)
|
||||
*/
|
||||
void SetMasterVolumeScale(float fScale, bool bForceRecalc=false);
|
||||
|
||||
/*! Remove a sound reference from the sound system
|
||||
@param nSoundId sound id
|
||||
*/
|
||||
void RemoveReference(CSound *);
|
||||
|
||||
/*! Get a sound interface from the sound system
|
||||
@param nSoundId sound id
|
||||
*/
|
||||
ISound* GetSound(int nSoundID);
|
||||
|
||||
/*! Play a sound from the sound system
|
||||
@param nSoundId sound id
|
||||
*/
|
||||
void PlaySound(int nSoundID);
|
||||
|
||||
/*! Set the listener position
|
||||
@param vPos position
|
||||
@param vVel velocity
|
||||
@param vAngles angles
|
||||
*/
|
||||
//void SetListener(const Vec3d &vPos, const Vec3d &vVel,const Vec3d& vAngles);
|
||||
void SetListener(const CCamera &cCam, const Vec3d &vVel);
|
||||
|
||||
//! Sets minimal priority for sound to be played.
|
||||
int SetMinSoundPriority( int nPriority );
|
||||
int GetMinSoundPriority() { return m_nMinSoundPriority; };
|
||||
|
||||
/*! to be called when something changes in the environment which could affect
|
||||
sound occlusion, for example a door closes etc.
|
||||
*/
|
||||
void RecomputeSoundOcclusion(bool bRecomputeListener,bool bForceRecompute,bool bReset=false);
|
||||
|
||||
void FadeOutSound(CSound *pSound);
|
||||
|
||||
//! Stop all sounds and music
|
||||
void Silence();
|
||||
|
||||
//! pause all sounds
|
||||
void Pause(bool bPause,bool bResetVolume=false);
|
||||
|
||||
//! Mute/unmute all sounds
|
||||
void Mute(bool bMute);
|
||||
|
||||
//! reset the sound system (between loading levels)
|
||||
void Reset();
|
||||
|
||||
//! Check for EAX support.
|
||||
bool IsEAX(int version);
|
||||
//! Set EAX listener environment.
|
||||
bool SetEaxListenerEnvironment(int nPreset, CS_REVERB_PROPERTIES *pProps=NULL, int nFlags=0);
|
||||
//! Gets current EAX listener environment.
|
||||
bool GetCurrentEaxEnvironment(int &nPreset, CS_REVERB_PROPERTIES &Props);
|
||||
|
||||
bool SetGroupScale(int nGroup, float fScale);
|
||||
|
||||
//! Will set speaker config
|
||||
void SetSpeakerConfig();
|
||||
|
||||
//! get memory usage info
|
||||
void GetSoundMemoryUsageInfo(size_t &nCurrentMemory,size_t &nMaxMemory);
|
||||
|
||||
//! get number of voices playing
|
||||
int GetUsedVoices();
|
||||
|
||||
//! get cpu-usuage
|
||||
float GetCPUUsage();
|
||||
|
||||
//! get music-volume
|
||||
float GetMusicVolume();
|
||||
|
||||
//! sets parameters for directional attenuation (for directional microphone effect); set fConeInDegree to 0 to disable the effect
|
||||
void CalcDirectionalAttenuation(Vec3d &Pos, Vec3d &Dir, float fConeInRadians);
|
||||
|
||||
//! returns the maximum sound-enhance-factor to use it in the binoculars as "graphical-equalizer"...
|
||||
float GetDirectionalAttenuationMaxScale() { return m_fDirAttMaxScale; }
|
||||
|
||||
//! returns if directional attenuation is used
|
||||
bool UsingDirectionalAttenuation() { return (m_fDirAttCone!=0.0f); }
|
||||
|
||||
//! remove a sound
|
||||
void RemoveBuffer(SSoundBufferProps &sn);
|
||||
|
||||
//! compute memory-consumption
|
||||
void GetMemoryUsage(class ICrySizer* pSizer);
|
||||
|
||||
//! get the current area the listener is in
|
||||
IVisArea *GetListenerArea() { return(m_pVisArea); }
|
||||
Vec3d GetListenerPos() {return(m_cCam.GetPos());}
|
||||
|
||||
void BufferLoaded(CSoundBuffer *pSoundBuffer) { m_nBuffersLoaded++; }
|
||||
void BufferUnloaded(CSoundBuffer *pSoundBuffer) { m_nBuffersLoaded--; }
|
||||
|
||||
//! Returns true if sound can be stopped.
|
||||
bool ProcessActiveSound( CSound *pSound );
|
||||
|
||||
void LockResources();
|
||||
void UnlockResources();
|
||||
|
||||
//! Return true.
|
||||
bool IsEnabled();
|
||||
|
||||
public:
|
||||
|
||||
bool m_bOK,m_bInside;
|
||||
bool m_bValidPos;
|
||||
|
||||
int m_nBuffersLoaded;
|
||||
|
||||
//SoundMap m_sounds;
|
||||
SoundBufferPropsMap m_soundBuffers;
|
||||
SoundList m_vecSounds;
|
||||
SoundList m_lstSoundSpotsInactive;
|
||||
SoundList m_lstSoundSpotsActive;
|
||||
int m_nInactiveSoundSpotsSize;
|
||||
SoundListItor m_itLastInactivePos;
|
||||
SoundList m_lstFadeUnderwaterSounds;
|
||||
|
||||
typedef std::set<_smart_ptr<CSound> > AutoStopSounds;
|
||||
AutoStopSounds m_autoStopSounds;
|
||||
//! This smart pointer list keep`s reference to stoped auto delete sounds, untill next update.
|
||||
std::vector<_smart_ptr<CSound> > m_stoppedSoundToBeDeleted;
|
||||
//int m_nLastInactiveListPos;
|
||||
std::vector<_smart_ptr<CSoundBuffer> > m_lockedResources;
|
||||
|
||||
// sfx-filter stuff //////////////////////////////////////////////////////
|
||||
CS_DSPUNIT *m_pDSPUnitSFXFilter;
|
||||
float m_fDSPUnitSFXFilterCutoff;
|
||||
float m_fDSPUnitSFXFilterResonance;
|
||||
float m_fDSPUnitSFXFilterLowLVal;
|
||||
float m_fDSPUnitSFXFilterBandLVal;
|
||||
float m_fDSPUnitSFXFilterLowRVal;
|
||||
float m_fDSPUnitSFXFilterBandRVal;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
float m_fSoundScale[MAX_SOUNDSCALE_GROUPS];
|
||||
|
||||
ISystem *m_pISystem;
|
||||
ITimer *m_pTimer;
|
||||
ILog *m_pILog;
|
||||
IStreamEngine *m_pStreamEngine;
|
||||
IVisArea *m_pVisArea;
|
||||
IVisArea *m_VisAreas[MAX_VIS_AREAS];
|
||||
char m_szEmptyName[32];
|
||||
|
||||
int m_nMuteRefCnt;
|
||||
|
||||
float m_fSFXVolume;
|
||||
float m_fSFXResetVolume;
|
||||
float m_fMusicVolume;
|
||||
int m_nSampleRate;
|
||||
|
||||
// this is used for the binocular-feature where sounds are heard according to their screen-projection
|
||||
Vec3d m_DirAttPos;
|
||||
Vec3d m_DirAttDir;
|
||||
float m_fDirAttCone;
|
||||
float m_fDirAttMaxScale;
|
||||
|
||||
CCamera m_cCam;
|
||||
|
||||
//listener infos
|
||||
Vec3d m_vPos,m_vForward,m_vTop;
|
||||
|
||||
int m_nSpeakerConfig;
|
||||
int m_nMinSoundPriority;
|
||||
bool m_bPause,m_bResetVolume;
|
||||
|
||||
int m_nLastEax;
|
||||
CS_REVERB_PROPERTIES *m_pLastEAXProps;
|
||||
|
||||
SEAXProps m_EAXIndoor;
|
||||
SEAXProps m_EAXOutdoor;
|
||||
|
||||
private:
|
||||
|
||||
//! if sound is potentially hearable
|
||||
bool IsSoundPH(CSound *pSound);
|
||||
void AddToSoundSystem(CSound *pSound,int dwFlags);
|
||||
void DeactivateSound( CSound *pSound );
|
||||
};
|
||||
|
||||
#endif // CRYSOUND_SOUNDSYSTEM_H
|
||||
118
CrySoundSystem/SoundSystemCommon.cpp
Normal file
118
CrySoundSystem/SoundSystemCommon.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
#include "StdAfx.h"
|
||||
#include <ISystem.h>
|
||||
#include <IConsole.h>
|
||||
#include "soundsystemcommon.h"
|
||||
|
||||
CSoundSystemCommon::CSoundSystemCommon(ISystem* pSystem)
|
||||
{
|
||||
m_pCVARDummySound= pSystem->GetIConsole()->CreateVariable("s_DummySound","0",VF_DUMPTODISK,
|
||||
"Toggles dummy(NULL) sound system.\n");
|
||||
m_pCVARSoundEnable= pSystem->GetIConsole()->CreateVariable("s_SoundEnable","1",VF_DUMPTODISK,
|
||||
"Toggles sound on and off.\n"
|
||||
"Usage: s_SoundEnable [0/1]\n"
|
||||
"Default is 1 (on). Set to 0 to disable sound.");
|
||||
m_pCVarMaxSoundDist= pSystem->GetIConsole()->CreateVariable("s_MaxSoundDist","500",VF_DUMPTODISK,
|
||||
"Sets the maximum sound distance, in metres. Default is 500 metres.\n"
|
||||
"Usage: s_MaxSoundDist 500");
|
||||
m_pCVarDopplerEnable = pSystem->GetIConsole()->CreateVariable("s_DopplerEnable","0",VF_DUMPTODISK,
|
||||
"Toggles Doppler effect on and off.\n"
|
||||
"Usage: s_DopplerEnable [0/1]\n"
|
||||
"Default is 0 (off).");
|
||||
m_pCVarDopplerValue = pSystem->GetIConsole()->CreateVariable("s_DopplerValue","1.0",VF_DUMPTODISK,
|
||||
"Sets the strength of the Doppler effect.\n"
|
||||
"Usage: s_DopplerValue 1.0"
|
||||
"Default is 1.0. This multiplier affects the sound velocity.");
|
||||
m_pCVarSFXVolume = pSystem->GetIConsole()->CreateVariable("s_SFXVolume","1",VF_DUMPTODISK,
|
||||
"Sets the percentile volume of the sound effects.\n"
|
||||
"Usage: s_SFXVolume 0.5\n"
|
||||
"Default is 1, which is full volume.");
|
||||
m_pCVarMusicVolume = pSystem->GetIConsole()->CreateVariable("s_MusicVolume","0.5",VF_DUMPTODISK,
|
||||
"Sets the music volume from 0 to 1.\n"
|
||||
"Usage: s_MusicVolume 7\n"
|
||||
"Default is 1, which is full volume.");
|
||||
m_pCVarSampleRate = pSystem->GetIConsole()->CreateVariable("s_SampleRate","44100",VF_DUMPTODISK,
|
||||
"Sets the output sample rate.\n"
|
||||
"Usage: s_SampleRate 44100\n"
|
||||
"Default is 44100. Sets the rate, in samples per second,\n"
|
||||
"at which the output of the sound system is played.");
|
||||
m_pCVarSpeakerConfig = pSystem->GetIConsole()->CreateVariable("s_SpeakerConfig","5",VF_DUMPTODISK,
|
||||
"Sets up the preferred speaker configuration.\n"
|
||||
"Usage: s_SpeakerConfig #\n"
|
||||
"where # is a number between 1 and 6 representing\n"
|
||||
" 1: 5.1\n"
|
||||
" 2: Headphones\n"
|
||||
" 3: Mono\n"
|
||||
" 4: Quad\n"
|
||||
" 5: Stereo\n"
|
||||
" 6: Surround\n"
|
||||
"Default is 5 (Stereo).");
|
||||
m_pCVarEnableSoundFX = pSystem->GetIConsole()->CreateVariable("s_EnableSoundFX","1",VF_DUMPTODISK,
|
||||
"Toggles sound effects on and off.\n"
|
||||
"Usage: s_EnableSoundFX [0/1]\n"
|
||||
"Default is 1 (on).");
|
||||
m_pCVarDebugSound = pSystem->GetIConsole()->CreateVariable("s_DebugSound","0",VF_CHEAT,
|
||||
"Toggles sound debugging mode.\n"
|
||||
"Usage: s_DebugSound [0/1]\n"
|
||||
"Default is 0 (off).");
|
||||
m_pCVarSoundInfo = pSystem->GetIConsole()->CreateVariable("s_SoundInfo","0",VF_CHEAT,
|
||||
"Toggles onscreen sound statistics.\n"
|
||||
"Usage: s_SoundInfo [0/1]"
|
||||
"Default is 0 (off). Set to 1 to display sound information.");
|
||||
m_pCVarInactiveSoundIterationTimeout = pSystem->GetIConsole()->CreateVariable("s_InactiveSoundIterationTimeout","1",VF_DUMPTODISK,
|
||||
"This variable is for internal use only.");
|
||||
m_pCVarMinHWChannels = pSystem->GetIConsole()->CreateVariable("s_MinHWChannels","16",VF_DUMPTODISK,
|
||||
"Sets the minimum number of sound hardware channels used./n"
|
||||
"Usage: s_MinHWChannels 16\n"
|
||||
"Default value is 16. This is the number of hardware channels\n"
|
||||
"used to play back game sound. If the hardware does not have\n"
|
||||
"the required channels, the system will use software mixing,\n"
|
||||
"resulting in reduced performance (no eax).");
|
||||
// 28 = hw mixing
|
||||
m_pCVarMaxHWChannels= pSystem->GetIConsole()->CreateVariable("s_MaxHWChannels","28",VF_DUMPTODISK,
|
||||
"Sets the maximum number of sound hardware channels used./n"
|
||||
"0=software mixing.");
|
||||
m_pCVarVisAreaProp=pSystem->GetIConsole()->CreateVariable("s_VisAreasPropagation","10",VF_DUMPTODISK,
|
||||
"Sets the vis area propagation number.\n"
|
||||
"Usage: s_VisAreasPropagation 5\n"
|
||||
"Default is 10. This number defines how far sound will\n"
|
||||
"propagate, in vis areas from the player's position. A\n"
|
||||
"value of 1 means the sound is only heard in the current\n"
|
||||
"vis area, while 2 means sound is heard in adjacent areas.");
|
||||
m_pCVarMaxSoundSpots=pSystem->GetIConsole()->CreateVariable("s_MaxActiveSoundSpots","100",VF_DUMPTODISK,
|
||||
"Sets the maximum number of active soundspots.\n");
|
||||
m_pCVarMinRepeatSoundTimeout = pSystem->GetIConsole()->CreateVariable("s_MinRepeatSoundTimeout","200",VF_DUMPTODISK,
|
||||
"Timeout in ms,play of same sounds cannot be repeated more often then that.\n");
|
||||
m_pCVarCompatibleMode = pSystem->GetIConsole()->CreateVariable("s_CompatibleMode","0",VF_DUMPTODISK,
|
||||
"Toggles sound system compatible mode ON/OFF. Use only in case of playback issues.\n");
|
||||
m_pCVarCapsCheck= pSystem->GetIConsole()->CreateVariable("s_CapsCheck","0",VF_DUMPTODISK,
|
||||
"Checks for sound CAPS on startup and write them into the log.\n");
|
||||
}
|
||||
|
||||
CSoundSystemCommon::~CSoundSystemCommon()
|
||||
{
|
||||
m_pCVARDummySound->Release();
|
||||
m_pCVARSoundEnable->Release();
|
||||
m_pCVarMaxSoundDist->Release();
|
||||
m_pCVarDopplerEnable->Release();
|
||||
m_pCVarDopplerValue->Release();
|
||||
m_pCVarSFXVolume->Release();
|
||||
m_pCVarMusicVolume->Release();
|
||||
m_pCVarSampleRate->Release();
|
||||
m_pCVarSpeakerConfig->Release();
|
||||
m_pCVarEnableSoundFX->Release();
|
||||
m_pCVarDebugSound->Release();
|
||||
m_pCVarSoundInfo->Release();
|
||||
m_pCVarInactiveSoundIterationTimeout->Release();
|
||||
m_pCVarMinHWChannels->Release();
|
||||
m_pCVarMaxHWChannels->Release();
|
||||
m_pCVarVisAreaProp->Release();
|
||||
m_pCVarMaxSoundSpots->Release();
|
||||
m_pCVarMinRepeatSoundTimeout->Release();
|
||||
m_pCVarCompatibleMode->Release();
|
||||
m_pCVarCapsCheck->Release();
|
||||
}
|
||||
|
||||
bool CSoundSystemCommon::DebuggingSound()
|
||||
{
|
||||
return (m_pCVarDebugSound!=NULL) && (m_pCVarDebugSound->GetIVal()!=0);
|
||||
}
|
||||
40
CrySoundSystem/SoundSystemCommon.h
Normal file
40
CrySoundSystem/SoundSystemCommon.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
struct ISystem;
|
||||
struct ICVar;
|
||||
|
||||
class CSoundSystemCommon : public ISoundSystem
|
||||
{
|
||||
public:
|
||||
|
||||
CSoundSystemCommon(ISystem* pSystem);
|
||||
virtual ~CSoundSystemCommon();
|
||||
bool DebuggingSound();
|
||||
|
||||
//enable playback of sounds
|
||||
ICVar *m_pCVARSoundEnable;
|
||||
|
||||
ICVar *m_pCVARDummySound;
|
||||
|
||||
//max sound distance
|
||||
ICVar *m_pCVarMaxSoundDist;
|
||||
|
||||
ICVar *m_pCVarDopplerEnable;
|
||||
ICVar *m_pCVarDopplerValue;
|
||||
|
||||
ICVar *m_pCVarSFXVolume;
|
||||
ICVar *m_pCVarMusicVolume;
|
||||
ICVar *m_pCVarSampleRate;
|
||||
ICVar *m_pCVarSpeakerConfig;
|
||||
ICVar *m_pCVarEnableSoundFX;
|
||||
ICVar *m_pCVarDebugSound;
|
||||
ICVar *m_pCVarSoundInfo;
|
||||
ICVar *m_pCVarInactiveSoundIterationTimeout;
|
||||
ICVar *m_pCVarMinHWChannels;
|
||||
ICVar *m_pCVarMaxHWChannels;
|
||||
ICVar *m_pCVarVisAreaProp;
|
||||
ICVar *m_pCVarMaxSoundSpots;
|
||||
ICVar *m_pCVarMinRepeatSoundTimeout;
|
||||
ICVar *m_pCVarCompatibleMode;
|
||||
ICVar *m_pCVarCapsCheck;
|
||||
};
|
||||
10
CrySoundSystem/StdAfx.cpp
Normal file
10
CrySoundSystem/StdAfx.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// CrySound.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#pragma warning( disable:4786 )
|
||||
#include "stdafx.h"
|
||||
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
||||
118
CrySoundSystem/StdAfx.h
Normal file
118
CrySoundSystem/StdAfx.h
Normal file
@@ -0,0 +1,118 @@
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#if !defined(AFX_STDAFX_H__9793C644_C91F_4BA6_A176_44537782901A__INCLUDED_)
|
||||
#define AFX_STDAFX_H__9793C644_C91F_4BA6_A176_44537782901A__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// THIS MUST BE AT THE VERY BEGINING OF STDAFX.H FILE.
|
||||
// Sound must use MultiThread safe STL.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//#define _NOTHREADS
|
||||
//#define _STLP_NO_THREADS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#pragma warning( disable:4786 ) //Disable "identifier was truncated to '255' characters" warning.
|
||||
|
||||
#ifndef _XBOX
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#else
|
||||
#include <xtl.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#define NOT_USE_CRY_MEMORY_MANAGER
|
||||
#include <platform.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <ILog.h>
|
||||
#include <IConsole.h>
|
||||
#include <ISound.h>
|
||||
#include <ISystem.h>
|
||||
#ifdef WIN64
|
||||
#include <CrySound64.h>
|
||||
#else
|
||||
#include <CrySound.h>
|
||||
#endif
|
||||
#include <Cry_Math.h>
|
||||
//#include <vector.h>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef PS2
|
||||
inline void __CRYTEKDLL_TRACE(const char *sFormat, ... )
|
||||
#else
|
||||
_inline void __cdecl __CRYTEKDLL_TRACE(const char *sFormat, ... )
|
||||
#endif
|
||||
{
|
||||
va_list vl;
|
||||
static char sTraceString[1024];
|
||||
|
||||
va_start(vl, sFormat);
|
||||
vsprintf(sTraceString, sFormat, vl);
|
||||
va_end(vl);
|
||||
|
||||
strcat(sTraceString, "\n");
|
||||
|
||||
::OutputDebugString(sTraceString);
|
||||
}
|
||||
|
||||
#define TRACE __CRYTEKDLL_TRACE
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifdef WIN32
|
||||
#include <crtdbg.h>
|
||||
#define DEBUG_NEW_NORMAL_CLIENTBLOCK(file, line) new(_NORMAL_BLOCK, file, line)
|
||||
#define new DEBUG_NEW_NORMAL_CLIENTBLOCK( __FILE__, __LINE__)
|
||||
#define calloc(s,t) _calloc_dbg(s, t, _NORMAL_BLOCK, __FILE__, __LINE__)
|
||||
#define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)
|
||||
#define realloc(p, s) _realloc_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__)
|
||||
#endif //WIN32
|
||||
|
||||
#ifdef ASSERT
|
||||
#undef ASSERT
|
||||
#endif
|
||||
|
||||
#ifdef WIN64
|
||||
#define ASSERT(x) {assert(x);}
|
||||
#else
|
||||
|
||||
#define ASSERT(x) { if (!(x)) { TRACE("Assertion Failed (%s) File: \"%s\" Line: %d\n", #x, __FILE__, __LINE__); _asm { int 3 } } }
|
||||
#endif // WIN64
|
||||
|
||||
#else
|
||||
#define ASSERT(x) {assert(x);}
|
||||
|
||||
#endif //_DEBUG
|
||||
|
||||
class CHeapGuardian
|
||||
{
|
||||
public: CHeapGuardian() {assert (IsHeapValid());} ~CHeapGuardian() {assert (IsHeapValid());}
|
||||
};
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define GUARD_HEAP //CHeapGuardian __heap_guardian
|
||||
#else
|
||||
#define GUARD_HEAP
|
||||
#endif
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_STDAFX_H__9793C644_C91F_4BA6_A176_44537782901A__INCLUDED_)
|
||||
BIN
CrySoundSystem/crysound.lib
Normal file
BIN
CrySoundSystem/crysound.lib
Normal file
Binary file not shown.
BIN
CrySoundSystem/crysound64.lib
Normal file
BIN
CrySoundSystem/crysound64.lib
Normal file
Binary file not shown.
BIN
CrySoundSystem/crysound64d.lib
Normal file
BIN
CrySoundSystem/crysound64d.lib
Normal file
Binary file not shown.
BIN
CrySoundSystem/crysoundvc.lib
Normal file
BIN
CrySoundSystem/crysoundvc.lib
Normal file
Binary file not shown.
BIN
CrySoundSystem/ogg_static.lib
Normal file
BIN
CrySoundSystem/ogg_static.lib
Normal file
Binary file not shown.
BIN
CrySoundSystem/ogg_static_d64.lib
Normal file
BIN
CrySoundSystem/ogg_static_d64.lib
Normal file
Binary file not shown.
BIN
CrySoundSystem/ogg_static_r64.lib
Normal file
BIN
CrySoundSystem/ogg_static_r64.lib
Normal file
Binary file not shown.
BIN
CrySoundSystem/vorbis_static.lib
Normal file
BIN
CrySoundSystem/vorbis_static.lib
Normal file
Binary file not shown.
BIN
CrySoundSystem/vorbis_static_d64.lib
Normal file
BIN
CrySoundSystem/vorbis_static_d64.lib
Normal file
Binary file not shown.
BIN
CrySoundSystem/vorbis_static_r64.lib
Normal file
BIN
CrySoundSystem/vorbis_static_r64.lib
Normal file
Binary file not shown.
BIN
CrySoundSystem/vorbisfile_static.lib
Normal file
BIN
CrySoundSystem/vorbisfile_static.lib
Normal file
Binary file not shown.
BIN
CrySoundSystem/vorbisfile_static_d64.lib
Normal file
BIN
CrySoundSystem/vorbisfile_static_d64.lib
Normal file
Binary file not shown.
BIN
CrySoundSystem/vorbisfile_static_r64.lib
Normal file
BIN
CrySoundSystem/vorbisfile_static_r64.lib
Normal file
Binary file not shown.
Reference in New Issue
Block a user