From da35f0db477e92d8747e51b357683cd0b6aa49b5 Mon Sep 17 00:00:00 2001 From: Slick Daddy <129640104+slick-daddy@users.noreply.github.com> Date: Tue, 21 Jul 2026 12:58:35 +0300 Subject: [PATCH] [Audio] Hoist volume clamp out of the per-sample PCM loop (#487) Co-authored-by: slick-daddy --- src/SharpEmu.Libs/Audio/AudioPcmConversion.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/SharpEmu.Libs/Audio/AudioPcmConversion.cs b/src/SharpEmu.Libs/Audio/AudioPcmConversion.cs index b8e2c110..6294402f 100644 --- a/src/SharpEmu.Libs/Audio/AudioPcmConversion.cs +++ b/src/SharpEmu.Libs/Audio/AudioPcmConversion.cs @@ -25,6 +25,10 @@ internal static class AudioPcmConversion float volume) { var sourceFrameSize = checked(channels * bytesPerSample); + // Volume is constant for the whole submission, so clamp it once here + // rather than per sample inside the loop (this runs on every real-time + // audio buffer, hundreds of frames at a time). + var clampedVolume = Math.Clamp(volume, 0.0f, 1.0f); for (var frame = 0; frame < frames; frame++) { var sourceFrame = source.Slice(frame * sourceFrameSize, sourceFrameSize); @@ -32,8 +36,8 @@ internal static class AudioPcmConversion var right = channels == 1 ? left : ReadSample(sourceFrame, 1, bytesPerSample, isFloat); - left = ApplyVolume(left, volume); - right = ApplyVolume(right, volume); + left = ApplyVolume(left, clampedVolume); + right = ApplyVolume(right, clampedVolume); BinaryPrimitives.WriteInt16LittleEndian(destination[(frame * OutputFrameSize)..], left); BinaryPrimitives.WriteInt16LittleEndian(destination[((frame * OutputFrameSize) + 2)..], right); } @@ -67,9 +71,10 @@ internal static class AudioPcmConversion return checked((short)MathF.Round(value * scale)); } + // is expected pre-clamped to [0, 1] by the caller. private static short ApplyVolume(short sample, float volume) { - var scaled = MathF.Round(sample * Math.Clamp(volume, 0.0f, 1.0f)); + var scaled = MathF.Round(sample * volume); return (short)Math.Clamp(scaled, short.MinValue, short.MaxValue); } }