deargui-vpl/ref/virtools/Samples/Managers/DX7 Sound Manager/Dx7SoundManager.cpp

960 lines
26 KiB
C++

// Dx7SoundManager.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#if _MSC_VER >= 1400 //visual studio 8
#define DIRECTSOUND_VERSION 0x01000
#else
#define DIRECTSOUND_VERSION 0x0800
#endif
#include <mmreg.h>
#include <dsound.h>
#include "DxSoundManager.h"
#include "Dx7SoundManager.h"
CKERROR CreateDx7SoundManager(CKContext *ctx){
new DX7SoundManager(ctx);
return CK_OK;
}
extern long g_InitialVolume;
extern BOOL g_InitialVolumeChanged;
CK_SOUNDMANAGER_CAPS
DX7SoundManager::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*
DX7SoundManager::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|m_Mixing_Location|DSBCAPS_GETCURRENTPOSITION2;
#if _MSC_VER >= 1400 //visual studio 8
if (VxGetOs()==VXOS_WINVISTA)
dsbd.dwFlags |= DSBCAPS_TRUEPLAYPOSITION;
#endif
// Buffer must be a multiple of samples
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;
if (m_Mixing_Location == DSBCAPS_LOCSOFTWARE && m_Use_Mute_after_Max_in_LOCSOFTWARE) {
dsbd.dwFlags |= DSBCAPS_MUTE3DATMAXDISTANCE;
}
}
LPDIRECTSOUNDBUFFER lpdsb = NULL;
// Create the static DirectSound buffer
HRESULT err = m_Root->CreateSoundBuffer( &dsbd, &lpdsb, NULL );
// If sound could not be created in hardware try managed mode
if (FAILED(err) && (m_Mixing_Location == DSBCAPS_LOCHARDWARE)) {
dsbd.dwFlags &= ~DSBCAPS_LOCHARDWARE;
err = m_Root->CreateSoundBuffer( &dsbd, &lpdsb, NULL );
}
if (err)
return NULL;
#ifdef _DEBUG
// Fill Buffer With rubbbish to Detect problems
{
BYTE *sbuf1,*sbuf2;
DWORD ssz1=0,ssz2=0;
DWORD i;
HRESULT res = lpdsb->Lock(0,0,(LPVOID*)&sbuf1,&ssz1,(LPVOID*)&sbuf2,&ssz2,DSBLOCK_ENTIREBUFFER);
if(res == S_OK){
for(i=0;i<ssz1;i++){
sbuf1[i] = rand();
}
for(i=0;i<ssz2;i++){
sbuf2[i] = rand();
}
lpdsb->Unlock(sbuf1,ssz1,sbuf2,ssz2);
}
}
#endif
err = lpdsb->SetFrequency(wf->nSamplesPerSec);
return lpdsb;
}
void*
DX7SoundManager::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 sound could not be created in hardware try managed mode
if (FAILED(err) && (m_Mixing_Location == DSBCAPS_LOCHARDWARE)) {
dsbd.dwFlags &= ~DSBCAPS_LOCHARDWARE;
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(DS_OK == src->Lock(0,0,(LPVOID*)&sbuf1,&ssz1,(LPVOID*)&sbuf2,&ssz2,DSBLOCK_ENTIREBUFFER)){
BYTE *dbuf1,*dbuf2;
DWORD dsz1,dsz2;
if(DS_OK == newsource->Lock(0,0,(LPVOID*)&dbuf1,&dsz1,(LPVOID*)&dbuf2,&dsz2,DSBLOCK_ENTIREBUFFER)){
if(ssz1)
memcpy(dbuf1,sbuf1,ssz1);
if(ssz2)
memcpy(dbuf2,sbuf2,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
DX7SoundManager::ReleaseSource(void* source)
{
if (!source) return;
LPDIRECTSOUNDBUFFER m_Source = (LPDIRECTSOUNDBUFFER)source;
m_Source->Stop();
m_Source->Release();
}
void
DX7SoundManager::InternalPause(void* source)
{
if(!source) return;
LPDIRECTSOUNDBUFFER m_Source = (LPDIRECTSOUNDBUFFER)source;
HRESULT res = m_Source->Stop();
}
void
DX7SoundManager::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
DX7SoundManager::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
DX7SoundManager::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
DX7SoundManager::SetPlayPosition(void* source,int pos)
{
if (!source) return;
LPDIRECTSOUNDBUFFER m_Source = (LPDIRECTSOUNDBUFFER)source;
m_Source->SetCurrentPosition(pos);
}
int
DX7SoundManager::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
DX7SoundManager::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
DX7SoundManager::SetWaveFormat(void* source,CKWaveFormat& wf)
{
if (!source) return FALSE;
LPDIRECTSOUNDBUFFER m_Source = (LPDIRECTSOUNDBUFFER)source;
return m_Source->SetFormat((WAVEFORMATEX*)&wf);
}
CKERROR
DX7SoundManager::GetWaveFormat(void* source,CKWaveFormat& wf)
{
if (!source) return FALSE;
LPDIRECTSOUNDBUFFER m_Source = (LPDIRECTSOUNDBUFFER)source;
return m_Source->GetFormat((WAVEFORMATEX*)&wf,sizeof(CKWaveFormat),NULL);
}
int
DX7SoundManager::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
DX7SoundManager::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
DX7SoundManager::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
DX7SoundManager::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
DX7SoundManager::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
DX7SoundManager::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)
&&
(GetType(source) == CK_WAVESOUND_BACKGROUND) //We set the pan only for 2D sound
)
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
DX7SoundManager::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
DX7SoundManager::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 Dx7PositionSource(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();
}
DX7SoundManager::DX7SoundManager(CKContext *Context):DXSoundManager(Context)
{
m_Root=0;
m_Listener=NULL;
m_Primary = NULL;
m_BackSound = NULL;
m_Use_Mute_after_Max_in_LOCSOFTWARE = FALSE;
m_Context->RegisterNewManager(this);
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")
}
DX7SoundManager::~DX7SoundManager()
{
UNBIND(m_Context,"Sounds/Mixing Method");
UNBIND(m_Context,"Sounds/Mute 3D Sounds After Max Distance");
}
//{secret}
CKERROR DX7SoundManager::PostClearAll()
{
CKSoundManager::PostClearAll();
m_SoundsPlaying.Clear();
ReleaseMinions();
RegisterAttribute();
return CK_OK;
}
/*************************************************
Name:
Summary: Not Yet Documented
Arguments:
Return Value:
Remarks:
See also:
*************************************************/
CKERROR
DX7SoundManager::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
DX7SoundManager::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 IsSourcePlaying(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
DX7SoundManager::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
Dx7PositionSource((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
DX7SoundManager::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 DX7SoundManager::IsInitialized()
{
return m_Root && m_Primary;
}