Files
Descent3/sndlib/soundload.cpp
Kevin Bentley df209742fc Initial import
2024-04-15 21:43:29 -06:00

765 lines
18 KiB
C++

/*
* $Logfile: /DescentIII/Main/sndlib/soundload.cpp $
* $Revision: 59 $
* $Date: 10/21/99 3:23p $
* $Author: Kevin $
*
* Code to load sounds
*
* $Log: /DescentIII/Main/sndlib/soundload.cpp $
*
* 59 10/21/99 3:23p Kevin
* Mac merge w/memory savings
*
* 58 5/11/99 12:10a Ardussi
* changes to compile on Mac
*
* 57 5/08/99 3:30p Matt
* Added weapon-hit-water sound.
*
* 56 4/30/99 3:28p Matt
* Weapons now make a special sound when colliding with lava & volatile
* surfaces, instead of the standard hit-wall sound.
*
* 55 4/29/99 3:50p Matt
* Added hiss sound for volatile surface damage
*
* 54 4/29/99 1:10p Jeff
* added sounds for inventory and countermeasure switch
*
* 53 4/14/99 1:46a Jeff
* fixed case mismatched #includes
*
* 52 4/12/99 4:18p Jason
* remap textures during sound remapping
*
* 51 4/11/99 5:03p Matt
* Changed static sound remapping code to use simpler & more
* space-efficient scheme. Also deleted an unused entry in the static
* sound list.
*
* 50 3/04/99 10:57a Matt
* Added goal message notification sound
*
* 49 2/22/99 10:24p Matt
* Added a static sound for debris explosion
*
* 48 2/18/99 4:48p Matt
* Changed the default import volume for new sounds to 100%
*
* 47 2/18/99 2:49p Matt
* Added goal complete sound
*
* 46 2/10/99 4:38p Matt
* Misc. changes for table file parsing
*
* 45 1/29/99 12:48p Matt
* Rewrote the doorway system
*
* 44 1/13/99 6:55a Jeff
* fixed #includes to work for linux
*
* 43 11/23/98 1:50p Jason
* added thruster sounds
*
* 42 10/22/98 8:31p Chris
* Sounds use GlobalAlloc and GlobalFree
*
* 41 10/21/98 4:53p Jeff
* added some sounds to sounds array
*
* 40 10/20/98 2:09p Jeff
* added 2 more sounds to static sounds
*
* 39 10/20/98 12:49p Matt
* Removed obsolete sounds from static sound list.
*
* 38 10/19/98 7:19p Matt
* Added system to support different types of damage to the player and
* have these different types make different sounds.
*
* 37 10/19/98 11:57a Chris
* Update the sound system to use the import volume
*
* 36 10/14/98 1:02p Jason
* fixed FindSoundName issues
*
* 35 10/12/98 1:27p Jeff
* all mem_free's do set the value to NULL after they are complete
*
* 34 9/21/98 8:19p Chris
* Improved volatile and forcefield hits
*
* 33 9/18/98 1:27p Matt
* Added afterburner release sound
*
* 32 9/08/98 12:05p Jason
* moved doorway.h out of room.h
*
* 31 7/24/98 5:22p Samir
* took out WAV file stuff because low level sound libray needs this code.
*
* 30 6/19/98 3:03p Chris
* Made CheckAndForceSoundDataAlloc a SoundSystem function - useful for
* multiple mixers. Added IsSoundPlaying to the high level sound lib.
*
* 29 6/17/98 4:39p Chris
* Added the playing of 8bit samples with the 16 bit sound mixer
*
* 28 5/26/98 10:54p Chris
* Ooops again
*
* 27 5/26/98 10:42p Chris
* Fixed door sound paging
*
* 26 5/26/98 10:21p Chris
* Added door sound paging
*
* 25 5/22/98 11:59a Chris
* Fixed improper uses of FindSoundName and made the proper static sounds
*
* 24 5/17/98 4:08p Chris
* Fixed bugs with initial sound loading. :)
*
* 23 5/14/98 1:28p Chris
* Improved sound loading stuff
*
* 22 5/14/98 11:49a Chris
* Bettered the sound paging system
*
* 21 5/03/98 10:22p Matt
* Added breaking glass sound
*
* 20 5/03/98 5:38p Chris
* Added sounds to anim page
*
* 19 4/24/98 3:02p Chris
* Removed GlobalAlloc and GlobalFree
*
* 18 4/22/98 5:38p Chris
* Fixed problems with adding new sounds
*
* 17 4/22/98 11:55a Jeff
* fixed stack overrun in ChangeSoundFileName
*
* 16 4/21/98 2:35p Chris
* Made soundload use the standard mem_malloc stuff
*
* 15 4/06/98 5:13p Chris
* Sounds page in at the beginning of a level
*
* 14 3/31/98 3:49p Jason
* added memory lib
*
* 13 3/02/98 4:16p Chris
* Added 14 new fields to the AI Settings Dialog/page.
*
* 12 2/23/98 5:03p Chris
* Added the global alloc calls (deifned them to malloc and free when not
* Win32)
*
* 11 2/16/98 4:55p Chris
* Added default sounds for explosions
*
* 10 2/12/98 4:23p Chris
* Fixed problem with sound dialog and allowing users to enter invalid
* values
*
* 9 1/02/98 5:32p Chris
* More radical changes to the sound system
*
* 8 12/31/97 2:58a Chris
* Another major revision to the SoundLib. This cleaned up the code after
* removing the direct sound secondary buffers.
*
* 7 12/30/97 2:15p Chris
* Adding further support for software 3d stuff
*
* 6 12/22/97 6:19p Chris
* Moved weapon battery firing sound off the projectile (weapon) and into
* the weapon battery.
*
* 5 12/19/97 4:09p Chris
* New dynamically loading sounds
*
* 4 12/10/97 4:47p Chris
* Revision 1.0 of new sound library (no hardware -- uses primary buffer
* streaming)
*
* 3 7/15/97 7:29p Chris
* Added a sound for helicopter blades.
*
* 13 5/29/97 3:26p Chris
*
* 12 5/29/97 3:11p Chris
* Fixed loadsound
*
* 11 5/22/97 3:29p Jason
* made sounds loading faster
*
* 10 5/14/97 11:31p Jason
* fixed annoying printf
*
* 9 5/14/97 12:31p Chris
*
* 8 5/13/97 10:31p Matt
* Added hook for refueling sound
*
* $NoKeywords: $
*/
#include "pstypes.h"
#include "pserror.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "ssl_lib.h"
#include "object.h"
#include "CFILE.H"
#include "ddio.h"
#include "soundload.h"
#include "weapon.h"
#include "ship.h"
#include "pstypes.h"
#include "mem.h"
#include "door.h"
#include "room.h"
#include "doorway.h"
#if defined(WIN32) || defined(__LINUX__)
#include "../manage/soundpage.h"
#include "../Descent3/sounds.h"
#elif defined(MACINTOSH)
#include "sounds.h"
#include "soundpage.h"
#endif
int Num_sounds = 0;
int Num_sound_files = 0;
char *Static_sound_names[NUM_STATIC_SOUNDS] = {
TBL_SOUND("Default"), //0 SOUND_NONE_INDEX
TBL_SOUND("Refuel"), //1 SOUND_REFUELING
TBL_SOUND("DefaultRobotExplode1"), //2 SOUND_ROBOT_EXPLODE_1
TBL_SOUND("DefaultRobotExplode2"), //3 SOUND_ROBOT_EXPLODE_2
TBL_SOUND("DefaultBuildingExplode"), //4 SOUND_BUILDING_EXPLODE
TBL_SOUND("BreakingGlass"), //5 SOUND_BREAKING_GLASS
TBL_SOUND("Tear01"), //6 SOUND_MELEE_HIT_0
TBL_SOUND("Tear02"), //7 SOUND_MELEE_HIT_1
TBL_SOUND("Afterburner"), //8 SOUND_AFTERBURNER
TBL_SOUND("Drop unknown "), //9 SOUND_ENERGY_DRAIN
TBL_SOUND("Missle lock"), //10 SOUND_MISSLE_LOCK
TBL_SOUND("Powerup pickup"), //11 SOUND_POWERUP_PICKUP
TBL_SOUND("You don't have it BEEP"), //12 SOUND_DO_NOT_HAVE_IT
TBL_SOUND("Change primary weapon"), //13 SOUND_CHANGE_PRIMARY
TBL_SOUND("Change secondary weapon"), //14 SOUND_CHANGE_SECONDARY
TBL_SOUND("HitWall"), //15 SOUND_PLAYER_HIT_WALL
TBL_SOUND("AftrBrnrTail"), //16 SOUND_AFTERBURNER_TAIL
TBL_SOUND("Forcefield bounce"), //17 SOUND_FORCEFIELD_BOUNCE
TBL_SOUND("Headlight1"), //18 SOUND_HEADLIGHT
TBL_SOUND("Cheater!"), //19 SOUND_CHEATER
TBL_SOUND("Energy Converter"), //20 SOUND_ENERGY_CONVERTER
TBL_SOUND("CockpitSequenceTest1"), //21 SOUND_COCKPIT
TBL_SOUND("Metallic Door Hit"), //22 SOUND_METALLIC_DOOR_HIT
TBL_SOUND("Wall Fade ???"), //23 SOUND_WALL_FADE
TBL_SOUND("Raindrop"), //24 SOUND_RAINDROP
TBL_SOUND("Lightning"), //25 SOUND_LIGHTNING
TBL_SOUND("HitEnergy"), //26 SOUND_HIT_BY_ENERGY_WEAPON
TBL_SOUND("HitMatter"), //27 SOUND_HIT_BY_MATTER_WEAPON
TBL_SOUND("HitConcussion"), //28 SOUND_HIT_BY_CONCUSSIVE_FORCE
TBL_SOUND("HitFire"), //29 SOUND_PLAYER_BURNING
TBL_SOUND("Menu Slider Click"), //30 SOUND_MENU_SOUND_CLICK
TBL_SOUND("Hostage pickup"), //31 SOUND_HOSTAGE_PICKUP
TBL_SOUND("Briefstartup1"), //32 SOUND_BRIEF_STARTUP
TBL_SOUND("BriefStatic"), //33 SOUND_BRIEF_STATIC
TBL_SOUND("Briefmonitoroff1"), //34 SOUND_BRIEF_MONITOROFF
TBL_SOUND("Briefingrunning"), //35 SOUND_BRIEF_RUNNING
TBL_SOUND("Briefbulb1"), //36 SOUND_BRIEF_BULLB
TBL_SOUND("Briefingtype"), //37 SOUND_BRIEF_TYPE
TBL_SOUND("ShpIdle"), //38 SHIP_IDLE
TBL_SOUND("ShpForwardThrust"), //39 SHIP_FORWARD_THRUST
TBL_SOUND("ShpForwardThrRelease"), //40 SHIP_FORWARD_THRUST_RELEASE
TBL_SOUND("GoalComplete"), //41 SOUND_GOAL_COMPLETE
TBL_SOUND("DebrisExplosion"), //42 SOUND_DEBRIS_EXPLODE
TBL_SOUND("GameMessageNotify"), //43 SOUND_GAME_MESSAGE
TBL_SOUND("Change countermeasure weapon"), //44 SOUND_CHANGE_COUNTERMEASURE
TBL_SOUND("Change inventory item"), //45 SOUND_CHANGE_INVENTORY
TBL_SOUND("VolatileHiss"), //46 SOUND_VOLATILE_HISS
TBL_SOUND("WeaponHitLava"), //47 SOUND_WEAPON_HIT_LAVA
TBL_SOUND("WeaponHitWater"), //48 SOUND_WEAPON_HIT_WATER
};
// Allocs a sound file for use, returns -1 if error, else index on success
int AllocSoundFile ()
{
for (int i=0;i<MAX_SOUND_FILES;i++)
{
if (SoundFiles[i].used == 0)
{
memset(&SoundFiles[i], 0, sizeof(sound_file_info));
SoundFiles[i].used=1;
Num_sound_files++;
return i;
}
}
Int3(); // No sound files free!
return -1;
}
// Frees sound index n
void FreeSoundFile (int n)
{
ASSERT (SoundFiles[n].used>0);
SoundFiles[n].used = 0;
SoundFiles[n].name[0] = 0;
if(SoundFiles[n].sample_8bit)
{
GlobalFree(SoundFiles[n].sample_8bit);
SoundFiles[n].sample_8bit = NULL;
}
if(SoundFiles[n].sample_16bit)
{
GlobalFree(SoundFiles[n].sample_16bit);
SoundFiles[n].sample_16bit = NULL;
}
Num_sound_files--;
}
// Gets next sound file from n that has actually been alloced
int GetNextSoundFile (int n)
{
int i;
ASSERT (n>=0 && n<MAX_SOUND_FILES);
if (Num_sound_files == 0)
return -1;
for (i=n+1;i<MAX_SOUND_FILES;i++)
if (SoundFiles[i].used)
return i;
for (i=0;i<n;i++)
if (SoundFiles[i].used)
return i;
// this is the only one
return n;
}
// Gets previous sound file from n that has actually been alloced
int GetPrevSoundFile (int n)
{
int i;
ASSERT (n>=0 && n<MAX_SOUND_FILES);
if (Num_sound_files==0)
return -1;
for (i=n-1;i>=0;i--)
{
if (SoundFiles[i].used)
return i;
}
for (i=MAX_SOUND_FILES-1;i>n;i--)
{
if (SoundFiles[i].used)
return i;
}
// this is the only one
return n;
}
// Searches thru all sounds for a specific name, returns -1 if not found
// or index of sound with name
int FindSoundFileName (char *name)
{
int i;
ASSERT (name!=NULL);
for (i=0;i<MAX_SOUND_FILES;i++)
if (SoundFiles[i].used && !stricmp (name,SoundFiles[i].name))
return i;
return -1;
}
// gets the filename from a path, plus appends our .wav extension
void ChangeSoundFileName (char *src,char *dest)
{
int limit;
char path[256],ext[256],filename[256];
limit=PAGENAME_LEN-5;
ddio_SplitPath (src,path,filename,ext);
// Make sure we don't go over our name length limit
strncpy (dest,filename,limit);
strcat (dest,".wav");
}
// Given a filename, loads the sound file.
int LoadSoundFile (char *filename, float import_volume, bool f_get_data)
{
int sound_file_index;
char extension[10];
char name[90];
int len;
ChangeSoundFileName (filename,name);
// See if the file was already loaded
sound_file_index = FindSoundFileName(name);
if(sound_file_index != -1) return sound_file_index;
// Make room for the new sound
sound_file_index = AllocSoundFile();
if(sound_file_index == -1) {
mprintf((0, "SOUND LOADER: No free sound file slots are available.\n", filename));
Int3();
return -1;
}
// Validate the extension length
len = strlen(filename);
if (len < 4) {
mprintf((0, "SOUND LOADER: %s does not have a 3 charactor extension.\n", filename));
Int3(); // Get chris
goto error_state;
}
strcpy(SoundFiles[sound_file_index].name, name);
// Load the file by its type (as defined by the extension)
strncpy (extension,&filename[len-3], 5);
if (strnicmp ("wav", extension, 3) == 0)
{
if(!SoundLoadWaveFile(filename, import_volume, sound_file_index, false, f_get_data))
{
mprintf((0, "SOUND LOADER: Error loading %s.\n", filename));
goto error_state;
}
} else {
mprintf((0, "SOUND LOADER: %s in not a supported file type.\n", extension));
goto error_state;
}
return sound_file_index;
error_state:
if (SoundFiles[sound_file_index].used)
FreeSoundFile(sound_file_index);
return -1;
}
// Sets all sounds to unused
void InitSounds ()
{
int i;
for (i = 0;i<MAX_SOUNDS;i++)
{
Sounds[i].used = 0;
Sounds[i].name[0] = 0;
Sounds[i].flags = 0;
}
Num_sounds = 0;
for (i = 0;i<MAX_SOUND_FILES;i++)
{
SoundFiles[i].name[0] = 0;
SoundFiles[i].used = 0;
}
Num_sound_files = 0;
}
// Allocs a sound for use, returns -1 if error, else index on success
int AllocSound ()
{
//Don't alloc sound 0, because 0 means something special (default/none)
for (int i=1;i<MAX_SOUNDS;i++)
{
if (Sounds[i].used==0)
{
memset(&Sounds[i], 0, sizeof(sound_info));
Sounds[i].min_distance = 10.0;
Sounds[i].max_distance = 256.0;
Sounds[i].outer_cone_volume = 1.0;
Sounds[i].inner_cone_angle = 360;
Sounds[i].outer_cone_angle = 360;
Sounds[i].import_volume = 1.0;
Sounds[i].flags = SPF_LISTENER_UPDATE;
Sounds[i].used=1;
Num_sounds++;
return i;
}
}
Int3(); // No sounds free!
return -1;
}
// Frees sound index n
void FreeSound (int n)
{
ASSERT (Sounds[n].used>0);
Sounds[n].used = 0;
Sounds[n].name[0] = 0;
Sounds[n].flags = 0;
Num_sounds--;
}
// Gets next sound from n that has actually been alloced
int GetNextSound (int n)
{
int i;
ASSERT (n>=0 && n<MAX_SOUNDS);
if (Num_sounds == 0)
return -1;
for (i=n+1;i<MAX_SOUNDS;i++)
if (Sounds[i].used)
return i;
for (i=0;i<n;i++)
if (Sounds[i].used)
return i;
// this is the only one
return n;
}
// Gets previous sound from n that has actually been alloced
int GetPrevSound (int n)
{
int i;
ASSERT (n>=0 && n<MAX_SOUNDS);
if (Num_sounds==0)
return -1;
for (i=n-1;i>=0;i--)
{
if (Sounds[i].used)
return i;
}
for (i=MAX_SOUNDS-1;i>n;i--)
{
if (Sounds[i].used)
return i;
}
// this is the only one
return n;
}
// Searches thru all sounds for a specific name, returns -1 if not found
// or index of sound with name
int FindSoundName (char *name)
{
int i;
ASSERT (name!=NULL);
for (i=0;i<MAX_SOUNDS;i++)
if (Sounds[i].used && !stricmp (name,Sounds[i].name))
return i;
return -1;
}
// Given a filename, loads the sound.
int LoadSound (char *filename)
{
int sound_handle;
sound_handle=mng_GetGuaranteedSoundPage (filename);
return sound_handle;
}
void RemapSounds()
{
//Loop through the static sounds and move them to the correct slots
for (int i=0;i<NUM_STATIC_SOUNDS;i++) {
int cur_index = FindSoundName(Static_sound_names[i]);
if (cur_index == -1) {
Int3(); //couldn't find statically-mapped sound
continue;
}
if (cur_index != i) { //not in right slot
if (Sounds[i].used) { //someone else in this slot, so swap
sound_info tsound = Sounds[i];
Sounds[i] = Sounds[cur_index];
Sounds[cur_index] = tsound;
RemapAllSoundObjects(i,MAX_SOUNDS);
RemapAllSoundObjects(cur_index,i);
RemapAllSoundObjects(MAX_SOUNDS,cur_index);
}
else { //slot is unused, so just take it
Sounds[i] = Sounds[cur_index];
Sounds[cur_index].used = 0;
RemapAllSoundObjects(cur_index,i);
}
}
}
}
// goes thru every entity that could possible have a sound index (ie objects, robots, etc)
// and changes the old index to the new index
void RemapAllSoundObjects (int old_index,int new_index)
{
int i, j, k;
// Remaps weapon sounds
for (i = 0; i < MAX_WEAPONS; i++)
{
if (Weapons[i].used)
{
for(j = 0; j < MAX_WEAPON_SOUNDS; j++)
{
if (Weapons[i].sounds[j] == old_index)
{
Weapons[i].sounds[j] = new_index;
}
}
}
}
// Remaps all non-wb object sounds
for (i = 0; i < MAX_OBJECT_IDS; i++)
{
for(j = 0; j < MAX_OBJ_SOUNDS; j++)
{
if (Object_info[i].sounds[j] == old_index)
{
Object_info[i].sounds[j] = new_index;
}
}
if(Object_info[i].ai_info) {
for(j = 0; j < MAX_AI_SOUNDS; j++)
{
if (Object_info[i].ai_info->sound[j] == old_index)
{
Object_info[i].ai_info->sound[j] = new_index;
}
}
}
}
// Remaps weapon battery sounds contained by generic objects
for (i = 0; i < MAX_OBJECT_IDS; i++)
{
if(Object_info[i].static_wb) {
for(j = 0; j < MAX_WBS_PER_OBJ; j++)
{
for(k = 0; k < MAX_WB_FIRING_MASKS; k++)
{
if(Object_info[i].static_wb[j].fm_fire_sound_index[k] == old_index)
{
Object_info[i].static_wb[j].fm_fire_sound_index[k] = new_index;
}
}
}
}
}
// Remaps anim sounds contained by generic objects
for (i = 0; i < MAX_OBJECT_IDS; i++)
{
if(Object_info[i].anim)
{
for(j = 0; j < NUM_MOVEMENT_CLASSES; j++)
{
for(k = 0; k < NUM_ANIMS_PER_CLASS; k++)
{
if(Object_info[i].anim[j].elem[k].anim_sound_index == old_index)
{
Object_info[i].anim[j].elem[k].anim_sound_index = new_index;
}
}
}
}
}
// Remaps weapons contained by Ships
for (i = 0; i < MAX_SHIPS; i++)
{
for(j = 0; j < MAX_WBS_PER_OBJ; j++)
{
if(Ships[i].firing_sound[j] == old_index)
{
Ships[i].firing_sound[j] = new_index;
}
if(Ships[i].firing_release_sound[j] == old_index)
{
Ships[i].firing_release_sound[j] = new_index;
}
for(k = 0; k < MAX_WB_FIRING_MASKS; k++)
{
if(Ships[i].static_wb[j].fm_fire_sound_index[k] == old_index)
{
Ships[i].static_wb[j].fm_fire_sound_index[k] = new_index;
}
}
}
}
for(i = 0; i <= Highest_room_index; i++)
{
if(Rooms[i].used)
{
if(Rooms[i].flags & RF_DOOR)
{
door *door = &Doors[Rooms[i].doorway_data->doornum];
if(door->open_sound == old_index)
door->open_sound = new_index;
if(door->close_sound == old_index)
door->close_sound = new_index;
}
}
}
// Remaps textures
for (i=0;i<MAX_TEXTURES;i++)
{
if (GameTextures[i].used)
{
if (GameTextures[i].sound == old_index)
{
GameTextures[i].sound = new_index;
}
}
}
}