📄 dsutil.cpp
字号:
{ hr = pDSB->Play( 0, dwPriority, dwFlags ); } pDS3DBuffer->Release(); } return hr;}//-----------------------------------------------------------------------------// Name: CSound::Stop()// Desc: Stops the sound from playing//-----------------------------------------------------------------------------HRESULT CSound::Stop(){ if( m_apDSBuffer == NULL ) return CO_E_NOTINITIALIZED; HRESULT hr = 0; for( DWORD i=0; i<m_dwNumBuffers; i++ ) hr |= m_apDSBuffer[i]->Stop(); return hr;}//-----------------------------------------------------------------------------// Name: CSound::Reset()// Desc: Reset all of the sound buffers//-----------------------------------------------------------------------------HRESULT CSound::Reset(){ if( m_apDSBuffer == NULL ) return CO_E_NOTINITIALIZED; HRESULT hr = 0; for( DWORD i=0; i<m_dwNumBuffers; i++ ) hr |= m_apDSBuffer[i]->SetCurrentPosition( 0 ); return hr;}//-----------------------------------------------------------------------------// Name: CSound::IsSoundPlaying()// Desc: Checks to see if a buffer is playing and returns true if it is.//-----------------------------------------------------------------------------BOOL CSound::IsSoundPlaying(){ BOOL bIsPlaying = false; if( m_apDSBuffer == NULL ) return false; for( DWORD i=0; i<m_dwNumBuffers; i++ ) { if( m_apDSBuffer[i] ) { DWORD dwStatus = 0; m_apDSBuffer[i]->GetStatus( &dwStatus ); bIsPlaying |= ( ( dwStatus & DSBSTATUS_PLAYING ) != 0 ); } } return bIsPlaying;}//-----------------------------------------------------------------------------// Name: CStreamingSound::CStreamingSound()// Desc: Setups up a buffer so data can be streamed from the wave file into // a buffer. This is very useful for large wav files that would take a // while to load. The buffer is initially filled with data, then // as sound is played the notification events are signaled and more data// is written into the buffer by calling HandleWaveStreamNotification()//-----------------------------------------------------------------------------CStreamingSound::CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, CWaveFile* pWaveFile, DWORD dwNotifySize ) : CSound( &pDSBuffer, dwDSBufferSize, 1, pWaveFile, 0 ) { m_dwLastPlayPos = 0; m_dwPlayProgress = 0; m_dwNotifySize = dwNotifySize; m_dwNextWriteOffset = 0; m_bFillNextNotificationWithSilence = false;}//-----------------------------------------------------------------------------// Name: CStreamingSound::~CStreamingSound()// Desc: Destroys the class//-----------------------------------------------------------------------------CStreamingSound::~CStreamingSound(){}//-----------------------------------------------------------------------------// Name: CStreamingSound::HandleWaveStreamNotification()// Desc: Handle the notification that tells us to put more wav data in the // circular buffer//-----------------------------------------------------------------------------HRESULT CStreamingSound::HandleWaveStreamNotification( BOOL bLoopedPlay ){ HRESULT hr; DWORD dwCurrentPlayPos; DWORD dwPlayDelta; DWORD dwBytesWrittenToBuffer; VOID* pDSLockedBuffer = NULL; VOID* pDSLockedBuffer2 = NULL; DWORD dwDSLockedBufferSize; DWORD dwDSLockedBufferSize2; if( m_apDSBuffer == NULL || m_pWaveFile == NULL ) return CO_E_NOTINITIALIZED; // Restore the buffer if it was lost BOOL bRestored; if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); if( bRestored ) { // The buffer was restored, so we need to fill it with new data if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], false ) ) ) return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); return S_OK; } // Lock the DirectSound buffer if( FAILED( hr = m_apDSBuffer[0]->Lock( m_dwNextWriteOffset, m_dwNotifySize, &pDSLockedBuffer, &dwDSLockedBufferSize, &pDSLockedBuffer2, &dwDSLockedBufferSize2, 0L ) ) ) return DXTRACE_ERR( TEXT("Lock"), hr ); // m_dwDSBufferSize and m_dwNextWriteOffset are both multiples of m_dwNotifySize, // it should the second buffer, so it should never be valid if( pDSLockedBuffer2 != NULL ) return E_UNEXPECTED; if( !m_bFillNextNotificationWithSilence ) { // Fill the DirectSound buffer with wav data if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, dwDSLockedBufferSize, &dwBytesWrittenToBuffer ) ) ) return DXTRACE_ERR( TEXT("Read"), hr ); } else { // Fill the DirectSound buffer with silence FillMemory( pDSLockedBuffer, dwDSLockedBufferSize, (BYTE)( m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); dwBytesWrittenToBuffer = dwDSLockedBufferSize; } // If the number of bytes written is less than the // amount we requested, we have a short file. if( dwBytesWrittenToBuffer < dwDSLockedBufferSize ) { if( !bLoopedPlay ) { // Fill in silence for the rest of the buffer. FillMemory( (BYTE*) pDSLockedBuffer + dwBytesWrittenToBuffer, dwDSLockedBufferSize - dwBytesWrittenToBuffer, (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); // Any future notifications should just fill the buffer with silence m_bFillNextNotificationWithSilence = true; } else { // We are looping, so reset the file and fill the buffer with wav data DWORD dwReadSoFar = dwBytesWrittenToBuffer; // From previous call above. while( dwReadSoFar < 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 ); if( FAILED( hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, dwDSLockedBufferSize - dwReadSoFar, &dwBytesWrittenToBuffer ) ) ) return DXTRACE_ERR( TEXT("Read"), hr ); dwReadSoFar += dwBytesWrittenToBuffer; } } } // Unlock the DirectSound buffer m_apDSBuffer[0]->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); // Figure out how much data has been played so far. When we have played // past the end of the file, we will either need to start filling the // buffer with silence or starting reading from the beginning of the file, // depending if the user wants to loop the sound if( FAILED( hr = m_apDSBuffer[0]->GetCurrentPosition( &dwCurrentPlayPos, NULL ) ) ) return DXTRACE_ERR( TEXT("GetCurrentPosition"), hr ); // Check to see if the position counter looped if( dwCurrentPlayPos < m_dwLastPlayPos ) dwPlayDelta = ( m_dwDSBufferSize - m_dwLastPlayPos ) + dwCurrentPlayPos; else dwPlayDelta = dwCurrentPlayPos - m_dwLastPlayPos; m_dwPlayProgress += dwPlayDelta; m_dwLastPlayPos = dwCurrentPlayPos; // If we are now filling the buffer with silence, then we have found the end so // check to see if the entire sound has played, if it has then stop the buffer. if( m_bFillNextNotificationWithSilence ) { // We don't want to cut off the sound before it's done playing. if( m_dwPlayProgress >= m_pWaveFile->GetSize() ) { m_apDSBuffer[0]->Stop(); } } // Update where the buffer will lock (for next time) m_dwNextWriteOffset += dwDSLockedBufferSize; m_dwNextWriteOffset %= m_dwDSBufferSize; // Circular buffer return S_OK;}//-----------------------------------------------------------------------------// Name: CStreamingSound::Reset()// Desc: Resets the sound so it will begin playing at the beginning//-----------------------------------------------------------------------------HRESULT CStreamingSound::Reset(){ HRESULT hr; if( m_apDSBuffer[0] == NULL || m_pWaveFile == NULL ) return CO_E_NOTINITIALIZED; m_dwLastPlayPos = 0; m_dwPlayProgress = 0; m_dwNextWriteOffset = 0; m_bFillNextNotificationWithSilence = false; // Restore the buffer if it was lost BOOL bRestored; if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); if( bRestored ) { // The buffer was restored, so we need to fill it with new data if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], false ) ) ) return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); } m_pWaveFile->ResetFile(); return m_apDSBuffer[0]->SetCurrentPosition( 0L ); }//-----------------------------------------------------------------------------// Name: CWaveFile::CWaveFile()// Desc: Constructs the class. Call Open() to open a wave file for reading. // Then call Read() as needed. Calling the destructor or Close() // will close the file. //-----------------------------------------------------------------------------CWaveFile::CWaveFile(){ m_pwfx = NULL; m_hmmio = NULL; m_pResourceBuffer = NULL; m_dwSize = 0; m_bIsReadingFromMemory = false;}//-----------------------------------------------------------------------------// Name: CWaveFile::~CWaveFile()// Desc: Destructs the class//-----------------------------------------------------------------------------CWaveFile::~CWaveFile(){ Close(); if( !m_bIsReadingFromMemory ) SAFE_DELETE_ARRAY( m_pwfx );}//-----------------------------------------------------------------------------// Name: CWaveFile::Open()// Desc: Opens a wave file for reading//-----------------------------------------------------------------------------HRESULT CWaveFile::Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ){ HRESULT hr; m_dwFlags = dwFlags; m_bIsReadingFromMemory = false; if( m_dwFlags == WAVEFILE_READ ) { if( strFileName == NULL ) return E_INVALIDARG; SAFE_DELETE_ARRAY( m_pwfx ); m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ ); if( NULL == m_hmmio ) { HRSRC hResInfo; HGLOBAL hResData; DWORD dwSize; VOID* pvRes; // Loading it as a file failed, so try it as a resource if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAVE") ) ) ) { if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAV") ) ) ) return DXTRACE_ERR( TEXT("FindResource"), E_FAIL ); } if( NULL == ( hResData = LoadResource( NULL, hResInfo ) ) ) return DXTRACE_ERR( TEXT("LoadResource"), E_FAIL ); if( 0 == ( dwSize = SizeofResource( NULL, hResInfo ) ) ) return DXTRACE_ERR( TEXT("SizeofResource"), E_FAIL ); if( NULL == ( pvRes = LockResource( hResData ) ) ) return DXTRACE_ERR( TEXT("LockResource"), E_FAIL ); m_pResourceBuffer = new CHAR[ dwSize ]; memcpy( m_pResourceBuffer, pvRes, dwSize ); MMIOINFO mmioInfo; ZeroMemory( &mmioInfo, sizeof(mmioInfo) ); mmioInfo.fccIOProc = FOURCC_MEM; mmioInfo.cchBuffer = dwSize; mmioInfo.pchBuffer = (CHAR*) m_pResourceBuffer; m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ ); } if( FAILED( hr = ReadMMIO() ) ) { // ReadMMIO will fail if its an not a wave file mmioClose( m_hmmio, 0 ); return DXTRACE_ERR( TEXT("ReadMMIO"), hr ); } if( FAILED( hr = ResetFile() ) ) return DXTRACE_ERR( TEXT("ResetFile"), hr ); // After the reset, the size of the wav file is m_ck.cksize so store it now m_dwSize = m_ck.cksize; } else { m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READWRITE | MMIO_CREATE ); if( NULL == m_hmmio ) return DXTRACE_ERR( TEXT("mmioOpen"), E_FAIL ); if( FAILED( hr = WriteMMIO( pwfx ) ) ) { mmioClose( m_hmmio, 0 ); return DXTRACE_ERR( TEXT("WriteMMIO"), hr ); } if( FAILED( hr = ResetFile() ) ) return DXTRACE_ERR( TEXT("ResetFile"), hr ); } return hr;}//-----------------------------------------------------------------------------// Name: CWaveFile::OpenFromMemory()// Desc: copy data to CWaveFile member variable from memory//-----------------------------------------------------------------------------HRESULT CWaveFile::OpenFromMemory( BYTE* pbData, ULONG ulDataSize, WAVEFORMATEX* pwfx, DWORD dwFlags ){ m_pwfx = pwfx;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -