2015-05-19 21:54:34 +00:00
//-------------------------------------------------------------------------
/*
Copyright ( C ) 1997 , 2005 - 3 D Realms Entertainment
This file is part of Shadow Warrior version 1.2
Shadow Warrior 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 2
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 , write to the Free Software
Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
Original Source : 1997 - Frank Maddin and Jim Norwood
Prepared for public release : 03 / 28 / 2005 - Charlie Wiederhold , 3 D Realms
*/
//-------------------------------------------------------------------------
2019-10-09 16:09:05 +00:00
# include "ns.h"
2017-02-25 08:15:36 +00:00
# include "compat.h"
2015-05-19 21:54:34 +00:00
# include "build.h"
# include "cache1d.h"
# include "keys.h"
# include "names2.h"
# include "mytypes.h"
# include "fx_man.h"
# include "music.h"
2019-10-24 05:47:33 +00:00
# include "al_midi.h"
2015-05-19 21:54:34 +00:00
# include "gamedefs.h"
# include "config.h"
# include "panel.h"
# include "game.h"
# include "sounds.h"
# include "ai.h"
2019-03-21 02:24:19 +00:00
# include "network.h"
2015-05-19 21:54:34 +00:00
# include "cache.h"
# include "text.h"
# include "rts.h"
# include "menus.h"
2019-04-08 06:26:44 +00:00
# include "config.h"
2019-12-02 20:05:19 +00:00
# include "menu/menu.h"
2019-12-07 18:57:19 +00:00
# include "z_music.h"
2015-05-19 21:54:34 +00:00
2015-05-19 22:06:04 +00:00
# ifdef _WIN32
2019-10-09 17:58:09 +00:00
# include "sdlayer.h"
2015-05-19 22:06:04 +00:00
# endif
2019-10-09 16:09:05 +00:00
BEGIN_SW_NS
2015-05-19 21:54:34 +00:00
extern USERp User [ MAXSPRITES ] ;
void DumpSounds ( void ) ;
// Parentally locked sounds list
int PLocked_Sounds [ ] =
{
483 , 328 , 334 , 335 , 338 , 478 , 450 , 454 , 452 , 453 , 456 , 457 , 458 , 455 , 460 , 462 ,
461 , 464 , 466 , 465 , 467 , 463 , 342 , 371 , 254 , 347 , 350 , 432 , 488 , 489 , 490 , 76 , 339 ,
499 , 500 , 506 , 479 , 480 , 481 , 482 , 78 , 600 , 467 , 548 , 547 , 544 , 546 , 545 , 542 , 541 , 540 ,
539 , 536 , 529 , 525 , 522 , 521 , 515 , 516 , 612 , 611 , 589 , 625 , 570 , 569 , 567 , 565 ,
558 , 557
} ;
// Global vars used by ambient sounds to set spritenum of ambient sounds for later lookups in
// the sprite array so FAFcansee can know the sound sprite's current sector location
2015-05-19 21:58:29 +00:00
SWBOOL Use_SoundSpriteNum = FALSE ;
int16_t SoundSpriteNum = - 1 ; // Always set this back to -1 for proper validity checking!
2015-05-19 21:54:34 +00:00
2015-05-19 21:58:29 +00:00
SWBOOL FxInitialized = FALSE ;
2015-05-19 21:54:34 +00:00
void SoundCallBack ( unsigned int num ) ;
# define MUSIC_ID -65536
# define NUM_SAMPLES 10
2019-04-08 06:25:22 +00:00
const char * BitNames [ 2 ] =
2015-05-19 21:54:34 +00:00
{
" 8-bit " , " 16-bit "
} ;
2019-04-08 06:25:22 +00:00
const char * ChannelNames [ 2 ] =
2015-05-19 21:54:34 +00:00
{
" Mono " , " Stereo "
} ;
2019-04-08 06:25:22 +00:00
const char * VoiceNames [ 8 ] =
2015-05-19 21:54:34 +00:00
{
" 1 " , " 2 " , " 3 " , " 4 " , " 5 " , " 6 " , " 7 " , " 8 "
} ;
int music ;
int soundfx ;
int num_voices ;
int NumSounds = 0 ;
int angle ;
int distance ;
int voice ;
int loopflag ;
2015-05-19 21:58:29 +00:00
extern SWBOOL DemoMode ;
2015-05-19 21:54:34 +00:00
//
// Includes digi.h to build the table
//
# define DIGI_TABLE
VOC_INFO voc [ ] =
{
# include "digi.h"
} ;
# undef DIGI_TABLE
//
// Includes ambient.h to build the table of ambient sounds for game
//
# define AMBIENT_TABLE
AMB_INFO ambarray [ ] =
{
# include "ambient.h"
} ;
# undef AMBIENT_TABLE
# define MAX_AMBIENT_SOUNDS 82
# define MAXSONGS 10 // This is the max songs per episode
2019-10-20 15:09:58 +00:00
SWBOOL OpenSound ( VOC_INFOp vp , FileReader & handle , int * length ) ;
int ReadSound ( FileReader & handle , VOC_INFOp vp , int length ) ;
2015-05-19 21:54:34 +00:00
// 3d sound engine function prototype
VOC3D_INFOp Insert3DSound ( void ) ;
#if 0
// DEBUG
char * globsndata [ DIGI_MAX ] , * globvpdata [ DIGI_MAX ] ;
int glength [ DIGI_MAX ] ;
# endif
/*
= = = = = = = = = = = = = = = = = = =
=
= My stuff
=
= = = = = = = = = = = = = = = = = = =
*/
int PlayerPainVocs [ ] =
{
DIGI_PLAYERPAIN1 ,
DIGI_PLAYERPAIN2 ,
DIGI_PLAYERPAIN3 ,
DIGI_PLAYERPAIN4 ,
DIGI_PLAYERPAIN5
} ;
// Don't have these sounds yet
int PlayerLowHealthPainVocs [ ] =
{
DIGI_HURTBAD1 ,
DIGI_HURTBAD2 ,
DIGI_HURTBAD3 ,
DIGI_HURTBAD4 ,
DIGI_HURTBAD5
} ;
int TauntAIVocs [ ] =
{
DIGI_TAUNTAI1 ,
DIGI_TAUNTAI2 ,
DIGI_TAUNTAI3 ,
DIGI_TAUNTAI4 ,
DIGI_TAUNTAI5 ,
DIGI_TAUNTAI6 ,
DIGI_TAUNTAI7 ,
DIGI_TAUNTAI8 ,
DIGI_TAUNTAI9 ,
DIGI_TAUNTAI10 ,
DIGI_COWABUNGA ,
DIGI_NOCHARADE ,
DIGI_TIMETODIE ,
DIGI_EATTHIS ,
DIGI_FIRECRACKERUPASS ,
DIGI_HOLYCOW ,
DIGI_HAHA2 ,
DIGI_HOLYPEICESOFCOW ,
DIGI_HOLYSHIT ,
DIGI_HOLYPEICESOFSHIT ,
DIGI_PAYINGATTENTION ,
DIGI_EVERYBODYDEAD ,
DIGI_KUNGFU ,
DIGI_HOWYOULIKEMOVE ,
DIGI_HAHA3 ,
DIGI_NOMESSWITHWANG ,
DIGI_RAWREVENGE ,
DIGI_YOULOOKSTUPID ,
DIGI_TINYDICK ,
DIGI_NOTOURNAMENT ,
DIGI_WHOWANTSWANG ,
DIGI_MOVELIKEYAK ,
DIGI_ALLINREFLEXES
} ;
int PlayerGetItemVocs [ ] =
{
DIGI_GOTITEM1 ,
DIGI_HAHA1 ,
DIGI_BANZAI ,
DIGI_COWABUNGA ,
DIGI_TIMETODIE
} ;
int PlayerYellVocs [ ] =
{
DIGI_PLAYERYELL1 ,
DIGI_PLAYERYELL2 ,
DIGI_PLAYERYELL3
} ;
//
// Routine called when a sound is finished playing
//
void
2019-09-13 16:23:10 +00:00
SoundCallBack ( intptr_t num )
2015-05-19 21:54:34 +00:00
{
VOC_INFOp vp ;
if ( ( int ) num = = MUSIC_ID )
{
return ;
}
// RTS sounds are negative
if ( ( int ) num < 0 )
{
return ;
}
vp = & voc [ num ] ;
// Update counter
//vp->playing--;
vp - > lock - - ;
}
//
void
ClearSoundLocks ( void )
{
unsigned i ;
for ( i = 0 ; i < SIZ ( voc ) ; i + + )
{
if ( voc [ i ] . lock > = 200 )
voc [ i ] . lock = 199 ;
}
}
2015-05-19 21:58:29 +00:00
void
UnInitSound ( void )
2015-05-19 21:54:34 +00:00
{
SoundShutdown ( ) ;
2019-12-07 18:57:19 +00:00
Mus_Stop ( ) ;
2015-05-19 21:54:34 +00:00
}
2015-05-19 21:58:29 +00:00
void
InitFX ( void )
2015-05-19 21:54:34 +00:00
{
VOC_INFOp vp ;
short i ;
// Select which cards to use
SoundStartup ( ) ;
for ( vp = voc ; vp < & voc [ SIZ ( voc ) ] ; vp + + )
{
vp - > playing = 0 ;
}
// Set up our fx callback so we can display the sounds that are playing
FX_SetCallBack ( SoundCallBack ) ;
}
extern short Level ;
2019-12-09 19:12:54 +00:00
CVAR ( Bool , sw_nothememidi , false , CVAR_ARCHIVE )
2015-05-19 21:54:34 +00:00
2019-12-07 18:57:19 +00:00
SWBOOL PlaySong ( const char * mapname , const char * song_file_name , int cdaudio_track , bool isThemeTrack ) //(nullptr, nullptr, -1, false) starts the normal level music.
2015-05-19 21:54:34 +00:00
{
2019-12-07 18:57:19 +00:00
if ( mapname = = nullptr & & song_file_name = = nullptr & & cdaudio_track = = - 1 )
2015-05-19 21:54:34 +00:00
{
2019-12-07 18:57:19 +00:00
// Get the music defined for the current level.
2015-05-19 21:54:34 +00:00
}
2019-12-09 19:12:54 +00:00
// Play CD audio if enabled.
if ( cdaudio_track > = 0 & & mus_redbook )
2015-05-19 21:54:34 +00:00
{
2019-12-07 18:57:19 +00:00
FStringf trackname ( " track%02d.ogg " , cdaudio_track ) ;
if ( ! Mus_Play ( nullptr , trackname , true ) )
2015-05-19 21:54:34 +00:00
{
2019-12-07 18:57:19 +00:00
buildprintf ( " Can't find CD track %i! \n " , cdaudio_track ) ;
2015-05-19 21:54:34 +00:00
}
}
2019-12-09 19:12:54 +00:00
else if ( isThemeTrack & & sw_nothememidi ) return false ; // The original SW source only used CD Audio for theme tracks, so this is optional.
2019-12-07 18:57:19 +00:00
return Mus_Play ( nullptr , song_file_name , true ) ;
2015-05-19 21:54:34 +00:00
}
2015-05-19 21:58:29 +00:00
void
StopFX ( void )
2015-05-19 21:54:34 +00:00
{
2019-12-16 15:18:47 +00:00
FX_StopAllSounds_ ( ) ;
2015-05-19 21:54:34 +00:00
}
2015-05-19 21:58:29 +00:00
void
StopSound ( void )
2015-05-19 21:54:34 +00:00
{
StopFX ( ) ;
2019-12-07 18:57:19 +00:00
Mus_Stop ( ) ;
2015-05-19 21:54:34 +00:00
}
//
// Sound Distance Calculation
//
# define MAXLEVLDIST 19000 // The higher the number, the further away you can hear sound
2019-11-17 17:02:17 +00:00
short SoundDist ( int x , int y , int z , int basedist )
2015-05-19 21:54:34 +00:00
{
double tx , ty , tz ;
double sqrdist , retval ;
double decay , decayshift ;
extern short screenpeek ;
# define DECAY_CONST 4000
tx = fabs ( Player [ screenpeek ] . posx - x ) ;
ty = fabs ( Player [ screenpeek ] . posy - y ) ;
tz = fabs ( ( Player [ screenpeek ] . posz - z ) > > 4 ) ;
// Use the Pythagreon Theorem to compute the magnitude of a 3D vector
sqrdist = fabs ( tx * tx + ty * ty + tz * tz ) ;
retval = sqrt ( sqrdist ) ;
if ( basedist < 0 ) // if basedist is negative
{
short i ;
decayshift = 2 ;
decay = labs ( basedist ) / DECAY_CONST ;
for ( i = 0 ; i < decay ; i + + )
decayshift * = 2 ;
2019-04-10 01:00:35 +00:00
if ( fabs ( double ( basedist ) / decayshift ) > = retval )
2015-05-19 21:54:34 +00:00
retval = 0 ;
else
retval * = decay ;
}
else
{
if ( basedist > retval )
retval = 0 ;
else
retval - = basedist ;
}
retval = retval * 256 / MAXLEVLDIST ;
if ( retval < 0 ) retval = 0 ;
if ( retval > 255 ) retval = 255 ;
return retval ;
}
//
// Angle calcuations - may need to be checked to make sure they are right
//
2019-11-17 17:02:17 +00:00
short SoundAngle ( int x , int y )
2015-05-19 21:54:34 +00:00
{
extern short screenpeek ;
short angle , delta_angle ;
angle = getangle ( x - Player [ screenpeek ] . posx , y - Player [ screenpeek ] . posy ) ;
delta_angle = GetDeltaAngle ( angle , Player [ screenpeek ] . pang ) ;
// convert a delta_angle to a real angle if negative
if ( delta_angle < 0 )
delta_angle = NORM_ANGLE ( ( 1024 + delta_angle ) + 1024 ) ;
2019-11-30 06:10:21 +00:00
// convert 2048 degree angle to 128 degree angle
return delta_angle > > 4 ;
2015-05-19 21:54:34 +00:00
}
2019-04-08 06:25:22 +00:00
int _PlayerSound ( const char * file , int line , int num , int * x , int * y , int * z , Voc3D_Flags flags , PLAYERp pp )
2015-05-19 21:54:34 +00:00
//PlayerSound(int num, int *x, int *y, int *z, Voc3D_Flags flags, PLAYERp pp)
{
int handle ;
VOC_INFOp vp ;
if ( Prediction )
return 0 ;
if ( pp < Player | | pp > = Player + MAX_SW_PLAYERS )
{
TerminateGame ( ) ;
printf ( " Player Sound invalid player: file %s, line %d \n " , file , line ) ;
exit ( 0 ) ;
}
PRODUCTION_ASSERT ( pp > = Player & & pp < Player + MAX_SW_PLAYERS ) ;
PRODUCTION_ASSERT ( num > = 0 & & num < DIGI_MAX ) ;
if ( TEST ( pp - > Flags , PF_DEAD ) ) return 0 ; // You're dead, no talking!
// If this is a player voice and he's already yacking, forget it.
vp = & voc [ num ] ;
if ( vp = = NULL )
{
TerminateGame ( ) ;
printf ( " vp == NULL in PlayerSound, num = %d \n " , num ) ;
exit ( 0 ) ;
}
// Not a player voice, bail.
if ( vp - > priority ! = PRI_PLAYERVOICE & & vp - > priority ! = PRI_PLAYERDEATH )
return 0 ;
// He wasn't talking, but he will be now.
if ( ! pp - > PlayerTalking )
{
pp - > PlayerTalking = TRUE ;
pp - > TalkVocnum = num ; // Set the voc number
pp - > TalkVocHandle = PlaySound ( num , x , y , z , flags ) ; // Play the sound
if ( pp - > TalkVocHandle < 0 )
{
pp - > PlayerTalking = FALSE ;
pp - > TalkVocnum = - 1 ;
pp - > TalkVocHandle = - 1 ;
}
}
return 0 ;
}
void LockSound ( int num )
{
VOC_INFOp vp = & voc [ num ] ;
// if data is not locked
if ( vp - > lock < = CACHE_UNLOCK_MAX )
{
vp - > lock = CACHE_LOCK_START ;
}
else
// if data is already locked
{
vp - > lock + + ;
if ( vp - > lock > = CACHE_LOCK_MAX | | vp - > lock = = 0 )
{
DumpSounds ( ) ;
TerminateGame ( ) ;
printf ( " lock > MAX, num = %d " , num ) ;
exit ( 0 ) ;
}
//ASSERT(vp->lock < CACHE_LOCK_MAX);
//ASSERT(vp->lock != 0);
}
}
2015-05-19 21:58:29 +00:00
SWBOOL CacheSound ( int num , int type )
2015-05-19 21:54:34 +00:00
{
VOC_INFOp vp = & voc [ num ] ;
PRODUCTION_ASSERT ( num > = 0 & & num < DIGI_MAX ) ;
// if no data we need to cache it in
if ( ! vp - > data )
{
2019-10-20 15:09:58 +00:00
FileReader handle ;
2015-05-19 21:54:34 +00:00
int length ;
2019-10-20 15:09:58 +00:00
if ( ! OpenSound ( vp , handle , & length ) )
2015-05-19 21:54:34 +00:00
{
sprintf ( ds , " Could not open sound %s, num %d, priority %d \n " , vp - > name , num , vp - > priority ) ;
2019-12-02 23:57:03 +00:00
OSD_Printf ( " %s " , ds ) ;
2015-05-19 21:54:34 +00:00
return FALSE ;
}
if ( vp ! = NULL )
{
//FILE *fp;
/*
if ( type = = CACHE_SOUND_PLAY )
// start it out locked at the min
vp - > lock = CACHE_LOCK_START ;
else
if ( type = = CACHE_SOUND_PRECACHE )
// start it out unlocked at the max
*/
vp - > lock = CACHE_UNLOCK_MAX ;
2019-04-08 06:26:36 +00:00
cacheAllocateBlock ( ( intptr_t * ) & vp - > data , length , & vp - > lock ) ;
2015-05-19 21:54:34 +00:00
///////
ASSERT ( vp - > data ) ;
ReadSound ( handle , vp , length ) ;
}
}
return TRUE ;
}
////////////////////////////////////////////////////////////////////////////
// Play a sound
////////////////////////////////////////////////////////////////////////////
# define SOUND_UNIT MAXLEVLDIST / 255
// NOTE: If v3df_follow == 1, x,y,z are considered literal coordinates
2019-11-17 17:02:17 +00:00
int PlaySound ( int num , int * x , int * y , int * z , Voc3D_Flags flags )
2015-05-19 21:54:34 +00:00
{
VOC_INFOp vp ;
VOC3D_INFOp v3p ;
int pitch = 0 ;
short angle , sound_dist ;
int tx , ty , tz ;
2015-05-19 21:58:29 +00:00
uint8_t priority ;
2015-05-19 21:54:34 +00:00
SPRITEp sp = NULL ;
// DEBUG
2015-05-19 21:58:29 +00:00
//extern SWBOOL Pachinko_Win_Cheat;
2015-05-19 21:54:34 +00:00
// Don't play game sounds when in menus
2019-12-02 20:05:19 +00:00
//if (M_Active() && (*x!=0 || *y!=0 || *z!=0)) return(-1);
2015-05-19 21:54:34 +00:00
// Weed out parental lock sounds if PLock is active
2019-10-27 12:40:24 +00:00
if ( adult_lockout | | Global_PLock )
2015-05-19 21:54:34 +00:00
{
unsigned i ;
for ( i = 0 ; i < sizeof ( PLocked_Sounds ) ; i + + )
{
if ( num = = PLocked_Sounds [ i ] )
return - 1 ;
}
}
if ( Prediction )
return - 1 ;
2019-10-28 21:19:50 +00:00
if ( ! SoundEnabled ( ) )
2015-05-19 21:54:34 +00:00
return - 1 ;
PRODUCTION_ASSERT ( num > = 0 & & num < DIGI_MAX ) ;
// Reset voice
voice = - 1 ;
// This is used for updating looping sounds in Update3DSounds
if ( Use_SoundSpriteNum & & SoundSpriteNum > = 0 )
{
ASSERT ( SoundSpriteNum > = 0 & & SoundSpriteNum < MAXSPRITES ) ;
sp = & sprite [ SoundSpriteNum ] ;
}
2019-10-22 00:01:05 +00:00
if ( snd_ambience & & TEST ( flags , v3df_ambient ) & & ! TEST ( flags , v3df_nolookup ) ) // Look for invalid ambient numbers
2015-05-19 21:54:34 +00:00
{
if ( num < 0 | | num > MAX_AMBIENT_SOUNDS )
{
sprintf ( ds , " Invalid or out of range ambient sound number %d \n " , num ) ;
PutStringInfo ( Player + screenpeek , ds ) ;
return - 1 ;
}
}
// Call queue management to add sound to play list.
// 3D sound manager will update playing sound 10x per second until
// the sound ends, at which time it is removed from both the 3D
// sound list as well as the actual cache.
v3p = Insert3DSound ( ) ;
// If the ambient flag is set, do a name conversion to point to actual
// digital sound entry.
v3p - > num = num ;
v3p - > priority = 0 ;
v3p - > FX_Ok = FALSE ; // Hasn't played yet
2019-10-22 00:01:05 +00:00
if ( snd_ambience & & TEST ( flags , v3df_ambient ) & & ! TEST ( flags , v3df_nolookup ) )
2015-05-19 21:54:34 +00:00
{
v3p - > maxtics = STD_RANDOM_RANGE ( ambarray [ num ] . maxtics ) ;
flags | = ambarray [ num ] . ambient_flags ; // Add to flags if any
num = ambarray [ num ] . diginame ;
}
PRODUCTION_ASSERT ( num > = 0 & & num < DIGI_MAX ) ;
// Assign voc to voc pointer
vp = & voc [ num ] ;
2019-12-02 20:05:19 +00:00
if ( M_Active ( ) & & * x = = 0 & & * y = = 0 & & * z = = 0 ) // Menus sound outdo everything
2015-05-19 21:54:34 +00:00
priority = 100 ;
else
priority = vp - > priority ;
v3p - > vp = vp ;
// Assign voc info to 3d struct for future reference
v3p - > x = x ;
v3p - > y = y ;
v3p - > z = z ;
v3p - > fx = * x ;
v3p - > fy = * y ;
v3p - > fz = * z ;
v3p - > flags = flags ;
if ( flags & v3df_follow )
{
tx = * x ;
ty = * y ;
if ( ! z )
tz = 0 ; // Some sound calls don't have a z
// value
else
tz = * z ;
}
else
{
// Don't use pointers to coordinate values.
tx = v3p - > fx ;
ty = v3p - > fy ;
tz = v3p - > fz ;
}
// Special case stuff for sounds being played in a level
if ( * x = = 0 & & * y = = 0 & & * z = = 0 )
tx = ty = tz = 0 ;
if ( ( vp - > voc_flags & vf_loop ) & & Use_SoundSpriteNum & & SoundSpriteNum > = 0 & & sp )
{
tx = sp - > x ;
ty = sp - > y ;
tz = sp - > z ;
//CON_Message("Using sp to set tx=%ld,ty=%ld,tz=%ld",tx,ty,tz);
}
// Calculate sound angle
if ( flags & v3df_dontpan ) // If true, don't do panning
angle = 0 ;
else
angle = SoundAngle ( tx , ty ) ;
// Calculate sound distance
if ( tx = = 0 & & ty = = 0 & & tz = = 0 )
sound_dist = 255 ; // Special case for menus sounds,etc.
else
sound_dist = SoundDist ( tx , ty , tz , vp - > voc_distance ) ;
v3p - > doplr_delta = sound_dist ; // Save of distance for doppler
// effect
// //DSPRINTF(ds,"sound dist = %d\n",sound_dist);
// MONO_PRINT(ds);
// Can the ambient sound see the player? If not, tone it down some.
if ( ( vp - > voc_flags & vf_loop ) & & Use_SoundSpriteNum & & SoundSpriteNum > = 0 )
{
PLAYERp pp = Player + screenpeek ;
//MONO_PRINT("PlaySound:Checking sound cansee");
if ( ! FAFcansee ( tx , ty , tz , sp - > sectnum , pp - > posx , pp - > posy , pp - > posz , pp - > cursectnum ) )
{
//MONO_PRINT("PlaySound:Reducing sound distance");
sound_dist + = ( ( sound_dist / 2 ) + ( sound_dist / 4 ) ) ; // Play more quietly
if ( sound_dist > 255 ) sound_dist = 255 ;
// Special Cases
if ( num = = DIGI_WHIPME ) sound_dist = 255 ;
}
}
// Assign ambient priorities based on distance
2019-10-22 00:01:05 +00:00
if ( snd_ambience & & TEST ( flags , v3df_ambient ) )
2015-05-19 21:54:34 +00:00
{
v3p - > priority = v3p - > vp - > priority - ( sound_dist / 26 ) ;
priority = v3p - > priority ;
}
if ( ! CacheSound ( num , CACHE_SOUND_PLAY ) )
{
v3p - > flags = v3df_kill ;
v3p - > handle = - 1 ;
v3p - > dist = 0 ;
v3p - > deleted = TRUE ; // Sound init failed, remove it!
return - 1 ;
}
LockSound ( num ) ;
if ( sound_dist < 5 )
angle = 0 ;
// Check for pitch bending
if ( vp - > pitch_lo > vp - > pitch_hi )
ASSERT ( vp - > pitch_lo < = vp - > pitch_hi ) ;
if ( vp - > pitch_hi = = vp - > pitch_lo )
pitch = vp - > pitch_lo ;
else if ( vp - > pitch_hi ! = vp - > pitch_lo )
pitch = vp - > pitch_lo + ( STD_RANDOM_RANGE ( vp - > pitch_hi - vp - > pitch_lo ) ) ;
#if 0
// DEBUG
if ( Pachinko_Win_Cheat )
{
CheckSndData ( __FILE__ , __LINE__ ) ;
Pachinko_Win_Cheat = FALSE ;
CON_Message ( " S O U N D S C H E C K E D " ) ;
}
# endif
// Request playback and play it as a looping sound if flag is set.
if ( vp - > voc_flags & vf_loop )
{
short loopvol = 0 ;
if ( ( loopvol = 255 - sound_dist ) < = 0 )
loopvol = 0 ;
if ( sound_dist < 255 | | ( flags & v3df_init ) )
{
2017-01-23 11:21:40 +00:00
voice = FX_Play ( ( char * ) vp - > data , vp - > datalen , 0 , 0 ,
2019-04-08 06:27:09 +00:00
pitch , loopvol , loopvol , loopvol , priority , 1.f , num ) ; // [JM] Should probably utilize floating point volume. !CHECKME!
2015-05-19 21:54:34 +00:00
}
else
voice = - 1 ;
}
else
//if(!flags & v3df_init) // If not initing sound, play it
if ( tx = = 0 & & ty = = 0 & & tz = = 0 ) // It's a non-inlevel sound
{
2019-04-08 06:27:09 +00:00
voice = FX_Play ( ( char * ) vp - > data , vp - > datalen , - 1 , - 1 , pitch , 255 , 255 , 255 , priority , 1.f , num ) ; // [JM] And here !CHECKME!
2015-05-19 21:54:34 +00:00
}
else // It's a 3d sound
{
if ( sound_dist < 255 )
{
2019-04-08 06:27:09 +00:00
voice = FX_Play3D ( ( char * ) vp - > data , vp - > datalen , FX_ONESHOT , pitch , angle , sound_dist , priority , 1.f , num ) ; // [JM] And here !CHECKME!
2015-05-19 21:54:34 +00:00
}
else
voice = - 1 ;
}
// If sound played, update our counter
if ( voice > FX_Ok )
{
//vp->playing++;
v3p - > FX_Ok = TRUE ;
}
else
{
vp - > lock - - ;
}
// Assign voc info to 3d struct for future reference
v3p - > handle = voice ; // Save the current voc handle in struct
v3p - > dist = sound_dist ;
v3p - > tics = 0 ; // Reset tics
if ( flags & v3df_init )
v3p - > flags ^ = v3df_init ; // Turn init off now
return voice ;
}
2015-05-19 21:58:29 +00:00
void PlaySoundRTS ( int rts_num )
2015-05-19 21:54:34 +00:00
{
char * rtsptr ;
int voice = - 1 ;
2019-10-28 21:19:50 +00:00
if ( ! RTS_IsInitialized ( ) | | ! SoundEnabled ( ) )
2015-05-19 21:54:34 +00:00
return ;
rtsptr = ( char * ) RTS_GetSound ( rts_num - 1 ) ;
ASSERT ( rtsptr ) ;
2019-04-08 06:27:09 +00:00
voice = FX_Play3D ( rtsptr , RTS_SoundLength ( rts_num - 1 ) , FX_ONESHOT , 0 , 0 , 0 , 255 , 1.f , - rts_num ) ; // [JM] Float volume here too I bet. !CHECKME!
2015-05-19 21:54:34 +00:00
}
///////////////////////////////////////////////
2015-05-19 21:58:29 +00:00
SWBOOL
2019-10-20 15:09:58 +00:00
OpenSound ( VOC_INFOp vp , FileReader & handle , int * length )
2015-05-19 21:54:34 +00:00
{
2019-12-07 09:14:51 +00:00
handle = fileSystem . OpenFileReader ( vp - > name , 0 ) ;
2015-05-19 21:54:34 +00:00
2019-10-20 15:09:58 +00:00
if ( ! handle . isOpen ( ) )
2015-05-19 21:54:34 +00:00
{
return FALSE ;
}
2019-10-20 15:09:58 +00:00
* length = handle . GetLength ( ) ;
2015-05-19 21:54:34 +00:00
return TRUE ;
}
int
2019-10-20 15:09:58 +00:00
ReadSound ( FileReader & handle , VOC_INFOp vp , int length )
2015-05-19 21:54:34 +00:00
{
2019-10-20 15:09:58 +00:00
if ( handle . Read ( vp - > data , length ) ! = length )
2015-05-19 21:54:34 +00:00
{
TerminateGame ( ) ;
printf ( " Error reading file '%s'. \n " , vp - > name ) ;
exit ( 0 ) ;
}
vp - > datalen = length ;
return 0 ;
}
void
SoundStartup ( void )
{
void * initdata = 0 ;
2015-05-19 22:06:04 +00:00
# ifdef MIXERTYPEWIN
2015-05-19 21:54:34 +00:00
initdata = ( void * ) win_gethwnd ( ) ;
# endif
2019-10-22 00:01:05 +00:00
//snd_enabled = TRUE;
2015-05-19 21:54:34 +00:00
2019-10-24 05:47:11 +00:00
2019-10-24 18:28:46 +00:00
int status = FX_Init ( snd_numvoices , snd_numchannels , snd_mixrate , initdata ) ;
2015-05-19 21:54:34 +00:00
if ( status ! = FX_Ok )
{
2019-10-24 05:47:24 +00:00
buildprintf ( " Sound error: %s \n " , FX_ErrorString ( status ) ) ;
2019-10-24 05:47:15 +00:00
return ;
2015-05-19 21:54:34 +00:00
}
2019-10-24 05:47:15 +00:00
FxInitialized = TRUE ;
snd_fxvolume . Callback ( ) ;
snd_reversestereo . Callback ( ) ;
2017-01-23 11:21:40 +00:00
FX_SetCallBack ( SoundCallBack ) ;
2015-05-19 21:54:34 +00:00
}
/*
= = = = = = = = = = = = = = = = = = =
=
= SoundShutdown
=
= = = = = = = = = = = = = = = = = = =
*/
void
SoundShutdown ( void )
{
if ( ! FxInitialized )
return ;
2019-10-24 05:47:24 +00:00
int status = FX_Shutdown ( ) ;
2015-05-19 21:54:34 +00:00
if ( status ! = FX_Ok )
{
2019-10-24 05:47:24 +00:00
buildprintf ( " Sound error: %s \n " , FX_ErrorString ( status ) ) ;
2015-05-19 21:54:34 +00:00
}
}
void COVER_SetReverb ( int amt )
{
FX_SetReverb ( amt ) ;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////
//
// 3D sound engine
// Sound management routines that keep a list of
// all sounds being played in a level.
// Doppler and Panning effects are achieved here.
//
///////////////////////////////////////////////
// Declare and initialize linked list of vocs.
VOC3D_INFOp voc3dstart = NULL ;
VOC3D_INFOp voc3dend = NULL ;
//////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////
// Initialize new vocs in the 3D sound queue
///////////////////////////////////////////////
VOC3D_INFOp
InitNew3DSound ( VOC3D_INFOp v3p )
{
v3p - > handle = - 1 ; // Initialize handle to new sound
// value
v3p - > owner = - 1 ;
v3p - > deleted = FALSE ; // Used for when sound gets deleted
return v3p ;
}
///////////////////////////////////////////////
// Inserts new vocs in the 3D sound queue
///////////////////////////////////////////////
VOC3D_INFOp
Insert3DSound ( void )
{
VOC3D_INFOp vp , old ;
// Allocate memory for new sound
// You can allocate new sounds as long as memory holds out.
// If you run out of memory for sounds, you got problems anyway.
vp = ( VOC3D_INFOp ) AllocMem ( sizeof ( VOC3D_INFO ) ) ;
ASSERT ( vp ! = NULL ) ;
memset ( vp , 0xCC , sizeof ( VOC3D_INFO ) ) ; // Zero out the memory
if ( ! voc3dend ) // First item in list
{
vp - > next = vp - > prev = NULL ;
voc3dend = vp ;
voc3dstart = vp ;
InitNew3DSound ( vp ) ;
return vp ;
}
old = voc3dend ; // Put it on the end
old - > next = vp ;
vp - > next = NULL ;
vp - > prev = old ;
voc3dend = vp ;
InitNew3DSound ( vp ) ;
return vp ;
}
/////////////////////////////////////////////////////
// Deletes vocs in the 3D sound queue with no owners
/////////////////////////////////////////////////////
void
DeleteNoSoundOwner ( short spritenum )
{
VOC3D_INFOp vp , dp ;
vp = voc3dstart ;
while ( vp )
{
dp = NULL ;
if ( vp - > owner = = spritenum & & vp - > owner > = 0 & & ( vp - > vp - > voc_flags & vf_loop ) )
{
//DSPRINTF(ds,"Deleting owner %d\n",vp->owner);
//MONO_PRINT(ds);
// Make sure to stop active
// sounds
2019-11-26 08:25:08 +00:00
if ( FX_SoundValidAndActive ( vp - > handle ) )
2015-05-19 21:54:34 +00:00
{
FX_StopSound ( vp - > handle ) ;
2019-11-26 08:25:08 +00:00
vp - > handle = 0 ;
2015-05-19 21:54:34 +00:00
}
#if 0
// Clean up the sound active counter for cacheing locks
if ( vp - > FX_Ok ) // Only decrement if sound ever played
vp - > vp - > playing - - ; // Decrement instance of sound playing
if ( vp - > vp - > playing = = 0 & & vp - > vp - > lock > CACHE_UNLOCK_MAX )
vp - > vp - > lock = CACHE_UNLOCK_MAX ;
# endif
dp = vp ; // Point to sound to be deleted
if ( vp - > prev )
{
vp - > prev - > next = vp - > next ;
}
else
{
voc3dstart = vp - > next ; // New first item
if ( voc3dstart )
voc3dstart - > prev = NULL ;
}
if ( vp - > next )
{
vp - > next - > prev = vp - > prev ; // Middle element
}
else
{
voc3dend = vp - > prev ; // Delete last element
}
}
vp = vp - > next ;
if ( dp ! = NULL )
FreeMem ( dp ) ; // Return memory to heap
}
}
// This is called from KillSprite to kill a follow sound with no valid sprite owner
// Stops and active sound with the follow bit set, even play once sounds.
void DeleteNoFollowSoundOwner ( short spritenum )
{
VOC3D_INFOp vp , dp ;
SPRITEp sp = & sprite [ spritenum ] ;
vp = voc3dstart ;
while ( vp )
{
dp = NULL ;
// If the follow flag is set, compare the x and y addresses.
if ( ( vp - > flags & v3df_follow ) & & vp - > x = = & sp - > x & & vp - > y = = & sp - > y )
{
2019-11-26 08:25:08 +00:00
if ( FX_SoundValidAndActive ( vp - > handle ) )
2015-05-19 21:54:34 +00:00
{
FX_StopSound ( vp - > handle ) ;
2019-11-26 08:25:08 +00:00
vp - > handle = 0 ;
2015-05-19 21:54:34 +00:00
}
#if 0
if ( vp - > FX_Ok ) // Only decrement if sound ever played
vp - > vp - > playing - - ; // Decrement instance of sound playing
if ( vp - > vp - > playing = = 0 & & vp - > vp - > lock > CACHE_UNLOCK_MAX )
vp - > vp - > lock = CACHE_UNLOCK_MAX ;
# endif
dp = vp ; // Point to sound to be deleted
if ( vp - > prev )
{
vp - > prev - > next = vp - > next ;
}
else
{
voc3dstart = vp - > next ; // New first item
if ( voc3dstart )
voc3dstart - > prev = NULL ;
}
if ( vp - > next )
{
vp - > next - > prev = vp - > prev ; // Middle element
}
else
{
voc3dend = vp - > prev ; // Delete last element
}
}
vp = vp - > next ;
if ( dp ! = NULL )
FreeMem ( dp ) ; // Return memory to heap
}
}
///////////////////////////////////////////////
// Deletes vocs in the 3D sound queue
///////////////////////////////////////////////
void
Delete3DSounds ( void )
{
VOC3D_INFOp vp , dp ;
PLAYERp pp ;
int cnt = 0 ;
vp = voc3dstart ;
while ( vp )
{
dp = NULL ;
if ( vp - > deleted )
{
#if 0
if ( vp - > FX_Ok ) // Only decrement if sound ever played
vp - > vp - > playing - - ; // Decrement instance of sound playing
if ( vp - > vp - > playing = = 0 & & vp - > vp - > lock > CACHE_UNLOCK_MAX )
vp - > vp - > lock = CACHE_UNLOCK_MAX ;
# endif
//DSPRINTF(ds,"Delete3DSounds: deleting owner %d digi %d\n",vp->owner,vp->num);
//MONO_PRINT(ds);
// Reset Player talking flag if a voice was deleted
//if(vp->num > DIGI_FIRSTPLAYERVOICE && vp->num < DIGI_LASTPLAYERVOICE)
if ( ! vp - > vp )
{
printf ( " Delete3DSounds(): NULL vp->vp \n " ) ;
}
else // JBF: added null check
if ( vp - > vp - > priority = = PRI_PLAYERVOICE | | vp - > vp - > priority = = PRI_PLAYERDEATH )
{
2015-05-19 21:58:29 +00:00
int16_t pnum ;
2015-05-19 21:54:34 +00:00
TRAVERSE_CONNECT ( pnum )
{
pp = & Player [ pnum ] ;
if ( vp - > num = = pp - > TalkVocnum )
{
pp - > PlayerTalking = FALSE ;
pp - > TalkVocnum = - 1 ;
pp - > TalkVocHandle = - 1 ;
//DSPRINTF(ds,"DELETED PLAYER VOICE VOC! NUM=%d\n",vp->num);
//MONO_PRINT(ds);
}
}
}
dp = vp ; // Point to sound to be deleted
if ( vp - > prev )
{
vp - > prev - > next = vp - > next ;
}
else
{
voc3dstart = vp - > next ; // New first item
if ( voc3dstart )
voc3dstart - > prev = NULL ;
}
if ( vp - > next )
{
vp - > next - > prev = vp - > prev ; // Middle element
}
else
{
voc3dend = vp - > prev ; // Delete last element
}
}
vp = vp - > next ;
if ( dp ! = NULL )
{
FreeMem ( dp ) ; // Return memory to heap
}
}
}
////////////////////////////////////////////////////////////////////////////
// Play a sound
////////////////////////////////////////////////////////////////////////////
int
RandomizeAmbientSpecials ( int handle )
{
# define MAXRNDAMB 12
int ambrand [ ] =
{
56 , 57 , 58 , 59 , 60 , 61 , 62 , 63 , 64 , 65 , 66 , 67
} ;
short i ;
// If ambient sound is found in the array, randomly pick a new sound
for ( i = 0 ; i < MAXRNDAMB ; i + + )
{
if ( handle = = ambrand [ i ] )
return ambrand [ STD_RANDOM_RANGE ( MAXRNDAMB - 1 ) ] ;
}
return handle ; // Give back the sound, no new one was found
}
void
DoTimedSound ( VOC3D_INFOp p )
{
p - > tics + = synctics ;
if ( p - > tics > = p - > maxtics )
{
2019-11-26 08:25:08 +00:00
if ( ! FX_SoundValidAndActive ( p - > handle ) )
2015-05-19 21:54:34 +00:00
{
// Check for special case ambient sounds
p - > num = RandomizeAmbientSpecials ( p - > num ) ;
// Sound was bumped from active sounds list, try to play again.
// Don't bother if voices are already maxed out.
2019-10-22 00:01:05 +00:00
if ( FX_SoundsPlaying ( ) < snd_numvoices )
2015-05-19 21:54:34 +00:00
{
if ( p - > flags & v3df_follow )
{
PlaySound ( p - > num , p - > x , p - > y , p - > z , p - > flags ) ;
p - > deleted = TRUE ; // Mark old sound for deletion
}
else
{
PlaySound ( p - > num , & p - > fx , & p - > fy , & p - > fz , p - > flags ) ;
p - > deleted = TRUE ; // Mark old sound for deletion
}
}
2019-11-26 08:25:08 +00:00
}
2015-05-19 21:54:34 +00:00
p - > tics = 0 ;
//while (p->tics >= p->maxtics) // Really stupid thing to do!
// {
// p->tics -= p->maxtics;
// }
}
}
void
StopAmbientSound ( void )
{
VOC3D_INFOp p ;
2015-05-19 21:58:29 +00:00
extern SWBOOL InMenuLevel ;
2015-05-19 21:54:34 +00:00
if ( InMenuLevel ) return ;
p = voc3dstart ;
while ( p )
{
// kill ambient sounds if Ambient is off
if ( TEST ( p - > flags , v3df_ambient ) )
SET ( p - > flags , v3df_kill ) ;
if ( p - > flags & v3df_kill )
{
2019-11-26 08:25:08 +00:00
if ( FX_SoundValidAndActive ( p - > handle ) )
{
2015-05-19 21:54:34 +00:00
FX_StopSound ( p - > handle ) ; // Make sure to stop active sounds
2019-11-26 08:25:08 +00:00
p - > handle = 0 ;
}
2015-05-19 21:54:34 +00:00
p - > deleted = TRUE ;
}
p = p - > next ;
}
Delete3DSounds ( ) ;
}
void
StartAmbientSound ( void )
{
VOC3D_INFOp p ;
short i , nexti ;
2015-05-19 21:58:29 +00:00
extern SWBOOL InMenuLevel ;
2015-05-19 21:54:34 +00:00
if ( InMenuLevel ) return ; // Don't restart ambience if no level is active! Will crash game.
TRAVERSE_SPRITE_STAT ( headspritestat [ STAT_AMBIENT ] , i , nexti )
{
SPRITEp sp = & sprite [ i ] ;
PlaySound ( sp - > lotag , & sp - > x , & sp - > y , & sp - > z , v3df_ambient | v3df_init
| v3df_doppler | v3df_follow ) ;
Set3DSoundOwner ( i ) ; // Ambient sounds need this to get sectnum for later processing
}
}
///////////////////////////////////////////////
// Main function to update 3D sound array
///////////////////////////////////////////////
typedef struct
{
VOC3D_INFOp p ;
short dist ;
2015-05-19 21:58:29 +00:00
uint8_t priority ;
2015-05-19 21:54:34 +00:00
} TVOC_INFO , * TVOC_INFOp ;
void
DoUpdateSounds3D ( void )
{
VOC3D_INFOp p ;
2015-05-19 21:58:29 +00:00
SWBOOL looping ;
2015-05-19 21:54:34 +00:00
int pitch = 0 , pitchmax ;
int delta ;
short dist , angle ;
2015-05-19 21:58:29 +00:00
SWBOOL deletesound = FALSE ;
2015-05-19 21:54:34 +00:00
TVOC_INFO TmpVocArray [ 32 ] ;
int i ;
2015-05-19 21:58:29 +00:00
static SWBOOL MoveSkip8 = 0 ;
2015-05-19 21:54:34 +00:00
2019-12-02 20:05:19 +00:00
if ( M_Active ( ) ) return ;
2015-05-19 21:54:34 +00:00
// This function is already only call 10x per sec, this widdles it down even more!
MoveSkip8 = ( MoveSkip8 + 1 ) & 15 ;
//CON_Message("Sounds Playing = %d",FX_SoundsPlaying());
// Zero out the temporary array
//memset(&TmpVocArray[0],0,sizeof(TmpVocArray));
for ( i = 0 ; i < 32 ; i + + )
{
TmpVocArray [ i ] . p = NULL ;
TmpVocArray [ i ] . dist = 0 ;
TmpVocArray [ i ] . priority = 0 ;
}
p = voc3dstart ;
while ( p )
{
ASSERT ( p - > num > = 0 & & p - > num < DIGI_MAX ) ;
looping = p - > vp - > voc_flags & vf_loop ;
// //DSPRINTF(ds,"sound %d FX_SoundActive = %d\n,",p->num,FX_SoundActive(p->handle));
// MONO_PRINT(ds);
// If sprite owner is dead, kill this sound as long as it isn't ambient
if ( looping & & p - > owner = = - 1 & & ! TEST ( p - > flags , v3df_ambient ) )
{
SET ( p - > flags , v3df_kill ) ;
}
// Is the sound slated for death? Kill it, otherwise play it.
if ( p - > flags & v3df_kill )
{
2019-11-26 08:25:08 +00:00
if ( FX_SoundValidAndActive ( p - > handle ) )
{
2015-05-19 21:54:34 +00:00
FX_StopSound ( p - > handle ) ; // Make sure to stop active sounds
2019-11-26 08:25:08 +00:00
p - > handle = 0 ;
}
2015-05-19 21:54:34 +00:00
//DSPRINTF(ds,"%d had v3df_kill.\n",p->num);
//MONO_PRINT(ds);
p - > deleted = TRUE ;
}
else
{
2019-11-26 08:25:08 +00:00
if ( ! FX_SoundValidAndActive ( p - > handle ) & & ! looping )
2015-05-19 21:54:34 +00:00
{
if ( p - > flags & v3df_intermit )
{
DoTimedSound ( p ) ;
}
else
//if(p->owner == -1 && !TEST(p->flags,v3df_ambient))
{
//DSPRINTF(ds,"%d is now inactive.\n",p->num);
//MONO_PRINT(ds);
p - > deleted = TRUE ;
}
}
2019-11-26 08:25:08 +00:00
else if ( FX_SoundValidAndActive ( p - > handle ) )
2015-05-19 21:54:34 +00:00
{
if ( p - > flags & v3df_follow )
{
dist = SoundDist ( * p - > x , * p - > y , * p - > z , p - > vp - > voc_distance ) ;
angle = SoundAngle ( * p - > x , * p - > y ) ;
}
else
{
if ( p - > fx = = 0 & & p - > fy = = 0 & & p - > fz = = 0 )
dist = 0 ;
else
dist = SoundDist ( p - > fx , p - > fy , p - > fz , p - > vp - > voc_distance ) ;
angle = SoundAngle ( p - > fx , p - > fy ) ;
}
// Can the ambient sound see the player? If not, tone it down some.
if ( ( p - > vp - > voc_flags & vf_loop ) & & p - > owner ! = - 1 )
{
PLAYERp pp = Player + screenpeek ;
SPRITEp sp = & sprite [ p - > owner ] ;
//MONO_PRINT("Checking sound cansee");
if ( ! FAFcansee ( sp - > x , sp - > y , sp - > z , sp - > sectnum , pp - > posx , pp - > posy , pp - > posz , pp - > cursectnum ) )
{
//MONO_PRINT("Reducing sound distance");
dist + = ( ( dist / 2 ) + ( dist / 4 ) ) ; // Play more quietly
if ( dist > 255 ) dist = 255 ;
// Special cases
if ( p - > num = = 76 & & TEST ( p - > flags , v3df_ambient ) )
{
dist = 255 ; // Cut off whipping sound, it's secret
}
}
}
if ( dist > = 255 & & p - > vp - > voc_distance = = DIST_NORMAL )
{
FX_StopSound ( p - > handle ) ; // Make sure to stop active
2019-11-26 08:25:08 +00:00
p - > handle = 0 ;
2015-05-19 21:54:34 +00:00
// sounds
}
else
{
// Handle Panning Left and Right
if ( ! ( p - > flags & v3df_dontpan ) )
FX_Pan3D ( p - > handle , angle , dist ) ;
else
FX_Pan3D ( p - > handle , 0 , dist ) ;
// Handle Doppler Effects
# define DOPPLERMAX 400
if ( ! ( p - > flags & v3df_doppler ) & & FX_SoundActive ( p - > handle ) )
{
pitch - = ( dist - p - > doplr_delta ) ;
if ( p - > vp - > pitch_lo ! = 0 & & p - > vp - > pitch_hi ! = 0 )
{
if ( abs ( p - > vp - > pitch_lo ) > abs ( p - > vp - > pitch_hi ) )
pitchmax = abs ( p - > vp - > pitch_lo ) ;
else
pitchmax = abs ( p - > vp - > pitch_hi ) ;
}
else
pitchmax = DOPPLERMAX ;
if ( pitch > pitchmax )
pitch = pitchmax ;
if ( pitch < - pitchmax )
pitch = - pitchmax ;
p - > doplr_delta = dist ; // Save new distance to
// struct
FX_SetPitch ( p - > handle , pitch ) ;
}
}
}
2019-11-26 08:25:08 +00:00
else if ( ! FX_SoundValidAndActive ( p - > handle ) & & looping )
2015-05-19 21:54:34 +00:00
{
if ( p - > flags & v3df_follow )
{
dist = SoundDist ( * p - > x , * p - > y , * p - > z , p - > vp - > voc_distance ) ;
angle = SoundAngle ( * p - > x , * p - > y ) ;
}
else
{
dist = SoundDist ( p - > fx , p - > fy , p - > fz , p - > vp - > voc_distance ) ;
angle = SoundAngle ( p - > fx , p - > fy ) ;
}
// Sound was bumped from active sounds list, try to play
// again.
// Don't bother if voices are already maxed out.
// Sort looping vocs in order of priority and distance
2019-10-22 00:01:05 +00:00
//if (FX_SoundsPlaying() < snd_numvoices && dist <= 255)
2015-05-19 21:54:34 +00:00
if ( dist < = 255 )
{
2019-10-22 15:47:24 +00:00
for ( i = 0 ; i < min ( ( int ) SIZ ( TmpVocArray ) , * snd_numvoices ) ; i + + )
2015-05-19 21:54:34 +00:00
{
if ( p - > priority > = TmpVocArray [ i ] . priority )
{
if ( ! TmpVocArray [ i ] . p | | dist < TmpVocArray [ i ] . dist )
{
ASSERT ( p - > num > = 0 & & p - > num < DIGI_MAX ) ;
TmpVocArray [ i ] . p = p ;
TmpVocArray [ i ] . dist = dist ;
TmpVocArray [ i ] . priority = p - > priority ;
break ;
}
}
}
}
} // !FX_SoundActive
} // if(p->flags & v3df_kill)
p = p - > next ;
} // while(p)
// //DSPRINTF(ds,"Num vocs in list: %d, Sounds playing: %d\n",numelems,FX_SoundsPlaying());
// MONO_PRINT(ds);
// Process all the looping sounds that said they wanted to get back in
// Only update these sounds 5x per second! Woo hoo!, aren't we optimized now?
//if(MoveSkip8==0)
// {
2019-10-22 15:47:24 +00:00
for ( i = 0 ; i < min ( ( int ) SIZ ( TmpVocArray ) , * snd_numvoices ) ; i + + )
2015-05-19 21:54:34 +00:00
{
int handle ;
p = TmpVocArray [ i ] . p ;
2019-10-22 00:01:05 +00:00
//if (FX_SoundsPlaying() >= snd_numvoices || !p) break;
2015-05-19 21:54:34 +00:00
if ( ! p ) break ;
ASSERT ( p - > num > = 0 & & p - > num < DIGI_MAX ) ;
if ( p - > flags & v3df_follow )
{
if ( p - > owner = = - 1 )
{
int enumber ;
enumber = p - > num ;
TerminateGame ( ) ;
printf ( " Owner == -1 on looping sound with follow flag set! \n " ) ;
printf ( " p->num = %d \n " , enumber ) ;
exit ( 0 ) ;
}
Use_SoundSpriteNum = TRUE ;
SoundSpriteNum = p - > owner ;
handle = PlaySound ( p - > num , p - > x , p - > y , p - > z , p - > flags ) ;
//if(handle >= 0 || TEST(p->flags,v3df_ambient)) // After a valid PlaySound, it's ok to use voc3dend
voc3dend - > owner = p - > owner ; // Transfer the owner
p - > deleted = TRUE ;
Use_SoundSpriteNum = FALSE ;
SoundSpriteNum = - 1 ;
//MONO_PRINT("TmpVocArray playing a follow sound");
}
else
{
if ( p - > owner = = - 1 )
{
int enumber ;
enumber = p - > num ;
TerminateGame ( ) ;
printf ( " Owner == -1 on looping sound, no follow flag. \n " ) ;
printf ( " p->num = %d \n " , enumber ) ;
exit ( 0 ) ;
}
Use_SoundSpriteNum = TRUE ;
SoundSpriteNum = p - > owner ;
handle = PlaySound ( p - > num , & p - > fx , & p - > fy , & p - > fz , p - > flags ) ;
//if(handle >= 0 || TEST(p->flags,v3df_ambient))
voc3dend - > owner = p - > owner ; // Transfer the owner
p - > deleted = TRUE ;
Use_SoundSpriteNum = FALSE ;
SoundSpriteNum = - 1 ;
//MONO_PRINT("TmpVocArray playing a non-follow sound");
}
}
// } // MoveSkip8
// Clean out any deleted sounds now
Delete3DSounds ( ) ;
}
//////////////////////////////////////////////////
// Terminate the sounds list
//////////////////////////////////////////////////
void
Terminate3DSounds ( void )
{
VOC3D_INFOp vp ;
vp = voc3dstart ;
while ( vp )
{
2019-11-26 08:25:08 +00:00
if ( vp - > handle > 0 )
FX_StopSound ( vp - > handle ) ; // Make sure to stop active sounds
vp - > handle = 0 ;
2015-05-19 21:54:34 +00:00
vp - > deleted = TRUE ;
vp = vp - > next ;
}
Delete3DSounds ( ) ; // Now delete all remaining sounds
ClearSoundLocks ( ) ;
}
void
DumpSounds ( void )
{
VOC3D_INFOp vp ;
vp = voc3dstart ;
while ( vp )
{
if ( TEST ( vp - > flags , v3df_ambient ) )
sprintf ( ds , " vp->num=%d, vp->owner=%d, vp->vp->lock=%d " , ambarray [ vp - > num ] . diginame , vp - > owner , vp - > vp - > lock ) ;
else
sprintf ( ds , " vp->num=%d, vp->owner=%d, vp->vp->lock=%d " , vp - > num , vp - > owner , vp - > vp - > lock ) ;
DebugWriteString ( ds ) ;
if ( vp - > owner > = 0 )
{
SPRITEp sp = & sprite [ vp - > owner ] ;
2019-04-08 06:25:33 +00:00
sprintf ( ds , " sp->picnum=%d, sp->hitag=%d, sp->lotag=%d, sp->owner=%d \n " , TrackerCast ( sp - > picnum ) , TrackerCast ( sp - > hitag ) , TrackerCast ( sp - > lotag ) , TrackerCast ( sp - > owner ) ) ;
2015-05-19 21:54:34 +00:00
DebugWriteString ( ds ) ;
}
vp = vp - > next ;
}
}
//////////////////////////////////////////////////
// Set owner to check when to kill looping sounds
// Must be called immediately after PlaySound call
// since this only assigns value to last sound
// on voc list
//////////////////////////////////////////////////
void
Set3DSoundOwner ( short spritenum )
{
VOC3D_INFOp p ;
// ASSERT(p->handle != -1); // Check for bogus sounds
p = voc3dend ;
if ( ! p ) return ;
// Queue up sounds with ambient flag even if they didn't play right away!
if ( p - > handle ! = - 1 | | TEST ( p - > flags , v3df_ambient ) )
{
p - > owner = spritenum ;
}
else
{
p - > deleted = TRUE ;
p - > flags = v3df_kill ;
}
}
//////////////////////////////////////////////////
// Play a sound using special sprite setup
//////////////////////////////////////////////////
void
PlaySpriteSound ( short spritenum , int attrib_ndx , Voc3D_Flags flags )
{
SPRITEp sp = & sprite [ spritenum ] ;
USERp u = User [ spritenum ] ;
ASSERT ( u ) ;
// //DSPRINTF(ds,"index = %d, digi num = %d\n",attrib_ndx,u->Attrib->Sounds[attrib_ndx]);
// MONO_PRINT(ds);
PlaySound ( u - > Attrib - > Sounds [ attrib_ndx ] , & sp - > x , & sp - > y , & sp - > z , flags ) ;
}
2019-10-09 16:09:05 +00:00
END_SW_NS