Files
Leviathan/Library/Internal/source/sound/XDSound.cpp
T
2026-06-01 12:46:52 +02:00

301 lines
6.4 KiB
C++

#include "../../include/sound/XDSound.h"
const int MAX_VOLUME = 5000;
static bool setVolume( IDirectSoundBuffer8 *pBuffer, int nVolume )
{
if( !pBuffer ) return false;
long lVolume;
if( nVolume ) lVolume = (long)( 0 - MAX_VOLUME*((100 - nVolume)/100.0f) );
else lVolume = -10000;
return !FAILED( pBuffer->SetVolume( lVolume ) );
}
static int getVolume( IDirectSoundBuffer8 *pBuffer )
{
if( !pBuffer ) return 0;
long nVolume;
pBuffer->GetVolume( &nVolume );
nVolume = (int)( 100 + (nVolume / (float)MAX_VOLUME) * 100.0f );
if( nVolume < 0 ) nVolume = 0;
return nVolume;
}
XDSound::XDSound()
{
m_fx = m_fy = m_fz = 0;
m_bUse3D = false;
m_bGlobal = false;
m_pPrimaryBuffer = NULL;
m_pDS = NULL;
m_p3DListener = NULL;
}
XDSound::~XDSound()
{
DeInit();
}
bool XDSound::Init( HWND hWnd, bool bUse3D, bool bGlobal, bool bIsStereo, unsigned freq, unsigned bit )
{
WAVEFORMATEX waveFormat;
DSBUFFERDESC bufferInfo;
m_bGlobal = bGlobal;
m_bUse3D = bUse3D;
if( FAILED( DirectSoundCreate8( NULL, &m_pDS, NULL ) ) )
{
return false;
}
if( FAILED( m_pDS->SetCooperativeLevel( hWnd, DSSCL_PRIORITY ) ) ) return false;
memset( &waveFormat, 0, sizeof(waveFormat) );
waveFormat.wFormatTag = WAVE_FORMAT_PCM;
waveFormat.nChannels = (unsigned short)(1 + bIsStereo );
waveFormat.nSamplesPerSec = freq;
waveFormat.wBitsPerSample = (unsigned short)bit;
waveFormat.nBlockAlign = (unsigned short)((waveFormat.wBitsPerSample / 8) * waveFormat.nChannels);
waveFormat.nAvgBytesPerSec = (unsigned short)waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
memset( &bufferInfo, 0, sizeof(bufferInfo) );
bufferInfo.dwSize = sizeof(bufferInfo);
bufferInfo.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_PRIMARYBUFFER;
if( m_bUse3D ) bufferInfo.dwFlags |= DSBCAPS_CTRL3D;
bufferInfo.dwBufferBytes = 0;
bufferInfo.lpwfxFormat = NULL;
if( FAILED( m_pDS->CreateSoundBuffer( &bufferInfo, (LPDIRECTSOUNDBUFFER*)&m_pPrimaryBuffer, NULL ) ) )
{
m_pDS->Release();
m_pDS = NULL;
return false;
}
if( m_bUse3D )
{
m_pPrimaryBuffer->QueryInterface( IID_IDirectSound3DListener8, (LPVOID*)&m_p3DListener );
if( !m_p3DListener )
{
m_pDS->Release();
m_pDS = NULL;
m_pPrimaryBuffer->Release();
m_pPrimaryBuffer = NULL;
return false;
}
D3DVECTOR v;
m_p3DListener->GetPosition( &v );
m_fx = v.x;
m_fy = v.y;
m_fz = v.z;
}
return true;
};
bool XDSound::DeInit()
{
if( m_pDS ) m_pDS->Release();
m_pDS = NULL;
return true;
}
bool XDSound::SetVolume( int nVolume )
{
return setVolume( m_pPrimaryBuffer, nVolume );
}
int XDSound::GetVolume()
{
return getVolume( m_pPrimaryBuffer );
}
bool XDSound::SetPosition( float x, float y, float z )
{
if( !m_p3DListener ) return false;
m_fx = x;
m_fy = y;
m_fz = z;
return !FAILED( m_p3DListener->SetPosition( x, y, z, DS3D_IMMEDIATE ) );
}
bool XDSound::GetPosition( float * x, float * y, float * z )
{
if( !m_p3DListener ) return false;
*x = m_fx;
*y = m_fy;
*z = m_fz;
return true;
}
bool XDSound::SetOrientation( float fx, float fy, float fz, float tx, float ty, float tz )
{
return !FAILED( m_p3DListener->SetOrientation( fx, fy, fz, tx, ty, tz, DS3D_IMMEDIATE ) );
}
bool XDSound::SetRollOffFactor( float x )
{
if( !m_p3DListener ) return false;
return !FAILED( m_p3DListener->SetRolloffFactor( x, DS3D_IMMEDIATE ) );
}
bool XDSound::GetRollOffFactor( float * x )
{
if( !m_p3DListener ) return false;
return !FAILED( m_p3DListener->GetRolloffFactor( x ) );
}
XDSoundBuffer * XDSound::CreateBuffer( XWave * pWave, bool bUse3D )
{
if( !m_pDS ) return NULL;
IDirectSoundBuffer8 * pBuffer = NULL;
DSBUFFERDESC desc;
char *pt1 = NULL;
DWORD size1;
int size_byte = 0;
DWORD flag = DSBLOCK_ENTIREBUFFER;
if( !pWave->ReadWaveInfo() ) return NULL;
size_byte = pWave->GetSize() * pWave->GetWaveFormat().nBlockAlign;
memset( &desc, 0, sizeof(desc) );
desc.dwSize = sizeof(desc);
if( m_bGlobal ) desc.dwFlags |= DSBCAPS_GLOBALFOCUS;
if( bUse3D ) desc.dwFlags |= DSBCAPS_CTRL3D;
desc.dwBufferBytes = pWave->GetSize();
desc.lpwfxFormat = (LPWAVEFORMATEX)&pWave->GetWaveFormat();
if( FAILED( m_pDS->CreateSoundBuffer( &desc, (LPDIRECTSOUNDBUFFER*)&pBuffer, NULL ) ) ) return NULL;
// DSERR_BADFORMAT
if( pBuffer->Lock( 0, size_byte, (void**)&pt1, (DWORD*)&size1, NULL, NULL, flag ) == DSERR_BUFFERLOST )
{
pBuffer->Restore();
if( pBuffer->Lock( 0, size_byte, (void**)&pt1, (DWORD*)&size1, NULL, NULL, flag ) == DSERR_BUFFERLOST )
{
pBuffer->Release();
return false;
}
}
if( !pWave->ReadWaveData( pt1, size1 ) )
{
pBuffer->Release();
return false;
}
XDSoundBuffer * pNewBuffer = new XDSoundBuffer( pBuffer, pWave->IsStereo(), m_pDS );
if( bUse3D ) pNewBuffer->Init3D();
return pNewBuffer;
}
XDSoundBuffer * XDSoundBuffer::DuplicateBuffer()
{
IDirectSoundBuffer8 * pNewDSBuffer;
m_pDS->DuplicateSoundBuffer( (LPDIRECTSOUNDBUFFER)m_pBuffer, (LPDIRECTSOUNDBUFFER*) &pNewDSBuffer );
XDSoundBuffer * pNewBuffer = new XDSoundBuffer( pNewDSBuffer, m_bIsStereo, m_pDS );
if( Is3DBuffer() )
{
float fMin, fMax;
m_p3D->GetMinDistance( &fMin );
m_p3D->GetMaxDistance( &fMax );
pNewBuffer->Init3D();
pNewBuffer->SetMinMax( fMin, fMax );
}
return pNewBuffer;
}
XDSoundBuffer::XDSoundBuffer( IDirectSoundBuffer8* pBuffer, bool bStereo, IDirectSound8* pDS )
{
m_pBuffer = pBuffer;
m_p3D = NULL;
m_pDS = pDS;
m_bIsStereo = bStereo;
}
XDSoundBuffer::~XDSoundBuffer()
{
m_pBuffer->Release();
}
bool XDSoundBuffer::Play( bool bIsLoop )
{
if( FAILED( m_pBuffer->SetCurrentPosition( 0 ) ) ) return false;
return !FAILED( m_pBuffer->Play( 0, 0, ( bIsLoop ? DSBPLAY_LOOPING : 0 ) ) );
}
bool XDSoundBuffer::Stop()
{
return !FAILED( m_pBuffer->Stop() );
}
bool XDSoundBuffer::Init3D()
{
if( FAILED( m_pBuffer->QueryInterface( IID_IDirectSound3DBuffer8, (LPVOID*)&m_p3D ) ) ) return false;
return true;
}
bool XDSoundBuffer::SetMinMax( float fMin, float fMax )
{
if( !m_p3D ) return false;
m_p3D->SetMinDistance( fMin, DS3D_IMMEDIATE );
m_p3D->SetMaxDistance( fMax, DS3D_IMMEDIATE );
return true;
}
bool XDSoundBuffer::Play( float x, float y, float z, bool bIsLoop )
{
if( m_p3D ) m_p3D->SetPosition( x, y, z, DS3D_IMMEDIATE );
return Play( bIsLoop );
}
bool XDSoundBuffer::IsPlaying()
{
DWORD dwStatus;
m_pBuffer->GetStatus( &dwStatus );
return ( dwStatus & DSBSTATUS_PLAYING );
}
bool XDSoundBuffer::SetVolume( int nVolume )
{
return setVolume( m_pBuffer, nVolume );
}
int XDSoundBuffer::GetVolume()
{
return getVolume( m_pBuffer );
}