audio_core: Clean up AAC decoder infrastructure. (#7310)
This commit is contained in:
parent
c6bcbc02de
commit
8e2037b3ff
8 changed files with 63 additions and 146 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
26
src/audio_core/hle/aac_decoder.h
Normal file
26
src/audio_core/hle/aac_decoder.h
Normal 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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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/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;
|
||||||
|
|
Loading…
Reference in a new issue