440 lines
13 KiB
C++
Executable file
440 lines
13 KiB
C++
Executable file
#include "fmod_settings.h"
|
|
|
|
#ifdef FMOD_SUPPORT_EAX
|
|
|
|
#include "fmod_output_dsound.h"
|
|
#include "fmod_eax4.h"
|
|
#include "fmod_localcriticalsection.h"
|
|
#include "fmod_sample_dsound.h"
|
|
#include "fmod_systemi.h"
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
namespace FMOD
|
|
{
|
|
|
|
bool gFXslot2set = false;
|
|
bool gFXslot3set = false;
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
bool OutputDSound::querySupportEAX4(FMOD_GUID guid, unsigned long ulProperty)
|
|
{
|
|
HRESULT hr;
|
|
unsigned long ulSupport;
|
|
GUID g;
|
|
|
|
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::querySupportEAX4", "check properties %08X\n", ulProperty));
|
|
|
|
FMOD_memcpy(&g, &guid, sizeof(GUID));
|
|
|
|
hr = mBufferReverb->QuerySupport(g, ulProperty, &ulSupport);
|
|
if ( FAILED(hr) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ( (ulSupport&(KSPROPERTY_SUPPORT_GET|KSPROPERTY_SUPPORT_SET)) ==
|
|
(KSPROPERTY_SUPPORT_GET|KSPROPERTY_SUPPORT_SET) )
|
|
{
|
|
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::querySupportEAX4", "success.\n"));
|
|
|
|
return true;
|
|
}
|
|
|
|
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::querySupportEAX4", "failed.\n"));
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
bool OutputDSound::initEAX4()
|
|
{
|
|
FMOD_RESULT result;
|
|
ULONG support = 0;
|
|
HRESULT hr = DS_OK;
|
|
GUID guid;
|
|
FMOD_CODEC_WAVEFORMAT waveformat;
|
|
|
|
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX4", "Querying EAX4\n"));
|
|
|
|
if (mBufferReverb)
|
|
{
|
|
mBufferReverb->Release();
|
|
mBufferReverb = NULL;
|
|
}
|
|
|
|
/*
|
|
Create EAX sample
|
|
*/
|
|
|
|
FMOD_memset(&waveformat, 0, sizeof(FMOD_CODEC_WAVEFORMAT));
|
|
waveformat.frequency = 44100;
|
|
waveformat.lengthpcm = 1024;
|
|
waveformat.channels = 1;
|
|
waveformat.format = FMOD_SOUND_FORMAT_PCM16;
|
|
|
|
result = createSample(FMOD_3D | FMOD_UNIQUE, &waveformat, (Sample **)&mSampleReverb);
|
|
if (result != FMOD_OK)
|
|
{
|
|
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX4", "could not create hardware sample.\n"));
|
|
return false;
|
|
}
|
|
|
|
mSampleReverb->mSystem = mSystem;
|
|
|
|
|
|
/*
|
|
OBTAIN EAX INTERFACE TO BUFFER
|
|
*/
|
|
FMOD_memcpy(&guid, &FMOD_IID_IKsPropertySet, sizeof(GUID));
|
|
|
|
if(mSampleReverb->mBuffer3D->QueryInterface(guid, (void **)&mBufferReverb) != DS_OK)
|
|
{
|
|
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX4", "failed (1).\n"));
|
|
|
|
mBufferReverb = NULL;
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
QUERY FOR EAX support
|
|
*/
|
|
support = querySupportEAX4(FMOD_EAXPROPERTYID_EAX40_Context, EAXCONTEXT_ALLPARAMETERS);
|
|
if (support) support = querySupportEAX4(FMOD_EAXPROPERTYID_EAX40_FXSlot0, EAXFXSLOT_ALLPARAMETERS);
|
|
if (support) support = querySupportEAX4(FMOD_EAXPROPERTYID_EAX40_FXSlot1, EAXFXSLOT_ALLPARAMETERS);
|
|
if (support) support = querySupportEAX4(FMOD_EAXPROPERTYID_EAX40_FXSlot2, EAXFXSLOT_ALLPARAMETERS);
|
|
if (support) support = querySupportEAX4(FMOD_EAXPROPERTYID_EAX40_FXSlot3, EAXFXSLOT_ALLPARAMETERS);
|
|
if (support) support = querySupportEAX4(FMOD_EAXPROPERTYID_EAX40_Source, EAXSOURCE_ALLPARAMETERS);
|
|
|
|
if (support)
|
|
{
|
|
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX4", "EAX 4.0 - success\n"));
|
|
}
|
|
else
|
|
{
|
|
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX4", "failed (2).\n"));
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
/*
|
|
Turn down reverb to start with
|
|
*/
|
|
{
|
|
long room = EAXREVERB_MINROOM;
|
|
|
|
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX4", "setting reverb environment to OFF\n"));
|
|
|
|
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX40_FXSlot0, sizeof(GUID));
|
|
hr = mBufferReverb->Set(guid, EAXREVERB_ROOM, 0, 0, &room, sizeof(long));
|
|
if (FAILED(hr))
|
|
{
|
|
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX4", "failed (3).\n"));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX4", "found!\n"));
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT OutputDSound::closeEAX4()
|
|
{
|
|
GUID guid;
|
|
long lock = EAXFXSLOT_UNLOCKED;
|
|
|
|
if (mBufferReverb)
|
|
{
|
|
/*
|
|
Unlock FX slots
|
|
*/
|
|
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX40_FXSlot2, sizeof(GUID));
|
|
mBufferReverb->Set(guid, EAXFXSLOT_LOCKED, 0, 0, &lock, sizeof(long));
|
|
|
|
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX40_FXSlot3, sizeof(GUID));
|
|
mBufferReverb->Set(guid, EAXFXSLOT_LOCKED, 0, 0, &lock, sizeof(long));
|
|
|
|
mBufferReverb->Release();
|
|
mBufferReverb = NULL;
|
|
}
|
|
|
|
if (mSampleReverb)
|
|
{
|
|
mSampleReverb->release();
|
|
mSampleReverb = NULL;
|
|
}
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT OutputDSound::setPropertiesEAX4(const FMOD_REVERB_PROPERTIES *prop)
|
|
{
|
|
HRESULT hr;
|
|
EAXREVERBPROPERTIES eaxprop = {0};
|
|
EAXFXSLOTPROPERTIES fxslot;
|
|
GUID guid;
|
|
|
|
if (!prop)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
switch(prop->Instance)
|
|
{
|
|
case 1:
|
|
{
|
|
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX40_FXSlot2, sizeof(GUID));
|
|
|
|
if (!gFXslot2set)
|
|
{
|
|
FMOD_memcpy(&fxslot.guidLoadEffect, &FMOD_EAX_REVERB_EFFECT, sizeof(GUID));
|
|
fxslot.lLock = EAXFXSLOT_LOCKED;
|
|
fxslot.lVolume = 0;
|
|
fxslot.ulFlags = EAXFXSLOTFLAGS_ENVIRONMENT;
|
|
|
|
hr = mBufferReverb->Set(guid, EAXFXSLOT_ALLPARAMETERS, NULL, 0, &fxslot, sizeof(EAXFXSLOTPROPERTIES));
|
|
if (FAILED(hr))
|
|
{
|
|
ULONG ulReceived;
|
|
GUID effect;
|
|
|
|
/*
|
|
Check if the slot contains a reverb. If so, we can still use that slot.
|
|
*/
|
|
hr = mBufferReverb->Get(guid, EAXFXSLOT_LOADEFFECT, NULL, 0, &effect, sizeof(GUID), &ulReceived);
|
|
if (FAILED(hr))
|
|
{
|
|
return FMOD_ERR_REVERB_INSTANCE;
|
|
}
|
|
|
|
if (memcmp(&effect, &fxslot.guidLoadEffect, sizeof(GUID)))
|
|
{
|
|
return FMOD_ERR_REVERB_INSTANCE;
|
|
}
|
|
}
|
|
|
|
gFXslot2set = true;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX40_FXSlot3, sizeof(GUID));
|
|
|
|
if (!gFXslot3set)
|
|
{
|
|
FMOD_memcpy(&fxslot.guidLoadEffect, &FMOD_EAX_REVERB_EFFECT, sizeof(GUID));
|
|
fxslot.lLock = EAXFXSLOT_LOCKED;
|
|
fxslot.lVolume = 0;
|
|
fxslot.ulFlags = EAXFXSLOTFLAGS_ENVIRONMENT;
|
|
|
|
hr = mBufferReverb->Set(guid, EAXFXSLOT_ALLPARAMETERS, NULL, 0, &fxslot, sizeof(EAXFXSLOTPROPERTIES));
|
|
if (FAILED(hr))
|
|
{
|
|
ULONG ulReceived;
|
|
GUID effect;
|
|
|
|
/*
|
|
Check if the slot contains a reverb. If so, we can still use that slot.
|
|
*/
|
|
hr = mBufferReverb->Get(guid, EAXFXSLOT_LOADEFFECT, NULL, 0, &effect, sizeof(GUID), &ulReceived);
|
|
if (FAILED(hr))
|
|
{
|
|
return FMOD_ERR_REVERB_INSTANCE;
|
|
}
|
|
|
|
if (memcmp(&effect, &fxslot.guidLoadEffect, sizeof(GUID)))
|
|
{
|
|
return FMOD_ERR_REVERB_INSTANCE;
|
|
}
|
|
}
|
|
|
|
gFXslot3set = true;
|
|
}
|
|
|
|
break;
|
|
}
|
|
default:
|
|
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX40_FXSlot0, sizeof(GUID));
|
|
break;
|
|
}
|
|
|
|
eaxprop.ulEnvironment = prop->Environment < 0 ? 0 : prop->Environment;
|
|
eaxprop.flEnvironmentSize = prop->EnvSize;
|
|
eaxprop.flEnvironmentDiffusion = prop->EnvDiffusion;
|
|
eaxprop.lRoom = prop->Room;
|
|
eaxprop.lRoomHF = prop->RoomHF;
|
|
eaxprop.lRoomLF = prop->RoomLF;
|
|
eaxprop.flDecayTime = prop->DecayTime;
|
|
eaxprop.flDecayHFRatio = prop->DecayHFRatio;
|
|
eaxprop.flDecayLFRatio = prop->DecayLFRatio;
|
|
eaxprop.lReflections = prop->Reflections;
|
|
eaxprop.flReflectionsDelay = prop->ReflectionsDelay;
|
|
eaxprop.vReflectionsPan.x = prop->ReflectionsPan[0];
|
|
eaxprop.vReflectionsPan.y = prop->ReflectionsPan[1];
|
|
eaxprop.vReflectionsPan.z = prop->ReflectionsPan[2];
|
|
eaxprop.lReverb = prop->Reverb;
|
|
eaxprop.flReverbDelay = prop->ReverbDelay;
|
|
eaxprop.vReverbPan.x = prop->ReverbPan[0];
|
|
eaxprop.vReverbPan.y = prop->ReverbPan[1];
|
|
eaxprop.vReverbPan.z = prop->ReverbPan[2];
|
|
eaxprop.flEchoTime = prop->EchoTime;
|
|
eaxprop.flEchoDepth = prop->EchoDepth;
|
|
eaxprop.flModulationTime = prop->ModulationTime;
|
|
eaxprop.flModulationDepth = prop->ModulationDepth;
|
|
eaxprop.flAirAbsorptionHF = prop->AirAbsorptionHF;
|
|
eaxprop.flHFReference = prop->HFReference;
|
|
eaxprop.flLFReference = prop->LFReference;
|
|
eaxprop.flRoomRolloffFactor = prop->RoomRolloffFactor;
|
|
eaxprop.ulFlags = prop->Flags & 0xFF;
|
|
|
|
hr = mBufferReverb->Set(guid, EAXREVERB_ALLPARAMETERS, NULL, 0, &eaxprop, sizeof(EAXREVERBPROPERTIES));
|
|
if (FAILED(hr))
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT OutputDSound::getPropertiesEAX4(FMOD_REVERB_PROPERTIES *prop)
|
|
{
|
|
HRESULT hr;
|
|
EAXREVERBPROPERTIES eaxprop;
|
|
ULONG ulReceived;
|
|
GUID guid;
|
|
|
|
if (!prop)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
switch(prop->Instance)
|
|
{
|
|
case 1:
|
|
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX40_FXSlot2, sizeof(GUID));
|
|
break;
|
|
case 2:
|
|
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX40_FXSlot3, sizeof(GUID));
|
|
break;
|
|
default:
|
|
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX40_FXSlot0, sizeof(GUID));
|
|
break;
|
|
}
|
|
|
|
hr = mBufferReverb->Get(guid, EAXREVERB_ALLPARAMETERS, NULL, 0, &eaxprop, sizeof(EAXREVERBPROPERTIES), &ulReceived);
|
|
if (FAILED(hr))
|
|
{
|
|
return FMOD_ERR_UNSUPPORTED;
|
|
}
|
|
|
|
prop->Environment = eaxprop.ulEnvironment ;
|
|
prop->EnvSize = eaxprop.flEnvironmentSize ;
|
|
prop->EnvDiffusion = eaxprop.flEnvironmentDiffusion ;
|
|
prop->Room = eaxprop.lRoom ;
|
|
prop->RoomHF = eaxprop.lRoomHF ;
|
|
prop->RoomLF = eaxprop.lRoomLF ;
|
|
prop->DecayTime = eaxprop.flDecayTime ;
|
|
prop->DecayHFRatio = eaxprop.flDecayHFRatio ;
|
|
prop->DecayLFRatio = eaxprop.flDecayLFRatio ;
|
|
prop->Reflections = eaxprop.lReflections ;
|
|
prop->ReflectionsDelay = eaxprop.flReflectionsDelay ;
|
|
prop->ReflectionsPan[0] = eaxprop.vReflectionsPan.x ;
|
|
prop->ReflectionsPan[1] = eaxprop.vReflectionsPan.y ;
|
|
prop->ReflectionsPan[2] = eaxprop.vReflectionsPan.z ;
|
|
prop->Reverb = eaxprop.lReverb ;
|
|
prop->ReverbDelay = eaxprop.flReverbDelay ;
|
|
prop->ReverbPan[0] = eaxprop.vReverbPan.x ;
|
|
prop->ReverbPan[1] = eaxprop.vReverbPan.y ;
|
|
prop->ReverbPan[2] = eaxprop.vReverbPan.z ;
|
|
prop->EchoTime = eaxprop.flEchoTime ;
|
|
prop->EchoDepth = eaxprop.flEchoDepth ;
|
|
prop->ModulationTime = eaxprop.flModulationTime ;
|
|
prop->ModulationDepth = eaxprop.flModulationDepth ;
|
|
prop->AirAbsorptionHF = eaxprop.flAirAbsorptionHF ;
|
|
prop->HFReference = eaxprop.flHFReference ;
|
|
prop->LFReference = eaxprop.flLFReference ;
|
|
prop->RoomRolloffFactor = eaxprop.flRoomRolloffFactor ;
|
|
prop->Flags = eaxprop.ulFlags ;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* FMOD_SUPPORT_EAX */
|
|
|