From f9f9447013af71920a1826901f50e7d09505d8a7 Mon Sep 17 00:00:00 2001
From: Stenzek <stenzek@gmail.com>
Date: Fri, 29 Mar 2024 15:08:12 +1000
Subject: [PATCH] SPU: Ignore End+Mute flag for noise channels

Fixes the noise effects cutting out too early in Motor Toon Grand Prix.
---
 src/core/spu.cpp | 154 +++++++++++++++++++++++++----------------------
 1 file changed, 81 insertions(+), 73 deletions(-)

diff --git a/src/core/spu.cpp b/src/core/spu.cpp
index 51dab9cd6..b44c9c9e5 100644
--- a/src/core/spu.cpp
+++ b/src/core/spu.cpp
@@ -430,10 +430,10 @@ void SPU::Initialize()
 
 void SPU::CreateOutputStream()
 {
-  Log_InfoPrintf(
-    "Creating '%s' audio stream, sample rate = %u, channels = %u, buffer = %u, latency = %u, stretching = %s",
-    Settings::GetAudioBackendName(g_settings.audio_backend), SAMPLE_RATE, NUM_CHANNELS, g_settings.audio_buffer_ms,
-    g_settings.audio_output_latency_ms, AudioStream::GetStretchModeName(g_settings.audio_stretch_mode));
+  Log_InfoFmt("Creating '{}' audio stream, sample rate = {}, channels = {}, buffer = {}, latency = {}, stretching = {}",
+              Settings::GetAudioBackendName(g_settings.audio_backend), static_cast<u32>(SAMPLE_RATE),
+              static_cast<u32>(NUM_CHANNELS), g_settings.audio_buffer_ms, g_settings.audio_output_latency_ms,
+              AudioStream::GetStretchModeName(g_settings.audio_stretch_mode));
 
   s_audio_stream =
     Host::CreateAudioStream(g_settings.audio_backend, SAMPLE_RATE, NUM_CHANNELS, g_settings.audio_buffer_ms,
@@ -656,28 +656,28 @@ u16 SPU::ReadRegister(u32 offset)
       return s_reverb_registers.mBASE;
 
     case 0x1F801DA4 - SPU_BASE:
-      Log_TracePrintf("SPU IRQ address -> 0x%04X", ZeroExtend32(s_irq_address));
+      Log_TraceFmt("SPU IRQ address -> 0x{:04X}", s_irq_address);
       return s_irq_address;
 
     case 0x1F801DA6 - SPU_BASE:
-      Log_TracePrintf("SPU transfer address register -> 0x%04X", ZeroExtend32(s_transfer_address_reg));
+      Log_TraceFmt("SPU transfer address register -> 0x{:04X}", s_transfer_address_reg);
       return s_transfer_address_reg;
 
     case 0x1F801DA8 - SPU_BASE:
-      Log_TracePrintf("SPU transfer data register read");
+      Log_TraceFmt("SPU transfer data register read");
       return UINT16_C(0xFFFF);
 
     case 0x1F801DAA - SPU_BASE:
-      Log_TracePrintf("SPU control register -> 0x%04X", ZeroExtend32(s_SPUCNT.bits));
+      Log_TraceFmt("SPU control register -> 0x{:04X}", s_SPUCNT.bits);
       return s_SPUCNT.bits;
 
     case 0x1F801DAC - SPU_BASE:
-      Log_TracePrintf("SPU transfer control register -> 0x%04X", ZeroExtend32(s_transfer_control.bits));
+      Log_TraceFmt("SPU transfer control register -> 0x{:04X}", s_transfer_control.bits);
       return s_transfer_control.bits;
 
     case 0x1F801DAE - SPU_BASE:
       GeneratePendingSamples();
-      Log_TracePrintf("SPU status register -> 0x%04X", ZeroExtend32(s_SPUCNT.bits));
+      Log_TraceFmt("SPU status register -> 0x{:04X}", s_SPUCNT.bits);
       return s_SPUSTAT.bits;
 
     case 0x1F801DB0 - SPU_BASE:
@@ -718,7 +718,7 @@ u16 SPU::ReadRegister(u32 offset)
           return s_voices[voice_index].right_volume.current_level;
       }
 
-      Log_DevPrintf("Unknown SPU register read: offset 0x%X (address 0x%08X)", offset, offset | SPU_BASE);
+      Log_DevFmt("Unknown SPU register read: offset 0x{:X} (address 0x{:08X})", offset, offset | SPU_BASE);
       return UINT16_C(0xFFFF);
     }
   }
