@ -22,7 +22,6 @@ static float SND_FMOD_Attenuation(FMOD_CHANNELCONTROL *channelControl, float dis
typedef struct entchannel_s
{
sfx_t * sfx ;
int entnum ;
int entchannel ;
float dist_mult ;
@ -134,6 +133,12 @@ static float SND_FMOD_Attenuation(FMOD_CHANNELCONTROL *channelcontrol, float dis
return 1.0f ;
}
/ / Anything coming from the view entity will always be full volume
if ( userdata - > entnum = = cl . viewentity )
{
return 1.0f ;
}
scale = 1.0f - ( distance * userdata - > dist_mult ) ;
if ( scale < 0.0f )
scale = 0.0f ;
@ -190,7 +195,7 @@ static float SND_FMOD_Attenuation(FMOD_CHANNELCONTROL *channelcontrol, float dis
/ / return channel ;
/ / }
void S_StartSound ( int entnum , int entchannel , sfx_t * sfx , vec3_t origin , float fvol , float attenuation )
void S_StartSound ( int entnum , int entchannel , sfx_t * sfx , vec3_t origin , float fvol , float attenuation ) / / Note : volume and attenuation are properly normalized here
{
FMOD_CHANNEL * channel ;
FMOD_VECTOR position ;
@ -200,7 +205,7 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f
return ;
/ / TODO : check nosound cvar
return ; / / HACK play no entity sfx for now
/ / return ; / / HACK play no entity sfx for now
S_LoadSound ( sfx ) ;
if ( ! sfx - > sound )
@ -208,12 +213,13 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f
/ / Find channel group for entity number ( or create ) = > note entnum can also be some random hash value
/ / ChannelControl : : setMode = > set to 3 D
/ / Can use channel group per entity to store entity - specific userdata , with maybe 16 fixed channel slots
/ / Pre - define channels for each entity ( could be an array of ints , probably array of entchannel_t structs )
/ / For entchannel 0 , dynamically select a free channel ( or just play without doing anything , let FMOD handle it )
/ / If channel at index entchannel > 0 is already playing : stop
/ / Set userdata pointer to entchannel_t so we can check if the FMOD channel still belongs to this entity & entchannel , before checking if it ' s already playing
/ / Special case entchannel - 1 = > just play locally on listener , no 3 D
/ / Special case entchannel - 1 = > just play locally on listener , no 3 D ( also override any sound already playing on entity )
/ / System : : playSound with paused = true
result = FMOD_System_PlaySound ( fmod_system , sfx - > sound , sfx_channelGroup , 1 , & channel ) ;
@ -229,7 +235,14 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f
FMOD_Channel_SetMode ( channel , FMOD_LOOP_OFF ) ; / / TODO : some entity sounds do need to loop , e . g . moving elevators . How is this done ?
FMOD_Channel_SetVolume ( channel , fvol ) ;
FMOD_Channel_Set3DLevel ( channel , entchannel < 0 ? 0.0f : 1.0f ) ; / / entchannel - 1 is used for local sounds
/ / TODO : attenuation
/ / TODO : attenuation ( this is just a quick hack to test )
entchannel_t * userdata = ( entchannel_t * ) malloc ( sizeof ( entchannel_t ) ) ; / / TODO : we REALLY need to allocate this properly , this is now a memory leak ! !
userdata - > entnum = entnum ;
userdata - > entchannel = entchannel ;
userdata - > channel = channel ;
userdata - > dist_mult = attenuation / sound_nominal_clip_dist ;
FMOD_Channel_SetUserData ( channel , userdata ) ;
/ / TODO : use ChannelControl Callback to detect when the sound ends , then clear it from the entchannel_t list
@ -249,9 +262,6 @@ void S_StaticSound(sfx_t *sfx, vec3_t origin, float vol, float attenuation) // N
FMOD_RESULT result ;
unsigned long long dspclock ;
/ / Similar to above , but without the per - entity channel group song and dance
/ / Check if sound is looped ( should be ) and FMOD_Channel_SetMode to looped
/ / Set Channel : : setLoopPoints if the sfxcache specifies something non - standard
if ( ! fmod_system | | ! sfx )
return ;
@ -271,14 +281,15 @@ void S_StaticSound(sfx_t *sfx, vec3_t origin, float vol, float attenuation) // N
FMOD_Channel_SetMode ( channel , FMOD_LOOP_NORMAL ) ;
FMOD_Channel_SetVolume ( channel , vol / 255 ) ;
/ / TODO : attenuation ( which is pre - multiplied by 64 )
/ / Set up attenuation info for use by the rolloff callback
entchannel_t * userdata = ( entchannel_t * ) malloc ( sizeof ( entchannel_t ) ) ; / / This is rather convenient . Can we use Z_Malloc here perhaps ?
userdata - > sfx = sfx ;
userdata - > entnum = - 1 ;
userdata - > channel = channel ;
userdata - > dist_mult = ( attenuation / 64 ) / sound_nominal_clip_dist ;
FMOD_Channel_SetUserData ( channel , userdata ) ;
/ / Add a random delay so that similar sounds don ' t phase together ( note : this isn ' t really authentic to original Quake , but it improves the sense of directionality )
/ / Add a random delay so that similar sounds don ' t phase together
/ / Note : this isn ' t really authentic to the original Quake sound system , but it does improve the sense of directionality
FMOD_ChannelGroup_GetDSPClock ( sfx_channelGroup , & dspclock , NULL ) ;
FMOD_Channel_SetDelay ( channel , dspclock + SND_GetDelay ( sfx ) , 0 , 0 ) ;
@ -302,7 +313,7 @@ void S_StopAllSounds(qboolean clear)
void S_ClearBuffer ( void )
{
/ / TODO Use this to remove per - entity channel group and clear all userdata ?
}
void S_Update ( vec3_t origin , vec3_t forward , vec3_t right , vec3_t up )