123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848 |
- /*
- ===========================================================================
- Doom 3 GPL Source Code
- Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
- Doom 3 Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #include "../../idlib/precompiled.h"
- #pragma hdrstop
- // DirectX SDK
- #include <DxErr.h>
- #include <ks.h>
- #include <ksmedia.h>
- #include "../../sound/snd_local.h"
- #include "win_local.h"
- #include "../../openal/idal.cpp"
- #define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
- #define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } }
- #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
- class idAudioBufferWIN32 : public idAudioBuffer {
- public:
- idAudioBufferWIN32( LPDIRECTSOUNDBUFFER apDSBuffer, dword dwDSBufferSize, idWaveFile* pWaveFile=NULL );
- ~idAudioBufferWIN32();
- int FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, bool bRepeatWavIfBufferLarger );
- bool Lock( void **pDSLockedBuffer, ulong *dwDSLockedBufferSize );
- bool Unlock(void *pDSLockedBuffer, dword dwDSLockedBufferSize );
- bool GetCurrentPosition( ulong *pdwCurrentWriteCursor );
- int Play( dword dwPriority=0, dword dwFlags=0 );
- int Stop( void );
- int Reset( void );
- bool IsSoundPlaying( void );
- void SetVolume( float x);
- idWaveFile* m_pWaveFile;
- private:
- LPDIRECTSOUNDBUFFER m_apDSBuffer;
- dword m_dwDSBufferSize;
- int RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, bool* pbWasRestored );
- };
- class idAudioHardwareWIN32 : public idAudioHardware {
- public:
- idAudioHardwareWIN32();
- ~idAudioHardwareWIN32();
- bool Initialize( );
- bool InitializeSpeakers( byte *buffer, int bufferSize, dword dwPrimaryFreq, dword dwPrimaryBitRate, dword dwSpeakers );
- void SetPrimaryBufferFormat( dword dwPrimaryFreq, dword dwPrimaryBitRate, dword dwSpeakers );
- int Create( idWaveFile* pWaveFile, idAudioBuffer** ppiab );
- int Create( idAudioBuffer** ppSound, const char* strWaveFileName, dword dwCreationFlags = 0 );
- int CreateFromMemory( idAudioBufferWIN32** ppSound, byte* pbData, ulong ulDataSize, waveformatextensible_t *pwfx, dword dwCreationFlags = 0 );
- bool Lock( void **pDSLockedBuffer, ulong *dwDSLockedBufferSize );
- bool Unlock( void *pDSLockedBuffer, dword dwDSLockedBufferSize );
- bool GetCurrentPosition( ulong *pdwCurrentWriteCursor );
-
- int GetNumberOfSpeakers() { return numSpeakers; }
- int GetMixBufferSize() { return MIXBUFFER_SAMPLES * blockAlign; }
- // WIN32 driver doesn't support write API
- bool Flush( void ) { return true; }
- void Write( bool ) { }
- short* GetMixBuffer( void ) { return NULL; }
- private:
- LPDIRECTSOUND m_pDS;
- LPDIRECTSOUNDBUFFER pDSBPrimary;
- idAudioBufferWIN32 *speakers;
- int numSpeakers;
- int bitsPerSample;
- int bufferSize; // allocate buffer handed over to DirectSound
- int blockAlign; // channels * bits per sample / 8: sound frame size
- };
- idAudioHardware *idAudioHardware::Alloc() { return new idAudioHardwareWIN32; }
- idAudioHardware::~idAudioHardware() {}
- /*
- ================
- idAudioHardwareWIN32::idAudioHardware
- ================
- */
- idAudioHardwareWIN32::idAudioHardwareWIN32() {
- m_pDS = NULL;
- pDSBPrimary = NULL;
- speakers = NULL;
- }
- /*
- ================
- idAudioHardwareWIN32::~idAudioHardware
- ================
- */
- idAudioHardwareWIN32::~idAudioHardwareWIN32() {
- SAFE_DELETE( speakers );
- SAFE_RELEASE( pDSBPrimary );
- SAFE_RELEASE( m_pDS );
- }
- /*
- ===============
- idAudioHardwareWIN32::Initialize
- ===============
- */
- bool idAudioHardwareWIN32::Initialize( void ) {
- int hr;
- bufferSize = 0;
- numSpeakers = 0;
- blockAlign = 0;
- SAFE_RELEASE( m_pDS );
- // Create IDirectSound using the primary sound device
- if( FAILED( hr = DirectSoundCreate( NULL, &m_pDS, NULL ) )) {
- return false;
- }
- // Set primary buffer format
- SetPrimaryBufferFormat( PRIMARYFREQ, 16, idSoundSystemLocal::s_numberOfSpeakers.GetInteger() );
- return true;
- }
- /*
- ===============
- idAudioHardwareWIN32::InitializeSpeakers
- ===============
- */
- bool idAudioHardwareWIN32::InitializeSpeakers( byte *speakerData, int bufferSize, dword dwPrimaryFreq, dword dwPrimaryBitRate, dword dwSpeakers ) {
- if ( dwSpeakers == 2 ) {
- WAVEFORMATEXTENSIBLE wfx;
- ZeroMemory( &wfx, sizeof(WAVEFORMATEXTENSIBLE) );
- wfx.Format.wFormatTag = WAVE_FORMAT_PCM;
- wfx.Format.nChannels = 2;
- wfx.Format.nSamplesPerSec = dwPrimaryFreq;
- wfx.Format.wBitsPerSample = dwPrimaryBitRate;
- wfx.Format.nBlockAlign = wfx.Format.wBitsPerSample / 8 * wfx.Format.nChannels;
- wfx.Format.nAvgBytesPerSec = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign;
- wfx.Format.cbSize = sizeof(WAVEFORMATEX);
- CreateFromMemory( &speakers, speakerData, bufferSize, (waveformatextensible_t *)&wfx );
- common->Printf("sound: STEREO\n");
- } else {
- WAVEFORMATEXTENSIBLE waveFormatPCMEx;
- ZeroMemory( &waveFormatPCMEx, sizeof(WAVEFORMATEXTENSIBLE) );
- waveFormatPCMEx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
- waveFormatPCMEx.Format.nChannels = 6;
- waveFormatPCMEx.Format.nSamplesPerSec = dwPrimaryFreq;
- waveFormatPCMEx.Format.wBitsPerSample = dwPrimaryBitRate;
- waveFormatPCMEx.Format.nBlockAlign = waveFormatPCMEx.Format.wBitsPerSample / 8 * waveFormatPCMEx.Format.nChannels;
- waveFormatPCMEx.Format.nAvgBytesPerSec = waveFormatPCMEx.Format.nSamplesPerSec * waveFormatPCMEx.Format.nBlockAlign;
- waveFormatPCMEx.dwChannelMask = KSAUDIO_SPEAKER_5POINT1;
- // SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT |
- // SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |
- // SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT
- waveFormatPCMEx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; // Specify PCM
- waveFormatPCMEx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE);
- waveFormatPCMEx.Samples.wValidBitsPerSample = 16;
- CreateFromMemory( &speakers, speakerData, bufferSize, (waveformatextensible_t *)&waveFormatPCMEx );
- common->Printf("sound: MULTICHANNEL\n");
- }
- if (!speakers) {
- return false;
- }
- speakers->Play(0,DSBPLAY_LOOPING);
- return true;
- }
- /*
- ===============
- idAudioHardwareWIN32::SetPrimaryBufferFormat
- Set primary buffer to a specified format
- For example, to set the primary buffer format to 22kHz stereo, 16-bit
- then: dwPrimaryChannels = 2
- dwPrimaryFreq = 22050,
- dwPrimaryBitRate = 16
- ===============
- */
- void idAudioHardwareWIN32::SetPrimaryBufferFormat( dword dwPrimaryFreq, dword dwPrimaryBitRate, dword dwSpeakers ) {
- HRESULT hr;
- if( m_pDS == NULL ) {
- return;
- }
- ulong cfgSpeakers;
- m_pDS->GetSpeakerConfig( &cfgSpeakers );
- DSCAPS dscaps;
- dscaps.dwSize = sizeof(DSCAPS);
- m_pDS->GetCaps(&dscaps);
- if (dscaps.dwFlags & DSCAPS_EMULDRIVER) {
- return;
- }
- // Get the primary buffer
- DSBUFFERDESC dsbd;
- ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
- dsbd.dwSize = sizeof(DSBUFFERDESC);
- dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
- dsbd.dwBufferBytes = 0;
- dsbd.lpwfxFormat = NULL;
-
- // Obtain write-primary cooperative level.
- if( FAILED( hr = m_pDS->SetCooperativeLevel(win32.hWnd, DSSCL_PRIORITY ) ) ) {
- DXTRACE_ERR( TEXT("SetPrimaryBufferFormat"), hr );
- return;
- }
- if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) ) {
- return;
- }
- if ( dwSpeakers == 6 && (cfgSpeakers == DSSPEAKER_5POINT1 || cfgSpeakers == DSSPEAKER_SURROUND) ) {
- WAVEFORMATEXTENSIBLE waveFormatPCMEx;
- ZeroMemory( &waveFormatPCMEx, sizeof(WAVEFORMATEXTENSIBLE) );
- waveFormatPCMEx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
- waveFormatPCMEx.Format.nChannels = 6;
- waveFormatPCMEx.Format.nSamplesPerSec = dwPrimaryFreq;
- waveFormatPCMEx.Format.wBitsPerSample = (WORD) dwPrimaryBitRate;
- waveFormatPCMEx.Format.nBlockAlign = waveFormatPCMEx.Format.wBitsPerSample / 8 * waveFormatPCMEx.Format.nChannels;
- waveFormatPCMEx.Format.nAvgBytesPerSec = waveFormatPCMEx.Format.nSamplesPerSec * waveFormatPCMEx.Format.nBlockAlign;
- waveFormatPCMEx.dwChannelMask = KSAUDIO_SPEAKER_5POINT1;
- // SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT |
- // SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |
- // SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT
- waveFormatPCMEx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; // Specify PCM
- waveFormatPCMEx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE);
- waveFormatPCMEx.Samples.wValidBitsPerSample = 16;
- if( FAILED( hr = pDSBPrimary->SetFormat((WAVEFORMATEX*)&waveFormatPCMEx) ) ) {
- DXTRACE_ERR( TEXT("SetPrimaryBufferFormat"), hr );
- return;
- }
- numSpeakers = 6; // force it to think 5.1
- blockAlign = waveFormatPCMEx.Format.nBlockAlign;
- } else {
- if (dwSpeakers == 6) {
- common->Printf("sound: hardware reported unable to use multisound, defaulted to stereo\n");
- }
- WAVEFORMATEX wfx;
- ZeroMemory( &wfx, sizeof(WAVEFORMATEX) );
- wfx.wFormatTag = WAVE_FORMAT_PCM;
- wfx.nChannels = 2;
- wfx.nSamplesPerSec = dwPrimaryFreq;
- wfx.wBitsPerSample = (WORD) dwPrimaryBitRate;
- wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels;
- wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
- wfx.cbSize = sizeof(WAVEFORMATEX);
- if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) ) {
- return;
- }
- numSpeakers = 2; // force it to think stereo
- blockAlign = wfx.nBlockAlign;
- }
- byte *speakerData;
- bufferSize = MIXBUFFER_SAMPLES * sizeof(word) * numSpeakers * ROOM_SLICES_IN_BUFFER;
- speakerData = (byte *)Mem_Alloc( bufferSize );
- memset( speakerData, 0, bufferSize );
- InitializeSpeakers( speakerData, bufferSize, dwPrimaryFreq, dwPrimaryBitRate, numSpeakers );
- }
- /*
- ===============
- idAudioHardwareWIN32::Create
- ===============
- */
- int idAudioHardwareWIN32::Create( idAudioBuffer** ppSound,
- const char* strWaveFileName,
- dword dwCreationFlags ) {
- int hr;
- LPDIRECTSOUNDBUFFER apDSBuffer = NULL;
- dword dwDSBufferSize = NULL;
- idWaveFile* pWaveFile = NULL;
- if( m_pDS == NULL )
- return -1;
- if( strWaveFileName == NULL || ppSound == NULL )
- return -1;
- pWaveFile = new idWaveFile();
- pWaveFile->Open( strWaveFileName, NULL );
- if( pWaveFile->GetOutputSize() == 0 ) {
- // Wave is blank, so don't create it.
- hr = E_FAIL;
- goto LFail;
- }
- // Make the DirectSound buffer the same size as the wav file
- dwDSBufferSize = pWaveFile->GetOutputSize();
- // Create the direct sound buffer, and only request the flags needed
- // since each requires some overhead and limits if the buffer can
- // be hardware accelerated
- DSBUFFERDESC dsbd;
- memset( &dsbd, 0, sizeof(DSBUFFERDESC) );
- dsbd.dwSize = sizeof(DSBUFFERDESC);
- dsbd.dwFlags = dwCreationFlags;
- dsbd.dwBufferBytes = dwDSBufferSize;
- dsbd.guid3DAlgorithm = GUID_NULL;
- dsbd.lpwfxFormat = (WAVEFORMATEX*)&pWaveFile->mpwfx;
- // DirectSound is only guarenteed to play PCM data. Other
- // formats may or may not work depending the sound card driver.
- if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer, NULL ) ) )
- return -1;
- // Create the sound
- *ppSound = new idAudioBufferWIN32( apDSBuffer, dwDSBufferSize, pWaveFile );
-
- pWaveFile->Close();
- return 0;
- LFail:
- // Cleanup
- SAFE_DELETE( pWaveFile );
- return -1;
- }
- /*
- ===============
- idAudioHardwareWIN32::Create
- ===============
- */
- int idAudioHardwareWIN32::Create( idWaveFile* pWaveFile, idAudioBuffer** ppiab ) {
- int hr;
- LPDIRECTSOUNDBUFFER apDSBuffer = NULL;
- dword dwDSBufferSize = NULL;
- if( m_pDS == NULL )
- return -1;
- if( pWaveFile == NULL )
- return -1;
- *ppiab = NULL;
- if( pWaveFile->GetOutputSize() == 0 ) {
- // Wave is blank, so don't create it.
- hr = E_FAIL;
- goto LFail;
- }
- // Make the DirectSound buffer the same size as the wav file
- dwDSBufferSize = pWaveFile->GetOutputSize();
- // Create the direct sound buffer, and only request the flags needed
- // since each requires some overhead and limits if the buffer can
- // be hardware accelerated
- DSBUFFERDESC dsbd;
- memset( &dsbd, 0, sizeof(DSBUFFERDESC) );
- dsbd.dwSize = sizeof(DSBUFFERDESC);
- dsbd.dwFlags = 0;
- dsbd.dwBufferBytes = dwDSBufferSize;
- dsbd.guid3DAlgorithm = GUID_NULL;
- dsbd.lpwfxFormat = (WAVEFORMATEX*)&pWaveFile->mpwfx;
- // DirectSound is only guarenteed to play PCM data. Other
- // formats may or may not work depending the sound card driver.
- if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer, NULL ) ) )
- return -1;
- // Create the sound
- *ppiab = new idAudioBufferWIN32( apDSBuffer, dwDSBufferSize, pWaveFile );
-
- return 0;
- LFail:
- // Cleanup
- SAFE_DELETE( pWaveFile );
- return -1;
- }
- //-----------------------------------------------------------------------------
- // Name: idAudioHardwareWIN32::CreateFromMemory()
- // Desc:
- //-----------------------------------------------------------------------------
- int idAudioHardwareWIN32::CreateFromMemory( idAudioBufferWIN32** ppSound,
- byte* pbData,
- ulong ulDataSize,
- waveformatextensible_t* pwfx,
- dword dwCreationFlags ) {
- int hr;
- LPDIRECTSOUNDBUFFER apDSBuffer = NULL;
- dword dwDSBufferSize = NULL;
- idWaveFile* pWaveFile = NULL;
- if( m_pDS == NULL )
- return -1;
- if( pbData == NULL || ppSound == NULL )
- return -1;
- pWaveFile = new idWaveFile();
- pWaveFile->OpenFromMemory( (short *)pbData, ulDataSize, (waveformatextensible_t *)pwfx);
- // Make the DirectSound buffer the same size as the wav file
- dwDSBufferSize = ulDataSize;
- // Create the direct sound buffer, and only request the flags needed
- // since each requires some overhead and limits if the buffer can
- // be hardware accelerated
- DSBUFFERDESC dsbd;
- memset( &dsbd, 0, sizeof(DSBUFFERDESC) );
- dsbd.dwSize = sizeof(DSBUFFERDESC);
- dsbd.dwFlags = dwCreationFlags | DSBCAPS_GETCURRENTPOSITION2;
- dsbd.dwBufferBytes = dwDSBufferSize;
- dsbd.guid3DAlgorithm = GUID_NULL;
- dsbd.lpwfxFormat = (WAVEFORMATEX *)pwfx;
- if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer, NULL ) ) )
- return -1;
- // Create the sound
- *ppSound = new idAudioBufferWIN32( apDSBuffer, dwDSBufferSize, pWaveFile );
- return S_OK;
- }
- /*
- ===============
- idAudioHardwareWIN32::Lock
- ===============
- */
- bool idAudioHardwareWIN32::Lock( void **pDSLockedBuffer, ulong *dwDSLockedBufferSize ) {
- if (speakers) {
- return speakers->Lock( pDSLockedBuffer, dwDSLockedBufferSize );
- }
- return false;
- }
- /*
- ===============
- idAudioHardwareWIN32::Unlock
- ===============
- */
- bool idAudioHardwareWIN32::Unlock(void *pDSLockedBuffer, dword dwDSLockedBufferSize ) {
- if (speakers) {
- return speakers->Unlock( pDSLockedBuffer, dwDSLockedBufferSize );
- }
- return false;
- }
- /*
- ===============
- idAudioHardwareWIN32::GetCurrentPosition
- ===============
- */
- bool idAudioHardwareWIN32::GetCurrentPosition( ulong *pdwCurrentWriteCursor ) {
- if (speakers) {
- return speakers->GetCurrentPosition( pdwCurrentWriteCursor );
- }
- return false;
- }
- static HMODULE hOpenAL = NULL;
- /*
- ===============
- Sys_LoadOpenAL
- ===============
- */
- bool Sys_LoadOpenAL( void ) {
- #if ID_OPENAL
- const char *sym;
- if ( hOpenAL ) {
- return true;
- }
- hOpenAL = LoadLibrary( idSoundSystemLocal::s_libOpenAL.GetString() );
- if ( !hOpenAL ) {
- common->Warning( "LoadLibrary %s failed.", idSoundSystemLocal::s_libOpenAL.GetString() );
- return false;
- }
- if ( ( sym = InitializeIDAL( hOpenAL ) ) ) {
- common->Warning( "GetProcAddress %s failed.", sym );
- FreeLibrary( hOpenAL );
- hOpenAL = NULL;
- return false;
- }
- return true;
- #else
- return false;
- #endif
- }
- /*
- ===============
- Sys_FreeOpenAL
- ===============
- */
- void Sys_FreeOpenAL( void ) {
- if ( hOpenAL ) {
- FreeLibrary( hOpenAL );
- hOpenAL = NULL;
- }
- }
- /*
- ===============
- idAudioBufferWIN32::idAudioBuffer
- ===============
- */
- idAudioBufferWIN32::idAudioBufferWIN32( LPDIRECTSOUNDBUFFER apDSBuffer, dword dwDSBufferSize, idWaveFile* pWaveFile ) {
- m_apDSBuffer = apDSBuffer;
- m_dwDSBufferSize = dwDSBufferSize;
- m_pWaveFile = pWaveFile;
- if (pWaveFile) {
- FillBufferWithSound( m_apDSBuffer, false );
- m_apDSBuffer->SetCurrentPosition(0);
- }
- }
- /*
- ===============
- idAudioBufferWIN32::~idAudioBuffer
- ===============
- */
- idAudioBufferWIN32::~idAudioBufferWIN32() {
- SAFE_DELETE(m_pWaveFile);
- SAFE_RELEASE( m_apDSBuffer );
- m_pWaveFile = NULL;
- m_apDSBuffer = NULL;
- }
- /*
- ===============
- idAudioBufferWIN32::FillBufferWithSound
- ===============
- */
- int idAudioBufferWIN32::FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, bool bRepeatWavIfBufferLarger ) {
- int hr;
- void* pDSLockedBuffer = NULL; // Pointer to locked buffer memory
- ulong dwDSLockedBufferSize = 0; // Size of the locked DirectSound buffer
- int dwWavDataRead = 0; // Amount of data read from the wav file
- if( pDSB == NULL )
- return -1;
- // we may not even have a wavefile
- if (m_pWaveFile==NULL) {
- return -1;
- }
- // Make sure we have focus, and we didn't just switch in from
- // an app which had a DirectSound device
- if( FAILED( hr = RestoreBuffer( pDSB, NULL ) ) ) {
- DXTRACE_ERR( TEXT("RestoreBuffer"), hr );
- return -1;
- }
- // Lock the buffer down
- if( FAILED( hr = pDSB->Lock( 0, m_dwDSBufferSize, &pDSLockedBuffer, &dwDSLockedBufferSize, NULL, NULL, 0L ) ) ) {
- DXTRACE_ERR( TEXT("Lock"), hr );
- return -1;
- }
- // Reset the wave file to the beginning
- m_pWaveFile->ResetFile();
- if( FAILED( hr = m_pWaveFile->Read( (byte*) pDSLockedBuffer, dwDSLockedBufferSize, &dwWavDataRead ) ) ) {
- return DXTRACE_ERR( TEXT("Read"), hr );
- }
- if( dwWavDataRead == 0 ) {
- // Wav is blank, so just fill with silence
- memset( pDSLockedBuffer, (byte)(m_pWaveFile->mpwfx.Format.wBitsPerSample == 8 ? 128 : 0 ), dwDSLockedBufferSize );
- } else if( dwWavDataRead < (int)dwDSLockedBufferSize ) {
- // If the wav file was smaller than the DirectSound buffer,
- // we need to fill the remainder of the buffer with data
- if( bRepeatWavIfBufferLarger ) {
- // Reset the file and fill the buffer with wav data
- int dwReadSoFar = dwWavDataRead; // From previous call above.
- while( dwReadSoFar < (int)dwDSLockedBufferSize ) {
- // This will keep reading in until the buffer is full
- // for very short files
- if( FAILED( hr = m_pWaveFile->ResetFile() ) ) {
- return DXTRACE_ERR( TEXT("ResetFile"), hr );
- }
- hr = m_pWaveFile->Read( (byte*)pDSLockedBuffer + dwReadSoFar, dwDSLockedBufferSize - dwReadSoFar, &dwWavDataRead );
- if( FAILED(hr) ) {
- return DXTRACE_ERR( TEXT("Read"), hr );
- }
- dwReadSoFar += dwWavDataRead;
- }
- } else {
- // Don't repeat the wav file, just fill in silence
- memset( (byte*) pDSLockedBuffer + dwWavDataRead, (byte)(m_pWaveFile->mpwfx.Format.wBitsPerSample == 8 ? 128 : 0 ), dwDSLockedBufferSize - dwWavDataRead);
- }
- }
- // Unlock the buffer, we don't need it anymore.
- pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 );
- return S_OK;
- }
- /*
- ===============
- idAudioBufferWIN32::RestoreBuffer
- Desc: Restores the lost buffer. *pbWasRestored returns true if the buffer was
- restored. It can also NULL if the information is not needed.
- ===============
- */
- int idAudioBufferWIN32::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, bool* pbWasRestored ) {
- int hr;
- if( pDSB == NULL ) {
- return -1;
- }
- if( pbWasRestored ) {
- *pbWasRestored = false;
- }
- ulong dwStatus;
- if( FAILED( hr = pDSB->GetStatus( &dwStatus ) ) ) {
- return DXTRACE_ERR( TEXT("GetStatus"), hr );
- }
- if( dwStatus & DSBSTATUS_BUFFERLOST ) {
- // Since the app could have just been activated, then
- // DirectSound may not be giving us control yet, so
- // the restoring the buffer may fail.
- // If it does, sleep until DirectSound gives us control.
- do {
- hr = pDSB->Restore();
- if( hr == DSERR_BUFFERLOST ) {
- Sleep( 10 );
- }
- hr = pDSB->Restore();
- } while( hr );
- if( pbWasRestored != NULL ) {
- *pbWasRestored = true;
- }
- return S_OK;
- } else {
- return S_FALSE;
- }
- }
- /*
- ===============
- idAudioBufferWIN32::Play
- Desc: Plays the sound using voice management flags. Pass in DSBPLAY_LOOPING
- in the dwFlags to loop the sound
- ===============
- */
- int idAudioBufferWIN32::Play( dword dwPriority, dword dwFlags ) {
- int hr;
- bool bRestored;
- if( m_apDSBuffer == NULL ) {
- return -1;
- }
- // Restore the buffer if it was lost
- if( FAILED( hr = RestoreBuffer( m_apDSBuffer, &bRestored ) ) ) {
- common->Error( TEXT("RestoreBuffer"), hr );
- }
- if( bRestored ) {
- // The buffer was restored, so we need to fill it with new data
- if( FAILED( hr = FillBufferWithSound( m_apDSBuffer, false ) ) ) {
- common->Error( TEXT("FillBufferWithSound"), hr );
- }
- // Make DirectSound do pre-processing on sound effects
- Reset();
- }
- m_apDSBuffer->Play( 0, dwPriority, dwFlags );
- return 0;
- }
- /*
- ===============
- idAudioBufferWIN32::Stop
- Desc: Stops the sound from playing
- ===============
- */
- int idAudioBufferWIN32::Stop() {
- if( this == NULL || m_apDSBuffer == NULL ) {
- return -1;
- }
- m_apDSBuffer->Stop();
- return 0;
- }
- /*
- ===============
- idAudioBufferWIN32::Reset
- Desc: Reset all of the sound buffers
- ===============
- */
- int idAudioBufferWIN32::Reset() {
- if( m_apDSBuffer == NULL ) {
- return -1;
- }
- m_apDSBuffer->SetCurrentPosition( 0 );
- return 0;
- }
- /*
- ===============
- idAudioBufferWIN32::IsSoundPlaying
- Desc: Checks to see if a buffer is playing and returns true if it
- ===============
- */
- bool idAudioBufferWIN32::IsSoundPlaying( ) {
- if( m_apDSBuffer == NULL ) {
- return false;
- }
- if( m_apDSBuffer ) {
- ulong dwStatus = 0;
- m_apDSBuffer->GetStatus( &dwStatus );
- if ( dwStatus & DSBSTATUS_PLAYING ) {
- return true;
- }
- }
- return false;
- }
- /*
- ===============
- idAudioBufferWIN32::Lock
- ===============
- */
- bool idAudioBufferWIN32::Lock( void **pDSLockedBuffer, ulong *dwDSLockedBufferSize ) {
- int hr;
- // Restore the buffer if it was lost
- bool bRestored;
- if( FAILED( hr = RestoreBuffer( m_apDSBuffer, &bRestored ) ) ) {
- return false;
- }
- // Lock the DirectSound buffer
- if( FAILED( hr = m_apDSBuffer->Lock( 0, m_dwDSBufferSize, pDSLockedBuffer, dwDSLockedBufferSize, NULL, NULL, 0 ) ) ) {
- return false;
- }
- return true;
- }
- /*
- ===============
- idAudioBufferWIN32::Unlock
- ===============
- */
- bool idAudioBufferWIN32::Unlock(void *pDSLockedBuffer, dword dwDSLockedBufferSize ) {
- // Unlock the DirectSound buffer
- m_apDSBuffer->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 );
- return true;
- }
- /*
- ===============
- idAudioBufferWIN32::GetCurrentPosition
- ===============
- */
- bool idAudioBufferWIN32::GetCurrentPosition( ulong *pdwCurrentWriteCursor ) {
- int hr;
- // Make sure we have focus, and we didn't just switch in from
- // an app which had a DirectSound device
- if( FAILED( hr = RestoreBuffer( m_apDSBuffer, NULL ) ) ) {
- DXTRACE_ERR( TEXT("RestoreBuffer"), hr );
- return false;
- }
- if( FAILED( hr = m_apDSBuffer->GetCurrentPosition( NULL, pdwCurrentWriteCursor ) ) ) {
- return false;
- }
- return true;
- }
- /*
- ===============
- idAudioBufferWIN32::SetVolume
- ===============
- */
- void idAudioBufferWIN32::SetVolume( float x) {
- if (m_apDSBuffer) {
- m_apDSBuffer->SetVolume(x);
- }
- }
|