@@ -730,7 +730,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
   {
     case 0x1F801D80 - SPU_BASE:
     {
-      Log_DebugPrintf("SPU main volume left <- 0x%04X", ZeroExtend32(value));
+      Log_DebugFmt("SPU main volume left <- 0x{:04X}", value);
       GeneratePendingSamples();
       s_main_volume_left_reg.bits = value;
       s_main_volume_left.Reset(s_main_volume_left_reg);
@@ -739,7 +739,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
 
     case 0x1F801D82 - SPU_BASE:
     {
-      Log_DebugPrintf("SPU main volume right <- 0x%04X", ZeroExtend32(value));
+      Log_DebugFmt("SPU main volume right <- 0x{:04X}", value);
       GeneratePendingSamples();
       s_main_volume_right_reg.bits = value;
       s_main_volume_right.Reset(s_main_volume_right_reg);
@@ -748,7 +748,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
 
     case 0x1F801D84 - SPU_BASE:
     {
-      Log_DebugPrintf("SPU reverb output volume left <- 0x%04X", ZeroExtend32(value));
+      Log_DebugFmt("SPU reverb output volume left <- 0x{:04X}", value);
       GeneratePendingSamples();
       s_reverb_registers.vLOUT = value;
       return;
@@ -756,7 +756,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
 
     case 0x1F801D86 - SPU_BASE:
     {
-      Log_DebugPrintf("SPU reverb output volume right <- 0x%04X", ZeroExtend32(value));
+      Log_DebugFmt("SPU reverb output volume right <- 0x{:04X}", value);
       GeneratePendingSamples();
       s_reverb_registers.vROUT = value;
       return;
@@ -764,7 +764,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
 
     case 0x1F801D88 - SPU_BASE:
     {
-      Log_DebugPrintf("SPU key on low <- 0x%04X", ZeroExtend32(value));
+      Log_DebugFmt("SPU key on low <- 0x{:04X}", value);
       GeneratePendingSamples();
       s_key_on_register = (s_key_on_register & 0xFFFF0000) | ZeroExtend32(value);
     }
@@ -772,7 +772,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
 
     case 0x1F801D8A - SPU_BASE:
     {
-      Log_DebugPrintf("SPU key on high <- 0x%04X", ZeroExtend32(value));
+      Log_DebugFmt("SPU key on high <- 0x{:04X}", value);
       GeneratePendingSamples();
       s_key_on_register = (s_key_on_register & 0x0000FFFF) | (ZeroExtend32(value) << 16);
     }
@@ -780,7 +780,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
 
     case 0x1F801D8C - SPU_BASE:
     {
-      Log_DebugPrintf("SPU key off low <- 0x%04X", ZeroExtend32(value));
+      Log_DebugFmt("SPU key off low <- 0x{:04X}", value);
       GeneratePendingSamples();
       s_key_off_register = (s_key_off_register & 0xFFFF0000) | ZeroExtend32(value);
     }
@@ -788,7 +788,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
 
     case 0x1F801D8E - SPU_BASE:
     {
-      Log_DebugPrintf("SPU key off high <- 0x%04X", ZeroExtend32(value));
+      Log_DebugFmt("SPU key off high <- 0x{:04X}", value);
       GeneratePendingSamples();
       s_key_off_register = (s_key_off_register & 0x0000FFFF) | (ZeroExtend32(value) << 16);
     }
@@ -798,7 +798,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
     {
       GeneratePendingSamples();
       s_pitch_modulation_enable_register = (s_pitch_modulation_enable_register & 0xFFFF0000) | ZeroExtend32(value);
-      Log_DebugPrintf("SPU pitch modulation enable register <- 0x%08X", s_pitch_modulation_enable_register);
+      Log_DebugFmt("SPU pitch modulation enable register <- 0x{:08X}", s_pitch_modulation_enable_register);
     }
     break;
 
@@ -807,13 +807,13 @@ void SPU::WriteRegister(u32 offset, u16 value)
       GeneratePendingSamples();
       s_pitch_modulation_enable_register =
         (s_pitch_modulation_enable_register & 0x0000FFFF) | (ZeroExtend32(value) << 16);
-      Log_DebugPrintf("SPU pitch modulation enable register <- 0x%08X", s_pitch_modulation_enable_register);
+      Log_DebugFmt("SPU pitch modulation enable register <- 0x{:08X}", s_pitch_modulation_enable_register);
     }
     break;
 
     case 0x1F801D94 - SPU_BASE:
     {
-      Log_DebugPrintf("SPU noise mode register <- 0x%04X", ZeroExtend32(value));
+      Log_DebugFmt("SPU noise mode register <- 0x{:04X}", value);
       GeneratePendingSamples();
       s_noise_mode_register = (s_noise_mode_register & 0xFFFF0000) | ZeroExtend32(value);
     }
@@ -821,7 +821,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
 
     case 0x1F801D96 - SPU_BASE:
     {
-      Log_DebugPrintf("SPU noise mode register <- 0x%04X", ZeroExtend32(value));
+      Log_DebugFmt("SPU noise mode register <- 0x{:04X}", value);
       GeneratePendingSamples();
       s_noise_mode_register = (s_noise_mode_register & 0x0000FFFF) | (ZeroExtend32(value) << 16);
     }
@@ -829,7 +829,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
 
     case 0x1F801D98 - SPU_BASE:
     {
-      Log_DebugPrintf("SPU reverb on register <- 0x%04X", ZeroExtend32(value));
+      Log_DebugFmt("SPU reverb on register <- 0x{:04X}", value);
       GeneratePendingSamples();
       s_reverb_on_register = (s_reverb_on_register & 0xFFFF0000) | ZeroExtend32(value);
     }
@@ -837,7 +837,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
 
     case 0x1F801D9A - SPU_BASE:
     {
-      Log_DebugPrintf("SPU reverb on register <- 0x%04X", ZeroExtend32(value));
+      Log_DebugFmt("SPU reverb on register <- 0x{:04X}", value);
       GeneratePendingSamples();
       s_reverb_on_register = (s_reverb_on_register & 0x0000FFFF) | (ZeroExtend32(value) << 16);
     }
@@ -845,7 +845,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
 
     case 0x1F801DA2 - SPU_BASE:
     {
-      Log_DebugPrintf("SPU reverb base address < 0x%04X", ZeroExtend32(value));
+      Log_DebugFmt("SPU reverb base address < 0x{:04X}", value);
       GeneratePendingSamples();
       s_reverb_registers.mBASE = value;
       s_reverb_base_address = ZeroExtend32(value << 2) & 0x3FFFFu;
@@ -855,7 +855,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
 
     case 0x1F801DA4 - SPU_BASE:
     {
-      Log_DebugPrintf("SPU IRQ address register <- 0x%04X", ZeroExtend32(value));
+      Log_DebugFmt("SPU IRQ address register <- 0x{:04X}", value);
       GeneratePendingSamples();
       s_irq_address = value;
 
@@ -867,14 +867,14 @@ void SPU::WriteRegister(u32 offset, u16 value)
 
     case 0x1F801DA6 - SPU_BASE:
     {
-      Log_DebugPrintf("SPU transfer address register <- 0x%04X", ZeroExtend32(value));
+      Log_DebugFmt("SPU transfer address register <- 0x{:04X}", value);
       s_transfer_event->InvokeEarly();
       s_transfer_address_reg = value;
       s_transfer_address = ZeroExtend32(value) * 8;
       if (IsRAMIRQTriggerable() && CheckRAMIRQ(s_transfer_address))
       {
-        Log_DebugPrintf("Trigger IRQ @ %08X %04X from transfer address reg set", s_transfer_address,
-                        s_transfer_address / 8);
+        Log_DebugFmt("Trigger IRQ @ {:08X} {:04X} from transfer address reg set", s_transfer_address,
+                     s_transfer_address / 8);
         TriggerRAMIRQ();
       }
       return;
@@ -882,8 +882,8 @@ void SPU::WriteRegister(u32 offset, u16 value)
 
     case 0x1F801DA8 - SPU_BASE:
     {
-      Log_TracePrintf("SPU transfer data register <- 0x%04X (RAM offset 0x%08X)", ZeroExtend32(value),
-                      s_transfer_address);
+      Log_TraceFmt("SPU transfer data register <- 0x{:04X} (RAM offset 0x{:08X})", ZeroExtend32(value),
+                   s_transfer_address);
 
       ManualTransferWrite(value);
       return;
@@ -891,7 +891,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
 
     case 0x1F801DAA - SPU_BASE:
     {
-      Log_DebugPrintf("SPU control register <- 0x%04X", ZeroExtend32(value));
+      Log_DebugFmt("SPU control register <- 0x{:04X}", value);
       GeneratePendingSamples();
 
       const SPUCNT new_value{value};
@@ -905,14 +905,14 @@ void SPU::WriteRegister(u32 offset, u16 value)
           {
             // I would guess on the console it would gradually write the FIFO out. Hopefully nothing relies on this
             // level of timing granularity if we force it all out here.
-            Log_WarningPrintf("Draining write SPU transfer FIFO with %u bytes left", s_transfer_fifo.GetSize());
+            Log_WarningFmt("Draining write SPU transfer FIFO with {} bytes left", s_transfer_fifo.GetSize());
             TickCount ticks = std::numeric_limits<TickCount>::max();
             ExecuteFIFOWriteToRAM(ticks);
             DebugAssert(s_transfer_fifo.IsEmpty());
           }
           else
           {
-            Log_DebugPrintf("Clearing read SPU transfer FIFO with %u bytes left", s_transfer_fifo.GetSize());
+            Log_DebugFmt("Clearing read SPU transfer FIFO with {} bytes left", s_transfer_fifo.GetSize());
             s_transfer_fifo.Clear();
           }
         }
@@ -947,14 +947,14 @@ void SPU::WriteRegister(u32 offset, u16 value)
 
     case 0x1F801DAC - SPU_BASE:
     {
-      Log_DebugPrintf("SPU transfer control register <- 0x%04X", ZeroExtend32(value));
+      Log_DebugFmt("SPU transfer control register <- 0x{:04X}", value);
       s_transfer_control.bits = value;
       return;
     }
 
     case 0x1F801DB0 - SPU_BASE:
     {
-      Log_DebugPrintf("SPU left cd audio register <- 0x%04X", ZeroExtend32(value));
+      Log_DebugFmt("SPU left cd audio register <- 0x{:04X}", value);
       GeneratePendingSamples();
       s_cd_audio_volume_left = value;
     }
@@ -962,7 +962,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
 
     case 0x1F801DB2 - SPU_BASE:
     {
-      Log_DebugPrintf("SPU right cd audio register <- 0x%04X", ZeroExtend32(value));
+      Log_DebugFmt("SPU right cd audio register <- 0x{:04X}", value);
       GeneratePendingSamples();
       s_cd_audio_volume_right = value;
     }
@@ -971,7 +971,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
     case 0x1F801DB4 - SPU_BASE:
     {
       // External volumes aren't used, so don't bother syncing.
-      Log_DebugPrintf("SPU left external volume register <- 0x%04X", ZeroExtend32(value));
+      Log_DebugFmt("SPU left external volume register <- 0x{:04X}", value);
       s_external_volume_left = value;
     }
     break;
@@ -979,7 +979,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
     case 0x1F801DB6 - SPU_BASE:
     {
       // External volumes aren't used, so don't bother syncing.
-      Log_DebugPrintf("SPU right external volume register <- 0x%04X", ZeroExtend32(value));
+      Log_DebugFmt("SPU right external volume register <- 0x{:04X}", value);
       s_external_volume_right = value;
     }
     break;
@@ -1001,14 +1001,14 @@ void SPU::WriteRegister(u32 offset, u16 value)
       if (offset >= (0x1F801DC0 - SPU_BASE) && offset < (0x1F801E00 - SPU_BASE))
       {
         const u32 reg = (offset - (0x1F801DC0 - SPU_BASE)) / 2;
-        Log_DebugPrintf("SPU reverb register %u <- 0x%04X", reg, value);
+        Log_DebugFmt("SPU reverb register {} <- 0x{:04X}", reg, value);
         GeneratePendingSamples();
         s_reverb_registers.rev[reg] = value;
         return;
       }
 
-      Log_DevPrintf("Unknown SPU register write: offset 0x%X (address 0x%08X) value 0x%04X", offset, offset | SPU_BASE,
-                    ZeroExtend32(value));
+      Log_DevFmt("Unknown SPU register write: offset 0x{:X} (address 0x{:08X}) value 0x{:04X}", offset,
+                 offset | SPU_BASE, value);
       return;
     }
   }
@@ -1025,7 +1025,7 @@ u16 SPU::ReadVoiceRegister(u32 offset)
   if (reg_index >= 6 && (voice.IsOn() || s_key_on_register & (1u << voice_index)))
     GeneratePendingSamples();
 
-  Log_TracePrintf("Read voice %u register %u -> 0x%02X", voice_index, reg_index, voice.regs.index[reg_index]);
+  Log_TraceFmt("Read voice {} register {} -> 0x{:02X}", voice_index, reg_index, voice.regs.index[reg_index]);
   return voice.regs.index[reg_index];
 }
 
@@ -1044,7 +1044,7 @@ void SPU::WriteVoiceRegister(u32 offset, u16 value)
   {
     case 0x00: // volume left
     {
-      Log_DebugPrintf("SPU voice %u volume left <- 0x%04X", voice_index, value);
+      Log_DebugFmt("SPU voice {} volume left <- 0x{:04X}", voice_index, value);
       voice.regs.volume_left.bits = value;
       voice.left_volume.Reset(voice.regs.volume_left);
     }
@@ -1052,7 +1052,7 @@ void SPU::WriteVoiceRegister(u32 offset, u16 value)
 
     case 0x02: // volume right
     {
-      Log_DebugPrintf("SPU voice %u volume right <- 0x%04X", voice_index, value);
+      Log_DebugFmt("SPU voice {} volume right <- 0x{:04X}", voice_index, value);
       voice.regs.volume_right.bits = value;
       voice.right_volume.Reset(voice.regs.volume_right);
     }
@@ -1060,21 +1060,21 @@ void SPU::WriteVoiceRegister(u32 offset, u16 value)
 
     case 0x04: // sample rate
     {
-      Log_DebugPrintf("SPU voice %u ADPCM sample rate <- 0x%04X", voice_index, value);
+      Log_DebugFmt("SPU voice {} ADPCM sample rate <- 0x{:04X}", voice_index, value);
       voice.regs.adpcm_sample_rate = value;
     }
     break;
 
     case 0x06: // start address
     {
-      Log_DebugPrintf("SPU voice %u ADPCM start address <- 0x%04X", voice_index, value);
+      Log_DebugFmt("SPU voice {} ADPCM start address <- 0x{:04X}", voice_index, value);
       voice.regs.adpcm_start_address = value;
     }
     break;
 
     case 0x08: // adsr low
     {
-      Log_DebugPrintf("SPU voice %u ADSR low <- 0x%04X (was 0x%04X)", voice_index, value, voice.regs.adsr.bits_low);
+      Log_DebugFmt("SPU voice {} ADSR low <- 0x{:04X} (was 0x{:04X})", voice_index, value, voice.regs.adsr.bits_low);
       voice.regs.adsr.bits_low = value;
       if (voice.IsOn())
         voice.UpdateADSREnvelope();
@@ -1083,7 +1083,7 @@ void SPU::WriteVoiceRegister(u32 offset, u16 value)
 
     case 0x0A: // adsr high
     {
-      Log_DebugPrintf("SPU voice %u ADSR high <- 0x%04X (was 0x%04X)", voice_index, value, voice.regs.adsr.bits_low);
+      Log_DebugFmt("SPU voice {} ADSR high <- 0x{:04X} (was 0x{:04X})", voice_index, value, voice.regs.adsr.bits_low);
       voice.regs.adsr.bits_high = value;
       if (voice.IsOn())
         voice.UpdateADSREnvelope();
@@ -1092,7 +1092,7 @@ void SPU::WriteVoiceRegister(u32 offset, u16 value)
 
     case 0x0C: // adsr volume
     {
-      Log_DebugPrintf("SPU voice %u ADSR volume <- 0x%04X (was 0x%04X)", voice_index, value, voice.regs.adsr_volume);
+      Log_DebugFmt("SPU voice {} ADSR volume <- 0x{:04X} (was 0x{:04X})", voice_index, value, voice.regs.adsr_volume);
       voice.regs.adsr_volume = value;
     }
     break;
@@ -1106,22 +1106,22 @@ void SPU::WriteVoiceRegister(u32 offset, u16 value)
       //  - Valkyrie Profile
 
       const bool ignore_loop_address = voice.IsOn() && !voice.is_first_block;
-      Log_DebugPrintf("SPU voice %u ADPCM repeat address <- 0x%04X", voice_index, value);
+      Log_DebugFmt("SPU voice {} ADPCM repeat address <- 0x{:04X}", voice_index, value);
       voice.regs.adpcm_repeat_address = value;
       voice.ignore_loop_address |= ignore_loop_address;
 
       if (!ignore_loop_address)
       {
-        Log_DevPrintf("Not ignoring loop address, the ADPCM repeat address of 0x%04X for voice %u will be overwritten",
-                      value, voice_index);
+        Log_DevFmt("Not ignoring loop address, the ADPCM repeat address of 0x{:04X} for voice {} will be overwritten",
+                   value, voice_index);
       }
     }
     break;
 
     default:
     {
-      Log_ErrorPrintf("Unknown SPU voice %u register write: offset 0x%X (address 0x%08X) value 0x%04X", offset,
-                      voice_index, offset | SPU_BASE, ZeroExtend32(value));
+      Log_ErrorFmt("Unknown SPU voice {} register write: offset 0x%X (address 0x{:08X}) value 0x{:04X}", offset,
+                   voice_index, offset | SPU_BASE, ZeroExtend32(value));
     }
     break;
   }
@@ -1168,7 +1168,7 @@ void SPU::CheckForLateRAMIRQs()
 {
   if (CheckRAMIRQ(s_transfer_address))
   {
-    Log_DebugPrintf("Trigger IRQ @ %08X %04X from late transfer", s_transfer_address, s_transfer_address / 8);
+    Log_DebugFmt("Trigger IRQ @ {:08X} {:04X} from late transfer", s_transfer_address, s_transfer_address / 8);
     TriggerRAMIRQ();
     return;
   }
@@ -1184,7 +1184,7 @@ void SPU::CheckForLateRAMIRQs()
     const u32 address = v.current_address * 8;
     if (CheckRAMIRQ(address) || CheckRAMIRQ((address + 8) & RAM_MASK))
     {
-      Log_DebugPrintf("Trigger IRQ @ %08X %04X from late", address, address / 8);
+      Log_DebugFmt("Trigger IRQ @ {:08X} ({:04X}) from late", address, address / 8);
       TriggerRAMIRQ();
       return;
     }
@@ -1194,11 +1194,11 @@ void SPU::CheckForLateRAMIRQs()
 void SPU::WriteToCaptureBuffer(u32 index, s16 value)
 {
   const u32 ram_address = (index * CAPTURE_BUFFER_SIZE_PER_CHANNEL) | ZeroExtend16(s_capture_buffer_position);
-  // Log_DebugPrintf("write to capture buffer %u (0x%08X) <- 0x%04X", index, ram_address, u16(value));
+  // Log_DebugFmt("write to capture buffer {} (0x{:08X}) <- 0x{:04X}", index, ram_address, u16(value));
   std::memcpy(&s_ram[ram_address], &value, sizeof(value));
   if (IsRAMIRQTriggerable() && CheckRAMIRQ(ram_address))
   {
-    Log_DebugPrintf("Trigger IRQ @ %08X %04X from capture buffer", ram_address, ram_address / 8);
+    Log_DebugFmt("Trigger IRQ @ {:08X} ({:04X}) from capture buffer", ram_address, ram_address / 8);
     TriggerRAMIRQ();
   }
 }
@@ -1222,7 +1222,7 @@ ALWAYS_INLINE_RELEASE void SPU::ExecuteFIFOReadFromRAM(TickCount& ticks)
 
     if (IsRAMIRQTriggerable() && CheckRAMIRQ(s_transfer_address))
     {
-      Log_DebugPrintf("Trigger IRQ @ %08X %04X from transfer read", s_transfer_address, s_transfer_address / 8);
+      Log_DebugFmt("Trigger IRQ @ {:08X} ({:04X}) from transfer read", s_transfer_address, s_transfer_address / 8);
       TriggerRAMIRQ();
     }
   }
@@ -1239,7 +1239,7 @@ ALWAYS_INLINE_RELEASE void SPU::ExecuteFIFOWriteToRAM(TickCount& ticks)
 
     if (IsRAMIRQTriggerable() && CheckRAMIRQ(s_transfer_address))
     {
-      Log_DebugPrintf("Trigger IRQ @ %08X %04X from transfer write", s_transfer_address, s_transfer_address / 8);
+      Log_DebugFmt("Trigger IRQ @ {:08X} ({:04X}) from transfer write", s_transfer_address, s_transfer_address / 8);
       TriggerRAMIRQ();
     }
   }
@@ -1303,7 +1303,7 @@ void SPU::ManualTransferWrite(u16 value)
 {
   if (!s_transfer_fifo.IsEmpty() && s_SPUCNT.ram_transfer_mode != RAMTransferMode::DMARead)
   {
-    Log_WarningPrintf("FIFO not empty on manual SPU write, draining to hopefully avoid corruption. Game is silly.");
+    Log_WarningPrint("FIFO not empty on manual SPU write, draining to hopefully avoid corruption. Game is silly.");
     if (s_SPUCNT.ram_transfer_mode != RAMTransferMode::Stopped)
       ExecuteTransfer(nullptr, std::numeric_limits<s32>::max(), 0);
   }
@@ -1313,7 +1313,7 @@ void SPU::ManualTransferWrite(u16 value)
 
   if (IsRAMIRQTriggerable() && CheckRAMIRQ(s_transfer_address))
   {
-    Log_DebugPrintf("Trigger IRQ @ %08X %04X from manual write", s_transfer_address, s_transfer_address / 8);
+    Log_DebugFmt("Trigger IRQ @ {:08X} ({:04X}) from manual write", s_transfer_address, s_transfer_address / 8);
     TriggerRAMIRQ();
   }
 }
@@ -1431,7 +1431,7 @@ void SPU::DMARead(u32* words, u32 word_count)
       fill_value = halfwords[size - 1];
     }
 
-    Log_WarningPrintf("Transfer FIFO underflow, filling with 0x%04X", fill_value);
+    Log_WarningFmt("Transfer FIFO underflow, filling with 0x{:04X}", fill_value);
     std::fill_n(&halfwords[size], halfword_count - size, fill_value);
   }
   else
@@ -1452,7 +1452,7 @@ void SPU::DMAWrite(const u32* words, u32 word_count)
   s_transfer_fifo.PushRange(halfwords, words_to_transfer);
 
   if (words_to_transfer != halfword_count) [[unlikely]]
-    Log_WarningPrintf("Transfer FIFO overflow, dropping %u halfwords", halfword_count - words_to_transfer);
+    Log_WarningFmt("Transfer FIFO overflow, dropping {} halfwords", halfword_count - words_to_transfer);
 
   UpdateDMARequest();
   UpdateTransferEvent();
@@ -1491,7 +1491,7 @@ bool SPU::StartDumpingAudio(const char* filename)
   s_dump_writer = std::make_unique<WAVWriter>();
   if (!s_dump_writer->Open(filename, SAMPLE_RATE, 2))
   {
-    Log_ErrorPrintf("Failed to open '%s'", filename);
+    Log_ErrorFmt("Failed to open '{}'", filename);
     s_dump_writer.reset();
     return false;
   }
@@ -1511,7 +1511,7 @@ bool SPU::StartDumpingAudio(const char* filename)
     const std::string voice_filename = Path::ReplaceExtension(filename, new_suffix);
     if (!s_voice_dump_writers[i]->Open(voice_filename.c_str(), SAMPLE_RATE, 2))
     {
-      Log_ErrorPrintf("Failed to open voice dump filename '%s'", voice_filename.c_str());
+      Log_ErrorFmt("Failed to open voice dump filename '{}'", voice_filename.c_str());
       s_voice_dump_writers[i].reset();
     }
   }
@@ -1916,7 +1916,7 @@ void SPU::ReadADPCMBlock(u16 address, ADPCMBlock* block)
   u32 ram_address = (ZeroExtend32(address) * 8) & RAM_MASK;
   if (IsRAMIRQTriggerable() && (CheckRAMIRQ(ram_address) || CheckRAMIRQ((ram_address + 8) & RAM_MASK)))
   {
-    Log_DebugPrintf("Trigger IRQ @ %08X %04X from ADPCM reader", ram_address, ram_address / 8);
+    Log_DebugFmt("Trigger IRQ @ {:08X} ({:04X}) from ADPCM reader", ram_address, ram_address / 8);
     TriggerRAMIRQ();
   }
 
@@ -1965,7 +1965,7 @@ ALWAYS_INLINE_RELEASE std::tuple<s32, s32> SPU::SampleVoice(u32 voice_index)
 
     if (voice.current_block_flags.loop_start && !voice.ignore_loop_address)
     {
-      Log_TracePrintf("Voice %u loop start @ 0x%08X", voice_index, ZeroExtend32(voice.current_address));
+      Log_TraceFmt("Voice {} loop start @ 0x{:08X}", voice_index, voice.current_address);
       voice.regs.adpcm_repeat_address = voice.current_address;
     }
   }
@@ -2024,12 +2024,20 @@ ALWAYS_INLINE_RELEASE std::tuple<s32, s32> SPU::SampleVoice(u32 voice_index)
 
       if (!voice.current_block_flags.loop_repeat)
       {
-        Log_TracePrintf("Voice %u loop end+mute @ 0x%08X", voice_index, ZeroExtend32(voice.current_address));
-        voice.ForceOff();
+        // End+Mute flags are ignored when noise is enabled. ADPCM data is still decoded.
+        if (!IsVoiceNoiseEnabled(voice_index))
+        {
+          Log_TraceFmt("Voice {} loop end+mute @ 0x{:04X}", voice_index, voice.current_address);
+          voice.ForceOff();
+        }
+        else
+        {
+          Log_TraceFmt("IGNORING voice {} loop end+mute @ 0x{:04X}", voice_index, voice.current_address);
+        }
       }
       else
       {
-        Log_TracePrintf("Voice %u loop end+repeat @ 0x%08X", voice_index, ZeroExtend32(voice.current_address));
+        Log_TraceFmt("Voice {} loop end+repeat @ 0x{:04X}", voice_index, voice.current_address);
       }
     }
   }