Files
Client/GameTools/SoundLib/StreamBuffer.cpp
LGram16 dd97ddec92 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>
2025-11-29 20:17:20 +09:00

433 lines
13 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "StreamBuffer.h"
#include "SoundFile.h"
#include <dsound.h>
#include <assert.h>
extern bool g_b3DSound;
/////////////////////////////////////////////////////////////////////////////////////////
//
CStreamBuffer::CStreamBuffer()
: m_dwLastPlayPos( 0 )
, m_dwPlayProgress( 0 )
, m_dwNotifySize( 0 )
, m_dwNextWriteOffset( 0 )
, m_hNotificationEvent( NULL )
, m_bFillNextNotificationWithSilence( false )
{
}
/////////////////////////////////////////////////////////////////////////////////////////
//
CStreamBuffer::CStreamBuffer( IDirectSound8 * pDSound, ISoundFile * pSoundFile, bool b3DSound, DWORD dwNumBuffers )
: m_dwLastPlayPos( 0 )
, m_dwPlayProgress( 0 )
, m_dwNotifySize( 0 )
, m_dwNextWriteOffset( 0 )
, m_hNotificationEvent( NULL )
, m_bFillNextNotificationWithSilence( false )
, m_bLoopPlay( false )
{
Create( pDSound, pSoundFile, b3DSound, dwNumBuffers, 0 );
}
/////////////////////////////////////////////////////////////////////////////////////////
//
CStreamBuffer::CStreamBuffer( IDirectSound8 * pDSound, const char * szFilename, bool b3DSound, DWORD dwNumBuffers )
: m_dwLastPlayPos( 0 )
, m_dwPlayProgress( 0 )
, m_dwNotifySize( 0 )
, m_dwNextWriteOffset( 0 )
, m_hNotificationEvent( NULL )
, m_bFillNextNotificationWithSilence( false )
, m_bLoopPlay( false )
{
Create( pDSound, szFilename, b3DSound, dwNumBuffers, 0 );
}
/////////////////////////////////////////////////////////////////////////////////////////
//
CStreamBuffer::~CStreamBuffer()
{
Destroy();
}
/////////////////////////////////////////////////////////////////////////////////////////
//
//( DWORD dwNotifyCount, DWORD dwNotifySize, HANDLE hNotifyEvent )
void CStreamBuffer::Create( IDirectSound8 * pDSound, ISoundFile * pSoundFile, bool b3DSound, DWORD dwNumBuffers, DWORD dwAddFlag )
{
Destroy();
if( g_b3DSound == false )
b3DSound = false;
m_hNotificationEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
m_pSoundFile = pSoundFile;
assert( pDSound != NULL && m_pSoundFile != NULL );
WAVEFORMATEX wfx;
ZeroMemory( &wfx, sizeof(WAVEFORMATEX) );
wfx.nChannels = m_pSoundFile->GetChannelCount();
wfx.nSamplesPerSec = m_pSoundFile->GetSamplePerSec();
wfx.wBitsPerSample = m_pSoundFile->GetBitsPerSample();
if( b3DSound )
{
if( wfx.nChannels != 1 ) //<2F>̰<EFBFBD><CCB0><EFBFBD> Stereo(2)<29><> <20>Ǿ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> DSBCAPS_CTRL3D<33><44> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>
{
MessageBox( NULL, "3D <20><><EFBFBD><EFBFBD><EFBFBD><20><><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD> <20><><EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ȭ<><C8AD><EFBFBD><EFBFBD> mono<6E><6F> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ǿ<EFBFBD> <20>־<EFBFBD><D6BE><EFBFBD> <20>մϴ<D5B4>. <20>׷<EFBFBD><D7B7><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><20>̻<EFBFBD><CCBB>ϰ<EFBFBD> <20>÷<EFBFBD><C3B7><EFBFBD> <20><> <20><><EFBFBD>Դϴ<D4B4>.", pSoundFile->GetFilename(), MB_OK );
wfx.nChannels = 1;
}
}
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nBlockAlign = ( wfx.wBitsPerSample * wfx.nChannels ) / 8;
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
DWORD dwNotifyCount = 32;
DWORD dwTotalSize = wfx.nSamplesPerSec * 3 * wfx.nBlockAlign; //3<><33> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><20><><EFBFBD><EFBFBD> <20><> <20>ֵ<EFBFBD><D6B5><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ũ<><C5A9> <20><><EFBFBD><EFBFBD>
m_dwNotifySize = dwTotalSize / dwNotifyCount;
m_dwNotifySize -= m_dwNotifySize % wfx.nBlockAlign;
m_dwDSBufferSize = m_dwNotifySize * dwNotifyCount;
// Set up the direct sound buffer. Request the NOTIFY flag, so
// that we are notified as the sound buffer plays. Note, that using this flag
// may limit the amount of hardware acceleration that can occur.
DSBUFFERDESC dsbd;
ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY |
DSBCAPS_GETCURRENTPOSITION2 |
dwAddFlag;
if( b3DSound )
dsbd.dwFlags |= DSBCAPS_CTRL3D | DSBCAPS_MUTE3DATMAXDISTANCE;
dsbd.dwBufferBytes = m_dwDSBufferSize;
dsbd.guid3DAlgorithm = GUID_NULL;
dsbd.lpwfxFormat = &wfx;
LPDIRECTSOUNDBUFFER tempBuffer = 0;
HRESULT hr = pDSound->CreateSoundBuffer( &dsbd, &tempBuffer, NULL );
if( FAILED( hr ) )
{
return;
/*
if( hr == E_INVALIDARG )
{
SNDError( "Create Streaming Buffer Failed!! ErrorCode : 0x%x, ExtraInfo : %d, %d, %d, %d, %d, %d, %d, SoundFileName : %s "
, hr, wfx.nChannels, wfx.nSamplesPerSec, wfx.wBitsPerSample, wfx.nBlockAlign
, wfx.nAvgBytesPerSec, dsbd.dwFlags, dsbd.dwBufferBytes, pSoundFile->GetFilename() );
}
else
SNDError( "Create Streaming Buffer Failed!! ErrorCode : 0x%x", hr );
*/
}
hr = tempBuffer->QueryInterface( IID_IDirectSoundBuffer8, (void**)&m_pDSBuffer8 );
ULONG refCount = tempBuffer->Release();
if( FAILED( hr ) )
{
SNDError( "QueryInterface Failed!! (at CStreamBuffer::Create)... ErrorCode : 0x%x", hr );
}
m_dwNumBuffers = dwNumBuffers;
m_apDSBuffer = new LPDIRECTSOUNDBUFFER[m_dwNumBuffers];
ZeroMemory( m_apDSBuffer, sizeof(LPDIRECTSOUNDBUFFER) * m_dwNumBuffers );
for( DWORD 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 );
}
}
LPDIRECTSOUNDNOTIFY pDSNotify = NULL;
// Create the notification events, so that we know when to fill
// the buffer as the sound plays.
if( FAILED( hr = m_apDSBuffer[0]->QueryInterface( IID_IDirectSoundNotify, (VOID**)&pDSNotify ) ) )
SNDError( "Query DirectSoundNotify Object Failed!! ErrorCode : 0x%x", hr );
DSBPOSITIONNOTIFY* aPosNotify = new DSBPOSITIONNOTIFY[ dwNotifyCount ];
for( i = 0; i < dwNotifyCount; i++ )
{
aPosNotify[i].dwOffset = (m_dwNotifySize * i) + m_dwNotifySize - 1;
aPosNotify[i].hEventNotify = m_hNotificationEvent;
#ifdef DEBUG_LOG
log_file << "[NotificationPositions:" << m_pSoundFile->GetFilename() << "] Offset: "
<< aPosNotify[i].dwOffset << endl;
#endif
}
// Tell DirectSound when to notify us. The notification will come in the from
// of signaled events that are handled in WinMain()
if( FAILED( hr = pDSNotify->SetNotificationPositions( dwNotifyCount,
aPosNotify ) ) )
{
pDSNotify->Release();
delete [] aPosNotify;
SNDError( "SetNotificationPositions Failed!! ErrorCode : 0x%x", hr );
}
if( pDSNotify )
pDSNotify->Release();
delete [] aPosNotify;
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] );
m_dwLastPlayPos = 0;
m_dwPlayProgress = 0;
m_dwNextWriteOffset = 0;
m_bFillNextNotificationWithSilence = false;
#ifdef DEBUG_LOG
if( log_file.is_open() && m_pSoundFile != NULL )
log_file << "StreamBuffer Created! (" << m_pSoundFile->GetFilename() << ")\n";
#endif
}
/////////////////////////////////////////////////////////////////////////////////////////
//
void CStreamBuffer::Create( IDirectSound8 * pDSound, const char * szFilename, bool b3DSound, DWORD dwNumBuffers, DWORD dwAddFlag )
{
if( !IsFileExist2( szFilename ) )
{
SNDError( "%s : ȭ<><C8AD><EFBFBD><EFBFBD> <20><> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>.", szFilename );
}
ISoundFile * pSoundFile = ISoundFile::CreateSoundFileInstance( szFilename );
Create( pDSound, pSoundFile, b3DSound, dwNumBuffers, dwAddFlag );
}
/////////////////////////////////////////////////////////////////////////////////////////
//
void CStreamBuffer::Destroy()
{
CSoundBuffer::Destroy();
if( m_hNotificationEvent )
{
CloseHandle( m_hNotificationEvent );
m_hNotificationEvent = NULL;
}
}
/////////////////////////////////////////////////////////////////////////////////////////
//
int CStreamBuffer::Play( bool bLoopPlay )
{
m_bLoopPlay = bLoopPlay;
unsigned index = CSoundBuffer::Play( true );
if( index >= m_dwNumBuffers )
return index;
DWORD Pos;
m_apDSBuffer[0]->GetCurrentPosition( &Pos, NULL );
m_apDSBuffer[index]->SetCurrentPosition( Pos );
return index;
}
void CStreamBuffer::Play( DWORD dwIndex, bool bLoopPlay )
{
if( dwIndex >= m_dwNumBuffers )
return;
m_bLoopPlay = bLoopPlay;
CSoundBuffer::Play( dwIndex, true );
DWORD Pos;
m_apDSBuffer[dwIndex]->GetCurrentPosition( &Pos, NULL );
m_apDSBuffer[dwIndex]->SetCurrentPosition( Pos );
}
/////////////////////////////////////////////////////////////////////////////////////////
//
void CStreamBuffer::Reset( unsigned bufIndex )
{
ResetAll();
}
/////////////////////////////////////////////////////////////////////////////////////////
//
void CStreamBuffer::ResetAll()
{
assert( m_apDSBuffer[0] != NULL && m_pSoundFile != NULL );
m_dwLastPlayPos = 0;
m_dwPlayProgress = 0;
m_dwNextWriteOffset = 0;
m_bFillNextNotificationWithSilence = false;
if( Restore( m_apDSBuffer[0] ) )
{
FillBufferWithSound( m_apDSBuffer[0] );
}
m_pSoundFile->Reset();
HRESULT hr = m_apDSBuffer[0]->SetCurrentPosition( 0L );
if( FAILED( hr ) )
SNDError( "SetCurrentPosition(at CStreamBuffer::Reset) Failed!! ErrorCode : 0x%x", hr );
}
/////////////////////////////////////////////////////////////////////////////////////////
//
void CStreamBuffer::HandleNotification()
{
assert( m_apDSBuffer != NULL && m_pSoundFile != NULL );
//Play<61>ǰ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ŵ<EFBFBD>Ѵ<EFBFBD>.
DWORD dwStatus = 0;
m_apDSBuffer[0]->GetStatus( &dwStatus );
if( ( dwStatus & DSBSTATUS_PLAYING ) == 0 )
return;
if( Restore( m_apDSBuffer[0] ) )
{
FillBufferWithSound( m_apDSBuffer[0] );
return;
}
DWORD dwDSLockedBufferSize, dwDSLockedBufferSize2;
void *pDSLockedBuffer = NULL, *pDSLockedBuffer2 = NULL;
#ifdef DEBUG_LOG
DWORD dwPos;
m_apDSBuffer[0]->GetCurrentPosition( &dwPos, NULL );
char szBuf[1024];
sprintf( szBuf, "[HandleNotification:%s] NextWriteOffset : %u, Pos : %u, LastPlayPos : %u, NotifySize : %u\n",
m_pSoundFile->GetFilename(), m_dwNextWriteOffset, dwPos, m_dwLastPlayPos, m_dwNotifySize );
log_file << szBuf;
#endif
HRESULT hr = m_apDSBuffer[0]->Lock( m_dwNextWriteOffset, m_dwNotifySize,
&pDSLockedBuffer, &dwDSLockedBufferSize,
&pDSLockedBuffer2, &dwDSLockedBufferSize2, 0L );
if( FAILED( hr ) )
SNDError( "Stream SoundBuffer Lock Failed!! ErrorCode : 0x%x", hr );
if( pDSLockedBuffer2 != NULL )
SNDError( "Stream SoundBuffer Lock Failed2!! ErrorCode : 0x%x", E_UNEXPECTED );
DWORD dwBytesWrittenToBuffer = 0;
DWORD dwBitsPerSample = m_pSoundFile->GetBitsPerSample();
if( m_bFillNextNotificationWithSilence )
{
FillMemory( pDSLockedBuffer, dwDSLockedBufferSize,
(BYTE)( dwBitsPerSample == 8 ? 128 : 0 ) );
dwBytesWrittenToBuffer = dwDSLockedBufferSize;
}
else
{
dwBytesWrittenToBuffer = m_pSoundFile->Read( (BYTE*) pDSLockedBuffer, dwDSLockedBufferSize );
}
if( dwBytesWrittenToBuffer < dwDSLockedBufferSize )
{
if( m_bLoopPlay )
{
//<2F>ݺ<EFBFBD><DDBA><EFBFBD> <20>ؾ<EFBFBD> <20>ϱ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>۸<EFBFBD> <20><><EFBFBD>̺<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD> <20><><EFBFBD><EFBFBD> ä<><C3A4><EFBFBD><EFBFBD>.
DWORD dwReadSoFar = dwBytesWrittenToBuffer;
while( dwReadSoFar < dwDSLockedBufferSize )
{
//<2F>ſ<EFBFBD> ª<><C2AA> ȭ<><C8AD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>۰<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ݺ<EFBFBD><DDBA>ϸ<EFBFBD> <20>о<EFBFBD><D0BE><EFBFBD><EFBFBD>δ<EFBFBD>.
m_pSoundFile->Reset();
dwBytesWrittenToBuffer = m_pSoundFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar,
dwDSLockedBufferSize - dwReadSoFar );
dwReadSoFar += dwBytesWrittenToBuffer;
}
}
else
{
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>(silence)<29><><EFBFBD><EFBFBD> ä<><C3A4><EFBFBD><EFBFBD>.
FillMemory( (BYTE*) pDSLockedBuffer + dwBytesWrittenToBuffer,
dwDSLockedBufferSize - dwBytesWrittenToBuffer,
(BYTE)( dwBitsPerSample == 8 ? 128 : 0 ) );
//<2F><> <20><><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ó<><C3B3>
m_bFillNextNotificationWithSilence = true;
}
}
m_apDSBuffer[0]->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 );
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>󸶳<EFBFBD> <20>÷<EFBFBD><C3B7><EFBFBD> <20>Ǿ<EFBFBD><C7BE><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>, <20>÷<EFBFBD><C3B7><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ȭ<><C8AD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>
//m_bLoopPlay <20>÷<EFBFBD><C3B7>׿<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>۸<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ä<><C3A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ȭ<><C8AD><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٽ<EFBFBD> <20>о
//<2F><><EFBFBD><20>ϴ<EFBFBD><CFB4><EFBFBD> <20>Ѵ<EFBFBD>.
DWORD dwCurrentPlayPos;
DWORD dwPlayDelta;
if( FAILED( hr = m_apDSBuffer[0]->GetCurrentPosition( &dwCurrentPlayPos, NULL ) ) )
SNDError( "GetCurrentPosition(at CStreamBuffer::HandleNotification) Failed!! ErrorCode : 0x%x", 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( m_bFillNextNotificationWithSilence )
{
//<2F><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD> stop<6F>Ѵ<EFBFBD>.
if( m_dwPlayProgress >= m_pSoundFile->GetSize() )
{
m_apDSBuffer[0]->Stop();
ResetAll();
}
}
m_dwNextWriteOffset += dwDSLockedBufferSize;
m_dwNextWriteOffset %= m_dwDSBufferSize; //<2F><><EFBFBD>۰<EFBFBD> <20><>ȯ<EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD>..
if( m_dwDSBufferSize - m_dwNotifySize < m_dwNextWriteOffset )
SNDError( "WriteOffset<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߸<EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ǿ<EFBFBD><C7BE><EFBFBD><EFBFBD>ϴ<EFBFBD>.(CStreamBuffer::HandleNotification)" );
}
/////////////////////////////////////////////////////////////////////////////////////////