Add new audio interfaces

This commit is contained in:
Tony Wasserka 2024-09-29 19:29:28 +02:00
parent 8dadaf304c
commit d66316c917
13 changed files with 78 additions and 18 deletions

View file

@ -0,0 +1,9 @@
#pragma once
#include <ui/audio_frontend.hpp>
class SDLAudioFrontend : public AudioFrontend {
public:
void OutputSamples(std::array<int16_t, 2> samples) override {}
SDLAudioFrontend() = default;
};

View file

@ -1,3 +1,5 @@
#include "audio_frontend_sdl.hpp"
#include <ui/key_database.hpp>
#include "platform/file_formats/cia.hpp"
@ -361,6 +363,7 @@ if (bootstrap_nand) // Experimental system bootstrapper
//exit(1);
g_samples.reserve(32768);
auto audio_frontend = std::make_unique<SDLAudioFrontend>();
#ifndef DISABLE_AUDIO
static std::ofstream ofs("samples.raw", std::ios_base::binary);
static std::ofstream ofs2("samples2.raw", std::ios_base::binary);
@ -531,7 +534,7 @@ if (bootstrap_nand) // Experimental system bootstrapper
}
auto gamecard = LoadGameCard(*frontend_logger, settings);
session = std::make_unique<EmuSession>(*log_manager, settings, *display, *display, keydb, std::move(gamecard));
session = std::make_unique<EmuSession>(*log_manager, settings, *audio_frontend, *display, *display, keydb, std::move(gamecard));
emuthread = std::thread {
[&emuthread_exception, &session]() {

View file

@ -10,6 +10,8 @@
#include "framework/logging.hpp"
#include "framework/meta_tools.hpp"
#include <ui/audio_frontend.hpp>
#include <spdlog/spdlog.h>
#include <boost/endian/arithmetic.hpp>
@ -842,6 +844,8 @@ static bool just_reset = false;
struct DSPMMIO : MemoryAccessHandler {
std::shared_ptr<spdlog::logger> logger;
AudioFrontend* frontend = nullptr;
DSPConfig config {};
DSPStatus status { DSPStatus{}.write_fifo_empty()(true) };
@ -1032,7 +1036,7 @@ struct DSPMMIO : MemoryAccessHandler {
static std::ofstream ofs2("samples2.raw", std::ios_base::binary);
static std::vector<uint16_t> data;
static std::vector<uint16_t> data2;
static auto audio_callback = [](std::array<int16_t, 2> samples) {
auto audio_callback = [this](std::array<int16_t, 2> samples) {
data.push_back(samples[0]);
data2.push_back(samples[1]);
if (data.size() == 0x10000) {
@ -1044,10 +1048,9 @@ struct DSPMMIO : MemoryAccessHandler {
data2.clear();
}
TeakraAudioCallback(samples);
frontend->OutputSamples(samples);
};
g_teakra->SetAudioCallback(audio_callback);
// g_teakra->SetAudioCallback(TeakraAudioCallback);
// NOTE: These don't seem to be needed (only for unaligned memory accesses?)
static Teakra::AHBMCallback ahbm;
@ -1265,6 +1268,10 @@ PhysicalMemory::PhysicalMemory(LogManager& log_manager)
g_mem = this;
}
void PhysicalMemory::InjectDependency(AudioFrontend& frontend) {
std::get<IO_DSP1>(memory).handler->frontend = &frontend;
}
void PhysicalMemory::InjectDependency(PicaContext& context) {
std::get<IO_GPU>(memory).handler->context = context.context.get();
}

View file

@ -15,6 +15,8 @@
#include <memory>
#include <vector>
struct AudioFrontend;
class LogManager;
class PicaContext;
@ -343,7 +345,8 @@ struct PhysicalMemory {
*/
PhysicalMemory(LogManager& log_manager);
void InjectDependency(PicaContext& pica);
void InjectDependency(AudioFrontend&);
void InjectDependency(PicaContext&);
void InjectDependency(InputSource&);
};

View file

@ -1942,8 +1942,11 @@ const uint32_t num_firm_modules = 5;
// See MakeNewProcessId for details.
// TODO: Instead of this workaround, we should just not launch
// FakeDebugProcess before the FIRM modules.
OS::OS(Profiler::Profiler& profiler, Settings::Settings& settings, Interpreter::Setup& setup_, LogManager& log_manager, PicaContext& pica, EmuDisplay::EmuDisplay& display)
: next_pid(num_firm_modules),
OS::OS( Profiler::Profiler& profiler, Settings::Settings& settings,
Interpreter::Setup& setup_, LogManager& log_manager,
AudioFrontend& audio, PicaContext& pica, EmuDisplay::EmuDisplay& display)
: hypervisor(settings, audio),
next_pid(num_firm_modules),
internal_memory_owner(std::make_shared<MemoryBlockOwner>()),
memory_regions {
MemoryManager { ApplicationMemoryStart(settings), ApplicationMemorySize(settings) },
@ -2020,8 +2023,8 @@ OS::~OS() {
debug_process.reset(); // TODO: Not needed
}
std::pair<std::unique_ptr<OS>, std::unique_ptr<::ConsoleModule>> OS::Create(Settings::Settings& settings, Interpreter::Setup& setup, LogManager& log_manager, Profiler::Profiler& profiler, PicaContext& pica, EmuDisplay::EmuDisplay& display) {
auto&& os = std::make_unique<OS>(profiler, settings, setup, log_manager, pica, display);
std::pair<std::unique_ptr<OS>, std::unique_ptr<::ConsoleModule>> OS::Create(Settings::Settings& settings, Interpreter::Setup& setup, LogManager& log_manager, Profiler::Profiler& profiler, AudioFrontend& audio, PicaContext& pica, EmuDisplay::EmuDisplay& display) {
auto&& os = std::make_unique<OS>(profiler, settings, setup, log_manager, audio, pica, display);
auto&& console_module = std::unique_ptr<::ConsoleModule>(new ConsoleModule(*os));
return std::make_pair(std::move(os), std::move(console_module));
}

View file

@ -1563,7 +1563,8 @@ public: // TODO: privatize this again!
[[deprecated]] MemoryManager& memory_base() { return memory_regions[2]; }
MemoryManager& FindMemoryRegionContaining(uint32_t paddr, uint32_t size);
OS(Profiler::Profiler&, Settings::Settings&, Interpreter::Setup&, LogManager&, PicaContext&, EmuDisplay::EmuDisplay&);
OS( Profiler::Profiler&, Settings::Settings&, Interpreter::Setup&,
LogManager&, AudioFrontend&, PicaContext&, EmuDisplay::EmuDisplay&);
~OS();
Profiler::Profiler& profiler;
@ -1869,7 +1870,7 @@ public:
*/
SVCEmptyFuture SVCAddThread(std::shared_ptr<Thread> thread);
static std::pair<std::unique_ptr<OS>, std::unique_ptr<ConsoleModule>> Create(Settings::Settings& settings, Interpreter::Setup& setup, LogManager& log_manager, Profiler::Profiler&, PicaContext&, EmuDisplay::EmuDisplay&);
static std::pair<std::unique_ptr<OS>, std::unique_ptr<ConsoleModule>> Create(Settings::Settings& settings, Interpreter::Setup& setup, LogManager& log_manager, Profiler::Profiler&, AudioFrontend&, PicaContext&, EmuDisplay::EmuDisplay&);
/**
* Initialized the OS, spawning all service processes along the way.

View file

@ -79,7 +79,9 @@ struct State {
}
Hypervisor::Hypervisor() : state(new HPV::State) {
Hypervisor::Hypervisor(Settings::Settings& settings, AudioFrontend& audio_frontend) : state(new HPV::State) {
state->dsp_context.settings = &settings;
state->dsp_context.frontend = &audio_frontend;
}
Hypervisor::~Hypervisor() = default;

View file

@ -1,9 +1,14 @@
#pragma once
#include <functional>
#include <map>
#include <memory>
struct AudioFrontend;
namespace Settings {
struct Settings;
}
namespace HLE {
namespace OS {
@ -32,7 +37,7 @@ class Hypervisor {
std::unique_ptr<HPV::State> state;
public:
Hypervisor();
Hypervisor(Settings::Settings&, AudioFrontend&);
~Hypervisor();
// "thread" refers to the target (i.e. server) thread

View file

@ -1,6 +1,7 @@
#include "dsp_hpv.hpp"
#include "os_hypervisor_private.hpp"
#include "os.hpp"
#include <ui/audio_frontend.hpp>
#include <platform/dsp.hpp>
@ -28,6 +29,10 @@ struct DspService : SessionToPort {
DspService(RefCounted<Port> port_, DSPContext& context_) : SessionToPort(port_, context_) {
}
DSPContext& GetContext() {
return static_cast<DSPContext&>(context);
}
void OnRequest(Hypervisor& hypervisor, Thread& thread, Handle session) override {
using namespace Platform::CTR::DSP;

View file

@ -2,6 +2,12 @@
#include "os_hypervisor_private.hpp"
struct AudioFrontend;
namespace Settings {
struct Settings;
}
namespace HLE {
namespace OS {
@ -9,6 +15,8 @@ namespace OS {
namespace HPV {
struct DSPContext : SessionContext {
Settings::Settings* settings = nullptr;
AudioFrontend* frontend = nullptr;
};
HPV::RefCounted<Object> CreateDspService(RefCounted<Port> port, DSPContext&);

View file

@ -63,16 +63,19 @@ std::unique_ptr<Loader::GameCard> LoadGameCard(spdlog::logger& logger, Settings:
}
EmuSession::EmuSession( LogManager& log_manager, Settings::Settings& settings,
VulkanDeviceManager& vulkan_device_manager, EmuDisplay::EmuDisplay& display,
const KeyDatabase& keydb, std::unique_ptr<Loader::GameCard> gamecard)
AudioFrontend& audio, VulkanDeviceManager& vulkan_device_manager,
EmuDisplay::EmuDisplay& display, const KeyDatabase& keydb,
std::unique_ptr<Loader::GameCard> gamecard)
: setup(std::make_shared<Interpreter::Setup>(log_manager, keydb, std::move(gamecard), profiler, debug_server)),
pica { log_manager.RegisterLogger("Pica"), debug_server, settings, setup->mem, profiler,
vulkan_device_manager.physical_device, *vulkan_device_manager.device,
vulkan_device_manager.graphics_queue_index, vulkan_device_manager.graphics_queue } {
setup->cpus[0].cpu.cpsr.mode = ARM::InternalProcessorMode::User;
setup->mem.InjectDependency(audio);
std::unique_ptr<ConsoleModule> os_module;
std::tie(setup->os, os_module) = HLE::OS::OS::Create(settings, *setup, log_manager, profiler, pica, display);
std::tie(setup->os, os_module) = HLE::OS::OS::Create(settings, *setup, log_manager, profiler, audio, pica, display);
for (auto& cpu : setup->cpus)
cpu.os = setup->os.get();
setup->os->Initialize();

View file

@ -9,6 +9,8 @@
#include <framework/profiler.hpp>
struct AudioFrontend;
class NetworkConsole;
namespace Loader {
@ -36,7 +38,7 @@ struct EmuSession {
std::thread console_thread;
EmuSession( LogManager&, Settings::Settings&,
VulkanDeviceManager&, EmuDisplay::EmuDisplay&,
AudioFrontend&, VulkanDeviceManager&, EmuDisplay::EmuDisplay&,
const KeyDatabase&, std::unique_ptr<Loader::GameCard>);
void Run();

View file

@ -0,0 +1,9 @@
#pragma once
#include <array>
#include <cstdint>
struct AudioFrontend {
virtual void OutputSamples(std::array<int16_t, 2> samples) = 0;
};