Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code: - Client: Game client source (moved to Client/Client/) - Server: Game server source - GameTools: Development tools - CryptoSource: Encryption utilities - database: Database scripts - Script: Game scripts - rylCoder_16.02.2008_src: Legacy coder tools - GMFont, Game: Additional resources 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
339
GameTools/SoundLib/StreamingSound.cpp
Normal file
339
GameTools/SoundLib/StreamingSound.cpp
Normal file
@@ -0,0 +1,339 @@
|
||||
// StreamingSound.cpp: implementation of the CStreamingSound class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StreamingSound.h"
|
||||
#include "Sound.h"
|
||||
#include "WaveLoader.h"
|
||||
#include "OggLoader.h"
|
||||
#include "SoundMgr.h"
|
||||
|
||||
|
||||
|
||||
CStreamingSound::CStreamingSound() : m_pDSBuffer(NULL),
|
||||
m_pOggFile(NULL),
|
||||
m_dwDSBufferSize(0),
|
||||
m_dwDataCursor(0),
|
||||
m_dwBytesPlayed(0),
|
||||
m_dwLastReadPos(0),
|
||||
m_bPlaying(false),
|
||||
m_bRemoveStream(true),
|
||||
m_bLoop(false),
|
||||
m_bSound3D(false),
|
||||
m_fVolume(VOLUME_MAX)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CStreamingSound::~CStreamingSound()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
|
||||
void CStreamingSound::Destroy()
|
||||
{
|
||||
EnterCriticalSection(&CSoundManager::_GetInstance()->GetUpdateCS());
|
||||
CSoundManager::_GetInstance()->RemoveStream(this);
|
||||
LeaveCriticalSection(&CSoundManager::_GetInstance()->GetUpdateCS());
|
||||
|
||||
SAFE_RELEASE( m_pDSBuffer );
|
||||
SAFE_DELETE( m_pOggFile );
|
||||
}
|
||||
|
||||
|
||||
HRESULT CStreamingSound::Reset()
|
||||
{
|
||||
m_dwDataCursor = 0;
|
||||
m_dwBytesPlayed = 0;
|
||||
m_dwLastReadPos = 0;
|
||||
m_bRemoveStream = false;
|
||||
|
||||
m_pOggFile->Reset();
|
||||
|
||||
return m_pDSBuffer->SetCurrentPosition( 0L );
|
||||
}
|
||||
|
||||
|
||||
bool CStreamingSound::Create( char* strFileName )
|
||||
{
|
||||
LPDIRECTSOUND8 pDS = CSoundManager::_GetInstance()->GetDirectSound();
|
||||
|
||||
m_pOggFile = new COggLoader();
|
||||
if( !m_pOggFile->Open( strFileName ) )
|
||||
{
|
||||
char buf[MAX_PATH] = {0};
|
||||
sprintf( buf, "<EFBFBD>ش<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>. %s \n CStreamingSound::Create", strFileName );
|
||||
MessageBox( NULL, buf, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>忡<EFBFBD><EFBFBD>", MB_OK );
|
||||
return false;
|
||||
}
|
||||
m_dwDSBufferSize = m_pOggFile->m_WaveFormatEx.nAvgBytesPerSec*3; //3<><33> <20><><EFBFBD>ۻ<EFBFBD><DBBB><EFBFBD>
|
||||
|
||||
if( m_bSound3D && m_pOggFile->GetFormat()->nChannels > 1 )
|
||||
{
|
||||
MessageBox( NULL, "3DSound Only Acquire One Channel", "CStreamingSound::Create", MB_OK );
|
||||
SAFE_DELETE(m_pOggFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
DSBUFFERDESC dsbd;
|
||||
ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
|
||||
dsbd.dwSize = sizeof(DSBUFFERDESC);
|
||||
dsbd.dwFlags = DSBCAPS_CTRLVOLUME|DSBCAPS_GETCURRENTPOSITION2;
|
||||
if( m_bSound3D ) dsbd.dwFlags |= DSBCAPS_CTRL3D|DSBCAPS_MUTE3DATMAXDISTANCE;
|
||||
dsbd.dwBufferBytes = m_dwDSBufferSize;
|
||||
dsbd.guid3DAlgorithm = m_bSound3D ?
|
||||
CSoundManager::_GetInstance()->GetInitProp()->m_guidSound3DAlgorithm:GUID_NULL;
|
||||
dsbd.lpwfxFormat = &m_pOggFile->m_WaveFormatEx;
|
||||
|
||||
|
||||
LPDIRECTSOUNDBUFFER tempBuffer;
|
||||
if( FAILED(pDS->CreateSoundBuffer( &dsbd, &tempBuffer, NULL )) )
|
||||
{
|
||||
SAFE_RELEASE(tempBuffer);
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
if( FAILED(tempBuffer->QueryInterface( IID_IDirectSoundBuffer8, (LPVOID*)&m_pDSBuffer )) )
|
||||
{
|
||||
SAFE_RELEASE(tempBuffer);
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
tempBuffer->Release();
|
||||
|
||||
/*
|
||||
if( FAILED(pDS->CreateSoundBuffer(&dsbd, &m_pDSBuffer, NULL) ))
|
||||
{
|
||||
//MessageBox( NULL, "CreateSoundBuffer", "streaming", MB_OK );
|
||||
SAFE_RELEASE( m_pDSBuffer );
|
||||
SAFE_DELETE( m_pOggFile );
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
FillBuffer();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CStreamingSound::Play()
|
||||
{
|
||||
if( m_bPlaying ) return;
|
||||
|
||||
EnterCriticalSection(&CSoundManager::_GetInstance()->GetUpdateCS());
|
||||
m_bRemoveStream = false;
|
||||
CSoundManager::_GetInstance()->InsertStream(this);
|
||||
LeaveCriticalSection(&CSoundManager::_GetInstance()->GetUpdateCS());
|
||||
|
||||
if( FAILED(m_pDSBuffer->Play(0,0,DSBPLAY_LOOPING)) )
|
||||
MessageBox( NULL, "m_pDSBuffer->Play(0,0,0)", "Play()", MB_OK );
|
||||
|
||||
m_bPlaying = true;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CStreamingSound::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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CStreamingSound::ServiceBuffer()
|
||||
{
|
||||
if(m_bRemoveStream)
|
||||
{
|
||||
if(!m_pDSBuffer || !m_pOggFile)
|
||||
return;
|
||||
|
||||
m_bRemoveStream = false;
|
||||
CSoundManager::_GetInstance()->RemoveStream(this);
|
||||
m_pOggFile->Reset();
|
||||
Reset();
|
||||
FillBuffer();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(!m_pDSBuffer || !m_pOggFile)
|
||||
return;
|
||||
|
||||
DWORD dwReadCursor;
|
||||
DWORD dwWriteCursor;
|
||||
if( FAILED(m_pDSBuffer->GetCurrentPosition(&dwReadCursor, &dwWriteCursor)) )
|
||||
MessageBox( NULL, "FAILED(m_pDSBuffer->GetCurrentPosition(&dwReadCursor, &dwWriteCursor))",
|
||||
"ServiceBuffer()", MB_OK );
|
||||
|
||||
if(dwReadCursor > m_dwLastReadPos)
|
||||
m_dwBytesPlayed += dwReadCursor - m_dwLastReadPos;
|
||||
else
|
||||
m_dwBytesPlayed += (m_dwDSBufferSize - m_dwLastReadPos) + dwReadCursor;
|
||||
|
||||
if(m_dwBytesPlayed >= m_pOggFile->GetSize())
|
||||
{
|
||||
if( m_bLoop )
|
||||
{
|
||||
m_dwBytesPlayed -= m_pOggFile->GetSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
Stop();
|
||||
m_bPlaying = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD dwDataToCopy;
|
||||
if(m_dwDataCursor < dwReadCursor)
|
||||
dwDataToCopy = dwReadCursor - m_dwDataCursor;
|
||||
else
|
||||
dwDataToCopy = (m_dwDSBufferSize - m_dwDataCursor) + dwReadCursor;
|
||||
|
||||
if(dwDataToCopy > (m_dwDSBufferSize / 2))
|
||||
dwDataToCopy = m_dwDSBufferSize / 2;
|
||||
|
||||
LPVOID pPtr1;
|
||||
DWORD dwBytes1;
|
||||
LPVOID pPtr2;
|
||||
DWORD dwBytes2;
|
||||
if( FAILED(m_pDSBuffer->Lock(m_dwDataCursor, dwDataToCopy,
|
||||
&pPtr1, &dwBytes1, &pPtr2, &dwBytes2, 0)) )
|
||||
{
|
||||
MessageBox( NULL, "m_pDSBuffer->Lock(m_dwDataCursor, dwDataToCopy, &pPtr1, &dwBytes1, &pPtr2, &dwBytes2, 0)",
|
||||
"ServiceBuffer()", MB_OK );
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_pOggFile->IsEOF())
|
||||
{
|
||||
memset(pPtr1, GetSilenceData(), dwBytes1);
|
||||
if(pPtr2) memset(pPtr2, GetSilenceData(), dwBytes2);
|
||||
m_dwDataCursor += (dwBytes1 + dwBytes2);
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD dwBytesRead = 0;
|
||||
if( FAILED(m_pOggFile->Read((BYTE*)pPtr1, dwBytes1, &dwBytesRead)) )
|
||||
{
|
||||
MessageBox( NULL, "m_pWaveFile->Read((BYTE*)pPtr1, dwBytes1, &dwBytesRead)",
|
||||
"ServiceBuffer()", MB_OK );
|
||||
}
|
||||
|
||||
m_dwDataCursor += dwBytesRead;
|
||||
|
||||
if(pPtr2 && (dwBytes1 == dwBytesRead))
|
||||
{
|
||||
if( FAILED(m_pOggFile->Read((BYTE*)pPtr2, dwBytes2, &dwBytesRead)) )
|
||||
{
|
||||
MessageBox( NULL, "m_pWaveFile->Read((BYTE*)pPtr2, dwBytes2, &dwBytesRead)",
|
||||
"ServiceBuffer()", MB_OK );
|
||||
}
|
||||
m_dwDataCursor += dwBytesRead;
|
||||
}
|
||||
}
|
||||
|
||||
m_pDSBuffer->Unlock(pPtr1, dwBytes1, pPtr2, dwBytes2);
|
||||
|
||||
if( m_bLoop && m_pOggFile->IsEOF())
|
||||
m_pOggFile->Reset();
|
||||
|
||||
m_dwDataCursor %= m_dwDSBufferSize;
|
||||
m_dwLastReadPos = dwReadCursor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CStreamingSound::Stop()
|
||||
{
|
||||
if(!m_pDSBuffer)
|
||||
return;
|
||||
|
||||
m_pDSBuffer->Stop();
|
||||
m_bRemoveStream = true;
|
||||
m_bPlaying = false;
|
||||
}
|
||||
|
||||
|
||||
BYTE CStreamingSound::GetSilenceData()
|
||||
{
|
||||
if(m_pOggFile->m_WaveFormatEx.wBitsPerSample == 8)
|
||||
return 0x80;
|
||||
else if(m_pOggFile->m_WaveFormatEx.wBitsPerSample == 16)
|
||||
return 0x00;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void CStreamingSound::FillBuffer()
|
||||
{
|
||||
// Lock the buffer
|
||||
void* pData;
|
||||
DWORD dwBytes;
|
||||
if( FAILED(m_pDSBuffer->Lock(0, 0, &pData, &dwBytes, NULL, NULL, DSBLOCK_ENTIREBUFFER)) )
|
||||
MessageBox( NULL, "m_pDSBuffer->Lock(0, 0, &pData, &nBytes, NULL, NULL, DSBLOCK_ENTIREBUFFER)",
|
||||
"FillBuffer", MB_OK );
|
||||
|
||||
// Fill the entire buffer with audio data from source
|
||||
DWORD dwBytesToRead;
|
||||
DWORD dwBytesRead;
|
||||
|
||||
dwBytesToRead = dwBytes;
|
||||
|
||||
if( FAILED(m_pOggFile->Read((BYTE*)pData, dwBytesToRead, &dwBytesRead)) )
|
||||
MessageBox( NULL, "m_pWaveFile->Read((BYTE*)pData, dwBytesToRead, &dwBytesRead)",
|
||||
"FillBuffer", MB_OK );
|
||||
|
||||
m_dwDataCursor += dwBytesRead;
|
||||
m_dwDataCursor %= dwBytes;
|
||||
|
||||
if(dwBytesRead < dwBytes)
|
||||
memset(((BYTE*)pData) + dwBytesRead, GetSilenceData(), dwBytes - dwBytesRead);
|
||||
|
||||
if( FAILED(m_pDSBuffer->Unlock(pData, dwBytes, NULL, 0)) )
|
||||
MessageBox( NULL, "m_pDSBuffer->Unlock(pData, nBytes, NULL, 0)", "FillBuffer", MB_OK );
|
||||
}
|
||||
|
||||
|
||||
void CStreamingSound::SetVolume( float fVol )
|
||||
{
|
||||
m_fVolume = Clamp( fVol, VOLUME_MIN, VOLUME_MAX );
|
||||
float fMasterVol = CSoundManager::_GetInstance()->GetVolume();
|
||||
int iVol = LinearToLogVol(m_fVolume * fMasterVol);
|
||||
|
||||
if( m_pDSBuffer )
|
||||
{
|
||||
if( FAILED(m_pDSBuffer->SetVolume(iVol)) )
|
||||
MessageBox( NULL, "FAILED(m_pDSBuffer->SetVolume(iVol))",
|
||||
"CStreamingSound::SetVolume", MB_OK );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user