mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-24 14:25:50 +12:00
Audio device pt 2
This commit is contained in:
parent
486e2ea5cb
commit
4b7fedb65c
4 changed files with 41 additions and 42 deletions
|
@ -8,17 +8,17 @@
|
||||||
class AudioDeviceInterface {
|
class AudioDeviceInterface {
|
||||||
protected:
|
protected:
|
||||||
using Samples = Common::RingBuffer<s16, 0x2000 * 2>;
|
using Samples = Common::RingBuffer<s16, 0x2000 * 2>;
|
||||||
|
using RenderBatchCallback = usize (*)(const s16*, usize);
|
||||||
|
|
||||||
Samples* samples = nullptr;
|
Samples* samples = nullptr;
|
||||||
|
|
||||||
const AudioDeviceConfig& audioSettings;
|
const AudioDeviceConfig& audioSettings;
|
||||||
|
// Store the last stereo sample we output. We play this when underruning to avoid pops.
|
||||||
|
std::array<s16, 2> lastStereoSample{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AudioDeviceInterface(Samples* samples, const AudioDeviceConfig& audioSettings) : samples(samples), audioSettings(audioSettings) {}
|
AudioDeviceInterface(Samples* samples, const AudioDeviceConfig& audioSettings) : samples(samples), audioSettings(audioSettings) {}
|
||||||
|
|
||||||
// Store the last stereo sample we output. We play this when underruning to avoid pops.
|
|
||||||
// TODO: Make this protected again before merging!!!
|
|
||||||
std::array<s16, 2> lastStereoSample{};
|
|
||||||
|
|
||||||
bool running = false;
|
bool running = false;
|
||||||
Samples* getSamples() { return samples; }
|
Samples* getSamples() { return samples; }
|
||||||
|
|
||||||
|
@ -28,4 +28,7 @@ class AudioDeviceInterface {
|
||||||
|
|
||||||
virtual void start() = 0;
|
virtual void start() = 0;
|
||||||
virtual void stop() = 0;
|
virtual void stop() = 0;
|
||||||
|
|
||||||
|
// Only used for audio devices that render multiple audio frames in one go, eg the libretro audio device.
|
||||||
|
virtual void renderBatch(RenderBatchCallback callback) {}
|
||||||
};
|
};
|
|
@ -1,7 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <atomic>
|
#include <cstring>
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "audio/audio_device.hpp"
|
#include "audio/audio_device.hpp"
|
||||||
|
|
||||||
|
@ -28,6 +26,35 @@ class LibretroAudioDevice : public AudioDeviceInterface {
|
||||||
void start() override { running = true; }
|
void start() override { running = true; }
|
||||||
void stop() override { running = false; };
|
void stop() override { running = false; };
|
||||||
|
|
||||||
|
void renderBatch(RenderBatchCallback callback) override {
|
||||||
|
if (running) {
|
||||||
|
static constexpr int frameCount = 547;
|
||||||
|
static constexpr int channelCount = 2;
|
||||||
|
static s16 audioBuffer[frameCount * channelCount];
|
||||||
|
|
||||||
|
usize samplesWritten = 0;
|
||||||
|
samplesWritten += samples->pop(audioBuffer, frameCount * channelCount);
|
||||||
|
|
||||||
|
// Get the last sample for underrun handling
|
||||||
|
if (samplesWritten != 0) {
|
||||||
|
std::memcpy(&lastStereoSample[0], &audioBuffer[(samplesWritten - 1) * 2], sizeof(lastStereoSample));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If underruning, copy the last output sample
|
||||||
|
{
|
||||||
|
s16* pointer = &audioBuffer[samplesWritten * 2];
|
||||||
|
s16 l = lastStereoSample[0];
|
||||||
|
s16 r = lastStereoSample[1];
|
||||||
|
|
||||||
|
for (usize i = samplesWritten; i < frameCount; i++) {
|
||||||
|
*pointer++ = l;
|
||||||
|
*pointer++ = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(audioBuffer, sizeof(audioBuffer) / (2 * sizeof(s16)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool isInitialized() const { return initialized; }
|
bool isInitialized() const { return initialized; }
|
||||||
bool isRunning() const { return running; }
|
|
||||||
};
|
};
|
|
@ -60,7 +60,7 @@ class Emulator {
|
||||||
static constexpr u32 width = 400;
|
static constexpr u32 width = 400;
|
||||||
static constexpr u32 height = 240 * 2; // * 2 because 2 screens
|
static constexpr u32 height = 240 * 2; // * 2 because 2 screens
|
||||||
ROMType romType = ROMType::None;
|
ROMType romType = ROMType::None;
|
||||||
bool running = false; // Is the emulator running a game?
|
bool running = false; // Is the emulator running a game?
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef PANDA3DS_ENABLE_HTTP_SERVER
|
#ifdef PANDA3DS_ENABLE_HTTP_SERVER
|
||||||
|
|
|
@ -389,39 +389,8 @@ void retro_run() {
|
||||||
emulator->runFrame();
|
emulator->runFrame();
|
||||||
|
|
||||||
videoCallback(RETRO_HW_FRAME_BUFFER_VALID, emulator->width, emulator->height, 0);
|
videoCallback(RETRO_HW_FRAME_BUFFER_VALID, emulator->width, emulator->height, 0);
|
||||||
auto& audioDevice = emulator->getAudioDevice();
|
// Call audio batch callback
|
||||||
|
emulator->getAudioDevice().renderBatch(audioBatchCallback);
|
||||||
if (audioDevice.running) {
|
|
||||||
static constexpr int frameCount = 547;
|
|
||||||
static constexpr int channelCount = 2;
|
|
||||||
static int16_t audioBuffer[frameCount * channelCount];
|
|
||||||
|
|
||||||
usize samplesWritten = 0;
|
|
||||||
samplesWritten += audioDevice.getSamples()->pop(audioBuffer, frameCount * channelCount);
|
|
||||||
|
|
||||||
// Get the last sample for underrun handling
|
|
||||||
if (samplesWritten != 0) {
|
|
||||||
std::memcpy(
|
|
||||||
&audioDevice.lastStereoSample[0],
|
|
||||||
&audioBuffer[(samplesWritten - 1) * 2],
|
|
||||||
sizeof(audioDevice.lastStereoSample)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If underruning, copy the last output sample
|
|
||||||
{
|
|
||||||
s16* pointer = &audioBuffer[samplesWritten * 2];
|
|
||||||
s16 l = audioDevice.lastStereoSample[0];
|
|
||||||
s16 r = audioDevice.lastStereoSample[1];
|
|
||||||
|
|
||||||
for (usize i = samplesWritten; i < frameCount; i++) {
|
|
||||||
*pointer++ = l;
|
|
||||||
*pointer++ = r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
audioBatchCallback(audioBuffer, sizeof(audioBuffer) / (2 * sizeof(int16_t)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void retro_set_controller_port_device(uint port, uint device) {}
|
void retro_set_controller_port_device(uint port, uint device) {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue