mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-08 07:05:40 +12:00
HLE DSP: Add embedded buffers
This commit is contained in:
parent
37f9f5d894
commit
1c355041fa
2 changed files with 62 additions and 9 deletions
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <queue>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "audio/dsp_core.hpp"
|
#include "audio/dsp_core.hpp"
|
||||||
#include "audio/dsp_shared_mem.hpp"
|
#include "audio/dsp_shared_mem.hpp"
|
||||||
|
@ -7,24 +9,38 @@
|
||||||
|
|
||||||
namespace Audio {
|
namespace Audio {
|
||||||
struct DSPSource {
|
struct DSPSource {
|
||||||
std::array<float, 3> gain0, gain1, gain2;
|
|
||||||
u16 syncCount;
|
|
||||||
bool enabled;
|
|
||||||
|
|
||||||
// Audio buffer information
|
// Audio buffer information
|
||||||
// https://www.3dbrew.org/wiki/DSP_Memory_Region
|
// https://www.3dbrew.org/wiki/DSP_Memory_Region
|
||||||
struct Buffer {
|
struct Buffer {
|
||||||
u32 paddr; // Physical address of the buffer
|
u32 paddr; // Physical address of the buffer
|
||||||
u32 sampleCount; // Total number of samples
|
u32 sampleCount; // Total number of samples
|
||||||
u8 adpcmScale; // ADPCM predictor/scale
|
u8 adpcmScale; // ADPCM predictor/scale
|
||||||
u8 pad; // Unknown
|
u8 pad1; // Unknown
|
||||||
|
|
||||||
std::array<s16, 2> previousSamples; // ADPCM y[n-1] and y[n-2]
|
std::array<s16, 2> previousSamples; // ADPCM y[n-1] and y[n-2]
|
||||||
bool adpcmDirty;
|
bool adpcmDirty;
|
||||||
bool looping;
|
bool looping;
|
||||||
u16 bufferID;
|
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<Buffer>;
|
||||||
|
|
||||||
|
std::array<float, 3> gain0, gain1, gain2;
|
||||||
|
u16 syncCount;
|
||||||
|
bool enabled;
|
||||||
|
|
||||||
|
BufferQueue buffers;
|
||||||
int index = 0; // Index of the voice in [0, 23] for debugging
|
int index = 0; // Index of the voice in [0, 23] for debugging
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "audio/hle_core.hpp"
|
#include "audio/hle_core.hpp"
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "services/dsp.hpp"
|
#include "services/dsp.hpp"
|
||||||
|
|
||||||
|
@ -206,6 +207,9 @@ namespace Audio {
|
||||||
updateSourceConfig(source, config);
|
updateSourceConfig(source, config);
|
||||||
|
|
||||||
// Generate audio
|
// Generate audio
|
||||||
|
if (source.enabled) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Update write region of shared memory
|
// Update write region of shared memory
|
||||||
auto& status = write.sourceStatuses.status[i];
|
auto& status = write.sourceStatuses.status[i];
|
||||||
|
@ -225,8 +229,6 @@ namespace Audio {
|
||||||
if (config.enableDirty) {
|
if (config.enableDirty) {
|
||||||
config.enableDirty = 0;
|
config.enableDirty = 0;
|
||||||
source.enabled = config.enable != 0;
|
source.enabled = config.enable != 0;
|
||||||
|
|
||||||
printf("Voice %d enable set to %d\n", source.index, source.enabled);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.syncCountDirty) {
|
if (config.syncCountDirty) {
|
||||||
|
@ -236,12 +238,45 @@ namespace Audio {
|
||||||
|
|
||||||
if (config.resetFlag) {
|
if (config.resetFlag) {
|
||||||
config.resetFlag = 0;
|
config.resetFlag = 0;
|
||||||
printf("Reset voice %d\n", source.index);
|
source.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.partialResetFlag) {
|
if (config.partialResetFlag) {
|
||||||
config.partialResetFlag = 0;
|
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;
|
config.dirtyRaw = 0;
|
||||||
|
@ -250,5 +285,7 @@ namespace Audio {
|
||||||
void DSPSource::reset() {
|
void DSPSource::reset() {
|
||||||
enabled = false;
|
enabled = false;
|
||||||
syncCount = 0;
|
syncCount = 0;
|
||||||
|
|
||||||
|
buffers = {};
|
||||||
}
|
}
|
||||||
} // namespace Audio
|
} // namespace Audio
|
||||||
|
|
Loading…
Add table
Reference in a new issue