summaryrefslogtreecommitdiff
path: root/tier2/soundutils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tier2/soundutils.cpp')
-rw-r--r--tier2/soundutils.cpp237
1 files changed, 237 insertions, 0 deletions
diff --git a/tier2/soundutils.cpp b/tier2/soundutils.cpp
new file mode 100644
index 0000000..bebda85
--- /dev/null
+++ b/tier2/soundutils.cpp
@@ -0,0 +1,237 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Helper methods + classes for sound
+//
+//===========================================================================//
+
+#include "tier2/soundutils.h"
+#include "tier2/riff.h"
+#include "tier2/tier2.h"
+#include "filesystem.h"
+
+#ifdef IS_WINDOWS_PC
+
+#include <windows.h> // WAVEFORMATEX, WAVEFORMAT and ADPCM WAVEFORMAT!!!
+#include <mmreg.h>
+
+#else
+
+#ifdef _X360
+#include "xbox/xbox_win32stubs.h" // WAVEFORMATEX, WAVEFORMAT and ADPCM WAVEFORMAT!!!
+#endif
+
+#endif
+
+//-----------------------------------------------------------------------------
+// RIFF reader/writers that use the file system
+//-----------------------------------------------------------------------------
+class CFSIOReadBinary : public IFileReadBinary
+{
+public:
+ // inherited from IFileReadBinary
+ virtual int open( const char *pFileName );
+ virtual int read( void *pOutput, int size, int file );
+ virtual void seek( int file, int pos );
+ virtual unsigned int tell( int file );
+ virtual unsigned int size( int file );
+ virtual void close( int file );
+};
+
+class CFSIOWriteBinary : public IFileWriteBinary
+{
+public:
+ virtual int create( const char *pFileName );
+ virtual int write( void *pData, int size, int file );
+ virtual void close( int file );
+ virtual void seek( int file, int pos );
+ virtual unsigned int tell( int file );
+};
+
+
+//-----------------------------------------------------------------------------
+// Singletons
+//-----------------------------------------------------------------------------
+static CFSIOReadBinary s_FSIoIn;
+static CFSIOWriteBinary s_FSIoOut;
+
+IFileReadBinary *g_pFSIOReadBinary = &s_FSIoIn;
+IFileWriteBinary *g_pFSIOWriteBinary = &s_FSIoOut;
+
+
+//-----------------------------------------------------------------------------
+// RIFF reader that use the file system
+//-----------------------------------------------------------------------------
+int CFSIOReadBinary::open( const char *pFileName )
+{
+ return (int)g_pFullFileSystem->Open( pFileName, "rb" );
+}
+
+int CFSIOReadBinary::read( void *pOutput, int size, int file )
+{
+ if ( !file )
+ return 0;
+
+ return g_pFullFileSystem->Read( pOutput, size, (FileHandle_t)file );
+}
+
+void CFSIOReadBinary::seek( int file, int pos )
+{
+ if ( !file )
+ return;
+
+ g_pFullFileSystem->Seek( (FileHandle_t)file, pos, FILESYSTEM_SEEK_HEAD );
+}
+
+unsigned int CFSIOReadBinary::tell( int file )
+{
+ if ( !file )
+ return 0;
+
+ return g_pFullFileSystem->Tell( (FileHandle_t)file );
+}
+
+unsigned int CFSIOReadBinary::size( int file )
+{
+ if ( !file )
+ return 0;
+
+ return g_pFullFileSystem->Size( (FileHandle_t)file );
+}
+
+void CFSIOReadBinary::close( int file )
+{
+ if ( !file )
+ return;
+
+ g_pFullFileSystem->Close( (FileHandle_t)file );
+}
+
+
+//-----------------------------------------------------------------------------
+// RIFF writer that use the file system
+//-----------------------------------------------------------------------------
+int CFSIOWriteBinary::create( const char *pFileName )
+{
+ g_pFullFileSystem->SetFileWritable( pFileName, true );
+ return (int)g_pFullFileSystem->Open( pFileName, "wb" );
+}
+
+int CFSIOWriteBinary::write( void *pData, int size, int file )
+{
+ return g_pFullFileSystem->Write( pData, size, (FileHandle_t)file );
+}
+
+void CFSIOWriteBinary::close( int file )
+{
+ g_pFullFileSystem->Close( (FileHandle_t)file );
+}
+
+void CFSIOWriteBinary::seek( int file, int pos )
+{
+ g_pFullFileSystem->Seek( (FileHandle_t)file, pos, FILESYSTEM_SEEK_HEAD );
+}
+
+unsigned int CFSIOWriteBinary::tell( int file )
+{
+ return g_pFullFileSystem->Tell( (FileHandle_t)file );
+}
+
+
+#ifndef POSIX
+//-----------------------------------------------------------------------------
+// Returns the duration of a wav file
+//-----------------------------------------------------------------------------
+float GetWavSoundDuration( const char *pWavFile )
+{
+ InFileRIFF riff( pWavFile, *g_pFSIOReadBinary );
+
+ // UNDONE: Don't use printf to handle errors
+ if ( riff.RIFFName() != RIFF_WAVE )
+ return 0.0f;
+
+ int nDataSize = 0;
+
+ // set up the iterator for the whole file (root RIFF is a chunk)
+ IterateRIFF walk( riff, riff.RIFFSize() );
+
+ // This chunk must be first as it contains the wave's format
+ // break out when we've parsed it
+ char pFormatBuffer[ 1024 ];
+ int nFormatSize;
+ bool bFound = false;
+ for ( ; walk.ChunkAvailable( ); walk.ChunkNext() )
+ {
+ switch ( walk.ChunkName() )
+ {
+ case WAVE_FMT:
+ bFound = true;
+ if ( walk.ChunkSize() > sizeof(pFormatBuffer) )
+ {
+ Warning( "oops, format tag too big!!!" );
+ return 0.0f;
+ }
+
+ nFormatSize = walk.ChunkSize();
+ walk.ChunkRead( pFormatBuffer );
+ break;
+
+ case WAVE_DATA:
+ nDataSize += walk.ChunkSize();
+ break;
+ }
+ }
+
+ if ( !bFound )
+ return 0.0f;
+
+ const WAVEFORMATEX *pHeader = (const WAVEFORMATEX *)pFormatBuffer;
+
+ int format = pHeader->wFormatTag;
+
+ int nBits = pHeader->wBitsPerSample;
+ int nRate = pHeader->nSamplesPerSec;
+ int nChannels = pHeader->nChannels;
+ int nSampleSize = ( nBits * nChannels ) / 8;
+
+ // this can never be zero -- other functions divide by this.
+ // This should never happen, but avoid crashing
+ if ( nSampleSize <= 0 )
+ {
+ nSampleSize = 1;
+ }
+
+ int nSampleCount = 0;
+ float flTrueSampleSize = nSampleSize;
+
+ if ( format == WAVE_FORMAT_ADPCM )
+ {
+ nSampleSize = 1;
+
+ ADPCMWAVEFORMAT *pFormat = (ADPCMWAVEFORMAT *)pFormatBuffer;
+ int blockSize = ((pFormat->wSamplesPerBlock - 2) * pFormat->wfx.nChannels ) / 2;
+ blockSize += 7 * pFormat->wfx.nChannels;
+
+ int blockCount = nSampleCount / blockSize;
+ int blockRem = nSampleCount % blockSize;
+
+ // total samples in complete blocks
+ nSampleCount = blockCount * pFormat->wSamplesPerBlock;
+
+ // add remaining in a short block
+ if ( blockRem )
+ {
+ nSampleCount += pFormat->wSamplesPerBlock - (((blockSize - blockRem) * 2) / nChannels);
+ }
+
+ flTrueSampleSize = 0.5f;
+
+ }
+ else
+ {
+ nSampleCount = nDataSize / nSampleSize;
+ }
+
+ float flDuration = (float)nSampleCount / (float)nRate;
+ return flDuration;
+}
+#endif