mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-23 03:58:59 +00:00
374 lines
8.8 KiB
C++
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;
|
|
}
|
|
|