Descent3/dd_sndlib/eax.cpp
2024-04-15 21:43:29 -06:00

374 lines
8.8 KiB
C++

/*
* $Source: $
* $Revision: 10 $
* $Author: Samir $
* $Date: 9/27/99 5:38p $
*
*
*
* $Log: /DescentIII/Main/dd_sndlib/eax.cpp $
*
* 10 9/27/99 5:38p Samir
* EAX 2.0->1.0 compatibility checkin.
*
* 9 8/24/99 3:42p Samir
* load EAX dynamically
*
* 8 8/24/99 1:47p Samir
* updated header file.
*
* 7 8/23/99 5:29p Samir
* incremental EAX 2.0 checkin
*
* 6 1/11/99 5:54p Samir
* made environment a hangar.
*
* 5 1/11/99 5:52p Samir
* updated EAX support.
*
* 4 1/08/99 6:31p Samir
* added reverb
*
* 3 12/23/98 11:50a Samir
*
* 2 12/23/98 11:48a Samir
* basic functionality.
*
* 1 12/21/98 7:06p Samir
* Creative Labs EAX
*
*/
#include "auddev.h"
#include <objbase.h>
#include <initguid.h>
#include "eax.h"
#include "eax2.h"
#include "pserror.h"
// DATA
#define EAX_ENVIRONMENTS_AVAILABLE (1<<0)
#define VOICE_MANAGMENT_AVAILABLE (1<<1)
struct
{
HINSTANCE m_dll;
LPDIRECTSOUND m_lpds;
LPDIRECTSOUNDBUFFER m_lpdsb;
LPKSPROPERTYSET m_lpksps;
DWORD m_dwSoundProperties;
VmMode m_vmode;
EAX_REVERBPROPERTIES m_preset;
}
EAX = { NULL, NULL, 0, 0, 0 };
const EAX_REVERBPROPERTIES EAX_Environments[EAX_ENVIRONMENT_COUNT] =
{
{ EAX_PRESET_GENERIC } ,
{ EAX_PRESET_PADDEDCELL } ,
{ EAX_PRESET_ROOM } ,
{ EAX_PRESET_BATHROOM } ,
{ EAX_PRESET_LIVINGROOM } ,
{ EAX_PRESET_STONEROOM } ,
{ EAX_PRESET_AUDITORIUM } ,
{ EAX_PRESET_CONCERTHALL } ,
{ EAX_PRESET_CAVE } ,
{ EAX_PRESET_ARENA } ,
{ EAX_PRESET_HANGAR } ,
{ EAX_PRESET_CARPETEDHALLWAY } ,
{ EAX_PRESET_HALLWAY } ,
{ EAX_PRESET_STONECORRIDOR } ,
{ EAX_PRESET_ALLEY } ,
{ EAX_PRESET_FOREST } ,
{ EAX_PRESET_CITY } ,
{ EAX_PRESET_MOUNTAINS } ,
{ EAX_PRESET_QUARRY } ,
{ EAX_PRESET_PLAIN } ,
{ EAX_PRESET_PARKINGLOT } ,
{ EAX_PRESET_SEWERPIPE } ,
{ EAX_PRESET_UNDERWATER } ,
{ EAX_PRESET_DRUGGED } ,
{ EAX_PRESET_DIZZY } ,
{ EAX_PRESET_PSYCHOTIC }
};
// FUNCTIONS
HRESULT (FAR PASCAL *DLLEAXDirectSoundCreate)(GUID*, LPDIRECTSOUND*, IUnknown FAR *) = NULL;
// EAX 1.0 support.
bool EAX_SetEnvironmentPreset(unsigned environment);
bool EAX_SetEnvironmentalReverb(float volume, float damping, float decay);
// CODE
bool EAX_Create(GUID *pGuid, LPDIRECTSOUND *lpds)
{
HRESULT hr;
EAX.m_dll = LoadLibrary("eax.dll");
if (EAX.m_dll) {
DLLEAXDirectSoundCreate = (LPEAXDIRECTSOUNDCREATE)GetProcAddress(EAX.m_dll, "EAXDirectSoundCreate");
if (!DLLEAXDirectSoundCreate) {
Error ("EAX DLL doesn't contain latest code for 2.0 functionality.");
return false;
}
mprintf((0, "EAX 2.0 support detected.\n"));
hr = (*DLLEAXDirectSoundCreate)(pGuid, &EAX.m_lpds, NULL);
}
else {
mprintf((0, "EAX 1.0 support detected.\n"));
hr = DirectSoundCreate(pGuid, &EAX.m_lpds, NULL);
}
if (hr != DS_OK) {
*lpds = NULL;
return false;
}
EAX.m_lpdsb = NULL;
EAX.m_dwSoundProperties = 0;
*lpds = EAX.m_lpds;
return true;
}
void EAX_Destroy()
{
if (EAX.m_lpds) {
if ( EAX.m_lpksps != NULL ) {
EAX.m_lpksps->Release();
EAX.m_lpksps = NULL;
}
if (EAX.m_lpdsb) {
EAX.m_lpdsb->Release();
EAX.m_lpdsb = NULL;
}
EAX.m_lpds->Release();
EAX.m_lpds = NULL;
}
if (EAX.m_dll) {
FreeLibrary(EAX.m_dll);
EAX.m_dll = NULL;
DLLEAXDirectSoundCreate = NULL;
}
EAX.m_dwSoundProperties = 0;
}
// returns EAX caps
int EAX_Caps()
{
return EAX.m_dwSoundProperties;
}
// initializes EAX specific interfaces.
bool EAX_SetPrimaryBuffer()
{
HRESULT hr;
DWORD support;
bool retval = true;
WAVEFORMATEX wave;
DSBUFFERDESC dsbdesc;
EAX_REVERBPROPERTIES props = {EAX_PRESET_HANGAR};
ASSERT(EAX.m_lpds);
memset(&wave, 0, sizeof(WAVEFORMATEX));
wave.wFormatTag = WAVE_FORMAT_PCM;
wave.nChannels = 2;
wave.nSamplesPerSec = 22050;
wave.wBitsPerSample = 16;
wave.nBlockAlign = wave.wBitsPerSample / 8 * wave.nChannels;
wave.nAvgBytesPerSec = wave.nSamplesPerSec * wave.nBlockAlign;
memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = DSBCAPS_STATIC|DSBCAPS_CTRL3D;
dsbdesc.dwBufferBytes = DSBSIZE_MIN*2;
dsbdesc.lpwfxFormat = &wave;
if ( FAILED(EAX.m_lpds->CreateSoundBuffer(&dsbdesc, &EAX.m_lpdsb, NULL)) ) {
return false;
}
if (EAX.m_lpksps == NULL) {
if ( FAILED(EAX.m_lpdsb->QueryInterface(IID_IKsPropertySet, (LPVOID *)&EAX.m_lpksps)) ) {
mprintf((0, "EAX: Error failed to query property set interface.\n"));
Int3();
retval = false;
goto error_sub;
}
}
// now, query support depending on EAX 2.0 availability
if (EAX.m_dll) {
hr = EAX.m_lpksps->QuerySupport(DSPROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ENVIRONMENT, &support);
if (SUCCEEDED(hr)) {
if ((support & (KSPROPERTY_SUPPORT_SET | KSPROPERTY_SUPPORT_GET)) == (KSPROPERTY_SUPPORT_SET | KSPROPERTY_SUPPORT_GET)) {
EAX.m_dwSoundProperties |= EAX_ENVIRONMENTS_AVAILABLE;
}
}
hr = EAX.m_lpksps->QuerySupport(DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_OBSTRUCTION, &support);
if (SUCCEEDED(hr)) {
if ((support & (KSPROPERTY_SUPPORT_SET | KSPROPERTY_SUPPORT_GET)) == (KSPROPERTY_SUPPORT_SET | KSPROPERTY_SUPPORT_GET)) {
EAX.m_dwSoundProperties |= EAXF_SOURCE_OBSTRUCTION;
}
}
}
else {
hr = EAX.m_lpksps->QuerySupport(DSPROPSETID_EAX_ReverbProperties, DSPROPERTY_EAX_ALL, &support);
if (SUCCEEDED(hr)) {
if ( (support & KSPROPERTY_SUPPORT_SET|KSPROPERTY_SUPPORT_GET) == (KSPROPERTY_SUPPORT_SET|KSPROPERTY_SUPPORT_GET) ) {
EAX.m_dwSoundProperties |= EAX_ENVIRONMENTS_AVAILABLE;
/*
Here the reverb environment is initialized to off.
*/
EAX_SetEnvironmentPreset(EAX_ENVIRONMENT_HANGAR);
}
}
}
retval = (EAX.m_dwSoundProperties & EAX_ENVIRONMENTS_AVAILABLE) ? true : false;
EAX_SetEnvironmentalReverb(props.fVolume, props.fDamping,props.fDecayTime_sec);
error_sub:
if (retval == false) {
mprintf((0, "EAX: Error failed to query environmental support.\n"));
Int3();
if (EAX.m_lpksps) {
EAX.m_lpksps->Release();
EAX.m_lpksps = NULL;
}
}
return retval;
}
/*
This routine can be used to change the current EAX preset environment. The environment applies
to all 3D buffers.
*/
// sets up current global environment reverb
bool EAX_SetEnvironmentalReverb(float volume, float damping, float decay)
{
if ( EAX.m_dwSoundProperties & EAX_ENVIRONMENTS_AVAILABLE ) {
int i;
EAX.m_preset.environment = EAX_ENVIRONMENT_GENERIC;
EAX.m_preset.fVolume = volume;
EAX.m_preset.fDecayTime_sec = decay;
EAX.m_preset.fDamping = damping;
if (EAX.m_dll) {
for (i = 0; i < EAX_ENVIRONMENT_COUNT; i++)
{
if (volume == EAX_Environments[i].fVolume && damping == EAX_Environments[i].fDamping && decay == EAX_Environments[i].fDecayTime_sec) {
EAX.m_preset.environment = (ulong)i;
break;
}
}
if (FAILED(
EAX.m_lpksps->Set(DSPROPSETID_EAX_ListenerProperties,
DSPROPERTY_EAXLISTENER_ENVIRONMENT,
NULL,
0,
&EAX.m_preset.environment, sizeof(ulong)
)
)
) {
return false;
}
}
else {
if ( FAILED(EAX.m_lpksps->Set(DSPROPSETID_EAX_ReverbProperties, DSPROPERTY_EAX_VOLUME, NULL, 0, &EAX.m_preset.fVolume, sizeof(float))) ) {
return false;
}
if ( FAILED(EAX.m_lpksps->Set(DSPROPSETID_EAX_ReverbProperties, DSPROPERTY_EAX_DECAYTIME, NULL, 0, &EAX.m_preset.fDecayTime_sec, sizeof(float))) ) {
return false;
}
if ( FAILED(EAX.m_lpksps->Set(DSPROPSETID_EAX_ReverbProperties, DSPROPERTY_EAX_DAMPING, NULL, 0, &EAX.m_preset.fDamping, sizeof(float))) ) {
return false;
}
}
return true;
}
return false;
}
// intializes a sound source for EAX
bool EAX_InitSource(LPDIRECTSOUND3DBUFFER lpBuffer3D, LPKSPROPERTYSET *plpksp)
{
if (!lpBuffer3D) return true;
if ( SUCCEEDED(lpBuffer3D->QueryInterface(IID_IKsPropertySet, (void**)plpksp)) )
{
return true;
}
return false;
}
// frees an eax sound source
void EAX_FreeSource(LPKSPROPERTYSET lpksp)
{
if (lpksp) {
lpksp->Release();
}
}
// sets source properties
void EAX_SetSourceProperties(LPKSPROPERTYSET lpksp, float obstruction)
{
if (!lpksp) return;
if (EAX.m_dwSoundProperties & EAXF_SOURCE_OBSTRUCTION) {
LONG lValue = (DWORD)(-10000 * obstruction);
lpksp->Set(DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_OBSTRUCTION, NULL, 0, &lValue, sizeof(LONG));
}
}
/*
This routine can be used to change the current EAX preset environment. The environment applies
to all 3D buffers.
*/
// sets up current global environment reverb
bool EAX_SetEnvironmentPreset(unsigned environment)
{
EAX.m_preset.environment = environment;
if ( FAILED(EAX.m_lpksps->Set(DSPROPSETID_EAX_ReverbProperties, DSPROPERTY_EAX_ENVIRONMENT, NULL, 0, &EAX.m_preset.environment, sizeof(float))) )
{
return false;
}
return true;
}