From b251f84ab102dfbf40ed3e35aecf92003739e14a Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Thu, 28 Nov 2024 17:47:36 +0200 Subject: [PATCH] DSP: Add option to enable/disable AAC --- include/audio/aac_decoder.hpp | 3 ++- include/audio/dsp_core.hpp | 7 +++++-- include/audio/hle_core.hpp | 2 +- include/audio/null_core.hpp | 2 +- include/audio/teakra_core.hpp | 2 +- include/config.hpp | 1 + src/config.cpp | 3 +++ src/core/audio/aac_decoder.cpp | 17 +++++++++++++---- src/core/audio/dsp_core.cpp | 12 ++++++------ src/core/audio/hle_core.cpp | 9 +++++---- src/core/audio/teakra_core.cpp | 4 ++-- src/emulator.cpp | 2 +- src/libretro_core.cpp | 3 +++ 13 files changed, 44 insertions(+), 23 deletions(-) diff --git a/include/audio/aac_decoder.hpp b/include/audio/aac_decoder.hpp index 6538bce9..6197d1db 100644 --- a/include/audio/aac_decoder.hpp +++ b/include/audio/aac_decoder.hpp @@ -18,7 +18,8 @@ namespace Audio::AAC { public: // Decode function. Takes in a reference to the AAC response & request, and a callback for paddr -> pointer conversions - void decode(AAC::Message& response, const AAC::Message& request, PaddrCallback paddrCallback); + // We also allow for optionally muting the AAC output (setting all of it to 0) instead of properly decoding it, for debug/research purposes + void decode(AAC::Message& response, const AAC::Message& request, PaddrCallback paddrCallback, bool enableAudio = false); ~Decoder(); }; } // namespace Audio::AAC \ No newline at end of file diff --git a/include/audio/dsp_core.hpp b/include/audio/dsp_core.hpp index 5f5efa22..f180e717 100644 --- a/include/audio/dsp_core.hpp +++ b/include/audio/dsp_core.hpp @@ -14,6 +14,7 @@ // The DSP core must have access to the DSP service to be able to trigger interrupts properly class DSPService; class Memory; +struct EmulatorConfig; namespace Audio { // There are 160 stereo samples in 1 audio frame, so 320 samples total @@ -31,6 +32,7 @@ namespace Audio { Memory& mem; Scheduler& scheduler; DSPService& dspService; + EmulatorConfig& settings; Samples sampleBuffer; bool audioEnabled = false; @@ -39,7 +41,8 @@ namespace Audio { public: enum class Type { Null, Teakra, HLE }; - DSPCore(Memory& mem, Scheduler& scheduler, DSPService& dspService) : mem(mem), scheduler(scheduler), dspService(dspService) {} + DSPCore(Memory& mem, Scheduler& scheduler, DSPService& dspService, EmulatorConfig& settings) + : mem(mem), scheduler(scheduler), dspService(dspService), settings(settings) {} virtual ~DSPCore() {} virtual void reset() = 0; @@ -62,5 +65,5 @@ namespace Audio { virtual void setAudioEnabled(bool enable) { audioEnabled = enable; } }; - std::unique_ptr makeDSPCore(DSPCore::Type type, Memory& mem, Scheduler& scheduler, DSPService& dspService); + std::unique_ptr makeDSPCore(EmulatorConfig& config, Memory& mem, Scheduler& scheduler, DSPService& dspService); } // namespace Audio \ No newline at end of file diff --git a/include/audio/hle_core.hpp b/include/audio/hle_core.hpp index 32bbaae8..0e3b8636 100644 --- a/include/audio/hle_core.hpp +++ b/include/audio/hle_core.hpp @@ -206,7 +206,7 @@ namespace Audio { SampleBuffer decodeADPCM(const u8* data, usize sampleCount, Source& source); public: - HLE_DSP(Memory& mem, Scheduler& scheduler, DSPService& dspService); + HLE_DSP(Memory& mem, Scheduler& scheduler, DSPService& dspService, EmulatorConfig& config); ~HLE_DSP() override {} void reset() override; diff --git a/include/audio/null_core.hpp b/include/audio/null_core.hpp index 7a0f368d..e7ae12dc 100644 --- a/include/audio/null_core.hpp +++ b/include/audio/null_core.hpp @@ -23,7 +23,7 @@ namespace Audio { bool loaded = false; // Have we loaded a component? public: - NullDSP(Memory& mem, Scheduler& scheduler, DSPService& dspService) : DSPCore(mem, scheduler, dspService) {} + NullDSP(Memory& mem, Scheduler& scheduler, DSPService& dspService, EmulatorConfig& config) : DSPCore(mem, scheduler, dspService, config) {} ~NullDSP() override {} void reset() override; diff --git a/include/audio/teakra_core.hpp b/include/audio/teakra_core.hpp index 17104985..3fd5abc3 100644 --- a/include/audio/teakra_core.hpp +++ b/include/audio/teakra_core.hpp @@ -77,7 +77,7 @@ namespace Audio { } public: - TeakraDSP(Memory& mem, Scheduler& scheduler, DSPService& dspService); + TeakraDSP(Memory& mem, Scheduler& scheduler, DSPService& dspService, EmulatorConfig& config); ~TeakraDSP() override {} void reset() override; diff --git a/include/config.hpp b/include/config.hpp index 81a03385..55fcbe4f 100644 --- a/include/config.hpp +++ b/include/config.hpp @@ -41,6 +41,7 @@ struct EmulatorConfig { bool audioEnabled = false; bool vsyncEnabled = true; + bool aacEnabled = true; // Enable AAC audio? bool enableRenderdoc = false; bool printAppVersion = true; diff --git a/src/config.cpp b/src/config.cpp index 4cd18858..e4fc9a13 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -96,7 +96,9 @@ void EmulatorConfig::load() { auto dspCoreName = toml::find_or(audio, "DSPEmulation", "HLE"); dspType = Audio::DSPCore::typeFromString(dspCoreName); + audioEnabled = toml::find_or(audio, "EnableAudio", false); + aacEnabled = toml::find_or(audio, "EnableAACAudio", true); } } @@ -167,6 +169,7 @@ void EmulatorConfig::save() { data["Audio"]["DSPEmulation"] = std::string(Audio::DSPCore::typeToString(dspType)); data["Audio"]["EnableAudio"] = audioEnabled; + data["Audio"]["EnableAACAudio"] = aacEnabled; data["Battery"]["ChargerPlugged"] = chargerPlugged; data["Battery"]["BatteryPercentage"] = batteryPercentage; diff --git a/src/core/audio/aac_decoder.cpp b/src/core/audio/aac_decoder.cpp index 281539d8..5b9ecee4 100644 --- a/src/core/audio/aac_decoder.cpp +++ b/src/core/audio/aac_decoder.cpp @@ -5,7 +5,7 @@ #include using namespace Audio; -void AAC::Decoder::decode(AAC::Message& response, const AAC::Message& request, AAC::Decoder::PaddrCallback paddrCallback) { +void AAC::Decoder::decode(AAC::Message& response, const AAC::Message& request, AAC::Decoder::PaddrCallback paddrCallback, bool enableAudio) { // Copy the command and mode fields of the request to the response response.command = request.command; response.mode = request.mode; @@ -95,9 +95,18 @@ void AAC::Decoder::decode(AAC::Message& response, const AAC::Message& request, A } } - for (int sample = 0; sample < info->frameSize; sample++) { - for (int stream = 0; stream < channels; stream++) { - audioStreams[stream].push_back(frame[(sample * channels) + stream]); + if (enableAudio) { + for (int sample = 0; sample < info->frameSize; sample++) { + for (int stream = 0; stream < channels; stream++) { + audioStreams[stream].push_back(frame[(sample * channels) + stream]); + } + } + } else { + // If audio is not enabled, push 0s + for (int sample = 0; sample < info->frameSize; sample++) { + for (int stream = 0; stream < channels; stream++) { + audioStreams[stream].push_back(0); + } } } } else { diff --git a/src/core/audio/dsp_core.cpp b/src/core/audio/dsp_core.cpp index 01cee11e..c793fcf8 100644 --- a/src/core/audio/dsp_core.cpp +++ b/src/core/audio/dsp_core.cpp @@ -8,17 +8,17 @@ #include "audio/null_core.hpp" #include "audio/teakra_core.hpp" -std::unique_ptr Audio::makeDSPCore(DSPCore::Type type, Memory& mem, Scheduler& scheduler, DSPService& dspService) { +std::unique_ptr Audio::makeDSPCore(EmulatorConfig& config, Memory& mem, Scheduler& scheduler, DSPService& dspService) { std::unique_ptr core; - switch (type) { - case DSPCore::Type::Null: core = std::make_unique(mem, scheduler, dspService); break; - case DSPCore::Type::Teakra: core = std::make_unique(mem, scheduler, dspService); break; - case DSPCore::Type::HLE: core = std::make_unique(mem, scheduler, dspService); break; + switch (config.dspType) { + case DSPCore::Type::Null: core = std::make_unique(mem, scheduler, dspService, config); break; + case DSPCore::Type::Teakra: core = std::make_unique(mem, scheduler, dspService, config); break; + case DSPCore::Type::HLE: core = std::make_unique(mem, scheduler, dspService, config); break; default: Helpers::warn("Invalid DSP core selected!"); - core = std::make_unique(mem, scheduler, dspService); + core = std::make_unique(mem, scheduler, dspService, config); break; } diff --git a/src/core/audio/hle_core.cpp b/src/core/audio/hle_core.cpp index 7e82a139..ddb893e7 100644 --- a/src/core/audio/hle_core.cpp +++ b/src/core/audio/hle_core.cpp @@ -8,6 +8,7 @@ #include "audio/aac_decoder.hpp" #include "audio/dsp_simd.hpp" +#include "config.hpp" #include "services/dsp.hpp" namespace Audio { @@ -20,7 +21,8 @@ namespace Audio { }; } - HLE_DSP::HLE_DSP(Memory& mem, Scheduler& scheduler, DSPService& dspService) : DSPCore(mem, scheduler, dspService) { + HLE_DSP::HLE_DSP(Memory& mem, Scheduler& scheduler, DSPService& dspService, EmulatorConfig& config) + : DSPCore(mem, scheduler, dspService, config) { // Set up source indices for (int i = 0; i < sources.size(); i++) { sources[i].index = i; @@ -713,9 +715,8 @@ namespace Audio { response.command = request.command; response.mode = request.mode; - // TODO: Make this a toggle in config.toml. Currently we have it on by default. - constexpr bool enableAAC = true; - if (enableAAC) { + // We allow disabling AAC audio. Mostly useful for debugging & figuring out if an audio track is AAC or not. + if (settings.aacEnabled) { aacDecoder->decode(response, request, [this](u32 paddr) { return getPointerPhys(paddr); }); } break; diff --git a/src/core/audio/teakra_core.cpp b/src/core/audio/teakra_core.cpp index da2e5a5a..cf1484f8 100644 --- a/src/core/audio/teakra_core.cpp +++ b/src/core/audio/teakra_core.cpp @@ -36,8 +36,8 @@ struct Dsp1 { Segment segments[10]; }; -TeakraDSP::TeakraDSP(Memory& mem, Scheduler& scheduler, DSPService& dspService) - : DSPCore(mem, scheduler, dspService), pipeBaseAddr(0), running(false) { +TeakraDSP::TeakraDSP(Memory& mem, Scheduler& scheduler, DSPService& dspService, EmulatorConfig& config) + : DSPCore(mem, scheduler, dspService, config), pipeBaseAddr(0), running(false) { // Set up callbacks for Teakra Teakra::AHBMCallback ahbm; diff --git a/src/emulator.cpp b/src/emulator.cpp index 9851adb1..3b91390e 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -28,7 +28,7 @@ Emulator::Emulator() { DSPService& dspService = kernel.getServiceManager().getDSP(); - dsp = Audio::makeDSPCore(config.dspType, memory, scheduler, dspService); + dsp = Audio::makeDSPCore(config, memory, scheduler, dspService); dspService.setDSPCore(dsp.get()); audioDevice.init(dsp->getSamples()); diff --git a/src/libretro_core.cpp b/src/libretro_core.cpp index 319b0a72..23054057 100644 --- a/src/libretro_core.cpp +++ b/src/libretro_core.cpp @@ -172,6 +172,7 @@ static void configInit() { {"panda3ds_use_vsync", "Enable VSync; enabled|disabled"}, {"panda3ds_dsp_emulation", "DSP emulation; HLE|LLE|Null"}, {"panda3ds_use_audio", "Enable audio; disabled|enabled"}, + {"panda3ds_enable_aac", "Enable AAC audio; enabled|disabled"}, {"panda3ds_use_virtual_sd", "Enable virtual SD card; enabled|disabled"}, {"panda3ds_write_protect_virtual_sd", "Write protect virtual SD card; disabled|enabled"}, {"panda3ds_battery_level", "Battery percentage; 5|10|20|30|50|70|90|100"}, @@ -194,6 +195,8 @@ static void configUpdate() { config.batteryPercentage = fetchVariableRange("panda3ds_battery_level", 5, 100); config.dspType = Audio::DSPCore::typeFromString(fetchVariable("panda3ds_dsp_emulation", "null")); config.audioEnabled = fetchVariableBool("panda3ds_use_audio", false); + config.aacEnabled = fetchVariableBool("panda3ds_enable_aac", true); + config.sdCardInserted = fetchVariableBool("panda3ds_use_virtual_sd", true); config.sdWriteProtected = fetchVariableBool("panda3ds_write_protect_virtual_sd", false); config.accurateShaderMul = fetchVariableBool("panda3ds_accurate_shader_mul", false);