📄 dsutil.cpp
字号:
// 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 ) ) )
return -1;
// Lock the buffer down
if( FAILED( hr = pDSB->Lock( 0, m_dwDSBufferSize,
&pDSLockedBuffer, &dwDSLockedBufferSize,
NULL, NULL, 0L ) ) )
return -1;
// Reset the wave file to the beginning
m_pWaveFile->ResetFile();
if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer,
dwDSLockedBufferSize,
&dwWavDataRead ) ) )
return -1;
if( dwWavDataRead == 0 )
{
// Wav is blank, so just fill with silence
FillMemory( (BYTE*) pDSLockedBuffer,
dwDSLockedBufferSize,
(BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) );
}
else if( dwWavDataRead < 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
DWORD dwReadSoFar = dwWavDataRead; // 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 -1;
hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar,
dwDSLockedBufferSize - dwReadSoFar,
&dwWavDataRead );
if( FAILED(hr) )
return -1;
dwReadSoFar += dwWavDataRead;
}
}
else
{
// Don't repeat the wav file, just fill in silence
FillMemory( (BYTE*) pDSLockedBuffer + dwWavDataRead,
dwDSLockedBufferSize - dwWavDataRead,
(BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) );
}
}
// Unlock the buffer, we don't need it anymore.
pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: CSound::RestoreBuffer()
// Desc: Restores the lost buffer. *pbWasRestored returns TRUE if the buffer was
// restored. It can also NULL if the information is not needed.
//-----------------------------------------------------------------------------
HRESULT CSound::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored )
{
HRESULT hr;
if( pDSB == NULL )
return CO_E_NOTINITIALIZED;
if( pbWasRestored )
*pbWasRestored = FALSE;
DWORD dwStatus=0;
if( FAILED( hr = pDSB->GetStatus( &dwStatus ) ) )
return -1;
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 );
}
while( hr = pDSB->Restore() );
if( pbWasRestored != NULL )
*pbWasRestored = TRUE;
return S_OK;
}
else
{
return S_FALSE;
}
}
//-----------------------------------------------------------------------------
// Name: CSound::Play()
// Desc: Plays the sound using voice management flags. Pass in DSBPLAY_LOOPING
// in the dwFlags to loop the sound
//-----------------------------------------------------------------------------
BOOL CSound::RePlay(int nLoop,int nRange,int nX,int nY)
{
m_nWorldX = nX;m_nWorldY = nY;m_nRange = nRange;m_nLoop = nLoop;
Continue();
return 1;
}
HRESULT CSound::Play( DWORD dwPriority, DWORD dwFlags )
{
HRESULT hr;
BOOL bRestored;
if( m_apDSBuffer == NULL )
return CO_E_NOTINITIALIZED;
LPDIRECTSOUNDBUFFER pDSB = m_apDSBuffer;
if( pDSB == NULL )
return -1;
// Restore the buffer if it was lost
if( FAILED( hr = RestoreBuffer( pDSB, &bRestored ) ) )
return -1;
if( bRestored )
{
// The buffer was restored, so we need to fill it with new data
if( FAILED( hr = FillBufferWithSound( pDSB, FALSE ) ) )
return -1;
m_apDSBuffer->SetCurrentPosition( 0 );
}
m_dwSleepTime = 0;
m_n3DSoundActived = 1;
return pDSB->Play( 0, dwPriority, dwFlags );
}
//-----------------------------------------------------------------------------
// Name: CSound::Stop()
// Desc: Stops the sound from playing
//-----------------------------------------------------------------------------
HRESULT CSound::Stop()
{
if( m_apDSBuffer == NULL )
return CO_E_NOTINITIALIZED;
HRESULT hr = 0;
hr |= m_apDSBuffer->Stop();
m_n3DSoundActived = 0;
m_dwSleepTime = 1;
return hr;
}
HRESULT CSound::Continue()
{
HRESULT hr;
BOOL bRestored;
if( m_apDSBuffer == NULL )
return CO_E_NOTINITIALIZED;
LPDIRECTSOUNDBUFFER pDSB = m_apDSBuffer;
if( pDSB == NULL )
return -1;
// Restore the buffer if it was lost
if( FAILED( hr = RestoreBuffer( pDSB, &bRestored ) ) )
return -1;
if( bRestored )
{
// The buffer was restored, so we need to fill it with new data
if( FAILED( hr = FillBufferWithSound( pDSB, FALSE ) ) )
return -1;
}
DWORD flag;
if ( (m_dwControl & DSBPLAY_LOOPING ) == 0 )
flag = 0;
else
flag = DSBPLAY_LOOPING;
m_apDSBuffer->SetCurrentPosition(0);
hr |= m_apDSBuffer->Play(0,0,flag);
SetVolume(m_nVolume);
m_dwSleepTime = 0;
m_n3DSoundActived = 1;
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 )
{
DWORD dwStatus = 0;
m_apDSBuffer->GetStatus( &dwStatus );
bIsPlaying |= ( ( dwStatus & DSBSTATUS_PLAYING ) != 0 );
}
else
return FALSE;
return bIsPlaying;
}
//-----------------------------------------------------------------------------
// 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_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 -1;
}
if( NULL == ( hResData = LoadResource( NULL, hResInfo ) ) )
return -1;
if( 0 == ( dwSize = SizeofResource( NULL, hResInfo ) ) )
return -1;
if( NULL == ( pvRes = LockResource( hResData ) ) )
return -1;
CHAR* pData = new CHAR[ dwSize ];
memcpy( pData, pvRes, dwSize );
MMIOINFO mmioInfo;
ZeroMemory( &mmioInfo, sizeof(mmioInfo) );
mmioInfo.fccIOProc = FOURCC_MEM;
mmioInfo.cchBuffer = dwSize;
mmioInfo.pchBuffer = (CHAR*) pData;
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 -1;
}
if( FAILED( hr = ResetFile() ) )
return -1;
// 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 -1;
if( FAILED( hr = WriteMMIO( pwfx ) ) )
{
mmioClose( m_hmmio, 0 );
return -1;
}
if( FAILED( hr = ResetFile() ) )
return -1;
}
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;
m_ulDataSize = ulDataSize;
m_pbData = pbData;
m_pbDataCur = m_pbData;
m_bIsReadingFromMemory = TRUE;
if( dwFlags != WAVEFILE_READ )
return E_NOTIMPL;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: CWaveFile::ReadMMIO()
// Desc: Support function for reading from a multimedia I/O stream.
// m_hmmio must be valid before calling. This function uses it to
// update m_ckRiff, and m_pwfx.
//-----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -