From 22177753d2f00d58d19d930f51dcd086097dfd0d Mon Sep 17 00:00:00 2001
From: James R <justsomejames2@gmail.com>
Date: Tue, 8 Sep 2020 22:40:42 -0700
Subject: [PATCH] Apply volume to sounds with origin too

Previously sounds with an origin would always start at max volume. This is
because the distance calculation adjusts the volume, and that volume needs to
be updated every tic as distance changes. Storing the original volume works.
---
 src/s_sound.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/src/s_sound.c b/src/s_sound.c
index 2c96d389d..225863211 100644
--- a/src/s_sound.c
+++ b/src/s_sound.c
@@ -162,6 +162,9 @@ typedef struct
 	// origin of sound
 	const void *origin;
 
+	// initial volume of sound, which is applied after distance and direction
+	INT32 volume;
+
 	// handle of the sound being played
 	INT32 handle;
 
@@ -432,6 +435,7 @@ void S_StopSoundByNum(sfxenum_t sfxnum)
 
 void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
 {
+	const INT32 initial_volume = volume;
 	INT32 sep, pitch, priority, cnum;
 	sfxinfo_t *sfx;
 	const boolean reverse = (stereoreverse.value ^ encoremode);
@@ -789,6 +793,7 @@ dontplay4:
 
 	// Assigns the handle to one of the channels in the
 	// mix/output buffer.
+	channels[cnum].volume = initial_volume;
 	channels[cnum].handle = I_StartSound(sfx_id, volume, sep, pitch, priority, cnum);
 }
 
@@ -1054,7 +1059,7 @@ void S_UpdateSounds(void)
 			if (I_SoundIsPlaying(c->handle))
 			{
 				// initialize parameters
-				volume = 255; // 8 bits internal volume precision
+				volume = c->volume; // 8 bits internal volume precision
 				pitch = NORM_PITCH;
 				sep = NORM_SEP;
 
@@ -1361,15 +1366,12 @@ INT32 S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 *v
 	}
 
 	// volume calculation
-	if (approx_dist < S_CLOSE_DIST)
-	{
-		// SfxVolume is now hardware volume
-		*vol = 255; // not snd_SfxVolume
-	}
-	else
+	/* not sure if it should be > (no =), but this matches the old behavior */
+	if (approx_dist >= S_CLOSE_DIST)
 	{
 		// distance effect
-		*vol = (15 * ((S_CLIPPING_DIST - approx_dist)>>FRACBITS)) / S_ATTENUATOR;
+		INT32 n = (15 * ((S_CLIPPING_DIST - approx_dist)>>FRACBITS));
+		*vol = FixedMul(*vol * FRACUNIT / 255, n) / S_ATTENUATOR;
 	}
 
 	if (splitscreen)
-- 
GitLab