Browse Source

Implemented ambient sounds, did some refactoring and added explanations about the different types of sounds

console
Nico de Poel 5 years ago
parent
commit
9806b057c7
  1. 165
      engine/Quake/snd_fmod.c

165
engine/Quake/snd_fmod.c

@ -15,8 +15,11 @@ static float old_volume = -1.0f;
static FMOD_CHANNELGROUP *sfx_channelGroup = NULL;
vec3_t listener_origin;
static const char *FMOD_SpeakerModeString(FMOD_SPEAKERMODE speakermode);
static float SND_FMOD_Attenuation(FMOD_CHANNELCONTROL *channelControl, float distance);
static void SND_StartAmbientSounds();
// Copy and convert coordinate system
#define FMOD_VectorCopy(a, b) {(b).x=(a)[0];(b).y=(a)[2];(b).z=(a)[1];}
@ -35,6 +38,7 @@ typedef struct entsounds_s
} entsounds_t;
static entsounds_t entsounds[MAX_CHANNELS];
static FMOD_CHANNEL *ambients[NUM_AMBIENTS];
// Keep track of all the sounds started each frame
static sfx_t *sfxThisFrame[16];
@ -130,7 +134,7 @@ void S_Shutdown(void)
Con_DPrintf("[FMOD] Shutdown\n");
S_StopAllSounds(true);
S_StopAllSounds(false);
// Release all sounds that were loaded and attached to sfx_t's
for (i = 0; i < num_sfx; i++)
@ -228,6 +232,26 @@ static FMOD_RESULT SND_FMOD_Callback(FMOD_CHANNELCONTROL *channelcontrol, FMOD_C
return FMOD_OK;
}
static void SND_FMOD_SetChannelAttributes(FMOD_CHANNEL *channel, sfx_t *sfx, vec3_t origin, float vol)
{
FMOD_VECTOR position;
FMOD_VectorCopy(origin, position);
FMOD_Channel_Set3DAttributes(channel, &position, NULL);
FMOD_Channel_SetVolume(channel, vol);
FMOD_Channel_SetVolumeRamp(channel, 1); // This *might* help somewhat with slight audio pops (esp. noticable on the Nailgun)
if (sfx->loopstart >= 0)
{
FMOD_Channel_SetMode(channel, FMOD_LOOP_NORMAL);
FMOD_Channel_SetLoopPoints(channel, sfx->loopstart, FMOD_TIMEUNIT_MS, sfx->loopend, FMOD_TIMEUNIT_MS);
}
else
{
FMOD_Channel_SetMode(channel, FMOD_LOOP_OFF);
}
}
static soundslot_t *SND_PickSoundSlot(int entnum, int entchannel)
{
soundslot_t *slot;
@ -255,11 +279,107 @@ static soundslot_t *SND_PickSoundSlot(int entnum, int entchannel)
return slot;
}
/*
==============
Ambient sounds
These are sounds that are always present and always playing. They are unaffected by distance or orientation.
Instead they are modulated in volume based on whether the player is inside a world volume that has ambient sound levels set.
==============
*/
static FMOD_CHANNEL *SND_StartAmbientSound(const char *samplename)
{
sfx_t *sfx;
FMOD_CHANNEL *channel;
FMOD_RESULT result;
sfx = S_PrecacheSound(samplename);
if (!sfx)
return NULL;
S_LoadSound(sfx);
if (!sfx->sound)
return NULL;
result = FMOD_System_PlaySound(fmod_system, sfx->sound, sfx_channelGroup, 1, &channel);
if (result != FMOD_OK)
{
Con_Printf("Failed to play ambient FMOD sound: %s\n", FMOD_ErrorString(result));
return NULL;
}
SND_FMOD_SetChannelAttributes(channel, sfx, vec3_origin, 0.0f);
FMOD_Channel_Set3DLevel(channel, 0.0f);
FMOD_Channel_SetPaused(channel, 0);
return channel;
}
static void SND_StartAmbientSounds()
{
memset(ambients, 0, sizeof(ambients));
ambients[AMBIENT_WATER] = SND_StartAmbientSound("ambience/water1.wav");
ambients[AMBIENT_SKY] = SND_StartAmbientSound("ambience/wind2.wav");
}
static void S_UpdateAmbientSounds()
{
FMOD_CHANNEL *channel;
mleaf_t *leaf;
float vol, channel_vol;
if (cl.worldmodel && cl.worldmodel->nodes)
leaf = Mod_PointInLeaf(listener_origin, cl.worldmodel);
else
leaf = NULL;
for (int i = 0; i < NUM_AMBIENTS; i++)
{
channel = ambients[i];
if (!channel)
continue;
if (!leaf || !ambient_level.value)
{
FMOD_Channel_SetVolume(channel, 0.0f);
continue;
}
vol = (ambient_level.value * (float)leaf->ambient_sound_level[i]) / 255;
if (vol < 0.03f)
vol = 0.0f;
// don't adjust volume too fast
FMOD_Channel_GetVolume(channel, &channel_vol);
if (channel_vol < vol)
{
channel_vol += host_frametime * (ambient_fade.value / 255);
if (channel_vol > vol)
channel_vol = vol;
}
else if (channel_vol > vol)
{
channel_vol -= host_frametime * (ambient_fade.value / 255);
if (channel_vol < vol)
channel_vol = vol;
}
FMOD_Channel_SetVolume(channel, channel_vol);
}
}
/*
=============
Entity sounds
These are your typical 3D sounds generated by entities in the world, including the player.
Each entity has a number of preset voice channels, each of which can only play one sound at a time.
=============
*/
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
{
int i;
FMOD_CHANNEL *channel;
FMOD_VECTOR position;
FMOD_RESULT result;
soundslot_t *userdata;
unsigned long long dspclock;
@ -285,26 +405,14 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f
return;
}
SND_FMOD_SetChannelAttributes(channel, sfx, origin, fvol);
// Set up callback data for rolloff and cleanup
userdata->channel = channel;
userdata->dist_mult = attenuation / sound_nominal_clip_dist;
FMOD_Channel_SetUserData(channel, userdata);
FMOD_Channel_SetCallback(channel, &SND_FMOD_Callback);
FMOD_VectorCopy(origin, position);
FMOD_Channel_Set3DAttributes(channel, &position, NULL);
FMOD_Channel_SetVolume(channel, fvol);
if (sfx->loopstart >= 0)
{
FMOD_Channel_SetMode(channel, FMOD_LOOP_NORMAL);
FMOD_Channel_SetLoopPoints(channel, sfx->loopstart, FMOD_TIMEUNIT_MS, sfx->loopend, FMOD_TIMEUNIT_MS);
}
else
{
FMOD_Channel_SetMode(channel, FMOD_LOOP_OFF);
}
// Anything coming from the view entity will always be full volume, and entchannel -1 is used for local sounds (e.g. menu sounds)
if (entchannel < 0 || entnum == cl.viewentity)
{
@ -330,12 +438,17 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f
FMOD_Channel_SetPaused(channel, 0);
}
// TODO: we're still missing Automatic Ambient sounds for water, lava, slime etc (see S_UpdateAmbientSounds)
/*
=============
Static sounds
These are sounds that have a fixed position in the world and loop continuously.
They typically start playing immediately on level load.
=============
*/
void S_StaticSound(sfx_t *sfx, vec3_t origin, float vol, float attenuation) // Note: volume and attenuation are in 0-255 range here
{
FMOD_CHANNEL *channel;
FMOD_VECTOR position;
FMOD_RESULT result;
soundslot_t *userdata;
unsigned long long dspclock;
@ -354,11 +467,8 @@ void S_StaticSound(sfx_t *sfx, vec3_t origin, float vol, float attenuation) // N
return;
}
FMOD_VectorCopy(origin, position);
FMOD_Channel_Set3DAttributes(channel, &position, NULL);
FMOD_Channel_SetMode(channel, FMOD_LOOP_NORMAL);
FMOD_Channel_SetVolume(channel, vol / 255);
SND_FMOD_SetChannelAttributes(channel, sfx, origin, vol / 255);
// Set up attenuation info for use by the rolloff callback
userdata = SND_PickSoundSlot(-1, -1);
userdata->channel = channel;
@ -402,7 +512,12 @@ void S_StopAllSounds(qboolean clear)
FMOD_ChannelGroup_Stop(sfx_channelGroup);
if (clear)
{
S_ClearBuffer();
// Ambient sounds need to be restarted, as they are always "playing"
SND_StartAmbientSounds();
}
}
void S_ClearBuffer(void)
@ -426,6 +541,8 @@ void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
old_volume = sfxvolume.value;
}
VectorCopy(origin, listener_origin);
FMOD_VECTOR fmod_pos, fmod_forward, fmod_up;
FMOD_VectorCopy(origin, fmod_pos);
FMOD_VectorCopy(forward, fmod_forward);
@ -436,6 +553,8 @@ void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
FMOD_ChannelGroup_SetVolume(sfx_channelGroup, sfxvolume.value);
S_UpdateAmbientSounds();
FMOD_System_Update(fmod_system);
// Reset sounds played for the next frame

Loading…
Cancel
Save