audio_core: Clean up AAC decoder infrastructure. (#7310)
This commit is contained in:
		| @@ -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
 | ||||
							
								
								
									
										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 | ||||
|   | ||||
| @@ -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
	
	Block a user
	 Steveice10
					Steveice10