From 2ccb264a8695200c2b06061c9fc01c594cb102e2 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Mon, 21 Jul 2025 01:59:46 +0300 Subject: [PATCH] HLE DSP: Implement partial embedded buffer updates (#782) --- include/audio/hle_core.hpp | 4 +++- src/core/audio/hle_core.cpp | 25 ++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/include/audio/hle_core.hpp b/include/audio/hle_core.hpp index d374e304..f04ed6c2 100644 --- a/include/audio/hle_core.hpp +++ b/include/audio/hle_core.hpp @@ -69,7 +69,9 @@ namespace Audio { // In order to save up on CPU time. uint enabledMixStages = 0; - u32 samplePosition; // Sample number into the current audio buffer + u32 samplePosition; // Sample number into the current audio buffer + u32 currentBufferPaddr; // Physical address of current audio buffer + float rateMultiplier; u16 syncCount; u16 currentBufferID; diff --git a/src/core/audio/hle_core.cpp b/src/core/audio/hle_core.cpp index 97a6211e..059318c8 100644 --- a/src/core/audio/hle_core.cpp +++ b/src/core/audio/hle_core.cpp @@ -396,7 +396,28 @@ namespace Audio { if (config.partialEmbeddedBufferDirty) { config.partialEmbeddedBufferDirty = 0; - printf("Partial embedded buffer dirty for voice %d\n", source.index); + + const u8* data = getPointerPhys(source.currentBufferPaddr & ~0x3); + + if (data != nullptr) { + switch (source.sampleFormat) { + case SampleFormat::PCM8: source.currentSamples = decodePCM8(data, config.length, source); break; + case SampleFormat::PCM16: source.currentSamples = decodePCM16(data, config.length, source); break; + case SampleFormat::ADPCM: source.currentSamples = decodeADPCM(data, config.length, source); break; + + default: + Helpers::warn("Invalid DSP sample format"); + source.currentSamples = {}; + break; + } + + // We're skipping the first samplePosition samples, so remove them from the buffer so as not to consume them later + if (source.samplePosition > 0) { + auto start = source.currentSamples.begin(); + auto end = std::next(start, source.samplePosition); + source.currentSamples.erase(start, end); + } + } } if (config.bufferQueueDirty) { @@ -478,6 +499,7 @@ namespace Audio { return; } + source.currentBufferPaddr = buffer.paddr; source.currentBufferID = buffer.bufferID; source.previousBufferID = 0; // For looping buffers, this is only set for the first time we play it. Loops do not set the dirty bit. @@ -766,6 +788,7 @@ namespace Audio { interpolationMode = InterpolationMode::Linear; samplePosition = 0; + currentBufferPaddr = 0; previousBufferID = 0; currentBufferID = 0; syncCount = 0;