2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 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.
24 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.
26 ===========================================================================
28 #include "../../idlib/precompiled.h"
36 #include "../../sound/snd_local.h"
37 #include "win_local.h"
39 #include "../../openal/idal.cpp"
41 #define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
42 #define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } }
43 #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
45 class idAudioBufferWIN32 : public idAudioBuffer {
47 idAudioBufferWIN32( LPDIRECTSOUNDBUFFER apDSBuffer, dword dwDSBufferSize, idWaveFile* pWaveFile=NULL );
48 ~idAudioBufferWIN32();
50 int FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, bool bRepeatWavIfBufferLarger );
52 bool Lock( void **pDSLockedBuffer, ulong *dwDSLockedBufferSize );
53 bool Unlock(void *pDSLockedBuffer, dword dwDSLockedBufferSize );
54 bool GetCurrentPosition( ulong *pdwCurrentWriteCursor );
56 int Play( dword dwPriority=0, dword dwFlags=0 );
59 bool IsSoundPlaying( void );
60 void SetVolume( float x);
62 idWaveFile* m_pWaveFile;
64 LPDIRECTSOUNDBUFFER m_apDSBuffer;
65 dword m_dwDSBufferSize;
67 int RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, bool* pbWasRestored );
70 class idAudioHardwareWIN32 : public idAudioHardware {
73 idAudioHardwareWIN32();
74 ~idAudioHardwareWIN32();
77 bool InitializeSpeakers( byte *buffer, int bufferSize, dword dwPrimaryFreq, dword dwPrimaryBitRate, dword dwSpeakers );
79 void SetPrimaryBufferFormat( dword dwPrimaryFreq, dword dwPrimaryBitRate, dword dwSpeakers );
81 int Create( idWaveFile* pWaveFile, idAudioBuffer** ppiab );
82 int Create( idAudioBuffer** ppSound, const char* strWaveFileName, dword dwCreationFlags = 0 );
83 int CreateFromMemory( idAudioBufferWIN32** ppSound, byte* pbData, ulong ulDataSize, waveformatextensible_t *pwfx, dword dwCreationFlags = 0 );
85 bool Lock( void **pDSLockedBuffer, ulong *dwDSLockedBufferSize );
86 bool Unlock( void *pDSLockedBuffer, dword dwDSLockedBufferSize );
87 bool GetCurrentPosition( ulong *pdwCurrentWriteCursor );
89 int GetNumberOfSpeakers() { return numSpeakers; }
90 int GetMixBufferSize() { return MIXBUFFER_SAMPLES * blockAlign; }
92 // WIN32 driver doesn't support write API
93 bool Flush( void ) { return true; }
94 void Write( bool ) { }
95 short* GetMixBuffer( void ) { return NULL; }
99 LPDIRECTSOUNDBUFFER pDSBPrimary;
100 idAudioBufferWIN32 *speakers;
104 int bufferSize; // allocate buffer handed over to DirectSound
105 int blockAlign; // channels * bits per sample / 8: sound frame size
108 idAudioHardware *idAudioHardware::Alloc() { return new idAudioHardwareWIN32; }
109 idAudioHardware::~idAudioHardware() {}
113 idAudioHardwareWIN32::idAudioHardware
116 idAudioHardwareWIN32::idAudioHardwareWIN32() {
124 idAudioHardwareWIN32::~idAudioHardware
127 idAudioHardwareWIN32::~idAudioHardwareWIN32() {
128 SAFE_DELETE( speakers );
129 SAFE_RELEASE( pDSBPrimary );
130 SAFE_RELEASE( m_pDS );
135 idAudioHardwareWIN32::Initialize
138 bool idAudioHardwareWIN32::Initialize( void ) {
145 SAFE_RELEASE( m_pDS );
147 // Create IDirectSound using the primary sound device
148 if( FAILED( hr = DirectSoundCreate( NULL, &m_pDS, NULL ) )) {
152 // Set primary buffer format
153 SetPrimaryBufferFormat( PRIMARYFREQ, 16, idSoundSystemLocal::s_numberOfSpeakers.GetInteger() );
159 idAudioHardwareWIN32::InitializeSpeakers
162 bool idAudioHardwareWIN32::InitializeSpeakers( byte *speakerData, int bufferSize, dword dwPrimaryFreq, dword dwPrimaryBitRate, dword dwSpeakers ) {
163 if ( dwSpeakers == 2 ) {
164 WAVEFORMATEXTENSIBLE wfx;
165 ZeroMemory( &wfx, sizeof(WAVEFORMATEXTENSIBLE) );
166 wfx.Format.wFormatTag = WAVE_FORMAT_PCM;
167 wfx.Format.nChannels = 2;
168 wfx.Format.nSamplesPerSec = dwPrimaryFreq;
169 wfx.Format.wBitsPerSample = dwPrimaryBitRate;
170 wfx.Format.nBlockAlign = wfx.Format.wBitsPerSample / 8 * wfx.Format.nChannels;
171 wfx.Format.nAvgBytesPerSec = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign;
172 wfx.Format.cbSize = sizeof(WAVEFORMATEX);
174 CreateFromMemory( &speakers, speakerData, bufferSize, (waveformatextensible_t *)&wfx );
176 common->Printf("sound: STEREO\n");
178 WAVEFORMATEXTENSIBLE waveFormatPCMEx;
179 ZeroMemory( &waveFormatPCMEx, sizeof(WAVEFORMATEXTENSIBLE) );
181 waveFormatPCMEx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
182 waveFormatPCMEx.Format.nChannels = 6;
183 waveFormatPCMEx.Format.nSamplesPerSec = dwPrimaryFreq;
184 waveFormatPCMEx.Format.wBitsPerSample = dwPrimaryBitRate;
185 waveFormatPCMEx.Format.nBlockAlign = waveFormatPCMEx.Format.wBitsPerSample / 8 * waveFormatPCMEx.Format.nChannels;
186 waveFormatPCMEx.Format.nAvgBytesPerSec = waveFormatPCMEx.Format.nSamplesPerSec * waveFormatPCMEx.Format.nBlockAlign;
187 waveFormatPCMEx.dwChannelMask = KSAUDIO_SPEAKER_5POINT1;
188 // SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT |
189 // SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |
190 // SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT
191 waveFormatPCMEx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; // Specify PCM
192 waveFormatPCMEx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE);
193 waveFormatPCMEx.Samples.wValidBitsPerSample = 16;
195 CreateFromMemory( &speakers, speakerData, bufferSize, (waveformatextensible_t *)&waveFormatPCMEx );
197 common->Printf("sound: MULTICHANNEL\n");
204 speakers->Play(0,DSBPLAY_LOOPING);
211 idAudioHardwareWIN32::SetPrimaryBufferFormat
212 Set primary buffer to a specified format
213 For example, to set the primary buffer format to 22kHz stereo, 16-bit
214 then: dwPrimaryChannels = 2
215 dwPrimaryFreq = 22050,
216 dwPrimaryBitRate = 16
219 void idAudioHardwareWIN32::SetPrimaryBufferFormat( dword dwPrimaryFreq, dword dwPrimaryBitRate, dword dwSpeakers ) {
222 if( m_pDS == NULL ) {
227 m_pDS->GetSpeakerConfig( &cfgSpeakers );
230 dscaps.dwSize = sizeof(DSCAPS);
231 m_pDS->GetCaps(&dscaps);
233 if (dscaps.dwFlags & DSCAPS_EMULDRIVER) {
237 // Get the primary buffer
239 ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
240 dsbd.dwSize = sizeof(DSBUFFERDESC);
241 dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
242 dsbd.dwBufferBytes = 0;
243 dsbd.lpwfxFormat = NULL;
245 // Obtain write-primary cooperative level.
246 if( FAILED( hr = m_pDS->SetCooperativeLevel(win32.hWnd, DSSCL_PRIORITY ) ) ) {
247 DXTRACE_ERR( TEXT("SetPrimaryBufferFormat"), hr );
251 if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) ) {
255 if ( dwSpeakers == 6 && (cfgSpeakers == DSSPEAKER_5POINT1 || cfgSpeakers == DSSPEAKER_SURROUND) ) {
256 WAVEFORMATEXTENSIBLE waveFormatPCMEx;
257 ZeroMemory( &waveFormatPCMEx, sizeof(WAVEFORMATEXTENSIBLE) );
259 waveFormatPCMEx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
260 waveFormatPCMEx.Format.nChannels = 6;
261 waveFormatPCMEx.Format.nSamplesPerSec = dwPrimaryFreq;
262 waveFormatPCMEx.Format.wBitsPerSample = (WORD) dwPrimaryBitRate;
263 waveFormatPCMEx.Format.nBlockAlign = waveFormatPCMEx.Format.wBitsPerSample / 8 * waveFormatPCMEx.Format.nChannels;
264 waveFormatPCMEx.Format.nAvgBytesPerSec = waveFormatPCMEx.Format.nSamplesPerSec * waveFormatPCMEx.Format.nBlockAlign;
265 waveFormatPCMEx.dwChannelMask = KSAUDIO_SPEAKER_5POINT1;
266 // SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT |
267 // SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |
268 // SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT
269 waveFormatPCMEx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; // Specify PCM
270 waveFormatPCMEx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE);
271 waveFormatPCMEx.Samples.wValidBitsPerSample = 16;
273 if( FAILED( hr = pDSBPrimary->SetFormat((WAVEFORMATEX*)&waveFormatPCMEx) ) ) {
274 DXTRACE_ERR( TEXT("SetPrimaryBufferFormat"), hr );
277 numSpeakers = 6; // force it to think 5.1
278 blockAlign = waveFormatPCMEx.Format.nBlockAlign;
280 if (dwSpeakers == 6) {
281 common->Printf("sound: hardware reported unable to use multisound, defaulted to stereo\n");
284 ZeroMemory( &wfx, sizeof(WAVEFORMATEX) );
285 wfx.wFormatTag = WAVE_FORMAT_PCM;
287 wfx.nSamplesPerSec = dwPrimaryFreq;
288 wfx.wBitsPerSample = (WORD) dwPrimaryBitRate;
289 wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels;
290 wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
291 wfx.cbSize = sizeof(WAVEFORMATEX);
293 if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) ) {
296 numSpeakers = 2; // force it to think stereo
297 blockAlign = wfx.nBlockAlign;
301 bufferSize = MIXBUFFER_SAMPLES * sizeof(word) * numSpeakers * ROOM_SLICES_IN_BUFFER;
302 speakerData = (byte *)Mem_Alloc( bufferSize );
303 memset( speakerData, 0, bufferSize );
305 InitializeSpeakers( speakerData, bufferSize, dwPrimaryFreq, dwPrimaryBitRate, numSpeakers );
310 idAudioHardwareWIN32::Create
313 int idAudioHardwareWIN32::Create( idAudioBuffer** ppSound,
314 const char* strWaveFileName,
315 dword dwCreationFlags ) {
317 LPDIRECTSOUNDBUFFER apDSBuffer = NULL;
318 dword dwDSBufferSize = NULL;
319 idWaveFile* pWaveFile = NULL;
323 if( strWaveFileName == NULL || ppSound == NULL )
326 pWaveFile = new idWaveFile();
328 pWaveFile->Open( strWaveFileName, NULL );
330 if( pWaveFile->GetOutputSize() == 0 ) {
331 // Wave is blank, so don't create it.
336 // Make the DirectSound buffer the same size as the wav file
337 dwDSBufferSize = pWaveFile->GetOutputSize();
339 // Create the direct sound buffer, and only request the flags needed
340 // since each requires some overhead and limits if the buffer can
341 // be hardware accelerated
343 memset( &dsbd, 0, sizeof(DSBUFFERDESC) );
344 dsbd.dwSize = sizeof(DSBUFFERDESC);
345 dsbd.dwFlags = dwCreationFlags;
346 dsbd.dwBufferBytes = dwDSBufferSize;
347 dsbd.guid3DAlgorithm = GUID_NULL;
348 dsbd.lpwfxFormat = (WAVEFORMATEX*)&pWaveFile->mpwfx;
350 // DirectSound is only guarenteed to play PCM data. Other
351 // formats may or may not work depending the sound card driver.
352 if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer, NULL ) ) )
356 *ppSound = new idAudioBufferWIN32( apDSBuffer, dwDSBufferSize, pWaveFile );
364 SAFE_DELETE( pWaveFile );
370 idAudioHardwareWIN32::Create
373 int idAudioHardwareWIN32::Create( idWaveFile* pWaveFile, idAudioBuffer** ppiab ) {
375 LPDIRECTSOUNDBUFFER apDSBuffer = NULL;
376 dword dwDSBufferSize = NULL;
381 if( pWaveFile == NULL )
386 if( pWaveFile->GetOutputSize() == 0 ) {
387 // Wave is blank, so don't create it.
392 // Make the DirectSound buffer the same size as the wav file
393 dwDSBufferSize = pWaveFile->GetOutputSize();
395 // Create the direct sound buffer, and only request the flags needed
396 // since each requires some overhead and limits if the buffer can
397 // be hardware accelerated
399 memset( &dsbd, 0, sizeof(DSBUFFERDESC) );
400 dsbd.dwSize = sizeof(DSBUFFERDESC);
402 dsbd.dwBufferBytes = dwDSBufferSize;
403 dsbd.guid3DAlgorithm = GUID_NULL;
404 dsbd.lpwfxFormat = (WAVEFORMATEX*)&pWaveFile->mpwfx;
406 // DirectSound is only guarenteed to play PCM data. Other
407 // formats may or may not work depending the sound card driver.
408 if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer, NULL ) ) )
412 *ppiab = new idAudioBufferWIN32( apDSBuffer, dwDSBufferSize, pWaveFile );
418 SAFE_DELETE( pWaveFile );
422 //-----------------------------------------------------------------------------
423 // Name: idAudioHardwareWIN32::CreateFromMemory()
425 //-----------------------------------------------------------------------------
426 int idAudioHardwareWIN32::CreateFromMemory( idAudioBufferWIN32** ppSound,
429 waveformatextensible_t* pwfx,
430 dword dwCreationFlags ) {
432 LPDIRECTSOUNDBUFFER apDSBuffer = NULL;
433 dword dwDSBufferSize = NULL;
434 idWaveFile* pWaveFile = NULL;
438 if( pbData == NULL || ppSound == NULL )
441 pWaveFile = new idWaveFile();
443 pWaveFile->OpenFromMemory( (short *)pbData, ulDataSize, (waveformatextensible_t *)pwfx);
446 // Make the DirectSound buffer the same size as the wav file
447 dwDSBufferSize = ulDataSize;
449 // Create the direct sound buffer, and only request the flags needed
450 // since each requires some overhead and limits if the buffer can
451 // be hardware accelerated
453 memset( &dsbd, 0, sizeof(DSBUFFERDESC) );
454 dsbd.dwSize = sizeof(DSBUFFERDESC);
455 dsbd.dwFlags = dwCreationFlags | DSBCAPS_GETCURRENTPOSITION2;
456 dsbd.dwBufferBytes = dwDSBufferSize;
457 dsbd.guid3DAlgorithm = GUID_NULL;
458 dsbd.lpwfxFormat = (WAVEFORMATEX *)pwfx;
460 if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer, NULL ) ) )
464 *ppSound = new idAudioBufferWIN32( apDSBuffer, dwDSBufferSize, pWaveFile );
471 idAudioHardwareWIN32::Lock
474 bool idAudioHardwareWIN32::Lock( void **pDSLockedBuffer, ulong *dwDSLockedBufferSize ) {
476 return speakers->Lock( pDSLockedBuffer, dwDSLockedBufferSize );
483 idAudioHardwareWIN32::Unlock
486 bool idAudioHardwareWIN32::Unlock(void *pDSLockedBuffer, dword dwDSLockedBufferSize ) {
488 return speakers->Unlock( pDSLockedBuffer, dwDSLockedBufferSize );
495 idAudioHardwareWIN32::GetCurrentPosition
498 bool idAudioHardwareWIN32::GetCurrentPosition( ulong *pdwCurrentWriteCursor ) {
500 return speakers->GetCurrentPosition( pdwCurrentWriteCursor );
505 static HMODULE hOpenAL = NULL;
512 bool Sys_LoadOpenAL( void ) {
520 hOpenAL = LoadLibrary( idSoundSystemLocal::s_libOpenAL.GetString() );
522 common->Warning( "LoadLibrary %s failed.", idSoundSystemLocal::s_libOpenAL.GetString() );
525 if ( ( sym = InitializeIDAL( hOpenAL ) ) ) {
526 common->Warning( "GetProcAddress %s failed.", sym );
527 FreeLibrary( hOpenAL );
542 void Sys_FreeOpenAL( void ) {
544 FreeLibrary( hOpenAL );
551 idAudioBufferWIN32::idAudioBuffer
554 idAudioBufferWIN32::idAudioBufferWIN32( LPDIRECTSOUNDBUFFER apDSBuffer, dword dwDSBufferSize, idWaveFile* pWaveFile ) {
556 m_apDSBuffer = apDSBuffer;
558 m_dwDSBufferSize = dwDSBufferSize;
559 m_pWaveFile = pWaveFile;
562 FillBufferWithSound( m_apDSBuffer, false );
564 m_apDSBuffer->SetCurrentPosition(0);
570 idAudioBufferWIN32::~idAudioBuffer
573 idAudioBufferWIN32::~idAudioBufferWIN32() {
574 SAFE_DELETE(m_pWaveFile);
575 SAFE_RELEASE( m_apDSBuffer );
582 idAudioBufferWIN32::FillBufferWithSound
585 int idAudioBufferWIN32::FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, bool bRepeatWavIfBufferLarger ) {
587 void* pDSLockedBuffer = NULL; // Pointer to locked buffer memory
588 ulong dwDSLockedBufferSize = 0; // Size of the locked DirectSound buffer
589 int dwWavDataRead = 0; // Amount of data read from the wav file
594 // we may not even have a wavefile
595 if (m_pWaveFile==NULL) {
599 // Make sure we have focus, and we didn't just switch in from
600 // an app which had a DirectSound device
601 if( FAILED( hr = RestoreBuffer( pDSB, NULL ) ) ) {
602 DXTRACE_ERR( TEXT("RestoreBuffer"), hr );
606 // Lock the buffer down
607 if( FAILED( hr = pDSB->Lock( 0, m_dwDSBufferSize, &pDSLockedBuffer, &dwDSLockedBufferSize, NULL, NULL, 0L ) ) ) {
608 DXTRACE_ERR( TEXT("Lock"), hr );
612 // Reset the wave file to the beginning
613 m_pWaveFile->ResetFile();
615 if( FAILED( hr = m_pWaveFile->Read( (byte*) pDSLockedBuffer, dwDSLockedBufferSize, &dwWavDataRead ) ) ) {
616 return DXTRACE_ERR( TEXT("Read"), hr );
619 if( dwWavDataRead == 0 ) {
620 // Wav is blank, so just fill with silence
621 memset( pDSLockedBuffer, (byte)(m_pWaveFile->mpwfx.Format.wBitsPerSample == 8 ? 128 : 0 ), dwDSLockedBufferSize );
622 } else if( dwWavDataRead < (int)dwDSLockedBufferSize ) {
623 // If the wav file was smaller than the DirectSound buffer,
624 // we need to fill the remainder of the buffer with data
625 if( bRepeatWavIfBufferLarger ) {
626 // Reset the file and fill the buffer with wav data
627 int dwReadSoFar = dwWavDataRead; // From previous call above.
628 while( dwReadSoFar < (int)dwDSLockedBufferSize ) {
629 // This will keep reading in until the buffer is full
630 // for very short files
631 if( FAILED( hr = m_pWaveFile->ResetFile() ) ) {
632 return DXTRACE_ERR( TEXT("ResetFile"), hr );
635 hr = m_pWaveFile->Read( (byte*)pDSLockedBuffer + dwReadSoFar, dwDSLockedBufferSize - dwReadSoFar, &dwWavDataRead );
637 return DXTRACE_ERR( TEXT("Read"), hr );
640 dwReadSoFar += dwWavDataRead;
643 // Don't repeat the wav file, just fill in silence
644 memset( (byte*) pDSLockedBuffer + dwWavDataRead, (byte)(m_pWaveFile->mpwfx.Format.wBitsPerSample == 8 ? 128 : 0 ), dwDSLockedBufferSize - dwWavDataRead);
648 // Unlock the buffer, we don't need it anymore.
649 pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 );
656 idAudioBufferWIN32::RestoreBuffer
657 Desc: Restores the lost buffer. *pbWasRestored returns true if the buffer was
658 restored. It can also NULL if the information is not needed.
661 int idAudioBufferWIN32::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, bool* pbWasRestored ) {
667 if( pbWasRestored ) {
668 *pbWasRestored = false;
672 if( FAILED( hr = pDSB->GetStatus( &dwStatus ) ) ) {
673 return DXTRACE_ERR( TEXT("GetStatus"), hr );
676 if( dwStatus & DSBSTATUS_BUFFERLOST ) {
677 // Since the app could have just been activated, then
678 // DirectSound may not be giving us control yet, so
679 // the restoring the buffer may fail.
680 // If it does, sleep until DirectSound gives us control.
682 hr = pDSB->Restore();
683 if( hr == DSERR_BUFFERLOST ) {
686 hr = pDSB->Restore();
689 if( pbWasRestored != NULL ) {
690 *pbWasRestored = true;
701 idAudioBufferWIN32::Play
702 Desc: Plays the sound using voice management flags. Pass in DSBPLAY_LOOPING
703 in the dwFlags to loop the sound
706 int idAudioBufferWIN32::Play( dword dwPriority, dword dwFlags ) {
710 if( m_apDSBuffer == NULL ) {
714 // Restore the buffer if it was lost
715 if( FAILED( hr = RestoreBuffer( m_apDSBuffer, &bRestored ) ) ) {
716 common->Error( TEXT("RestoreBuffer"), hr );
720 // The buffer was restored, so we need to fill it with new data
721 if( FAILED( hr = FillBufferWithSound( m_apDSBuffer, false ) ) ) {
722 common->Error( TEXT("FillBufferWithSound"), hr );
725 // Make DirectSound do pre-processing on sound effects
729 m_apDSBuffer->Play( 0, dwPriority, dwFlags );
735 idAudioBufferWIN32::Stop
736 Desc: Stops the sound from playing
739 int idAudioBufferWIN32::Stop() {
740 if( this == NULL || m_apDSBuffer == NULL ) {
744 m_apDSBuffer->Stop();
751 idAudioBufferWIN32::Reset
752 Desc: Reset all of the sound buffers
755 int idAudioBufferWIN32::Reset() {
756 if( m_apDSBuffer == NULL ) {
760 m_apDSBuffer->SetCurrentPosition( 0 );
767 idAudioBufferWIN32::IsSoundPlaying
768 Desc: Checks to see if a buffer is playing and returns true if it
771 bool idAudioBufferWIN32::IsSoundPlaying( ) {
772 if( m_apDSBuffer == NULL ) {
778 m_apDSBuffer->GetStatus( &dwStatus );
779 if ( dwStatus & DSBSTATUS_PLAYING ) {
788 idAudioBufferWIN32::Lock
791 bool idAudioBufferWIN32::Lock( void **pDSLockedBuffer, ulong *dwDSLockedBufferSize ) {
793 // Restore the buffer if it was lost
795 if( FAILED( hr = RestoreBuffer( m_apDSBuffer, &bRestored ) ) ) {
799 // Lock the DirectSound buffer
800 if( FAILED( hr = m_apDSBuffer->Lock( 0, m_dwDSBufferSize, pDSLockedBuffer, dwDSLockedBufferSize, NULL, NULL, 0 ) ) ) {
808 idAudioBufferWIN32::Unlock
811 bool idAudioBufferWIN32::Unlock(void *pDSLockedBuffer, dword dwDSLockedBufferSize ) {
812 // Unlock the DirectSound buffer
813 m_apDSBuffer->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 );
819 idAudioBufferWIN32::GetCurrentPosition
822 bool idAudioBufferWIN32::GetCurrentPosition( ulong *pdwCurrentWriteCursor ) {
825 // Make sure we have focus, and we didn't just switch in from
826 // an app which had a DirectSound device
827 if( FAILED( hr = RestoreBuffer( m_apDSBuffer, NULL ) ) ) {
828 DXTRACE_ERR( TEXT("RestoreBuffer"), hr );
832 if( FAILED( hr = m_apDSBuffer->GetCurrentPosition( NULL, pdwCurrentWriteCursor ) ) ) {
840 idAudioBufferWIN32::SetVolume
843 void idAudioBufferWIN32::SetVolume( float x) {
845 m_apDSBuffer->SetVolume(x);