// Copyright 2020 yuzu Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. #pragma once #include #include #include #include "audio_core/common.h" #include "common/common_funcs.h" #include "common/common_types.h" #include "common/swap.h" namespace AudioCore { enum class EffectType : u8 { Invalid = 0, BufferMixer = 1, Aux = 2, Delay = 3, Reverb = 4, I3dl2Reverb = 5, BiquadFilter = 6, }; enum class UsageStatus : u8 { Invalid = 0, New = 1, Initialized = 2, Used = 3, Removed = 4, }; enum class UsageState { Invalid = 0, Initialized = 1, Running = 2, Stopped = 3, }; enum class ParameterStatus : u8 { Initialized = 0, Updating = 1, Updated = 2, }; struct BufferMixerParams { std::array input{}; std::array output{}; std::array volume{}; s32_le count{}; }; static_assert(sizeof(BufferMixerParams) == 0x94, "BufferMixerParams is an invalid size"); struct AuxInfoDSP { u32_le read_offset{}; u32_le write_offset{}; u32_le remaining{}; INSERT_PADDING_WORDS(13); }; static_assert(sizeof(AuxInfoDSP) == 0x40, "AuxInfoDSP is an invalid size"); struct AuxInfo { std::array input_mix_buffers{}; std::array output_mix_buffers{}; u32_le count{}; s32_le sample_rate{}; s32_le sample_count{}; s32_le mix_buffer_count{}; u64_le send_buffer_info{}; u64_le send_buffer_base{}; u64_le return_buffer_info{}; u64_le return_buffer_base{}; }; static_assert(sizeof(AuxInfo) == 0x60, "AuxInfo is an invalid size"); struct I3dl2ReverbParams { std::array input{}; std::array output{}; u16_le max_channels{}; u16_le channel_count{}; INSERT_PADDING_BYTES(1); u32_le sample_rate{}; f32 room_hf{}; f32 hf_reference{}; f32 decay_time{}; f32 hf_decay_ratio{}; f32 room{}; f32 reflection{}; f32 reverb{}; f32 diffusion{}; f32 reflection_delay{}; f32 reverb_delay{}; f32 density{}; f32 dry_gain{}; ParameterStatus status{}; INSERT_PADDING_BYTES(3); }; static_assert(sizeof(I3dl2ReverbParams) == 0x4c, "I3dl2ReverbParams is an invalid size"); struct BiquadFilterParams { std::array input{}; std::array output{}; std::array numerator; std::array denominator; s8 channel_count{}; ParameterStatus status{}; }; static_assert(sizeof(BiquadFilterParams) == 0x18, "BiquadFilterParams is an invalid size"); struct DelayParams { std::array input{}; std::array output{}; u16_le max_channels{}; u16_le channels{}; s32_le max_delay{}; s32_le delay{}; s32_le sample_rate{}; s32_le gain{}; s32_le feedback_gain{}; s32_le out_gain{}; s32_le dry_gain{}; s32_le channel_spread{}; s32_le low_pass{}; ParameterStatus status{}; INSERT_PADDING_BYTES(3); }; static_assert(sizeof(DelayParams) == 0x38, "DelayParams is an invalid size"); struct ReverbParams { std::array input{}; std::array output{}; u16_le max_channels{}; u16_le channels{}; s32_le sample_rate{}; s32_le mode0{}; s32_le mode0_gain{}; s32_le pre_delay{}; s32_le mode1{}; s32_le mode1_gain{}; s32_le decay{}; s32_le hf_decay_ratio{}; s32_le coloration{}; s32_le reverb_gain{}; s32_le out_gain{}; s32_le dry_gain{}; ParameterStatus status{}; INSERT_PADDING_BYTES(3); }; static_assert(sizeof(ReverbParams) == 0x44, "ReverbParams is an invalid size"); class EffectInfo { public: struct InParams { EffectType type{}; u8 is_new{}; u8 is_enabled{}; INSERT_PADDING_BYTES(1); s32_le mix_id{}; u64_le buffer_address{}; u64_le buffer_size{}; s32_le processing_order{}; INSERT_PADDING_BYTES(4); union { std::array raw; }; }; static_assert(sizeof(InParams) == 0xc0, "InParams is an invalid size"); struct OutParams { UsageStatus status{}; INSERT_PADDING_BYTES(15); }; static_assert(sizeof(OutParams) == 0x10, "OutParams is an invalid size"); }; struct AuxAddress { VAddr send_dsp_info{}; VAddr send_buffer_base{}; VAddr return_dsp_info{}; VAddr return_buffer_base{}; }; class EffectBase { public: explicit EffectBase(EffectType effect_type_); virtual ~EffectBase(); virtual void Update(EffectInfo::InParams& in_params) = 0; virtual void UpdateForCommandGeneration() = 0; [[nodiscard]] UsageState GetUsage() const; [[nodiscard]] EffectType GetType() const; [[nodiscard]] bool IsEnabled() const; [[nodiscard]] s32 GetMixID() const; [[nodiscard]] s32 GetProcessingOrder() const; protected: UsageState usage{UsageState::Invalid}; EffectType effect_type{}; s32 mix_id{}; s32 processing_order{}; bool enabled = false; }; template class EffectGeneric : public EffectBase { public: explicit EffectGeneric(EffectType effect_type_) : EffectBase(effect_type_) {} T& GetParams() { return internal_params; } const I3dl2ReverbParams& GetParams() const { return internal_params; } private: T internal_params{}; }; class EffectStubbed : public EffectBase { public: explicit EffectStubbed(); ~EffectStubbed() override; void Update(EffectInfo::InParams& in_params) override; void UpdateForCommandGeneration() override; }; class EffectI3dl2Reverb : public EffectGeneric { public: explicit EffectI3dl2Reverb(); ~EffectI3dl2Reverb() override; void Update(EffectInfo::InParams& in_params) override; void UpdateForCommandGeneration() override; private: bool skipped = false; }; class EffectBiquadFilter : public EffectGeneric { public: explicit EffectBiquadFilter(); ~EffectBiquadFilter() override; void Update(EffectInfo::InParams& in_params) override; void UpdateForCommandGeneration() override; }; class EffectAuxInfo : public EffectGeneric { public: explicit EffectAuxInfo(); ~EffectAuxInfo() override; void Update(EffectInfo::InParams& in_params) override; void UpdateForCommandGeneration() override; [[nodiscard]] VAddr GetSendInfo() const; [[nodiscard]] VAddr GetSendBuffer() const; [[nodiscard]] VAddr GetRecvInfo() const; [[nodiscard]] VAddr GetRecvBuffer() const; private: VAddr send_info{}; VAddr send_buffer{}; VAddr recv_info{}; VAddr recv_buffer{}; bool skipped = false; AuxAddress addresses{}; }; class EffectDelay : public EffectGeneric { public: explicit EffectDelay(); ~EffectDelay() override; void Update(EffectInfo::InParams& in_params) override; void UpdateForCommandGeneration() override; private: bool skipped = false; }; class EffectBufferMixer : public EffectGeneric { public: explicit EffectBufferMixer(); ~EffectBufferMixer() override; void Update(EffectInfo::InParams& in_params) override; void UpdateForCommandGeneration() override; }; class EffectReverb : public EffectGeneric { public: explicit EffectReverb(); ~EffectReverb() override; void Update(EffectInfo::InParams& in_params) override; void UpdateForCommandGeneration() override; private: bool skipped = false; }; class EffectContext { public: explicit EffectContext(std::size_t effect_count_); ~EffectContext(); [[nodiscard]] std::size_t GetCount() const; [[nodiscard]] EffectBase* GetInfo(std::size_t i); [[nodiscard]] EffectBase* RetargetEffect(std::size_t i, EffectType effect); [[nodiscard]] const EffectBase* GetInfo(std::size_t i) const; private: std::size_t effect_count{}; std::vector> effects; }; } // namespace AudioCore