2006-04-13 20:47:06 +00:00
//-------------------------------------------------------------------------
/*
2016-02-07 02:38:03 +00:00
Copyright ( C ) 2016 EDuke32 developers and contributors
2006-04-13 20:47:06 +00:00
2010-05-25 10:56:00 +00:00
This file is part of EDuke32 .
2006-04-13 20:47:06 +00:00
EDuke32 is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License version 2
as published by the Free Software Foundation .
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
2014-07-20 08:55:56 +00:00
Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
2006-04-13 20:47:06 +00:00
*/
//-------------------------------------------------------------------------
2019-09-21 18:59:54 +00:00
# include "ns.h" // Must come before everything else!
2017-02-25 08:15:45 +00:00
# include "compat.h"
2012-11-05 02:49:08 +00:00
2006-04-13 20:47:06 +00:00
# include "duke3d.h"
2019-11-10 22:58:51 +00:00
# include "z_music.h"
2019-12-09 23:01:45 +00:00
# include "mapinfo.h"
2019-12-12 20:42:58 +00:00
# include "sound/s_soundinternal.h"
2010-07-19 15:14:00 +00:00
2019-09-21 20:53:00 +00:00
BEGIN_DUKE_NS
2019-12-15 12:34:00 +00:00
int32_t g_highestSoundIdx ;
2019-09-21 20:53:00 +00:00
2015-02-11 05:22:00 +00:00
2019-12-15 12:34:00 +00:00
class DukeSoundEngine : public SoundEngine
2006-04-16 03:42:36 +00:00
{
2019-12-15 12:34:00 +00:00
// client specific parts of the sound engine go in this class.
void CalcPosVel ( int type , const void * source , const float pt [ 3 ] , int channum , int chanflags , FSoundID chanSound , FVector3 * pos , FVector3 * vel ) override ;
TArray < uint8_t > ReadSound ( int lumpnum ) ;
2009-08-06 10:12:13 +00:00
2019-12-15 12:34:00 +00:00
public :
2019-12-15 15:32:39 +00:00
DukeSoundEngine ( )
{
S_Rolloff = { ROLLOFF_Linear , 576 , 1088 } ; // These are the original values derived from the DN3D source, but the lower end looks like a bug. Needs checking and maybe an option.
}
2019-12-15 12:34:00 +00:00
} ;
2009-07-27 05:33:12 +00:00
2019-12-15 12:34:00 +00:00
//==========================================================================
//
// This is to avoid hardscoding the dependency on Wads into the sound engine
//
//==========================================================================
2006-04-13 20:47:06 +00:00
2019-12-15 12:34:00 +00:00
TArray < uint8_t > DukeSoundEngine : : ReadSound ( int lumpnum )
2006-04-16 03:42:36 +00:00
{
2019-12-15 12:34:00 +00:00
auto wlump = fileSystem . OpenFileReader ( lumpnum ) ;
return wlump . Read ( ) ;
2006-04-16 03:42:36 +00:00
}
2006-04-13 20:47:06 +00:00
2019-12-15 12:34:00 +00:00
//==========================================================================
//
//
//
//==========================================================================
2018-10-25 23:32:29 +00:00
void S_PauseSounds ( bool paused )
2016-02-02 06:39:22 +00:00
{
2019-12-15 12:34:00 +00:00
soundEngine - > SetPaused ( paused ) ;
}
2016-02-02 06:39:22 +00:00
2019-12-15 12:34:00 +00:00
//==========================================================================
//
//
//
//==========================================================================
2016-02-02 06:39:22 +00:00
2019-12-15 12:34:00 +00:00
void cacheAllSounds ( void )
{
for ( int i = 0 , j = 0 ; i < MAXSOUNDS ; + + i )
2016-02-02 06:39:22 +00:00
{
2019-12-15 12:34:00 +00:00
soundEngine - > CacheSound ( i ) ;
if ( ( i & 31 ) = = 0 )
gameHandleEvents ( ) ;
2016-02-02 06:39:22 +00:00
}
}
2019-12-15 12:34:00 +00:00
//==========================================================================
//
//
//
//==========================================================================
2006-04-13 20:47:06 +00:00
2019-12-15 12:34:00 +00:00
static inline int S_GetPitch ( int num )
{
auto const * snd = ( sound_t * ) soundEngine - > GetUserData ( num ) ;
int const range = abs ( snd - > pitchEnd - snd - > pitchStart ) ;
2010-01-05 21:53:14 +00:00
2019-12-15 12:34:00 +00:00
return ( range = = 0 ) ? snd - > pitchStart : min ( snd - > pitchStart , snd - > pitchEnd ) + rand ( ) % range ;
2006-04-13 20:47:06 +00:00
}
2019-12-15 12:34:00 +00:00
float S_ConvertPitch ( int lpitch )
2018-04-02 22:00:11 +00:00
{
2019-12-15 12:34:00 +00:00
return pow ( 2 , lpitch / 1200. ) ; // I hope I got this right that ASS uses a linear scale where 1200 is a full octave.
2018-04-02 22:00:11 +00:00
}
2012-08-13 18:25:48 +00:00
2019-12-15 12:34:00 +00:00
int S_GetUserFlags ( int sndnum )
2012-08-13 18:25:48 +00:00
{
2019-12-15 12:34:00 +00:00
return ( ( sound_t * ) soundEngine - > GetUserData ( sndnum + 1 ) ) - > flags ;
2012-08-13 18:25:48 +00:00
}
2019-12-15 09:00:25 +00:00
//==========================================================================
//
//
//
//==========================================================================
2015-02-11 05:22:00 +00:00
2019-12-15 12:34:00 +00:00
int S_DefineSound ( unsigned index , const char * filename , int minpitch , int maxpitch , int priority , int type , int distance , float volume )
2019-12-15 09:00:25 +00:00
{
2019-12-15 12:34:00 +00:00
if ( ( unsigned ) index > = MAXSOUNDS )
return - 1 ;
auto & S_sfx = soundEngine - > GetSounds ( ) ;
index + + ;
unsigned oldindex = S_sfx . Size ( ) ;
if ( index > = S_sfx . Size ( ) )
{
S_sfx . Resize ( index + 1 ) ;
for ( ; oldindex < = index ; oldindex + + )
{
S_sfx [ oldindex ] . Clear ( ) ;
}
}
auto sfx = & S_sfx [ index ] ;
bool alreadydefined = ! sfx - > bTentative ;
sfx - > UserData . Resize ( sizeof ( sound_t ) ) ;
auto sndinf = ( sound_t * ) sfx - > UserData . Data ( ) ;
sndinf - > flags = type & ~ SF_ONEINST_INTERNAL ;
if ( sndinf - > flags & SF_LOOP )
sndinf - > flags | = SF_ONEINST_INTERNAL ;
2019-12-15 15:32:39 +00:00
sfx - > lumpnum = fileSystem . FindFile ( filename ) ;
2019-12-15 12:34:00 +00:00
sndinf - > pitchStart = clamp ( minpitch , INT16_MIN , INT16_MAX ) ;
sndinf - > pitchEnd = clamp ( maxpitch , INT16_MIN , INT16_MAX ) ;
sndinf - > priority = priority & 255 ;
sndinf - > volAdjust = clamp ( distance , INT16_MIN , INT16_MAX ) ;
sfx - > Volume = volume ;
2019-12-15 15:32:39 +00:00
sfx - > NearLimit = 4 ;
2019-12-15 12:34:00 +00:00
return 0 ;
2019-12-15 09:00:25 +00:00
}
2018-10-25 23:32:29 +00:00
2019-12-15 12:34:00 +00:00
2019-12-15 09:00:25 +00:00
//==========================================================================
//
//
//
//==========================================================================
2012-08-13 18:25:48 +00:00
2019-12-15 12:34:00 +00:00
static int S_CalcDistAndAng ( int spriteNum , int soundNum , int sectNum ,
2019-12-15 09:00:25 +00:00
const vec3_t * cam , const vec3_t * pos , int * distPtr , FVector3 * sndPos )
{
2019-12-15 15:32:39 +00:00
// There's a lot of hackery going on here that could be mapped to rolloff and attenuation parameters.
// However, ultimately rolloff would also just reposition the sound source so this can remain as it is.
2019-12-15 09:00:25 +00:00
int orgsndist = 0 , sndang = 0 , sndist = 0 , explosion = 0 ;
2019-12-15 12:34:00 +00:00
auto const * snd = ( sound_t * ) soundEngine - > GetUserData ( soundNum ) ;
int userflags = snd - > flags ;
int dist_adjust = snd - > volAdjust ;
2018-10-25 23:32:29 +00:00
2019-12-15 15:32:39 +00:00
if ( PN ( spriteNum ) ! = APLAYER | | P_Get ( spriteNum ) ! = screenpeek )
{
orgsndist = sndist = FindDistance3D ( cam - > x - pos - > x , cam - > y - pos - > y , ( cam - > z - pos - > z ) ) ;
2018-10-25 23:32:29 +00:00
2019-12-15 15:32:39 +00:00
if ( ( userflags & ( SF_GLOBAL | SF_DTAG ) ) ! = SF_GLOBAL & & S_IsAmbientSFX ( spriteNum ) & & ( sector [ SECT ( spriteNum ) ] . lotag & 0xff ) < 9 ) // ST_9_SLIDING_ST_DOOR
sndist = divscale14 ( sndist , SHT ( spriteNum ) + 1 ) ;
}
2012-10-08 07:07:59 +00:00
2019-12-15 09:00:25 +00:00
sndist + = dist_adjust ;
if ( sndist < 0 )
sndist = 0 ;
2012-08-13 18:25:48 +00:00
2019-12-15 09:00:25 +00:00
if ( ! FURY & & sectNum > - 1 & & sndist & & PN ( spriteNum ) ! = MUSICANDSFX
& & ! cansee ( cam - > x , cam - > y , cam - > z - ( 24 < < 8 ) , sectNum , SX ( spriteNum ) , SY ( spriteNum ) , SZ ( spriteNum ) - ( 24 < < 8 ) , SECT ( spriteNum ) ) )
sndist + = sndist > > 5 ;
2012-10-08 07:07:17 +00:00
2019-12-15 09:00:25 +00:00
if ( ( userflags & ( SF_GLOBAL | SF_DTAG ) ) = = ( SF_GLOBAL | SF_DTAG ) )
{
boost :
int const sdist = dist_adjust ? dist_adjust : 6144 ;
2012-10-08 07:07:17 +00:00
2019-12-15 09:00:25 +00:00
explosion = true ;
2019-08-09 09:28:42 +00:00
2019-12-15 09:00:25 +00:00
if ( sndist > sdist )
sndist = sdist ;
}
else if ( ! FURY )
{
switch ( DYNAMICSOUNDMAP ( soundNum ) )
{
case PIPEBOMB_EXPLODE__STATIC :
case LASERTRIP_EXPLODE__STATIC :
case RPG_EXPLODE__STATIC :
goto boost ;
}
}
2012-10-08 07:07:17 +00:00
2019-12-15 15:32:39 +00:00
// Here the sound distance was clamped to a minimum of 144*4.
// It's better to handle rolloff in the backend instead of whacking the sound origin here.
// That way the lower end can be made customizable instead of losing all precision right here at the source.
if ( sndist < 0 ) sndist = 0 ;
2012-10-08 07:07:17 +00:00
2019-12-15 09:00:25 +00:00
if ( distPtr )
{
* distPtr = sndist ;
}
2012-10-08 07:07:17 +00:00
2019-12-15 09:00:25 +00:00
if ( sndPos )
{
2019-12-15 15:32:39 +00:00
// Now calculate the virtual position in sound system coordinates.
FVector3 sndvec = { float ( pos - > x - cam - > x ) , ( pos - > z - cam - > z ) / 16.f , float ( pos - > y - cam - > y ) } ; // distance vector. Note that the z-coordinate has different precision.
2019-12-15 09:00:25 +00:00
FVector3 campos = { float ( pos - > x ) , ( cam - > z ) / 16.f , float ( cam - > y ) } ; // camera position
sndvec * = float ( sndist ) / orgsndist ; // adjust by what was calculated above;
* sndPos = campos + sndvec ; // final sound pos - still in Build fixed point coordinates.
* sndPos * = ( 1.f / 16 ) ; sndPos - > Z = - sndPos - > Z ; // The sound engine works with Doom's coordinate system so do the necessary conversions
}
2012-10-08 07:07:17 +00:00
2019-12-15 09:00:25 +00:00
return explosion ;
2012-08-13 18:25:48 +00:00
}
2019-12-15 09:00:25 +00:00
//==========================================================================
//
//
//
//==========================================================================
2012-08-13 18:25:53 +00:00
2019-12-15 12:34:00 +00:00
void S_GetCamera ( vec3_t * * c , int32_t * ca , int32_t * cs )
2019-12-12 20:42:58 +00:00
{
if ( ud . camerasprite = = - 1 )
{
if ( ud . overhead_on ! = 2 )
{
2019-12-15 12:34:00 +00:00
if ( c ) * c = & CAMERA ( pos ) ;
if ( cs ) * cs = CAMERA ( sect ) ;
if ( ca ) * ca = fix16_to_int ( CAMERA ( q16ang ) ) ;
2019-12-12 20:42:58 +00:00
}
else
{
auto pPlayer = g_player [ screenpeek ] . ps ;
2019-12-15 12:34:00 +00:00
if ( c ) * c = & pPlayer - > pos ;
if ( cs ) * cs = pPlayer - > cursectnum ;
if ( ca ) * ca = fix16_to_int ( pPlayer - > q16ang ) ;
2019-12-12 20:42:58 +00:00
}
}
else
{
2019-12-15 12:34:00 +00:00
if ( c ) * c = & sprite [ ud . camerasprite ] . pos ;
if ( cs ) * cs = sprite [ ud . camerasprite ] . sectnum ;
if ( ca ) * ca = sprite [ ud . camerasprite ] . ang ;
2019-12-12 20:42:58 +00:00
}
2019-12-15 12:34:00 +00:00
}
2019-12-12 20:42:58 +00:00
2019-12-15 12:34:00 +00:00
//=========================================================================
//
// CalcPosVel
//
// The game specific part of the sound updater.
//
//=========================================================================
2019-12-12 20:42:58 +00:00
2019-12-15 12:34:00 +00:00
void DukeSoundEngine : : CalcPosVel ( int type , const void * source , const float pt [ 3 ] , int channum , int chanflags , FSoundID chanSound , FVector3 * pos , FVector3 * vel )
{
if ( pos ! = nullptr )
2019-12-12 20:42:58 +00:00
{
2019-12-15 12:34:00 +00:00
vec3_t * campos ;
int32_t camsect ;
S_GetCamera ( & campos , nullptr , & camsect ) ;
if ( vel ) vel - > Zero ( ) ;
2019-12-12 20:42:58 +00:00
2019-12-15 12:34:00 +00:00
// [BL] Moved this case out of the switch statement to make code easier
// on static analysis.
if ( type = = SOURCE_Unattached )
2019-12-12 20:42:58 +00:00
{
2019-12-15 12:34:00 +00:00
pos - > X = pt [ 0 ] ;
pos - > Y = campos & & ! ( chanflags & CHAN_LISTENERZ ) ? pt [ 1 ] : campos - > z / 256.f ;
pos - > Z = pt [ 2 ] ;
}
else
{
switch ( type )
{
case SOURCE_None :
default :
break ;
case SOURCE_Actor :
{
auto actor = ( spritetype * ) source ;
assert ( actor ! = nullptr ) ;
if ( actor ! = nullptr )
{
S_CalcDistAndAng ( int ( actor - sprite ) , chanSound - 1 , camsect , campos , & actor - > pos , nullptr , pos ) ;
/*
if ( vel )
{
vel - > X = float ( actor - > Vel . X * TICRATE ) ;
vel - > Y = float ( actor - > Vel . Z * TICRATE ) ;
vel - > Z = float ( actor - > Vel . Y * TICRATE ) ;
}
*/
}
break ;
}
}
if ( ( chanflags & CHAN_LISTENERZ ) & & campos ! = nullptr )
{
pos - > Y = campos - > z / 256.f ;
}
}
}
}
2019-12-12 20:42:58 +00:00
2019-12-15 12:34:00 +00:00
//==========================================================================
//
//
//
//==========================================================================
2019-12-12 20:42:58 +00:00
2019-12-15 12:34:00 +00:00
void S_Update ( void )
{
SoundListener listener ;
vec3_t * c ;
int32_t ca , cs ;
2019-12-12 20:42:58 +00:00
2019-12-15 12:34:00 +00:00
S_GetCamera ( & c , & ca , & cs ) ;
2019-12-12 20:42:58 +00:00
2019-12-15 12:34:00 +00:00
if ( c ! = nullptr )
{
listener . angle = ( float ) ca * pi : : pi ( ) / 2048 ; // todo: Check value range for angle.
listener . velocity . Zero ( ) ;
listener . position = { c - > x / 16.f , c - > z / 256.f , c - > y / 16.f } ;
listener . underwater = false ;
// This should probably use a real environment instead of the pitch hacking in S_PlaySound3D.
// listenactor->waterlevel == 3;
//assert(primaryLevel->Zones.Size() > listenactor->Sector->ZoneNumber);
listener . Environment = 0 ; // primaryLevel->Zones[listenactor->Sector->ZoneNumber].Environment;
listener . valid = true ;
}
else
{
listener . angle = 0 ;
listener . position . Zero ( ) ;
listener . velocity . Zero ( ) ;
listener . underwater = false ;
listener . Environment = nullptr ;
listener . valid = false ;
}
listener . ListenerObject = ud . camerasprite = = - 1 ? nullptr : & sprite [ ud . camerasprite ] ;
soundEngine - > SetListener ( listener ) ;
2019-12-12 20:42:58 +00:00
}
2014-06-23 02:24:10 +00:00
2019-12-12 20:42:58 +00:00
//==========================================================================
//
//
//
//==========================================================================
2014-06-23 02:24:10 +00:00
2019-12-15 12:34:00 +00:00
int S_PlaySound3D ( int num , int spriteNum , const vec3_t * pos , bool looped )
2019-12-12 20:42:58 +00:00
{
int32_t j = VM_OnEventWithReturn ( EVENT_SOUND , spriteNum , screenpeek , num ) ;
2012-05-17 17:33:29 +00:00
2019-12-12 20:42:58 +00:00
int sndnum = VM_OnEventWithReturn ( EVENT_SOUND , spriteNum , screenpeek , num ) ;
2018-05-04 22:42:37 +00:00
2019-07-08 00:41:25 +00:00
auto const pPlayer = g_player [ myconnectindex ] . ps ;
2019-12-12 20:42:58 +00:00
if ( ! soundEngine - > isValidSoundId ( sndnum ) | | ! SoundEnabled ( ) | | ( unsigned ) spriteNum > = MAXSPRITES | | ( pPlayer - > gm & MODE_MENU ) | |
( pPlayer - > timebeforeexit > 0 & & pPlayer - > timebeforeexit < = GAMETICSPERSEC * 3 ) ) return - 1 ;
2015-02-11 05:22:00 +00:00
2019-12-15 12:34:00 +00:00
int userflags = S_GetUserFlags ( sndnum ) ;
2019-12-12 20:42:58 +00:00
if ( ( ! ( snd_speech & 1 ) & & ( userflags & SF_TALK ) ) | | ( ( userflags & SF_ADULT ) & & adult_lockout ) )
2013-03-31 18:58:17 +00:00
return - 1 ;
2006-04-13 20:47:06 +00:00
2018-05-04 22:42:37 +00:00
// Duke talk
2019-12-12 20:42:58 +00:00
if ( userflags & SF_TALK )
2018-05-04 22:42:37 +00:00
{
2018-10-25 23:32:29 +00:00
if ( ( g_netServer | | ud . multimode > 1 ) & & PN ( spriteNum ) = = APLAYER & & P_Get ( spriteNum ) ! = screenpeek ) // other player sound
2018-05-04 22:42:37 +00:00
{
2019-10-22 00:01:05 +00:00
if ( ( snd_speech & 4 ) ! = 4 )
2018-05-04 22:42:37 +00:00
return - 1 ;
}
2019-10-22 00:01:05 +00:00
else if ( ( snd_speech & 1 ) ! = 1 )
2018-05-04 22:42:37 +00:00
return - 1 ;
2015-02-11 05:22:00 +00:00
2019-12-15 12:34:00 +00:00
bool foundone = soundEngine - > EnumerateChannels ( [ & ] ( FSoundChan * chan )
{
auto sid = chan - > SoundID ;
auto flags = ( ( sound_t * ) soundEngine - > GetUserData ( sid ) ) - > flags ;
return ! ! ( flags & SF_TALK ) ;
} ) ;
2018-05-04 22:42:37 +00:00
// don't play if any Duke talk sounds are already playing
2019-12-15 12:34:00 +00:00
if ( foundone ) return - 1 ;
2018-05-04 22:42:37 +00:00
}
2019-12-12 20:42:58 +00:00
else if ( ( userflags & ( SF_DTAG | SF_GLOBAL ) ) = = SF_DTAG ) // Duke-Tag sound
2006-04-13 20:47:06 +00:00
{
2019-12-12 20:42:58 +00:00
return S_PlaySound ( sndnum ) ;
2018-05-04 22:42:37 +00:00
2006-04-13 20:47:06 +00:00
}
2019-12-15 09:00:25 +00:00
int32_t sndist ;
FVector3 sndpos ; // this is in sound engine space.
2019-12-15 12:34:00 +00:00
vec3_t * campos ;
int32_t camsect ;
S_GetCamera ( & campos , nullptr , & camsect ) ;
int const explosionp = S_CalcDistAndAng ( spriteNum , sndnum , camsect , campos , pos , & sndist , & sndpos ) ;
2019-12-12 20:42:58 +00:00
int pitch = S_GetPitch ( sndnum ) ;
auto const pOther = g_player [ screenpeek ] . ps ;
2006-04-13 20:47:06 +00:00
2012-08-22 22:50:32 +00:00
2018-05-04 22:42:37 +00:00
if ( pOther - > sound_pitch )
pitch + = pOther - > sound_pitch ;
2012-08-13 18:25:51 +00:00
if ( explosionp )
2006-04-13 20:47:06 +00:00
{
2018-05-04 22:42:37 +00:00
if ( pOther - > cursectnum > - 1 & & sector [ pOther - > cursectnum ] . lotag = = ST_2_UNDERWATER )
2006-11-16 03:02:42 +00:00
pitch - = 1024 ;
2012-08-13 18:25:51 +00:00
}
else
{
2019-12-12 20:42:58 +00:00
if ( sndist > 32767 & & PN ( spriteNum ) ! = MUSICANDSFX & & ( userflags & ( SF_LOOP | SF_MSFX ) ) = = 0 )
2011-03-04 08:50:58 +00:00
return - 1 ;
2012-08-13 18:25:51 +00:00
2018-05-04 22:42:37 +00:00
if ( pOther - > cursectnum > - 1 & & sector [ pOther - > cursectnum ] . lotag = = ST_2_UNDERWATER
2019-12-12 20:42:58 +00:00
& & ( userflags & SF_TALK ) = = 0 )
2006-11-16 03:02:42 +00:00
pitch = - 768 ;
2006-04-13 20:47:06 +00:00
}
2019-12-15 12:34:00 +00:00
bool is_playing = soundEngine - > GetSoundPlayingInfo ( SOURCE_Any , nullptr , sndnum + 1 ) ;
2019-12-15 09:00:25 +00:00
if ( is_playing & & PN ( spriteNum ) ! = MUSICANDSFX )
S_StopEnvSound ( sndnum , spriteNum ) ;
2006-04-13 20:47:06 +00:00
2019-12-15 09:00:25 +00:00
int const repeatp = ( userflags & SF_LOOP ) ;
2006-04-13 20:47:06 +00:00
2019-12-15 09:00:25 +00:00
if ( repeatp & & ( userflags & SF_ONEINST_INTERNAL ) & & is_playing )
2010-03-01 09:09:26 +00:00
{
return - 1 ;
}
2010-01-05 21:53:14 +00:00
2019-12-15 09:00:25 +00:00
// Now
2019-12-15 15:32:39 +00:00
float attenuation = ( userflags & ( SF_GLOBAL | SF_DTAG ) ) = = SF_GLOBAL ? ATTN_NONE : ATTN_NORM ;
2019-12-15 12:34:00 +00:00
auto chflg = ( ( userflags & SF_LOOP ) | | looped ) ? CHAN_AUTO | CHAN_LOOP : CHAN_AUTO ;
2019-12-15 15:32:39 +00:00
auto chan = soundEngine - > StartSound ( SOURCE_Actor , & sprite [ spriteNum ] , & sndpos , chflg , sndnum + 1 , 1.f , attenuation , nullptr , S_ConvertPitch ( pitch ) ) ;
2019-12-15 09:00:25 +00:00
if ( ! chan ) return - 1 ;
return 0 ;
2006-04-13 20:47:06 +00:00
}
2019-12-12 20:42:58 +00:00
//==========================================================================
//
//
//
//==========================================================================
2019-12-15 12:34:00 +00:00
int S_PlaySound ( int num , bool looped )
2006-04-13 20:47:06 +00:00
{
2018-10-25 23:32:29 +00:00
int sndnum = VM_OnEventWithReturn ( EVENT_SOUND , g_player [ screenpeek ] . ps - > i , screenpeek , num ) ;
2014-06-23 02:24:10 +00:00
2019-12-15 12:34:00 +00:00
if ( ! soundEngine - > isValidSoundId ( sndnum + 1 ) | | ! SoundEnabled ( ) ) return - 1 ;
2007-08-15 03:05:14 +00:00
2019-12-15 12:34:00 +00:00
int userflags = S_GetUserFlags ( sndnum ) ;
2019-12-12 20:42:58 +00:00
if ( ( ! ( snd_speech & 1 ) & & ( userflags & SF_TALK ) ) | | ( ( userflags & SF_ADULT ) & & adult_lockout ) )
2015-02-11 05:22:00 +00:00
return - 1 ;
2012-01-10 23:44:49 +00:00
2019-12-15 12:34:00 +00:00
int const pitch = S_GetPitch ( sndnum ) ;
2006-04-13 20:47:06 +00:00
2019-12-15 12:34:00 +00:00
auto chflg = ( ( userflags & SF_LOOP ) | | looped ) ? CHAN_AUTO | CHAN_LOOP : CHAN_AUTO ;
soundEngine - > StartSound ( SOURCE_None , nullptr , nullptr , chflg , sndnum + 1 , 1.f , ATTN_NONE , nullptr , S_ConvertPitch ( pitch ) ) ;
2019-12-12 20:42:58 +00:00
/* for reference. May still be needed for balancing later.
: FX_Play3D ( snd . ptr , snd . siz , FX_ONESHOT , pitch , 0 , 255 - LOUDESTVOLUME , snd . pr , snd . volume ,
( num * MAXSOUNDINSTANCES ) + sndnum ) ;
*/
return 0 ;
2006-04-13 20:47:06 +00:00
}
2019-12-12 20:42:58 +00:00
//==========================================================================
//
//
//
//==========================================================================
2019-12-15 12:34:00 +00:00
int A_PlaySound ( int soundNum , int spriteNum , bool looped )
2006-04-13 20:47:06 +00:00
{
2019-12-15 12:34:00 +00:00
return ( unsigned ) spriteNum > = MAXSPRITES ? S_PlaySound ( soundNum , looped ) :
S_PlaySound3D ( soundNum , spriteNum , & sprite [ spriteNum ] . pos , looped ) ;
2006-04-13 20:47:06 +00:00
}
2019-08-09 11:00:34 +00:00
void S_StopEnvSound ( int sndNum , int sprNum )
2006-04-13 20:47:06 +00:00
{
2019-12-12 20:42:58 +00:00
if ( sprNum < - 1 | | sprNum > = MAXSPRITES ) return ;
2010-03-01 09:09:26 +00:00
2019-12-15 12:34:00 +00:00
if ( sprNum = = - 1 ) soundEngine - > StopSoundID ( sndNum + 1 ) ;
else soundEngine - > StopSound ( SOURCE_Actor , & sprite [ sprNum ] , - 1 , sndNum + 1 ) ;
2017-01-05 05:29:25 +00:00
}
2018-10-25 23:32:29 +00:00
void S_ChangeSoundPitch ( int soundNum , int spriteNum , int pitchoffset )
2011-11-03 23:08:54 +00:00
{
2019-12-12 20:42:58 +00:00
if ( spriteNum < - 1 | | spriteNum > = MAXSPRITES ) return ;
double expitch = pow ( 2 , pitchoffset / 1200. ) ; // I hope I got this right that ASS uses a linear scale where 1200 is a full octave.
if ( spriteNum = = - 1 )
2011-11-03 23:08:54 +00:00
{
2019-12-15 12:34:00 +00:00
soundEngine - > ChangeSoundPitch ( SOURCE_Unattached , nullptr , CHAN_AUTO , expitch , soundNum + 1 ) ;
2006-04-13 20:47:06 +00:00
}
else
{
2019-12-15 12:34:00 +00:00
soundEngine - > ChangeSoundPitch ( SOURCE_Actor , & sprite [ spriteNum ] , CHAN_AUTO , expitch , soundNum + 1 ) ;
2006-04-13 20:47:06 +00:00
}
}
2019-12-12 20:42:58 +00:00
//==========================================================================
//
//
//
//==========================================================================
2006-04-13 20:47:06 +00:00
2019-08-07 22:44:29 +00:00
int A_CheckSoundPlaying ( int spriteNum , int soundNum )
2006-04-16 03:42:36 +00:00
{
2019-12-15 12:34:00 +00:00
if ( spriteNum = = - 1 ) return soundEngine - > GetSoundPlayingInfo ( SOURCE_Any , nullptr , soundNum + 1 ) ;
2019-12-12 20:42:58 +00:00
if ( ( unsigned ) spriteNum > = MAXSPRITES ) return false ;
2019-12-15 12:34:00 +00:00
return soundEngine - > IsSourcePlayingSomething ( SOURCE_Actor , & sprite [ spriteNum ] , CHAN_AUTO , soundNum + 1 ) ;
2006-04-16 03:42:36 +00:00
}
2013-01-02 22:33:32 +00:00
// Check if actor <i> is playing any sound.
2019-08-07 22:44:29 +00:00
int A_CheckAnySoundPlaying ( int spriteNum )
2013-01-02 22:33:32 +00:00
{
2019-12-12 20:42:58 +00:00
if ( ( unsigned ) spriteNum > = MAXSPRITES ) return false ;
return soundEngine - > IsSourcePlayingSomething ( SOURCE_Actor , & sprite [ spriteNum ] , CHAN_AUTO , 0 ) ;
2013-01-02 22:33:32 +00:00
}
2019-08-07 22:44:29 +00:00
int S_CheckSoundPlaying ( int soundNum )
2006-04-16 03:42:36 +00:00
{
2019-12-15 12:34:00 +00:00
return soundEngine - > GetSoundPlayingInfo ( SOURCE_Any , nullptr , soundNum + 1 ) ;
2006-04-16 03:42:36 +00:00
}
2019-12-12 17:43:27 +00:00
//==========================================================================
//
//
//
//==========================================================================
void S_MenuSound ( void )
{
static int SoundNum ;
int const menusnds [ ] = {
LASERTRIP_EXPLODE , DUKE_GRUNT , DUKE_LAND_HURT , CHAINGUN_FIRE , SQUISHED , KICK_HIT ,
PISTOL_RICOCHET , PISTOL_BODYHIT , PISTOL_FIRE , SHOTGUN_FIRE , BOS1_WALK , RPG_EXPLODE ,
PIPEBOMB_BOUNCE , PIPEBOMB_EXPLODE , NITEVISION_ONOFF , RPG_SHOOT , SELECT_WEAPON ,
} ;
int s = VM_OnEventWithReturn ( EVENT_OPENMENUSOUND , g_player [ screenpeek ] . ps - > i , screenpeek , FURY ? - 1 : menusnds [ SoundNum + + % ARRAY_SIZE ( menusnds ) ] ) ;
if ( s ! = - 1 )
S_PlaySound ( s ) ;
}
2019-12-12 20:42:58 +00:00
//==========================================================================
//
// Music
//
//==========================================================================
2019-12-12 17:43:27 +00:00
static void S_SetMusicIndex ( unsigned int m )
{
ud . music_episode = m / MAXLEVELS ;
ud . music_level = m % MAXLEVELS ;
}
void S_PlayLevelMusicOrNothing ( unsigned int m )
{
ud . returnvar [ 0 ] = m / MAXLEVELS ;
ud . returnvar [ 1 ] = m % MAXLEVELS ;
int retval = VM_OnEvent ( EVENT_PLAYLEVELMUSICSLOT , g_player [ myconnectindex ] . ps - > i , myconnectindex ) ;
if ( retval > = 0 )
{
// Thanks to scripting that stupid slot hijack cannot be refactored - but we'll store the real data elsewhere anyway!
auto & mr = m = = USERMAPMUSICFAKESLOT ? userMapRecord : mapList [ m ] ;
Mus_Play ( mr . labelName , mr . music , true ) ;
S_SetMusicIndex ( m ) ;
}
}
int S_TryPlaySpecialMusic ( unsigned int m )
{
auto & musicfn = mapList [ m ] . music ;
if ( musicfn . IsNotEmpty ( ) )
{
if ( ! Mus_Play ( nullptr , musicfn , true ) )
{
S_SetMusicIndex ( m ) ;
return 0 ;
}
}
return 1 ;
}
void S_PlaySpecialMusicOrNothing ( unsigned int m )
{
if ( S_TryPlaySpecialMusic ( m ) )
{
S_SetMusicIndex ( m ) ;
}
}
void S_ContinueLevelMusic ( void )
{
VM_OnEvent ( EVENT_CONTINUELEVELMUSICSLOT , g_player [ myconnectindex ] . ps - > i , myconnectindex ) ;
}
2019-09-21 20:53:00 +00:00
END_DUKE_NS