/*
===========================================================================
ARX FATALIS GPL Source Code
Copyright (C) 1999-2010 Arkane Studios SA, a ZeniMax Media company.
This file is part of the Arx Fatalis GPL Source Code ('Arx Fatalis Source Code').
Arx Fatalis Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Arx Fatalis Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Arx Fatalis Source Code. If not, see
.
In addition, the Arx Fatalis Source Code is also subject to certain additional terms. You should have received a copy of these
additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Arx
Fatalis Source Code. If not, please request a copy in writing from Arkane Studios at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing Arkane Studios, c/o
ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
///////////////////////////////////////////////////////////////////////////////
// //
// TODO //
// //
// Finish reverb implementation //
// Keep finished instances a while before deleting in case we need it again //
// Abstract driver API for testing other libs than DirectSound //
// Finish ASF format implementation //
// //
// Ambiance //
// Make sure global 3D localisation and multiple keys / track works properly //
// //
///////////////////////////////////////////////////////////////////////////////
#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "dsound.lib")
#pragma comment(lib, "eaxguid.lib")
#pragma comment(lib, "implode.lib")
#pragma comment(lib, "winmm.lib")
#include
#include "Athena_Resource.h"
#include "Athena_Mixer.h"
#include "Athena_Sample.h"
#include "Athena_Ambiance.h"
#include "Athena_Instance.h"
#include "Athena_Global.h"
#include "Athena_Stream.h"
#include "Athena_FileIO.h"
#include
#include
#include
#define _CRTDBG_MAP_ALLOC
#include
//#include "console_public.h"
//#pragma comment(lib, "Console DLL")
namespace ATHENA
{
//Multithread data
static HANDLE mutex(NULL);
static const aalULong MUTEX_TIMEOUT(500);
static const aalULong MUTEX_ONUPDATE_TIMEOUT(200);
static aalError EnableEnvironmentalAudio();
HWND hwnd = NULL;
///////////////////////////////////////////////////////////////////////////////
// //
// Global setup //
// //
///////////////////////////////////////////////////////////////////////////////
aalError aalInit(aalVoid * param)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
//Clean any initialized data
aalClean();
CoInitialize(NULL);
//Initialize random number generator
InitSeed();
//Create DirectSound device interface
if (CoCreateInstance(CLSID_EAXDirectSound, NULL, CLSCTX_INPROC_SERVER, IID_IDirectSound, (aalVoid **)&device))
{
if (CoCreateInstance(CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER, IID_IDirectSound, (aalVoid **)&device))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_SYSTEM;
}
}
else is_reverb_present = AAL_UTRUE;
if (device->Initialize(NULL) ||
device->SetCooperativeLevel(IsWindow((HWND)param) ? (HWND)param : GetForegroundWindow(), DSSCL_PRIORITY))
{
device->Release(), device = NULL;
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_SYSTEM;
}
hwnd = (HWND)param;
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalInitForceNoEAX(aalVoid * param)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
//Clean any initialized data
aalClean();
CoInitialize(NULL);
//Initialize random number generator
InitSeed();
//Create DirectSound device interface
if (CoCreateInstance(CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER, IID_IDirectSound, (aalVoid **)&device))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_SYSTEM;
}
if (device->Initialize(NULL) ||
device->SetCooperativeLevel(IsWindow((HWND)param) ? (HWND)param : GetForegroundWindow(), DSSCL_PRIORITY))
{
device->Release(), device = NULL;
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_SYSTEM;
}
hwnd = (HWND)param;
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalClean()
{
if (mutex) WaitForSingleObject(mutex, MUTEX_TIMEOUT);
_mixer.Clean(false);
_amb.Clean(false);
_inst.Clean(true);
_sample.Clean(false);
_env.Clean(false);
if (environment) environment->Release(), environment = NULL;
if (listener) listener->Release(), listener = NULL;
if (primary) primary->Release(), primary = NULL;
if (device) device->Release(), device = NULL;
if (debug_log) fclose(debug_log), debug_log = NULL;
free(root_path), root_path = NULL;
free(sample_path), sample_path = NULL;
free(ambiance_path), ambiance_path = NULL;
free(environment_path), environment_path = NULL;
stream_limit_ms = AAL_DEFAULT_STREAMLIMIT;
session_start = GetTickCount();
session_time = 0;
is_reverb_present = AAL_UFALSE;
if (mutex) ReleaseMutex(mutex), CloseHandle(mutex), mutex = NULL;
CoUninitialize();
return AAL_OK;
}
aalError aalSetOutputFormat(const aalFormat & f)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
WAVEFORMATEX formatex;
DSBUFFERDESC desc;
//Set primary settings to default
memset(&formatex, 0, sizeof(WAVEFORMATEX));
formatex.wFormatTag = WAVE_FORMAT_PCM;
formatex.nChannels = (aalUWord)(f.channels);
formatex.nSamplesPerSec = f.frequency;
formatex.wBitsPerSample = (aalUWord)(f.quality);
formatex.nBlockAlign = (aalUWord)(f.channels * f.quality / 8);
formatex.nAvgBytesPerSec = formatex.nBlockAlign * f.frequency;
memset(&desc, 0, sizeof(DSBUFFERDESC));
desc.dwSize = sizeof(DSBUFFERDESC);
desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_GETCURRENTPOSITION2;
desc.dwFlags |= DSBCAPS_CTRL3D;
//Release previously created interfaces
if (environment) environment->Release(), environment = NULL;
if (listener) listener->Release(), listener = NULL;
if (primary) primary->Release(), primary = NULL;
//Get new buffer and set its format
if (device->CreateSoundBuffer(&desc, &primary, NULL) ||
primary->Play(0, 0, DSBPLAY_LOOPING) ||
primary->SetFormat(&formatex))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_SYSTEM;
}
global_format.frequency = f.frequency;
global_format.quality = f.quality;
global_format.channels = f.channels;
stream_limit_bytes = UnitsToBytes(stream_limit_ms, global_format, AAL_UNIT_MS);
//Must restore all buffers here?!
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalAddResourcePack(const char * name)
{
AddPack(name);
return AAL_OK;
}
aalError aalSetStreamLimit(const aalULong & limit)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
stream_limit_ms = limit < 500 ? 500 : limit;
stream_limit_bytes = UnitsToBytes(stream_limit_ms, global_format, AAL_UNIT_MS);
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalSetRootPath(const char * _path)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
char path[256] = "";
FILE * file = NULL;
aalULong len;
if (_path) strcat(path, _path);
len = strlen(path);
if (len && path[len - 1] != '\\') strcat(path, "\\");
for (aalULong i(0); i < _sample.Size(); i++)
{
Sample * sample = _sample[i];
if (sample)
{
file = FileOpen(sample->name, "rb");
if (file)
{
FileClose(file);
if (!strncmp(sample->name, path, len))
{
strcpy(sample->name, &sample->name[len]);
sample->name = (char *)realloc(sample->name, strlen(sample->name) + 1);
}
}
else if (root_path)
{
char temp[256];
strcpy(temp, root_path);
strcat(temp, sample->name);
if (!strncmp(temp, path, len))
{
aalVoid * ptr;
ptr = realloc(sample->name, strlen(&temp[len]) + 1);
if (!ptr)
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_MEMORY;
}
sample->name = (char *)ptr;
strcpy(sample->name, &temp[len]);
}
}
}
}
if (len)
{
aalVoid * ptr;
ptr = realloc(root_path, len + 1);
if (!ptr)
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_MEMORY;
}
root_path = (char *)ptr;
memcpy(root_path, path, len + 1);
}
else free(root_path), root_path = NULL;
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalSetSamplePath(const char * _path)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (_path)
{
aalVoid * ptr;
const char * temp = _path;
aalULong len(strlen(_path) + 1);
if (root_path)
{
aalULong len2(strlen(root_path));
if (len2 < len && !memicmp(_path, root_path, len2))
{
temp += len2;
len -= len2;
}
}
if (len <= 1) free(sample_path), sample_path = NULL;
else
{
ptr = realloc(sample_path, len);
if (!ptr)
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_MEMORY;
}
sample_path = (char *)ptr;
memcpy(sample_path, temp, len);
if (len && sample_path[len - 2] != '\\') strcat(sample_path, "\\");
}
}
else free(sample_path), sample_path = NULL;
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalSetAmbiancePath(const char * _path)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (_path)
{
aalVoid * ptr;
const char * temp = _path;
aalULong len(strlen(_path) + 1);
if (root_path)
{
aalULong len2(strlen(root_path));
if (len2 < len && !memicmp(_path, root_path, len2))
{
temp += len2;
len -= len2;
}
}
if (len <= 1) free(ambiance_path), ambiance_path = NULL;
else
{
ptr = realloc(ambiance_path, len);
if (!ptr)
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_MEMORY;
}
ambiance_path = (char *)ptr;
memcpy(ambiance_path, temp, len);
if (len && ambiance_path[len - 2] != '\\') strcat(ambiance_path, "\\");
}
}
else free(ambiance_path), ambiance_path = NULL;
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalSetEnvironmentPath(const char * _path)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (_path)
{
aalVoid * ptr;
const char * temp = _path;
aalULong len(strlen(_path) + 1);
if (root_path)
{
aalULong len2(strlen(root_path));
if (len2 < len && !memicmp(_path, root_path, len2))
{
temp += len2;
len -= len2;
}
}
if (len <= 1) free(environment_path), environment_path = NULL;
else
{
ptr = realloc(environment_path, len);
if (!ptr)
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_MEMORY;
}
environment_path = (char *)ptr;
memcpy(environment_path, temp, len);
if (len && environment_path[len - 2] != '\\') strcat(environment_path, "\\");
}
}
else free(environment_path), environment_path = NULL;
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalEnable(const aalULong & flags)
{
aalError _error(AAL_OK);
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (flags & AAL_FLAG_PACKEDRESOURCES)
global_status |= AAL_FLAG_PACKEDRESOURCES, FileIOInit();
if (flags & AAL_FLAG_DEBUG)
{
if (debug_log) fclose(debug_log);
if (root_path)
{
char text[512];
sprintf(text, "%s%s", root_path, "athena.log");
debug_log = fopen(text, "w");
}
else debug_log = fopen("athena.log", "w");
if (!debug_log)
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_FILEIO;
}
global_status |= AAL_FLAG_DEBUG;
}
if (flags & AAL_FLAG_MULTITHREAD && !mutex)
{
mutex = CreateMutex(NULL, FALSE, NULL);
if (!mutex) return AAL_ERROR_SYSTEM;
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
}
if (flags & FLAG_ANY_3D_FX && !listener)
{
if (primary->QueryInterface(IID_IDirectSound3DListener, (aalVoid **)&listener))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_SYSTEM;
}
global_status |= FLAG_ANY_3D_FX & ~FLAG_ANY_ENV_FX;
}
if (flags & FLAG_ANY_ENV_FX && is_reverb_present && !environment)
{
_error = EnableEnvironmentalAudio();
if (_error)
{
if (mutex) ReleaseMutex(mutex);
return _error;
}
global_status |= FLAG_ANY_ENV_FX;
}
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalDisable(const aalULong & flags)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (flags & AAL_FLAG_PACKEDRESOURCES)
global_status &= ~AAL_FLAG_PACKEDRESOURCES, FileIOInit();
if (flags & AAL_FLAG_DEBUG && debug_log)
fclose(debug_log), debug_log = NULL;
if (flags & AAL_FLAG_MULTITHREAD && mutex)
ReleaseMutex(mutex), CloseHandle(mutex), mutex = NULL;
if (flags & FLAG_ANY_ENV_FX && environment)
environment->Release(), environment = NULL, global_status &= ~FLAG_ANY_ENV_FX;
if (flags & (FLAG_ANY_3D_FX & ~FLAG_ANY_ENV_FX) && listener)
listener->Release(), listener = NULL, global_status &= FLAG_ANY_3D_FX;
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Global status //
// //
///////////////////////////////////////////////////////////////////////////////
aalUBool aalIsEnabled(const aalFlag & flag)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_UFALSE;
aalUBool status(AAL_UFALSE);
switch (flag)
{
case AAL_FLAG_DEBUG :
status = debug_log ? AAL_UTRUE : AAL_UFALSE;
break;
case AAL_FLAG_MULTITHREAD :
status = mutex ? AAL_UTRUE : AAL_UFALSE;
break;
case AAL_FLAG_POSITION :
case AAL_FLAG_VELOCITY :
case AAL_FLAG_DIRECTION :
case AAL_FLAG_CONE :
case AAL_FLAG_FALLOFF :
status = listener ? AAL_UTRUE : AAL_UFALSE;
break;
case AAL_FLAG_REVERBERATION :
case AAL_FLAG_OBSTRUCTION :
status = environment ? AAL_UTRUE : AAL_UFALSE;
break;
}
if (mutex) ReleaseMutex(mutex);
return status;
}
long NBREVERB = 0;
///////////////////////////////////////////////////////////////////////////////
// //
// Global control //
// //
///////////////////////////////////////////////////////////////////////////////
long MXupdate = 0;
long MXpos = 0;
aalError aalUpdate()
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
// Update global timer
session_time = GetTickCount() - session_start;
aalULong i;
unsigned long ulNb = 0;
// Update instances
for (i = 0; i < _inst.Size(); i++)
{
Instance * instance = _inst[i];
if (instance)
{
instance->Update();
if (instance->IsIdled())
{
_inst.Delete(i);
}
else
{
ulNb ++;
}
}
}
// Update ambiances
for (i = 0; i < _amb.Size(); i++)
{
Ambiance * ambiance = _amb[i];
if (ambiance)
{
ambiance->Update();
if (ambiance->channel.flags & AAL_FLAG_AUTOFREE &&
!ambiance->IsPaused() && !ambiance->IsPlaying())
_amb.Delete(i);
}
}
// Update samples
Sample * sample = NULL;
for (i = 0; i < _sample.Size(); i++)
{
sample = _sample[i];
if (sample && sample->IsHandled() < 1)
{
//Console_Log("- %03d %s", NBREVERB, sample->name);
_sample.Delete(i);
}
}
// Update output buffer with new 3D positional settings
if (listener) listener->CommitDeferredSettings();
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Resource creation //
// //
///////////////////////////////////////////////////////////////////////////////
aalSLong aalCreateMixer(const char * name)
{
Mixer * mixer = NULL;
aalSLong id;
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT) return AAL_SFALSE;
mixer = new Mixer;
if ((name && mixer->SetName(name)) || (id = _mixer.Add(mixer)) == AAL_SFALSE)
{
delete mixer;
if (mutex) ReleaseMutex(mutex);
return AAL_SFALSE;
}
if (mutex) ReleaseMutex(mutex);
return id;
}
aalSLong aalCreateSample(const char * name)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_SFALSE;
Sample * sample = NULL;
aalSLong s_id;
if (!sample)
{
sample = new Sample();
}
if ((name && sample->Load(name)) || (s_id = _sample.Add(sample)) == AAL_SFALSE)
{
delete sample;
if (mutex) ReleaseMutex(mutex);
return AAL_SFALSE;
}
sample->Catch();
if (mutex) ReleaseMutex(mutex);
return s_id | 0xffff0000;
}
aalSLong aalCreateAmbiance(const char * name)
{
Ambiance * ambiance = NULL;
aalSLong a_id;
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT) return AAL_SFALSE;
ambiance = new Ambiance;
if ((name && ambiance->Load(name)) || (a_id = _amb.Add(ambiance)) == AAL_SFALSE)
{
delete ambiance;
if (mutex) ReleaseMutex(mutex);
return AAL_SFALSE;
}
//MISERY
Track * track = &ambiance->track_l[ambiance->track_c];
while (track > ambiance->track_l)
{
--track;
track->a_id = a_id;
}
if (mutex) ReleaseMutex(mutex);
return a_id;
}
aalSLong aalCreateEnvironment(const char * name)
{
Environment * env = NULL;
aalSLong e_id;
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT) return AAL_SFALSE;
env = new Environment;
if ((name && env->Load(name)) || (e_id = _env.Add(env)) == AAL_SFALSE)
{
delete env;
if (mutex) ReleaseMutex(mutex);
return AAL_SFALSE;
}
if (mutex) ReleaseMutex(mutex);
return e_id;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Resource destruction //
// //
///////////////////////////////////////////////////////////////////////////////
aalError aalDeleteSample(const aalSLong & sample_id)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
aalSLong s_id(GetSampleID(sample_id));
if (_sample.IsNotValid(s_id))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_sample.Delete(s_id);
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalDeleteAmbiance(const aalSLong & a_id)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
_amb.Delete(a_id);
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Retrieve resource by name //
// //
///////////////////////////////////////////////////////////////////////////////
aalSLong aalGetMixer(const char * name)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_SFALSE;
for (aalULong i(0); i < _mixer.Size(); i++)
if (_mixer[i] && (!name || !_stricmp(name, _mixer[i]->name)))
{
if (mutex) ReleaseMutex(mutex);
return i;
}
if (mutex) ReleaseMutex(mutex);
return AAL_SFALSE;
}
aalSLong aalGetAmbiance(const char * name)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_SFALSE;
for (aalULong i(0); i < _amb.Size(); i++)
if (_amb[i] && (!name || !_stricmp(name, _amb[i]->name)))
{
if (mutex) ReleaseMutex(mutex);
return i;
}
if (mutex) ReleaseMutex(mutex);
return AAL_SFALSE;
}
aalSLong aalGetEnvironment(const char * name)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_SFALSE;
for (aalULong i(0); i < _env.Size(); i++)
if (_env[i] && (!name || !_stricmp(name, _env[i]->name)))
{
if (mutex) ReleaseMutex(mutex);
return i;
}
if (mutex) ReleaseMutex(mutex);
return AAL_SFALSE;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Retrieve next resource by ID //
// //
///////////////////////////////////////////////////////////////////////////////
AAL_APIFUNC aalSLong aalGetNextAmbiance(const aalSLong & ambiance_id)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_SFALSE;
aalULong i(_amb.IsValid(ambiance_id) ? ambiance_id + 1 : 0);
while (i < _amb.Size())
{
if (_amb[i])
{
if (mutex) ReleaseMutex(mutex);
return i;
}
++i;
}
if (mutex) ReleaseMutex(mutex);
return AAL_SFALSE;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Environment setup //
// //
///////////////////////////////////////////////////////////////////////////////
aalError aalSetEnvironmentRolloffFactor(const aalSLong & e_id, const aalFloat & factor)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (_env.IsNotValid(e_id))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_env[e_id]->SetRolloffFactor(factor);
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Listener settings //
// //
///////////////////////////////////////////////////////////////////////////////
aalError aalSetListenerUnitFactor(const aalFloat & factor)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (!listener)
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_INIT;
}
if (listener->SetDistanceFactor(factor, DS3D_DEFERRED))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_SYSTEM;
}
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalSetListenerRolloffFactor(const aalFloat & factor)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (!listener)
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_INIT;
}
if (listener->SetRolloffFactor(factor, DS3D_DEFERRED))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_SYSTEM;
}
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalSetListenerPosition(const aalVector & position)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (!listener)
{
return AAL_ERROR_INIT;
}
if (listener->SetPosition(position.x, position.y, position.z, DS3D_DEFERRED))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_SYSTEM;
}
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalSetListenerDirection(const aalVector & front, const aalVector & up)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (!listener)
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_INIT;
}
if (listener->SetOrientation(front.x, front.y, front.z, up.x, up.y, up.z, DS3D_DEFERRED))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_SYSTEM;
}
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalSetListenerEnvironment(const aalSLong & e_id)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (!environment)
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_INIT;
}
if (_env.IsNotValid(e_id))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
if (_env.IsValid(environment_id)) _env[environment_id]->lpksps = NULL;
environment_id = e_id;
_env[environment_id]->lpksps = environment;
Environment * env = _env[environment_id];
EAXLISTENERPROPERTIES props;
props.dwEnvironment = 0;
props.dwFlags = EAXLISTENERFLAGS_DECAYHFLIMIT;
props.flRoomRolloffFactor = 1.0F;
props.lRoom = 0;
props.lRoomHF = 0;
props.flEnvironmentSize = env->size;
props.flEnvironmentDiffusion = env->diffusion;
props.flAirAbsorptionHF = env->absorption * -100.0F;
if (env->reverb_volume <= 0.0F) props.lReverb = -10000;
else if (env->reverb_volume >= 10.0F) props.lReverb = 2000;
else props.lReverb = aalSLong(2000 * log10(env->reverb_volume));
if (env->reverb_delay >= 100.0F) props.flReverbDelay = 0.1F;
else props.flReverbDelay = aalFloat(env->reverb_delay) * 0.001F;
if (env->reverb_decay <= 100.0F) props.flDecayTime = 0.1F;
else if (env->reverb_decay >= 20000.0F) props.flDecayTime = 20.0F;
else props.flDecayTime = aalFloat(env->reverb_decay) * 0.001F;
props.flDecayHFRatio = env->reverb_hf_decay / env->reverb_decay;
if (props.flDecayHFRatio <= 0.1F) props.flDecayHFRatio = 0.1F;
else if (props.flDecayHFRatio >= 2.0F) props.flDecayHFRatio = 2.0F;
if (env->reflect_volume <= 0.0F) props.lReflections = -10000;
else if (env->reflect_volume >= 3.162F) props.lReflections = 1000;
else props.lReflections = aalSLong(2000 * log10(env->reflect_volume));
if (env->reflect_delay >= 300.0F) props.flReflectionsDelay = 0.3F;
else props.flReflectionsDelay = aalFloat(env->reflect_delay) * 0.001F;
if (environment->Set(DSPROPSETID_EAX_ListenerProperties,
DSPROPERTY_EAXLISTENER_ALLPARAMETERS | DSPROPERTY_EAXLISTENER_DEFERRED,
NULL, 0, &props, sizeof(EAXLISTENERPROPERTIES)))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_SYSTEM;
}
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Mixer setup //
// //
///////////////////////////////////////////////////////////////////////////////
aalError aalSetMixerVolume(const aalSLong & m_id, const aalFloat & volume)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (_mixer.IsNotValid(m_id))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_mixer[m_id]->SetVolume(volume);
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalSetMixerParent(const aalSLong & m_id, const aalSLong & pm_id)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (m_id == pm_id || _mixer.IsNotValid(m_id) || _mixer.IsNotValid(pm_id))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_mixer[m_id]->SetParent(_mixer[pm_id]);
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Mixer status //
// //
///////////////////////////////////////////////////////////////////////////////
aalError aalGetMixerVolume(const aalSLong & m_id, aalFloat * volume)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
{
*volume = AAL_DEFAULT_VOLUME;
return AAL_ERROR_TIMEOUT;
}
if (_mixer.IsNotValid(m_id))
{
*volume = AAL_DEFAULT_VOLUME;
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_mixer[m_id]->GetVolume(*volume);
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Mixer control //
// //
///////////////////////////////////////////////////////////////////////////////
aalError aalMixerStop(const aalSLong & m_id)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (_mixer.IsNotValid(m_id))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_mixer[m_id]->Stop();
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalMixerPause(const aalSLong & m_id)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (_mixer.IsNotValid(m_id))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_mixer[m_id]->Pause();
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalMixerResume(const aalSLong & m_id)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (_mixer.IsNotValid(m_id))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_mixer[m_id]->Resume();
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Sample setup //
// //
///////////////////////////////////////////////////////////////////////////////
aalError aalSetSampleVolume(const aalSLong & sample_id, const aalFloat & volume)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
aalSLong s_id(GetSampleID(sample_id));
aalSLong i_id(GetInstanceID(sample_id));
if (_sample.IsNotValid(s_id) || _inst.IsNotValid(i_id) || _inst[i_id]->sample != _sample[s_id])
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_inst[i_id]->SetVolume(volume);
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalSetSamplePitch(const aalSLong & sample_id, const aalFloat & pitch)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
aalSLong s_id(GetSampleID(sample_id));
aalSLong i_id(GetInstanceID(sample_id));
if (_sample.IsNotValid(s_id) || _inst.IsNotValid(i_id) || _inst[i_id]->sample != _sample[s_id])
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_inst[i_id]->SetPitch(pitch);
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalSetSamplePosition(const aalSLong & sample_id, const aalVector & position)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
aalSLong s_id(GetSampleID(sample_id));
aalSLong i_id(GetInstanceID(sample_id));
if (_sample.IsNotValid(s_id) || _inst.IsNotValid(i_id) || _inst[i_id]->sample != _sample[s_id])
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_inst[i_id]->SetPosition(position);
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Sample status //
// //
///////////////////////////////////////////////////////////////////////////////
aalError aalGetSampleName(const aalSLong & s_id, char * name, const aalULong & max_char)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
{
*name = 0;
return AAL_ERROR_TIMEOUT;
}
if (_sample.IsNotValid(GetSampleID(s_id)))
{
*name = 0;
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_sample[GetSampleID(s_id)]->GetName(name, max_char);
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalGetSampleLength(const aalSLong & s_id, aalULong & _length, const aalUnit & unit)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
{
_length = 0;
return AAL_ERROR_TIMEOUT;
}
if (_sample.IsNotValid(GetSampleID(s_id)))
{
_length = 0;
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_sample[GetSampleID(s_id)]->GetLength(_length, unit);
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalUBool aalIsSamplePlaying(const aalSLong & sample_id)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_UFALSE;
aalSLong s_id(GetSampleID(sample_id));
aalSLong i_id(GetInstanceID(sample_id));
if (_sample.IsNotValid(s_id) || _inst.IsNotValid(i_id) || _inst[i_id]->sample != _sample[s_id])
{
if (mutex) ReleaseMutex(mutex);
return AAL_UFALSE;
}
aalUBool status(_inst[i_id]->IsPlaying());
if (mutex) ReleaseMutex(mutex);
return status;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Sample control //
// //
///////////////////////////////////////////////////////////////////////////////
aalError aalSamplePlay(aalSLong & sample_id, const aalChannel & channel, const aalULong & play_count)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
aalSLong s_id(GetSampleID(sample_id));
sample_id = s_id;
if (_sample.IsNotValid(s_id) || _mixer.IsNotValid(channel.mixer))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
aalSLong i_id(GetInstanceID(sample_id));
Instance * instance = NULL;
if (_inst.IsValid(i_id) && _inst[i_id]->sample == _sample[s_id] &&
!(channel.flags ^ _inst[i_id]->channel.flags))
{
instance = _inst[i_id];
if (channel.flags & AAL_FLAG_RESTART)
{
instance->Stop();
}
else if (channel.flags & AAL_FLAG_ENQUEUE && instance->channel.flags == channel.flags)
{
instance->Play(play_count);
}
else if (instance->IsIdled())
{
instance->channel.mixer = channel.mixer;
instance->channel.environment = channel.environment;
instance->SetVolume(channel.volume);
instance->SetPitch(channel.pitch);
instance->SetPan(channel.pan);
instance->SetPosition(channel.position);
instance->SetVelocity(channel.velocity);
instance->SetDirection(channel.direction);
instance->SetCone(channel.cone);
instance->SetFalloff(channel.falloff);
}
else instance = NULL;
}
if (!instance)
{
Sample * sample = _sample[s_id];
aalULong i(0);
for (; i < _inst.Size(); i++)
{
if (_inst[i] && _inst[i]->sample == sample)
break;
}
instance = new Instance;
if ((i < _inst.Size() ? instance->Init(_inst[i], channel) : instance->Init(_sample[s_id], channel)) ||
(i_id = _inst.Add(instance)) == AAL_SFALSE)
{
delete instance;
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_SYSTEM;
}
}
if (listener && channel.flags & FLAG_ANY_3D_FX) listener->CommitDeferredSettings();
if (instance->Play(play_count))
{
_inst.Delete(i_id);
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_SYSTEM;
}
sample_id = instance->id = (i_id << 16) | s_id;
if (channel.flags & AAL_FLAG_AUTOFREE) _sample[s_id]->Release();
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalSampleStop(aalSLong & s_id)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (_sample.IsNotValid(GetSampleID(s_id)) || _inst.IsNotValid(GetInstanceID(s_id)))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_inst[GetInstanceID(s_id)]->Stop();
s_id |= 0xffff0000;
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Track setup //
// //
///////////////////////////////////////////////////////////////////////////////
aalError aalMuteAmbianceTrack(const aalSLong & a_id, const aalSLong & t_id, const aalUBool & mute)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (_amb.IsNotValid(a_id))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_amb[a_id]->MuteTrack(t_id, mute);
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Ambiance setup //
// //
///////////////////////////////////////////////////////////////////////////////
aalError aalSetAmbianceUserData(const aalSLong & a_id, aalVoid * data)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (_amb.IsNotValid(a_id))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_amb[a_id]->SetUserData(data);
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalSetAmbianceVolume(const aalSLong & a_id, const aalFloat & volume)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (_amb.IsNotValid(a_id))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_amb[a_id]->SetVolume(volume);
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Ambiance status //
// //
///////////////////////////////////////////////////////////////////////////////
aalError aalGetAmbianceName(const aalSLong & a_id, char * name, const aalULong & max_char)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
{
*name = 0;
return AAL_ERROR_TIMEOUT;
}
if (_amb.IsNotValid(a_id))
{
*name = 0;
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_amb[a_id]->GetName(name, max_char);
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalGetAmbianceUserData(const aalSLong & a_id, aalVoid ** data)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (_amb.IsNotValid(a_id))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_amb[a_id]->GetUserData(data);
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalGetAmbianceTrackID(const aalSLong & a_id, const char * name, aalSLong & _t_id)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
{
_t_id = AAL_SFALSE;
return AAL_ERROR_TIMEOUT;
}
if (_amb.IsNotValid(a_id))
{
_t_id = AAL_SFALSE;
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_amb[a_id]->GetTrackID(name, _t_id);
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalGetAmbianceVolume(const aalSLong & a_id, aalFloat & _volume)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
{
_volume = AAL_DEFAULT_VOLUME;
return AAL_ERROR_TIMEOUT;
}
if (_amb.IsNotValid(a_id))
{
_volume = AAL_DEFAULT_VOLUME;
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_amb[a_id]->GetVolume(_volume);
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
AAL_APIFUNC aalUBool aalIsAmbianceLooped(const aalSLong & a_id)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_UFALSE;
if (_amb.IsNotValid(a_id))
{
if (mutex) ReleaseMutex(mutex);
return AAL_UFALSE;
}
aalUBool status(_amb[a_id]->IsLooped());
if (mutex) ReleaseMutex(mutex);
return status;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Ambiance control //
// //
///////////////////////////////////////////////////////////////////////////////
aalError aalAmbiancePlay(const aalSLong & a_id, const aalChannel & channel, const aalULong & play_count, const aalULong & fade_interval)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (_amb.IsNotValid(a_id) || _mixer.IsNotValid(channel.mixer))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_amb[a_id]->Play(channel, play_count, fade_interval);
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
aalError aalAmbianceStop(const aalSLong & a_id, const aalULong & fade_interval)
{
if (mutex && WaitForSingleObject(mutex, MUTEX_TIMEOUT) == WAIT_TIMEOUT)
return AAL_ERROR_TIMEOUT;
if (_amb.IsNotValid(a_id))
{
if (mutex) ReleaseMutex(mutex);
return AAL_ERROR_HANDLE;
}
_amb[a_id]->Stop(fade_interval);
if (mutex) ReleaseMutex(mutex);
return AAL_OK;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Misc //
// //
///////////////////////////////////////////////////////////////////////////////
static aalError EnableEnvironmentalAudio()
{
WAVEFORMATEX formatex;
DSBUFFERDESC desc;
LPDIRECTSOUNDBUFFER lpdsbtmp(NULL);
LPDIRECTSOUND3DBUFFER lpds3dbtmp(NULL);
memset(&formatex, 0, sizeof(WAVEFORMATEX));
formatex.wFormatTag = WAVE_FORMAT_PCM;
formatex.nChannels = (aalUWord)(global_format.channels);
formatex.nSamplesPerSec = global_format.frequency;
formatex.wBitsPerSample = (aalUWord)(global_format.quality);
formatex.nBlockAlign = (aalUWord)(global_format.channels * global_format.quality / 8);
formatex.nAvgBytesPerSec = formatex.nBlockAlign * global_format.frequency;
memset(&desc, 0, sizeof(DSBUFFERDESC));
desc.dwSize = sizeof(DSBUFFERDESC);
desc.dwBufferBytes = 10000;
desc.dwFlags = DSBCAPS_CTRL3D;
desc.lpwfxFormat = &formatex;
if (device->CreateSoundBuffer(&desc, &lpdsbtmp, NULL) ||
lpdsbtmp->QueryInterface(IID_IDirectSound3DBuffer, (aalVoid **)&lpds3dbtmp) ||
lpds3dbtmp->QueryInterface(IID_IKsPropertySet, (aalVoid **)&environment))
{
if (lpdsbtmp) lpdsbtmp->Release();
if (lpds3dbtmp) lpds3dbtmp->Release();
return AAL_ERROR_SYSTEM;
}
lpdsbtmp->Release();
lpds3dbtmp->Release();
aalULong support(0);
if (environment->QuerySupport(DSPROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ALLPARAMETERS, &support) ||
((support & (KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET)) != (KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET)))
{
environment->Release(), environment = NULL;
return AAL_ERROR_SYSTEM;
}
if (environment->QuerySupport(DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_ALLPARAMETERS, &support) ||
((support & (KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET)) != (KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET)))
{
environment->Release(), environment = NULL;
return AAL_ERROR_SYSTEM;
}
EAXLISTENERPROPERTIES props;
props.dwEnvironment = 0;
props.dwFlags = EAXLISTENERFLAGS_DECAYHFLIMIT;
props.flRoomRolloffFactor = 1.0F;
props.lRoom = 0;
props.lRoomHF = 0;
props.flEnvironmentSize = AAL_DEFAULT_ENVIRONMENT_SIZE;
props.flEnvironmentDiffusion = AAL_DEFAULT_ENVIRONMENT_DIFFUSION;
props.flAirAbsorptionHF = AAL_DEFAULT_ENVIRONMENT_ABSORPTION * -100.0F;
props.lReflections = aalSLong(2000 * log10(AAL_DEFAULT_ENVIRONMENT_REFLECTION_VOLUME));
props.flReflectionsDelay = aalFloat(AAL_DEFAULT_ENVIRONMENT_REFLECTION_DELAY) * 0.001F;
props.lReverb = aalSLong(2000 * log10(AAL_DEFAULT_ENVIRONMENT_REVERBERATION_VOLUME));
props.flReverbDelay = aalFloat(AAL_DEFAULT_ENVIRONMENT_REVERBERATION_DELAY) * 0.001F;
props.flDecayTime = aalFloat(AAL_DEFAULT_ENVIRONMENT_REVERBERATION_DECAY) * 0.001F;
props.flDecayHFRatio = AAL_DEFAULT_ENVIRONMENT_REVERBERATION_HFDECAY / AAL_DEFAULT_ENVIRONMENT_REVERBERATION_DECAY;
if (environment->Set(DSPROPSETID_EAX_ListenerProperties,
DSPROPERTY_EAXLISTENER_ALLPARAMETERS | DSPROPERTY_EAXLISTENER_DEFERRED,
NULL, 0, &props, sizeof(EAXLISTENERPROPERTIES)))
{
environment->Release(), environment = NULL;
return AAL_ERROR_SYSTEM;
}
return AAL_OK;
}
}//ATHENA::