Files
FC1/CrySoundSystem/MusicPattern.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

296 lines
6.8 KiB
C++

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