audio_core: Clean up AAC decoder infrastructure. (#7310)
This commit is contained in:
parent
c6bcbc02de
commit
8e2037b3ff
|
@ -4,11 +4,11 @@ add_library(audio_core STATIC
|
|||
codec.h
|
||||
dsp_interface.cpp
|
||||
dsp_interface.h
|
||||
hle/aac_decoder.cpp
|
||||
hle/aac_decoder.h
|
||||
hle/common.h
|
||||
hle/decoder.cpp
|
||||
hle/decoder.h
|
||||
hle/faad2_decoder.cpp
|
||||
hle/faad2_decoder.h
|
||||
hle/filter.cpp
|
||||
hle/filter.h
|
||||
hle/hle.cpp
|
||||
|
|
|
@ -3,30 +3,11 @@
|
|||
// Refer to the license.txt file included.
|
||||
|
||||
#include <neaacdec.h>
|
||||
#include "audio_core/hle/faad2_decoder.h"
|
||||
#include "audio_core/hle/aac_decoder.h"
|
||||
|
||||
namespace AudioCore::HLE {
|
||||
|
||||
class FAAD2Decoder::Impl {
|
||||
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) {
|
||||
AACDecoder::AACDecoder(Memory::MemorySystem& memory) : memory(memory) {
|
||||
decoder = NeAACDecOpen();
|
||||
if (decoder == nullptr) {
|
||||
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.");
|
||||
}
|
||||
|
||||
FAAD2Decoder::Impl::~Impl() {
|
||||
AACDecoder::~AACDecoder() {
|
||||
if (decoder) {
|
||||
NeAACDecClose(decoder);
|
||||
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) {
|
||||
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));
|
||||
return {};
|
||||
return {
|
||||
.header =
|
||||
{
|
||||
.result = ResultStatus::Error,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
switch (request.header.cmd) {
|
||||
case DecoderCommand::Init: {
|
||||
return Initalize(request);
|
||||
BinaryMessage response = request;
|
||||
response.header.result = ResultStatus::Success;
|
||||
return response;
|
||||
}
|
||||
case DecoderCommand::EncodeDecode: {
|
||||
return Decode(request);
|
||||
|
@ -72,26 +60,25 @@ std::optional<BinaryMessage> FAAD2Decoder::Impl::ProcessRequest(const BinaryMess
|
|||
case DecoderCommand::Shutdown:
|
||||
case DecoderCommand::SaveState:
|
||||
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));
|
||||
BinaryMessage response = request;
|
||||
response.header.result = ResultStatus::Success;
|
||||
return response;
|
||||
}
|
||||
default:
|
||||
LOG_ERROR(Audio_DSP, "Got unknown binary request: {}",
|
||||
LOG_ERROR(Audio_DSP, "Got unknown AAC binary request: {}",
|
||||
static_cast<u16>(request.header.cmd));
|
||||
return {};
|
||||
return {
|
||||
.header =
|
||||
{
|
||||
.result = ResultStatus::Error,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<BinaryMessage> FAAD2Decoder::Impl::Initalize(const BinaryMessage& request) {
|
||||
BinaryMessage response = request;
|
||||
response.header.result = ResultStatus::Success;
|
||||
return response;
|
||||
}
|
||||
|
||||
std::optional<BinaryMessage> FAAD2Decoder::Impl::Decode(const BinaryMessage& request) {
|
||||
BinaryMessage AACDecoder::Decode(const BinaryMessage& request) {
|
||||
BinaryMessage response{};
|
||||
response.header.codec = request.header.codec;
|
||||
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_samples = 1024;
|
||||
|
||||
if (decoder == nullptr) {
|
||||
return response;
|
||||
}
|
||||
|
||||
if (request.decode_aac_request.src_addr < Memory::FCRAM_PADDR ||
|
||||
request.decode_aac_request.src_addr + request.decode_aac_request.size >
|
||||
Memory::FCRAM_PADDR + Memory::FCRAM_SIZE) {
|
||||
|
@ -171,16 +162,4 @@ std::optional<BinaryMessage> FAAD2Decoder::Impl::Decode(const BinaryMessage& req
|
|||
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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -135,21 +135,8 @@ enum_le<DecoderSampleRate> GetSampleRateEnum(u32 sample_rate);
|
|||
|
||||
class DecoderBase {
|
||||
public:
|
||||
virtual ~DecoderBase();
|
||||
virtual std::optional<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;
|
||||
}
|
||||
virtual ~DecoderBase() = default;
|
||||
virtual BinaryMessage ProcessRequest(const BinaryMessage& request) = 0;
|
||||
};
|
||||
|
||||
} // namespace AudioCore::HLE
|
||||
|
|
|
@ -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
|
|
@ -8,9 +8,9 @@
|
|||
#include <boost/serialization/vector.hpp>
|
||||
#include <boost/serialization/weak_ptr.hpp>
|
||||
#include "audio_core/audio_types.h"
|
||||
#include "audio_core/hle/aac_decoder.h"
|
||||
#include "audio_core/hle/common.h"
|
||||
#include "audio_core/hle/decoder.h"
|
||||
#include "audio_core/hle/faad2_decoder.h"
|
||||
#include "audio_core/hle/hle.h"
|
||||
#include "audio_core/hle/mixers.h"
|
||||
#include "audio_core/hle/shared_memory.h"
|
||||
|
@ -98,7 +98,7 @@ private:
|
|||
Core::Timing& core_timing;
|
||||
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{};
|
||||
|
||||
|
@ -114,13 +114,6 @@ private:
|
|||
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)
|
||||
: parent(parent_), core_timing(timing) {
|
||||
dsp_memory.raw_memory.fill(0);
|
||||
|
@ -129,19 +122,7 @@ DspHle::Impl::Impl(DspHle& parent_, Memory::MemorySystem& memory, Core::Timing&
|
|||
source.SetMemory(memory);
|
||||
}
|
||||
|
||||
for (auto& factory : decoder_backends) {
|
||||
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>();
|
||||
}
|
||||
|
||||
aac_decoder = std::make_unique<HLE::AACDecoder>(memory);
|
||||
tick_event =
|
||||
core_timing.RegisterEvent("AudioCore::DspHle::tick_event", [this](u64, s64 cycles_late) {
|
||||
this->AudioTickCallback(cycles_late);
|
||||
|
@ -291,12 +272,9 @@ void DspHle::Impl::PipeWrite(DspPipe pipe_number, std::span<const u8> buffer) {
|
|||
UNIMPLEMENTED();
|
||||
return;
|
||||
}
|
||||
std::optional<HLE::BinaryMessage> response = decoder->ProcessRequest(request);
|
||||
if (response) {
|
||||
const HLE::BinaryMessage& value = *response;
|
||||
pipe_data[static_cast<u32>(pipe_number)].resize(sizeof(value));
|
||||
std::memcpy(pipe_data[static_cast<u32>(pipe_number)].data(), &value, sizeof(value));
|
||||
}
|
||||
const HLE::BinaryMessage response = aac_decoder->ProcessRequest(request);
|
||||
pipe_data[static_cast<u32>(pipe_number)].resize(sizeof(response));
|
||||
std::memcpy(pipe_data[static_cast<u32>(pipe_number)].data(), &response, sizeof(response));
|
||||
|
||||
interrupt_handler(InterruptType::Pipe, DspPipe::Binary);
|
||||
break;
|
||||
|
|
Reference in New Issue