mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-06-09 12:31:40 +12:00
Merge pull request #642 from wheremyfoodat/more-dsp
Better audio playback code
This commit is contained in:
commit
842634e64e
8 changed files with 175 additions and 157 deletions
|
@ -1,5 +1,7 @@
|
|||
#include "audio/miniaudio_device.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "helpers.hpp"
|
||||
|
||||
MiniAudioDevice::MiniAudioDevice() : initialized(false), running(false), samples(nullptr) {}
|
||||
|
@ -87,20 +89,34 @@ void MiniAudioDevice::init(Samples& samples, bool safe) {
|
|||
deviceConfig.aaudio.usage = ma_aaudio_usage_game;
|
||||
deviceConfig.wasapi.noAutoConvertSRC = true;
|
||||
|
||||
lastStereoSample = {0, 0};
|
||||
|
||||
deviceConfig.dataCallback = [](ma_device* device, void* out, const void* input, ma_uint32 frameCount) {
|
||||
auto self = reinterpret_cast<MiniAudioDevice*>(device->pUserData);
|
||||
s16* output = reinterpret_cast<ma_int16*>(out);
|
||||
const usize maxSamples = std::min(self->samples->Capacity(), usize(frameCount * channelCount));
|
||||
|
||||
// Wait until there's enough samples to pop
|
||||
while (self->samples->size() < maxSamples) {
|
||||
// If audio output is disabled from the emulator thread, make sure that this callback will return and not hang
|
||||
if (!self->running) {
|
||||
return;
|
||||
}
|
||||
if (!self->running) {
|
||||
return;
|
||||
}
|
||||
|
||||
self->samples->pop(output, maxSamples);
|
||||
s16* output = reinterpret_cast<ma_int16*>(out);
|
||||
usize samplesWritten = 0;
|
||||
samplesWritten += self->samples->pop(output, frameCount * channelCount);
|
||||
|
||||
// Get the last sample for underrun handling
|
||||
if (samplesWritten != 0) {
|
||||
std::memcpy(&self->lastStereoSample[0], &output[(samplesWritten - 1) * 2], sizeof(lastStereoSample));
|
||||
}
|
||||
|
||||
// If underruning, copy the last output sample
|
||||
{
|
||||
s16* pointer = &output[samplesWritten * 2];
|
||||
s16 l = self->lastStereoSample[0];
|
||||
s16 r = self->lastStereoSample[1];
|
||||
|
||||
for (usize i = samplesWritten; i < frameCount; i++) {
|
||||
*pointer++ = l;
|
||||
*pointer++ = r;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (ma_device_init(&context, &deviceConfig, &device) != MA_SUCCESS) {
|
||||
|
|
|
@ -82,7 +82,7 @@ namespace Audio {
|
|||
|
||||
scheduler.addEvent(Scheduler::EventType::RunDSP, scheduler.currentTimestamp + Audio::cyclesPerFrame);
|
||||
}
|
||||
|
||||
|
||||
u16 NullDSP::recvData(u32 regId) {
|
||||
if (regId != 0) {
|
||||
Helpers::panic("Audio: invalid register in null frontend");
|
||||
|
@ -116,13 +116,11 @@ namespace Audio {
|
|||
// TODO: Other initialization stuff here
|
||||
dspState = DSPState::On;
|
||||
resetAudioPipe();
|
||||
|
||||
|
||||
dspService.triggerPipeEvent(DSPPipeType::Audio);
|
||||
break;
|
||||
|
||||
case StateChange::Shutdown:
|
||||
dspState = DSPState::Off;
|
||||
break;
|
||||
case StateChange::Shutdown: dspState = DSPState::Off; break;
|
||||
|
||||
default: Helpers::panic("Unimplemented DSP audio pipe state change %d", state);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue