#include "SoundBuffer.h" #include "SoundFile.h" #include "DirectSound.h" #include #include extern bool g_b3DSound; ///////////////////////////////////////////////////////////////////////////////////////// // CSoundBuffer::CSoundBuffer() : m_pDSBuffer8( NULL ) , m_apDSBuffer( NULL ) , m_ap3DBuffer( NULL ) , m_pSoundFile( NULL ) , m_dwDSBufferSize( 0 ) , m_dwNumBuffers( 0 ) { } ///////////////////////////////////////////////////////////////////////////////////////// // CSoundBuffer::CSoundBuffer( IDirectSound8 * pDSound, ISoundFile * pSoundFile, bool b3DSound, DWORD dwNumBuffers ) : m_pDSBuffer8( NULL ) , m_apDSBuffer( NULL ) , m_ap3DBuffer( NULL ) , m_pSoundFile( NULL ) , m_dwDSBufferSize( 0 ) , m_dwNumBuffers( 0 ) { Create( pDSound, pSoundFile, b3DSound, dwNumBuffers ); } ///////////////////////////////////////////////////////////////////////////////////////// // CSoundBuffer::CSoundBuffer( IDirectSound8 * pDSound, const char * szFilename, bool b3DSound, DWORD dwNumBuffers ) : m_pDSBuffer8( NULL ) , m_apDSBuffer( NULL ) , m_ap3DBuffer( NULL ) , m_pSoundFile( NULL ) , m_dwDSBufferSize( 0 ) , m_dwNumBuffers( 0 ) { Create( pDSound, szFilename, b3DSound, dwNumBuffers ); } ///////////////////////////////////////////////////////////////////////////////////////// // CSoundBuffer::~CSoundBuffer() { Destroy(); } ///////////////////////////////////////////////////////////////////////////////////////// // void CSoundBuffer::Create( IDirectSound8 * pDSound, ISoundFile * pSoundFile, bool b3DSound, DWORD dwNumBuffers, DWORD dwAddFlag ) { //ÀÎÀÚ·Î µé¾î¿Â pDSound´Â ¹«½ÃÇÔ.(¿ÜºÎ ÀÎÅÍÆäÀ̽º¸¦ º¯°æ½ÃŰÁö ¾ÊÀ¸·Á°í ³²°ÜµÐ °ÍÀÓ) pDSound = CDirectSound::GetInstance().GetDS(); Destroy(); if( g_b3DSound == false ) b3DSound = false; m_dwDSBufferSize = pSoundFile->GetSize(); m_pSoundFile = pSoundFile; assert( pDSound != NULL && m_pSoundFile != NULL && m_dwDSBufferSize != 0 ); WAVEFORMATEX wfx; ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); wfx.nChannels = pSoundFile->GetChannelCount(); wfx.nSamplesPerSec = pSoundFile->GetSamplePerSec(); wfx.wBitsPerSample = pSoundFile->GetBitsPerSample(); if( b3DSound ) { if( wfx.nChannels != 1 ) //À̰ÍÀÌ Stereo(2)·Î µÇ¾î ÀÖÀ¸¸é DSBCAPS_CTRL3D¸¦ ¼¼ÆÃÇÒ ¼ö ¾øÀ½ { MessageBox( NULL, "3D »ç¿îµå¸¦ »ç¿ëÇϱâ À§Çؼ­´Â »ç¿îµå È­ÀÏÀÌ mono·Î ¼³Á¤ÀÌ µÇ¾î ÀÖ¾î¾ß ÇÕ´Ï´Ù.", pSoundFile->GetFilename(), MB_OK ); wfx.nChannels = 1; } } wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; DSBUFFERDESC dsbd; ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = dwAddFlag; if( b3DSound ) dsbd.dwFlags |= DSBCAPS_CTRL3D | DSBCAPS_MUTE3DATMAXDISTANCE; dsbd.dwBufferBytes = m_dwDSBufferSize; dsbd.guid3DAlgorithm = GUID_NULL; dsbd.lpwfxFormat = &wfx; // DirectSound is only guarenteed to play PCM data. Other // formats may or may not work depending the sound card driver. LPDIRECTSOUNDBUFFER tempBuffer = 0; HRESULT hr = pDSound->CreateSoundBuffer( &dsbd, &tempBuffer, NULL ); if( FAILED( hr ) ) { return; //SNDError( "Cannot Create SoundBuffer!! ErrorCode : 0x%x", hr ); } hr = tempBuffer->QueryInterface( IID_IDirectSoundBuffer8, (void**)&m_pDSBuffer8 ); ULONG refCount = tempBuffer->Release(); if( FAILED( hr ) ) { SNDError( "QueryInterface at (CSoundBuffer::Create) Failed!! errorCode : 0x%x", hr ); } m_dwNumBuffers = dwNumBuffers; m_apDSBuffer = new LPDIRECTSOUNDBUFFER[m_dwNumBuffers]; for( DWORD i = 0; i < m_dwNumBuffers; i++ ) m_apDSBuffer[i] = 0; for( i = 0; i < m_dwNumBuffers; i++ ) { if( FAILED( hr = pDSound->DuplicateSoundBuffer( m_pDSBuffer8, &m_apDSBuffer[i] ) ) ) { delete [] m_apDSBuffer; SNDError( "Duplicate SoundBuffer Failed!! ErrorCode : 0x%x", hr ); } } if( b3DSound ) { m_ap3DBuffer = new IDirectSound3DBuffer*[ dwNumBuffers ]; for( i = 0; i < dwNumBuffers; i++ ) { m_apDSBuffer[i]->SetCurrentPosition(0); m_ap3DBuffer[i] = Get3DBufferInterface( i ); } } FillBufferWithSound( m_apDSBuffer[0] ); } ///////////////////////////////////////////////////////////////////////////////////////// // void CSoundBuffer::Create( IDirectSound8 * pDSound, const char * szFilename, bool b3DSound, DWORD dwNumBuffers, DWORD dwAddFlag ) { if( !IsFileExist2( szFilename ) ) { SNDError( "%s : È­ÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù.", szFilename ); } ISoundFile * pSoundFile = ISoundFile::CreateSoundFileInstance( szFilename ); Create( pDSound, pSoundFile, b3DSound, dwNumBuffers, dwAddFlag ); } ///////////////////////////////////////////////////////////////////////////////////////// // void CSoundBuffer::Destroy() { DWORD i; if( m_ap3DBuffer ) { for( i = 0; i < m_dwNumBuffers; i++ ) { if( m_ap3DBuffer[i] ) { m_ap3DBuffer[i]->Release(); m_ap3DBuffer[i] = NULL; } } delete [] m_ap3DBuffer; m_ap3DBuffer = NULL; } if( m_apDSBuffer ) { for( i = 0; i < m_dwNumBuffers; i++ ) { if( m_apDSBuffer[i] ) { ULONG refCount = m_apDSBuffer[i]->Release(); m_apDSBuffer[i] = NULL; } } delete [] m_apDSBuffer; m_apDSBuffer = NULL; } if( m_pDSBuffer8 ) { ULONG refCount = m_pDSBuffer8->Release(); m_pDSBuffer8 = NULL; } delete m_pSoundFile; m_pSoundFile = NULL; m_dwDSBufferSize = 0; m_dwNumBuffers = 0; } ///////////////////////////////////////////////////////////////////////////////////////// // int CSoundBuffer::Play( bool bLoop ) { int freeBuffer = GetFreeBuffer(); Play( freeBuffer, bLoop ); return freeBuffer; } ///////////////////////////////////////////////////////////////////////////////////////// // void CSoundBuffer::Play( DWORD index, bool bLoop ) { if( m_apDSBuffer == NULL ) return; if( index >= m_dwNumBuffers ) return; LPDIRECTSOUNDBUFFER pDSB = m_apDSBuffer[ index ]; if( pDSB == NULL ) return; if( Restore( pDSB ) ) { //¹öÆÛ°¡ restore µÇ¾úÀ» ¶§ µ¥ÀÌÅ͸¦ »õ·Î ä¿ö ³ÖÀ½. FillBufferWithSound( pDSB ); ResetAll(); } HRESULT hr = pDSB->Play( 0, 0, ( bLoop ? DSBPLAY_LOOPING : 0 ) ); if( FAILED( hr ) ) SNDError( "DirectSound Play Failed!! ErrorCode : 0x%x", hr ); } ///////////////////////////////////////////////////////////////////////////////////////// // void CSoundBuffer::Stop( unsigned bufIndex ) { if( m_apDSBuffer == NULL ) return; if( bufIndex >= m_dwNumBuffers ) return; HRESULT hr = m_apDSBuffer[ bufIndex ]->Stop(); if( FAILED( hr ) ) SNDError( "DirectSoundBuffer Stop Failed!! ErrorCode : 0x%x", hr ); } ///////////////////////////////////////////////////////////////////////////////////////// // void CSoundBuffer::StopAll() { if( m_apDSBuffer == NULL ) return; for( DWORD i = 0; i < m_dwNumBuffers; i++ ) { if( m_apDSBuffer[i] ) { HRESULT hr = m_apDSBuffer[i]->Stop(); if( FAILED( hr ) ) SNDError( "DirectSoundBuffer Stop(StopAll) Failed!! ErrorCode : 0x%x", hr ); } } } ///////////////////////////////////////////////////////////////////////////////////////// // void CSoundBuffer::Reset( unsigned bufIndex ) { if( m_apDSBuffer == NULL ) return; if( bufIndex >= m_dwNumBuffers ) return; HRESULT hr = m_apDSBuffer[ bufIndex ]->SetCurrentPosition( 0L ); if( FAILED( hr ) ) SNDError( "SetCurrnetPosition(CSoundBuffer::Reset) Failed!! ErrorCode : 0x%x", hr ); } ///////////////////////////////////////////////////////////////////////////////////////// // void CSoundBuffer::ResetAll() { if( m_apDSBuffer == NULL ) return; for( DWORD i = 0; i < m_dwNumBuffers; i++ ) { if( m_apDSBuffer[i] ) { HRESULT hr = m_apDSBuffer[i]->SetCurrentPosition( 0 ); if( FAILED( hr ) ) SNDError( "CSoundBuffer Reset Failed!! ErrorCode : 0x%x", hr ); } } } ///////////////////////////////////////////////////////////////////////////////////////// // bool CSoundBuffer::IsAllPlaying() { return ( GetFreeBuffer() == -1 ); } ///////////////////////////////////////////////////////////////////////////////////////// // bool CSoundBuffer::IsAllFree() { if( m_apDSBuffer == NULL ) return false; for( DWORD i = 0; i < m_dwNumBuffers; i++ ) { if( m_apDSBuffer[i] == NULL ) return false; DWORD dwStatus = 0; m_apDSBuffer[i]->GetStatus( &dwStatus ); if( (dwStatus & DSBSTATUS_PLAYING) != 0 ) return false; } return true; } ///////////////////////////////////////////////////////////////////////////////////////// // bool CSoundBuffer::IsPlaying( unsigned bufIndex ) { if( m_apDSBuffer == NULL ) return false; if( bufIndex >= m_dwNumBuffers ) return false; DWORD dwStatus = 0; m_apDSBuffer[ bufIndex ]->GetStatus( &dwStatus ); if( ( dwStatus & DSBSTATUS_PLAYING ) != 0 ) return true; return false; } ///////////////////////////////////////////////////////////////////////////////////////// // DWORD CSoundBuffer::GetMemoryUse() { return m_dwDSBufferSize; } ///////////////////////////////////////////////////////////////////////////////////////// // bool CSoundBuffer::IsSameFile( const char * szFilename ) { if( m_pSoundFile == NULL ) return false; return strcmp( m_pSoundFile->GetFilename(), szFilename ) == 0; } ///////////////////////////////////////////////////////////////////////////////////////// // const char * CSoundBuffer::GetFilename() { if( m_pSoundFile == NULL ) return NULL; return m_pSoundFile->GetFilename(); } ///////////////////////////////////////////////////////////////////////////////////////// // bool CSoundBuffer::Restore( IDirectSoundBuffer * pDSBuffer ) { assert( pDSBuffer != NULL ); DWORD dwStatus; HRESULT hr = pDSBuffer->GetStatus( &dwStatus ); if( FAILED( hr ) ) SNDError( "GetStatus(at CSoundBuffer::Restore) Failed!! ErrorCode : 0x%x", hr ); if( dwStatus & DSBSTATUS_BUFFERLOST ) { do { hr = pDSBuffer->Restore(); if( hr == DSERR_BUFFERLOST ) Sleep( 10 ); } while( hr = pDSBuffer->Restore() ); return true; } else { return false; } } ///////////////////////////////////////////////////////////////////////////////////////// // int CSoundBuffer::GetFreeBuffer() { if( m_apDSBuffer == NULL ) return -1; for( DWORD i = 0; i < m_dwNumBuffers; i++ ) { if( m_apDSBuffer[i] ) { DWORD dwStatus = 0; m_apDSBuffer[i]->GetStatus( &dwStatus ); if( ( dwStatus & DSBSTATUS_PLAYING ) == 0 ) return i; } } return -1; } ///////////////////////////////////////////////////////////////////////////////////////// // void CSoundBuffer::FillBufferWithSound( IDirectSoundBuffer * pDSBuffer ) { if( pDSBuffer == NULL ) return; Restore( pDSBuffer ); void * pLockedBuffer = NULL; DWORD dwLockedBufferSize = 0; HRESULT hr = pDSBuffer->Lock( 0, m_dwDSBufferSize, &pLockedBuffer, &dwLockedBufferSize, NULL, NULL, 0L ); if( FAILED( hr ) ) SNDError( "DirectSoundBuffer Lock Failed!! ErrorCode : 0x%x", hr ); m_pSoundFile->Reset(); DWORD dwDataRead = m_pSoundFile->Read( (BYTE*) pLockedBuffer, dwLockedBufferSize ); //³ª¸ÓÁö´Â ¹«À½À¸·Î ä¿ò. FillMemory( (BYTE*) pLockedBuffer + dwDataRead, dwLockedBufferSize - dwDataRead , (BYTE)( m_pSoundFile->GetBitsPerSample() == 8 ? 128 : 0 ) ); pDSBuffer->Unlock( pLockedBuffer, dwLockedBufferSize, NULL, 0 ); } ///////////////////////////////////////////////////////////////////////////////////////// // IDirectSound3DBuffer * CSoundBuffer::Get3DBufferInterface( DWORD dwIndex ) { if( m_apDSBuffer == NULL ) return NULL; if( dwIndex >= m_dwNumBuffers ) return NULL; LPDIRECTSOUND3DBUFFER8 pDS3DBuffer = NULL; HRESULT hr = m_apDSBuffer[dwIndex]->QueryInterface( IID_IDirectSound3DBuffer8, (void**)&pDS3DBuffer ); if( FAILED( hr ) ) SNDError( "QueryInterface (DirectSound3DBuffer) Failed!! ErrorCode : 0x%x", hr ); return pDS3DBuffer; } ///////////////////////////////////////////////////////////////////////////////////////// // void CSoundBuffer::SetPosition( DWORD dwIndex, D3DVALUE x, D3DVALUE y, D3DVALUE z ) { if( m_ap3DBuffer == NULL ) return; if( dwIndex >= m_dwNumBuffers ) return; HRESULT hr = m_ap3DBuffer[dwIndex]->SetPosition( x, y, z, DS3D_IMMEDIATE ); if( FAILED( hr ) ) SNDError( "SetPosition (DS3DBuffer) Failed!! ErrorCode : 0x%x", hr ); } ///////////////////////////////////////////////////////////////////////////////////////// // void CSoundBuffer::SetDistance( DWORD dwIndex, D3DVALUE minDistance, D3DVALUE maxDistance ) { if( m_ap3DBuffer == NULL ) return; if( dwIndex >= m_dwNumBuffers ) return; HRESULT hr = m_ap3DBuffer[dwIndex]->SetMinDistance( minDistance, DS3D_IMMEDIATE ); if( FAILED( hr ) ) SNDError( "SetMinDistance (DS3DBuffer) Failed!! ErrorCode : 0x%x", hr ); if( FAILED( hr = m_ap3DBuffer[dwIndex]->SetMaxDistance( maxDistance, DS3D_IMMEDIATE ) ) ) SNDError( "SetMaxDistance (DS3DBuffer) Failed!! ErrorCode : 0x%x", hr ); } /////////////////////////////////////////////////////////////////////////////////////////