audio_core: Clean up AAC decoder infrastructure. (#7310)

This commit is contained in:
Steveice10 2024-01-04 11:00:03 -08:00 committed by GitHub
parent c6bcbc02de
commit 8e2037b3ff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 63 additions and 146 deletions

View file

@ -4,11 +4,11 @@ add_library(audio_core STATIC
codec.h codec.h
dsp_interface.cpp dsp_interface.cpp
dsp_interface.h dsp_interface.h
hle/aac_decoder.cpp
hle/aac_decoder.h
hle/common.h hle/common.h
hle/decoder.cpp hle/decoder.cpp
hle/decoder.h hle/decoder.h
hle/faad2_decoder.cpp
hle/faad2_decoder.h
hle/filter.cpp hle/filter.cpp
hle/filter.h hle/filter.h
hle/hle.cpp hle/hle.cpp

View file

@ -3,30 +3,11 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <neaacdec.h> #include <neaacdec.h>
#include "audio_core/hle/faad2_decoder.h" #include "audio_core/hle/aac_decoder.h"
namespace AudioCore::HLE { namespace AudioCore::HLE {
class FAAD2Decoder::Impl { AACDecoder::AACDecoder(Memory::MemorySystem& memory) : memory(memory) {
public:
explicit Impl(Memory::MemorySystem& memory);
~Impl();
std::optional<BinaryMessage> ProcessRequest(const BinaryMessage& request);
bool IsValid() const {
return decoder != nullptr;
}
private:
std::optional<BinaryMessage> Initalize(const BinaryMessage& request);
std::optional<BinaryMessage> Decode(const BinaryMessage& request);
Memory::MemorySystem& memory;
NeAACDecHandle decoder = nullptr;
};
FAAD2Decoder::Impl::Impl(Memory::MemorySystem& memory) : memory(memory) {
decoder = NeAACDecOpen(); decoder = NeAACDecOpen();
if (decoder == nullptr) { if (decoder == nullptr) {
LOG_CRITICAL(Audio_DSP, "Could not open FAAD2 decoder."); LOG_CRITICAL(Audio_DSP, "Could not open FAAD2 decoder.");
@ -46,7 +27,7 @@ FAAD2Decoder::Impl::Impl(Memory::MemorySystem& memory) : memory(memory) {
LOG_INFO(Audio_DSP, "Created FAAD2 AAC decoder."); LOG_INFO(Audio_DSP, "Created FAAD2 AAC decoder.");
} }
FAAD2Decoder::Impl::~Impl() { AACDecoder::~AACDecoder() {
if (decoder) { if (decoder) {
NeAACDecClose(decoder); NeAACDecClose(decoder);
decoder = nullptr; decoder = nullptr;
@ -55,16 +36,23 @@ FAAD2Decoder::Impl::~Impl() {
} }
} }
std::optional<BinaryMessage> FAAD2Decoder::Impl::ProcessRequest(const BinaryMessage& request) { BinaryMessage AACDecoder::ProcessRequest(const BinaryMessage& request) {
if (request.header.codec != DecoderCodec::DecodeAAC) { if (request.header.codec != DecoderCodec::DecodeAAC) {
LOG_ERROR(Audio_DSP, "FAAD2 AAC Decoder cannot handle such codec: {}", LOG_ERROR(Audio_DSP, "AAC decoder received unsupported codec: {}",
static_cast<u16>(request.header.codec)); static_cast<u16>(request.header.codec));
return {}; return {
.header =
{
.result = ResultStatus::Error,
},
};
} }
switch (request.header.cmd) { switch (request.header.cmd) {
case DecoderCommand::Init: { case DecoderCommand::Init: {
return Initalize(request); BinaryMessage response = request;
response.header.result = ResultStatus::Success;
return response;
} }
case DecoderCommand::EncodeDecode: { case DecoderCommand::EncodeDecode: {
return Decode(request); return Decode(request);
@ -72,26 +60,25 @@ std::optional<BinaryMessage> FAAD2Decoder::Impl::ProcessRequest(const BinaryMess
case DecoderCommand::Shutdown: case DecoderCommand::Shutdown:
case DecoderCommand::SaveState: case DecoderCommand::SaveState:
case DecoderCommand::LoadState: { case DecoderCommand::LoadState: {
LOG_WARNING(Audio_DSP, "Got unimplemented binary request: {}", LOG_WARNING(Audio_DSP, "Got unimplemented AAC binary request: {}",
static_cast<u16>(request.header.cmd)); static_cast<u16>(request.header.cmd));
BinaryMessage response = request; BinaryMessage response = request;
response.header.result = ResultStatus::Success; response.header.result = ResultStatus::Success;
return response; return response;
} }
default: default:
LOG_ERROR(Audio_DSP, "Got unknown binary request: {}", LOG_ERROR(Audio_DSP, "Got unknown AAC binary request: {}",
static_cast<u16>(request.header.cmd)); static_cast<u16>(request.header.cmd));
return {}; return {
.header =
{
.result = ResultStatus::Error,
},
};
} }
} }
std::optional<BinaryMessage> FAAD2Decoder::Impl::Initalize(const BinaryMessage& request) { BinaryMessage AACDecoder::Decode(const BinaryMessage& request) {
BinaryMessage response = request;
response.header.result = ResultStatus::Success;
return response;
}
std::optional<BinaryMessage> FAAD2Decoder::Impl::Decode(const BinaryMessage& request) {
BinaryMessage response{}; BinaryMessage response{};
response.header.codec = request.header.codec; response.header.codec = request.header.codec;
response.header.cmd = request.header.cmd; response.header.cmd = request.header.cmd;
@ -101,6 +88,10 @@ std::optional<BinaryMessage> FAAD2Decoder::Impl::Decode(const BinaryMessage& req
response.decode_aac_response.num_channels = 2; response.decode_aac_response.num_channels = 2;
response.decode_aac_response.num_samples = 1024; response.decode_aac_response.num_samples = 1024;
if (decoder == nullptr) {
return response;
}
if (request.decode_aac_request.src_addr < Memory::FCRAM_PADDR || if (request.decode_aac_request.src_addr < Memory::FCRAM_PADDR ||
request.decode_aac_request.src_addr + request.decode_aac_request.size > request.decode_aac_request.src_addr + request.decode_aac_request.size >
Memory::FCRAM_PADDR + Memory::FCRAM_SIZE) { Memory::FCRAM_PADDR + Memory::FCRAM_SIZE) {
@ -171,16 +162,4 @@ std::optional<BinaryMessage> FAAD2Decoder::Impl::Decode(const BinaryMessage& req
return response; return response;
} }
FAAD2Decoder::FAAD2Decoder(Memory::MemorySystem& memory) : impl(std::make_unique<Impl>(memory)) {}
FAAD2Decoder::~FAAD2Decoder() = default;
std::optional<BinaryMessage> FAAD2Decoder::ProcessRequest(const BinaryMessage& request) {
return impl->ProcessRequest(request);
}
bool FAAD2Decoder::IsValid() const {
return impl->IsValid();
}
} // namespace AudioCore::HLE } // namespace AudioCore::HLE

View file

@ -0,0 +1,26 @@
// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "audio_core/hle/decoder.h"
namespace AudioCore::HLE {
using NeAACDecHandle = void*;
class AACDecoder final : public DecoderBase {
public:
explicit AACDecoder(Memory::MemorySystem& memory);
~AACDecoder() override;
BinaryMessage ProcessRequest(const BinaryMessage& request) override;
private:
BinaryMessage Decode(const BinaryMessage& request);
Memory::MemorySystem& memory;
NeAACDecHandle decoder = nullptr;
};
} // namespace AudioCore::HLE

View file

@ -32,34 +32,4 @@ DecoderSampleRate GetSampleRateEnum(u32 sample_rate) {
} }
} }
DecoderBase::~DecoderBase(){};
NullDecoder::NullDecoder() = default;
NullDecoder::~NullDecoder() = default;
std::optional<BinaryMessage> NullDecoder::ProcessRequest(const BinaryMessage& request) {
BinaryMessage response{};
switch (request.header.cmd) {
case DecoderCommand::Init:
case DecoderCommand::Shutdown:
case DecoderCommand::SaveState:
case DecoderCommand::LoadState:
response = request;
response.header.result = ResultStatus::Success;
return response;
case DecoderCommand::EncodeDecode:
response.header.codec = request.header.codec;
response.header.cmd = request.header.cmd;
response.header.result = ResultStatus::Success;
response.decode_aac_response.num_channels = 2; // Just assume stereo here
response.decode_aac_response.size = request.decode_aac_request.size;
response.decode_aac_response.num_samples = 1024; // Just assume 1024 here
return response;
default:
LOG_ERROR(Audio_DSP, "Got unknown binary request: {}",
static_cast<u16>(request.header.cmd));
return std::nullopt;
}
};
} // namespace AudioCore::HLE } // namespace AudioCore::HLE

View file

@ -135,21 +135,8 @@ enum_le<DecoderSampleRate> GetSampleRateEnum(u32 sample_rate);
class DecoderBase { class DecoderBase {
public: public:
virtual ~DecoderBase(); virtual ~DecoderBase() = default;
virtual std::optional<BinaryMessage> ProcessRequest(const BinaryMessage& request) = 0; virtual BinaryMessage ProcessRequest(const BinaryMessage& request) = 0;
/// Return true if this Decoder can be loaded. Return false if the system cannot create the
/// decoder
virtual bool IsValid() const = 0;
};
class NullDecoder final : public DecoderBase {
public:
NullDecoder();
~NullDecoder() override;
std::optional<BinaryMessage> ProcessRequest(const BinaryMessage& request) override;
bool IsValid() const override {
return true;
}
}; };
} // namespace AudioCore::HLE } // namespace AudioCore::HLE

View file

@ -1,23 +0,0 @@
// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "audio_core/hle/decoder.h"
namespace AudioCore::HLE {
class FAAD2Decoder final : public DecoderBase {
public:
explicit FAAD2Decoder(Memory::MemorySystem& memory);
~FAAD2Decoder() override;
std::optional<BinaryMessage> ProcessRequest(const BinaryMessage& request) override;
bool IsValid() const override;
private:
class Impl;
std::unique_ptr<Impl> impl;
};
} // namespace AudioCore::HLE

View file

@ -8,9 +8,9 @@
#include <boost/serialization/vector.hpp> #include <boost/serialization/vector.hpp>
#include <boost/serialization/weak_ptr.hpp> #include <boost/serialization/weak_ptr.hpp>
#include "audio_core/audio_types.h" #include "audio_core/audio_types.h"
#include "audio_core/hle/aac_decoder.h"
#include "audio_core/hle/common.h" #include "audio_core/hle/common.h"
#include "audio_core/hle/decoder.h" #include "audio_core/hle/decoder.h"
#include "audio_core/hle/faad2_decoder.h"
#include "audio_core/hle/hle.h" #include "audio_core/hle/hle.h"
#include "audio_core/hle/mixers.h" #include "audio_core/hle/mixers.h"
#include "audio_core/hle/shared_memory.h" #include "audio_core/hle/shared_memory.h"
@ -98,7 +98,7 @@ private:
Core::Timing& core_timing; Core::Timing& core_timing;
Core::TimingEventType* tick_event{}; Core::TimingEventType* tick_event{};
std::unique_ptr<HLE::DecoderBase> decoder{}; std::unique_ptr<HLE::DecoderBase> aac_decoder{};
std::function<void(Service::DSP::InterruptType type, DspPipe pipe)> interrupt_handler{}; std::function<void(Service::DSP::InterruptType type, DspPipe pipe)> interrupt_handler{};
@ -114,13 +114,6 @@ private:
friend class boost::serialization::access; friend class boost::serialization::access;
}; };
static std::vector<std::function<std::unique_ptr<HLE::DecoderBase>(Memory::MemorySystem&)>>
decoder_backends = {
[](Memory::MemorySystem& memory) -> std::unique_ptr<HLE::DecoderBase> {
return std::make_unique<HLE::FAAD2Decoder>(memory);
},
};
DspHle::Impl::Impl(DspHle& parent_, Memory::MemorySystem& memory, Core::Timing& timing) DspHle::Impl::Impl(DspHle& parent_, Memory::MemorySystem& memory, Core::Timing& timing)
: parent(parent_), core_timing(timing) { : parent(parent_), core_timing(timing) {
dsp_memory.raw_memory.fill(0); dsp_memory.raw_memory.fill(0);
@ -129,19 +122,7 @@ DspHle::Impl::Impl(DspHle& parent_, Memory::MemorySystem& memory, Core::Timing&
source.SetMemory(memory); source.SetMemory(memory);
} }
for (auto& factory : decoder_backends) { aac_decoder = std::make_unique<HLE::AACDecoder>(memory);
decoder = factory(memory);
if (decoder && decoder->IsValid()) {
break;
}
}
if (!decoder || !decoder->IsValid()) {
LOG_WARNING(Audio_DSP,
"Unable to load any decoders, this could cause missing audio in some games");
decoder = std::make_unique<HLE::NullDecoder>();
}
tick_event = tick_event =
core_timing.RegisterEvent("AudioCore::DspHle::tick_event", [this](u64, s64 cycles_late) { core_timing.RegisterEvent("AudioCore::DspHle::tick_event", [this](u64, s64 cycles_late) {
this->AudioTickCallback(cycles_late); this->AudioTickCallback(cycles_late);
@ -291,12 +272,9 @@ void DspHle::Impl::PipeWrite(DspPipe pipe_number, std::span<const u8> buffer) {
UNIMPLEMENTED(); UNIMPLEMENTED();
return; return;
} }
std::optional<HLE::BinaryMessage> response = decoder->ProcessRequest(request); const HLE::BinaryMessage response = aac_decoder->ProcessRequest(request);
if (response) { pipe_data[static_cast<u32>(pipe_number)].resize(sizeof(response));
const HLE::BinaryMessage& value = *response; std::memcpy(pipe_data[static_cast<u32>(pipe_number)].data(), &response, sizeof(response));
pipe_data[static_cast<u32>(pipe_number)].resize(sizeof(value));
std::memcpy(pipe_data[static_cast<u32>(pipe_number)].data(), &value, sizeof(value));
}
interrupt_handler(InterruptType::Pipe, DspPipe::Binary); interrupt_handler(InterruptType::Pipe, DspPipe::Binary);
break; break;