mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-08 23:25:40 +12:00
Better audio playback code
This commit is contained in:
parent
1baf8a13ed
commit
83aafa31f0
3 changed files with 32 additions and 12 deletions
|
@ -24,7 +24,8 @@ namespace Audio {
|
||||||
static constexpr u64 lleSlice = 16384;
|
static constexpr u64 lleSlice = 16384;
|
||||||
|
|
||||||
class DSPCore {
|
class DSPCore {
|
||||||
using Samples = Common::RingBuffer<s16, 1024>;
|
// 0x2000 stereo (= 2 channel) samples
|
||||||
|
using Samples = Common::RingBuffer<s16, 0x2000 * 2>;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Memory& mem;
|
Memory& mem;
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "helpers.hpp"
|
||||||
#include "miniaudio.h"
|
#include "miniaudio.h"
|
||||||
#include "ring_buffer.hpp"
|
#include "ring_buffer.hpp"
|
||||||
|
|
||||||
class MiniAudioDevice {
|
class MiniAudioDevice {
|
||||||
using Samples = Common::RingBuffer<ma_int16, 1024>;
|
using Samples = Common::RingBuffer<ma_int16, 0x2000 * 2>;
|
||||||
static constexpr ma_uint32 sampleRate = 32768; // 3DS sample rate
|
static constexpr ma_uint32 sampleRate = 32768; // 3DS sample rate
|
||||||
static constexpr ma_uint32 channelCount = 2; // Audio output is stereo
|
static constexpr ma_uint32 channelCount = 2; // Audio output is stereo
|
||||||
|
|
||||||
|
@ -20,6 +21,8 @@ class MiniAudioDevice {
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
bool running = false;
|
bool running = false;
|
||||||
|
|
||||||
|
// Store the last stereo sample we output. We play this when underruning to avoid pops.
|
||||||
|
std::array<s16, 2> lastStereoSample;
|
||||||
std::vector<std::string> audioDevices;
|
std::vector<std::string> audioDevices;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "audio/miniaudio_device.hpp"
|
#include "audio/miniaudio_device.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#include "helpers.hpp"
|
#include "helpers.hpp"
|
||||||
|
|
||||||
MiniAudioDevice::MiniAudioDevice() : initialized(false), running(false), samples(nullptr) {}
|
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.aaudio.usage = ma_aaudio_usage_game;
|
||||||
deviceConfig.wasapi.noAutoConvertSRC = true;
|
deviceConfig.wasapi.noAutoConvertSRC = true;
|
||||||
|
|
||||||
|
lastStereoSample = {0, 0};
|
||||||
|
|
||||||
deviceConfig.dataCallback = [](ma_device* device, void* out, const void* input, ma_uint32 frameCount) {
|
deviceConfig.dataCallback = [](ma_device* device, void* out, const void* input, ma_uint32 frameCount) {
|
||||||
auto self = reinterpret_cast<MiniAudioDevice*>(device->pUserData);
|
auto self = reinterpret_cast<MiniAudioDevice*>(device->pUserData);
|
||||||
s16* output = reinterpret_cast<ma_int16*>(out);
|
if (!self->running) {
|
||||||
const usize maxSamples = std::min(self->samples->Capacity(), usize(frameCount * channelCount));
|
return;
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
if (ma_device_init(&context, &deviceConfig, &device) != MA_SUCCESS) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue