diff --git a/include/audio/hle_core.hpp b/include/audio/hle_core.hpp index d4d72b62..46caf2f5 100644 --- a/include/audio/hle_core.hpp +++ b/include/audio/hle_core.hpp @@ -1,5 +1,7 @@ #pragma once #include +#include +#include #include "audio/dsp_core.hpp" #include "audio/dsp_shared_mem.hpp" @@ -7,24 +9,38 @@ namespace Audio { struct DSPSource { - std::array gain0, gain1, gain2; - u16 syncCount; - bool enabled; - // Audio buffer information // https://www.3dbrew.org/wiki/DSP_Memory_Region struct Buffer { u32 paddr; // Physical address of the buffer u32 sampleCount; // Total number of samples u8 adpcmScale; // ADPCM predictor/scale - u8 pad; // Unknown + u8 pad1; // Unknown std::array previousSamples; // ADPCM y[n-1] and y[n-2] bool adpcmDirty; bool looping; u16 bufferID; + u8 pad2; + + u32 playPosition = 0; // Current position in the buffer + bool fromQueue = false; // Is this buffer from the buffer queue or an embedded buffer? + bool hasPlayedOnce = false; // Has the buffer been played at least once before? + + bool operator<(const Buffer& other) const { + // Lower ID = Higher priority + // If this buffer ID is greater than the other one, then this buffer has a lower priority + return this->bufferID > other.bufferID; + } }; + using BufferQueue = std::priority_queue; + + std::array gain0, gain1, gain2; + u16 syncCount; + bool enabled; + + BufferQueue buffers; int index = 0; // Index of the voice in [0, 23] for debugging void reset(); diff --git a/src/core/audio/hle_core.cpp b/src/core/audio/hle_core.cpp index b27dd10b..06d15945 100644 --- a/src/core/audio/hle_core.cpp +++ b/src/core/audio/hle_core.cpp @@ -1,6 +1,7 @@ #include "audio/hle_core.hpp" #include +#include #include "services/dsp.hpp" @@ -206,6 +207,9 @@ namespace Audio { updateSourceConfig(source, config); // Generate audio + if (source.enabled) { + + } // Update write region of shared memory auto& status = write.sourceStatuses.status[i]; @@ -225,8 +229,6 @@ namespace Audio { if (config.enableDirty) { config.enableDirty = 0; source.enabled = config.enable != 0; - - printf("Voice %d enable set to %d\n", source.index, source.enabled); } if (config.syncCountDirty) { @@ -236,12 +238,45 @@ namespace Audio { if (config.resetFlag) { config.resetFlag = 0; - printf("Reset voice %d\n", source.index); + source.reset(); } if (config.partialResetFlag) { config.partialResetFlag = 0; - printf("Partially reset voice %d\n", source.index); + source.buffers = {}; + } + + if (config.embeddedBufferDirty) { + config.embeddedBufferDirty = 0; + if (s32(config.length) >= 0) [[likely]] { + // TODO: Add sample format and channel count + Source::Buffer buffer{ + .paddr = config.physicalAddress, + .sampleCount = config.length, + .adpcmScale = u8(config.adpcm_ps), + .previousSamples = {s16(config.adpcm_yn[0]), s16(config.adpcm_yn[1])}, + .adpcmDirty = config.adpcmDirty != 0, + .looping = config.isLooping != 0, + .bufferID = config.bufferID, + .playPosition = config.playPosition, + .fromQueue = false, + .hasPlayedOnce = false, + }; + + source.buffers.emplace(std::move(buffer)); + } else { + log("Invalid embedded buffer size for DSP voice %d\n", source.index); + } + } + + if (config.partialEmbeddedBufferDirty) { + config.partialEmbeddedBufferDirty = 0; + printf("Partial embedded buffer dirty for voice %d\n", source.index); + } + + if (config.bufferQueueDirty) { + config.bufferQueueDirty = 0; + printf("Buffer queue dirty for voice %d\n", source.index); } config.dirtyRaw = 0; @@ -250,5 +285,7 @@ namespace Audio { void DSPSource::reset() { enabled = false; syncCount = 0; + + buffers = {}; } } // namespace Audio