2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
2012-11-28 15:47:07 +00:00
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
2012-11-26 18:58:24 +00:00
Doom 3 BFG Edition Source Code 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 .
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 BFG Edition Source Code is also subject to certain additional terms . You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code . If not , please request a copy in writing from id Software at the address below .
If you have questions concerning this license or the applicable additional terms , you may contact in writing id Software LLC , c / o ZeniMax Media Inc . , Suite 120 , Rockville , Maryland 20850 USA .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# pragma hdrstop
# include "../idlib/precompiled.h"
# include "snd_local.h"
idCVar s_singleEmitter ( " s_singleEmitter " , " 0 " , CVAR_INTEGER , " mute all sounds but this emitter " ) ;
idCVar s_showStartSound ( " s_showStartSound " , " 0 " , CVAR_BOOL , " print a message every time a sound starts/stops " ) ;
idCVar s_useOcclusion ( " s_useOcclusion " , " 1 " , CVAR_BOOL , " Attenuate sounds based on walls " ) ;
idCVar s_centerFractionVO ( " s_centerFractionVO " , " 0.75 " , CVAR_FLOAT , " Portion of VO sounds routed to the center channel " ) ;
extern idCVar s_playDefaultSound ;
extern idCVar s_noSound ;
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idSoundFade
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundFade : : Clear
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundFade : : Clear ( )
{
2012-11-26 18:58:24 +00:00
fadeStartTime = 0 ;
fadeEndTime = 0 ;
fadeStartVolume = 0.0f ;
fadeEndVolume = 0.0f ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundFade : : SetVolume
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundFade : : SetVolume ( float to )
{
2012-11-26 18:58:24 +00:00
fadeStartVolume = to ;
fadeEndVolume = to ;
fadeStartTime = 0 ;
fadeEndTime = 0 ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundFade : : Fade
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundFade : : Fade ( float to , int length , int soundTime )
{
2012-11-26 18:58:24 +00:00
int startTime = soundTime ;
// if it is already fading to this volume at this rate, don't change it
2012-11-28 15:47:07 +00:00
if ( fadeEndTime = = startTime + length & & fadeEndVolume = = to )
{
2012-11-26 18:58:24 +00:00
return ;
}
fadeStartVolume = GetVolume ( soundTime ) ;
fadeEndVolume = to ;
fadeStartTime = startTime ;
fadeEndTime = startTime + length ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundFade : : GetVolume
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
float idSoundFade : : GetVolume ( const int soundTime ) const
{
2012-11-26 18:58:24 +00:00
const float fadeDuration = ( fadeEndTime - fadeStartTime ) ;
const int currentTime = soundTime ;
const float playTime = ( currentTime - fadeStartTime ) ;
2012-11-28 15:47:07 +00:00
if ( fadeDuration < = 0.0f )
{
2012-11-26 18:58:24 +00:00
return fadeEndVolume ;
2012-11-28 15:47:07 +00:00
}
else if ( currentTime > = fadeEndTime )
{
2012-11-26 18:58:24 +00:00
return fadeEndVolume ;
2012-11-28 15:47:07 +00:00
}
else if ( currentTime > fadeStartTime )
{
2012-11-26 18:58:24 +00:00
return fadeStartVolume + ( fadeEndVolume - fadeStartVolume ) * playTime / fadeDuration ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return fadeStartVolume ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundChannel : : idSoundChannel
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idSoundChannel : : idSoundChannel ( )
{
2012-11-26 18:58:24 +00:00
emitter = NULL ;
hardwareVoice = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
startTime = 0 ;
endTime = 0 ;
leadinSample = NULL ;
loopingSample = NULL ;
logicalChannel = SCHANNEL_ANY ;
allowSlow = false ;
soundShader = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
volumeFade . Clear ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
volumeDB = DB_SILENCE ;
currentAmplitude = 0.0f ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundChannel : : ~ idSoundChannel
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idSoundChannel : : ~ idSoundChannel ( )
{
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundChannel : : CanMute
Never actually mute VO because we can ' t restart them precisely enough for lip syncing to not fuck up
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSoundChannel : : CanMute ( ) const
{
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundChannel : : Mute
A muted sound is considered still running , and can restart when a listener
gets close enough .
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundChannel : : Mute ( )
{
if ( hardwareVoice ! = NULL )
{
2012-11-26 18:58:24 +00:00
soundSystemLocal . FreeVoice ( hardwareVoice ) ;
hardwareVoice = NULL ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundChannel : : IsLooping
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSoundChannel : : IsLooping ( ) const
{
2012-11-26 18:58:24 +00:00
return ( parms . soundShaderFlags & SSF_LOOPING ) ! = 0 ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundChannel : : CheckForCompletion
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSoundChannel : : CheckForCompletion ( int currentTime )
{
if ( leadinSample = = NULL )
{
2012-11-26 18:58:24 +00:00
return true ;
}
// endTime of 0 indicates a sound should loop forever
2012-11-28 15:47:07 +00:00
if ( endTime > 0 & & endTime < currentTime )
{
2012-11-26 18:58:24 +00:00
return true ;
}
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundChannel : : UpdateVolume
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundChannel : : UpdateVolume ( int currentTime )
{
idSoundWorldLocal * soundWorld = emitter - > soundWorld ;
2012-11-26 18:58:24 +00:00
volumeDB = DB_SILENCE ;
currentAmplitude = 0.0f ;
2012-11-28 15:47:07 +00:00
if ( leadinSample = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( startTime > currentTime )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( endTime > 0 & & endTime < currentTime )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if you don't want to hear all the beeps from missing sounds
2012-11-28 15:47:07 +00:00
if ( leadinSample - > IsDefault ( ) & & ! s_playDefaultSound . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool emitterIsListener = ( emitter - > emitterId = = soundWorld - > listener . id ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if it is a private sound, set the volume to zero unless we match the listener.id
2012-11-28 15:47:07 +00:00
if ( parms . soundShaderFlags & SSF_PRIVATE_SOUND )
{
if ( ! emitterIsListener )
{
2012-11-26 18:58:24 +00:00
return ;
}
}
2012-11-28 15:47:07 +00:00
if ( parms . soundShaderFlags & SSF_ANTI_PRIVATE_SOUND )
{
if ( emitterIsListener )
{
2012-11-26 18:58:24 +00:00
return ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// volume fading
float newVolumeDB = parms . volume ;
newVolumeDB + = volumeFade . GetVolume ( currentTime ) ;
newVolumeDB + = soundWorld - > volumeFade . GetVolume ( currentTime ) ;
newVolumeDB + = soundWorld - > pauseFade . GetVolume ( currentTime ) ;
2012-11-28 15:47:07 +00:00
if ( parms . soundClass > = 0 & & parms . soundClass < SOUND_MAX_CLASSES )
{
2012-11-26 18:58:24 +00:00
newVolumeDB + = soundWorld - > soundClassFade [ parms . soundClass ] . GetVolume ( currentTime ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool global = ( parms . soundShaderFlags & SSF_GLOBAL ) ! = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// attenuation
2012-11-28 15:47:07 +00:00
if ( ! global & & ! emitterIsListener )
{
2012-11-26 18:58:24 +00:00
float distance = ( parms . soundShaderFlags & SSF_NO_OCCLUSION ) = = 0 ? emitter - > spatializedDistance : emitter - > directDistance ;
float mindist = parms . minDistance ;
float maxdist = parms . maxDistance ;
2012-11-28 15:47:07 +00:00
if ( distance > = maxdist )
{
2012-11-26 18:58:24 +00:00
newVolumeDB = DB_SILENCE ;
2012-11-28 15:47:07 +00:00
}
else if ( ( distance > mindist ) & & ( maxdist > mindist ) )
{
2012-11-26 18:58:24 +00:00
float f = ( distance - mindist ) / ( maxdist - mindist ) ;
newVolumeDB + = LinearToDB ( Square ( 1.0f - f ) ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( soundSystemLocal . musicMuted & & ( parms . soundShaderFlags & SSF_MUSIC ) ! = 0 )
{
2012-11-26 18:58:24 +00:00
newVolumeDB = DB_SILENCE ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// store the new volume on the channel
volumeDB = newVolumeDB ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// keep track of the maximum volume
float currentVolumeDB = newVolumeDB ;
2012-11-28 15:47:07 +00:00
if ( hardwareVoice ! = NULL )
{
2012-11-26 18:58:24 +00:00
float amplitude = hardwareVoice - > GetAmplitude ( ) ;
2012-11-28 15:47:07 +00:00
if ( amplitude < = 0.0f )
{
2012-11-26 18:58:24 +00:00
currentVolumeDB = DB_SILENCE ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
currentVolumeDB + = LinearToDB ( amplitude ) ;
}
currentAmplitude = amplitude ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundChannel : : UpdateHardware
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundChannel : : UpdateHardware ( float volumeAdd , int currentTime )
{
idSoundWorldLocal * soundWorld = emitter - > soundWorld ;
if ( soundWorld = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( leadinSample = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( startTime > currentTime )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( endTime > 0 & & endTime < currentTime )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// convert volumes from decibels to linear
float volume = Max ( 0.0f , DBtoLinear ( volumeDB + volumeAdd ) ) ;
2012-11-28 15:47:07 +00:00
if ( ( parms . soundShaderFlags & SSF_UNCLAMPED ) = = 0 )
{
2012-11-26 18:58:24 +00:00
volume = Min ( 1.0f , volume ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool global = ( parms . soundShaderFlags & SSF_GLOBAL ) ! = 0 ;
bool omni = ( parms . soundShaderFlags & SSF_OMNIDIRECTIONAL ) ! = 0 ;
bool emitterIsListener = ( emitter - > emitterId = = soundWorld - > listener . id ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int startOffset = 0 ;
bool issueStart = false ;
2012-11-28 15:47:07 +00:00
if ( hardwareVoice = = NULL )
{
if ( volume < = 0.00001f )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
hardwareVoice = soundSystemLocal . AllocateVoice ( leadinSample , loopingSample ) ;
2012-11-28 15:47:07 +00:00
if ( hardwareVoice = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
issueStart = true ;
startOffset = currentTime - startTime ;
}
2012-11-28 15:47:07 +00:00
if ( omni | | global | | emitterIsListener )
{
2012-11-26 18:58:24 +00:00
hardwareVoice - > SetPosition ( vec3_zero ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
hardwareVoice - > SetPosition ( ( emitter - > spatializedOrigin - soundWorld - > listener . pos ) * soundWorld - > listener . axis . Transpose ( ) ) ;
}
2012-11-28 15:47:07 +00:00
if ( parms . soundShaderFlags & SSF_VO )
{
2012-11-26 18:58:24 +00:00
hardwareVoice - > SetCenterChannel ( s_centerFractionVO . GetFloat ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
hardwareVoice - > SetCenterChannel ( 0.0f ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
extern idCVar timescale ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
hardwareVoice - > SetGain ( volume ) ;
hardwareVoice - > SetInnerRadius ( parms . minDistance * METERS_TO_DOOM ) ;
hardwareVoice - > SetPitch ( soundWorld - > slowmoSpeed * idMath : : ClampFloat ( 0.2f , 5.0f , timescale . GetFloat ( ) ) ) ;
2012-11-28 15:47:07 +00:00
if ( soundWorld - > enviroSuitActive )
{
2012-11-26 18:58:24 +00:00
hardwareVoice - > SetOcclusion ( 0.5f ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
hardwareVoice - > SetOcclusion ( 0.0f ) ;
}
2012-11-28 15:47:07 +00:00
if ( issueStart )
{
2012-11-26 18:58:24 +00:00
hardwareVoice - > Start ( startOffset , parms . soundShaderFlags | ( parms . shakes = = 0.0f ? SSF_NO_FLICKER : 0 ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
hardwareVoice - > Update ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idSoundEmitterLocal
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundEmitterLocal : : idSoundEmitterLocal
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idSoundEmitterLocal : : idSoundEmitterLocal ( )
{
2012-11-26 18:58:24 +00:00
Init ( 0 , NULL ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundEmitterLocal : : ~ idSoundEmitterLocal
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idSoundEmitterLocal : : ~ idSoundEmitterLocal ( )
{
2012-11-26 18:58:24 +00:00
assert ( channels . Num ( ) = = 0 ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundEmitterLocal : : Clear
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundEmitterLocal : : Init ( int i , idSoundWorldLocal * sw )
{
2012-11-26 18:58:24 +00:00
index = i ;
soundWorld = sw ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Init should only be called on a freshly constructed sound emitter or in a Reset()
assert ( channels . Num ( ) = = 0 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
canFree = false ;
origin . Zero ( ) ;
emitterId = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
directDistance = 0.0f ;
lastValidPortalArea = - 1 ;
spatializedDistance = 0.0f ;
spatializedOrigin . Zero ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
memset ( & parms , 0 , sizeof ( parms ) ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundEmitterLocal : : Reset
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundEmitterLocal : : Reset ( )
{
for ( int i = 0 ; i < channels . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
soundWorld - > FreeSoundChannel ( channels [ i ] ) ;
}
channels . Clear ( ) ;
Init ( index , soundWorld ) ;
}
/*
= = = = = = = = = = = = = = = = = =
idSoundEmitterLocal : : OverrideParms
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundEmitterLocal : : OverrideParms ( const soundShaderParms_t * base , const soundShaderParms_t * over , soundShaderParms_t * out )
{
if ( ! over )
{
2012-11-26 18:58:24 +00:00
* out = * base ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( over - > minDistance )
{
2012-11-26 18:58:24 +00:00
out - > minDistance = over - > minDistance ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
out - > minDistance = base - > minDistance ;
}
2012-11-28 15:47:07 +00:00
if ( over - > maxDistance )
{
2012-11-26 18:58:24 +00:00
out - > maxDistance = over - > maxDistance ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
out - > maxDistance = base - > maxDistance ;
}
2012-11-28 15:47:07 +00:00
if ( over - > shakes )
{
2012-11-26 18:58:24 +00:00
out - > shakes = over - > shakes ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
out - > shakes = base - > shakes ;
}
2012-11-28 15:47:07 +00:00
if ( over - > volume )
{
2012-11-26 18:58:24 +00:00
out - > volume = over - > volume ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
out - > volume = base - > volume ;
}
2012-11-28 15:47:07 +00:00
if ( over - > soundClass )
{
2012-11-26 18:58:24 +00:00
out - > soundClass = over - > soundClass ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
out - > soundClass = base - > soundClass ;
}
out - > soundShaderFlags = base - > soundShaderFlags | over - > soundShaderFlags ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundEmitterLocal : : CheckForCompletion
Checks to see if any of the channels have completed , removing them as they do
This will also play any postSounds on the same channel as their owner .
Returns true if the emitter should be freed .
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSoundEmitterLocal : : CheckForCompletion ( int currentTime )
{
for ( int i = channels . Num ( ) - 1 ; i > = 0 ; i - - )
{
idSoundChannel * chan = channels [ i ] ;
if ( chan - > CheckForCompletion ( currentTime ) )
{
2012-11-26 18:58:24 +00:00
channels . RemoveIndex ( i ) ;
soundWorld - > FreeSoundChannel ( chan ) ;
}
}
return ( canFree & & channels . Num ( ) = = 0 ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundEmitterLocal : : Update
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundEmitterLocal : : Update ( int currentTime )
{
if ( channels . Num ( ) = = 0 )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
directDistance = ( soundWorld - > listener . pos - origin ) . LengthFast ( ) * DOOM_TO_METERS ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
spatializedDistance = directDistance ;
spatializedOrigin = origin ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Initialize all channels to silence
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < channels . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
channels [ i ] - > volumeDB = DB_SILENCE ;
}
2012-11-28 15:47:07 +00:00
if ( s_singleEmitter . GetInteger ( ) > 0 & & s_singleEmitter . GetInteger ( ) ! = index )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( soundWorld - > listener . area = = - 1 )
{
2012-11-26 18:58:24 +00:00
// listener is outside the world
return ;
}
2012-11-28 15:47:07 +00:00
if ( soundSystemLocal . muted | | soundWorld ! = soundSystemLocal . currentSoundWorld )
{
2012-11-26 18:58:24 +00:00
return ;
}
float maxDistance = 0.0f ;
bool maxDistanceValid = false ;
bool useOcclusion = false ;
2012-11-28 15:47:07 +00:00
if ( emitterId ! = soundWorld - > listener . id )
{
for ( int i = 0 ; i < channels . Num ( ) ; i + + )
{
idSoundChannel * chan = channels [ i ] ;
if ( ( chan - > parms . soundShaderFlags & SSF_GLOBAL ) ! = 0 )
{
2012-11-26 18:58:24 +00:00
continue ;
}
useOcclusion = useOcclusion | | ( ( chan - > parms . soundShaderFlags & SSF_NO_OCCLUSION ) = = 0 ) ;
maxDistanceValid = true ;
2012-11-28 15:47:07 +00:00
if ( maxDistance < channels [ i ] - > parms . maxDistance )
{
2012-11-26 18:58:24 +00:00
maxDistance = channels [ i ] - > parms . maxDistance ;
}
}
}
2012-11-28 15:47:07 +00:00
if ( maxDistanceValid & & directDistance > = maxDistance )
{
2012-11-26 18:58:24 +00:00
// too far away to possibly hear it
return ;
}
2012-11-28 15:47:07 +00:00
if ( useOcclusion & & s_useOcclusion . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
// work out virtual origin and distance, which may be from a portal instead of the actual origin
2012-11-28 15:47:07 +00:00
if ( soundWorld - > renderWorld ! = NULL )
{
2012-11-26 18:58:24 +00:00
// we have a valid renderWorld
int soundInArea = soundWorld - > renderWorld - > PointInArea ( origin ) ;
2012-11-28 15:47:07 +00:00
if ( soundInArea = = - 1 )
{
2012-11-26 18:58:24 +00:00
soundInArea = lastValidPortalArea ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
lastValidPortalArea = soundInArea ;
}
2012-11-28 15:47:07 +00:00
if ( soundInArea ! = - 1 & & soundInArea ! = soundWorld - > listener . area )
{
2012-11-26 18:58:24 +00:00
spatializedDistance = maxDistance * METERS_TO_DOOM ;
soundWorld - > ResolveOrigin ( 0 , NULL , soundInArea , 0.0f , origin , this ) ;
spatializedDistance * = DOOM_TO_METERS ;
}
}
}
2012-11-28 15:47:07 +00:00
for ( int j = 0 ; j < channels . Num ( ) ; j + + )
{
2012-11-26 18:58:24 +00:00
channels [ j ] - > UpdateVolume ( currentTime ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundEmitterLocal : : Index
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idSoundEmitterLocal : : Index ( ) const
{
2012-11-26 18:58:24 +00:00
assert ( soundWorld ) ;
assert ( soundWorld - > emitters [ this - > index ] = = this ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return index ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundEmitterLocal : : Free
Doesn ' t free it until the next update .
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundEmitterLocal : : Free ( bool immediate )
{
2012-11-26 18:58:24 +00:00
assert ( soundWorld ) ;
assert ( soundWorld - > emitters [ this - > index ] = = this ) ;
2012-11-28 15:47:07 +00:00
if ( canFree )
{
2012-11-26 18:58:24 +00:00
// Double free
return ;
}
2012-11-28 15:47:07 +00:00
if ( soundWorld & & soundWorld - > writeDemo )
{
2012-11-26 18:58:24 +00:00
soundWorld - > writeDemo - > WriteInt ( DS_SOUND ) ;
soundWorld - > writeDemo - > WriteInt ( SCMD_FREE ) ;
soundWorld - > writeDemo - > WriteInt ( index ) ;
soundWorld - > writeDemo - > WriteInt ( immediate ) ;
}
2012-11-28 15:47:07 +00:00
if ( immediate )
{
2012-11-26 18:58:24 +00:00
Reset ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
canFree = true ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundEmitterLocal : : UpdateEmitter
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundEmitterLocal : : UpdateEmitter ( const idVec3 & origin , int listenerId , const soundShaderParms_t * parms )
{
2012-11-26 18:58:24 +00:00
assert ( soundWorld ! = NULL ) ;
assert ( soundWorld - > emitters [ this - > index ] = = this ) ;
2012-11-28 15:47:07 +00:00
if ( soundWorld & & soundWorld - > writeDemo )
{
2012-11-26 18:58:24 +00:00
soundWorld - > writeDemo - > WriteInt ( DS_SOUND ) ;
soundWorld - > writeDemo - > WriteInt ( SCMD_UPDATE ) ;
soundWorld - > writeDemo - > WriteInt ( index ) ;
soundWorld - > writeDemo - > WriteVec3 ( origin ) ;
soundWorld - > writeDemo - > WriteInt ( listenerId ) ;
soundWorld - > writeDemo - > WriteFloat ( parms - > minDistance ) ;
soundWorld - > writeDemo - > WriteFloat ( parms - > maxDistance ) ;
soundWorld - > writeDemo - > WriteFloat ( parms - > volume ) ;
soundWorld - > writeDemo - > WriteFloat ( parms - > shakes ) ;
soundWorld - > writeDemo - > WriteInt ( parms - > soundShaderFlags ) ;
soundWorld - > writeDemo - > WriteInt ( parms - > soundClass ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
this - > origin = origin ;
this - > emitterId = listenerId ;
this - > parms = * parms ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundEmitterLocal : : StartSound
in most cases play sounds immediately , however
intercept sounds using SSF_FINITE_SPEED_OF_SOUND
and schedule them for playback later
return : int - the length of the started sound in msec .
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idSoundEmitterLocal : : StartSound ( const idSoundShader * shader , const s_channelType channel , float diversity , int shaderFlags , bool allowSlow )
{
2012-11-26 18:58:24 +00:00
assert ( soundWorld ! = NULL ) ;
assert ( soundWorld - > emitters [ this - > index ] = = this ) ;
2012-11-28 15:47:07 +00:00
if ( shader = = NULL )
{
2012-11-26 18:58:24 +00:00
return 0 ;
}
2012-11-28 15:47:07 +00:00
if ( soundWorld & & soundWorld - > writeDemo )
{
2012-11-26 18:58:24 +00:00
soundWorld - > writeDemo - > WriteInt ( DS_SOUND ) ;
soundWorld - > writeDemo - > WriteInt ( SCMD_START ) ;
soundWorld - > writeDemo - > WriteInt ( index ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
soundWorld - > writeDemo - > WriteHashString ( shader - > GetName ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
soundWorld - > writeDemo - > WriteInt ( channel ) ;
soundWorld - > writeDemo - > WriteFloat ( diversity ) ;
soundWorld - > writeDemo - > WriteInt ( shaderFlags ) ;
}
2012-11-28 15:47:07 +00:00
if ( s_noSound . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
return 0 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int currentTime = soundWorld - > GetSoundTime ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool showStartSound = s_showStartSound . GetBool ( ) ;
2012-11-28 15:47:07 +00:00
if ( showStartSound )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " %dms: StartSound(%d:%d): %s: " , currentTime , index , channel , shader - > GetName ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// build the channel parameters by taking the shader parms and optionally overriding
soundShaderParms_t chanParms ;
chanParms = shader - > parms ;
OverrideParms ( & chanParms , & parms , & chanParms ) ;
chanParms . soundShaderFlags | = shaderFlags ;
2012-11-28 15:47:07 +00:00
if ( shader - > entries . Num ( ) = = 0 )
{
if ( showStartSound )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( S_COLOR_RED " No Entries \n " ) ;
}
return 0 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// PLAY_ONCE sounds will never be restarted while they are running
2012-11-28 15:47:07 +00:00
if ( chanParms . soundShaderFlags & SSF_PLAY_ONCE )
{
for ( int i = 0 ; i < channels . Num ( ) ; i + + )
{
idSoundChannel * chan = channels [ i ] ;
if ( chan - > soundShader = = shader & & ! chan - > CheckForCompletion ( currentTime ) )
{
if ( showStartSound )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( S_COLOR_YELLOW " Not started because of playOnce \n " ) ;
}
return 0 ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// never play the same sound twice with the same starting time, even
// if they are on different channels
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < channels . Num ( ) ; i + + )
{
idSoundChannel * chan = channels [ i ] ;
if ( chan - > soundShader = = shader & & chan - > startTime = = currentTime & & chan - > endTime ! = 1 )
{
if ( showStartSound )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( S_COLOR_RED " Already started this frame \n " ) ;
}
return 0 ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// kill any sound that is currently playing on this channel
2012-11-28 15:47:07 +00:00
if ( channel ! = SCHANNEL_ANY )
{
for ( int i = 0 ; i < channels . Num ( ) ; i + + )
{
idSoundChannel * chan = channels [ i ] ;
if ( chan - > soundShader & & chan - > logicalChannel = = channel )
{
if ( showStartSound )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( S_COLOR_YELLOW " OVERRIDE %s: " , chan - > soundShader - > GetName ( ) ) ;
}
channels . RemoveIndex ( i ) ;
soundWorld - > FreeSoundChannel ( chan ) ;
break ;
}
}
}
2012-11-28 15:47:07 +00:00
idSoundSample * leadinSample = NULL ;
idSoundSample * loopingSample = NULL ;
if ( shader - > leadin & & ( chanParms . soundShaderFlags & SSF_LOOPING ) )
{
2012-11-26 18:58:24 +00:00
leadinSample = shader - > entries [ 0 ] ;
loopingSample = shader - > entries . Num ( ) > 1 ? shader - > entries [ 1 ] : NULL ;
2012-11-28 15:47:07 +00:00
}
else
{
if ( shader - > entries . Num ( ) = = 1 )
{
2012-11-26 18:58:24 +00:00
leadinSample = shader - > entries [ 0 ] ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
int choice ;
2012-11-28 15:47:07 +00:00
if ( chanParms . soundShaderFlags & SSF_NO_DUPS )
{
2012-11-26 18:58:24 +00:00
// Don't select the most recently played entry
int mostRecentTime = 0 ;
int mostRecent = 0 ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < shader - > entries . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
int entryTime = shader - > entries [ i ] - > GetLastPlayedTime ( ) ;
2012-11-28 15:47:07 +00:00
if ( entryTime > mostRecentTime )
{
2012-11-26 18:58:24 +00:00
mostRecentTime = entryTime ;
mostRecent = i ;
}
}
2012-11-28 15:47:07 +00:00
choice = ( int ) ( diversity * ( shader - > entries . Num ( ) - 1 ) ) ;
if ( choice > = mostRecent )
{
2012-11-26 18:58:24 +00:00
choice + + ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// pick a sound from the list based on the passed diversity
2012-11-28 15:47:07 +00:00
choice = ( int ) ( diversity * shader - > entries . Num ( ) ) ;
2012-11-26 18:58:24 +00:00
}
choice = idMath : : ClampInt ( 0 , shader - > entries . Num ( ) - 1 , choice ) ;
leadinSample = shader - > entries [ choice ] ;
leadinSample - > SetLastPlayedTime ( soundWorld - > GetSoundTime ( ) ) ;
}
2012-11-28 15:47:07 +00:00
if ( chanParms . soundShaderFlags & SSF_LOOPING )
{
2012-11-26 18:58:24 +00:00
loopingSample = leadinSample ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set all the channel parameters here,
// a hardware voice will be allocated next update if the volume is high enough to be audible
2012-11-28 15:47:07 +00:00
if ( channels . Num ( ) = = channels . Max ( ) )
{
2012-11-26 18:58:24 +00:00
CheckForCompletion ( currentTime ) ; // as a last chance try to release finished sounds here
2012-11-28 15:47:07 +00:00
if ( channels . Num ( ) = = channels . Max ( ) )
{
if ( showStartSound )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( S_COLOR_RED " No free emitter channels! \n " ) ;
}
2012-11-28 15:47:07 +00:00
return 0 ;
2012-11-26 18:58:24 +00:00
}
}
2012-11-28 15:47:07 +00:00
idSoundChannel * chan = soundWorld - > AllocSoundChannel ( ) ;
if ( chan = = NULL )
{
if ( showStartSound )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( S_COLOR_RED " No free global channels! \n " ) ;
}
return 0 ;
}
channels . Append ( chan ) ;
chan - > emitter = this ;
chan - > parms = chanParms ;
chan - > soundShader = shader ;
chan - > logicalChannel = channel ;
chan - > leadinSample = leadinSample ;
chan - > loopingSample = loopingSample ;
chan - > allowSlow = allowSlow ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// return length of sound in milliseconds
int length = chan - > leadinSample - > LengthInMsec ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// adjust the start time based on diversity for looping sounds, so they don't all start at the same point
int startOffset = 0 ;
2012-11-28 15:47:07 +00:00
if ( chan - > IsLooping ( ) & & ! shader - > leadin )
{
2012-11-26 18:58:24 +00:00
// looping sounds start at a random point...
startOffset = soundSystemLocal . random . RandomInt ( length ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
chan - > startTime = currentTime - startOffset ;
2012-11-28 15:47:07 +00:00
if ( ( chanParms . soundShaderFlags & SSF_LOOPING ) ! = 0 )
{
2012-11-26 18:58:24 +00:00
// This channel will never end!
chan - > endTime = 0 ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// This channel will automatically end at this time
chan - > endTime = chan - > startTime + length + 100 ;
}
2012-11-28 15:47:07 +00:00
if ( showStartSound )
{
if ( loopingSample = = NULL | | leadinSample = = loopingSample )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " Playing %s @ %d \n " , leadinSample - > GetName ( ) , startOffset ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " Playing %s then looping %s \n " , leadinSample - > GetName ( ) , loopingSample - > GetName ( ) ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return length ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundEmitterLocal : : OnReloadSound
This is a shortened version of StartSound , called whenever a sound shader is reloaded .
If the emitter is currently playing the given sound shader , restart it so
a change in the sound sample used for a given sound shader will be picked up .
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundEmitterLocal : : OnReloadSound ( const idDecl * decl )
{
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundEmitterLocal : : StopSound
Can pass SCHANNEL_ANY .
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundEmitterLocal : : StopSound ( const s_channelType channel )
{
2012-11-26 18:58:24 +00:00
assert ( soundWorld ! = NULL ) ;
assert ( soundWorld - > emitters [ this - > index ] = = this ) ;
2012-11-28 15:47:07 +00:00
if ( soundWorld & & soundWorld - > writeDemo )
{
2012-11-26 18:58:24 +00:00
soundWorld - > writeDemo - > WriteInt ( DS_SOUND ) ;
soundWorld - > writeDemo - > WriteInt ( SCMD_STOP ) ;
soundWorld - > writeDemo - > WriteInt ( index ) ;
soundWorld - > writeDemo - > WriteInt ( channel ) ;
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < channels . Num ( ) ; i + + )
{
idSoundChannel * chan = channels [ i ] ;
if ( channel ! = SCHANNEL_ANY & & chan - > logicalChannel ! = channel )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( s_showStartSound . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " %dms: StopSound(%d:%d): %s \n " , soundWorld - > GetSoundTime ( ) , index , channel , chan - > soundShader - > GetName ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// This forces CheckForCompletion to return true
chan - > endTime = 1 ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundEmitterLocal : : ModifySound
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundEmitterLocal : : ModifySound ( const s_channelType channel , const soundShaderParms_t * parms )
{
2012-11-26 18:58:24 +00:00
assert ( soundWorld ! = NULL ) ;
assert ( soundWorld - > emitters [ this - > index ] = = this ) ;
2012-11-28 15:47:07 +00:00
if ( soundWorld & & soundWorld - > writeDemo )
{
2012-11-26 18:58:24 +00:00
soundWorld - > writeDemo - > WriteInt ( DS_SOUND ) ;
soundWorld - > writeDemo - > WriteInt ( SCMD_MODIFY ) ;
soundWorld - > writeDemo - > WriteInt ( index ) ;
soundWorld - > writeDemo - > WriteInt ( channel ) ;
soundWorld - > writeDemo - > WriteFloat ( parms - > minDistance ) ;
soundWorld - > writeDemo - > WriteFloat ( parms - > maxDistance ) ;
soundWorld - > writeDemo - > WriteFloat ( parms - > volume ) ;
soundWorld - > writeDemo - > WriteFloat ( parms - > shakes ) ;
soundWorld - > writeDemo - > WriteInt ( parms - > soundShaderFlags ) ;
soundWorld - > writeDemo - > WriteInt ( parms - > soundClass ) ;
}
2012-11-28 15:47:07 +00:00
for ( int i = channels . Num ( ) - 1 ; i > = 0 ; i - - )
{
idSoundChannel * chan = channels [ i ] ;
if ( channel ! = SCHANNEL_ANY & & chan - > logicalChannel ! = channel )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( s_showStartSound . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " %dms: ModifySound(%d:%d): %s \n " , soundWorld - > GetSoundTime ( ) , index , channel , chan - > soundShader - > GetName ( ) ) ;
}
OverrideParms ( & chan - > parms , parms , & chan - > parms ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundEmitterLocal : : FadeSound
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundEmitterLocal : : FadeSound ( const s_channelType channel , float to , float over )
{
2012-11-26 18:58:24 +00:00
assert ( soundWorld ! = NULL ) ;
assert ( soundWorld - > emitters [ this - > index ] = = this ) ;
2012-11-28 15:47:07 +00:00
if ( soundWorld - > writeDemo )
{
2012-11-26 18:58:24 +00:00
soundWorld - > writeDemo - > WriteInt ( DS_SOUND ) ;
soundWorld - > writeDemo - > WriteInt ( SCMD_FADE ) ;
soundWorld - > writeDemo - > WriteInt ( index ) ;
soundWorld - > writeDemo - > WriteInt ( channel ) ;
soundWorld - > writeDemo - > WriteFloat ( to ) ;
soundWorld - > writeDemo - > WriteFloat ( over ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int overMSec = SEC2MS ( over ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < channels . Num ( ) ; i + + )
{
idSoundChannel * chan = channels [ i ] ;
if ( channel ! = SCHANNEL_ANY & & chan - > logicalChannel ! = channel )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( s_showStartSound . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " %dms: FadeSound(%d:%d): %s to %.2fdb over %.2f seconds \n " , soundWorld - > GetSoundTime ( ) , index , channel , chan - > soundShader - > GetName ( ) , to , over ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// fade it
chan - > volumeFade . Fade ( to - chan - > parms . volume , overMSec , soundWorld - > GetSoundTime ( ) ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundEmitterLocal : : CurrentlyPlaying
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSoundEmitterLocal : : CurrentlyPlaying ( const s_channelType channel ) const
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( channel = = SCHANNEL_ANY )
{
2012-11-26 18:58:24 +00:00
return ( channels . Num ( ) > 0 ) ;
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < channels . Num ( ) ; + + i )
{
if ( channels [ i ] ! = NULL & & channels [ i ] - > logicalChannel = = channel )
{
if ( channels [ i ] - > endTime = = 1 )
{
2012-11-26 18:58:24 +00:00
return false ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return true ;
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundEmitterLocal : : CurrentAmplitude
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
float idSoundEmitterLocal : : CurrentAmplitude ( )
{
2012-11-26 18:58:24 +00:00
float amplitude = 0.0f ;
int currentTime = soundWorld - > GetSoundTime ( ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < channels . Num ( ) ; i + + )
{
idSoundChannel * chan = channels [ i ] ;
if ( chan = = NULL | | currentTime < chan - > startTime | | ( chan - > endTime > 0 & & currentTime > = chan - > endTime ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
int relativeTime = currentTime - chan - > startTime ;
int leadinLength = chan - > leadinSample - > LengthInMsec ( ) ;
2012-11-28 15:47:07 +00:00
if ( relativeTime < leadinLength )
{
2012-11-26 18:58:24 +00:00
amplitude = Max ( amplitude , chan - > leadinSample - > GetAmplitude ( relativeTime ) ) ;
2012-11-28 15:47:07 +00:00
}
else if ( chan - > loopingSample ! = NULL )
{
2012-11-26 18:58:24 +00:00
amplitude = Max ( amplitude , chan - > loopingSample - > GetAmplitude ( ( relativeTime - leadinLength ) % chan - > loopingSample - > LengthInMsec ( ) ) ) ;
}
}
return amplitude ;
}