mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 11:28:56 +00:00
705c67a1be
Enhance logging facility
1453 lines
49 KiB
C++
1453 lines
49 KiB
C++
/*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
|
|
--- HISTORICAL COMMENTS FOLLOW ---
|
|
|
|
* $Logfile: /DescentIII/Main/sndlib/hlsoundlib.cpp $
|
|
* $Revision: 116 $
|
|
* $Date: 4/19/00 5:07p $
|
|
* $Author: Matt $
|
|
*
|
|
* High level sound library for Descent 3
|
|
*
|
|
* $Log: /DescentIII/Main/sndlib/hlsoundlib.cpp $
|
|
*
|
|
* 116 4/19/00 5:07p Matt
|
|
* From Duane for 1.4
|
|
* Added checks, asserts, and fixes for bad return values
|
|
*
|
|
* 115 3/20/00 12:30p Matt
|
|
* Merge of Duane's post-1.3 changes.
|
|
* Optimizations.
|
|
* A bunch of 3D sound code ifdef'd out for Mac.
|
|
*
|
|
* 114 2/09/00 4:59p Jason
|
|
* fixed access violation in VerifyUniqueID
|
|
*
|
|
* 113 10/22/99 10:40p Jeff
|
|
* commented out an mprintf put in by mac merge
|
|
*
|
|
* 112 10/21/99 3:27p Kevin
|
|
* Mac merge!
|
|
*
|
|
* 111 8/23/99 5:29p Samir
|
|
* incremental EAX 2.0 checkin
|
|
*
|
|
* 110 8/19/99 7:10p Jeff
|
|
* hooked in linux sound lib
|
|
*
|
|
* 109 8/13/99 2:00p Samir
|
|
* more aureal and geometry fixes.
|
|
*
|
|
* 108 8/11/99 3:12p Samir
|
|
* fixes for aureal support.
|
|
*
|
|
* 107 7/28/99 2:05p Kevin
|
|
* Macintosh Changes
|
|
*
|
|
* 106 5/07/99 1:32p Jeff
|
|
* kill a sound if the object is ghosted (aka OBJ_DUMMY)
|
|
*
|
|
* 105 4/27/99 2:10p Samir
|
|
* added code to set the desired sound card given the descriptive name of
|
|
* a sound card.
|
|
*
|
|
* 104 4/23/99 7:50p Samir
|
|
* looping fixes for directsound.
|
|
*
|
|
* 103 4/14/99 1:46a Jeff
|
|
* fixed case mismatched #includes
|
|
*
|
|
* 102 4/12/99 7:14p Samir
|
|
* prioritization code added.
|
|
*
|
|
* 101 4/10/99 5:09p Samir
|
|
* beginning to add prioritization of sounds code. currently non
|
|
* functional, but allows me to change all calls to Play3dSound so that I
|
|
* can test later.
|
|
*
|
|
* 100 4/06/99 8:31p Samir
|
|
* moved free memory code to low level library.
|
|
*
|
|
* 99 4/03/99 6:24p Nate
|
|
* ? Fixed a editor sound crash ?
|
|
*
|
|
* 98 4/01/99 4:28p Samir
|
|
* hardware geometry integration if it's available.
|
|
*
|
|
* 97 4/01/99 11:57a Chris
|
|
* Made the holy cow messed print the name of the sound that couldn't be
|
|
* played
|
|
*
|
|
* 96 3/03/99 5:07p Samir
|
|
* music volume will shutoff music if 0, restart if greater only after a
|
|
* change in vollume.
|
|
*
|
|
* 95 3/03/99 5:44a Chris
|
|
* Sound is based on the viewer_object
|
|
*
|
|
* 94 2/24/99 12:27p Chris
|
|
* Fixed problems with GB finding robots/room he couldn't get to. Fixed
|
|
* problems with forcefields(sound prop. and path finding). Fixed
|
|
* problems with small portals.
|
|
*
|
|
* 93 2/21/99 5:48p Matt
|
|
* Added SetVolumeObject()
|
|
*
|
|
* 92 2/16/99 3:38p Chris
|
|
* FIXED: Ship sounds being all messed up. :) (3d dist = 0) So, use the
|
|
* rvec... So, sounds could get muffled
|
|
*
|
|
* 91 2/14/99 3:27p Chris
|
|
* FIxed a load/save bug... hehe
|
|
*
|
|
* 90 2/12/99 2:10p Chris
|
|
*
|
|
* 89 2/12/99 1:54p Sean
|
|
*
|
|
* 88 2/12/99 1:33p Sean
|
|
*
|
|
* 87 2/12/99 1:18p Sean
|
|
*
|
|
* 86 2/12/99 1:10p Sean
|
|
* Encapsulated the last_portal code
|
|
*
|
|
* 85 2/12/99 11:22a Chris
|
|
* Updated what BOA uses for BOA_cost_array. It is not just the distance
|
|
* from the center of the room to the center of the portal. It was this +
|
|
* the dist to the next room's center. The reason for this change was it
|
|
* makes it easier to compute the exact BOA_DIST for sounds. This is
|
|
* because the two distances are separated (so from the start pos, we do a
|
|
* vm_Vect dist from the start point to the portal)... Hmmm....
|
|
*
|
|
* 84 2/09/99 12:40p Chris
|
|
* More aipath stuff has been merged with the new BOA
|
|
*
|
|
* 83 2/09/99 9:59a Chris
|
|
* Massive BOA update :) Terrain happy now. Vis happy now. Sound happy
|
|
* now.
|
|
*
|
|
* 82 1/30/99 3:44p Chris
|
|
* Added support for time-offset'ed 3d sounds (like start at 1.2 seconds
|
|
* into the sound)
|
|
*
|
|
* 81 1/29/99 12:48p Matt
|
|
* Rewrote the doorway system
|
|
*
|
|
* 80 1/26/99 5:16p Matt
|
|
* Added StopObjectSound()
|
|
*
|
|
* 79 1/12/99 4:04p Samir
|
|
* added environmental audio on a per room basis.
|
|
*
|
|
* 78 1/08/99 6:31p Samir
|
|
* added reverb
|
|
*
|
|
* 77 12/22/98 11:08a Chris
|
|
* Improved algorithm for 3d sounds
|
|
*
|
|
* 76 12/02/98 4:34p Samir
|
|
* made high level playstream set a variable needed to call low level
|
|
* stream playback.
|
|
*
|
|
* 75 11/16/98 4:29p Chris
|
|
* Added pause new flag to the high level system
|
|
*
|
|
* 74 11/10/98 1:52p Jason
|
|
* added dedicated server support
|
|
*
|
|
* 73 10/23/98 7:05p Samir
|
|
* added pause and resume
|
|
*
|
|
* 72 10/22/98 8:31p Chris
|
|
* Sounds use GlobalAlloc and GlobalFree
|
|
*
|
|
* 71 10/22/98 9:22a Chris
|
|
* Fixes problems with hl-uids only being valid for the first 256 sounds
|
|
*
|
|
* 70 10/20/98 2:53a Kevin
|
|
* gunboy crap
|
|
*
|
|
* 69 10/19/98 11:57a Chris
|
|
* Update the sound system to use the import volume
|
|
*
|
|
* 68 10/17/98 12:46p Kevin
|
|
* Beta 4 fixes
|
|
*
|
|
* 67 10/14/98 5:12p Samir
|
|
* added a null SOUND_MIXER.
|
|
*
|
|
* 66 10/12/98 1:27p Jeff
|
|
* all mem_free's do set the value to NULL after they are complete
|
|
*
|
|
* 65 10/02/98 3:39p Chris
|
|
* Fixed a bug in Stopallsounds (it always acted like you where in the
|
|
* game)
|
|
*
|
|
* 64 9/14/98 6:28p Jason
|
|
* first pass at getting dedicated server working
|
|
*
|
|
* 63 9/11/98 3:08p Chris
|
|
* Enabled the production sound
|
|
*
|
|
* 62 9/08/98 12:05p Jason
|
|
* moved doorway.h out of room.h
|
|
*
|
|
* 61 8/26/98 1:48a Chris
|
|
* Fixed odd non-stopping sounds when ESC out of the game - etc.
|
|
*
|
|
* 60 8/18/98 12:18p Chris
|
|
* Added f_in_game
|
|
*
|
|
* 59 7/09/98 8:34p Samir
|
|
* added argument to callback for streams.
|
|
*
|
|
* 58 7/09/98 11:32a Samir
|
|
* close stream system after init check in KillSoundLib.
|
|
*
|
|
* 57 7/08/98 6:27p Samir
|
|
* stream library integrated with highlevel sound system.
|
|
*
|
|
* 56 6/29/98 10:44p Chris
|
|
*
|
|
* 55 6/29/98 10:44p Chris
|
|
* Added support for SIF_ONCE_PER_OBJ
|
|
*
|
|
* 54 6/29/98 10:12a Chris
|
|
* Further improved the sound system
|
|
*
|
|
* 53 6/29/98 9:29a Chris
|
|
* Added some support for Direct Sound 3d
|
|
*
|
|
* 52 6/24/98 12:09p Chris
|
|
* Update
|
|
*
|
|
* 51 6/22/98 12:00p Chris
|
|
* Working on sound system to make it in a nice shape.
|
|
*
|
|
* 50 6/19/98 3:09p Chris
|
|
* Improved IsSoundPlaying
|
|
*
|
|
* 49 6/19/98 3:03p Chris
|
|
* Made CheckAndForceSoundDataAlloc a SoundSystem function - useful for
|
|
* multiple mixers. Added IsSoundPlaying to the high level sound lib.
|
|
*
|
|
* 48 6/17/98 4:39p Chris
|
|
* Added the playing of 8bit samples with the 16 bit sound mixer
|
|
*
|
|
* 47 6/16/98 4:46p Chris
|
|
* Revision 2 of the stream audio stuff
|
|
*
|
|
* 46 6/16/98 3:48p Chris
|
|
* Updated the sound system and added the start of sound streaming
|
|
*
|
|
* 45 5/14/98 7:32p Samir
|
|
* Removed an ASSert and replaced with a mprintf
|
|
*
|
|
* 44 5/04/98 6:31p Craig
|
|
* Added more bug checking
|
|
*
|
|
* 43 4/24/98 3:02p Chris
|
|
* Removed GlobalAlloc and GlobalFree
|
|
*
|
|
* 42 4/23/98 12:00p Jeff
|
|
* Fixed the GlobalFree problem
|
|
*
|
|
* 41 4/22/98 6:19p Chris
|
|
* Fixed a lockup bug
|
|
*
|
|
* 40 4/22/98 4:31p Chris
|
|
* Added DebugBlockPrint
|
|
*
|
|
* 39 4/06/98 3:43p Jason
|
|
* Removed an ASSERT and make it an if-block
|
|
*
|
|
* 38 3/20/98 4:03p Chris
|
|
* Made non-looping non-audible 3d sounds not play.
|
|
*
|
|
* 37 3/20/98 3:06p Chris
|
|
* Removed some mprintf's
|
|
*
|
|
* 36 3/20/98 2:59p Chris
|
|
* Added a wall hit sound for the player and added support for a base
|
|
* volume for 3d sounds
|
|
*
|
|
* 35 2/27/98 5:31p Chris
|
|
* Changed how master_volume is set.
|
|
*
|
|
* 34 2/23/98 6:32p Chris
|
|
* Added support for a hlsoundlib unique id. This is what all the public
|
|
* functions use. Also, looping sounds are now correctly turned off and
|
|
* on.
|
|
*
|
|
* 33 2/23/98 5:03p Chris
|
|
* Added the global alloc calls (deifned them to malloc and free when not
|
|
* Win32)
|
|
*
|
|
* 32 2/17/98 1:17p Chris
|
|
*
|
|
* 31 2/17/98 1:11p Chris
|
|
* Bails on invalid sound indices
|
|
*
|
|
* 30 2/16/98 4:34a Chris
|
|
*
|
|
* 29 2/16/98 4:23a Chris
|
|
*
|
|
* 28 2/16/98 3:54a Chris
|
|
*
|
|
* 27 2/16/98 3:20a Luke
|
|
*
|
|
* 26 2/16/98 2:47a Chris
|
|
* Fixed problems with 3d looping sounds
|
|
*
|
|
* 25 2/15/98 8:13p Luke
|
|
*
|
|
* 24 2/15/98 7:12p Chris
|
|
* More improvements to the sound lib
|
|
*
|
|
* 23 2/15/98 6:41p Chris
|
|
* Added Update2dSound
|
|
*
|
|
* 22 2/13/98 5:15p Chris
|
|
* Fixed multiple problems with looping sounds not being able to be
|
|
* stopped
|
|
*
|
|
* 21 2/04/98 6:10p Matt
|
|
* Changed object room number to indicate a terrain cell via a flag. Got
|
|
* rid of the object flag which used to indicate terrain.
|
|
*
|
|
* 20 1/19/98 10:04a Matt
|
|
* Added new object handle system
|
|
*
|
|
* 19 1/14/98 7:56p Chris
|
|
* Fixed bugs dealing with llsound system being full.
|
|
*
|
|
* 18 1/14/98 5:40p Chris
|
|
* Fixed problem of the hlsound system crashing when the llsound lib
|
|
* filled up.
|
|
*
|
|
* 17 1/13/98 5:08p Chris
|
|
* Increased sound object limit
|
|
*
|
|
* 16 1/08/98 1:11p Chris
|
|
* Forgot to OR SND_OUTSIDE of some sounds
|
|
*
|
|
* 15 1/06/98 2:12p Chris
|
|
* Added muffled sounds v.1 and made 3d sounds keep their roomnum.
|
|
*
|
|
* 14 1/05/98 4:36p Chris
|
|
* Added working ambient sounds to objects.
|
|
*
|
|
* 13 1/05/98 3:58p Chris
|
|
* Further improvements to the high level sound lib
|
|
*
|
|
* 12 1/02/98 5:32p Chris
|
|
* More radical changes to the sound system
|
|
*
|
|
* 11 12/31/97 2:58a Chris
|
|
* Another major revision to the SoundLib. This cleaned up the code after
|
|
* removing the direct sound secondary buffers.
|
|
*
|
|
* 10 12/30/97 2:15p Chris
|
|
* Adding further support for software 3d stuff
|
|
*
|
|
* 9 12/22/97 6:19p Chris
|
|
* Moved weapon battery firing sound off the projectile (weapon) and into
|
|
* the weapon battery.
|
|
*
|
|
* 8 12/12/97 11:43a Chris
|
|
* Added support to toggle sndlib on/off
|
|
*
|
|
* 7 12/11/97 1:33p Chris
|
|
* Added support for fixed 3d position updating sounds.
|
|
*
|
|
* 6 12/10/97 4:47p Chris
|
|
* Revision 1.0 of new sound library (no hardware -- uses primary buffer
|
|
* streaming)
|
|
*
|
|
* 5 11/21/97 1:10p Chris
|
|
* Incremental Improvements
|
|
*
|
|
* 4 11/21/97 12:33p Chris
|
|
* Fixed memory leak when -nosound was added.
|
|
*
|
|
* 3 11/07/97 5:43p Jason
|
|
* added -nosound command switch
|
|
*
|
|
* 2 7/16/97 5:15p Chris
|
|
* Fixed use of updating 3d sounds
|
|
*
|
|
* 23 6/11/97 1:07p Samir
|
|
* The removal of gameos and replaced with oeApplication, oeDatabase
|
|
*
|
|
* 22 5/22/97 5:15p Chris
|
|
*
|
|
* 21 5/15/97 1:59a Chris
|
|
*
|
|
* 20 4/29/97 8:03a Chris
|
|
* Improved the sound code. High-level sound now
|
|
* fully uses the flags in the sound page and it
|
|
* resulted in a simpilier coding interface :)
|
|
*
|
|
* 19 4/28/97 11:21a Chris
|
|
* Incremental improvements is the sound system
|
|
*
|
|
* 18 4/24/97 3:41a Chris
|
|
* Improved 3d sound support. :)
|
|
*
|
|
* 17 4/23/97 5:38p Chris
|
|
* Updated some 3d sound code
|
|
*
|
|
* 16 4/03/97 8:37p Chris
|
|
* Added the Main_OS object pass in the sound library
|
|
* initialization code.
|
|
*
|
|
* 15 4/01/97 9:32a Chris
|
|
* Getting sounds to work with the paging system.
|
|
*
|
|
* 14 3/27/97 11:44a Chris
|
|
* On a re-initialize, I now make sure that the old initializaton is
|
|
* cleared out
|
|
*
|
|
* 13 3/21/97 7:02 PM Jeremy
|
|
* changed a "== SIF_UNUSED" to "= SIF_UNUSED" in StopAllSounds as it was
|
|
* not really doing an assignment as intended.
|
|
*
|
|
* 12 3/21/97 4:06 PM Jeremy
|
|
* changed name of low level mac sound header
|
|
*
|
|
* 11 3/14/97 5:22 PM Jeremy
|
|
* unincluded malloc.h, changed #include of <pserror.h> to "pserror.h"
|
|
* since it's not an ANSI header, but one of ours.
|
|
*
|
|
* 10 3/14/97 12:17p Chris
|
|
* Abstract type for the low level sound lib
|
|
*
|
|
* 9 2/07/97 5:48p Matt
|
|
* Renamed vector.h to vecmat.h to fix DevStudio problem
|
|
*
|
|
* $NoKeywords: $
|
|
*/
|
|
// High level sound object. This code is 100% machine independent and
|
|
// completely encapsulates the lowel-level machine-dependant sound code.
|
|
|
|
#include <cstring>
|
|
|
|
#include "hlsoundlib.h"
|
|
#include "ssl_lib.h"
|
|
#include "log.h"
|
|
#include "pserror.h"
|
|
#include "vecmat.h"
|
|
#include "args.h"
|
|
#include "sounds.h"
|
|
#include "game.h"
|
|
#include "room.h"
|
|
#include "BOA.h"
|
|
#include "streamaudio.h"
|
|
#include "doorway.h"
|
|
#include "dedicated_server.h"
|
|
#include "sndrender.h"
|
|
#include "voice.h"
|
|
#include "descent.h"
|
|
|
|
#include "sdlsound.h"
|
|
|
|
hlsSystem Sound_system;
|
|
char Sound_quality = SQT_NORMAL;
|
|
char Sound_mixer = SOUND_MIXER_SOFTWARE_16;
|
|
char Sound_card_name[256] = "";
|
|
struct tEnvAudioPresets {
|
|
float volume;
|
|
float decay;
|
|
float damping;
|
|
}
|
|
EnvAudio_Presets[N_ENVAUDIO_PRESETS] = {
|
|
{0.0F, 0.0F, 0.0F}, // Use for reverb off.
|
|
{0.25F, 0.1F, 0.0F}, {0.417F, 0.4F, 0.666F}, {0.653F, 1.499F, 0.166F}, {0.208F, 0.478F, 0.0F},
|
|
{0.5F, 2.309F, 0.888F}, {0.403F, 4.279F, 0.5F}, {0.5F, 3.961F, 0.5F}, {0.5F, 2.886F, 1.304F},
|
|
{0.361F, 7.284F, 0.332F}, {0.5F, 10.0F, 0.3F}, {0.153F, 0.259F, 2.0F}, {0.361F, 1.493F, 0.0F},
|
|
{0.444F, 2.697F, 0.638F}, {0.25F, 1.752F, 0.776F}, {0.111F, 3.145F, 0.472F}, {0.111F, 2.767F, 0.224F},
|
|
{0.194F, 7.841F, 0.472F}, {1.0F, 1.499F, 0.5F}, {0.097F, 2.767F, 0.224F}, {0.208F, 1.652F, 1.5F},
|
|
{0.652F, 2.886F, 0.25F}, {1.0F, 1.499F, 0.0F}, {0.875F, 8.392F, 1.388F}, {0.139F, 17.234F, 0.666F},
|
|
{0.486F, 7.563F, 0.806F}};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
hlsSystem::hlsSystem() {
|
|
m_f_hls_system_init = 0;
|
|
m_ll_sound_ptr = NULL;
|
|
m_sounds_played = 0;
|
|
m_master_volume = 1.0;
|
|
m_pause_new = false;
|
|
n_lls_sounds = MAX_SOUNDS_MIXED;
|
|
}
|
|
bool hlsSystem::IsActive(void) {
|
|
if (m_f_hls_system_init)
|
|
return true;
|
|
return false;
|
|
}
|
|
void hlsSystem::SetLLSoundQuantity(int n_sounds) {
|
|
if (n_sounds > MAX_SOUNDS_MIXED) {
|
|
n_sounds = MAX_SOUNDS_MIXED;
|
|
}
|
|
n_lls_sounds = n_sounds;
|
|
LOG_DEBUG.printf("SNDLIB: Allow %d sounds to be mixed.", n_sounds);
|
|
if (m_f_hls_system_init) {
|
|
InitSoundLib(NULL, Sound_mixer, Sound_quality, false);
|
|
}
|
|
}
|
|
int hlsSystem::GetLLSoundQuantity() { return n_lls_sounds; }
|
|
// Start and clean-up after the sound library
|
|
int hlsSystem::InitSoundLib(oeApplication *sos, char mixer_type, char quality, bool f_kill_sound_list) {
|
|
int status;
|
|
// Turn off sound if desired
|
|
if ((FindArg("-nosound")) || Dedicated_server) {
|
|
m_ll_sound_ptr = NULL;
|
|
return 0;
|
|
}
|
|
if (m_f_hls_system_init) {
|
|
KillSoundLib(f_kill_sound_list);
|
|
}
|
|
|
|
// Create and initialize the low-level sound library
|
|
if (m_ll_sound_ptr == NULL)
|
|
m_ll_sound_ptr = new lnxsound;
|
|
ASSERT(m_ll_sound_ptr);
|
|
if (m_ll_sound_ptr == NULL)
|
|
return 0;
|
|
if (Sound_card_name[0]) {
|
|
m_ll_sound_ptr->SetSoundCard(Sound_card_name);
|
|
} else {
|
|
m_ll_sound_ptr->SetSoundCard(NULL);
|
|
}
|
|
status = m_ll_sound_ptr->InitSoundLib(mixer_type, sos, n_lls_sounds);
|
|
// Initialize the high-level sound library
|
|
// Set the flag to initialized if all was o.k.
|
|
if (status) {
|
|
m_f_hls_system_init = 1;
|
|
SetSoundQuality(quality);
|
|
Sound_quality = GetSoundQuality();
|
|
Sound_mixer = GetSoundMixer();
|
|
|
|
// invoke high level stream system
|
|
AudioStream::InitSystem(this->m_ll_sound_ptr);
|
|
// set current environment
|
|
m_cur_environment = ENVAUD_PRESET_NONE;
|
|
}
|
|
// All done
|
|
return status;
|
|
}
|
|
// Kills the sound library
|
|
void hlsSystem::KillSoundLib(bool f_kill_sound_list) {
|
|
int i;
|
|
if (m_f_hls_system_init) {
|
|
LOG_DEBUG.printf("m_sounds_played %d", m_sounds_played);
|
|
// clean up stream system
|
|
AudioStream::Shutdown();
|
|
for (i = 0; i < MAX_SOUND_OBJECTS; i++) {
|
|
m_sound_objects[i].m_obj_type_flags = SIF_UNUSED;
|
|
m_sound_objects[i].m_hlsound_uid = -1;
|
|
}
|
|
m_ll_sound_ptr->DestroySoundLib();
|
|
m_f_hls_system_init = 0;
|
|
}
|
|
if (m_ll_sound_ptr) {
|
|
delete m_ll_sound_ptr;
|
|
m_ll_sound_ptr = NULL;
|
|
}
|
|
// This is independent of the actual sound_lib status. It happened because sounds
|
|
// use the manage system.
|
|
// moved this from beginning of function because won't the data freed here screw up streaming/looping sounds?
|
|
// before the sound library is closed?
|
|
if (f_kill_sound_list) {
|
|
for (int i = 0; i < MAX_SOUND_FILES; i++) {
|
|
SoundLoadFree(i);
|
|
}
|
|
}
|
|
}
|
|
// Pause and Resume the library
|
|
// Pauses all sounds
|
|
void hlsSystem::PauseSounds(bool f_all_pause) {
|
|
if (!m_f_hls_system_init)
|
|
return;
|
|
m_pause_new = f_all_pause;
|
|
AudioStream::PauseAll();
|
|
m_ll_sound_ptr->PauseSounds();
|
|
}
|
|
// Resumes all sounds
|
|
void hlsSystem::ResumeSounds() {
|
|
if (!m_f_hls_system_init)
|
|
return;
|
|
m_pause_new = false;
|
|
m_ll_sound_ptr->ResumeSounds();
|
|
AudioStream::ResumeAll();
|
|
}
|
|
// int hlsSystem::SetSoundPos(int sound_uid, int pos)
|
|
//{
|
|
// if(!m_f_hls_system_init) return -1;
|
|
//
|
|
// return m_ll_sound_ptr->SetSoundPos(sound_uid, pos);
|
|
// return -1;
|
|
//}
|
|
// int hlsSystem::GetSoundPos(int sound_uid)
|
|
//{
|
|
// if(!m_f_hls_system_init) return -1;
|
|
//
|
|
// return m_ll_sound_ptr->GetSoundPos(sound_uid);
|
|
// return -1;
|
|
//}
|
|
// Stops all sound from playing
|
|
void hlsSystem::StopAllSounds() {
|
|
int i;
|
|
if (!m_f_hls_system_init)
|
|
return;
|
|
for (i = 0; i < MAX_SOUND_OBJECTS; i++) {
|
|
m_sound_objects[i].m_obj_type_flags = SIF_UNUSED;
|
|
m_sound_objects[i].m_hlsound_uid = -1;
|
|
}
|
|
m_ll_sound_ptr->StopAllSounds();
|
|
BeginSoundFrame(false);
|
|
EndSoundFrame();
|
|
|
|
SoundRenderReset();
|
|
|
|
LOG_DEBUG << "Stopped all sounds";
|
|
}
|
|
// Code for the beginning and ending of a frame of action
|
|
// Begin_sound_frame(listener pos/orient/velocity)
|
|
// SyncSounds
|
|
// Do sound pos updates -- IF VOLUME IS LOW AND NOT FOREVER (or looping), THEN STOP SOUND
|
|
// compute echo / reverb
|
|
// indirect/direct path sounds
|
|
|
|
#include "findintersection.h"
|
|
|
|
void hlsSystem::BeginSoundFrame(bool f_in_game) {
|
|
bool hwsound_support; // if this is true, sound_render_system is being used
|
|
int16_t *sound_room_list; // these values are only meant for sound render system
|
|
int i, n, counter = 0;
|
|
pos_state listener_pos;
|
|
const int num_samples_this_frame = (int)(Frametime * 22050);
|
|
if (!m_f_hls_system_init)
|
|
return;
|
|
// determine if we're using hardware for sound support.
|
|
m_ll_sound_ptr->SoundStartFrame();
|
|
// non game sound frame, this, just updates currently playing sounds.
|
|
// placed here to leave early and ensure any further processing involves game only.
|
|
if (!f_in_game) {
|
|
sound_room_list = NULL;
|
|
for (i = 0, counter = 0; i < MAX_SOUND_OBJECTS; i++) {
|
|
if (m_sound_objects[i].m_obj_type_flags && m_sound_objects[i].m_sound_uid != -1) {
|
|
counter++;
|
|
ASSERT(m_sound_objects[i].m_sound_uid > -1);
|
|
if (!m_ll_sound_ptr->IsSoundInstancePlaying(m_sound_objects[i].m_sound_uid)) {
|
|
StopSound(i); // stop any sounds playing.
|
|
}
|
|
}
|
|
}
|
|
|
|
goto end_beginsoundframe; // this will handle any remaining processing
|
|
}
|
|
// FROM HERE ON, WE ASSUME WE'RE IN GAME.
|
|
hwsound_support = (sound_render_start_frame());
|
|
// define current environment of the listener.
|
|
listener_pos.velocity = &Viewer_object->mtype.phys_info.velocity;
|
|
listener_pos.position = &Viewer_object->pos;
|
|
listener_pos.orient = &Viewer_object->orient;
|
|
listener_pos.roomnum = Viewer_object->roomnum;
|
|
m_ll_sound_ptr->SetListener(&listener_pos);
|
|
// do environmental audio int current room.
|
|
if (!OBJECT_OUTSIDE(Viewer_object)) {
|
|
n = Rooms[Viewer_object->roomnum].env_reverb;
|
|
if (n >= 0) {
|
|
if (m_cur_environment != n) {
|
|
ASSERT(n < N_ENVAUDIO_PRESETS);
|
|
m_ll_sound_ptr->SetGlobalReverbProperties(EnvAudio_Presets[n].volume, EnvAudio_Presets[n].damping,
|
|
EnvAudio_Presets[n].decay);
|
|
m_cur_environment = n;
|
|
}
|
|
}
|
|
} else {
|
|
if (m_cur_environment != ENVAUD_PRESET_MOUNTAINS) {
|
|
n = ENVAUD_PRESET_MOUNTAINS;
|
|
m_ll_sound_ptr->SetGlobalReverbProperties(EnvAudio_Presets[n].volume, EnvAudio_Presets[n].damping,
|
|
EnvAudio_Presets[n].decay);
|
|
m_cur_environment = n;
|
|
}
|
|
}
|
|
// render all rooms within a certain range from player (traverse rooms through portals)
|
|
sound_room_list = hwsound_support ? sound_render_audible_rooms(&listener_pos) : NULL;
|
|
// SoundQ_process();
|
|
// if sound object is outside listener's cone of audibility, emulate the sound.
|
|
// if sound is audible, then determine its playback properties.
|
|
//
|
|
for (i = 0, counter = 0; i < MAX_SOUND_OBJECTS; i++) {
|
|
if (m_sound_objects[i].m_obj_type_flags) {
|
|
counter++;
|
|
// oldvolume = m_sound_objects[i].volume;
|
|
// oldpan = m_sound_objects[i].pan;
|
|
// mprintf(0, "SO %d playing: uid %d\n", i, m_sound_objects[i].m_sound_uid);
|
|
// Handle high-level only sounds
|
|
if (m_sound_objects[i].m_obj_type_flags & SIF_TOO_FAR) {
|
|
if (m_sound_objects[i].m_obj_type_flags & SIF_LOOPING) {
|
|
// while(m_sound_objects[i].play_info.m_samples_played >=
|
|
// Sounds[m_sound_objects[i].m_sound_index].loop_end)
|
|
// {
|
|
// m_sound_objects[i].play_info.m_samples_played -=
|
|
//(Sounds[m_sound_objects[i].m_sound_index].loop_end - Sounds[m_sound_objects[i].m_sound_index].loop_start);
|
|
// }
|
|
} else {
|
|
// Advance sound pointer and see if sound is done
|
|
m_sound_objects[i].play_info.m_samples_played += num_samples_this_frame;
|
|
|
|
if (m_sound_objects[i].play_info.m_samples_played >=
|
|
SoundFiles[Sounds[m_sound_objects[i].m_sound_index].sample_index].sample_length) {
|
|
StopSound(i);
|
|
continue;
|
|
}
|
|
}
|
|
if (m_sound_objects[i].m_obj_type_flags & SIF_OBJ_UPDATE) {
|
|
// If object not alive, kill its sound
|
|
object *obj_sound = ObjGet(m_sound_objects[i].m_link_info.object_handle);
|
|
if (!obj_sound || obj_sound->type == OBJ_DUMMY) {
|
|
StopSound(i);
|
|
continue; // Go on to next sound...
|
|
}
|
|
}
|
|
// determine new properties of sound if it's still playing, its volume, other properties.
|
|
if (Emulate3dSound(i)) {
|
|
// sound is audible now.
|
|
if (m_sound_objects[i].m_sound_uid != -1) {
|
|
m_sound_objects[i].m_obj_type_flags &= (~SIF_TOO_FAR);
|
|
} else {
|
|
// mprintf(0, "LLSound full 3\n");
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
ASSERT(m_sound_objects[i].m_sound_uid > -1);
|
|
if (!m_ll_sound_ptr->IsSoundInstancePlaying(m_sound_objects[i].m_sound_uid)) {
|
|
StopSound(i);
|
|
continue; // Go on to next sound...
|
|
}
|
|
if ((Sounds[m_sound_objects[i].m_sound_index].flags & SPF_LISTENER_UPDATE) &&
|
|
!(m_sound_objects[i].m_obj_type_flags & SIF_NO_3D_EFFECTS)) {
|
|
if (m_sound_objects[i].m_obj_type_flags & SIF_OBJ_UPDATE) {
|
|
object *obj_sound = ObjGet(m_sound_objects[i].m_link_info.object_handle);
|
|
if (!obj_sound || obj_sound->type == OBJ_DUMMY) {
|
|
StopSound(i);
|
|
continue; // Go on to next sound...
|
|
}
|
|
}
|
|
if ((m_sound_objects[i].m_obj_type_flags & (SIF_PLAYING_3D | SIF_OBJ_UPDATE))) {
|
|
bool f_audible;
|
|
vector virtual_pos;
|
|
vector virtual_vel;
|
|
float adjusted_volume;
|
|
f_audible = ComputePlayInfo(i, &virtual_pos, &virtual_vel, &adjusted_volume);
|
|
if (!f_audible) {
|
|
m_ll_sound_ptr->StopSound(m_sound_objects[i].m_sound_uid, SKT_STOP_IMMEDIATELY);
|
|
m_sound_objects[i].m_sound_uid = 0;
|
|
m_sound_objects[i].m_obj_type_flags |= SIF_TOO_FAR;
|
|
} else {
|
|
matrix orient = Identity_matrix;
|
|
pos_state cur_pos;
|
|
cur_pos.velocity = &virtual_vel;
|
|
cur_pos.position = &virtual_pos;
|
|
cur_pos.orient = &orient;
|
|
m_ll_sound_ptr->AdjustSound(m_sound_objects[i].m_sound_uid, &cur_pos, adjusted_volume);
|
|
|
|
// handle additional 3d sound support
|
|
sound_object *so = &m_sound_objects[i];
|
|
if (m_ll_sound_ptr->SoundPropertySupport() && (so->m_obj_type_flags & SIF_OBJ_UPDATE)) {
|
|
float obstruction = 0.0f;
|
|
object *game_obj;
|
|
|
|
// sound must be in same room as listener
|
|
// if so, then use FVI to determine obstruction properties.
|
|
// and then set the obstruction properties.
|
|
if (OBJECT_OUTSIDE(Viewer_object))
|
|
continue;
|
|
game_obj = ObjGet(so->m_link_info.object_handle);
|
|
|
|
if (game_obj && game_obj->roomnum == Viewer_object->roomnum) {
|
|
// inside and same room? go for it.
|
|
fvi_info hit_data;
|
|
fvi_query fq;
|
|
|
|
// mprintf(0, "Obstruction test.\n");
|
|
|
|
hit_data.hit_type[0] = HIT_WALL;
|
|
fq.p1 = &Viewer_object->pos;
|
|
fq.p0 = &game_obj->pos;
|
|
fq.startroom = game_obj->roomnum;
|
|
fq.rad = .5;
|
|
fq.thisobjnum = so->m_link_info.object_handle & HANDLE_OBJNUM_MASK;
|
|
fq.ignore_obj_list = NULL;
|
|
fq.flags = 0;
|
|
fvi_FindIntersection(&fq, &hit_data);
|
|
|
|
if (hit_data.hit_type[0] == HIT_WALL) {
|
|
obstruction = 1.0f;
|
|
}
|
|
m_ll_sound_ptr->SetSoundProperties(so->m_sound_uid, obstruction);
|
|
} else {
|
|
m_ll_sound_ptr->SetSoundProperties(so->m_sound_uid, 0.0f);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// mprintf(0, "BeginSoundFrame: used sound_objects %d\n", counter);
|
|
end_beginsoundframe:
|
|
AudioStream::Frame();
|
|
}
|
|
|
|
// Plays the deffered 3d stuff
|
|
void hlsSystem::EndSoundFrame() {
|
|
if (!m_f_hls_system_init)
|
|
return;
|
|
sound_render_end_frame();
|
|
m_ll_sound_ptr->SoundEndFrame();
|
|
}
|
|
// Allows for changes in a currently playing sound
|
|
int hlsSystem::Update2dSound(int hlsound_uid, float volume, float pan) {
|
|
int sound_obj_index;
|
|
|
|
if (!m_f_hls_system_init)
|
|
return -1;
|
|
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;
|
|
if (!m_f_hls_system_init)
|
|
return -1;
|
|
sound_obj_index = ValidateUniqueId(hlsound_uid);
|
|
if (sound_obj_index == -1)
|
|
return -1;
|
|
m_ll_sound_ptr->AdjustSound(m_sound_objects[sound_obj_index].m_sound_uid, volume, pan, 22050);
|
|
return hlsound_uid;
|
|
}
|
|
bool hlsSystem::ComputePlayInfo(int sound_obj_index, vector *virtual_pos, vector *virtual_vel, float *adjusted_volume) {
|
|
int sound_index;
|
|
|
|
int sound_seg;
|
|
int ear_seg;
|
|
vector sound_pos;
|
|
m_sound_objects[sound_obj_index].play_info.sample_skip_interval = 0;
|
|
vector dir_to_sound;
|
|
float dist = 0;
|
|
if (m_master_volume <= 0.0)
|
|
return false;
|
|
|
|
*adjusted_volume = (m_master_volume * m_sound_objects[sound_obj_index].volume_3d);
|
|
if (*adjusted_volume <= 0.0) {
|
|
*adjusted_volume = 0.0;
|
|
return false;
|
|
}
|
|
|
|
sound_index = m_sound_objects[sound_obj_index].m_sound_index;
|
|
ASSERT(sound_index >= 0 && sound_index < MAX_SOUNDS);
|
|
|
|
if ((Sounds[m_sound_objects[sound_obj_index].m_sound_index].flags & SPF_LISTENER_UPDATE) &&
|
|
!(m_sound_objects[sound_obj_index].m_obj_type_flags & SIF_NO_3D_EFFECTS) &&
|
|
(m_sound_objects[sound_obj_index].m_obj_type_flags & SIF_OBJ_UPDATE)) { // this is an updating object sound
|
|
object *objp = ObjGet(m_sound_objects[sound_obj_index].m_link_info.object_handle);
|
|
if (!objp || objp->type == OBJ_DUMMY) { // Couldn't find object for given handle
|
|
// Int3(); // get Chris//removed for outside testers
|
|
return false;
|
|
}
|
|
if (objp->movement_type == MT_PHYSICS || objp->movement_type == MT_WALKING)
|
|
*virtual_vel = objp->mtype.phys_info.velocity;
|
|
else
|
|
*virtual_vel = Zero_vector;
|
|
|
|
sound_pos = objp->pos;
|
|
sound_seg = objp->roomnum;
|
|
} else {
|
|
*virtual_vel = Zero_vector;
|
|
sound_pos = m_sound_objects[sound_obj_index].m_link_info.pos_info.pos;
|
|
sound_seg = m_sound_objects[sound_obj_index].m_link_info.pos_info.segnum;
|
|
}
|
|
|
|
// sound_seg == -1 (which just means that the roomnum/segnum hasn't been
|
|
// initialized to a proper value yet )causes crashes when BOA_INDEX()
|
|
// calls TERRAIN_REGION() with that value. (By pure luck on 32bit platforms
|
|
// the overflow and truncation will likely use an address that doesn't crash,
|
|
// but it's still invalid). At least one case that could cause this was fixed,
|
|
// if there are others, the ASSERT should tell us about it
|
|
// (and if assertions are disabled, return false to handle this gracefully)
|
|
ASSERT(sound_seg != -1 && "invalid (unset) roomnum/segnum!");
|
|
if (sound_seg == -1)
|
|
return false;
|
|
|
|
sound_seg = BOA_INDEX(sound_seg);
|
|
ear_seg = BOA_INDEX(Viewer_object->roomnum);
|
|
if (!BOA_IsSoundAudible(sound_seg, ear_seg))
|
|
return false;
|
|
|
|
if (sound_seg != ear_seg && !(sound_seg == Highest_room_index + 1 && ear_seg > Highest_room_index) &&
|
|
!(ear_seg == Highest_room_index + 1 && sound_seg > Highest_room_index)) {
|
|
int cur_room = sound_seg;
|
|
int last_room;
|
|
|
|
do {
|
|
last_room = cur_room;
|
|
|
|
if (cur_room <= Highest_room_index && (Rooms[cur_room].flags & RF_DOOR) && (cur_room != sound_seg)) {
|
|
float door_position = DoorwayGetPosition(&Rooms[cur_room]);
|
|
// Closed doors antenuate a lot
|
|
if (door_position == 0.0) {
|
|
m_sound_objects[sound_obj_index].play_info.sample_skip_interval = 4;
|
|
*adjusted_volume *= 0.2f;
|
|
} else {
|
|
*adjusted_volume *= (0.6f + (0.4 * door_position));
|
|
}
|
|
}
|
|
cur_room = BOA_NEXT_ROOM(cur_room, ear_seg);
|
|
int last_portal;
|
|
if (BOA_INDEX(last_room) == BOA_INDEX(cur_room) || cur_room == BOA_NO_PATH)
|
|
return false;
|
|
if (BOA_INDEX(last_room) != BOA_INDEX(cur_room)) {
|
|
last_portal = BOA_DetermineStartRoomPortal(last_room, NULL, cur_room, NULL);
|
|
if (last_portal == -1) {
|
|
return false;
|
|
}
|
|
}
|
|
if (last_room == sound_seg) {
|
|
if (cur_room == ear_seg) {
|
|
dir_to_sound = sound_pos - Viewer_object->pos;
|
|
dist = vm_NormalizeVector(&dir_to_sound);
|
|
} else if ((cur_room != last_room) && (cur_room != BOA_NO_PATH)) {
|
|
int this_portal = BOA_DetermineStartRoomPortal(cur_room, NULL, last_room, NULL);
|
|
dist = this_portal >= 0 ? BOA_cost_array[cur_room][this_portal] : 0;
|
|
|
|
if (last_room > Highest_room_index) {
|
|
if (this_portal >= 0) {
|
|
vector pnt = Rooms[cur_room].portals[this_portal].path_pnt;
|
|
dist += vm_VectorDistance(&sound_pos, &pnt);
|
|
}
|
|
} else {
|
|
dist += vm_VectorDistance(&sound_pos, &Rooms[last_room].portals[last_portal].path_pnt);
|
|
}
|
|
}
|
|
} else if (cur_room == ear_seg) {
|
|
dist += BOA_cost_array[last_room][last_portal];
|
|
|
|
if (last_room > Highest_room_index) {
|
|
int this_portal = BOA_DetermineStartRoomPortal(cur_room, NULL, last_room, NULL);
|
|
vector pnt = Rooms[cur_room].portals[this_portal].path_pnt;
|
|
dist += vm_VectorDistance(&Viewer_object->pos, &pnt);
|
|
} else {
|
|
dist += vm_VectorDistance(&Viewer_object->pos, &Rooms[last_room].portals[last_portal].path_pnt);
|
|
}
|
|
} else if ((cur_room != last_room) && (cur_room != BOA_NO_PATH)) {
|
|
int this_portal = BOA_DetermineStartRoomPortal(cur_room, NULL, last_room, NULL);
|
|
dist += BOA_cost_array[last_room][last_portal] + BOA_cost_array[cur_room][this_portal];
|
|
}
|
|
} while ((cur_room != ear_seg) && (cur_room != last_room) && (cur_room != BOA_NO_PATH));
|
|
if (cur_room == BOA_NO_PATH) {
|
|
*adjusted_volume = 0.0;
|
|
} else if ((last_room != ear_seg) && (last_room != sound_seg)) {
|
|
dir_to_sound = Rooms[last_room].path_pnt - Viewer_object->pos;
|
|
vm_NormalizeVector(&dir_to_sound);
|
|
}
|
|
} else
|
|
{
|
|
dir_to_sound = sound_pos - Viewer_object->pos;
|
|
dist = vm_NormalizeVector(&dir_to_sound);
|
|
}
|
|
if (dist >= Sounds[sound_index].max_distance)
|
|
return false;
|
|
|
|
if (*adjusted_volume <= 0.0) {
|
|
*adjusted_volume = 0.0;
|
|
return false;
|
|
}
|
|
if (dist == 0.0f) {
|
|
dir_to_sound = Viewer_object->orient.fvec;
|
|
}
|
|
if ((m_sound_objects[sound_obj_index].play_info.sample_skip_interval == 0) && (*adjusted_volume > 0.0f) &&
|
|
(dir_to_sound * Viewer_object->orient.fvec < -.5))
|
|
m_sound_objects[sound_obj_index].play_info.sample_skip_interval = 1;
|
|
*virtual_pos = Viewer_object->pos + (dir_to_sound * dist);
|
|
return true;
|
|
}
|
|
bool hlsSystem::Emulate3dSound(int sound_obj_index) {
|
|
bool f_audible;
|
|
vector virtual_pos;
|
|
vector virtual_vel;
|
|
float adjusted_volume;
|
|
f_audible = ComputePlayInfo(sound_obj_index, &virtual_pos, &virtual_vel, &adjusted_volume);
|
|
|
|
if (f_audible) {
|
|
pos_state cur_pos;
|
|
matrix orient = Identity_matrix;
|
|
cur_pos.velocity = &virtual_vel;
|
|
cur_pos.position = &virtual_pos;
|
|
cur_pos.orient = &orient;
|
|
m_sound_objects[sound_obj_index].m_sound_uid = m_ll_sound_ptr->PlaySound3d(
|
|
&m_sound_objects[sound_obj_index].play_info, m_sound_objects[sound_obj_index].m_sound_index, &cur_pos,
|
|
adjusted_volume, (m_sound_objects[sound_obj_index].m_obj_type_flags & SIF_LOOPING) != 0);
|
|
if (m_sound_objects[sound_obj_index].m_sound_uid == -1)
|
|
f_audible = false;
|
|
} else {
|
|
m_sound_objects[sound_obj_index].m_sound_uid =
|
|
0; // This is a dummy value -- it just cannot be -1 (that would mean that the low level sound system is full)
|
|
}
|
|
return f_audible;
|
|
}
|
|
// Functions that play a 3d sound -- includes the 2d emulation of 3d sound
|
|
int hlsSystem::Play3dSound(int sound_index, pos_state *cur_pos, float volume, int flags, float offset) {
|
|
return Play3dSound(sound_index, SND_PRIORITY_NORMAL, cur_pos, volume, flags, offset);
|
|
}
|
|
// Functions that play a 3d sound -- includes the 2d emulation of 3d sound
|
|
int hlsSystem::Play3dSound(int sound_index, object *cur_obj, float volume, int flags, float offset) {
|
|
return Play3dSound(sound_index, SND_PRIORITY_NORMAL, cur_obj, volume, flags, offset);
|
|
}
|
|
int hlsSystem::Play3dSound(int sound_index, int priority, pos_state *cur_pos, float volume, int flags, float offset) {
|
|
if (!m_f_hls_system_init)
|
|
return -1;
|
|
return Play3dSound(sound_index, cur_pos, NULL, priority, volume, flags, offset);
|
|
}
|
|
// Functions that play a 3d sound -- includes the 2d emulation of 3d sound
|
|
int hlsSystem::Play3dSound(int sound_index, int priority, object *cur_obj, float volume, int flags, float offset) {
|
|
pos_state cur_pos;
|
|
if (!m_f_hls_system_init)
|
|
return -1;
|
|
cur_pos.position = &cur_obj->pos;
|
|
cur_pos.orient = &cur_obj->orient;
|
|
cur_pos.velocity = &cur_obj->mtype.phys_info.velocity;
|
|
cur_pos.roomnum = cur_obj->roomnum;
|
|
return Play3dSound(sound_index, &cur_pos, cur_obj, priority, volume, flags, offset);
|
|
}
|
|
// Functions that play a 3d sound -- includes the 2d emulation of 3d sound
|
|
int hlsSystem::Play3dSound(int sound_index, pos_state *cur_pos, object *cur_obj, int priority, float volume, int flags,
|
|
float offset) {
|
|
int i;
|
|
int sound_uid;
|
|
int sound_obj_index;
|
|
bool f_audible;
|
|
if (!m_f_hls_system_init)
|
|
return -1;
|
|
if (sound_index == SOUND_NONE_INDEX)
|
|
return -1;
|
|
if (sound_index < 0)
|
|
return -1;
|
|
if (sound_index >= MAX_SOUNDS || Sounds[sound_index].used == 0)
|
|
return -1;
|
|
// if the position doesn't belong to any valid room or cell,
|
|
// all this would fail anyway (in Emulate3dSound() -> ComputePlayInfo()),
|
|
// so might as well give up now; furthermore, this prevents m_sound_objects[i]
|
|
// from remaining in an half-initialized state below (esp. for looping sounds
|
|
// where StopSound() wouldn't be called after Emulate3dSound() returns false)
|
|
if (cur_pos->roomnum == -1)
|
|
return -1;
|
|
// initialize sound.
|
|
Sound_system.CheckAndForceSoundDataAlloc(sound_index);
|
|
int sample_offset = offset * 22050.0f;
|
|
if (sample_offset >= SoundFiles[Sounds[sound_index].sample_index].np_sample_length)
|
|
return -1;
|
|
// Handles exclusive sounds
|
|
if (Sounds[sound_index].flags & SPF_PLAYS_EXCLUSIVELY) {
|
|
sound_uid = m_ll_sound_ptr->IsSoundPlaying(sound_index);
|
|
if (sound_uid != -1)
|
|
return -1;
|
|
}
|
|
// Handles play once sounds
|
|
if (Sounds[sound_index].flags & SPF_PLAYS_ONCE) {
|
|
for (sound_obj_index = 0; sound_obj_index < MAX_SOUND_OBJECTS; sound_obj_index++) {
|
|
if ((m_sound_objects[sound_obj_index].m_sound_index == sound_index) &&
|
|
((sound_uid = m_sound_objects[sound_obj_index].m_sound_uid) != -1)) {
|
|
StopSound(sound_obj_index);
|
|
}
|
|
}
|
|
}
|
|
// Handles play once per object
|
|
if ((Sounds[sound_index].flags & SPF_ONCE_PER_OBJ) && cur_obj) {
|
|
for (sound_obj_index = 0; sound_obj_index < MAX_SOUND_OBJECTS; sound_obj_index++) {
|
|
if ((m_sound_objects[sound_obj_index].m_sound_index == sound_index) &&
|
|
((sound_uid = m_sound_objects[sound_obj_index].m_sound_uid) != -1)) {
|
|
if (m_sound_objects[sound_obj_index].m_obj_type_flags & SIF_OBJ_UPDATE) {
|
|
if (m_sound_objects[sound_obj_index].m_link_info.object_handle == cur_obj->handle) {
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// find free sound slot.
|
|
for (i = 0; i < MAX_SOUND_OBJECTS; i++) {
|
|
if (m_sound_objects[i].m_obj_type_flags == SIF_UNUSED)
|
|
break; //
|
|
}
|
|
// no free slots? hmmm....
|
|
if (i >= MAX_SOUND_OBJECTS) {
|
|
LOG_WARNING.printf("HLSOUNDLIB HOLY COW: Over %d sounds trying to play(beyond max) - %s", MAX_SOUND_OBJECTS,
|
|
Sounds[sound_index].name);
|
|
// Int3();
|
|
return -1;
|
|
}
|
|
// Set the current sound
|
|
m_sound_objects[i].m_sound_index = sound_index;
|
|
// Insert the passed flags
|
|
m_sound_objects[i].m_obj_type_flags = flags;
|
|
// Determine if the sound is linked to the object
|
|
if ((cur_obj != NULL) && (Sounds[sound_index].flags & SPF_LISTENER_UPDATE) &&
|
|
(Sounds[sound_index].flags & SPF_OBJ_UPDATE)) {
|
|
m_sound_objects[i].m_obj_type_flags |= SIF_OBJ_UPDATE;
|
|
m_sound_objects[i].m_link_info.object_handle = cur_obj->handle;
|
|
} else {
|
|
m_sound_objects[i].m_link_info.pos_info.pos = *cur_pos->position;
|
|
m_sound_objects[i].m_link_info.pos_info.orient = *cur_pos->orient;
|
|
m_sound_objects[i].m_link_info.pos_info.segnum = cur_pos->roomnum;
|
|
// NOTE: Velocity is zero for all non object-linked sounds
|
|
}
|
|
m_sound_objects[i].volume_3d = volume;
|
|
// m_sound_objects[i].m_sound_uid = m_ll_sound_ptr->PlaySound3d(sound_index, cur_pos, 22050);
|
|
// Increment the total number of sounds played
|
|
m_sounds_played++;
|
|
// Initialize the play information to nice values
|
|
memset(&m_sound_objects[i].play_info, 0, sizeof(play_information));
|
|
m_sound_objects[i].play_info.samples_per_22khz_sample = 1.0;
|
|
m_sound_objects[i].play_info.sample_skip_interval = 0;
|
|
m_sound_objects[i].play_info.priority = priority; // Set sound's priority rating
|
|
m_sound_objects[i].m_hlsound_uid = MakeUniqueId(i);
|
|
if (Sounds[sound_index].flags & SPF_LOOPED)
|
|
m_sound_objects[i].m_obj_type_flags |= SIF_LOOPING;
|
|
if (!m_pause_new) {
|
|
f_audible = Emulate3dSound(i);
|
|
if ((!f_audible) && (!(m_sound_objects[i].m_obj_type_flags & SIF_LOOPING))) {
|
|
StopSound(i, SKT_STOP_IMMEDIATELY);
|
|
return -1;
|
|
}
|
|
} else {
|
|
f_audible = false;
|
|
m_sound_objects[i].m_sound_uid = -1;
|
|
}
|
|
if (m_sound_objects[i].m_sound_uid == -1) {
|
|
m_sound_objects[i].m_obj_type_flags |= SIF_TOO_FAR;
|
|
// mprintf(0, "LLSound full 2\n");
|
|
} else if (!f_audible) {
|
|
m_sound_objects[i].m_obj_type_flags |= SIF_TOO_FAR;
|
|
}
|
|
m_sound_objects[i].m_obj_type_flags |= SIF_PLAYING_3D;
|
|
if (m_pause_new) {
|
|
PauseSounds(true);
|
|
}
|
|
|
|
return m_sound_objects[i].m_hlsound_uid;
|
|
}
|
|
// General purpose 2d sound play function
|
|
int hlsSystem::Play2dSound(int sound_index, float volume, float pan, uint16_t frequency) {
|
|
return hlsSystem::Play2dSound(sound_index, SND_PRIORITY_NORMAL, volume, pan, frequency);
|
|
}
|
|
int hlsSystem::Play2dSound(int sound_index, int priority, float volume, float pan, uint16_t frequency) {
|
|
int i = 0;
|
|
int sound_uid;
|
|
int sound_obj_index;
|
|
if (!m_f_hls_system_init)
|
|
return -1;
|
|
if (sound_index == SOUND_NONE_INDEX)
|
|
return -1;
|
|
if (m_pause_new)
|
|
return -1;
|
|
if (sound_index < 0) {
|
|
return -1;
|
|
}
|
|
Sound_system.CheckAndForceSoundDataAlloc(sound_index);
|
|
// Handles exclusive sounds
|
|
if (Sounds[sound_index].flags & SPF_PLAYS_EXCLUSIVELY) {
|
|
sound_uid = m_ll_sound_ptr->IsSoundPlaying(sound_index);
|
|
if (sound_uid != -1)
|
|
return -1;
|
|
}
|
|
// Handles play once sounds
|
|
if (Sounds[sound_index].flags & SPF_PLAYS_ONCE) {
|
|
for (sound_obj_index = 0; sound_obj_index < MAX_SOUND_OBJECTS; sound_obj_index++) {
|
|
if ((m_sound_objects[sound_obj_index].m_sound_index == sound_index) &&
|
|
((sound_uid = m_sound_objects[sound_obj_index].m_sound_uid) != -1)) {
|
|
StopSound(sound_obj_index);
|
|
}
|
|
}
|
|
}
|
|
for (i = 0; i < MAX_SOUND_OBJECTS; i++) {
|
|
if (m_sound_objects[i].m_obj_type_flags == SIF_UNUSED)
|
|
break;
|
|
}
|
|
// mprintf(0, "HL %d\n", i);
|
|
// ASSERT(i < MAX_SOUND_OBJECTS);
|
|
if (i >= MAX_SOUND_OBJECTS) {
|
|
LOG_WARNING << "Play2DSound: Max Sounds Objects used";
|
|
// Int3();
|
|
return -1;
|
|
}
|
|
// Increment the total number of sounds played
|
|
m_sounds_played++;
|
|
// Initialize the play information to nice values
|
|
memset(&m_sound_objects[i].play_info, 0, sizeof(play_information));
|
|
m_sound_objects[i].play_info.samples_per_22khz_sample = 1.0;
|
|
m_sound_objects[i].m_hlsound_uid = MakeUniqueId(i);
|
|
m_sound_objects[i].play_info.priority = SND_PRIORITY_NORMAL;
|
|
// static_skip++;
|
|
// if (static_skip > 2)
|
|
// static_skip = 0;
|
|
//
|
|
// m_sound_objects[i].play_info.sample_skip_interval = static_skip;
|
|
//
|
|
// if(m_sound_objects[i].play_info.sample_skip_interval == 0)
|
|
// mprintf(0, "22.5k\n");
|
|
// else if (m_sound_objects[i].play_info.sample_skip_interval == 1)
|
|
// mprintf(0, "11.25k\n");
|
|
// else
|
|
// mprintf(0, "5.75k\n");
|
|
m_sound_objects[i].m_sound_index = sound_index;
|
|
m_sound_objects[i].m_sound_uid =
|
|
m_ll_sound_ptr->PlaySound2d(&m_sound_objects[i].play_info, sound_index, volume * m_master_volume, pan,
|
|
(Sounds[sound_index].flags & SPF_LOOPED));
|
|
// ASSERT(m_sound_objects[i].m_sound_uid != -1);
|
|
if (m_sound_objects[i].m_sound_uid == -1) {
|
|
m_sound_objects[i].m_obj_type_flags = SIF_UNUSED;
|
|
m_sound_objects[i].m_hlsound_uid = -1;
|
|
LOG_WARNING.printf("Play2DSound: $%d Unplayed", i);
|
|
return -1;
|
|
}
|
|
|
|
m_sound_objects[i].m_obj_type_flags |= SIF_PLAYING_2D;
|
|
|
|
if (Sounds[m_sound_objects[i].m_sound_index].flags & SPF_LOOPED)
|
|
m_sound_objects[i].m_obj_type_flags |= SIF_LOOPING;
|
|
return m_sound_objects[i].m_hlsound_uid;
|
|
}
|
|
int hlsSystem::PlayStream(int unique_handle, void *data, int size, int stream_format, float volume,
|
|
void *stream_callback(void *user_data, int handle, int *size)) {
|
|
int i = 0;
|
|
ASSERT(stream_format == SIF_STREAMING_8_M || stream_format == SIF_STREAMING_16_M ||
|
|
stream_format == SIF_STREAMING_8_S || stream_format == SIF_STREAMING_16_S);
|
|
if (!m_f_hls_system_init)
|
|
return -1;
|
|
if (data == NULL || size <= 0)
|
|
return -1;
|
|
for (i = 0; i < MAX_SOUND_OBJECTS; i++) {
|
|
if (m_sound_objects[i].m_obj_type_flags == SIF_UNUSED)
|
|
break;
|
|
}
|
|
if (i >= MAX_SOUND_OBJECTS) {
|
|
LOG_WARNING << "PlayStream:Max Sounds Objects";
|
|
// Int3();
|
|
return -1;
|
|
}
|
|
// Increment the total number of sounds played
|
|
m_sounds_played++;
|
|
// Initialize the play information to nice values
|
|
memset(&m_sound_objects[i].play_info, 0, sizeof(play_information));
|
|
m_sound_objects[i].play_info.samples_per_22khz_sample = 1.0;
|
|
m_sound_objects[i].play_info.left_volume = m_sound_objects[i].play_info.right_volume = volume * m_master_volume;
|
|
m_sound_objects[i].play_info.m_stream_cback = stream_callback;
|
|
m_sound_objects[i].play_info.m_stream_data = data;
|
|
m_sound_objects[i].play_info.m_stream_format = stream_format;
|
|
m_sound_objects[i].play_info.m_stream_size = size;
|
|
m_sound_objects[i].play_info.m_stream_handle = unique_handle;
|
|
m_sound_objects[i].play_info.m_stream_bufsize = size;
|
|
m_sound_objects[i].m_hlsound_uid = MakeUniqueId(i);
|
|
m_sound_objects[i].m_sound_index = -1;
|
|
|
|
m_sound_objects[i].m_sound_uid = m_ll_sound_ptr->PlayStream(&m_sound_objects[i].play_info);
|
|
// ASSERT(m_sound_objects[i].m_sound_uid != -1);
|
|
if (m_sound_objects[i].m_sound_uid == -1) {
|
|
m_sound_objects[i].m_obj_type_flags = SIF_UNUSED;
|
|
m_sound_objects[i].m_hlsound_uid = -1;
|
|
LOG_WARNING << "LLSound full 1";
|
|
return -1;
|
|
}
|
|
|
|
m_sound_objects[i].m_obj_type_flags |= SIF_PLAYING_2D | stream_format;
|
|
if (m_pause_new) {
|
|
PauseSounds(true);
|
|
}
|
|
return m_sound_objects[i].m_hlsound_uid;
|
|
}
|
|
// Stop a looping sound and plays end snipit
|
|
void hlsSystem::StopSoundLooping(int hlsound_uid) {
|
|
int sound_object_index;
|
|
if (m_f_hls_system_init < 1)
|
|
return; // DAJ -1FIX
|
|
sound_object_index = ValidateUniqueId(hlsound_uid);
|
|
if (sound_object_index == -1)
|
|
return;
|
|
StopSound(sound_object_index, SKT_STOP_AFTER_LOOP);
|
|
}
|
|
void hlsSystem::StopSoundImmediate(int hlsound_uid) {
|
|
int sound_object_index;
|
|
if (m_f_hls_system_init < 1)
|
|
return; // DAJ -1FIX
|
|
sound_object_index = ValidateUniqueId(hlsound_uid);
|
|
if (sound_object_index == -1)
|
|
return;
|
|
StopSound(sound_object_index, SKT_STOP_IMMEDIATELY);
|
|
}
|
|
// Forcefully ends a sound
|
|
void hlsSystem::StopSound(int sound_obj_index, uint8_t f_stop_priority) {
|
|
if (!m_f_hls_system_init)
|
|
return;
|
|
m_sound_objects[sound_obj_index].m_obj_type_flags &= (~SIF_LOOPING);
|
|
|
|
if (m_sound_objects[sound_obj_index].m_sound_uid != -1) {
|
|
LOG_DEBUG.printf("stopSound %d", m_sound_objects[sound_obj_index].m_sound_uid);
|
|
m_ll_sound_ptr->StopSound(m_sound_objects[sound_obj_index].m_sound_uid, f_stop_priority);
|
|
}
|
|
if (f_stop_priority == SKT_STOP_IMMEDIATELY || m_sound_objects[sound_obj_index].m_sound_uid == -1) {
|
|
m_sound_objects[sound_obj_index].m_obj_type_flags = SIF_UNUSED;
|
|
m_sound_objects[sound_obj_index].m_hlsound_uid = -1;
|
|
}
|
|
}
|
|
// Stops all sounds attached to an object
|
|
void hlsSystem::StopObjectSound(int objhandle) {
|
|
int i;
|
|
for (i = 0; i < MAX_SOUND_OBJECTS; i++)
|
|
if (m_sound_objects[i].m_obj_type_flags & SIF_OBJ_UPDATE)
|
|
if (m_sound_objects[i].m_link_info.object_handle == objhandle)
|
|
StopSound(i, SKT_STOP_IMMEDIATELY);
|
|
}
|
|
// Set the volume for all the sounds attached to an object
|
|
void hlsSystem::SetVolumeObject(int objhandle, float volume) {
|
|
for (int i = 0; i < MAX_SOUND_OBJECTS; i++)
|
|
if (m_sound_objects[i].m_obj_type_flags & SIF_OBJ_UPDATE)
|
|
if (m_sound_objects[i].m_link_info.object_handle == objhandle)
|
|
m_sound_objects[i].volume_3d = volume;
|
|
}
|
|
// Queued sound functions
|
|
// Adds a sound to a queue
|
|
void hlsSystem::Add2dSoundQueued(int q_num, int sound_index, float volume, float pan, uint16_t frequency) {
|
|
if (!m_f_hls_system_init)
|
|
return;
|
|
}
|
|
// Cleans a queue (if sound is playing it will finish normally)
|
|
void hlsSystem::KillQueue(int q_num) {
|
|
if (!m_f_hls_system_init)
|
|
return;
|
|
}
|
|
// Kills all sound queues
|
|
void hlsSystem::KillAllQueues() {
|
|
if (!m_f_hls_system_init)
|
|
return;
|
|
}
|
|
// Midi play stuff
|
|
void hlsSystem::PlayMidi() {
|
|
if (!m_f_hls_system_init)
|
|
return;
|
|
}
|
|
void hlsSystem::StopMidi() {
|
|
if (!m_f_hls_system_init)
|
|
return;
|
|
}
|
|
void hlsSystem::PauseMidi() {
|
|
if (!m_f_hls_system_init)
|
|
return;
|
|
}
|
|
void hlsSystem::ResumeMidi() {
|
|
if (!m_f_hls_system_init)
|
|
return;
|
|
}
|
|
void hlsSystem::SetMidiVolume() {
|
|
if (!m_f_hls_system_init)
|
|
return;
|
|
}
|
|
void hlsSystem::GetMidiVolume() {
|
|
if (!m_f_hls_system_init)
|
|
return;
|
|
}
|
|
// Sets the master volume
|
|
void hlsSystem::SetMasterVolume(float volume) {
|
|
extern void StreamVolume(float master_volume);
|
|
ASSERT(volume >= 0.0 && volume <= 1.0);
|
|
|
|
if (volume == 0) {
|
|
StopAllSounds();
|
|
CloseVoices();
|
|
KillSoundLib(true);
|
|
m_master_volume = 0;
|
|
} else {
|
|
if (m_master_volume == 0) {
|
|
InitSoundLib(Descent, Sound_mixer, Sound_quality, false);
|
|
InitVoices();
|
|
}
|
|
}
|
|
m_master_volume = volume;
|
|
StreamVolume(m_master_volume);
|
|
}
|
|
|
|
// Gets the master volume
|
|
float hlsSystem::GetMasterVolume(void) { return m_master_volume; }
|
|
inline int hlsSystem::MakeUniqueId(int sound_obj_index) { return ((((int)m_sounds_played) << 12) + sound_obj_index); }
|
|
inline int hlsSystem::ValidateUniqueId(int hl_sound_uid) {
|
|
ASSERT(MAX_SOUND_OBJECTS <= 0x0FFF);
|
|
int index = hl_sound_uid & 0x0FFF;
|
|
if (index < 0 || index >= MAX_SOUND_OBJECTS)
|
|
return -1;
|
|
|
|
if (hl_sound_uid == m_sound_objects[index].m_hlsound_uid) {
|
|
return index;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
bool hlsSystem::CheckAndForceSoundDataAlloc(int sound_index) {
|
|
if (!m_f_hls_system_init)
|
|
return false;
|
|
return m_ll_sound_ptr->CheckAndForceSoundDataAlloc(sound_index);
|
|
}
|
|
bool hlsSystem::IsSoundPlaying(int hlsound_uid) {
|
|
int hl_index;
|
|
if (!m_f_hls_system_init)
|
|
return false;
|
|
hl_index = ValidateUniqueId(hlsound_uid);
|
|
if (hl_index != -1) {
|
|
return m_ll_sound_ptr->IsSoundInstancePlaying(m_sound_objects[hl_index].m_sound_uid);
|
|
}
|
|
return false;
|
|
}
|
|
bool hlsSystem::SetSoundQuality(char quality) {
|
|
if (!m_f_hls_system_init)
|
|
return false;
|
|
m_ll_sound_ptr->SetSoundQuality(quality);
|
|
Sound_quality = m_ll_sound_ptr->GetSoundQuality();
|
|
return true;
|
|
}
|
|
char hlsSystem::GetSoundQuality(void) {
|
|
if (!m_f_hls_system_init)
|
|
return -1;
|
|
return (Sound_quality = m_ll_sound_ptr->GetSoundQuality());
|
|
}
|
|
bool hlsSystem::SetSoundMixer(char mixer) {
|
|
if (!m_f_hls_system_init)
|
|
return false;
|
|
m_ll_sound_ptr->SetSoundMixer(mixer);
|
|
Sound_mixer = m_ll_sound_ptr->GetSoundMixer();
|
|
return true;
|
|
}
|
|
char hlsSystem::GetSoundMixer(void) {
|
|
if (!m_f_hls_system_init)
|
|
return SOUND_MIXER_NONE;
|
|
return (Sound_mixer = m_ll_sound_ptr->GetSoundMixer());
|
|
}
|