mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-07 22:55:40 +12:00
HLE DSP: Fix format and source type for audio buffers
This commit is contained in:
parent
1c355041fa
commit
1cc3bbf68d
3 changed files with 55 additions and 5 deletions
|
@ -8,6 +8,9 @@
|
||||||
#include "memory.hpp"
|
#include "memory.hpp"
|
||||||
|
|
||||||
namespace Audio {
|
namespace Audio {
|
||||||
|
using SampleFormat = HLE::SourceConfiguration::Configuration::Format;
|
||||||
|
using SourceType = HLE::SourceConfiguration::Configuration::MonoOrStereo;
|
||||||
|
|
||||||
struct DSPSource {
|
struct DSPSource {
|
||||||
// Audio buffer information
|
// Audio buffer information
|
||||||
// https://www.3dbrew.org/wiki/DSP_Memory_Region
|
// https://www.3dbrew.org/wiki/DSP_Memory_Region
|
||||||
|
@ -24,6 +27,9 @@ namespace Audio {
|
||||||
u8 pad2;
|
u8 pad2;
|
||||||
|
|
||||||
u32 playPosition = 0; // Current position in the buffer
|
u32 playPosition = 0; // Current position in the buffer
|
||||||
|
SampleFormat format;
|
||||||
|
SourceType sourceType;
|
||||||
|
|
||||||
bool fromQueue = false; // Is this buffer from the buffer queue or an embedded 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 hasPlayedOnce = false; // Has the buffer been played at least once before?
|
||||||
|
|
||||||
|
@ -81,6 +87,9 @@ namespace Audio {
|
||||||
std::array<Source, Audio::HLE::sourceCount> sources; // DSP voices
|
std::array<Source, Audio::HLE::sourceCount> sources; // DSP voices
|
||||||
Audio::HLE::DspMemory dspRam;
|
Audio::HLE::DspMemory dspRam;
|
||||||
|
|
||||||
|
SampleFormat sampleFormat = SampleFormat::ADPCM;
|
||||||
|
SourceType sourceType = SourceType::Stereo;
|
||||||
|
|
||||||
void resetAudioPipe();
|
void resetAudioPipe();
|
||||||
bool loaded = false; // Have we loaded a component?
|
bool loaded = false; // Have we loaded a component?
|
||||||
|
|
||||||
|
@ -104,9 +113,27 @@ namespace Audio {
|
||||||
Audio::HLE::SharedMemory& readRegion() { return readRegionIndex() == 0 ? dspRam.region0 : dspRam.region1; }
|
Audio::HLE::SharedMemory& readRegion() { return readRegionIndex() == 0 ? dspRam.region0 : dspRam.region1; }
|
||||||
Audio::HLE::SharedMemory& writeRegion() { return readRegionIndex() == 0 ? dspRam.region1 : dspRam.region0; }
|
Audio::HLE::SharedMemory& writeRegion() { return readRegionIndex() == 0 ? dspRam.region1 : dspRam.region0; }
|
||||||
|
|
||||||
|
// Get a pointer of type T* to the data starting from physical address paddr
|
||||||
|
template <typename T>
|
||||||
|
T* getPointerPhys(u32 paddr, u32 size = 0) {
|
||||||
|
if (paddr >= PhysicalAddrs::FCRAM && paddr + size <= PhysicalAddrs::FCRAMEnd) {
|
||||||
|
u8* fcram = mem.getFCRAM();
|
||||||
|
u32 index = paddr - PhysicalAddrs::FCRAM;
|
||||||
|
|
||||||
|
return (T*)&fcram[index];
|
||||||
|
} else if (paddr >= PhysicalAddrs::DSP_RAM && paddr + size <= PhysicalAddrs::DSP_RAM_End) {
|
||||||
|
u32 index = paddr - PhysicalAddrs::DSP_RAM;
|
||||||
|
return (T*)&dspRam.rawMemory[index];
|
||||||
|
} else [[unlikely]] {
|
||||||
|
Helpers::warn("[DSP] Tried to access unknown physical address: %08X", paddr);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void updateSourceConfig(Source& source, HLE::SourceConfiguration::Configuration& config);
|
void updateSourceConfig(Source& source, HLE::SourceConfiguration::Configuration& config);
|
||||||
void generateFrame(StereoFrame<s16>& frame);
|
void generateFrame(StereoFrame<s16>& frame);
|
||||||
void outputFrame();
|
void outputFrame();
|
||||||
|
void dumpBuffer(const Source::Buffer& buffer);
|
||||||
public:
|
public:
|
||||||
HLE_DSP(Memory& mem, Scheduler& scheduler, DSPService& dspService);
|
HLE_DSP(Memory& mem, Scheduler& scheduler, DSPService& dspService);
|
||||||
~HLE_DSP() override {}
|
~HLE_DSP() override {}
|
||||||
|
|
|
@ -19,7 +19,10 @@ namespace PhysicalAddrs {
|
||||||
VRAM = 0x18000000,
|
VRAM = 0x18000000,
|
||||||
VRAMEnd = VRAM + 0x005FFFFF,
|
VRAMEnd = VRAM + 0x005FFFFF,
|
||||||
FCRAM = 0x20000000,
|
FCRAM = 0x20000000,
|
||||||
FCRAMEnd = FCRAM + 0x07FFFFFF
|
FCRAMEnd = FCRAM + 0x07FFFFFF,
|
||||||
|
|
||||||
|
DSP_RAM = 0x1FF00000,
|
||||||
|
DSP_RAM_End = DSP_RAM + 0x0007FFFF
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,13 @@ namespace Audio {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HLE_DSP::reset() {
|
void HLE_DSP::reset() {
|
||||||
|
dspState = DSPState::Off;
|
||||||
loaded = false;
|
loaded = false;
|
||||||
|
|
||||||
|
// Initialize these to some sane defaults
|
||||||
|
sampleFormat = SampleFormat::ADPCM;
|
||||||
|
sourceType = SourceType::Stereo;
|
||||||
|
|
||||||
for (auto& e : pipeData) {
|
for (auto& e : pipeData) {
|
||||||
e.clear();
|
e.clear();
|
||||||
}
|
}
|
||||||
|
@ -207,16 +213,19 @@ namespace Audio {
|
||||||
updateSourceConfig(source, config);
|
updateSourceConfig(source, config);
|
||||||
|
|
||||||
// Generate audio
|
// Generate audio
|
||||||
if (source.enabled) {
|
if (source.enabled && !source.buffers.empty()) {
|
||||||
|
const auto& buffer = source.buffers.top();
|
||||||
|
const u8* data = getPointerPhys<u8>(buffer.paddr);
|
||||||
|
|
||||||
|
if (data != nullptr) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update write region of shared memory
|
// Update write region of shared memory
|
||||||
auto& status = write.sourceStatuses.status[i];
|
auto& status = write.sourceStatuses.status[i];
|
||||||
status.isEnabled = source.enabled;
|
status.isEnabled = source.enabled;
|
||||||
status.syncCount = source.syncCount;
|
status.syncCount = source.syncCount;
|
||||||
//status.lastBufferID=0,status.currentBufferID = 1; status.currentBufferIDDirty = 1;
|
|
||||||
//status.bufferPosition =
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,6 +254,15 @@ namespace Audio {
|
||||||
config.partialResetFlag = 0;
|
config.partialResetFlag = 0;
|
||||||
source.buffers = {};
|
source.buffers = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Should we check bufferQueueDirty here too?
|
||||||
|
if (config.formatDirty || config.embeddedBufferDirty) {
|
||||||
|
sampleFormat = config.format;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.monoOrStereoDirty || config.embeddedBufferDirty) {
|
||||||
|
sourceType = config.monoOrStereo;
|
||||||
|
}
|
||||||
|
|
||||||
if (config.embeddedBufferDirty) {
|
if (config.embeddedBufferDirty) {
|
||||||
config.embeddedBufferDirty = 0;
|
config.embeddedBufferDirty = 0;
|
||||||
|
@ -259,6 +277,8 @@ namespace Audio {
|
||||||
.looping = config.isLooping != 0,
|
.looping = config.isLooping != 0,
|
||||||
.bufferID = config.bufferID,
|
.bufferID = config.bufferID,
|
||||||
.playPosition = config.playPosition,
|
.playPosition = config.playPosition,
|
||||||
|
.format = sampleFormat,
|
||||||
|
.sourceType = sourceType,
|
||||||
.fromQueue = false,
|
.fromQueue = false,
|
||||||
.hasPlayedOnce = false,
|
.hasPlayedOnce = false,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue