This commit is contained in:
romkazvo
2023-08-07 19:29:24 +08:00
commit 34d6c5d489
4832 changed files with 1389451 additions and 0 deletions

View 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;
}

View 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
};

View 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>

View 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>

View 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"
}

View File

@@ -0,0 +1,227 @@
<?xml version="1.0" encoding = "windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.00"
Name="CrySoundSystem_XBox"
SccProjectName="&quot;$/Game01/CrySoundSystem&quot;, 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>

View 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"
}

View 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
View 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_

View 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

View 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;
}
}
}
};

View 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);
}

View 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);
};

View 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;
}

View 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();
};

File diff suppressed because it is too large Load Diff

View 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); }
};

View 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;
}

View 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);
};

View 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 */

View 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 */

View 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

View 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

View 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

View 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;
}

View 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);
};

View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

264
CrySoundSystem/Sound.h Normal file
View 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

View 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());
}

View 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;

File diff suppressed because it is too large Load Diff

View 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

View 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);
}

View 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
View 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
View 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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.