diff --git a/sndlib/ds3dgeometry.cpp b/sndlib/ds3dgeometry.cpp deleted file mode 100644 index 57098f86..00000000 --- a/sndlib/ds3dgeometry.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* This program 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. -* -* This program 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 this program. If not, see . - ---- HISTORICAL COMMENTS FOLLOW --- - - * $Source: $ - * $Revision: 8 $ - * $Author: Jeff $ - * $Date: 10/21/99 9:28p $ - * - * Hardware occlusion and reflection sound support - * - * $Log: /DescentIII/Main/dd_sndlib/geometry.cpp $ - * - * 8 10/21/99 9:28p Jeff - * B.A. Macintosh code merge - * - * 7 8/13/99 2:00p Samir - * more aureal and geometry fixes. - * - * 6 8/11/99 3:12p Samir - * fixes for aureal support. - * - * 5 4/13/99 4:09p Samir - * more priority stuff. - * - * 4 4/06/99 8:30p Samir - * added reflection support. - * - * 3 3/30/99 5:36p Matt - * Fixed compile warnings - * - * 2 3/29/99 10:52a Samir - * occlusion support almost complete. - * - */ - -#include "ds3dlib_internal.h" -#include "auddev.h" -#include "pserror.h" - -////////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////////// -llsGeometry::llsGeometry() { - m_snd_system = NULL; - m_snd_mixer = SOUND_MIXER_NONE; - m_lib_init = false; -} - -// specify a sound library to associate geometry with -bool llsGeometry::Init(llsSystem *snd_sys) { - int i; - - if (m_lib_init) { - Int3(); // really, this shouldn't happen. - return true; - } - if (!snd_sys) { - Int3(); - return false; - } - - if (!m_lib_init) { - mprintf(0, "DDSNDGEO: Failed to initialize geometry interface.\n"); - return false; - } - - m_snd_mixer = snd_sys->GetSoundMixer(); - - m_snd_system = snd_sys; - m_lib_init = true; - - // create material list. - for (i = 0; i < SNDGEO_MATERIAL_COUNT; i++) { - m_snd_materials[i] = NULL; - } - - CreateMaterial(SNDGEO_MATERIAL_ROCK, 0.2f, 0.5f, 0.9f, 0.8f); - CreateMaterial(SNDGEO_MATERIAL_WATER, 1.0f, 0.3f, 0.8f, 0.7f); - CreateMaterial(SNDGEO_MATERIAL_METAL, 0.1f, 0.1f, 0.95f, 0.85f); - - mprintf(0, "DDSNDGEO: Initialized.\n"); - return true; -} - -// closes low level geometry system. -void llsGeometry::Shutdown() { - int i; - - if (!m_lib_init) { // damn this shouldn't happen. - Int3(); - return; - } - - // destroy materials list - for (i = 0; i < SNDGEO_MATERIAL_COUNT; i++) { - DestroyMaterial(i); - } - - m_snd_mixer = SOUND_MIXER_NONE; - m_snd_system = NULL; - m_lib_init = false; - - mprintf(0, "DDSNDGEO: Shutdown.\n"); -} - -void llsGeometry::StartFrame() { - n_primatives_used = 0; - n_reflections_used = 0; - n_materials_used = 0; -} - -void llsGeometry::EndFrame() { - mprintf_at(3, 4, 20, "sndpoly=%04d", n_primatives_used); - mprintf_at(3, 4, 38, "sndmat=%04d", n_materials_used); - mprintf_at(3, 5, 20, "sndref=%04d", n_reflections_used); -} - -// polygon lists - -// marks beginning of a list of polygons to render -// -1 group if non cached (user doesn't want to reuse this. -void llsGeometry::StartPolygonGroup(int group) { - ASSERT(m_lib_init); -} - -// ends a list of polygons to render. -void llsGeometry::EndPolygonGroup(int group) { - ASSERT(m_lib_init); -} - -// renders a group. -void llsGeometry::RenderGroup(int group) { - ASSERT(m_lib_init); -} - -void llsGeometry::Clear() { - ASSERT(m_lib_init); -} - -// primatives -// 4 verts here. -void llsGeometry::AddQuad(unsigned tag, vector **verts) { - n_primatives_used++; -} - -// 3 verts here. -void llsGeometry::AddTriangle(unsigned tag, vector **verts) { - n_primatives_used++; -} - -void llsGeometry::AddPoly(int nv, vector **verts, unsigned tag, tSoundMaterial material) { - int i, saved_primatives_used; //,p; - void *matp = NULL; - - if (nv < 3) { - Int3(); - return; - } - - if (material >= 0 && material < SNDGEO_MATERIAL_COUNT) { - matp = m_snd_materials[material]; - } - - if (matp) { - n_materials_used++; - } - saved_primatives_used = n_primatives_used; - - // add polygons or split. - switch (nv) { - case 3: - AddTriangle(tag, verts); - break; - case 4: - AddQuad(tag, verts); - break; - default: - Int3(); - } - - if (matp) { - n_reflections_used += (n_primatives_used - saved_primatives_used); - } -} - -// values MUST be from 0 to 1 for gain and highfreq. -void llsGeometry::CreateMaterial(tSoundMaterial material, float transmit_gain, float transmit_highfreq, - float reflect_gain, float reflect_highfreq) { - if (m_snd_materials[material] || material < 0 || material >= SNDGEO_MATERIAL_COUNT) { - Int3(); // get samir, trying to intiialize a material in an existing slot. - return; - } - - // check values. - if (transmit_gain < 0) { - transmit_gain = 0; - } else if (transmit_gain > 1) { - transmit_gain = 1; - } - if (transmit_highfreq < 0) { - transmit_highfreq = 0; - } else if (transmit_highfreq > 1) { - transmit_highfreq = 1; - } - if (reflect_gain < 0) { - reflect_gain = 0; - } else if (reflect_gain > 1) { - reflect_gain = 1; - } - if (reflect_highfreq < 0) { - reflect_highfreq = 0; - } else if (reflect_highfreq > 1) { - reflect_highfreq = 1; - } -} - -void llsGeometry::DestroyMaterial(tSoundMaterial material) { - if (!m_snd_materials[material]) { - if (material < 0 || material >= SNDGEO_MATERIAL_COUNT) { - Int3(); // get samir, trying to destroy a material in an nonexisting slot. - } - return; - } - - if (m_snd_materials[material]) { - m_snd_materials[material] = NULL; - } -} diff --git a/sndlib/ds3dlib.cpp b/sndlib/ds3dlib.cpp deleted file mode 100644 index 7f8e9776..00000000 --- a/sndlib/ds3dlib.cpp +++ /dev/null @@ -1,3312 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* This program 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. -* -* This program 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 this program. If not, see . - ---- HISTORICAL COMMENTS FOLLOW --- - - * $Logfile: /DescentIII/Main/dd_sndlib/Ds3dlib.cpp $ - * $Revision: 149 $ - * $Date: 9/27/99 5:38p $ - * $Author: Samir $ - * - * DirectSound(2d and 3d) implementation of the Descent III low-level sound interface - * - * $Log: /DescentIII/Main/dd_sndlib/Ds3dlib.cpp $ - * - * 149 9/27/99 5:38p Samir - * EAX 2.0->1.0 compatibility checkin. - * - * 148 8/23/99 5:29p Samir - * incremental EAX 2.0 checkin - * - * 147 8/13/99 2:00p Samir - * more aureal and geometry fixes. - * - * 146 5/23/99 12:48a Samir - * decreased rolloff factor of 3d sounds under 3d sound mixers from 0.75 - * to 0.5 - * - * 145 5/20/99 6:23p Kevin - * minor speed up of software mixer and fix for memory debugging - * - * 144 5/20/99 1:00a Samir - * changes in ordering of EAX and NONE mixers. - * - * 143 5/09/99 7:09p Samir - * fixed sound card selection (enumeration) problems. - * - * 142 5/07/99 5:39p Samir - * better error checking for CheckAndForceDataAlloc for PageInSound. - * - * 141 5/03/99 3:12a Samir - * fixed up aureal so it works (a little slow though...) - * - * 140 5/01/99 10:25p Jeff - * (samir) fixed crash bug when alt-tabbing,inserting cds,etc - * - * 139 4/29/99 4:36p Kevin - * fixed a problem with low quality sounds & the optimizd software mixer - * - * 138 4/29/99 3:01p Samir - * added code for direct sound mixers only (and function for Aureal - * really) that will use direct sound looping for simple loops. - * - * 137 4/27/99 7:08p Kevin - * optimized software mixer! - * - * 136 4/27/99 6:21p Samir - * if callback gets a NULL guid, just return, assume that the sound device - * is the default? - * - * 135 4/27/99 5:19p Samir - * mprintf change. - * - * 134 4/27/99 2:10p Samir - * added code to set the desired sound card given the descriptive name of - * a sound card. - * - * 133 4/25/99 9:52p Samir - * fixed looping sequencing bug with thread for direct sound mixers. - * SSF_PLAY_LOOPING must be set before any buffer filling occurs, - * otherwise bad things happen with very small loops.... - * - * 132 4/23/99 7:51p Samir - * looping fixes for directsound - * - * 131 4/22/99 10:33p Samir - * modifications so that DirectSound mixers use one thread for all looping - * and streaming sounds. It worked without crashing for about twenty - * minutes of playing from level 1 to level 2 of D3. We'll see. - * - * 130 4/18/99 5:37p Kevin - * Very simple optimization for the software mixer - * - * 129 4/13/99 4:15p Jason - * took out register keyword because it was hurting performance - * - * 128 4/13/99 4:09p Samir - * more priority stuff. - * - * - * 126 4/12/99 7:14p Samir - * prioritization code added. - * - * 125 4/10/99 5:08p Samir - * took out obsolete data from play_information structure that should save - * around 70 bytes per instance. - * - * 124 4/09/99 5:00p Kevin - * put the memset in -- memset should be doing at least 32 bit copies, - * which is FAR better than a for loop. - * - * 123 4/09/99 12:03p Samir - * took out windows.h again, this time made HWND a void pointer, and - * checked under both editor and main projects. - * - * 122 4/06/99 8:29p Samir - * added error check system. - * - * 121 3/29/99 11:00a Samir - * added system to support different 3d sound options. - * - * 120 3/17/99 4:20p Samir - * added functions to pause and resume individual sounds. - * - * 119 3/04/99 1:23p Kevin - * Fixed Poping sound!!! - * - * 118 3/03/99 6:53p Matt - * Fixed compile warning - * - * 117 3/03/99 3:12p Chris - * Fixed volume problems - * - * 116 3/01/99 8:12p Samir - * pause sounds when switching sound quality! - * - * 115 2/25/99 4:50p Kevin - * Semi-hack to fix the problem with music looping and stuttering in DS - * - * 114 2/24/99 3:15p Kevin - * OEM menu changes, and bug fixes for the save/load system - * - * 113 2/22/99 6:28p Kevin - * Fixed a bug that was introduced (?) when the thread problem was fixed. - * - * 112 2/20/99 1:14a Kevin - * Fixed another bug - * - * 111 2/19/99 10:45p Kevin - * Fixed bug I just introduced... - * - * 110 2/19/99 5:21p Kevin - * Fixed some connection DLLs and a Direct Sound bug with threads. - * - * 109 2/11/99 3:30p Doug - * error checking in PlaySoundBuffer. - * - * 108 2/04/99 9:46a Kevin - * OEM version changes - * - * 107 1/14/99 6:10p Samir - * added DirectSound buffer duplication code. - * - * 106 1/11/99 5:51p Samir - * reverb on the buffer level. - * - * 105 1/08/99 6:31p Samir - * added reverb - * - * 104 1/08/99 11:36a Samir - * implemented basic Aureal 2.0 support. - * - * 103 1/08/99 10:32a Chris - * - * 102 12/23/98 11:49a Samir - * reorganized code so it works with different APIs. - * - * 101 12/11/98 5:21p Samir - * (chris) fixed problem with software streaming audio. - * - * 100 12/10/98 3:16p Chris - * added mprintfs for later use - * - * 99 12/10/98 2:18p Chris - * Added more asserts to the streaming code - * - * 98 11/13/98 4:55p Nate - * don't do dedicated server check in lowlevel. - * - * 97 11/13/98 12:17p Chris - * - * 96 11/12/98 12:15p Chris - * Fixed a bug with streaming mixers - * - * 95 10/30/98 1:20p Chris - * Fixed a m_unique_id bug where it was being used before it was being - * assigned - * - * - * $NoKeywords: $ - */ - -#include "ds3dlib_internal.h" - -#include -#include -#include -#include "cfile.h" -#include "pserror.h" -#include "mono.h" -#include "soundload.h" -#include "mem.h" -#include "application.h" -#include "auddev.h" -#include "Macros.h" -#include "ddio.h" - -// Hacked window handle -- chrishack -static oeWin32Application *SoundApp = NULL; -static void *GameWindowHandle; -#define MIN_SOUND_MIX_VOLUME 0.0 -#define MAX_WRITE_AHEAD .04 // Seconds to write ahead of the play position (in seconds) - -// write position - -#define IS_3D_MIXER(_type) ((_type) >= SOUND_MIXER_DS3D_16 && (_type) != SOUND_MIXER_NONE) - -win_llsSystem *ll_sound_ptr; -emulated_listener *g_emulated_listener = NULL; // silly hack (Samir) -int16_t Global_DS_alloced_sounds = 0; - -int *Fast_mixer = NULL; -int Fast_mixer_len = 0; - -#define VOLUME_FIX_BITS 1024 - -// Streaming primary buffer information -DSSTREAM m_sb_info; -char m_sound_device_name[256] = ""; // set by set sound card - -// Loads a sound buffer with data -HRESULT LoadSoundData(LPDIRECTSOUNDBUFFER lp_dsb, char *sound_data_ptr, DWORD total_bytes); - -/////////////////////////////////////////////////////////////////////////////// - -static t3dEnvironmentValues Env3dValues; -static t3dEnvironmentToggles Env3dToggles; - -#define ENV3DTOG_DOPPLER true -#define ENV3DTOG_GEOMETRY true - -#define ENV3DVAL_DOPPLER_DEFAULT 0.5f -#define ENV3DVAL_ROLLOFF_DEFAULT 0.5f - -/////////////////////////////////////////////////////////////////////////////// - -win_llsSystem::win_llsSystem(void) : llsSystem() { - m_lp_ds = NULL; - m_f_sound_lib_init = 0; - m_hwnd_main = NULL; - m_mixer_type = -1; - m_sound_quality = SQT_NORMAL; - m_cache_stress_timer = 0.0f; - ll_sound_ptr = NULL; - m_timer_last_frametime = -1; - memset(&Env3dValues, 0, sizeof(Env3dValues)); - memset(&Env3dToggles, 0, sizeof(Env3dToggles)); - SetError(SSL_OK); -} - -win_llsSystem::~win_llsSystem(void) { - DestroySoundLib(); - SetSoundCard(NULL); -} - -inline void opti_8m_mix(uint8_t *cur_sample_8bit, const int num_write, int &samples_played, int *mixer_buffer16, - const float l_volume, const float r_volume) { - int i; - int *mb = mixer_buffer16; - - const int fix_rvol = r_volume * VOLUME_FIX_BITS; - const int fix_lvol = l_volume * VOLUME_FIX_BITS; - - for (i = 0; i < (num_write << 1); i += 2) { - int sample; - int l_sample; - int r_sample; - - sample = (((*cur_sample_8bit)) - 128) << 8; - cur_sample_8bit++; - - l_sample = *mb + (sample * fix_lvol); - r_sample = *(mb + 1) + (sample * fix_rvol); - - *mb = l_sample; - mb++; - *mb = r_sample; - mb++; - } - samples_played += (i / 2); -} - -inline void opti_8s_mix(uint8_t *cur_sample_8bit, const int num_write, int &samples_played, int *mixer_buffer16, - const float l_volume, const float r_volume) { - int i; - int *mb = mixer_buffer16; - - const int fix_rvol = r_volume * VOLUME_FIX_BITS; - const int fix_lvol = l_volume * VOLUME_FIX_BITS; - - for (i = 0; i < (num_write << 1); i += 2) { - int lsample; - int rsample; - int l_sample; - int r_sample; - - lsample = (((*cur_sample_8bit)) - 128) << 8; - cur_sample_8bit++; - rsample = (((*cur_sample_8bit)) - 128) << 8; - cur_sample_8bit++; - - l_sample = *mb + (lsample * fix_lvol); - r_sample = *(mb + 1) + (rsample * fix_rvol); - - *mb = l_sample; - mb++; - *mb = r_sample; - mb++; - } - samples_played += (i / 2); -} - -inline void opti_16m_mix(int16_t *cur_sample_16bit, const int num_write, int &samples_played, int *mixer_buffer16, - const float l_volume, const float r_volume) { - int i; - int *mb = mixer_buffer16; - - const int fix_rvol = r_volume * VOLUME_FIX_BITS; - const int fix_lvol = l_volume * VOLUME_FIX_BITS; - - for (i = 0; i < (num_write << 1); i += 2) { - int sample; - int l_sample; - int r_sample; - - sample = *cur_sample_16bit; - cur_sample_16bit++; - - l_sample = *mb + (sample * fix_lvol); - r_sample = *(mb + 1) + (sample * fix_rvol); - - *mb = l_sample; - mb++; - *mb = r_sample; - mb++; - } - samples_played += (i / 2); -} - -inline void opti_16s_mix(int16_t *cur_sample_16bit, const int num_write, int &samples_played, int *mixer_buffer16, - const float l_volume, const float r_volume) { - int i; - int *mb = mixer_buffer16; - - const int fix_rvol = r_volume * VOLUME_FIX_BITS; - const int fix_lvol = l_volume * VOLUME_FIX_BITS; - - for (i = 0; i < (num_write << 1); i += 2) { - int lsample; - int rsample; - int l_sample; - int r_sample; - - lsample = *cur_sample_16bit; - cur_sample_16bit++; - rsample = *cur_sample_16bit; - cur_sample_16bit++; - - l_sample = *mb + (lsample * fix_lvol); - r_sample = *(mb + 1) + (rsample * fix_rvol); - - *mb = l_sample; - mb++; - *mb = r_sample; - *mb++; - } - samples_played += (i / 2); -} - -//////////////////////////////////////////////////////////////////////////////////// - -#define MAX_DS_PAN 1000.0f - -int GamePanToDsPan(float pan) { - int ds_pan; - ds_pan = (int)(pan * MAX_DS_PAN); - - if (ds_pan > MAX_DS_PAN) - ds_pan = MAX_DS_PAN; - if (ds_pan < -MAX_DS_PAN) - ds_pan = -MAX_DS_PAN; - - // mprintf(0, "P %f %d\n", pan, ds_pan); - return ds_pan; -} - -int GameVolumeToDsAttenuation(float volume) { - float fvol; - - if (volume <= 0.0f) { - fvol = 2000.0f; - } else { - fvol = logf(volume) / logf(10.0f); - fvol *= 2000.0; - } - - if (volume <= 0.01f) { - fvol = DSBVOLUME_MIN; - } - - // mprintf(0, "V %f %f\n", volume, fvol); - return (int)fvol; -} - -//////////////////////////////////////////////////////////////////////////////////// - -inline char *get_sound_info(sound_buffer_info *sb, int *length, bool *f16bit) { - if (sb->m_sound_index < 0) { - if (sb->s) { - *f16bit = sb->s->f_sample_16bit; - } - return NULL; - } - if (SoundFiles[Sounds[sb->m_sound_index].sample_index].sample_8bit) { - *length = SoundFiles[Sounds[sb->m_sound_index].sample_index].np_sample_length; - *f16bit = false; - return (char *)SoundFiles[Sounds[sb->m_sound_index].sample_index].sample_8bit; - } else { - ASSERT(SoundFiles[Sounds[sb->m_sound_index].sample_index].sample_16bit); - *f16bit = true; - *length = SoundFiles[Sounds[sb->m_sound_index].sample_index].np_sample_length * 2; - return (char *)SoundFiles[Sounds[sb->m_sound_index].sample_index].sample_16bit; - } -} - -////////////////////////////////////////////////////////////////////////////////// -#define SB_STATUS_PLAYING 0x1 -#define SB_STATUS_INVALID 0x2 - -inline int sb_get_status(sound_buffer_info *sb) { - int retflags = 0; - - if (sb->m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - LPDIRECTSOUNDBUFFER sound_ptr = sb->m_sound_buffer; - unsigned long status; - - if (sound_ptr) { - sound_ptr->GetStatus(&status); - if (status & DSBSTATUS_PLAYING) - retflags |= SB_STATUS_PLAYING; - } else { - retflags |= SB_STATUS_INVALID; - } - } - - return retflags; -} - -inline void sb_adjust_properties_3d(sound_buffer_info *sb, float f_volume, pos_state *pos, float reverb) { - if (!ll_sound_ptr->m_in_sound_frame) - ll_sound_ptr->m_pending_actions = true; - - sb->m_volume = f_volume; - - if (IS_3D_MIXER(sb->m_mixer_type)) { - LPDIRECTSOUNDBUFFER lp_dsb = sb->m_sound_buffer; - LPDIRECTSOUND3DBUFFER lpDSB3D = sb->m_sound_buffer_3d; - - lp_dsb->SetVolume(GameVolumeToDsAttenuation(f_volume)); - - ASSERT(lpDSB3D != NULL); - - if (sb->m_mixer_type == SOUND_MIXER_CREATIVE_EAX) { - lpDSB3D->SetMinDistance(30.0f, DS3D_IMMEDIATE); - } else { - lpDSB3D->SetMinDistance(Sounds[sb->m_sound_index].min_distance, DS3D_IMMEDIATE); - } - lpDSB3D->SetMaxDistance(Sounds[sb->m_sound_index].max_distance, DS3D_IMMEDIATE); - lpDSB3D->SetConeOrientation(pos->orient->fvec.x, pos->orient->fvec.y, pos->orient->fvec.z, DS3D_IMMEDIATE); - lpDSB3D->SetPosition(pos->position->x, pos->position->y, pos->position->z, DS3D_IMMEDIATE); - lpDSB3D->SetVelocity(pos->velocity->x, pos->velocity->y, pos->velocity->z, DS3D_IMMEDIATE); - - // if (sb->m_mixer_type == SOUND_MIXER_CREATIVE_EAX) { - // EAX_SetBufferReverbMix(lpDSB3D, reverb); - // } - } else { - mprintf(0, "m_mixer_type = %d\n", sb->m_mixer_type); - Int3(); - } -} - -inline void sb_adjust_properties_2d(sound_buffer_info *sb, float f_volume, float f_pan, uint16_t frequency) { - if (!ll_sound_ptr->m_in_sound_frame) - ll_sound_ptr->m_pending_actions = true; - - sb->m_volume = f_volume; - - if (sb->m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - LPDIRECTSOUNDBUFFER lpdsb; - - ASSERT(f_pan >= -1.0f && f_pan <= 1.0f); - ASSERT(f_volume >= 0.0f && f_volume <= 1.0f); - - lpdsb = sb->m_sound_buffer; - if (lpdsb == NULL) - return; - - // mprintf(0, "Sound UID %d is now at %d volume,%d pan\n", sound_uid, volume, pan); - - lpdsb->SetVolume(GameVolumeToDsAttenuation(f_volume)); - lpdsb->SetPan(GamePanToDsPan(f_pan)); // chrishack pan is off - lpdsb->SetFrequency(frequency); - } -} - -// functions for different APIs -int sb_get_current_position(sound_buffer_info *sb, uint32_t *writep) { - DWORD playp, wp; - - if (sb->m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - if (sb->m_sound_buffer && sb->m_sound_buffer->GetCurrentPosition(&playp, &wp) == DS_OK) { - *writep = (uint32_t)wp; - } else { - playp = (DWORD)(-1); - *writep = (uint32_t)(-1); - } - } - - return (uint32_t)playp; -} - -inline void sb_set_current_position(sound_buffer_info *sb, uint32_t pos) { - if (!ll_sound_ptr->m_in_sound_frame) - ll_sound_ptr->m_pending_actions = true; - - if (sb->m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - sb->m_sound_buffer->SetCurrentPosition((DWORD)pos); - } -} - -void sb_free_buffer(sound_buffer_info *sb) { - if (!ll_sound_ptr->m_in_sound_frame) - ll_sound_ptr->m_pending_actions = true; - if (!sb->m_sound_buffer) - return; - - if (sb->m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - if (sb->m_mixer_type == SOUND_MIXER_CREATIVE_EAX) { - EAX_FreeSource(sb->m_lpksps); - } - - if (sb->m_sound_buffer) { - sb->m_sound_buffer->Release(); - sb->m_sound_buffer = NULL; - } - if (sb->m_sound_buffer_3d) { - sb->m_sound_buffer_3d->Release(); - sb->m_sound_buffer_3d = NULL; - } - } -} - -void sb_stop_buffer(sound_buffer_info *sb) { - if (!ll_sound_ptr->m_in_sound_frame) - ll_sound_ptr->m_pending_actions = true; - - if (sb->m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - sb->m_sound_buffer->Stop(); - } -} - -bool sb_lock_buffer(sound_buffer_info *sb, uint32_t dwWriteCursor, uint32_t dwWriteBytes, void **lplpvAudioPtr1, - uint32_t *lpdwAudioBytes1, void **lplpvAudioPtr2, uint32_t *lpdwAudioBytes2) { - DWORD len1, len2; - - if (sb->m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - TryLockAgainLabel: - switch (sb->m_sound_buffer->Lock(dwWriteCursor, dwWriteBytes, lplpvAudioPtr1, &len1, lplpvAudioPtr2, &len2, 0)) { - case DS_OK: - *lpdwAudioBytes1 = len1; - *lpdwAudioBytes2 = len2; - return true; - - case DSERR_BUFFERLOST: - if (sb->m_sound_buffer->Restore() == DS_OK) - goto TryLockAgainLabel; - } - - return false; - } - - return false; -} - -bool sb_unlock_buffer(sound_buffer_info *sb, void *ptr1, uint32_t len1, void *ptr2, uint32_t len2) { - if (sb->m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - sb->m_sound_buffer->Unlock(ptr1, len1, ptr2, len2); - return true; - } - - return false; -} - -bool sb_load_buffer(sound_buffer_info *sb, void *sample_data, int length) { - if (!ll_sound_ptr->m_in_sound_frame) - ll_sound_ptr->m_pending_actions = true; - - if (LoadSoundData(sb->m_sound_buffer, (char *)sample_data, length) != DS_OK) { - Int3(); - sb->m_status = SSF_UNUSED; - return false; - } - return true; -} - -/////////////////////////////////////////////////////////////////////////////// - -// The actual mixer code that sum's the sounds on each channel and does all the actual -// mixing and effects (writes data to the locked primary buffer) -void StreamMixer(char *ptr, int len) { - int i; - int16_t *mixer_buffer16 = (int16_t *)ptr; - int current_slot = 0; - bool f_loop; - bool f_mono; - - const int buff_len = len / ll_sound_ptr->m_primary_alignment; - - // this code will assure that this function will not be called when sound system is in error mode. - if (ll_sound_ptr->m_lib_error_code != SSL_OK) { - return; - } - - ASSERT(len <= m_sb_info.BufferSize); - ASSERT(ptr && len >= 0); - - ASSERT((len % ll_sound_ptr->m_primary_alignment) == 0); - - // memset((char *)ptr, 0, len); - - // This memset is hopefully temporary - memset(Fast_mixer, 0, Fast_mixer_len * sizeof(int)); - int *fast_mix_ptr = Fast_mixer; - - // Mix the sound slots - while (current_slot < ll_sound_ptr->m_sound_mixer.m_max_sounds_played) { - sound_buffer_info *cur_buf = &ll_sound_ptr->m_sound_mixer.m_sound_cache[current_slot]; - int num_samples = buff_len; - // mixer_buffer16 = (int16_t *) ptr; - fast_mix_ptr = Fast_mixer; - f_mono = true; - - // Find slots with sounds in them - if ((cur_buf->m_status != SSF_UNUSED) && !(cur_buf->m_status & SSF_PAUSED)) { - float l_volume = cur_buf->play_info->left_volume; - float r_volume = cur_buf->play_info->right_volume; - int skip_interval = cur_buf->play_info->sample_skip_interval; - int samples_played = cur_buf->play_info->m_samples_played; - int16_t *sample_16bit; - uint8_t *sample_8bit; - int np_sample_length; - int sample_length; - int loop_start; - int loop_end; - - if (cur_buf->m_status & SSF_PLAY_STREAMING) { - switch (cur_buf->play_info->m_stream_format) { - case SIF_STREAMING_16_M: - sample_16bit = (int16_t *)cur_buf->play_info->m_stream_data; - sample_8bit = NULL; - np_sample_length = sample_length = cur_buf->play_info->m_stream_size / 2; - break; - case SIF_STREAMING_8_M: - sample_16bit = NULL; - sample_8bit = (uint8_t *)cur_buf->play_info->m_stream_data; - np_sample_length = sample_length = cur_buf->play_info->m_stream_size; - break; - case SIF_STREAMING_16_S: - sample_16bit = (int16_t *)cur_buf->play_info->m_stream_data; - sample_8bit = NULL; - np_sample_length = sample_length = cur_buf->play_info->m_stream_size / 4; - f_mono = false; - break; - case SIF_STREAMING_8_S: - sample_16bit = NULL; - sample_8bit = (uint8_t *)cur_buf->play_info->m_stream_data; - np_sample_length = sample_length = cur_buf->play_info->m_stream_size / 2; - f_mono = false; - break; - default: - Int3(); - break; - } - loop_start = 0; - loop_end = np_sample_length - 1; - } else { - int sound_index = cur_buf->m_sound_index; - int sample_index = Sounds[sound_index].sample_index; - sound_file_info *snd_file = &SoundFiles[sample_index]; - sample_16bit = snd_file->sample_16bit; - sample_8bit = snd_file->sample_8bit; - np_sample_length = snd_file->np_sample_length; - sample_length = snd_file->sample_length; - loop_start = Sounds[sound_index].loop_start; - loop_end = Sounds[sound_index].loop_end; - if (!sample_16bit && !sample_8bit) { - mprintf(0, "sound file %s didn't have data for samples.\n", snd_file->name); - } - } - - // cleanly continue if this happens, and inform a logfile, if it does. error handling - // ASSERT(sample_16bit || sample_8bit); - if (!sample_16bit && !sample_8bit) { - sound_file_info *snd_file = &SoundFiles[Sounds[cur_buf->m_sound_index].sample_index]; - ll_sound_ptr->SetError(SSL_ERROR_SAMPLE_NODATA); - ll_sound_ptr->ErrorText("ASSERT(sample_16bit || sample_8bit)\nNo data found for sound file: %s", - snd_file->name); - cur_buf->m_status = SSF_UNUSED; - goto error_bail; - } - - ASSERT(np_sample_length <= sample_length); - ASSERT(samples_played >= 0 || samples_played <= sample_length); - - int num_write; - - error_trap: - - // We have not looped -- yet - f_loop = false; - - // Verify the volume levels are o.k. - ASSERT(l_volume >= 0.0 && l_volume <= 1.0); - ASSERT(r_volume >= 0.0 && r_volume <= 1.0); - - looping: // Will go to this label to do the next iteration of a looping sample - - if (cur_buf->m_status & - (SSF_PLAY_LOOPING | SSF_PLAY_STREAMING)) // Looping sample's process is broken up into linear pieces - { - if (f_loop) { - ASSERT(num_write >= 0); - - num_samples -= num_write; - ASSERT(num_samples > 0); - - fast_mix_ptr += (num_write * 2); - // mixer_buffer16 += num_write << 1; // update to the new start position - // (2x because of left and right channels) - - samples_played = loop_start; - } - - if (cur_buf->m_status & SSF_PLAY_LOOPING) // Looping sample's process is broken up into linear pieces - { - ASSERT(loop_end < sample_length); - if (loop_end < samples_played) { - // CHRISHACK -- Fuck milestone. Fix later. Code below is a major hack (but it works). :) - - if (loop_end != loop_start) { - while (loop_end < samples_played) { - // Int3(); - samples_played -= loop_end - loop_start; - } - - ASSERT(samples_played >= 0); - } else { - cur_buf->m_status &= ~SSF_PLAY_LOOPING; - cur_buf->m_status |= SSF_PLAY_NORMAL; - } - - goto error_trap; - } - } - // The number of samples to write to the primary buffer - num_write = ((num_samples) < (loop_end - samples_played + 1)) ? (num_samples) : (loop_end - samples_played + 1); - ASSERT(num_write >= 0 && num_write <= num_samples); - - if (num_write < num_samples) - f_loop = true; - else - f_loop = false; - - if (num_write <= 0) { - num_write = 0; - mprintf(0, "d"); - goto stream_done; - } - } else { - // The number of samples to write to the primary buffer - num_write = - ((num_samples) < (np_sample_length - samples_played)) ? (num_samples) : (np_sample_length - samples_played); - if (!(num_write > 0 && num_write <= num_samples)) { - num_write = 0; - goto done; - } - - // Optimization for silent sounds - if (l_volume <= MIN_SOUND_MIX_VOLUME && r_volume <= MIN_SOUND_MIX_VOLUME) { - cur_buf->play_info->m_samples_played += num_write; - goto done; - } - } - - if (!(num_write > 0 && num_write <= num_samples)) // this was an assert - { - num_write = 0; - mprintf(0, "D"); - goto done; - } - - // Mix at 16 bits per sample - if (skip_interval == 0) { - int16_t *cur_sample_16bit = sample_16bit; - uint8_t *cur_sample_8bit = sample_8bit; - - if (f_mono) { - if (sample_8bit) { - cur_sample_8bit += samples_played; - opti_8m_mix(cur_sample_8bit, num_write, samples_played, fast_mix_ptr, l_volume, r_volume); - } else { - cur_sample_16bit += samples_played; - opti_16m_mix(cur_sample_16bit, num_write, samples_played, fast_mix_ptr, l_volume, r_volume); - } - } else { - if (sample_8bit) { - cur_sample_8bit += (samples_played << 1); - opti_8s_mix(cur_sample_8bit, num_write, samples_played, fast_mix_ptr, l_volume, r_volume); - } else { - cur_sample_16bit += (samples_played << 1); - opti_16s_mix(cur_sample_16bit, num_write, samples_played, fast_mix_ptr, l_volume, r_volume); - } - } - } else - // Account for lower-sampling rate - { - if (skip_interval == 1) { - const int fix_rvol = r_volume * VOLUME_FIX_BITS; - const int fix_lvol = l_volume * VOLUME_FIX_BITS; - - for (i = 0; i < (num_write << 1); i += 2) { - int sample; - - if (sample_16bit) { - if (samples_played & 0x0001) { - sample = ((int)sample_16bit[samples_played ^ 0x0001] + (int)sample_16bit[samples_played + 1]) >> 1; - } else - sample = sample_16bit[samples_played]; - } else { - if (samples_played & 0x0001) { - // Notes: (<<7) is from a (<<8) - (>>1) - // Notes: (-256) is from (-128) + (-128) - sample = ((int)sample_8bit[samples_played ^ 0x0001] + (int)sample_8bit[samples_played + 1] - 256) << 7; - } else - sample = (((int)sample_8bit[samples_played]) - (int)128) << 8; - } - - samples_played++; - - ASSERT(i >= 0 && (i + 1 < num_samples * 2)); - - int l_sample = fast_mix_ptr[i] + (sample * fix_lvol); - int r_sample = fast_mix_ptr[i + 1] + (sample * fix_rvol); - - fast_mix_ptr[i] = l_sample; - fast_mix_ptr[i + 1] = r_sample; - } - } else { - const int fix_rvol = r_volume * VOLUME_FIX_BITS; - const int fix_lvol = l_volume * VOLUME_FIX_BITS; - for (i = 0; i < (num_write << 1); i += 2) { - int sample; - const int mod_pos = samples_played % 4; - - if (sample_16bit) { - switch (mod_pos) { - case 0: - sample = sample_16bit[samples_played]; - break; - case 1: - sample = (sample_16bit[samples_played - 1] * 3 + sample_16bit[samples_played + 3]) >> 2; - break; - case 2: - sample = (sample_16bit[samples_played - 2] + sample_16bit[samples_played + 2]) >> 1; - break; - case 3: - sample = (sample_16bit[samples_played - 3] + sample_16bit[samples_played + 1] * 3) >> 2; - break; - } - } else { - switch (mod_pos) { - case 0: - sample = ((((int)sample_8bit[samples_played]) - 128) << 8); - break; - case 1: - sample = (((((int)sample_8bit[samples_played - 1]) - 128) << 8) * 3 + - ((((int)sample_8bit[samples_played + 3]) - 128) << 8)) >> - 2; - break; - case 2: - sample = (((((int)sample_8bit[samples_played - 2]) - 128) << 8) + - ((((int)sample_8bit[samples_played + 2]) - 128) << 8)) >> - 1; - break; - case 3: - sample = (((((int)sample_8bit[samples_played - 3]) - 128) << 8) + - ((((int)sample_8bit[samples_played + 1]) - 128) << 8) * 3) >> - 2; - break; - } - } - - samples_played++; - - ASSERT(i >= 0 && (i + 1 < num_samples * 2)); - - int l_sample = fast_mix_ptr[i] + (sample * fix_lvol); - int r_sample = fast_mix_ptr[i + 1] + (sample * fix_rvol); - - fast_mix_ptr[i] = l_sample; - fast_mix_ptr[i + 1] = r_sample; - } - } - } - - stream_done: - - cur_buf->play_info->m_samples_played = samples_played; - - if (cur_buf->m_status & SSF_PLAY_STREAMING) { - if (f_loop) { - if (cur_buf->play_info->m_stream_cback && cur_buf->play_info->m_stream_data) { - cur_buf->play_info->m_stream_data = (*cur_buf->play_info->m_stream_cback)( - cur_buf->play_info->user_data, cur_buf->play_info->m_stream_handle, &cur_buf->play_info->m_stream_size); -// cur_buf->s->current_position = (char*)cur_buf->play_info->m_stream_data; -// mprintf(0, "%x %d\n", cur_buf->play_info->m_stream_data, cur_buf->play_info->m_stream_size)); - ASSERT(!(cur_buf->play_info->m_stream_data && cur_buf->play_info->m_stream_size <= 0)); -/* - mprintf(0, "Data %X, length %d\n", - cur_buf->play_info->m_stream_data, - cur_buf->play_info->m_stream_size); -*/ - - if (cur_buf->play_info->m_stream_data) { - switch (cur_buf->play_info->m_stream_format) { - case SIF_STREAMING_16_M: - sample_16bit = (int16_t *)cur_buf->play_info->m_stream_data; - loop_end = sample_length = np_sample_length = cur_buf->play_info->m_stream_size / 2; - break; - case SIF_STREAMING_8_M: - sample_8bit = (uint8_t *)cur_buf->play_info->m_stream_data; - loop_end = sample_length = np_sample_length = cur_buf->play_info->m_stream_size; - break; - case SIF_STREAMING_16_S: - sample_16bit = (int16_t *)cur_buf->play_info->m_stream_data; - loop_end = sample_length = np_sample_length = cur_buf->play_info->m_stream_size / 4; - break; - case SIF_STREAMING_8_S: - sample_8bit = (uint8_t *)cur_buf->play_info->m_stream_data; - loop_end = sample_length = np_sample_length = cur_buf->play_info->m_stream_size / 2; - break; - default: - Int3(); - break; - } - loop_end -= 1; - } else { - mprintf(0, "SE: Data is NULL\n"); - cur_buf->m_status &= ~SSF_PLAY_STREAMING; - f_loop = false; - } - } else { - mprintf(0, "SE: Callback/data is NULL\n"); - cur_buf->m_status &= ~SSF_PLAY_STREAMING; - f_loop = false; - } - } - } - - if (f_loop) - goto looping; - - done: - - if (cur_buf->play_info->m_samples_played >= (np_sample_length) && - !(cur_buf->m_status & (SSF_PLAY_LOOPING | SSF_PLAY_STREAMING))) { - ll_sound_ptr->StopSound(cur_buf->m_unique_id); - } - } - - error_bail: - current_slot++; - } - - for (int a = 0; a < (buff_len * 2); a++) { - Fast_mixer[a] = Fast_mixer[a] / VOLUME_FIX_BITS; - - if (Fast_mixer[a] > 32767) - Fast_mixer[a] = 32767; - if (Fast_mixer[a] < -32767) - Fast_mixer[a] = -32767; - - mixer_buffer16[a] = Fast_mixer[a]; - - Fast_mixer[a + 1] = Fast_mixer[a + 1] / VOLUME_FIX_BITS; - - if (Fast_mixer[a + 1] > 32767) - Fast_mixer[a + 1] = 32767; - if (Fast_mixer[a + 1] < -32767) - Fast_mixer[a + 1] = -32767; - - mixer_buffer16[a + 1] = Fast_mixer[a + 1]; - - a++; - } - // mprintf(0," -%d- ",a); -} - -// Locks the primary buffer and fills in the new data -void StreamFill(int start_byte, int num_bytes) { - char *ptr1; - char *ptr2; - int len1, len2; - - if ((num_bytes % ll_sound_ptr->m_primary_alignment) != 0) { - ll_sound_ptr->SetError(SSL_ERROR_STREAMMIXER); - ll_sound_ptr->ErrorText("ASSERT((len % ll_sound_ptr->m_primary_alignment) == 0)\nLen:%d PrA:%d", num_bytes, - ll_sound_ptr->m_primary_alignment); - return; - } - ASSERT((num_bytes % ll_sound_ptr->m_primary_alignment) == 0); - ASSERT((start_byte % ll_sound_ptr->m_primary_alignment) == 0); - - start_byte = (start_byte % m_sb_info.BufferSize); - -TryLockAgainLabel: - - switch (m_sb_info.m_lp_looping_buffer->Lock(start_byte, num_bytes, (void **)&ptr1, (DWORD *)&len1, (void **)&ptr2, - (DWORD *)&len2, 0)) { - ASSERT((len1 % ll_sound_ptr->m_primary_alignment) == 0); - ASSERT((len2 % ll_sound_ptr->m_primary_alignment) == 0); - - // The pointers are to the lock areas of the primary buffer. There are two because locked region - // might be a discontinuous chunk (wrapped around the end of the buffer i.e. 'LLLLBBBBBBLLLLL' - // L is for Locked and B is unlocked buffer. - case DS_OK: - StreamMixer(ptr1, len1); - if (ptr2) - StreamMixer(ptr2, len2); - - m_sb_info.m_lp_looping_buffer->Unlock(ptr1, len1, ptr2, len2); - - m_sb_info.NextWritePos = (start_byte + num_bytes) % m_sb_info.BufferSize; - break; - - case DSERR_BUFFERLOST: - if (m_sb_info.m_lp_primary_buffer->Restore() == DS_OK && m_sb_info.m_lp_looping_buffer->Restore() == DS_OK) - goto TryLockAgainLabel; - break; - } -} - -// A peroidic mixer that uses the primary buffer as a stream buffer -void __cdecl StreamTimer(void *user_ptr) { - int playp, writep; - int try_count = 0; - DSSTREAM *sb_info = (DSSTREAM *)user_ptr; - DWORD result; - - m_sb_info.m_lp_primary_buffer->Restore(); - m_sb_info.m_lp_primary_buffer->Play(0, 0, DSBPLAY_LOOPING); - - while (!sb_info->thread_request_kill) { - try_count = 0; - - TryAgain: - try_count++; - - // hresult = m_sb_info.m_lp_primary_buffer->GetStatus(&stat_result); - // - // if(hresult != DS_OK || !(stat_result & DSBSTATUS_LOOPING)) - // { - // m_sb_info.m_lp_primary_buffer->Restore(); - m_sb_info.m_lp_primary_buffer->Restore(); - m_sb_info.m_lp_primary_buffer->Play(0, 0, DSBPLAY_LOOPING); - // } - - result = sb_info->m_lp_looping_buffer->GetCurrentPosition((DWORD *)&playp, (DWORD *)&writep); - - // mprintf(0, "(%d,%d)\n", playp, writep); - - // If primary buffer was stopped from playing - if (writep == playp) { - sb_info->NextWritePos = -1; - - if ((try_count == 1) && - (m_sb_info.m_lp_primary_buffer->Restore() == DS_OK && m_sb_info.m_lp_looping_buffer->Restore() == DS_OK)) { - if ((try_count == 1) && (m_sb_info.m_lp_looping_buffer->Play(0, 0, DSBPLAY_LOOPING) == DS_OK)) { - goto TryAgain; - } - } - - goto done; - } - - // Insert mixer code - { - int num_write_bytes; - - if (sb_info->NextWritePos < 0) - sb_info->NextWritePos = writep; - - // Debugging code (not sure what would happen if we hit these without an Int3()) -- Skipping noise - if (sb_info->LastPlayPos < sb_info->NextWritePos) { - - if (playp >= sb_info->NextWritePos || playp < sb_info->LastPlayPos) { - if (!sb_info->m_f_secondary_looping) - goto done; - playp = sb_info->NextWritePos - 4; - num_write_bytes = 4 * (int)(22050 * DSPB_TICK_INTERVAL); - } else { - // Determine how much we can write out. - num_write_bytes = (sb_info->MaxWriteBytes + playp) - sb_info->NextWritePos; - } - } else { - if (playp >= sb_info->NextWritePos && playp < sb_info->LastPlayPos) { - if (!sb_info->m_f_secondary_looping) - goto done; - - playp = sb_info->NextWritePos - 4; - num_write_bytes = 4 * (int)(22050 * DSPB_TICK_INTERVAL); - } else { - // Determine how much we can write out. - if (playp < sb_info->NextWritePos) - num_write_bytes = (sb_info->MaxWriteBytes + playp) - sb_info->NextWritePos; - else - num_write_bytes = sb_info->MaxWriteBytes - (sb_info->NextWritePos + (sb_info->BufferSize - playp)); - } - } - - num_write_bytes &= (0xFFFFFFFF & (~(ll_sound_ptr->m_primary_alignment))); - - if (num_write_bytes > 0) { - // ASSERT(num_write_bytes < sb_info->BufferSize); - if (num_write_bytes >= sb_info->BufferSize) { - num_write_bytes = sb_info->BufferSize / 2; - } - - StreamFill(sb_info->NextWritePos, num_write_bytes); - } - } - - sb_info->LastPlayPos = playp; - - done: - Sleep(DSPB_TICK_MILLISECONDS); - } - - sb_info->thread_alive = false; -} - -// Begins the whole streaming process -bool win_llsSystem::StartStreaming(void) { - DSBCAPS dsbcaps; - - dsbcaps.dwSize = sizeof(DSBCAPS); - m_sb_info.m_lp_looping_buffer->GetCaps(&dsbcaps); - - m_sb_info.m_f_secondary_looping = (m_sb_info.m_lp_looping_buffer != m_sb_info.m_lp_primary_buffer); - - m_sb_info.BufferSize = dsbcaps.dwBufferBytes; - - m_sb_info.MaxWriteSamples = m_primary_frequency * MAX_WRITE_AHEAD; - m_sb_info.MaxWriteBytes = m_sb_info.MaxWriteSamples * m_primary_alignment; - - m_sb_info.NextWritePos = -1; - m_sb_info.LastPlayPos = 0; - - StreamFill(0, dsbcaps.dwBufferBytes); - - m_sb_info.thread_request_kill = false; - m_sb_info.thread_alive = true; - - // Start mixing thread. - m_sb_info.thread_handle = _beginthread(StreamTimer, 16384, (void *)&m_sb_info); - if (m_sb_info.thread_handle == -1) { - m_sb_info.thread_alive = false; - mprintf(0, "Thread failed\n"); - Int3(); - return false; - } - - if (m_sb_info.m_f_secondary_looping) { - if (!SetThreadPriority((HANDLE)m_sb_info.thread_handle, THREAD_PRIORITY_HIGHEST)) - Int3(); - } else { - if (!SetThreadPriority((HANDLE)m_sb_info.thread_handle, THREAD_PRIORITY_TIME_CRITICAL)) - Int3(); - } - - return true; -} - -// Creates a 2d, 3d, or Primary direct sound buffer -HRESULT win_llsSystem::CreateDSBuffer(int buffer_type, LPDIRECTSOUNDBUFFER *lp_lp_dsb, LPDIRECTSOUND3DBUFFER *lp_lp_dsb_3d, - DWORD sound_bytes, DWORD frequency, bool f_is_stereo, bool f_is_16_bit) { - DSBUFFERDESC dsbd; - tWAVEFORMATEX fmt; - HRESULT result = DS_OK; - - ASSERT(m_lp_ds != NULL && sound_bytes >= 0); - ASSERT(frequency == 44100 || frequency == 22050 || frequency == 11025); - if (!m_f_sound_lib_init) - return 0; - - if (lp_lp_dsb) { - *lp_lp_dsb = NULL; - } - if (lp_lp_dsb_3d) { - *lp_lp_dsb_3d = NULL; - } - - // Setup the wave format - fmt.nChannels = (f_is_stereo) ? 2 : 1; - fmt.wBitsPerSample = (f_is_16_bit) ? 16 : 8; - fmt.nSamplesPerSec = ((DWORD)frequency); - fmt.nBlockAlign = fmt.nChannels * (fmt.wBitsPerSample >> 3); - fmt.nAvgBytesPerSec = ((DWORD)fmt.nSamplesPerSec) * ((DWORD)fmt.nBlockAlign); - fmt.wFormatTag = WAVE_FORMAT_PCM; - - // Setup the secondary direct sound buffer - memset(&dsbd, 0, sizeof(dsbd)); - dsbd.lpwfxFormat = (LPWAVEFORMATEX)&fmt; - dsbd.dwSize = sizeof(DSBUFFERDESC); - dsbd.dwBufferBytes = sound_bytes; - - if (m_mixer_type == SOUND_MIXER_SOFTWARE_16) { - dsbd.dwFlags = DSBCAPS_GETCURRENTPOSITION2; - - ASSERT(buffer_type == SBT_PRIMARY); - - m_primary_frequency = m_current_frequency = frequency; - m_primary_bit_depth = fmt.wBitsPerSample; - m_primary_alignment = fmt.nBlockAlign; - - dsbd.lpwfxFormat = NULL; - dsbd.dwBufferBytes = 0; - dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_GETCURRENTPOSITION2; - } else if (m_mixer_type == SOUND_MIXER_DS_16 || m_mixer_type == SOUND_MIXER_DS_8) { - // There are three buffer types that we should consider. - switch (buffer_type) { - case SBT_2D: - dsbd.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN; - break; - case SBT_PRIMARY: - dsbd.lpwfxFormat = NULL; - dsbd.dwBufferBytes = 0; - dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; - break; - default: - ASSERT(0); // Invalid type of buffer - } - } else if (IS_3D_MIXER(m_mixer_type)) { - // There are three buffer types that we should consider. - switch (buffer_type) { - case SBT_2D: - dsbd.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN; - break; - case SBT_3D: - dsbd.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME; - break; - case SBT_PRIMARY: - dsbd.lpwfxFormat = NULL; - dsbd.dwBufferBytes = 0; - dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME; - break; - default: - ASSERT(0); // Invalid type of buffer - } - } else { - mprintf(0, "DS3DLIB: Unsupported function for mixer specfied in CreateDSBuffer (%d,%d)\n", m_mixer_type, buffer_type); - Int3(); // Get Samir!!! - return DSERR_UNSUPPORTED; - } - - // Create the buffer - result = m_lp_ds->CreateSoundBuffer(&dsbd, lp_lp_dsb, 0); - /// ASSERT(result == DS_OK); - - if (result == DS_OK && buffer_type == SBT_PRIMARY) { - // Creative EAX Init - if (m_mixer_type == SOUND_MIXER_CREATIVE_EAX) { - if (!EAX_SetPrimaryBuffer()) { - mprintf(0, "CreateDSBuffer: EAX Init failed.\n"); - result = DSERR_UNSUPPORTED; - goto ds_error; - } - } - - // Succeeded. Set primary buffer to desired format. - result = (*lp_lp_dsb)->SetFormat(&fmt); - } - - if (result != DS_OK) { - mprintf(0, "DS3DLIB: Failed to init sound buffer of type %d for mixer %d.\n", buffer_type, m_mixer_type); - goto ds_error; - } - - // call get format to make sure we're okay. - if (buffer_type == SBT_PRIMARY) { - } - - // do 3d sound support stuff. - if (IS_3D_MIXER(m_mixer_type)) { - // a 3d buffer needs a 3d interface pointer - if (buffer_type == SBT_3D) { - ASSERT(lp_lp_dsb_3d != NULL); - result = (*lp_lp_dsb)->QueryInterface(IID_IDirectSound3DBuffer, (void **)lp_lp_dsb_3d); - if (result != DS_OK) { - goto ds_error; - } - - // ASSERT(result == DS_OK); - } else if (buffer_type == SBT_PRIMARY) { - if ((result = (*lp_lp_dsb)->QueryInterface(IID_IDirectSound3DListener, (void **)&m_lp_listener)) == S_OK) { - m_lp_listener->SetRolloffFactor(ENV3DVAL_ROLLOFF_DEFAULT, DS3D_IMMEDIATE); - } - } - } - -ds_error: - if (result != DS_OK) { - mprintf(0, "DS3DLIB:result=%x\n", result); - if (lp_lp_dsb_3d && (*lp_lp_dsb_3d)) { - (*lp_lp_dsb_3d)->Release(); - *lp_lp_dsb_3d = NULL; - } - - if (lp_lp_dsb && (*lp_lp_dsb)) { - (*lp_lp_dsb)->Release(); - *lp_lp_dsb = NULL; - } - } - - return (long)result; -} - -// Internal function to enumerate sound devices -BOOL CALLBACK LLEnumCallback(LPGUID lp_guid, LPCSTR lpstr_description, LPCSTR lpstr_module, LPVOID lp_Context) { - GUID FAR *lp_ret_guid = (GUID FAR *)lp_Context; - - if (m_sound_device_name[0]) { - if (strcmp(lpstr_description, m_sound_device_name) == 0) { - mprintf(0, "Using sound card:%s-%s\n", lpstr_description, lpstr_module); - if (lp_guid) { - memmove(lp_ret_guid, lp_guid, sizeof(GUID)); - } - return FALSE; - } - } - - return TRUE; -} - -void win_llsSystem::SetSoundCard(const char *name) { - if (name) { - strcpy(m_sound_device_name, name); - } else { - m_sound_device_name[0] = 0; - } -} - -// Initializes the sound library -int win_llsSystem::InitSoundLib(char mixer_type, oeApplication *sos, uint8_t MaxSoundsPlayed) // add playlist info -{ - GUID card_guid, zero_card_guid; - GUID *pguid = NULL; - DSCAPS dscaps; - HRESULT hresult; - bool f16bit; - bool retval = true; - - // reset error system. - SetError(SSL_OK); - SoundApp = (oeWin32Application *)sos; - - if (sos) { - oeWin32Application *obj = (oeWin32Application *)sos; - - // If the the library if already init'ed, then return o.k. - if (m_f_sound_lib_init) - return 1; - - GameWindowHandle = (void *)obj->m_hWnd; - } else { - ASSERT(GameWindowHandle); - } - - ll_sound_ptr = this; - m_timer_last_frametime = -1; - m_cache_stress_timer = 0.0f; - m_in_sound_frame = false; - m_pending_actions = false; - - ////////////////////////////////////////////////////////////////////////////// - // chrishack -- Need to enumerate sound devices for now - // Attempt to enumerate the sound device - // if(DirectSoundEnumerate(&LLEnumCallback, NULL) != DS_OK) return 0; - - // Setup the game handle - m_hwnd_main = GameWindowHandle; - - // Check for invalid values and NULL pointers - ASSERT(m_hwnd_main != NULL); - ASSERT(Sounds != NULL); - ASSERT(SoundFiles != NULL); - ASSERT(MaxSoundsPlayed > 0); - - memset(&m_sb_info, 0, sizeof(DSSTREAM)); - - // Currently restart total sounds played count (for unique ids and stats) - m_total_sounds_played = 0; - - // Setup the sound mixer object - m_sound_mixer.m_cur_sounds_played = 0; - m_sound_mixer.m_max_sounds_played = MaxSoundsPlayed; - m_sound_mixer.m_sound_cache = new sound_buffer_info[MaxSoundsPlayed]; - m_mixer_type = SOUND_MIXER_NONE; - - if (m_sound_mixer.m_sound_cache == NULL) { - Int3(); - goto error_sub; - } - - // Create the Direct Sound Interface - // determine GUID for sound card which was chosen in the launcher... - ZeroMemory(&card_guid, sizeof(GUID)); - ZeroMemory(&zero_card_guid, sizeof(GUID)); - hresult = DirectSoundEnumerate(LLEnumCallback, &card_guid); - if (hresult == DS_OK) { - if (memcmp(&card_guid, &zero_card_guid, sizeof(GUID)) != 0) { - pguid = &card_guid; - } - } - - if (mixer_type != SOUND_MIXER_NONE) { - if (mixer_type == SOUND_MIXER_CREATIVE_EAX) { - if (!EAX_Create(pguid, &m_lp_ds)) { - mprintf(0, "Sound NT: Error EAX\n"); - retval = false; - goto error_sub; - } - } else { - hresult = DirectSoundCreate(pguid, &m_lp_ds, NULL); - if (hresult != DS_OK) { - retval = false; - goto error_sub; - } - } - - ASSERT(m_lp_ds != NULL); - - // determine if we're using a crappy card - dscaps.dwSize = sizeof(DSCAPS); - m_lp_ds->GetCaps(&dscaps); - if (dscaps.dwFlags & DSCAPS_EMULDRIVER) { - mixer_type = SOUND_MIXER_DS_8; - mprintf(0, "SOUND INIT(1): We are in NT or have a crappy sound card\n"); - } - - m_sound_mixer.m_loop_method = DSLOOP_STREAM_METHOD; - } - - if (mixer_type != SOUND_MIXER_NONE) { - m_f_sound_lib_init = 1; - } - -// This section initializes the primary buffer -// software mixer try. -retry_mixer_init: - if (mixer_type == SOUND_MIXER_SOFTWARE_16) { - // test different conditions to see if we really can play sound in software - hresult = m_lp_ds->SetCooperativeLevel((HWND)m_hwnd_main, DSSCL_WRITEPRIMARY); - if (hresult != DS_OK) { - mprintf(0, "SOUND INIT(2): SCL: WritePrimary failed. Attempting DS 8 init.\n"); - mixer_type = SOUND_MIXER_DS_8; - goto retry_mixer_init; - } - - // Creates a primary buffer and makes sure we are at the specified frequency, bit depth, and that we - // can to 3d stuff too :) - m_mixer_type = SOUND_MIXER_SOFTWARE_16; - f16bit = true; - hresult = CreateDSBuffer(SBT_PRIMARY, &m_sb_info.m_lp_primary_buffer, NULL, 0, - 22050, // frequency - true, // stereo - f16bit); // 16-bit - if (hresult != DS_OK) { - if (m_sb_info.m_lp_primary_buffer) { - m_sb_info.m_lp_primary_buffer->Release(); - m_sb_info.m_lp_primary_buffer = NULL; - } - mprintf(0, "SOUND INIT(3): Cannot create primary buffer.\n"); - mixer_type = SOUND_MIXER_DS_8; - goto retry_mixer_init; - } else { - // Determine if we are running NT or have a shitty Win95 sound card - DSBCAPS dsbcaps; - - ASSERT(m_sb_info.m_lp_primary_buffer); - - dsbcaps.dwSize = sizeof(DSBCAPS); - m_sb_info.m_lp_primary_buffer->GetCaps(&dsbcaps); - - // Let's allocate our array of ints for our optimized software mixer! - if (!Fast_mixer) { - Fast_mixer = (int *)mem_malloc(dsbcaps.dwBufferBytes * sizeof(int)); - Fast_mixer_len = dsbcaps.dwBufferBytes; - mprintf(0, "Using %d ints for fast software mixer\n", dsbcaps.dwBufferBytes); - } - - // Is you want to see the caps, here is where -- mprintf all you want - if (!(dsbcaps.dwFlags & DSBCAPS_LOCHARDWARE)) { - mprintf(0, "SOUND INIT(4): Primary is not in hardware\n"); - m_sb_info.m_lp_primary_buffer->Release(); - m_sb_info.m_lp_primary_buffer = NULL; - mixer_type = SOUND_MIXER_DS_8; - goto retry_mixer_init; - } - } - - // looping buffer is the same as the primary buffer for software mixers. - m_sb_info.m_lp_looping_buffer = m_sb_info.m_lp_primary_buffer; - - // Start the primary and have it always play. - m_f_sound_lib_init = StartStreaming(); - if (!m_f_sound_lib_init) { - mprintf(0, "SOUND INIT(5): Something went wrong in StartStreaming\n"); - m_sb_info.m_lp_primary_buffer->Release(); - m_sb_info.m_lp_primary_buffer = NULL; - mixer_type = SOUND_MIXER_DS_8; - goto retry_mixer_init; - } - - } else if (mixer_type == SOUND_MIXER_NONE) { - m_mixer_type = mixer_type; - m_f_sound_lib_init = 0; - } else { - // This is for DirectSound Internal Mixers. We let DirectSound do its magic. - m_mixer_type = mixer_type; - hresult = m_lp_ds->SetCooperativeLevel((HWND)m_hwnd_main, DSSCL_PRIORITY); - if (hresult != DS_OK) { - mprintf(0, "Sound NT: Error 1\n"); - retval = false; - goto error_sub; - } - - // start primary buffer - f16bit = (mixer_type == SOUND_MIXER_DS_16 || mixer_type == SOUND_MIXER_DS3D_16 || - mixer_type == SOUND_MIXER_CREATIVE_EAX); - hresult = CreateDSBuffer(SBT_PRIMARY, &m_sb_info.m_lp_primary_buffer, NULL, 0, - 22050, // frequency - true, // stereo - f16bit); // 8 or 16 bit - if (hresult != DS_OK) { - mprintf(0, "Sound NT: Error 2\n"); - if (m_sb_info.m_lp_primary_buffer) { - m_sb_info.m_lp_primary_buffer->Release(); - m_sb_info.m_lp_primary_buffer = NULL; - } - retval = false; - goto error_sub; - } - - m_sb_info.m_lp_primary_buffer->Play(0, 0, DSBPLAY_LOOPING); - } - - // buffered method doesn't use threads at all. - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16 && m_mixer_type != SOUND_MIXER_NONE && - m_sound_mixer.m_loop_method != DSLOOP_BUFFER_METHOD) { - // start looping thread, failure results in a 'clean exit' - if (!sb_loop_thread_init(this)) { - retval = false; - if (m_sb_info.m_lp_primary_buffer) { - m_sb_info.m_lp_primary_buffer->Release(); - m_sb_info.m_lp_primary_buffer = NULL; - } - goto error_sub; - } - } - - mprintf(0, "Sound mixer: "); - retval = true; - - switch (m_mixer_type) { - case SOUND_MIXER_SOFTWARE_16: - mprintf(0, "Software 16\n"); - break; - case SOUND_MIXER_DS_8: - mprintf(0, "DS 8\n"); - break; - case SOUND_MIXER_DS_16: - mprintf(0, "DS 16\n"); - break; - case SOUND_MIXER_DS3D_16: - mprintf(0, "DS3D 16\n"); - break; - case SOUND_MIXER_CREATIVE_EAX: - mprintf(0, "Creative EAX\n"); - break; - case SOUND_MIXER_NONE: - mprintf(0, "None\n"); - break; - default: - mprintf(0, "LLSound ERROR: Unsupported mixer"); - Int3(); - retval = false; - break; - } - - // set 3d environment settings - t3dEnvironmentToggles env_toggles; - t3dEnvironmentValues env_values; - - memset(&Env3dValues, 0, sizeof(Env3dValues)); - memset(&Env3dToggles, 0, sizeof(Env3dToggles)); - - env_toggles.flags = 0; // get supported features - GetEnvironmentToggles(&env_toggles); - - env_values.flags = 0; // set up values and toggles to be set - env_toggles.flags = env_toggles.supported; - - // we may want to check this with configured options later -- samir - if (CHECK_FLAG(env_toggles.supported, ENV3DVALF_DOPPLER) && ENV3DTOG_DOPPLER) { - env_values.flags |= ENV3DVALF_DOPPLER; - env_values.doppler_scalar = ENV3DVAL_DOPPLER_DEFAULT; - env_toggles.doppler = true; - } - if (CHECK_FLAG(env_toggles.supported, ENV3DVALF_GEOMETRY) && ENV3DTOG_GEOMETRY) { - env_toggles.geometry = true; - } - SetEnvironmentToggles(&env_toggles); - SetEnvironmentValues(&env_values); - - ///////////////////////////////////////////////////////////////////////////// - g_emulated_listener = &m_emulated_listener; - -error_sub: - if (retval == false) { - // Only gets here if there was an error - if (m_mixer_type == SOUND_MIXER_CREATIVE_EAX) { - EAX_Destroy(); - } else if (m_lp_ds) { - m_lp_ds->Release(); - } - m_lp_ds = NULL; - mprintf(0, "Sound Warning: Didn't initialize sound library.\n"); - if (m_sound_mixer.m_sound_cache != NULL) - delete[] m_sound_mixer.m_sound_cache; - m_f_sound_lib_init = 0; - m_mixer_type = SOUND_MIXER_NONE; - } - - Global_DS_alloced_sounds = 0; - - return (m_f_sound_lib_init); -} - -// Cleans up after the sound library is done being used -void win_llsSystem::DestroySoundLib(void) { - bool f_all_done = false; - - if (!m_f_sound_lib_init) - return; - - mprintf(0, "Start of sound system close\n"); - - // kill sound geometry object if any. - if (m_geometry) { - m_geometry->Shutdown(); - m_geometry = NULL; - } - - StopAllSounds(); - - // Wait till they are all done - mprintf(0, "Waiting for sounds to stop\n"); - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - while (!f_all_done) { - f_all_done = true; - int i; - - for (i = 0; i < m_sound_mixer.m_max_sounds_played; i++) { - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[i]; - if (sb->s && sb->s->kill_me && !(sb->m_status & (SSF_BUFFERED_LOOP + SSF_BUFFERED_STRM))) { - cleanup_directsound_looping_sb(&m_sound_mixer.m_sound_cache[i]); - } else if (sb->m_status & (SSF_PLAY_LOOPING | SSF_PLAY_STREAMING)) { - // this should block until the sound is truly free, so we don't need to do a 'all done' - StopSound(m_sound_mixer.m_sound_cache[i].m_unique_id, SKT_HOLD_UNTIL_STOP); - // f_all_done = false; - } - } - } - - // buffered method doesn't use threads at all. - if (m_sound_mixer.m_loop_method != DSLOOP_BUFFER_METHOD) { - sb_loop_thread_kill(); - } - } - mprintf(0, "All sounds stopped\n"); - - if (m_mixer_type == SOUND_MIXER_SOFTWARE_16) { - // Kill thread goes here - if (m_sb_info.thread_handle) { - m_sb_info.thread_request_kill = true; - while (m_sb_info.thread_alive) { - } - } - - if (m_mixer_type == SOUND_MIXER_SOFTWARE_16) { - m_sb_info.m_lp_looping_buffer->Stop(); - m_sb_info.m_lp_looping_buffer->Release(); - } - } - - // free audio device; - if (m_mixer_type == SOUND_MIXER_CREATIVE_EAX) { - EAX_Destroy(); - } else if (m_lp_ds) { - m_lp_ds->Release(); - } - - m_lp_ds = NULL; - m_sb_info.m_lp_looping_buffer = NULL; - - mprintf(0, "End of sound system close\n"); - - if (m_sound_mixer.m_sound_cache != NULL) - delete[] m_sound_mixer.m_sound_cache; - - m_f_sound_lib_init = false; - g_emulated_listener = NULL; - m_mixer_type = -1; - ll_sound_ptr = NULL; - if (Fast_mixer) { - mem_free(Fast_mixer); - Fast_mixer = NULL; - Fast_mixer_len = 0; - } -} - -// used to clean up direct sound buffer stuff -void win_llsSystem::cleanup_directsound_looping_sb(sound_buffer_info *sb) { - if (!sb->s) - return; - if (!sb->s->kill_me) - return; - - // should occur when kill_me set, sb_stop_buffer(&ll_sound_ptr->m_sound_mixer.m_sound_cache[i]); - sb_free_buffer(sb); - - sb->m_sound_buffer = NULL; - sb->s->playing = 0; - - void *p = (void *)sb->s; - sb->s = NULL; - sb->m_status = SSF_UNUSED; - mem_free(p); -} - -// cleans up a sound -replaces a lot of repeated code whenever we cleanup sounds. -void win_llsSystem::update_directsound_sb(sound_buffer_info *sb, bool update_looping) { - if (m_mixer_type == SOUND_MIXER_SOFTWARE_16 || m_mixer_type == SOUND_MIXER_NONE) { - return; - } - - // take care of any streamed threaded method looping sounds that are done. - // orphan streaming structure, clean it up! (sound buffer is NULL yet sb->s is valid - if (sb->s && (((sb->m_status & (SSF_BUFFERED_LOOP + SSF_BUFFERED_STRM)) && !sb->m_sound_buffer) || sb->s->kill_me)) { - cleanup_directsound_looping_sb(sb); - } else if (sb->m_status && !(sb->m_status & SSF_PAUSED)) { - // non playing sounds should be stopped always - int status = sb_get_status(sb); - - if (update_looping) { - if (status & SB_STATUS_PLAYING) { - if ((sb->m_status & (SSF_PLAY_STREAMING + SSF_BUFFERED_STRM)) == (SSF_PLAY_STREAMING + SSF_BUFFERED_STRM)) { - sb_stream_buffered_update(sb); - } - } else { - if ((sb->m_status & (SSF_PLAY_LOOPING + SSF_BUFFERED_LOOP)) == (SSF_PLAY_LOOPING + SSF_BUFFERED_LOOP)) { - sb_buffered_loop_step(this, sb); - status = sb_get_status(sb); // get new status for following checks. - } - } - } - if (!(status & SB_STATUS_PLAYING)) { - StopSound(sb->m_unique_id); - } else if (status & SB_STATUS_INVALID) { - StopSound(sb->m_unique_id); - } - } -} - -// Stops the sound from playing -- f_immediately is used for looping samples -- i.e. so we can -// play the end of loop snipit -void win_llsSystem::StopSound(int sound_uid, uint8_t f_immediately) { - int current_slot; - sound_buffer_info *sb; - - if (!m_f_sound_lib_init) - return; - - if ((current_slot = ValidateUniqueId(sound_uid)) == -1) - return; - - sb = &m_sound_mixer.m_sound_cache[current_slot]; - - if (sb->m_status == SSF_UNUSED) - return; - - // update sound count. - m_sound_mixer.m_cur_sounds_played--; - - if (f_immediately == SKT_STOP_AFTER_LOOP) { - sb->m_status &= ~SSF_PLAY_LOOPING; - sb->m_status |= SSF_PLAY_NORMAL; - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16 && (sb->m_status & SSF_BUFFERED_LOOP)) { - sb_buffered_loop_step(this, sb, DSBUFLOOP_FINISH_STEP); - } - return; - } - - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - if (sb->s && !(sb->m_status & (SSF_BUFFERED_LOOP + SSF_BUFFERED_STRM))) { - sb_loop_element_kill(sb); - if (f_immediately == SKT_HOLD_UNTIL_STOP) { - sb_loop_element_wait_until_dead(sb); - cleanup_directsound_looping_sb(sb); - } - return; - } else if (sb->m_sound_buffer) // this works for buffered loops too. - { - if (sb->m_status & (SSF_BUFFERED_LOOP + SSF_BUFFERED_STRM)) { - if (sb->m_status & SSF_PLAY_STREAMING) { - sb_stream_element_kill(sb); - } - - void *p = (void *)sb->s; - if (p) { - mem_free(p); - sb->s = NULL; - } - } - GetSoundPos(sb->m_unique_id); - sb_stop_buffer(sb); - sb_free_buffer(sb); - - if (SoundFiles[Sounds[sb->m_sound_index].sample_index].use_count > 0) { - SoundFiles[Sounds[sb->m_sound_index].sample_index].use_count--; - // DUPSND if (SoundFiles[Sounds[sb->m_sound_index].sample_index].use_count == 0) { - // DUPSND Global_DS_alloced_sounds--; - // DUPSND } - } - Global_DS_alloced_sounds--; - } - m_sound_mixer.m_sound_cache[current_slot].m_sound_buffer = NULL; - } - - // mprintf(0, "SL cleaning slot %d\n", current_slot); - m_sound_mixer.m_sound_cache[current_slot].m_status = SSF_UNUSED; -} - -// Copies sound data from the external sound data block to an individual sound buffer -HRESULT LoadSoundData(LPDIRECTSOUNDBUFFER lp_dsb, char *sound_data_ptr, DWORD total_bytes) { - LPVOID ptr1, ptr2; - DWORD len1, len2; - HRESULT result; - - ASSERT(lp_dsb != NULL && sound_data_ptr != NULL && total_bytes > 0); - -TryLockAgainLabel: - result = lp_dsb->Lock(0, total_bytes, &ptr1, &len1, &ptr2, &len2, 0); - - switch (result) { - case DS_OK: - memcpy(ptr1, sound_data_ptr, len1); - if (ptr2) - memcpy(ptr2, sound_data_ptr + len1, len2); - lp_dsb->Unlock(ptr1, len1, ptr2, len2); - break; - case DSERR_BUFFERLOST: - result = lp_dsb->Restore(); - if (result == DS_OK) - goto TryLockAgainLabel; - break; - } - - return (long)result; -} - -// Determines if a sound will play. Takes into account maximum allowable -// sounds. -// Also put prioritization code in here -// ignore reserved slots - -#ifdef _DEBUG -int16_t win_llsSystem::FindFreeSoundSlot(int sound_index, float volume, int priority) -#else -int16_t win_llsSystem::FindFreeSoundSlot(float volume, int priority) -#endif -{ - int current_slot; - sound_buffer_info *sb; - - // stop any left over sounds for Direct Sound. - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - sb = &m_sound_mixer.m_sound_cache[current_slot]; - update_directsound_sb(sb); - } - } - - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - sb = &m_sound_mixer.m_sound_cache[current_slot]; - if (sb->m_status == SSF_UNUSED) { - if (!((m_mixer_type == SOUND_MIXER_DS_8 || m_mixer_type == SOUND_MIXER_DS_16 || - m_mixer_type == SOUND_MIXER_DS3D_16 || - m_mixer_type == SOUND_MIXER_CREATIVE_EAX) && - sb->s)) - return current_slot; - } - } - - // no more slots? take priority into account. - // throw out lowest priority sound slot (must be lower than or equal to new sound priority) - float weighted_priority = (priority * 2.0f) * volume; - if (current_slot == m_sound_mixer.m_max_sounds_played) { - int throw_out_slot = -1, equiv_priority_slot = -1; - float weighted_priorityA, weighted_priorityB; - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - sb = &m_sound_mixer.m_sound_cache[current_slot]; - if (!(sb->m_status & (SSF_PLAY_LOOPING + SSF_PLAY_STREAMING))) { - weighted_priorityA = sb->play_info->priority * 2.0f * sb->m_volume; - if (weighted_priorityA < weighted_priority) { - if (throw_out_slot == -1) { - throw_out_slot = current_slot; - } else { - play_information *play_info2 = m_sound_mixer.m_sound_cache[throw_out_slot].play_info; - weighted_priorityB = play_info2->priority * 2.0f * sb->m_volume; - if (weighted_priorityB > weighted_priorityA) { - throw_out_slot = current_slot; - } - } - } - - else if (equiv_priority_slot == -1 && weighted_priorityA == weighted_priority) { - equiv_priority_slot = current_slot; - } - } - } - - // if no slot found to stop, look for a slot with priority == new priority - if (throw_out_slot == -1) { - throw_out_slot = equiv_priority_slot; - } - if (throw_out_slot > -1) { - sb = &m_sound_mixer.m_sound_cache[throw_out_slot]; - win_llsSystem::StopSound(sb->m_unique_id, SKT_HOLD_UNTIL_STOP); -/* - mprintf(0, "DDSNDLIB: Replace sound (p:%d) with sound (p:%d) in slot %d\n", - sb->play_info->priority, - priority, - throw_out_slot)); -*/ - return throw_out_slot; - } - } - -#ifdef _DEBUG - if (sound_index > -1) { - mprintf(0, "DDSNDLIB: Sound %s with priority (%d) too low.\n", Sounds[sound_index].name, priority); - } else { - mprintf(0, "DDSNDLIB: Sound unknown with priority (%d) too low.\n", priority); - } -#endif - - return -1; -} - -int win_llsSystem::PlaySound2d(play_information *play_info, int sound_index, float f_volume, float f_pan, - bool f_looped) { - sound_buffer_info *sb = NULL; - int16_t sound_slot; - - if (!m_f_sound_lib_init) { - return -1; - } - - // calculate volume and pan - f_volume = (f_volume < 0.0f) ? 0.0f : (f_volume > 1.0f) ? 1.0f : f_volume; - play_info->left_volume = play_info->right_volume = f_volume; - - f_pan = (f_pan < -1.0f) ? -1.0f : (f_pan > 1.0f) ? 1.0f : f_pan; - if (f_pan < 0.0) { - play_info->right_volume += f_volume * f_pan; - } else { - play_info->left_volume -= f_volume * f_pan; - } - - // do common processing. - if (SoundFiles[Sounds[sound_index].sample_index].used == 0) { - mprintf(0, "Tryed to play %d sound, it DNE.\n", sound_index); - return -1; - } -#ifdef _DEBUG - sound_slot = FindFreeSoundSlot(sound_index, f_volume, play_info->priority); -#else - sound_slot = FindFreeSoundSlot(f_volume, play_info->priority); -#endif - if (sound_slot < 0) { - // do prioritization code here. - return -1; - } - sb = &m_sound_mixer.m_sound_cache[sound_slot]; - m_total_sounds_played++; - sb->play_info = play_info; - sb->m_unique_id = MakeUniqueId(sound_slot); - sb->m_buffer_type = SBT_2D; - sb->m_sound_index = sound_index; - sb->m_status = SSF_UNUSED; - - ASSERT(sb->m_unique_id != -1); - - // play 2d sound - if (m_mixer_type == SOUND_MIXER_SOFTWARE_16) { - sb->m_status = (f_looped) ? SSF_PLAY_LOOPING : SSF_PLAY_NORMAL; - return sb->m_unique_id; - } - - if (f_looped) { - LoopStartStreaming(sb, SBT_2D, f_volume, f_pan, NULL); - if (sb->m_snd_obj == NULL) { - sb->m_status = SSF_UNUSED; - Int3(); - return -1; - } - } else { - tPSBInfo psb; - - if (SoundFiles[Sounds[sound_index].sample_index].use_count > 0) { - if (DuplicateSoundBuffer(sb)) { - goto play_sound; - } - } - if (!CreateSoundBuffer(sb, false)) { - return -1; - } - if (!LoadSoundBuffer(sb)) { - sb_free_buffer(sb); - return -1; - } - - play_sound: - sb->m_status = SSF_PLAY_NORMAL; - - psb.volume = f_volume; - psb.pan = f_pan; - psb.freq = 22050; - psb.looping = false; - if (!PlaySoundBuffer(sb, &psb)) { - sb_free_buffer(sb); - return -1; - } - } - - m_sound_mixer.m_cur_sounds_played++; - - return sb->m_unique_id; -} - -void win_llsSystem::LoopStartStreaming(sound_buffer_info *sb, int buffer_type, float volume, float pan, - pos_state *cur_pos) { - // unsigned long thread_handle; - int sound_length, buffer_size; - int determined_method; - bool f_sample_16bit; - char *sample_ptr; - tPSBInfo psb; - DSLOOPSTREAM *s; - - // setup looping buffer. must clear out before assigning to sound buffer for thread security. - s = (DSLOOPSTREAM *)mem_malloc(sizeof(DSLOOPSTREAM)); - if (s == NULL) { - sb->s = NULL; - return; - } - memset((void *)s, 0, sizeof(DSLOOPSTREAM)); - sb->s = s; - - sample_ptr = get_sound_info(sb, &sound_length, &f_sample_16bit); - sb->s->f_sample_16bit = f_sample_16bit; - sb->m_buffer_type = buffer_type; - - if (m_sound_mixer.m_loop_method == DSLOOP_SMART_METHOD) { - int loop_startb, loop_endb; - bool b; - if (sb_get_loop_info(sb, &loop_startb, &loop_endb, &b)) { - if (SoundFiles[Sounds[sb->m_sound_index].sample_index].np_sample_length == (loop_endb - loop_startb + 1)) { - determined_method = DSLOOP_BUFFER_METHOD; - } else { - determined_method = DSLOOP_STREAM_METHOD; - } - } else { // wtf? - return; - } - } else { - determined_method = m_sound_mixer.m_loop_method; - } - - switch (determined_method) { - case DSLOOP_BUFFER_METHOD: - sound_length = 0; - sb->s->loop_step = -1; - while (!sound_length && sb->s->loop_step < 2) { - sample_ptr = sb_get_loop_step_info(sb, sb->s->loop_step, f_sample_16bit, &sound_length); - sb->s->loop_step++; - } - if (!sound_length && sb->s->loop_step == 2) { - // hmm, weird loop. no sample? - return; - } - sb->s->loop_step--; // return to proper step. - sb->s->loop_timer = 0.0f; - sb->s->bytes_left = sound_length; - buffer_size = sound_length; - sb->m_status = SSF_PLAY_LOOPING | SSF_BUFFERED_LOOP; - // mprintf(0, "DDSNDLIB: Starting buffered loop %d (step %d).\n", sb->m_unique_id, sb->s->loop_step); - break; - default: - buffer_size = STREAM_BUFFER_SIZE; - sb->m_status = SSF_PLAY_LOOPING; // must go before buffer is initialized!!!!!! - } - - sb->sample_data = sample_ptr; - - // allocate buffer for playback - if (!CreateSoundBuffer(sb, false, buffer_size, (sb->m_status & SSF_BUFFERED_LOOP) ? false : true)) { - return; - } - - // remind sb system and play. - if (determined_method == DSLOOP_BUFFER_METHOD) { - psb.looping = (sb->s->loop_step == 0) ? true : false; - if (!sb_load_buffer(sb, sb->sample_data, sound_length)) - return; - } else if (sb_loop_element_init(sb, sample_ptr, sound_length, STREAM_BUFFER_SIZE)) { - psb.looping = true; - } else { - sb->s->playing = 0; - return; - } - - if (buffer_type == SBT_3D) { - psb.cur_pos = cur_pos; - } else { - ASSERT(buffer_type == SBT_2D); - psb.pan = pan; - } - psb.volume = volume; - psb.freq = 22050; - - PlaySoundBuffer(sb, &psb); - - // must be at end to initiate thread management. - sb->s->playing = 1; -} - -void win_llsSystem::DSStartStreaming(sound_buffer_info *sb, float volume, float pan) { - tPSBInfo psb; - int sound_length; - int stream_buflength; - int determined_method; - char *sample_ptr; - bool f_stereo; - - sb->s = (DSLOOPSTREAM *)mem_malloc(sizeof(DSLOOPSTREAM)); - ASSERT(sb->s); - if (sb->s == NULL) - return; - - memset((void *)sb->s, 0, sizeof(DSLOOPSTREAM)); - - sample_ptr = (char *)sb->play_info->m_stream_data; - sound_length = sb->play_info->m_stream_size; - stream_buflength = sb->play_info->m_stream_bufsize; - - switch (sb->play_info->m_stream_format) { - case SIF_STREAMING_16_M: - sb->s->f_sample_16bit = true; - f_stereo = false; - break; - - case SIF_STREAMING_8_M: - sb->s->f_sample_16bit = false; - f_stereo = false; - break; - - case SIF_STREAMING_16_S: - sb->s->f_sample_16bit = true; - f_stereo = true; - break; - - case SIF_STREAMING_8_S: - sb->s->f_sample_16bit = false; - f_stereo = true; - break; - - default: - ASSERT(0); - break; - } - - ASSERT(sb->m_buffer_type == SBT_2D); - sb->m_sound_index = -1; - - // determine how we will stream this data - determined_method = m_sound_mixer.m_loop_method; - switch (determined_method) { - case DSLOOP_BUFFER_METHOD: - sb->m_status = SSF_PLAY_STREAMING | SSF_BUFFERED_STRM; - break; - default: - sb->m_status = SSF_PLAY_STREAMING; // must go before buffer is initialized!!!!!! - break; - } - - if (!CreateSoundBuffer(sb, f_stereo, stream_buflength, true)) { - mem_free((void *)sb->s); - sb->s = NULL; - return; - } - - // set wave event or do thread streamed method - if (sb_stream_element_init(sb, sample_ptr, sound_length, stream_buflength)) { - psb.pan = pan; - psb.volume = volume; - psb.freq = 22050; - psb.looping = true; - - PlaySoundBuffer(sb, &psb); - - // must be at end to initiate thread management. - sb->s->playing = 1; - } -} - -int win_llsSystem::PlayStream(play_information *play_info) { - int16_t sound_slot; - DWORD ds_flags = 0; - - ASSERT(play_info != NULL); - - float volume = (play_info->left_volume > play_info->right_volume) ? play_info->left_volume : play_info->right_volume; - - if (!m_f_sound_lib_init) - return -1; - -#ifdef _DEBUG - sound_slot = FindFreeSoundSlot(-1, volume, play_info->priority); -#else - sound_slot = FindFreeSoundSlot(volume, play_info->priority); -#endif - // Out of sound slots - if (sound_slot < 0) { - return -1; - } - - // mprintf(0, "TS(%d)Playing sound index %d at %d volume,%d pan\n", TotalSoundsPlayed, sound_index, volume, pan); - - m_total_sounds_played++; - m_sound_mixer.m_sound_cache[sound_slot].play_info = play_info; - - m_sound_mixer.m_sound_cache[sound_slot].m_unique_id = MakeUniqueId(sound_slot); - ASSERT(m_sound_mixer.m_sound_cache[sound_slot].m_unique_id != -1); - - m_sound_mixer.m_sound_cache[sound_slot].m_buffer_type = SBT_2D; - - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - float volume; - float pan; - LPDIRECTSOUNDBUFFER sound_ptr; - - if (play_info->left_volume > play_info->right_volume) { - volume = play_info->left_volume; - pan = -1.0f + (play_info->right_volume / play_info->left_volume); - } else { - volume = play_info->right_volume; - pan = 1.0f - (play_info->left_volume / play_info->right_volume); - } - - DSStartStreaming(&m_sound_mixer.m_sound_cache[sound_slot], volume, pan); - sound_ptr = m_sound_mixer.m_sound_cache[sound_slot].m_sound_buffer; - if (sound_ptr == NULL) { - m_sound_mixer.m_sound_cache[sound_slot].m_sound_buffer = NULL; - return -1; - } - } else { - m_sound_mixer.m_sound_cache[sound_slot].m_status = SSF_PLAY_STREAMING; - } - - m_sound_mixer.m_cur_sounds_played++; - - return (m_sound_mixer.m_sound_cache[sound_slot].m_unique_id); -} - -// Checks a Unique Sound ID and determines if that sound is still playing -bool win_llsSystem::IsSoundInstancePlaying(int sound_uid) { - int current_slot; - - if (!m_f_sound_lib_init) - return false; - - if ((current_slot = ValidateUniqueId(sound_uid)) == -1) - return false; - - // mprintf(0, "Checking slot %d of UID %d\n", current_slot, sound_uid); - - if (m_sound_mixer.m_sound_cache[current_slot].m_status != SSF_UNUSED) { - return true; - } - - return false; -} - -// Is this sound placing on any "channel" -int win_llsSystem::IsSoundPlaying(int sound_index) { - int current_slot; - - if (!m_f_sound_lib_init) - return -1; - - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - if ((m_sound_mixer.m_sound_cache[current_slot].m_status != SSF_UNUSED) && - (m_sound_mixer.m_sound_cache[current_slot].m_sound_index == sound_index)) { - return m_sound_mixer.m_sound_cache[current_slot].m_unique_id; - } - } - - return -1; -} - -// This function limits the number of sounds cached to 255(8bits) and 256 bit is for invalid channel -// The purpose is to create unique signatures for each sound played (and allow for -// the slot_number to be quickly determined) -inline int win_llsSystem::MakeUniqueId(int sound_slot) { return ((((int)m_total_sounds_played) << 8) + sound_slot); } - -inline int win_llsSystem::ValidateUniqueId(int sound_uid) { - if (sound_uid == m_sound_mixer.m_sound_cache[sound_uid & 0x00FF].m_unique_id) { - return sound_uid & 0x00FF; - } else { - return -1; - } -} - -void win_llsSystem::PauseSounds() { - int current_slot; - - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[current_slot]; - update_directsound_sb(sb); - - /* if((sb->m_status != SSF_UNUSED) && - ((sb->m_status & SSF_PAUSED) == 0)) - { - int status = sb_get_status(sb); - - if(!(status & SB_STATUS_PLAYING)) { - ll_sound_ptr->StopSound(sb->m_unique_id); - } - else if (status & SB_STATUS_INVALID) { - ll_sound_ptr->StopSound(sb->m_unique_id); - } - } - */ - } - } - - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[current_slot]; - if (sb->m_status != SSF_UNUSED && !(sb->m_status & SSF_PAUSED)) { - sb->m_status |= SSF_PAUSED; - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16 && (sb->m_sound_buffer)) { - sb_stop_buffer(sb); - } - } - } -} - -void win_llsSystem::ResumeSounds() { - int current_slot; - - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[current_slot]; - - if (sb->m_status != SSF_UNUSED && (sb->m_status & SSF_PAUSED)) { - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - PlaySoundBuffer(sb, NULL); - } - - m_sound_mixer.m_sound_cache[current_slot].m_status &= (~SSF_PAUSED); - } - } -} - -void win_llsSystem::PauseSound(int sound_uid) { - int current_slot; - - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[current_slot]; - - if (sb->m_unique_id == sound_uid) { - update_directsound_sb(sb); - - /* if((sb->m_status != SSF_UNUSED) && ((sb->m_status & SSF_PAUSED) == 0)) - { - int status = sb_get_status(sb); - - if(!(status & SB_STATUS_PLAYING)) { - ll_sound_ptr->StopSound(sb->m_unique_id); - } - else if (status & SB_STATUS_INVALID) { - ll_sound_ptr->StopSound(sb->m_unique_id); - } - } - */ - break; - } - } - } - - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[current_slot]; - if (sb->m_unique_id == sound_uid) { - if (sb->m_status != SSF_UNUSED && !(sb->m_status & SSF_PAUSED)) { - sb->m_status |= SSF_PAUSED; - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16 && (sb->m_sound_buffer)) { - sb_stop_buffer(sb); - } - } - break; - } - } -} - -void win_llsSystem::ResumeSound(int sound_uid) { - int current_slot; - - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - if (sound_uid == m_sound_mixer.m_sound_cache[current_slot].m_unique_id) { - if (m_sound_mixer.m_sound_cache[current_slot].m_status != SSF_UNUSED && - (m_sound_mixer.m_sound_cache[current_slot].m_status & SSF_PAUSED)) { - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - PlaySoundBuffer(&m_sound_mixer.m_sound_cache[current_slot], NULL); - } - - m_sound_mixer.m_sound_cache[current_slot].m_status &= (~SSF_PAUSED); - break; - } - } - } -} - -void win_llsSystem::StopAllSounds() { - int current_slot; - - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - if (m_sound_mixer.m_sound_cache[current_slot].m_status != SSF_UNUSED) { - StopSound(m_sound_mixer.m_sound_cache[current_slot].m_unique_id); - } - } -} - -// Begin sound frame -void win_llsSystem::SoundStartFrame(void) { - float frame_time; - int current_slot; - int i; - - if (m_timer_last_frametime == -1) { - frame_time = 0.0f; - } else { - frame_time = (timer_GetMSTime() - m_timer_last_frametime) / 1000.0f; - } - m_timer_last_frametime = timer_GetMSTime(); - - // perform necessary functions if sound events are pending for frame, this doesn't have to do anything - // if the mixer doesn't require such actions. Aureal does though. - if (m_pending_actions) { - mprintf(0, "pending actions\n"); - } - - // start mixer dependant frame - m_in_sound_frame = true; - m_pending_actions = false; - - // cleanup sound cache. - // mprintf(0, "StartCleanup\n"); - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - for (i = 0; i < m_sound_mixer.m_max_sounds_played; i++) { - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[i]; - update_directsound_sb(sb, true); - } - } - // mprintf(0, "EndCleanup\n"); - - int counter = 0, loop_counter = 0, stream_counter = 0, buf_loop_counter = 0; - -#ifdef _DEBUG - int n_p5 = 0, n_p4 = 0, n_p3 = 0, n_p2 = 0, n_p1 = 0, n_p0 = 0; -#endif - - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[current_slot]; - if (sb->m_status != SSF_UNUSED) { - counter++; - if (sb->m_status & SSF_PLAY_LOOPING) { - if (sb->m_status & SSF_BUFFERED_LOOP) - buf_loop_counter++; - loop_counter++; - } - if (sb->m_status & SSF_PLAY_STREAMING) - stream_counter++; - -#ifdef _DEBUG - if (sb->play_info->priority == SND_PRIORITY_CRITICAL) - n_p5++; - else if (sb->play_info->priority == SND_PRIORITY_HIGHEST) - n_p4++; - else if (sb->play_info->priority == SND_PRIORITY_HIGH) - n_p3++; - else if (sb->play_info->priority == SND_PRIORITY_NORMAL) - n_p2++; - else if (sb->play_info->priority == SND_PRIORITY_LOW) - n_p1++; - else if (sb->play_info->priority == SND_PRIORITY_LOWEST) - n_p0++; -#endif - } - } - - // update cache stress timer. - if (counter < (m_sound_mixer.m_max_sounds_played * 3 / 4)) { - m_cache_stress_timer += frame_time; - } else { - m_cache_stress_timer = 0.0f; - } - -#ifdef _DEBUG - mprintf_at(3, 2, 0, "LNS: %02d/%02d", counter, m_sound_mixer.m_max_sounds_played); - mprintf_at(3, 3, 1, "Lp: %02d", loop_counter); - mprintf_at(3, 4, 1, "St: %02d", stream_counter); - mprintf_at(3, 5, 0, " Ot: %02d", counter - loop_counter - stream_counter); - - if (m_sound_mixer.m_loop_method != DSLOOP_STREAM_METHOD && m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - mprintf_at(3, 3, 10, "Bf: %02d", buf_loop_counter); - } - - mprintf_at(3, 2, 20, "P5:%02d P4:%02d P3:%02d", n_p5, n_p4, n_p3); - mprintf_at(3, 3, 20, "P2:%02d P1:%02d P0:%02d", n_p2, n_p1, n_p0); -#endif -} - -// End sound frame -void win_llsSystem::SoundEndFrame(void) { - CheckForErrors(); // handles errors. - - m_in_sound_frame = false; -} - -bool win_llsSystem::LockSound(int sound_uid) { return false; } - -bool win_llsSystem::UnlockSound(int sound_uid) { return false; } - -// True means it was already loaded, false means that it was not -bool win_llsSystem::CheckAndForceSoundDataAlloc(int sound_index) { - int result; - int sound_file_index = Sounds[sound_index].sample_index; - - ASSERT(sound_file_index >= 0 && sound_file_index < MAX_SOUND_FILES); - - if (sound_file_index < 0 || sound_file_index >= MAX_SOUND_FILES) { - return false; - } - - // Check if the sample data is already loaded - if (SoundFiles[sound_file_index].sample_16bit != NULL || SoundFiles[sound_file_index].sample_8bit != NULL) - return true; - - // If not, get the sound data - result = SoundLoadWaveFile(SoundFiles[sound_file_index].name, Sounds[sound_index].import_volume, sound_file_index, - (m_sound_quality == SQT_HIGH), true); - - // Why would it load once (table load time) and not now? - if (!result) - return false; - - mprintf(0, "Sound %s loaded.\n", SoundFiles[sound_file_index].name); - - return true; -} - -bool win_llsSystem::SetSoundQuality(char quality) { - int i; - - if (quality == m_sound_quality) - return true; - - // pause any sounds that may be playing - win_llsSystem::PauseSounds(); - - if (quality == SQT_NORMAL) { - m_sound_quality = SQT_NORMAL; - } else { - m_sound_quality = SQT_HIGH; - } - - for (i = 0; i < MAX_SOUNDS; i++) { - if (Sounds[i].used != 0) { - int j = Sounds[i].sample_index; - - if (SoundFiles[j].sample_8bit && m_sound_quality == SQT_HIGH) { - mem_free(SoundFiles[j].sample_8bit); - SoundFiles[j].sample_8bit = NULL; - - CheckAndForceSoundDataAlloc(i); - } - if (SoundFiles[j].sample_16bit && m_sound_quality == SQT_NORMAL) { - int count; - - ASSERT(SoundFiles[j].sample_8bit == NULL); - SoundFiles[j].sample_8bit = (uint8_t *)mem_malloc(SoundFiles[j].sample_length); - - // NOTE: Interesting note on sound conversion: 16 bit sounds are signed (0 biase). 8 bit sounds are unsigned - // (+128 biase). - for (count = 0; count < (int)SoundFiles[j].sample_length; count++) { - SoundFiles[j].sample_8bit[count] = (uint8_t)((((int)SoundFiles[j].sample_16bit[count]) + 32767) >> 8); - } - - mem_free(SoundFiles[j].sample_16bit); - SoundFiles[j].sample_16bit = NULL; - } - } - } - - win_llsSystem::ResumeSounds(); - - return true; -} - -char win_llsSystem::GetSoundQuality(void) { return m_sound_quality; } - -bool win_llsSystem::SetSoundMixer(char mixer_type) { - if (mixer_type == m_mixer_type) - return true; - else { - // Chris note: This is not the best way to do this. All the currently playing - // sounds are lost. This shouldn't happen. A real solutions has to take in account - // for three things: Normal sounds, looping sounds, and streaming audio. - DestroySoundLib(); - InitSoundLib(mixer_type, SoundApp, m_sound_mixer.m_max_sounds_played); - SetSoundQuality(m_sound_quality); - } - return true; -} - -char win_llsSystem::GetSoundMixer(void) { return m_mixer_type; } - -void win_llsSystem::SetListener(pos_state *cur_pos) { - if (!m_f_sound_lib_init) - return; - - m_emulated_listener.orient = *cur_pos->orient; - m_emulated_listener.position = *cur_pos->position; - m_emulated_listener.velocity = *cur_pos->velocity; - - if (IS_3D_MIXER(m_mixer_type)) { - m_lp_listener->SetOrientation(cur_pos->orient->fvec.x, cur_pos->orient->fvec.y, cur_pos->orient->fvec.z, - cur_pos->orient->uvec.x, cur_pos->orient->uvec.y, cur_pos->orient->uvec.z, - DS3D_DEFERRED); - m_lp_listener->SetPosition(cur_pos->position->x, cur_pos->position->y, cur_pos->position->z, DS3D_DEFERRED); - m_lp_listener->SetVelocity(cur_pos->velocity->x, cur_pos->velocity->y, cur_pos->velocity->z, DS3D_DEFERRED); - m_lp_listener->CommitDeferredSettings(); - } -} - -// AdjustSound2d -- adjusts the volume, pan, and freq. of a sound -void win_llsSystem::AdjustSound(int sound_uid, float f_volume, float f_pan, uint16_t frequency) { - int current_slot; - - if (!m_f_sound_lib_init) - return; - - if ((current_slot = ValidateUniqueId(sound_uid)) == -1) - return; - if (m_sound_mixer.m_sound_cache[current_slot].m_status == SSF_UNUSED) - return; - - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[current_slot]; - play_information *play_info = sb->play_info; - - play_info->left_volume = play_info->right_volume = f_volume; - if (f_pan < 0.0) - play_info->right_volume += f_volume * f_pan; - else - play_info->left_volume -= f_volume * f_pan; - - sb_adjust_properties_2d(&m_sound_mixer.m_sound_cache[current_slot], f_volume, f_pan, frequency); - - return; -} - -void win_llsSystem::AdjustSound(int sound_uid, pos_state *cur_pos, float adjusted_volume, float reverb) { - if (!m_f_sound_lib_init) - return; - - LPDIRECTSOUNDBUFFER lp_dsb; - // LPDIRECTSOUND3DBUFFER lpDSB3D; - int current_slot; - - if (!m_f_sound_lib_init) - return; - - if ((current_slot = ValidateUniqueId(sound_uid)) == -1) - return; - if (m_sound_mixer.m_sound_cache[current_slot].m_status == SSF_UNUSED) - return; - - // sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[current_slot]; - - if (IS_3D_MIXER(m_mixer_type)) { - int sound_index = m_sound_mixer.m_sound_cache[current_slot].m_sound_index; - lp_dsb = m_sound_mixer.m_sound_cache[current_slot].m_sound_buffer; - if (lp_dsb == NULL) - return; - - sb_adjust_properties_3d(&m_sound_mixer.m_sound_cache[current_slot], adjusted_volume, cur_pos, reverb); - } else { - // We need to determine the pan and volume - float volume; - - volume = adjusted_volume; - - float dist; - vector dir_to_sound = *cur_pos->position - m_emulated_listener.position; - float pan; - - dist = vm_NormalizeVector(&dir_to_sound); - if (dist < .1f) { - dir_to_sound = m_emulated_listener.orient.fvec; - } - - if (dist >= Sounds[m_sound_mixer.m_sound_cache[current_slot].m_sound_index].max_distance) { - volume = 0.0f; - } else if (dist > Sounds[m_sound_mixer.m_sound_cache[current_slot].m_sound_index].min_distance) { - volume *= (1.0 - ((dist - Sounds[m_sound_mixer.m_sound_cache[current_slot].m_sound_index].min_distance) / - (Sounds[m_sound_mixer.m_sound_cache[current_slot].m_sound_index].max_distance - - Sounds[m_sound_mixer.m_sound_cache[current_slot].m_sound_index].min_distance))); - } - - pan = (dir_to_sound * m_emulated_listener.orient.rvec); - - if (volume < 0.0f) - volume = 0.0f; - else if (volume > 1.0f) - volume = 1.0f; - - if (pan < -1.0f) - pan = -1.0f; - else if (pan > 1.0f) - pan = 1.0f; - - AdjustSound(m_sound_mixer.m_sound_cache[current_slot].m_unique_id, volume, pan, 22050); - } - - return; -} - -int win_llsSystem::PlaySound3d(play_information *play_info, int sound_index, pos_state *cur_pos, float adjusted_volume, - bool f_looped, float reverb) { - int16_t sound_slot; - DWORD ds_flags = 0; - float volume; - - volume = adjusted_volume; // Adjust base volume by sent volume, let 3d stuff do the rest - - if (!m_f_sound_lib_init) - return -1; - - ASSERT(Sounds[sound_index].used != 0); - if (Sounds[sound_index].used == 0) - return -1; - - if (!IS_3D_MIXER(m_mixer_type)) { - float dist; - vector dir_to_sound = *cur_pos->position - m_emulated_listener.position; - float pan; - - dist = vm_NormalizeVector(&dir_to_sound); - if (dist < .1f) { - dir_to_sound = m_emulated_listener.orient.fvec; - } - - if (dist >= Sounds[sound_index].max_distance) { - return -1; - } else if (dist > Sounds[sound_index].min_distance) { - volume *= (1.0 - ((dist - Sounds[sound_index].min_distance) / - (Sounds[sound_index].max_distance - Sounds[sound_index].min_distance))); - } - - pan = (dir_to_sound * m_emulated_listener.orient.rvec); - - if (volume < 0.0f) - volume = 0.0f; - else if (volume > 1.0f) - volume = 1.0f; - - if (pan < -1.0f) - pan = -1.0f; - else if (pan > 1.0f) - pan = 1.0f; - - return PlaySound2d(play_info, sound_index, volume, pan, f_looped); - } - -// Out of sound slots -#ifdef _DEBUG - sound_slot = FindFreeSoundSlot(sound_index, volume, play_info->priority); -#else - sound_slot = FindFreeSoundSlot(volume, play_info->priority); -#endif - - if (sound_slot < 0) { - return -1; - } - - m_sound_mixer.m_sound_cache[sound_slot].play_info = play_info; - m_total_sounds_played++; - m_sound_mixer.m_sound_cache[sound_slot].m_unique_id = MakeUniqueId(sound_slot); - ASSERT(m_sound_mixer.m_sound_cache[sound_slot].m_unique_id != -1); - - // 3-D!! - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[sound_slot]; - - sb->m_buffer_type = SBT_3D; - sb->m_sound_index = sound_index; - - if (f_looped) { - LoopStartStreaming(sb, SBT_3D, adjusted_volume, 0.0, cur_pos); - if (sb->m_snd_obj == NULL) { - sb->m_sound_buffer = NULL; - Int3(); - return -1; - } - } else { - tPSBInfo psb; - - if (SoundFiles[Sounds[sound_index].sample_index].use_count > 0) { - if (DuplicateSoundBuffer(sb)) { - goto play_sound; - } - } - if (!CreateSoundBuffer(sb, false)) { - return -1; - } - if (!LoadSoundBuffer(sb)) { - sb_free_buffer(sb); - return -1; - } - - play_sound: - sb->m_status = SSF_PLAY_NORMAL; - - psb.cur_pos = cur_pos; - psb.volume = volume; - psb.freq = 22050; - psb.reverb = reverb; - psb.looping = false; - if (!PlaySoundBuffer(sb, &psb)) { - sb_free_buffer(sb); - return -1; - } -/* - mprintf(0, "SL Play sound on slot %d, TP = %d UI = %X\n", - sound_slot, - TotalSoundsPlayed, - m_sound_mixer.m_sound_cache[sound_slot].m_unique_id); -*/ - } - - m_sound_mixer.m_cur_sounds_played++; - - return (sb->m_unique_id); -} - -// These work in samples to make things easier in the long run -int win_llsSystem::SetSoundPos(int sound_uid, int pos) { - int current_slot; - - if (pos <= 0) - return 1; - - if (!m_f_sound_lib_init) - return -1; - if ((current_slot = ValidateUniqueId(sound_uid)) == -1) - return -1; - if (m_sound_mixer.m_sound_cache[current_slot].m_status == SSF_UNUSED) - return -1; - - m_sound_mixer.m_sound_cache[current_slot].play_info->m_samples_played = pos; - - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[current_slot]; - - if (sb->stereo) { - pos *= 2; - } - - if (sb->bps == 16) { - pos *= 2; - } - - sb_set_current_position(sb, pos); - } - - return 1; -} - -// These work in samples to make things easier in the long run -int win_llsSystem::GetSoundPos(int sound_uid) { - int current_slot; - uint32_t temp, pos; - - if (!m_f_sound_lib_init) - return -1; - if ((current_slot = ValidateUniqueId(sound_uid)) == -1) - return -1; - if (m_sound_mixer.m_sound_cache[current_slot].m_status == SSF_UNUSED) - return -1; - - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[current_slot]; - - temp = sb_get_current_position(sb, &pos); - - if (sb->stereo) { - pos /= 2; - } - if (sb->bps == 16) { - pos /= 2; - } - - // Updates the readable data - m_sound_mixer.m_sound_cache[current_slot].play_info->m_samples_played = pos; - - return pos; - } else { - return m_sound_mixer.m_sound_cache[current_slot].play_info->m_samples_played; - } - - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -bool win_llsSystem::CreateSoundBuffer(sound_buffer_info *sb, bool f_is_stereo, int size, bool dynamic) { - // do buffer creation - int buftype = sb->m_buffer_type; - bool f_sample_16bit; - int sound_length; - - get_sound_info(sb, &sound_length, &f_sample_16bit); - - if (size != -1) { - sound_length = size; - } - - switch (m_mixer_type) { - case SOUND_MIXER_SOFTWARE_16: - Int3(); - break; - default: - CreateDSBuffer(buftype, &sb->m_sound_buffer, &sb->m_sound_buffer_3d, sound_length, 22050, f_is_stereo, - f_sample_16bit); - - sb->m_lpksps = NULL; - if (m_mixer_type == SOUND_MIXER_CREATIVE_EAX) { - EAX_InitSource(sb->m_sound_buffer_3d, &sb->m_lpksps); - } - - if (!sb->m_sound_buffer) { - Int3(); - sb->m_status = SSF_UNUSED; - return false; - } - } - - sb->m_mixer_type = m_mixer_type; - sb->bps = f_sample_16bit ? 16 : 8; - sb->stereo = f_is_stereo; - - if (sb->m_sound_index > -1) { - SoundFiles[Sounds[sb->m_sound_index].sample_index].use_count++; - // Global_DS_alloced_sounds++; - } - - return true; -} - -bool win_llsSystem::LoadSoundBuffer(sound_buffer_info *sb) { - // play 2d sound - int buftype = sb->m_buffer_type; - bool f_sample_16bit; - char *sample_ptr; - int sound_length; - - // get pointer - sample_ptr = get_sound_info(sb, &sound_length, &f_sample_16bit); - sb->sample_data = sample_ptr; - sb->sample_length = (int)sound_length; - - // do buffer creation - switch (m_mixer_type) { - case SOUND_MIXER_SOFTWARE_16: - Int3(); - break; - default: - if (LoadSoundData(sb->m_sound_buffer, sample_ptr, sound_length) != DS_OK) { - Int3(); - sb->m_status = SSF_UNUSED; - return false; - } - } - - return true; -} - -bool win_llsSystem::PlaySoundBuffer(sound_buffer_info *sb, tPSBInfo *psb) { - bool f_looping; - - if (!m_f_sound_lib_init) - return false; - if (!m_in_sound_frame) - m_pending_actions = true; - -TryPlayAgainLabel: - if (psb) { - if (sb->m_buffer_type == SBT_2D) { - AdjustSound(sb->m_unique_id, psb->volume, psb->pan, psb->freq); - } else if (sb->m_buffer_type == SBT_3D) { - AdjustSound(sb->m_unique_id, psb->cur_pos, psb->volume, psb->reverb); - } - - SetSoundPos(sb->m_unique_id, sb->play_info->m_samples_played); - - f_looping = psb->looping; - } else { - f_looping = ((sb->m_status & SSF_PLAY_LOOPING) || sb->s) ? true : false; - if (f_looping && m_sound_mixer.m_loop_method == DSLOOP_BUFFER_METHOD && sb->s->loop_step != 0 && - (sb->m_status & SSF_BUFFERED_LOOP)) { - f_looping = false; - } - } - - switch (m_mixer_type) { - case SOUND_MIXER_SOFTWARE_16: - Int3(); - break; - - default: { - LPDIRECTSOUNDBUFFER sound_ptr = sb->m_sound_buffer; - DWORD ds_flags = f_looping ? DSBPLAY_LOOPING : 0; - - ASSERT(sound_ptr); - - if (sound_ptr->Play(0, 0, ds_flags) == DSERR_BUFFERLOST) { - if (LoadSoundData(sound_ptr, sb->sample_data, sb->sample_length) == DS_OK) { - goto TryPlayAgainLabel; - } - - sb->m_status = SSF_UNUSED; - - // Some type of error -- we cannot play the sound? -- get chris - Int3(); - return false; - } - } - } - - return true; -} - -bool win_llsSystem::DuplicateSoundBuffer(sound_buffer_info *sb) { - return false; // for now, let's not do this. -/* - sound_buffer_info *source_sb = m_sound_mixer.FindSoundBuffer(sb->m_sound_index); - - ASSERT(m_mixer_type != SOUND_MIXER_SOFTWARE_16); - - if (!source_sb) { - Int3(); - return false; - } - - // we have a source sound buffer. let's use it. - if (m_mixer_type == SOUND_MIXER_AUREAL) { - sb->m_snd_obj = A3D_DuplicateSource(source_sb->m_snd_obj); - if (!sb->m_snd_obj) { - return false; - } - } else { - HRESULT hr; - hr = m_lp_ds->DuplicateSoundBuffer(source_sb->m_sound_buffer, &sb->m_sound_buffer); - if (FAILED(hr)) { - mprintf(0, "DDSNDLIB: Failed to duplicate sound buffer (%x)\n", hr); - return false; - } - - if (IS_3D_MIXER(m_mixer_type)) { - // a 3d buffer needs a 3d interface pointer - if (sb->m_buffer_type == SBT_3D) { - hr = sb->m_sound_buffer->QueryInterface(IID_IDirectSound3DBuffer, (void **)&sb->m_sound_buffer_3d); - if (FAILED(hr)) { - mprintf(0, "DDSNDLIB: Failed to acquire 3d interface from duplicate buffer (%x)\n", hr); - return false; - } - } - } - } - - sb->m_mixer_type = source_sb->m_mixer_type; - sb->bps = source_sb->bps; - sb->stereo = source_sb->stereo; - sb->sample_data = source_sb->sample_data; - sb->sample_length = source_sb->sample_length; - - // mprintf(0, "Duplicated!!\n"); - SoundFiles[Sounds[sb->m_sound_index].sample_index].use_count++; - - return true; - */ -} - -// environmental sound interface -// volume modifier (0-1), damping(0-1), 1 = complete, 0 = none -// decay 0.1 to 100 seconds, how long it takes for a sound to die. -bool win_llsSystem::SetGlobalReverbProperties(float volume, float damping, float decay) { - if (m_mixer_type == SOUND_MIXER_CREATIVE_EAX) { - return EAX_SetEnvironmentalReverb(volume, damping, decay); - } - - return false; -} - -sound_buffer_info *sound_buffer_cache::FindSoundBuffer(int sound_index) { - int i; - - // is there's no use count for this soudn, then there should be no available buffer. - if (SoundFiles[Sounds[sound_index].sample_index].use_count == 0) { - return NULL; - } - - // returns a sound buffer with the 'sound_index' if it is still active. - // we can use the sound buffer to create duplicates. - for (i = 0; i < m_max_sounds_played; i++) { - sound_buffer_info *sb = &m_sound_cache[i]; - - if (sb->m_status != SSF_UNUSED) { - if (sb->m_sound_index == sound_index) { - return sb; - } - } - } - - return NULL; -} - -// set special parameters for the 3d environment. -// of strcuture passed, you must set the appropriate 'flags' value for values you wish to modify -void win_llsSystem::SetEnvironmentValues(const t3dEnvironmentValues *env) { - if (CHECK_FLAG(env->flags, ENV3DVALF_DOPPLER)) { - Env3dValues.doppler_scalar = env->doppler_scalar; - } -} - -// get special parameters for the 3d environment. -// of strcuture passed, you must set the appropriate 'flags' value for values you wish to modify -void win_llsSystem::GetEnvironmentValues(t3dEnvironmentValues *env) { - if (CHECK_FLAG(env->flags, ENV3DVALF_DOPPLER)) { - env->doppler_scalar = Env3dValues.doppler_scalar; - } -} - -// enable special parameters for the 3d environment. -// of strcuture passed, you must set the appropriate 'flags' value for values you wish to modify -void win_llsSystem::SetEnvironmentToggles(const t3dEnvironmentToggles *env) { - t3dEnvironmentValues values; - - if (CHECK_FLAG(env->flags, ENV3DVALF_DOPPLER)) { - // set toggle then set doppler again. - Env3dToggles.doppler = env->doppler; - values.flags = ENV3DVALF_DOPPLER; - values.doppler_scalar = Env3dValues.doppler_scalar; - SetEnvironmentValues(&Env3dValues); - } - if (CHECK_FLAG(env->flags, ENV3DVALF_GEOMETRY)) { - // initialize geometry object if available and true. - if (m_geometry) { - delete m_geometry; - } - m_geometry = NULL; - Env3dToggles.geometry = m_geometry ? true : false; - } -} - -// get states of special parameters for the 3d environment. -// of strcuture passed, you must set the appropriate 'flags' value for values you wish to modify -void win_llsSystem::GetEnvironmentToggles(t3dEnvironmentToggles *env) { - if (CHECK_FLAG(env->flags, ENV3DVALF_DOPPLER)) { - env->doppler = Env3dToggles.doppler; - } - - env->supported = 0; -} - -// Sound System Error Handler. -void win_llsSystem::CheckForErrors() { - // if a fatal error occurred, quit and display an error - // non fatal errors should be put inside a logfile, or just mprinted out. - switch (m_lib_error_code) { - case SSL_ERROR_SAMPLE_NODATA: - Error("%s\nSample had no data.", m_error_text); - break; - - case SSL_ERROR_STREAMMIXER: - Error("%s\nMixer alignment check failed.", m_error_text); - break; - - case SSL_ERROR_GENERIC: - Error("%s\nGeneric error.", m_error_text); - break; - } - - // must call! - llsSystem::CheckForErrors(); - - // add our default error string. - char buf[8]; - sprintf(buf, "mix:%d\n", m_mixer_type); - strcat(m_error_text, buf); -} - -///////////////////////////////////////////////////////////////////////////////////// -// set auxillary 3d sound properties -bool win_llsSystem::SoundPropertySupport() const { - switch (m_mixer_type) { - case SOUND_MIXER_CREATIVE_EAX: - if (EAX_Caps() & EAXF_SOURCE_OBSTRUCTION) { - return true; - } - break; - } - - return false; -} - -// sound obstruction from 0 to 1.0 (1.0 = fully obstructed) -void win_llsSystem::SetSoundProperties(int sound_uid, float obstruction) { - sound_buffer_info *sb; - int current_slot; - - if (!m_f_sound_lib_init) - return; - - if ((current_slot = ValidateUniqueId(sound_uid)) == -1) - return; - - sb = &m_sound_mixer.m_sound_cache[current_slot]; - - switch (m_mixer_type) { - case SOUND_MIXER_CREATIVE_EAX: - EAX_SetSourceProperties(sb->m_lpksps, obstruction); - break; - } -} diff --git a/sndlib/dsound3d.cpp b/sndlib/dsound3d.cpp deleted file mode 100644 index 4af8c3b4..00000000 --- a/sndlib/dsound3d.cpp +++ /dev/null @@ -1,616 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* This program 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. -* -* This program 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 this program. If not, see . - ---- HISTORICAL COMMENTS FOLLOW --- - - * $Source: $ - * $Revision: 6 $ - * $Author: Samir $ - * $Date: 5/03/99 3:12a $ - * - * Direct Sound subsystem. - * - * $Log: /DescentIII/Main/dd_sndlib/dsound3d.cpp $ - * - * 6 5/03/99 3:12a Samir - * fixed up aureal so it works (a little slow though...) - * - * 5 4/29/99 3:01p Samir - * added code for direct sound mixers only (and function for Aureal - * really) that will use direct sound looping for simple loops. - * - * 4 4/25/99 9:53p Samir - * added debugging. - * - * 3 4/23/99 7:51p Samir - * looping fixes for directsound. - * - * 2 4/22/99 10:33p Samir - * modifications so that DirectSound mixers use one thread for all looping - * and streaming sounds. It worked without crashing for about twenty - * minutes of playing from level 1 to level 2 of D3. We'll see. - * - * 1 4/22/99 10:30p Samir - * initial revision ( a bit messy) - * - */ - -#include "ds3dlib_internal.h" -#include "auddev.h" - -#include "pserror.h" - -#include - -static struct t_sb_loop_thread_data { - win_llsSystem *m_ll_sndsys; - uintptr_t thread_handle; - int16_t no_callbacks; - bool request_kill; - bool thread_alive; -} m_ds; - -static uint8_t m_sb_cur_timeslice; - -//////////////////////////////////////////////////////////////////////////////// -// DSLOOP_STREAM_METHOD - -inline void sb_loop_thread_clean_buffer(sound_buffer_info *sb) { - m_ds.m_ll_sndsys->GetSoundPos(sb->m_unique_id); - sb_stop_buffer(sb); - sb->s->playing = 0; - sb->s->kill_me = true; - - // TODO: investigate why this is -1 sometimes, 32bit builds seem to work by - // chance while 64bit builds crash without this ckeck - if (sb->m_sound_index < 0) { - return; - } - - if (SoundFiles[Sounds[sb->m_sound_index].sample_index].use_count > 0) { - SoundFiles[Sounds[sb->m_sound_index].sample_index].use_count--; - // DUPSND if (SoundFiles[Sounds[sb->m_sound_index].sample_index].use_count == 0) { - // Global_DS_alloced_sounds--; - // DUPSND } - } -} - -// helper functions for loop streaming. -void sb_loop_stream_copy(sound_buffer_info *sb, char *ptr, DWORD len) { - DWORD amt; - bool f_looping = (sb->m_status & SSF_PLAY_LOOPING) != 0; - char *sample_ptr; - - if (f_looping) { - const int sound_index = sb->m_sound_index; - int loop_start = Sounds[sound_index].loop_start; - int loop_end = Sounds[sound_index].loop_end; - if (sb->s->f_sample_16bit) { - loop_start = loop_start << 1; - loop_end = loop_end << 1; - sample_ptr = (char *)SoundFiles[Sounds[sound_index].sample_index].sample_16bit; - } else { - sample_ptr = (char *)SoundFiles[Sounds[sound_index].sample_index].sample_8bit; - } - - while (sb->s->num_written + (int)len >= loop_end) { - int num_till_loop_end = loop_end - sb->s->num_written; - int num_to_loop_start = sb->s->num_written - loop_start; - - if (num_till_loop_end > 0) { - memcpy(ptr, sb->s->current_position, num_till_loop_end); - len -= num_till_loop_end; - } - ptr += num_till_loop_end; - - sb->s->current_position = sample_ptr + loop_start; - // ASSERT(sb->s->current_position >= sample_ptr && sample_ptr == sb->sample_data); - - sb->s->num_written -= num_to_loop_start; - sb->s->bytes_left += num_to_loop_start; - - // ASSERT(sb->s->num_written == loop_start); - } - } - - amt = (len > sb->s->bytes_left) ? sb->s->bytes_left : len; - - // int i_amt = (int)amt; - - // ASSERT(i_amt >= 0); - - if (amt) { - memcpy(ptr, sb->s->current_position, amt); - sb->s->current_position += amt; - sb->s->bytes_left -= amt; - sb->s->num_written += amt; - // ASSERT(sb->s->current_position >= sb->sample_data); - } - - len -= amt; - - if (len) { - memset(ptr + amt, sb->s->silence_byte, len); - sb->s->close_on_next = 1; - } -} - -// helper functions for loop streaming. -void sb_loop_stream_fillhalf(sound_buffer_info *sb, DWORD half) { - char *ptr1 = NULL; - char *ptr2 = NULL; - uint32_t len1, len2; - - if (sb_lock_buffer(sb, half, sb->s->half_buffer_point, (void **)&ptr1, &len1, (void **)&ptr2, &len2)) { - // memset(ptr1, sb->s->silence_byte, len1); - sb_loop_stream_copy(sb, ptr1, len1); - if (ptr2) { - sb_loop_stream_copy(sb, ptr2, len2); - } - sb_unlock_buffer(sb, ptr1, len1, ptr2, len2); - } -} - -// helper functions for streaming -void sb_stream_copy(sound_buffer_info *sb, char *ptr, DWORD len) { - DWORD amt; - -new_data: - - amt = (len > sb->s->bytes_left) ? sb->s->bytes_left : len; - - ASSERT(amt >= 0); - - if (amt) { - ASSERT(sb->s->current_position); - - memcpy(ptr, sb->s->current_position, amt); - sb->s->current_position += amt; - sb->s->bytes_left -= amt; - } - - len -= amt; - - if (len) { - if (sb->play_info->m_stream_cback && sb->s->current_position) { - memset(ptr + amt, sb->s->silence_byte, len); - int new_len = sb->play_info->m_stream_size; - sb->s->current_position = - (char *)(*sb->play_info->m_stream_cback)(sb->play_info->user_data, sb->play_info->m_stream_handle, &new_len); - sb->play_info->m_stream_data = sb->s->current_position; - ASSERT(!(sb->play_info->m_stream_data && sb->play_info->m_stream_size <= 0)); - - sb->s->bytes_left = sb->play_info->m_stream_size; - - if (sb->s->current_position == NULL) { - sb->s->bytes_left = sb->play_info->m_stream_size = 0; - } - - goto new_data; - } - - memset(ptr + amt, sb->s->silence_byte, len); - sb->s->close_on_next = 1; - } -} - -void sb_stream_fillhalf(sound_buffer_info *sb, DWORD half) { - char *ptr1 = NULL; - char *ptr2 = NULL; - uint32_t len1, len2; - - if (sb_lock_buffer(sb, half, sb->s->half_buffer_point, (void **)&ptr1, &len1, (void **)&ptr2, &len2)) { - sb_stream_copy(sb, ptr1, len1); - if (ptr2) { - sb_stream_copy(sb, ptr2, len2); - } - sb_unlock_buffer(sb, ptr1, len1, ptr2, len2); - } -} - -// main looping thread. -void __cdecl sb_loop_thread(void *user_ptr) { - sound_buffer_cache *sndcache; - DWORD playp, writep, whichhalf; - int i; - uint8_t iteration; - - // validate thread - m_ds.m_ll_sndsys = (win_llsSystem *)user_ptr; - m_ds.thread_alive = true; - sndcache = &m_ds.m_ll_sndsys->m_sound_mixer; - iteration = 0; - - mprintf(0, "DS3DLIB: Looping thread begins.\n"); - - // main thread body - while (!m_ds.request_kill) { - if (m_ds.no_callbacks++ == 0) { - for (i = 0; i < sndcache->m_max_sounds_played; i++) { - sound_buffer_info *sb = &sndcache->m_sound_cache[i]; - - // skip unused slots and only handle looping (maybe streaming) slots. - if ((sb->m_status == SSF_UNUSED) || (sb->m_status & SSF_BUFFERED_LOOP) || !sb->s) { - continue; - } - if (!sb->s->playing) { // loops before calling play do have SSF_PLAY_LOOPING set, and MUST!! - continue; - } - - // at this point it's definitely either a streaming buffer or loop streaming buffer - if (sb->m_status & SSF_PLAY_STREAMING) { - // streams will stop at the request of the application always, unlike looping buffers (see below) - if (sb->s->please_close) { - sb_loop_thread_clean_buffer(sb); - // mprintf(0, "ds thread pleas_close request processed.\n"); - } else if (sb->m_status & SSF_PAUSED) { - continue; // just continue - } else if ((iteration % 4) == (sb->s->time_slice % 4)) { - // update streamed buffer only when allowed - playp = sb_get_current_position(sb, (uint32_t *)&writep); - whichhalf = (playp < sb->s->half_buffer_point) ? 0 : sb->s->half_buffer_point; - - if (whichhalf != sb->s->last_half) { - if (sb->s->close_on_next) { - sb_loop_thread_clean_buffer(sb); - } else { - sb_stream_fillhalf(sb, sb->s->last_half); - sb->s->last_half = whichhalf; - } - } - // mprintf(0, "ds thread stream update.\n"); - } - } else if (!(sb->m_status & SSF_BUFFERED_LOOP)) { - // this slot is a looping slot. check to see if app requested closing this loop. - // also we don't check the looping flag because we could be playing the end part of a loop - // and the stream filling code below will set close_on_next when done itself. - if (sb->s->please_close) { - sb_loop_thread_clean_buffer(sb); - } else if (sb->m_status & SSF_PAUSED) { - continue; // just continue - } else if ((iteration % 4) == (sb->s->time_slice % 4)) { - // update looped buffer only when allowed - playp = sb_get_current_position(sb, (uint32_t *)&writep); - whichhalf = (playp < sb->s->half_buffer_point) ? 0 : sb->s->half_buffer_point; - - if (whichhalf != sb->s->last_half) { - if (sb->s->close_on_next) { - sb_loop_thread_clean_buffer(sb); - } else { - sb_loop_stream_fillhalf(sb, sb->s->last_half); - sb->s->last_half = whichhalf; - } - } - } - } - } - iteration++; - } - m_ds.no_callbacks--; - Sleep(DSPB_TICK_MILLISECONDS); // defer to OS - } - - // invalidate thread - m_ds.thread_alive = false; - m_ds.m_ll_sndsys = NULL; - mprintf(0, "DS3DLIB: Looping thread done.\n"); -} - -/////////////////////////////////////////////////////////////////////////////// -// this will initialize the looping thread - -bool sb_loop_thread_init(win_llsSystem *lls) { - // start looping thread - m_sb_cur_timeslice = 0; - - m_ds.request_kill = false; - m_ds.thread_alive = false; - m_ds.no_callbacks = 1; - - m_ds.thread_handle = _beginthread(sb_loop_thread, 16384, (void *)lls); - if (m_ds.thread_handle == -1) { - return false; - } - if (!SetThreadPriority((HANDLE)m_ds.thread_handle, THREAD_PRIORITY_TIME_CRITICAL)) { - return false; - } - - m_ds.no_callbacks = 0; - - return true; -} - -void sb_loop_thread_kill() { - if (m_ds.thread_alive) { - mprintf(0, "DS3DLIB: Killing looping thread.\n"); - m_ds.request_kill = true; - while (m_ds.thread_alive) { - Sleep(DSPB_TICK_MILLISECONDS); - } - } -} - -// a lot of looping info will be initialized here, including copying data, etc. -bool sb_loop_element_init(sound_buffer_info *sb, char *sample_ptr, int sound_length, int buffer_size) { - // finish initting loop - if (!sb->s) { - Int3(); - return false; - } - - sb->s->time_slice = m_sb_cur_timeslice; // allocate timeslice for updating. - sb->s->half_buffer_point = buffer_size / 2; - sb->s->current_position = sample_ptr; - sb->s->bytes_left = sound_length; - sb->s->silence_byte = (sb->s->f_sample_16bit) ? 0 : 128; - sb_loop_stream_fillhalf(sb, 0); - sb_loop_stream_fillhalf(sb, sb->s->half_buffer_point); - - sb->s->close_on_next = 0; - sb->s->kill_me = false; - m_ds.m_ll_sndsys->SetSoundPos(sb->m_unique_id, sb->play_info->m_samples_played); - - m_sb_cur_timeslice++; - - return true; -} - -void sb_loop_element_kill(sound_buffer_info *sb) { sb->s->please_close = 1; } - -void sb_loop_element_wait_until_dead(sound_buffer_info *sb) { - if (!sb->s) - return; - - while (!sb->s->kill_me) { - } -} - -// initialize streaming audio. -bool sb_stream_element_init(sound_buffer_info *sb, char *sample_ptr, int sound_length, int buffer_size) { - // finish initting loop - if (!sb->s) { - Int3(); - return false; - } - - sb->s->time_slice = m_sb_cur_timeslice; // allocate timeslice for updating. - - sb->s->half_buffer_point = buffer_size / 2; - sb->s->current_position = sample_ptr; - sb->s->bytes_left = sound_length; - sb->s->silence_byte = (sb->s->f_sample_16bit) ? 0 : 128; - sb_stream_fillhalf(sb, 0); - sb_stream_fillhalf(sb, sb->s->half_buffer_point); - sb->s->close_on_next = 0; - sb->s->kill_me = false; - - if (sb->m_status & SSF_BUFFERED_STRM) { - sb->s->hEvent = NULL; - /* sb->s->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if (sb->m_mixer_type == SOUND_MIXER_AUREAL) { - if (!A3D_SetSourceWaveEvent(sb->m_snd_obj, sb->s->half_buffer_point, sb->s->hEvent)) { - CloseHandle(sb->s->hEvent); - sb->s->hEvent = NULL; - return false; - } - } - else { - Int3(); - // unimplemented for normal DirectSound CloseHandle(sb->s->hEvent); sb->s->hEvent = NULL; - } - */ - } - - m_sb_cur_timeslice++; - - return true; -} - -// these work on buffered streams only -void sb_stream_element_kill(sound_buffer_info *sb) { - if (sb->m_status & SSF_BUFFERED_STRM) { - if (sb->s->hEvent) { - CloseHandle(sb->s->hEvent); - sb->s->hEvent = NULL; - } - } -} - -void sb_stream_buffered_update(sound_buffer_info *sb) { - DWORD playp, writep, whichhalf; - ASSERT((sb->m_status & SSF_BUFFERED_STRM)); - - playp = sb_get_current_position(sb, (uint32_t *)&writep); - whichhalf = (playp < sb->s->half_buffer_point) ? 0 : sb->s->half_buffer_point; - - if (whichhalf != sb->s->last_half) { - // mprintf(0, "DSOUND3D: event triggered. Updating stream half %d.\n", sb->s->last_half); - if (sb->s->close_on_next) { - extern win_llsSystem *ll_sound_ptr; - ll_sound_ptr->StopSound(sb->m_unique_id); - } else { - sb_stream_fillhalf(sb, sb->s->last_half); - sb->s->last_half = whichhalf; - } - } - - /* if (WaitForSingleObject(sb->s->hEvent, 0) == WAIT_OBJECT_0) { - // event was signaled by DirectSound/Aureal. do appropriate stream fill. - if (sb->s->close_on_next) { - extern win_llsSystem *ll_sound_ptr; - ll_sound_ptr->StopSound(sb->m_unique_id); - } - else { - mprintf(0, "DSOUND3D: event triggered. Updating stream half %d.\n", sb->s->last_half); - A3D_ClearSourceWaveEvents(sb->m_snd_obj); - sb_stream_fillhalf(sb, sb->s->last_half); - sb->s->last_half = (sb->s->last_half) ? 0 : sb->s->half_buffer_point; - ResetEvent(sb->s->hEvent); - if (sb->m_mixer_type == SOUND_MIXER_AUREAL) { - A3D_SetSourceWaveEvent(sb->m_snd_obj, sb->s->last_half, sb->s->hEvent); - } - else { - Int3(); - } - } - } - */ -} - -//////////////////////////////////////////////////////////////////////////////// -// DSLOOP_BUFFER_METHOD - -char *sb_get_loop_info(const sound_buffer_info *sb, int *loop_start, int *loop_end, bool *is_16_bit) { - int sound_index = sb->m_sound_index; - - if (sound_index > -1) { - *loop_start = Sounds[sound_index].loop_start; - *loop_end = Sounds[sound_index].loop_end; - - if (SoundFiles[Sounds[sound_index].sample_index].sample_16bit) { - *is_16_bit = true; - return (char *)SoundFiles[Sounds[sound_index].sample_index].sample_16bit; - } - if (SoundFiles[Sounds[sound_index].sample_index].sample_8bit) { - *is_16_bit = false; - return (char *)SoundFiles[Sounds[sound_index].sample_index].sample_8bit; - } - } - Int3(); - return NULL; -} - -char *sb_get_loop_step_info(const sound_buffer_info *sb, int step, bool is16bit, int *length) { - sound_file_info *sf; - char *sample_ptr; - - if (sb->m_sound_index < 0) { - Int3(); - return NULL; - } - - int loop_start_byte = Sounds[sb->m_sound_index].loop_start; - int loop_end_byte = Sounds[sb->m_sound_index].loop_end; - - if (is16bit) { - loop_start_byte = loop_start_byte << 1; - loop_end_byte = loop_end_byte << 1; - } - - sf = &SoundFiles[Sounds[sb->m_sound_index].sample_index]; - sample_ptr = is16bit ? (char *)sf->sample_16bit : (char *)sf->sample_8bit; - - if (step == DSBUFLOOP_INIT_STEP) { - *length = loop_start_byte; - return sample_ptr; - } - if (step == DSBUFLOOP_LOOP_STEP) { - *length = (loop_end_byte - loop_start_byte); - return (sample_ptr + loop_start_byte); - } - if (step == DSBUFLOOP_FINISH_STEP) { - int sample_length_byte = is16bit ? (sf->np_sample_length * 2) : sf->np_sample_length; - *length = (sample_length_byte - loop_end_byte); - return (sample_ptr + loop_end_byte); - } - - Int3(); // illegal step!! - *length = 0; - - return NULL; -} - -// steps to next state of buffered loop. -// force_next_step = -2, do it automatically, otherwise set 'next_step' using passed value. -// this will stop and free the current ds object -// advance to next valid step (may skip a step) -// if new step is > 1, then we're done. -// else create and play the new one if we can. - -// before destroying old object, we must get the current sound properties depending on buffer type. -// and set them for the new sound object. -// we will call either direct sound or custom mixer functions. -// yuck. - -void sb_buffered_loop_step(win_llsSystem *lls, sound_buffer_info *sb, int force_next_step) { - if (!sb->s) - return; - if (!(sb->m_status & SSF_BUFFERED_LOOP)) - return; - - tPSBInfo psb; - char *sample_ptr; - int sound_length; - - pos_state old_pos_state; - float old_pan; - float old_volume = 0.0f; - - ASSERT(lls->m_mixer_type != SOUND_MIXER_SOFTWARE_16 && lls->m_mixer_type != SOUND_MIXER_NONE); - - // get current properties. - old_pan = 0; - - // advance to next step. - sound_length = 0; - sb->s->loop_step = (force_next_step == -2) ? (sb->s->loop_step + 1) : force_next_step; - while (!sound_length && sb->s->loop_step < 2) { - sample_ptr = sb_get_loop_step_info(sb, sb->s->loop_step, sb->s->f_sample_16bit, &sound_length); - sb->s->loop_step++; - } - if (!sound_length && sb->s->loop_step == 2) { - // mprintf(0, "DS3DLIB: Buffered loop %d advancing to post-end step (done)\n", sb->m_unique_id); - lls->StopSound(sb->m_unique_id); - return; - } else { - sb_stop_buffer(sb); - sb_free_buffer(sb); - } - - sb->s->loop_step--; // return to proper step. - sb->s->loop_timer = 0.0f; - sb->s->bytes_left = sound_length; - sb->m_status = SSF_PLAY_LOOPING | SSF_BUFFERED_LOOP; - sb->sample_data = sample_ptr; - - // allocate buffer for playback - if (!lls->CreateSoundBuffer(sb, false, sb->s->bytes_left, true)) { - return; - } - - if (!sb_load_buffer(sb, sb->sample_data, sound_length)) { - return; - } - - // using old sound properties, play the next buffer with those qualities! - psb.looping = (sb->s->loop_step == 0) ? true : false; - - if (sb->m_buffer_type == SBT_3D) { - psb.cur_pos = &old_pos_state; - } else { - psb.pan = old_pan; - } - - psb.volume = old_volume; - psb.freq = 22050; - lls->PlaySoundBuffer(sb, &psb); - - // must be at end to initiate thread management. - sb->s->playing = 1; - - // mprintf(0, "DDSNDLIB: Buffered loop %d advancing to step %d.\n", sb->m_unique_id, sb->s->loop_step); -} diff --git a/sndlib/eax.cpp b/sndlib/eax.cpp deleted file mode 100644 index 823c7739..00000000 --- a/sndlib/eax.cpp +++ /dev/null @@ -1,335 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* This program 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. -* -* This program 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 this program. If not, see . - ---- HISTORICAL COMMENTS FOLLOW --- - - * $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 -#include - -#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 = (uint32_t)i; - break; - } - } - if (FAILED(EAX.m_lpksps->Set(DSPROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ENVIRONMENT, NULL, 0, - &EAX.m_preset.environment, sizeof(uint32_t)))) { - 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; -} diff --git a/sndlib/eax.h b/sndlib/eax.h deleted file mode 100644 index f11b928c..00000000 --- a/sndlib/eax.h +++ /dev/null @@ -1,105 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* This program 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. -* -* This program 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 this program. If not, see . -*/ - - -// EAX.H -- DirectSound Environmental Audio Extensions - -#ifndef EAX_H_INCLUDED -#define EAX_H_INCLUDED - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -// EAX (listener) reverb property set {4a4e6fc1-c341-11d1-b73a-444553540000} -DEFINE_GUID(DSPROPSETID_EAX_ReverbProperties, 0x4a4e6fc1, 0xc341, 0x11d1, 0xb7, 0x3a, 0x44, 0x45, 0x53, 0x54, 0x00, - 0x00); - -enum DSPROPERTY_EAX_REVERBPROPERTY { - DSPROPERTY_EAX_ALL, // all reverb properties - DSPROPERTY_EAX_ENVIRONMENT, // standard environment no. - DSPROPERTY_EAX_VOLUME, // loudness of the reverb - DSPROPERTY_EAX_DECAYTIME, // how long the reverb lasts - DSPROPERTY_EAX_DAMPING // the high frequencies decay faster -}; - -#define EAX_NUM_STANDARD_PROPERTIES (DSPROPERTY_EAX_DAMPING + 1) - -// use this structure for get/set all properties... -struct EAX_REVERBPROPERTIES { - uint32_t environment; // 0 to EAX_ENVIRONMENT_COUNT-1 - float fVolume; // 0 to 1 - float fDecayTime_sec; // seconds, 0.1 to 100 - float fDamping; // 0 to 1 -}; - -// #define EAX_MAX_ENVIRONMENT (EAX_ENVIRONMENT_COUNT - 1) - -// presets -#define EAX_PRESET_GENERIC EAX_ENVIRONMENT_GENERIC, 0.5F, 1.493F, 0.5F -#define EAX_PRESET_PADDEDCELL EAX_ENVIRONMENT_PADDEDCELL, 0.25F, 0.1F, 0.0F -#define EAX_PRESET_ROOM EAX_ENVIRONMENT_ROOM, 0.417F, 0.4F, 0.666F -#define EAX_PRESET_BATHROOM EAX_ENVIRONMENT_BATHROOM, 0.653F, 1.499F, 0.166F -#define EAX_PRESET_LIVINGROOM EAX_ENVIRONMENT_LIVINGROOM, 0.208F, 0.478F, 0.0F -#define EAX_PRESET_STONEROOM EAX_ENVIRONMENT_STONEROOM, 0.5F, 2.309F, 0.888F -#define EAX_PRESET_AUDITORIUM EAX_ENVIRONMENT_AUDITORIUM, 0.403F, 4.279F, 0.5F -#define EAX_PRESET_CONCERTHALL EAX_ENVIRONMENT_CONCERTHALL, 0.5F, 3.961F, 0.5F -#define EAX_PRESET_CAVE EAX_ENVIRONMENT_CAVE, 0.5F, 2.886F, 1.304F -#define EAX_PRESET_ARENA EAX_ENVIRONMENT_ARENA, 0.361F, 7.284F, 0.332F -#define EAX_PRESET_HANGAR EAX_ENVIRONMENT_HANGAR, 0.5F, 10.0F, 0.3F -#define EAX_PRESET_CARPETEDHALLWAY EAX_ENVIRONMENT_CARPETEDHALLWAY, 0.153F, 0.259F, 2.0F -#define EAX_PRESET_HALLWAY EAX_ENVIRONMENT_HALLWAY, 0.361F, 1.493F, 0.0F -#define EAX_PRESET_STONECORRIDOR EAX_ENVIRONMENT_STONECORRIDOR, 0.444F, 2.697F, 0.638F -#define EAX_PRESET_ALLEY EAX_ENVIRONMENT_ALLEY, 0.25F, 1.752F, 0.776F -#define EAX_PRESET_FOREST EAX_ENVIRONMENT_FOREST, 0.111F, 3.145F, 0.472F -#define EAX_PRESET_CITY EAX_ENVIRONMENT_CITY, 0.111F, 2.767F, 0.224F -#define EAX_PRESET_MOUNTAINS EAX_ENVIRONMENT_MOUNTAINS, 0.194F, 7.841F, 0.472F -#define EAX_PRESET_QUARRY EAX_ENVIRONMENT_QUARRY, 1.0F, 1.499F, 0.5F -#define EAX_PRESET_PLAIN EAX_ENVIRONMENT_PLAIN, 0.097F, 2.767F, 0.224F -#define EAX_PRESET_PARKINGLOT EAX_ENVIRONMENT_PARKINGLOT, 0.208F, 1.652F, 1.5F -#define EAX_PRESET_SEWERPIPE EAX_ENVIRONMENT_SEWERPIPE, 0.652F, 2.886F, 0.25F -#define EAX_PRESET_UNDERWATER EAX_ENVIRONMENT_UNDERWATER, 1.0F, 1.499F, 0.0F -#define EAX_PRESET_DRUGGED EAX_ENVIRONMENT_DRUGGED, 0.875F, 8.392F, 1.388F -#define EAX_PRESET_DIZZY EAX_ENVIRONMENT_DIZZY, 0.139F, 17.234F, 0.666F -#define EAX_PRESET_PSYCHOTIC EAX_ENVIRONMENT_PSYCHOTIC, 0.486F, 7.563F, 0.806F - -// EAX buffer reverb property set {4a4e6fc0-c341-11d1-b73a-444553540000} -DEFINE_GUID(DSPROPSETID_EAXBUFFER_ReverbProperties, 0x4a4e6fc0, 0xc341, 0x11d1, 0xb7, 0x3a, 0x44, 0x45, 0x53, 0x54, - 0x00, 0x00); - -enum DSPROPERTY_EAXBUFFER_REVERBPROPERTY { - DSPROPERTY_EAXBUFFER_ALL, // all reverb buffer properties - DSPROPERTY_EAXBUFFER_REVERBMIX // the wet source amount -}; - -// use this structure for get/set all properties... -struct EAXBUFFER_REVERBPROPERTIES { - float fMix; // linear factor, 0.0F to 1.0F -}; - -#define EAX_REVERBMIX_USEDISTANCE \ - -1.0F // out of normal range - // signifies the reverb engine should - // calculate it's own reverb mix value - // based on distance - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif diff --git a/sndlib/eax2.h b/sndlib/eax2.h deleted file mode 100644 index 35b02f33..00000000 --- a/sndlib/eax2.h +++ /dev/null @@ -1,404 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* This program 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. -* -* This program 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 this program. If not, see . -*/ - -/****************************************************************** - * - * EAX.H - DirectSound3D Environmental Audio Extensions version 2.0 - * Updated June 18, 1999 - * - ******************************************************************* - */ - -#ifndef EAX2_H_INCLUDED -#define EAX2_H_INCLUDED - -#include - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -#pragma pack(push, 4) - -/* - EAX Wrapper Interface -*/ -// {4FF53B81-1CE0-11d3-AAB8-00A0C95949D5} -DEFINE_GUID(CLSID_EAXDirectSound, 0x4ff53b81, 0x1ce0, 0x11d3, 0xaa, 0xb8, 0x0, 0xa0, 0xc9, 0x59, 0x49, 0xd5); - -__declspec(dllimport) HRESULT WINAPI EAXDirectSoundCreate(GUID *, LPDIRECTSOUND *, IUnknown FAR *); - -typedef HRESULT(FAR PASCAL *LPEAXDIRECTSOUNDCREATE)(GUID *, LPDIRECTSOUND *, IUnknown FAR *); - -/* - * EAX 2.0 listener property set {0306A6A8-B224-11d2-99E5-0000E8D8C722} - */ -DEFINE_GUID(DSPROPSETID_EAX20_ListenerProperties, 0x306a6a8, 0xb224, 0x11d2, 0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, - 0x22); - -// For compatibility with future EAX versions: -#define DSPROPSETID_EAX_ListenerProperties DSPROPSETID_EAX20_ListenerProperties - -enum DSPROPERTY_EAX_LISTENERPROPERTY { - DSPROPERTY_EAXLISTENER_NONE, - DSPROPERTY_EAXLISTENER_ALLPARAMETERS, - DSPROPERTY_EAXLISTENER_ROOM, - DSPROPERTY_EAXLISTENER_ROOMHF, - DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAXLISTENER_DECAYTIME, - DSPROPERTY_EAXLISTENER_DECAYHFRATIO, - DSPROPERTY_EAXLISTENER_REFLECTIONS, - DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY, - DSPROPERTY_EAXLISTENER_REVERB, - DSPROPERTY_EAXLISTENER_REVERBDELAY, - DSPROPERTY_EAXLISTENER_ENVIRONMENT, - DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE, - DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION, - DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF, - DSPROPERTY_EAXLISTENER_FLAGS -}; - -// OR these flags with property id -#define DSPROPERTY_EAXLISTENER_IMMEDIATE 0x00000000 // changes take effect immediately -#define DSPROPERTY_EAXLISTENER_DEFERRED 0x80000000 // changes take effect later -#define DSPROPERTY_EAXLISTENER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXLISTENER_NONE | DSPROPERTY_EAXLISTENER_IMMEDIATE) - -// Use this structure for DSPROPERTY_EAXLISTENER_ALLPARAMETERS -// - all levels are hundredths of decibels -// - all times are in seconds -// - the reference for high frequency controls is 5 kHz -// -// NOTE: This structure may change in future EAX versions. -// It is recommended to initialize fields by name: -// myListener.lRoom = -1000; -// myListener.lRoomHF = -100; -// ... -// myListener.dwFlags = myFlags /* see EAXLISTENERFLAGS below */ ; -// instead of: -// myListener = { -1000, -100, ... , 0x00000009 }; -// If you want to save and load presets in binary form, you -// should define your own structure to insure future compatibility. -// -struct EAXLISTENERPROPERTIES { - LONG lRoom; // room effect level at low frequencies - LONG lRoomHF; // room effect high-frequency level re. low frequency level - FLOAT flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - FLOAT flDecayTime; // reverberation decay time at low frequencies - FLOAT flDecayHFRatio; // high-frequency to low-frequency decay time ratio - LONG lReflections; // early reflections level relative to room effect - FLOAT flReflectionsDelay; // initial reflection delay time - LONG lReverb; // late reverberation level relative to room effect - FLOAT flReverbDelay; // late reverberation delay time relative to initial reflection - DWORD dwEnvironment; // sets all listener properties - FLOAT flEnvironmentSize; // environment size in meters - FLOAT flEnvironmentDiffusion; // environment diffusion - FLOAT flAirAbsorptionHF; // change in level per meter at 5 kHz - DWORD dwFlags; // modifies the behavior of properties -}; - -// used by DSPROPERTY_EAXLISTENER_ENVIRONMENT -enum { - EAX_ENVIRONMENT_GENERIC, - EAX_ENVIRONMENT_PADDEDCELL, - EAX_ENVIRONMENT_ROOM, - EAX_ENVIRONMENT_BATHROOM, - EAX_ENVIRONMENT_LIVINGROOM, - EAX_ENVIRONMENT_STONEROOM, - EAX_ENVIRONMENT_AUDITORIUM, - EAX_ENVIRONMENT_CONCERTHALL, - EAX_ENVIRONMENT_CAVE, - EAX_ENVIRONMENT_ARENA, - EAX_ENVIRONMENT_HANGAR, - EAX_ENVIRONMENT_CARPETEDHALLWAY, - EAX_ENVIRONMENT_HALLWAY, - EAX_ENVIRONMENT_STONECORRIDOR, - EAX_ENVIRONMENT_ALLEY, - EAX_ENVIRONMENT_FOREST, - EAX_ENVIRONMENT_CITY, - EAX_ENVIRONMENT_MOUNTAINS, - EAX_ENVIRONMENT_QUARRY, - EAX_ENVIRONMENT_PLAIN, - EAX_ENVIRONMENT_PARKINGLOT, - EAX_ENVIRONMENT_SEWERPIPE, - EAX_ENVIRONMENT_UNDERWATER, - EAX_ENVIRONMENT_DRUGGED, - EAX_ENVIRONMENT_DIZZY, - EAX_ENVIRONMENT_PSYCHOTIC, - - EAX_ENVIRONMENT_COUNT -}; - -// Used by DSPROPERTY_EAXLISTENER_FLAGS -// -// Note: The number and order of flags may change in future EAX versions. -// It is recommended to use the flag defines as follows: -// myFlags = EAXLISTENERFLAGS_DECAYTIMESCALE | EAXLISTENERFLAGS_REVERBSCALE; -// instead of: -// myFlags = 0x00000009; -// -// These flags determine what properties are affected by environment size. -#define EAXLISTENERFLAGS_DECAYTIMESCALE 0x00000001 // reverberation decay time -#define EAXLISTENERFLAGS_REFLECTIONSSCALE 0x00000002 // reflection level -#define EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE 0x00000004 // initial reflection delay time -#define EAXLISTENERFLAGS_REVERBSCALE 0x00000008 // reflections level -#define EAXLISTENERFLAGS_REVERBDELAYSCALE 0x00000010 // late reverberation delay time - -// This flag limits high-frequency decay time according to air absorption. -#define EAXLISTENERFLAGS_DECAYHFLIMIT 0x00000020 - -#define EAXLISTENERFLAGS_RESERVED 0xFFFFFFC0 // reserved future use - -// property ranges and defaults: - -#define EAXLISTENER_MINROOM -10000 -#define EAXLISTENER_MAXROOM 0 -#define EAXLISTENER_DEFAULTROOM -1000 - -#define EAXLISTENER_MINROOMHF -10000 -#define EAXLISTENER_MAXROOMHF 0 -#define EAXLISTENER_DEFAULTROOMHF -100 - -#define EAXLISTENER_MINROOMROLLOFFFACTOR 0.0f -#define EAXLISTENER_MAXROOMROLLOFFFACTOR 10.0f -#define EAXLISTENER_DEFAULTROOMROLLOFFFACTOR 0.0f - -#define EAXLISTENER_MINDECAYTIME 0.1f -#define EAXLISTENER_MAXDECAYTIME 20.0f -#define EAXLISTENER_DEFAULTDECAYTIME 1.49f - -#define EAXLISTENER_MINDECAYHFRATIO 0.1f -#define EAXLISTENER_MAXDECAYHFRATIO 2.0f -#define EAXLISTENER_DEFAULTDECAYHFRATIO 0.83f - -#define EAXLISTENER_MINREFLECTIONS -10000 -#define EAXLISTENER_MAXREFLECTIONS 1000 -#define EAXLISTENER_DEFAULTREFLECTIONS -2602 - -#define EAXLISTENER_MINREFLECTIONSDELAY 0.0f -#define EAXLISTENER_MAXREFLECTIONSDELAY 0.3f -#define EAXLISTENER_DEFAULTREFLECTIONSDELAY 0.007f - -#define EAXLISTENER_MINREVERB -10000 -#define EAXLISTENER_MAXREVERB 2000 -#define EAXLISTENER_DEFAULTREVERB 200 - -#define EAXLISTENER_MINREVERBDELAY 0.0f -#define EAXLISTENER_MAXREVERBDELAY 0.1f -#define EAXLISTENER_DEFAULTREVERBDELAY 0.011f - -#define EAXLISTENER_MINENVIRONMENT 0 -#define EAXLISTENER_MAXENVIRONMENT (EAX_ENVIRONMENT_COUNT - 1) -#define EAXLISTENER_DEFAULTENVIRONMENT EAX_ENVIRONMENT_GENERIC - -#define EAXLISTENER_MINENVIRONMENTSIZE 1.0f -#define EAXLISTENER_MAXENVIRONMENTSIZE 100.0f -#define EAXLISTENER_DEFAULTENVIRONMENTSIZE 7.5f - -#define EAXLISTENER_MINENVIRONMENTDIFFUSION 0.0f -#define EAXLISTENER_MAXENVIRONMENTDIFFUSION 1.0f -#define EAXLISTENER_DEFAULTENVIRONMENTDIFFUSION 1.0f - -#define EAXLISTENER_MINAIRABSORPTIONHF -100.0f -#define EAXLISTENER_MAXAIRABSORPTIONHF 0.0f -#define EAXLISTENER_DEFAULTAIRABSORPTIONHF -5.0f - -#define EAXLISTENER_DEFAULTFLAGS \ - (EAXLISTENERFLAGS_DECAYTIMESCALE | EAXLISTENERFLAGS_REFLECTIONSSCALE | EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE | \ - EAXLISTENERFLAGS_REVERBSCALE | EAXLISTENERFLAGS_REVERBDELAYSCALE | EAXLISTENERFLAGS_DECAYHFLIMIT) - -/* - * EAX 2.0 buffer property set {0306A6A7-B224-11d2-99E5-0000E8D8C722} - */ -DEFINE_GUID(DSPROPSETID_EAX20_BufferProperties, 0x306a6a7, 0xb224, 0x11d2, 0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, - 0x22); - -// For compatibility with future EAX versions: -#define DSPROPSETID_EAX_BufferProperties DSPROPSETID_EAX20_BufferProperties - -enum DSPROPERTY_EAX_BUFFERPROPERTY { - DSPROPERTY_EAXBUFFER_NONE, - DSPROPERTY_EAXBUFFER_ALLPARAMETERS, - DSPROPERTY_EAXBUFFER_DIRECT, - DSPROPERTY_EAXBUFFER_DIRECTHF, - DSPROPERTY_EAXBUFFER_ROOM, - DSPROPERTY_EAXBUFFER_ROOMHF, - DSPROPERTY_EAXBUFFER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAXBUFFER_OBSTRUCTION, - DSPROPERTY_EAXBUFFER_OBSTRUCTIONLFRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSION, - DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO, - DSPROPERTY_EAXBUFFER_OUTSIDEVOLUMEHF, - DSPROPERTY_EAXBUFFER_AIRABSORPTIONFACTOR, - DSPROPERTY_EAXBUFFER_FLAGS -}; - -// OR these flags with property id -#define DSPROPERTY_EAXBUFFER_IMMEDIATE 0x00000000 // changes take effect immediately -#define DSPROPERTY_EAXBUFFER_DEFERRED 0x80000000 // changes take effect later -#define DSPROPERTY_EAXBUFFER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXBUFFER_NONE | DSPROPERTY_EAXBUFFER_IMMEDIATE) - -// Use this structure for DSPROPERTY_EAXBUFFER_ALLPARAMETERS -// - all levels are hundredths of decibels -// -// NOTE: This structure may change in future EAX versions. -// It is recommended to initialize fields by name: -// myBuffer.lDirect = 0; -// myBuffer.lDirectHF = -200; -// ... -// myBuffer.dwFlags = myFlags /* see EAXBUFFERFLAGS below */ ; -// instead of: -// myBuffer = { 0, -200, ... , 0x00000003 }; -// -struct EAXBUFFERPROPERTIES { - LONG lDirect; // direct path level - LONG lDirectHF; // direct path level at high frequencies - LONG lRoom; // room effect level - LONG lRoomHF; // room effect level at high frequencies - FLOAT flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - LONG lObstruction; // main obstruction control (attenuation at high frequencies) - FLOAT flObstructionLFRatio; // obstruction low-frequency level re. main control - LONG lOcclusion; // main occlusion control (attenuation at high frequencies) - FLOAT flOcclusionLFRatio; // occlusion low-frequency level re. main control - FLOAT flOcclusionRoomRatio; // occlusion room effect level re. main control - LONG lOutsideVolumeHF; // outside sound cone level at high frequencies - FLOAT flAirAbsorptionFactor; // multiplies DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF - DWORD dwFlags; // modifies the behavior of properties -}; - -// Used by DSPROPERTY_EAXBUFFER_FLAGS -// TRUE: value is computed automatically - property is an offset -// FALSE: value is used directly -// -// Note: The number and order of flags may change in future EAX versions. -// To insure future compatibility, use flag defines as follows: -// myFlags = EAXBUFFERFLAGS_DIRECTHFAUTO | EAXBUFFERFLAGS_ROOMAUTO; -// instead of: -// myFlags = 0x00000003; -// -#define EAXBUFFERFLAGS_DIRECTHFAUTO 0x00000001 // affects DSPROPERTY_EAXBUFFER_DIRECTHF -#define EAXBUFFERFLAGS_ROOMAUTO 0x00000002 // affects DSPROPERTY_EAXBUFFER_ROOM -#define EAXBUFFERFLAGS_ROOMHFAUTO 0x00000004 // affects DSPROPERTY_EAXBUFFER_ROOMHF - -#define EAXBUFFERFLAGS_RESERVED 0xFFFFFFF8 // reserved future use - -// property ranges and defaults: - -#define EAXBUFFER_MINDIRECT -10000 -#define EAXBUFFER_MAXDIRECT 1000 -#define EAXBUFFER_DEFAULTDIRECT 0 - -#define EAXBUFFER_MINDIRECTHF -10000 -#define EAXBUFFER_MAXDIRECTHF 0 -#define EAXBUFFER_DEFAULTDIRECTHF 0 - -#define EAXBUFFER_MINROOM -10000 -#define EAXBUFFER_MAXROOM 1000 -#define EAXBUFFER_DEFAULTROOM 0 - -#define EAXBUFFER_MINROOMHF -10000 -#define EAXBUFFER_MAXROOMHF 0 -#define EAXBUFFER_DEFAULTROOMHF 0 - -#define EAXBUFFER_MINROOMROLLOFFFACTOR 0.0f -#define EAXBUFFER_MAXROOMROLLOFFFACTOR 10.f -#define EAXBUFFER_DEFAULTROOMROLLOFFFACTOR 0.0f - -#define EAXBUFFER_MINOBSTRUCTION -10000 -#define EAXBUFFER_MAXOBSTRUCTION 0 -#define EAXBUFFER_DEFAULTOBSTRUCTION 0 - -#define EAXBUFFER_MINOBSTRUCTIONLFRATIO 0.0f -#define EAXBUFFER_MAXOBSTRUCTIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTOBSTRUCTIONLFRATIO 0.0f - -#define EAXBUFFER_MINOCCLUSION -10000 -#define EAXBUFFER_MAXOCCLUSION 0 -#define EAXBUFFER_DEFAULTOCCLUSION 0 - -#define EAXBUFFER_MINOCCLUSIONLFRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTOCCLUSIONLFRATIO 0.25f - -#define EAXBUFFER_MINOCCLUSIONROOMRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONROOMRATIO 10.0f -#define EAXBUFFER_DEFAULTOCCLUSIONROOMRATIO 0.5f - -#define EAXBUFFER_MINOUTSIDEVOLUMEHF -10000 -#define EAXBUFFER_MAXOUTSIDEVOLUMEHF 0 -#define EAXBUFFER_DEFAULTOUTSIDEVOLUMEHF 0 - -#define EAXBUFFER_MINAIRABSORPTIONFACTOR 0.0f -#define EAXBUFFER_MAXAIRABSORPTIONFACTOR 10.0f -#define EAXBUFFER_DEFAULTAIRABSORPTIONFACTOR 1.0f - -#define EAXBUFFER_DEFAULTFLAGS (EAXBUFFERFLAGS_DIRECTHFAUTO | EAXBUFFERFLAGS_ROOMAUTO | EAXBUFFERFLAGS_ROOMHFAUTO) - -// Material transmission presets -// 3 values in this order: -// 1: occlusion (or obstruction) -// 2: occlusion LF Ratio (or obstruction LF Ratio) -// 3: occlusion Room Ratio - -// Single window material preset -#define EAX_MATERIAL_SINGLEWINDOW -2800 -#define EAX_MATERIAL_SINGLEWINDOWLF 0.71 -#define EAX_MATERIAL_SINGLEWINDOWROOMRATIO 0.43 - -// Double window material preset -#define EAX_MATERIAL_DOUBLEWINDOW -5000 -#define EAX_MATERIAL_DOUBLEWINDOWHF 0.40 -#define EAX_MATERIAL_DOUBLEWINDOWROOMRATIO 0.24 - -// Thin door material preset -#define EAX_MATERIAL_THINDOOR -1800 -#define EAX_MATERIAL_THINDOORLF 0.66 -#define EAX_MATERIAL_THINDOORROOMRATIO 0.66 - -// Thick door material preset -#define EAX_MATERIAL_THICKDOOR -4400 -#define EAX_MATERIAL_THICKDOORLF 0.64 -#define EAX_MATERIAL_THICKDOORROOMRTATION 0.27 - -// Wood wall material preset -#define EAX_MATERIAL_WOODWALL -4000 -#define EAX_MATERIAL_WOODWALLLF 0.50 -#define EAX_MATERIAL_WOODWALLROOMRATIO 0.30 - -// Brick wall material preset -#define EAX_MATERIAL_BRICKWALL -5000 -#define EAX_MATERIAL_BRICKWALLLF 0.60 -#define EAX_MATERIAL_BRICKWALLROOMRATIO 0.24 - -// Stone wall material preset -#define EAX_MATERIAL_STONEWALL -6000 -#define EAX_MATERIAL_STONEWALLLF 0.68 -#define EAX_MATERIAL_STONEWALLROOMRATIO 0.20 - -// Curtain material preset -#define EAX_MATERIAL_CURTAIN -1200 -#define EAX_MATERIAL_CURTAINLF 0.15 -#define EAX_MATERIAL_CURTAINROOMRATIO 1.00 - -#pragma pack(pop) - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif