894 lines
24 KiB
C++
894 lines
24 KiB
C++
// DX3SoundManager.cpp : Defines the entry point for the DLL application.
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
|
#define DIRECTSOUND_VERSION 0x0300
|
|
|
|
#include <mmreg.h>
|
|
#include <dsound.h>
|
|
|
|
|
|
#include "DxSoundManager.h"
|
|
#include "Dx3SoundManager.h"
|
|
|
|
extern long g_InitialVolume;
|
|
extern BOOL g_InitialVolumeChanged;
|
|
|
|
|
|
CKERROR CreateDx3SoundManager(CKContext *ctx){
|
|
new DX3SoundManager(ctx);
|
|
return CK_OK;
|
|
}
|
|
|
|
CK_SOUNDMANAGER_CAPS
|
|
DX3SoundManager::GetCaps()
|
|
{
|
|
DWORD d = CK_WAVESOUND_SETTINGS_ALL|CK_WAVESOUND_3DSETTINGS_ALL|CK_LISTENERSETTINGS_ALL|CK_WAVESOUND_3DSETTINGS_DISTANCEFACTOR|CK_WAVESOUND_3DSETTINGS_DOPPLERFACTOR;
|
|
d &= ~(CK_WAVESOUND_SETTINGS_EQUALIZATION|CK_WAVESOUND_SETTINGS_PRIORITY|CK_LISTENERSETTINGS_EQ|CK_LISTENERSETTINGS_PRIORITY|CK_SOUNDMANAGER_ONFLYTYPE);
|
|
return (CK_SOUNDMANAGER_CAPS)d;
|
|
}
|
|
|
|
// Creation
|
|
void*
|
|
DX3SoundManager::CreateSource(CK_WAVESOUND_TYPE type,CKWaveFormat* wf,CKDWORD bytes,BOOL streamed)
|
|
{
|
|
if (m_Context->GetStartOptions() & CK_CONFIG_DISABLEDSOUND) {
|
|
if (m_Context->IsInInterfaceMode()) m_Context->OutputToConsole("Cannot create sound : Sound Disabled");
|
|
return NULL;
|
|
}
|
|
if (!m_Root) {
|
|
if (m_Context->IsInInterfaceMode()) m_Context->OutputToConsole("Cannot create sound : Sound Manager not initialized");
|
|
return NULL;
|
|
}
|
|
|
|
// Set up the direct sound buffer, only requesting the flags we need,
|
|
// since each require overhead.
|
|
DSBUFFERDESC dsbd;
|
|
ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
|
|
dsbd.dwSize = sizeof(DSBUFFERDESC);
|
|
dsbd.dwFlags = DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLVOLUME|
|
|
DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_GLOBALFOCUS|DSBCAPS_GETCURRENTPOSITION2;
|
|
dsbd.dwBufferBytes = ((bytes+(wf->wBitsPerSample/8)-1)/(wf->wBitsPerSample/8))*(wf->wBitsPerSample/8);
|
|
dsbd.lpwfxFormat = (WAVEFORMATEX*)wf;
|
|
|
|
// We test if we want a 2D or 3D Sound
|
|
if (type == CK_WAVESOUND_BACKGROUND)
|
|
dsbd.dwFlags |= DSBCAPS_CTRLPAN;
|
|
else
|
|
dsbd.dwFlags |= DSBCAPS_CTRL3D;
|
|
|
|
LPDIRECTSOUNDBUFFER lpdsb = NULL;
|
|
|
|
// Create the static DirectSound buffer
|
|
HRESULT err = m_Root->CreateSoundBuffer( &dsbd, &lpdsb, NULL );
|
|
if (err)
|
|
return NULL;
|
|
|
|
err = lpdsb->SetFrequency(wf->nSamplesPerSec);
|
|
|
|
return lpdsb;
|
|
}
|
|
|
|
void*
|
|
DX3SoundManager::DuplicateSource(void* source)
|
|
{
|
|
if (!m_Root) return NULL;
|
|
|
|
LPDIRECTSOUNDBUFFER newsource = NULL;
|
|
HRESULT err = m_Root->DuplicateSoundBuffer((LPDIRECTSOUNDBUFFER)source,&newsource);
|
|
if (err){ // Failed, create a new Buffer
|
|
LPDIRECTSOUNDBUFFER src = (LPDIRECTSOUNDBUFFER)source;
|
|
|
|
DWORD sz;
|
|
WAVEFORMATEX wfe;
|
|
src->GetFormat(&wfe,sizeof(WAVEFORMATEX),&sz);
|
|
|
|
DSBCAPS caps; caps.dwSize=sizeof(DSBCAPS);
|
|
src->GetCaps(&caps);
|
|
|
|
DSBUFFERDESC dsbd;
|
|
ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
|
|
dsbd.dwSize = sizeof(DSBUFFERDESC);
|
|
|
|
dsbd.dwFlags = m_Mixing_Location | caps.dwFlags & ~(DSBCAPS_LOCHARDWARE | DSBCAPS_LOCSOFTWARE | DSBCAPS_LOCDEFER | DSBCAPS_GETCURRENTPOSITION2);
|
|
dsbd.dwBufferBytes = caps.dwBufferBytes;
|
|
dsbd.lpwfxFormat = &wfe;
|
|
|
|
HRESULT err = m_Root->CreateSoundBuffer( &dsbd, &newsource, NULL );
|
|
if (err)
|
|
return NULL;
|
|
|
|
LONG val;
|
|
src->GetVolume(&val);newsource->SetVolume(val);
|
|
src->GetPan(&val);newsource->SetPan(val);
|
|
DWORD freq;
|
|
src->GetFrequency(&freq);newsource->SetFrequency(freq);
|
|
|
|
// Copy 3d param
|
|
LPDIRECTSOUND3DBUFFER lp3dd=NULL,lp3ds=NULL;
|
|
err = src->QueryInterface(IID_IDirectSound3DBuffer,(LPVOID*) &lp3ds);
|
|
err = newsource->QueryInterface(IID_IDirectSound3DBuffer,(LPVOID*) &lp3ds);
|
|
|
|
if(lp3dd && lp3ds){
|
|
DS3DBUFFER buf;
|
|
lp3ds->GetAllParameters(&buf);
|
|
lp3dd->SetAllParameters(&buf,DS3D_IMMEDIATE ) ;
|
|
}
|
|
|
|
if(lp3dd)
|
|
lp3dd->Release();
|
|
|
|
if(lp3ds)
|
|
lp3ds->Release();
|
|
|
|
// Copy Content
|
|
BYTE *sbuf1,*sbuf2;
|
|
DWORD ssz1,ssz2;
|
|
if(err = src->Lock(0,0,(LPVOID*)&sbuf1,&ssz1,(LPVOID*)&sbuf2,&ssz2,DSBLOCK_ENTIREBUFFER)){
|
|
|
|
BYTE *dbuf1,*dbuf2;
|
|
DWORD dsz1,dsz2;
|
|
if(err = newsource->Lock(0,0,(LPVOID*)&dbuf1,&dsz1,(LPVOID*)&dbuf2,&dsz2,DSBLOCK_ENTIREBUFFER)){
|
|
if(ssz1)
|
|
memcpy(sbuf1,dbuf1,ssz1);
|
|
if(ssz2)
|
|
memcpy(sbuf2,dbuf2,ssz2);
|
|
newsource->Unlock(dbuf1,dsz1,dbuf2,dsz2);
|
|
}else{
|
|
newsource->Release();
|
|
newsource = NULL;
|
|
}
|
|
|
|
newsource->Unlock(sbuf1,ssz1,sbuf2,ssz2);
|
|
}else{
|
|
newsource->Release();
|
|
newsource = NULL;
|
|
}
|
|
}
|
|
return newsource;
|
|
}
|
|
|
|
void
|
|
DX3SoundManager::ReleaseSource(void* source)
|
|
{
|
|
if (!source) return;
|
|
LPDIRECTSOUNDBUFFER m_Source = (LPDIRECTSOUNDBUFFER)source;
|
|
|
|
m_Source->Stop();
|
|
m_Source->Release();
|
|
}
|
|
|
|
void
|
|
DX3SoundManager::InternalPause(void* source)
|
|
{
|
|
if(!source) return;
|
|
LPDIRECTSOUNDBUFFER m_Source = (LPDIRECTSOUNDBUFFER)source;
|
|
HRESULT res = m_Source->Stop();
|
|
}
|
|
|
|
void
|
|
DX3SoundManager::InternalPlay(void* source,CKBOOL loop)
|
|
{
|
|
if(!source)return;
|
|
LPDIRECTSOUNDBUFFER m_Source = (LPDIRECTSOUNDBUFFER)source;
|
|
HRESULT res = m_Source->Play(0,0,loop?DSBPLAY_LOOPING:0);
|
|
}
|
|
|
|
|
|
// Control
|
|
void
|
|
DX3SoundManager::Play(CKWaveSound* ws,void* source,CKBOOL loop)
|
|
{
|
|
if (!source) return;
|
|
LPDIRECTSOUNDBUFFER m_Source;
|
|
|
|
if (ws) { // it's a normal sound
|
|
m_Source = (LPDIRECTSOUNDBUFFER)source;
|
|
// We add the sound to the playing list
|
|
m_SoundsPlaying.AddIfNotHere(ws->GetID());
|
|
} else { // it's a minion playing
|
|
SoundMinion* minion = (SoundMinion*)source;
|
|
m_Source = (LPDIRECTSOUNDBUFFER)minion->m_Source;
|
|
}
|
|
|
|
InternalPlay(m_Source,loop);
|
|
}
|
|
|
|
void
|
|
DX3SoundManager::Pause(CKWaveSound* ws,void* source)
|
|
{
|
|
if (!source) return;
|
|
LPDIRECTSOUNDBUFFER m_Source = (LPDIRECTSOUNDBUFFER)source;
|
|
|
|
// We remove the sound from the playing list
|
|
// m_SoundsPlaying.erase(ws->GetID());
|
|
InternalPause(m_Source);
|
|
}
|
|
|
|
void
|
|
DX3SoundManager::SetPlayPosition(void* source,int pos)
|
|
{
|
|
if (!source) return;
|
|
LPDIRECTSOUNDBUFFER m_Source = (LPDIRECTSOUNDBUFFER)source;
|
|
|
|
m_Source->SetCurrentPosition(pos);
|
|
}
|
|
|
|
int
|
|
DX3SoundManager::GetPlayPosition(void* source)
|
|
{
|
|
if (!source) return 0;
|
|
LPDIRECTSOUNDBUFFER m_Source = (LPDIRECTSOUNDBUFFER)source;
|
|
|
|
DWORD pos = 0,wpos = 0;
|
|
m_Source->GetCurrentPosition(&pos,&wpos);
|
|
return pos;
|
|
}
|
|
|
|
CKBOOL
|
|
DX3SoundManager::IsPlaying(void* source)
|
|
{
|
|
if (!source) return FALSE;
|
|
LPDIRECTSOUNDBUFFER m_Source = (LPDIRECTSOUNDBUFFER)source;
|
|
|
|
DWORD status = 0;
|
|
m_Source->GetStatus(&status);
|
|
|
|
return status & DSBSTATUS_PLAYING;// & A3DSTATUS_PLAYING;
|
|
}
|
|
|
|
// PCM Buffer Informations
|
|
CKERROR
|
|
DX3SoundManager::SetWaveFormat(void* source,CKWaveFormat& wf)
|
|
{
|
|
if (!source) return FALSE;
|
|
LPDIRECTSOUNDBUFFER m_Source = (LPDIRECTSOUNDBUFFER)source;
|
|
|
|
return m_Source->SetFormat((WAVEFORMATEX*)&wf);
|
|
}
|
|
|
|
CKERROR
|
|
DX3SoundManager::GetWaveFormat(void* source,CKWaveFormat& wf)
|
|
{
|
|
if (!source) return FALSE;
|
|
LPDIRECTSOUNDBUFFER m_Source = (LPDIRECTSOUNDBUFFER)source;
|
|
|
|
return m_Source->GetFormat((WAVEFORMATEX*)&wf,sizeof(CKWaveFormat),NULL);
|
|
}
|
|
|
|
int
|
|
DX3SoundManager::GetWaveSize(void* source)
|
|
{
|
|
if (!source) return FALSE;
|
|
LPDIRECTSOUNDBUFFER m_Source = (LPDIRECTSOUNDBUFFER)source;
|
|
|
|
DSBCAPS caps;
|
|
ZeroMemory(&caps,sizeof(DSBCAPS));
|
|
caps.dwSize = sizeof(DSBCAPS);
|
|
m_Source->GetCaps(&caps);
|
|
return caps.dwBufferBytes;
|
|
}
|
|
|
|
// Buffer access
|
|
CKERROR
|
|
DX3SoundManager::Lock(void* source,CKDWORD dwWriteCursor,CKDWORD dwNumBytes,void **pvAudioPtr1,CKDWORD *dwAudioBytes1,void **pvAudioPtr2,CKDWORD *dwAudioBytes2,CK_WAVESOUND_LOCKMODE dwFlags)
|
|
{
|
|
if (!source) return 1;
|
|
LPDIRECTSOUNDBUFFER m_Source = (LPDIRECTSOUNDBUFFER)source;
|
|
|
|
return m_Source->Lock(dwWriteCursor,dwNumBytes,pvAudioPtr1,(DWORD*)dwAudioBytes1,pvAudioPtr2,(DWORD*)dwAudioBytes2,dwFlags);
|
|
}
|
|
|
|
CKERROR
|
|
DX3SoundManager::Unlock(void* source,void *pvAudioPtr1,CKDWORD dwNumBytes1,void *pvAudioPtr2,CKDWORD dwAudioBytes2)
|
|
{
|
|
if (!source) return 1;
|
|
LPDIRECTSOUNDBUFFER m_Source = (LPDIRECTSOUNDBUFFER)source;
|
|
|
|
return m_Source->Unlock(pvAudioPtr1,dwNumBytes1,pvAudioPtr2,dwAudioBytes2);
|
|
}
|
|
|
|
// 2D/3D Members Functions
|
|
void
|
|
DX3SoundManager::SetType(void* source,CK_WAVESOUND_TYPE type)
|
|
{
|
|
if (!source) return;
|
|
LPDIRECTSOUNDBUFFER m_Source = (LPDIRECTSOUNDBUFFER)source;
|
|
|
|
m_Context->OutputToConsole("Warning: DirectX SoundManager doesn't support on fly type changes");
|
|
}
|
|
|
|
CK_WAVESOUND_TYPE
|
|
DX3SoundManager::GetType(void* source)
|
|
{
|
|
if (!source) return CK_WAVESOUND_TYPE(0);
|
|
LPDIRECTSOUNDBUFFER m_Source = (LPDIRECTSOUNDBUFFER)source;
|
|
|
|
// conversion
|
|
DSBCAPS caps;
|
|
ZeroMemory(&caps,sizeof(DSBCAPS));
|
|
caps.dwSize = sizeof(DSBCAPS);
|
|
m_Source->GetCaps(&caps);
|
|
|
|
if(caps.dwFlags & DSBCAPS_CTRL3D)
|
|
return CK_WAVESOUND_POINT;
|
|
|
|
|
|
return CK_WAVESOUND_BACKGROUND;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------
|
|
// 2D/3D Settings
|
|
void
|
|
DX3SoundManager::UpdateSettings(void* source,CK_SOUNDMANAGER_CAPS settingsoptions,CKWaveSoundSettings& settings,CKBOOL set)
|
|
{
|
|
if (!source) return;
|
|
LPDIRECTSOUNDBUFFER m_Source = (LPDIRECTSOUNDBUFFER)source;
|
|
|
|
if (set) {
|
|
if (settingsoptions & CK_WAVESOUND_SETTINGS_GAIN)
|
|
m_Source->SetVolume(FloatToDb(settings.m_Gain));
|
|
|
|
if (settingsoptions & CK_WAVESOUND_SETTINGS_PITCH) {
|
|
WAVEFORMATEX wf;
|
|
m_Source->GetFormat(&wf,sizeof(WAVEFORMATEX),0);
|
|
m_Source->SetFrequency((LONG)(wf.nSamplesPerSec * settings.m_Pitch));
|
|
}
|
|
if (settingsoptions & CK_WAVESOUND_SETTINGS_PAN)
|
|
m_Source->SetPan(FloatPanningToDb(settings.m_Pan));
|
|
} else {
|
|
if (settingsoptions & CK_WAVESOUND_SETTINGS_GAIN) {
|
|
long d;m_Source->GetVolume(&d);
|
|
settings.m_Gain = DbToFloat(d);
|
|
}
|
|
if (settingsoptions & CK_WAVESOUND_SETTINGS_PITCH) {
|
|
WAVEFORMATEX wf;
|
|
m_Source->GetFormat(&wf,sizeof(WAVEFORMATEX),0);
|
|
DWORD d;m_Source->GetFrequency(&d);
|
|
settings.m_Pitch = (float)d / wf.nSamplesPerSec;
|
|
}
|
|
if (settingsoptions & CK_WAVESOUND_SETTINGS_PAN) {
|
|
long d;m_Source->GetPan(&d);
|
|
settings.m_Pan = DbPanningToFloat(d);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------
|
|
// 3D Settings
|
|
void
|
|
DX3SoundManager::Update3DSettings(void* source,CK_SOUNDMANAGER_CAPS settingsoptions,CKWaveSound3DSettings& settings,CKBOOL set)
|
|
{
|
|
if (!source) return;
|
|
LPDIRECTSOUNDBUFFER lpdsb = (LPDIRECTSOUNDBUFFER)source;
|
|
|
|
LPDIRECTSOUND3DBUFFER m_Source = NULL;
|
|
HRESULT err = lpdsb->QueryInterface(IID_IDirectSound3DBuffer,(VOID**)&m_Source);
|
|
if (err) return;
|
|
|
|
if (set) {
|
|
if (settingsoptions & CK_WAVESOUND_3DSETTINGS_CONE) {
|
|
m_Source->SetConeAngles((LONG)settings.m_InAngle,(LONG)settings.m_OutAngle,DS3D_IMMEDIATE);
|
|
m_Source->SetConeOutsideVolume(FloatToDb(settings.m_OutsideGain),DS3D_IMMEDIATE);
|
|
}
|
|
if (settingsoptions & CK_WAVESOUND_3DSETTINGS_MINMAXDISTANCE) {
|
|
m_Source->SetMinDistance(settings.m_MinDistance,DS3D_IMMEDIATE);
|
|
m_Source->SetMaxDistance(settings.m_MaxDistance,DS3D_IMMEDIATE);
|
|
}
|
|
if (settingsoptions & CK_WAVESOUND_3DSETTINGS_POSITION)
|
|
m_Source->SetPosition(settings.m_Position.x,settings.m_Position.y,settings.m_Position.z,DS3D_IMMEDIATE);
|
|
if (settingsoptions & CK_WAVESOUND_3DSETTINGS_VELOCITY)
|
|
m_Source->SetVelocity(settings.m_Velocity.x,settings.m_Velocity.y,settings.m_Velocity.z,DS3D_IMMEDIATE);
|
|
if (settingsoptions & CK_WAVESOUND_3DSETTINGS_ORIENTATION)
|
|
m_Source->SetConeOrientation(settings.m_OrientationDir.x,settings.m_OrientationDir.y,settings.m_OrientationDir.z,DS3D_IMMEDIATE);
|
|
|
|
|
|
if (settingsoptions & CK_WAVESOUND_3DSETTINGS_HEADRELATIVE){
|
|
if(settings.m_HeadRelative)
|
|
m_Source->SetMode(DS3DMODE_HEADRELATIVE,DS3D_IMMEDIATE);
|
|
else
|
|
m_Source->SetMode(DS3DMODE_NORMAL,DS3D_IMMEDIATE);
|
|
|
|
}
|
|
|
|
} else {
|
|
if (settingsoptions & CK_WAVESOUND_3DSETTINGS_CONE) {
|
|
DWORD ia,oa;
|
|
m_Source->GetConeAngles(&ia,&oa);
|
|
settings.m_InAngle = (float)ia;
|
|
settings.m_OutAngle = (float)oa;
|
|
|
|
long og;
|
|
m_Source->GetConeOutsideVolume(&og);
|
|
settings.m_OutsideGain = DbToFloat(og);
|
|
}
|
|
if (settingsoptions & CK_WAVESOUND_3DSETTINGS_MINMAXDISTANCE) {
|
|
m_Source->GetMinDistance(&settings.m_MinDistance);
|
|
m_Source->GetMaxDistance(&settings.m_MaxDistance);
|
|
}
|
|
if (settingsoptions & CK_WAVESOUND_3DSETTINGS_HEADRELATIVE) {
|
|
DWORD d;m_Source->GetMode(&d);
|
|
settings.m_HeadRelative = (d==DS3DMODE_HEADRELATIVE )?1:0;
|
|
}
|
|
if (settingsoptions & CK_WAVESOUND_3DSETTINGS_POSITION) {
|
|
D3DVECTOR v;m_Source->GetPosition(&v);
|
|
settings.m_Position.Set(v.x,v.y,v.z);
|
|
}
|
|
if (settingsoptions & CK_WAVESOUND_3DSETTINGS_VELOCITY) {
|
|
D3DVECTOR v;m_Source->GetVelocity(&v);
|
|
settings.m_Velocity.Set(v.x,v.y,v.z);
|
|
}
|
|
if (settingsoptions & CK_WAVESOUND_3DSETTINGS_ORIENTATION) {
|
|
D3DVECTOR v;m_Source->GetConeOrientation(&v);
|
|
settings.m_OrientationDir.Set(v.x,v.y,v.z);
|
|
}
|
|
}
|
|
|
|
m_Source->Release();
|
|
}
|
|
|
|
//----------------------------------------------------------
|
|
// 3D Settings
|
|
void
|
|
DX3SoundManager::UpdateListenerSettings(CK_SOUNDMANAGER_CAPS settingsoptions,CKListenerSettings& settings,CKBOOL set)
|
|
{
|
|
if(!m_Listener)
|
|
return;
|
|
|
|
if (set) {
|
|
if (settingsoptions & CK_LISTENERSETTINGS_DISTANCE)
|
|
m_Listener->SetDistanceFactor(settings.m_DistanceFactor,DS3D_IMMEDIATE);
|
|
if (settingsoptions & CK_LISTENERSETTINGS_DOPPLER)
|
|
m_Listener->SetDopplerFactor(settings.m_DopplerFactor,DS3D_IMMEDIATE);
|
|
if (settingsoptions & CK_LISTENERSETTINGS_ROLLOFF)
|
|
m_Listener->SetRolloffFactor(settings.m_RollOff,DS3D_IMMEDIATE);
|
|
if (settingsoptions & CK_LISTENERSETTINGS_GAIN){
|
|
m_Primary->SetVolume(FloatToDb(settings.m_GlobalGain));
|
|
g_InitialVolumeChanged = TRUE;
|
|
}
|
|
} else {
|
|
if (settingsoptions & CK_LISTENERSETTINGS_DISTANCE)
|
|
m_Listener->GetDistanceFactor(&settings.m_DistanceFactor);
|
|
if (settingsoptions & CK_LISTENERSETTINGS_DOPPLER)
|
|
m_Listener->GetDopplerFactor(&settings.m_DopplerFactor);
|
|
if (settingsoptions & CK_LISTENERSETTINGS_ROLLOFF)
|
|
m_Listener->GetRolloffFactor(&settings.m_RollOff);
|
|
if (settingsoptions & CK_LISTENERSETTINGS_GAIN) {
|
|
long d;m_Primary->GetVolume(&d);
|
|
settings.m_GlobalGain = DbToFloat(d);
|
|
}
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// End Of New Functions
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//{secret}
|
|
void Dx3PositionSource(LPDIRECTSOUNDBUFFER psource,CK3dEntity* ent,VxVector& position,VxVector& direction,VxVector& oldpos)
|
|
{
|
|
LPDIRECTSOUND3DBUFFER source = NULL;
|
|
HRESULT err = psource->QueryInterface(IID_IDirectSound3DBuffer,(VOID**)&source);
|
|
if (err) return;
|
|
|
|
// Calulate position
|
|
VxVector pos(position);
|
|
if(ent) ent->Transform(&pos,&position);
|
|
|
|
// Calculate velocity
|
|
VxVector vel = pos - oldpos;
|
|
|
|
// Calculate orientation
|
|
VxVector dir(direction);
|
|
if(ent) ent->TransformVector(&dir,&direction);
|
|
|
|
// API Call
|
|
// We set the aureal source
|
|
source->SetPosition(pos.x,pos.y,pos.z,DS3D_IMMEDIATE);
|
|
source->SetVelocity(vel.x,vel.y,vel.z,DS3D_IMMEDIATE);
|
|
source->SetConeOrientation(dir.x,dir.y,dir.z,DS3D_IMMEDIATE);
|
|
|
|
// We update the old position
|
|
oldpos = pos;
|
|
|
|
source->Release();
|
|
}
|
|
|
|
|
|
DX3SoundManager::DX3SoundManager(CKContext *Context):DXSoundManager(Context)
|
|
{
|
|
m_Root=0;
|
|
m_Listener=NULL;
|
|
m_Primary = NULL;
|
|
m_Context->RegisterNewManager(this);
|
|
m_BackSound = NULL;
|
|
m_Use_Mute_after_Max_in_LOCSOFTWARE = FALSE;
|
|
|
|
m_Variable_Manager_Str << "enum:" << DSBCAPS_LOCSOFTWARE << "=Software;" << DSBCAPS_LOCDEFER << "=Managed;" << DSBCAPS_LOCHARDWARE << "=Hardware";
|
|
BINDREP(m_Context,"Sounds/Mixing Method",&m_Mixing_Location,DSBCAPS_LOCSOFTWARE,VxVar::NATIVECOMPOSITIONBOUND,m_Variable_Manager_Str.CStr(),"Sound Mixing Method.")
|
|
BINDREP(m_Context,"Sounds/Mute 3D Sounds After Max Distance",&m_Use_Mute_after_Max_in_LOCSOFTWARE,0,0,"bool:","Enable mute after max distance for 3D sound created in software mixing method")
|
|
}
|
|
|
|
|
|
DX3SoundManager::~DX3SoundManager()
|
|
{
|
|
UNBIND(m_Context,"Sounds/Mixing Method");
|
|
UNBIND(m_Context,"Sounds/Mute 3D Sounds After Max Distance");
|
|
}
|
|
|
|
|
|
//{secret}
|
|
CKERROR DX3SoundManager::PostClearAll()
|
|
{
|
|
|
|
CKSoundManager::PostClearAll();
|
|
m_SoundsPlaying.Clear();
|
|
|
|
ReleaseMinions();
|
|
RegisterAttribute();
|
|
return CK_OK;
|
|
}
|
|
|
|
/*************************************************
|
|
Name:
|
|
|
|
Summary: Not Yet Documented
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
Remarks:
|
|
|
|
See also:
|
|
|
|
*************************************************/
|
|
CKERROR
|
|
DX3SoundManager::OnCKInit()
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (m_Context->GetStartOptions() & CK_CONFIG_DISABLEDSOUND) return CK_OK;
|
|
// We put all the available features in here (we disable the splash screen (coz it happens we loading the first sound...))
|
|
CKDWORD dwFeatures = 0;
|
|
|
|
#ifdef CK_LIB
|
|
if (FAILED(CoInitialize(NULL)))
|
|
return -1;
|
|
|
|
hr = CoCreateInstance(CLSID_DirectSound,NULL,CLSCTX_ALL,IID_IDirectSound,(void **)&m_Root);
|
|
if (hr) {
|
|
if (m_Context->GetStartOptions() & CK_CONFIG_DOWARN) MessageBox(NULL,"DirectX Sound Engine Initialization Failed","Warning",MB_OK);
|
|
return hr;
|
|
}
|
|
hr = m_Root->Initialize(NULL);
|
|
#else
|
|
// Create IDirectSound using the primary sound device
|
|
hr = DirectSoundCreate( NULL, &m_Root, NULL );
|
|
#endif
|
|
if (hr) {
|
|
if (m_Context->GetStartOptions() & CK_CONFIG_DOWARN) MessageBox(NULL,"DirectX Sound Engine Initialization Failed","Warning",MB_OK);
|
|
return hr;
|
|
}
|
|
|
|
// Set cooperative level before creating a source
|
|
hr = m_Root->SetCooperativeLevel( (HWND)m_Context->GetMainWindow(), DSSCL_PRIORITY );
|
|
if (hr) {
|
|
if (m_Context->GetStartOptions() & CK_CONFIG_DOWARN) MessageBox(NULL,"DirectX Coop level failed","Warning",MB_OK);
|
|
return hr;
|
|
}
|
|
|
|
// Primary Buffer
|
|
DSBUFFERDESC dsbdesc;
|
|
ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) );
|
|
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
|
|
dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRL3D;
|
|
|
|
hr = m_Root->CreateSoundBuffer( &dsbdesc, &m_Primary, NULL );
|
|
if (hr) {
|
|
if (m_Context->GetStartOptions() & CK_CONFIG_DOWARN) MessageBox(NULL,"DirectX primary buffer failed","Warning",MB_OK);
|
|
return hr;
|
|
}
|
|
|
|
m_Primary->GetVolume(&g_InitialVolume);
|
|
|
|
// Listener
|
|
hr = m_Primary->QueryInterface( IID_IDirectSound3DListener,(VOID**)&m_Listener );
|
|
if (hr) {
|
|
if (m_Context->GetStartOptions() & CK_CONFIG_DOWARN) MessageBox(NULL,"DirectX listener failed","Warning",MB_OK);
|
|
return hr;
|
|
}
|
|
|
|
// Set primary buffer format to 44kHz and 16-bit output.
|
|
WAVEFORMATEX wfx;
|
|
ZeroMemory( &wfx, sizeof(WAVEFORMATEX) );
|
|
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
|
wfx.nChannels = 2;
|
|
wfx.nSamplesPerSec = 44100;
|
|
wfx.wBitsPerSample = 16;
|
|
wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels;
|
|
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
|
|
|
|
hr = m_Primary->SetFormat(&wfx);
|
|
switch(hr) {
|
|
case DSERR_BADFORMAT:return hr;
|
|
case DSERR_INVALIDCALL:return hr;
|
|
case DSERR_INVALIDPARAM:return hr;
|
|
case DSERR_OUTOFMEMORY:return hr;
|
|
case DSERR_PRIOLEVELNEEDED:return hr;
|
|
case DSERR_UNSUPPORTED:return hr;
|
|
}
|
|
if (hr) {
|
|
if (m_Context->GetStartOptions() & CK_CONFIG_DOWARN) MessageBox(NULL,"DirectX set format failed","Warning",MB_OK);
|
|
return hr;
|
|
}
|
|
|
|
RegisterAttribute();
|
|
|
|
// We have to restart all the sounds
|
|
int soundsnumber = m_Context->GetObjectsCountByClassID( CKCID_WAVESOUND);
|
|
if(soundsnumber) {
|
|
// we create the ws array
|
|
CK_ID *id = m_Context->GetObjectsListByClassID(CKCID_WAVESOUND);
|
|
|
|
for(int i=0;i<soundsnumber;++i) {
|
|
CKWaveSound* ws = (CKWaveSound*) m_Context->GetObject(id[i]);
|
|
if(ws) ws->Recreate();
|
|
}
|
|
}
|
|
|
|
if(m_BackSound){
|
|
m_BackSound->Release();
|
|
m_BackSound = NULL;
|
|
}
|
|
CKWaveFormat wf;
|
|
wf.wFormatTag = WAVE_FORMAT_PCM;
|
|
wf.nChannels = 1;
|
|
wf.nSamplesPerSec = 8000;
|
|
wf.wBitsPerSample = 8;
|
|
wf.nBlockAlign = wf.wBitsPerSample*wf.nChannels/8;
|
|
wf.nAvgBytesPerSec = wf.nSamplesPerSec*wf.nBlockAlign;
|
|
|
|
m_BackSound = (LPDIRECTSOUNDBUFFER) CreateSource(CK_WAVESOUND_BACKGROUND,&wf,(wf.nAvgBytesPerSec/wf.nBlockAlign)*wf.nBlockAlign,FALSE);
|
|
if(m_BackSound){
|
|
m_BackSound->SetVolume(DSBVOLUME_MIN );
|
|
InternalPlay(m_BackSound,TRUE);
|
|
}
|
|
|
|
m_Primary->Play(0,0,DSBPLAY_LOOPING);
|
|
|
|
return CK_OK;
|
|
}
|
|
|
|
/*************************************************
|
|
Name:
|
|
|
|
Summary: Not Yet Documented
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
Remarks:
|
|
|
|
See also:
|
|
|
|
*************************************************/
|
|
CKERROR
|
|
DX3SoundManager::OnCKEnd()
|
|
{
|
|
if (m_Context->GetStartOptions() & CK_CONFIG_DISABLEDSOUND) return CK_OK;
|
|
// We have to release all the sounds
|
|
int soundsnumber = m_Context->GetObjectsCountByClassID( CKCID_WAVESOUND);
|
|
if(soundsnumber) {
|
|
// we create the ws array
|
|
CK_ID *id = m_Context->GetObjectsListByClassID(CKCID_WAVESOUND);
|
|
|
|
for(int i=0;i<soundsnumber;++i) {
|
|
CKWaveSound* ws = (CKWaveSound*)m_Context->GetObject(id[i]);
|
|
if(ws) ws->Release();
|
|
}
|
|
}
|
|
|
|
|
|
if(m_BackSound) {
|
|
m_BackSound->Release();
|
|
m_BackSound = NULL;
|
|
}
|
|
|
|
|
|
// We release the listener
|
|
if (m_Listener){
|
|
m_Listener->Release();
|
|
m_Listener = NULL;
|
|
}
|
|
|
|
|
|
if (m_Primary){
|
|
m_Primary->Stop();
|
|
m_Primary->Release();
|
|
m_Primary = NULL;
|
|
}
|
|
|
|
|
|
// We release the main interface
|
|
if (m_Root){
|
|
m_Root->Release();
|
|
m_Root = NULL;
|
|
}
|
|
#ifdef CK_LIB
|
|
CoUninitialize();
|
|
#endif
|
|
return CK_OK;
|
|
}
|
|
|
|
//{secret}
|
|
BOOL
|
|
Dx3IsSourcePlaying(LPDIRECTSOUNDBUFFER source)
|
|
{
|
|
if(!source) return FALSE;
|
|
|
|
DWORD status;
|
|
source->GetStatus(&status);
|
|
|
|
return (status&DSBSTATUS_PLAYING);
|
|
}
|
|
|
|
/*************************************************
|
|
Name:
|
|
|
|
Summary: Not Yet Documented
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
Remarks:
|
|
|
|
See also:
|
|
|
|
*************************************************/
|
|
CKERROR
|
|
DX3SoundManager::PostProcess()
|
|
{
|
|
// Profiling Start
|
|
float deltaT = m_Context->GetTimeManager()->GetLastDeltaTime();
|
|
if(m_Root && m_Listener) {
|
|
// We clear the sound engine
|
|
CKBOOL somethingIsPlayingIn3D = FALSE;
|
|
|
|
// position the sources
|
|
for(CK_ID* it = m_SoundsPlaying.Begin();it!=m_SoundsPlaying.End();) {
|
|
CKWaveSound* ws = (CKWaveSound*)m_Context->GetObject(*it);
|
|
// We check that the sound is currently playing
|
|
if(ws && ws->IsPlaying()) {
|
|
// The sound is a file streamed one
|
|
if(ws->GetFileStreaming() && !(ws->GetState() & CK_WAVESOUND_STREAMFULLYLOADED)){
|
|
// we fill the buffer, if possible
|
|
ws->WriteDataFromReader();
|
|
}
|
|
|
|
// We update the fade, if it were in fade mode
|
|
ws->UpdateFade();
|
|
|
|
// We update the position if it were in 3D
|
|
if(!(ws->GetType()&CK_WAVESOUND_BACKGROUND)) {
|
|
somethingIsPlayingIn3D = TRUE;
|
|
ws->UpdatePosition(deltaT);
|
|
}
|
|
|
|
it++;
|
|
} else {
|
|
it = m_SoundsPlaying.Remove(it);
|
|
}
|
|
}
|
|
|
|
// we check if minions are playing
|
|
for (SoundMinion** itm = m_Minions.Begin();itm != m_Minions.End();++itm) {
|
|
if (IsPlaying((*itm)->m_Source)) {
|
|
somethingIsPlayingIn3D = TRUE;
|
|
// We have to update its position
|
|
if ((*itm)->m_Entity) { // if it is attached to an entity
|
|
CK3dEntity* ent = (CK3dEntity*)m_Context->GetObject((*itm)->m_Entity);
|
|
if(ent)// && (ent->GetMoveableFlags()&VX_MOVEABLE_HASMOVED))
|
|
{
|
|
// We set the aureal source
|
|
Dx3PositionSource((LPDIRECTSOUNDBUFFER)(*itm)->m_Source,ent,(*itm)->m_Position,(*itm)->m_Direction,(*itm)->m_OldPosition);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// If something is playing in 3D, we need to update the listener position and the obstacle source
|
|
// TODO : if a minion is playing, it doesn't work....
|
|
if(somethingIsPlayingIn3D) {
|
|
// temp : put a velocity in objects....
|
|
static VxVector expos;
|
|
|
|
// position the listener
|
|
CK3dEntity *ent=GetListener();
|
|
if (ent)// && ent->GetMoveableFlags()&VX_MOVEABLE_HASMOVED)
|
|
{
|
|
VxVector veloc;
|
|
const VxMatrix& mat = ent->GetWorldMatrix();
|
|
|
|
const VxVector4* pos = &mat[3];
|
|
const VxVector4* dir = &mat[2];
|
|
const VxVector4* up = &mat[1];
|
|
veloc=(*pos-expos);
|
|
expos=*pos;
|
|
m_Listener->SetPosition(pos->x,pos->y,pos->z,DS3D_DEFERRED);
|
|
m_Listener->SetVelocity(veloc.x,veloc.y,veloc.z,DS3D_DEFERRED);
|
|
m_Listener->SetOrientation(dir->x,dir->y,dir->z,up->x,up->y,up->z,DS3D_DEFERRED);
|
|
}
|
|
}
|
|
|
|
// we commit the changes
|
|
m_Listener->CommitDeferredSettings();
|
|
|
|
// Process Minions : finished one are deleted
|
|
ProcessMinions();
|
|
|
|
}
|
|
|
|
// Profiling End
|
|
|
|
return CK_OK;
|
|
}
|
|
|
|
CKERROR
|
|
DX3SoundManager::OnCKReset()
|
|
{
|
|
// we clear the Dx engine
|
|
|
|
if(m_Root && m_Listener)
|
|
{
|
|
// stop the playing sources
|
|
for(CK_ID* itw = m_SoundsPlaying.Begin();itw!=m_SoundsPlaying.End();itw++) {
|
|
CKWaveSound* ws = (CKWaveSound*)m_Context->GetObject(*itw);
|
|
// We check that the sound is not in 2D
|
|
if(ws && ws->m_Source) {
|
|
ws->InternalStop();
|
|
/*
|
|
m_Source->Stop(); // NICO problem with streamed sound doesn't right call Stop or rewind
|
|
ws->m_Source->Rewind(); // can't call Stop or rewind cause it removes ti from the list and it crashes
|
|
*/
|
|
}
|
|
}
|
|
|
|
// we clear the sounds of the resume list
|
|
m_SoundsPlaying.Clear();
|
|
|
|
|
|
// We release all the minions
|
|
ReleaseMinions();
|
|
|
|
if(g_InitialVolumeChanged)
|
|
m_Primary->SetVolume(g_InitialVolume);
|
|
|
|
// we commit the changes
|
|
m_Listener->CommitDeferredSettings();
|
|
}
|
|
|
|
return CK_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CKBOOL
|
|
DX3SoundManager::IsInitialized(){
|
|
return m_Root && m_Primary;
|
|
}
|