// Sound.cpp: implementation of the CSound class. // ////////////////////////////////////////////////////////////////////// #include "WaveLoader.h" #include "Sound.h" #include "SoundMgr.h" #include "GMMemory.h" CSound::CSound() : m_ppDSBuffer( NULL ), m_pWaveFile( NULL ), m_dwNumBuffers( 0 ), m_dwDSBufferSize( 0 ), m_bSound3D( false ), m_bLoop( false ), m_fVolume( VOLUME_MAX ), m_dwLastPlayTime( 0 ), m_dwLatestPlayIndex( 0 ), m_iPreserveScore( 0 ) { } CSound::~CSound() { Destroy(); } HRESULT CSound::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, bool* pbWasRestored ) { HRESULT hr; if( pDSB == NULL ) return CO_E_NOTINITIALIZED; if( pbWasRestored ) *pbWasRestored = FALSE; DWORD dwStatus; if( FAILED( hr = pDSB->GetStatus( &dwStatus ) ) ) return E_FAIL; if( dwStatus & DSBSTATUS_BUFFERLOST ) { do { hr = pDSB->Restore(); if( hr == DSERR_BUFFERLOST ) Sleep( 10 ); } while( ( hr = pDSB->Restore() ) == DSERR_BUFFERLOST ); if( pbWasRestored != NULL ) *pbWasRestored = TRUE; return S_OK; } else { return S_FALSE; } } LPDIRECTSOUNDBUFFER CSound::GetFreeBuffer() { if( m_ppDSBuffer == NULL ) return FALSE; DWORD i=0; for( ; iGetStatus( &dwStatus ); if ( ( dwStatus & DSBSTATUS_PLAYING ) == 0 ) break; } } if( i != m_dwNumBuffers ) { m_dwLatestPlayIndex = i; return m_ppDSBuffer[ i ]; } else return m_ppDSBuffer[ rand() % m_dwNumBuffers ]; } LPDIRECTSOUNDBUFFER CSound::GetBuffer( DWORD dwIndex ) { if( m_ppDSBuffer == NULL ) return NULL; if( dwIndex >= m_dwNumBuffers ) return NULL; return m_ppDSBuffer[dwIndex]; } void CSound::Stop() { HRESULT hr = 0; for( DWORD i=0; iStop(); if( FAILED(hr) ) MessageBox( NULL, "hr |= m_ppDSBuffer[i]->Stop()", "CSound::Stop", MB_OK ); } void CSound::Reset() { HRESULT hr = 0; for( DWORD i=0; iSetCurrentPosition( 0 ); if( FAILED(hr) ) MessageBox( NULL, "hr |= m_ppDSBuffer[i]->SetCurrentPosition", "CSound::Stop", MB_OK ); } bool CSound::IsPlaying() { bool bIsPlaying = false; if( m_ppDSBuffer == NULL ) return false; for( DWORD i=0; iGetStatus( &dwStatus ); bIsPlaying |= ( ( dwStatus & DSBSTATUS_PLAYING ) != 0 ); } } return bIsPlaying; } bool CSound::Create( const char* strFileName, DWORD dwNumBuffers ) { DWORD i; DWORD dwDSBufferSize = NULL; m_dwNumBuffers = dwNumBuffers; LPDIRECTSOUND8 pDS = CSoundMgr::_GetInstance()->GetDirectSound(); m_ppDSBuffer = new LPDIRECTSOUNDBUFFER8[dwNumBuffers]; for( i = 0; i < dwNumBuffers; ++i ) { m_ppDSBuffer[i] = 0; } m_pWaveFile = new CWaveLoader; if( FAILED(m_pWaveFile->Open((LPSTR)strFileName, NULL, WAVEFILE_READ)) ) { char buf[MAX_PATH] = {0}; sprintf( buf, "ÇØ´ç ÆÄÀÏÀ» ¿­¼ö°¡ ¾ø½À´Ï´Ù. : %s \n CSound::Create", strFileName ); MessageBox( NULL, buf, "»ç¿îµå¿¡·¯", MB_OK ); SAFE_DELETE(m_pWaveFile); return false; } m_dwDSBufferSize = m_pWaveFile->GetSize(); WAVEFORMATEX wfx; ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); wfx.nChannels = m_pWaveFile->m_pwfx->nChannels; wfx.nSamplesPerSec = m_pWaveFile->m_pwfx->nSamplesPerSec; wfx.wBitsPerSample = m_pWaveFile->m_pwfx->wBitsPerSample; wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; if( m_bSound3D && wfx.nChannels != 1 ) { MessageBox( NULL, "3DSound Only Acquire One Channel", "Sound::Create", MB_OK ); wfx.nChannels = 1; Destroy(); return false; } //Create Buffer DSBUFFERDESC dsbd; ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = DSBCAPS_CTRLVOLUME; if( m_bSound3D ) dsbd.dwFlags |= DSBCAPS_CTRL3D|DSBCAPS_MUTE3DATMAXDISTANCE; dsbd.dwBufferBytes = m_dwDSBufferSize; dsbd.guid3DAlgorithm = m_bSound3D ? CSoundMgr::_GetInstance()->GetInitProp()->m_guidSound3DAlgorithm : GUID_NULL; dsbd.lpwfxFormat = &wfx; //======================================== LPDIRECTSOUNDBUFFER tempBuffer; if( FAILED(pDS->CreateSoundBuffer( &dsbd, &tempBuffer, NULL )) ) { //MessageBox( NULL, "pDS->CreateSoundBuffer( &dsbd, &tempBuffer, NULL )", "CSound::Create", MB_OK ); SAFE_RELEASE( tempBuffer ); Destroy(); return false; } if( FAILED(tempBuffer->QueryInterface( IID_IDirectSoundBuffer8, (LPVOID*)m_ppDSBuffer )) ) { //MessageBox( NULL, "pDS->CreateSoundBuffer( &dsbd, &tempBuffer, NULL )", "CSound::Create", MB_OK ); SAFE_RELEASE( tempBuffer ); Destroy(); return false; } SAFE_RELEASE(tempBuffer) for( i = 1; i < dwNumBuffers; i++ ) { if( FAILED(pDS->DuplicateSoundBuffer( m_ppDSBuffer[0], (LPDIRECTSOUNDBUFFER*)&m_ppDSBuffer[i])) ) { //MessageBox( NULL, "pDS->DuplicateSoundBuffer( m_ppDSBuffer[0], &m_ppDSBuffer[i])", // "CSound::Create", MB_OK ); Destroy(); return false; } } FillBuffer( m_ppDSBuffer[0] ); //=============================================== /* if( FAILED(pDS->CreateSoundBuffer( &dsbd, &m_ppDSBuffer[0], NULL )) ) { //MessageBox( NULL, "pDS->CreateSoundBuffer( &dsbd, &m_ppDSBuffer[0], NULL )", // "CSound::Create", MB_OK ); Destroy(); return false; } for( i = 1; i < dwNumBuffers; i++ ) { if( FAILED(pDS->DuplicateSoundBuffer( m_ppDSBuffer[0], &m_ppDSBuffer[i])) ) { //MessageBox( NULL, "pDS->DuplicateSoundBuffer( m_ppDSBuffer[0], &m_ppDSBuffer[i])", // "CSound::Create", MB_OK ); Destroy(); return false; } } FillBuffer( m_ppDSBuffer[0] ); */ return true; } void CSound::Destroy() { for( DWORD i = 0; i < m_dwNumBuffers; i++ ) { SAFE_RELEASE( m_ppDSBuffer[i] ); } SAFE_DELETE_ARRAY( m_ppDSBuffer ); SAFE_DELETE( m_pWaveFile ); } void CSound::Play() { if( 0 == this ) { return; } m_dwLastPlayTime = timeGetTime(); bool bRestored; LPDIRECTSOUNDBUFFER pDSB = GetFreeBuffer(); if( FAILED(RestoreBuffer(pDSB, &bRestored)) ) { MessageBox(NULL, "FAILED(RestoreBuffer(pDSB, &bRestored))", "CSound::Play", MB_OK ); return; } if( bRestored ) { FillBuffer( pDSB ); } SetVolume(pDSB, m_fVolume); pDSB->Play(0,0, m_bLoop ? DSBPLAY_LOOPING:0 ); } void CSound::FillBuffer( LPDIRECTSOUNDBUFFER pDSBuffer ) { VOID* pDSLockedBuffer = NULL; DWORD dwDSLockedBufferSize = 0; DWORD dwWavDataRead = 0; if( FAILED(RestoreBuffer( pDSBuffer, NULL)) ) { MessageBox( NULL, "FAILED(RestoreBuffer( pDSBuffer, NULL))", "CSound::FillBuffer", MB_OK ); return; } if( FAILED(pDSBuffer->Lock(0, 0, &pDSLockedBuffer, &dwDSLockedBufferSize, NULL, NULL, DSBLOCK_ENTIREBUFFER ) ) ) { MessageBox( NULL, "FAILED(pDSBuffer->Lock", "CSound::FillBuffer", MB_OK ); return; } m_pWaveFile->ResetFile(); if( FAILED(m_pWaveFile->Read((BYTE*)pDSLockedBuffer, dwDSLockedBufferSize, &dwWavDataRead)) ) { MessageBox( NULL, "FAILED(m_pWaveFile->Read", "CSound::FillBuffer", MB_OK ); return; } if( dwWavDataRead == 0 ) { MessageBox( NULL, "dwWavDataRead == 0", "CSound::FillBuffer", MB_OK ); return; } pDSBuffer->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); } void CSound::SetVolume(LPDIRECTSOUNDBUFFER pDSBuffer, float fVol ) { if( !pDSBuffer ) return; m_fVolume = Clamp( fVol, VOLUME_MIN, VOLUME_MAX ); float fMasterVol = CSoundMgr::_GetInstance()->GetVolume(); fMasterVol = Clamp( fMasterVol, VOLUME_MIN, VOLUME_MAX ); int iVol = LinearToLogVol(m_fVolume * fMasterVol); if(iVol < -10000) iVol = -10000; if( FAILED(pDSBuffer->SetVolume(iVol)) ) { MessageBox( NULL, "FAILED(pDSBuffer->SetVolume(iVol))", "CSound::SetVolume", MB_OK ); } } void CSound::SetVolume( float fVol ) { if( !m_ppDSBuffer ) return; m_fVolume = Clamp( fVol, VOLUME_MIN, VOLUME_MAX ); }