// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include #include #include #include "audio_core/renderer/behavior/behavior_info.h" #include "audio_core/renderer/command/command_processing_time_estimator.h" #include "audio_core/renderer/effect/effect_context.h" #include "audio_core/renderer/memory/memory_pool_info.h" #include "audio_core/renderer/mix/mix_context.h" #include "audio_core/renderer/performance/performance_manager.h" #include "audio_core/renderer/sink/sink_context.h" #include "audio_core/renderer/splitter/splitter_context.h" #include "audio_core/renderer/upsampler/upsampler_manager.h" #include "audio_core/renderer/voice/voice_context.h" #include "common/thread.h" #include "core/hle/service/audio/errors.h" namespace Core { namespace Memory { class Memory; } class System; } // namespace Core namespace Kernel { class KEvent; class KTransferMemory; } // namespace Kernel namespace AudioCore { struct AudioRendererParameterInternal; namespace ADSP { class ADSP; namespace AudioRenderer { class AudioRenderer; } } // namespace ADSP namespace Renderer { using namespace ::AudioCore::ADSP; class CommandBuffer; /** * Audio Renderer System, the main worker for audio rendering. */ class System { enum class State { Started = 0, Stopped = 2, }; public: explicit System(Core::System& core, Kernel::KEvent* adsp_rendered_event); /** * Calculate the total size required for all audio render workbuffers. * * @param params - Input parameters with the numbers of voices/mixes/sinks/etc. * @return Size (in bytes) required for the audio renderer. */ static u64 GetWorkBufferSize(const AudioRendererParameterInternal& params); /** * Initialize the renderer system. * Allocates workbuffers and initializes everything to a default state, ready to receive a * RequestUpdate. * * @param params - Input parameters to initialize the system with. * @param transfer_memory - Game-supplied memory for all workbuffers. Unused. * @param transfer_memory_size - Size of the transfer memory. Unused. * @param process_handle - Process handle, also used for memory. Unused. * @param applet_resource_user_id - Applet id for this renderer. Unused. * @param session_id - Session id of this renderer. * @return Result code. */ Result Initialize(const AudioRendererParameterInternal& params, Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, u32 process_handle, u64 applet_resource_user_id, s32 session_id); /** * Finalize the system. */ void Finalize(); /** * Start the system. */ void Start(); /** * Stop the system. */ void Stop(); /** * Update the system. * * @param input - Inout buffer containing the update data. * @param performance - Optional buffer for writing back performance metrics. * @param output - Output information from rendering. * @return Result code. */ Result Update(std::span input, std::span performance, std::span output); /** * Get the time limit (percent) for rendering * * @return Time limit as a percent. */ u32 GetRenderingTimeLimit() const; /** * Set the time limit (percent) for rendering * * @param limit - New time limit. */ void SetRenderingTimeLimit(u32 limit); /** * Get the session id for this system. * * @return Session id of this system. */ u32 GetSessionId() const; /** * Get the sample rate of this system. * * @return Sample rate of this system. */ u32 GetSampleRate() const; /** * Get the sample count of this system. * * @return Sample count of this system. */ u32 GetSampleCount() const; /** * Get the number of mix buffers for this system. * * @return Number of mix buffers in the system. */ u32 GetMixBufferCount() const; /** * Get the execution mode of this system. * Note: Only Auto is implemented. * * @return Execution mode for this system. */ ExecutionMode GetExecutionMode() const; /** * Get the rendering device for this system. * This is unused. * * @return Rendering device for this system. */ u32 GetRenderingDevice() const; /** * Check if this system is currently active. * * @return True if active, otherwise false. */ bool IsActive() const; /** * Prepare and generate a list of commands for the AudioRenderer based on current state, * signalling the buffer event when all processed. */ void SendCommandToDsp(); /** * Generate a list of commands for the AudioRenderer based on current state. * * @param command_buffer - Buffer for commands to be written to. * @param command_buffer_size - Size of the command_buffer. * * @return Number of bytes written. */ u64 GenerateCommand(std::span command_buffer, u64 command_buffer_size); /** * Try to drop some voices if the AudioRenderer fell behind. * * @param command_buffer - Command buffer to drop voices from. * @param estimated_process_time - Current estimated processing time of all commands. * @param time_limit - Time limit for rendering, voices are dropped if estimated * exceeds this. * * @return Number of voices dropped. */ u32 DropVoices(CommandBuffer& command_buffer, u32 estimated_process_time, u32 time_limit); /** * Get the current voice drop parameter. * * @return The current voice drop. */ f32 GetVoiceDropParameter() const; /** * Set the voice drop parameter. * * @param The new voice drop. */ void SetVoiceDropParameter(f32 voice_drop); private: /// Core system Core::System& core; /// Reference to the ADSP's AudioRenderer for communication ::AudioCore::ADSP::AudioRenderer::AudioRenderer& audio_renderer; /// Is this system initialized? bool initialized{}; /// Is this system currently active? std::atomic active{}; /// State of the system State state{State::Stopped}; /// Sample rate for the system u32 sample_rate{}; /// Sample count of the system u32 sample_count{}; /// Number of mix buffers in use by the system s16 mix_buffer_count{}; /// Workbuffer for mix buffers, used by the AudioRenderer std::span samples_workbuffer{}; /// Depop samples for depopping commands std::span depop_buffer{}; /// Number of memory pools in the buffer u32 memory_pool_count{}; /// Workbuffer for memory pools std::span memory_pool_workbuffer{}; /// System memory pool info MemoryPoolInfo memory_pool_info{}; /// Workbuffer that commands will be generated into std::span command_workbuffer{}; /// Size of command workbuffer u64 command_workbuffer_size{}; /// Number of commands in the workbuffer u64 command_buffer_size{}; /// Manager for upsamplers UpsamplerManager* upsampler_manager{}; /// Upsampler workbuffer std::span upsampler_infos{}; /// Number of upsamplers in the workbuffer u32 upsampler_count{}; /// Holds and controls all voices VoiceContext voice_context{}; /// Holds and controls all mixes MixContext mix_context{}; /// Holds and controls all effects EffectContext effect_context{}; /// Holds and controls all sinks SinkContext sink_context{}; /// Holds and controls all splitters SplitterContext splitter_context{}; /// Estimates the time taken for each command std::unique_ptr command_processing_time_estimator{}; /// Session id of this system s32 session_id{}; /// Number of channels in use by voices s32 voice_channels{}; /// Event to be called when the AudioRenderer processes a command list Kernel::KEvent* adsp_rendered_event{}; /// Event signalled on system terminate Common::Event terminate_event{}; /// Does what locks do std::mutex lock{}; /// Handle for the process for this system, unused u32 process_handle{}; /// Applet resource id for this system, unused u64 applet_resource_user_id{}; /// Controls performance input and output PerformanceManager performance_manager{}; /// Workbuffer for performance metrics std::span performance_workbuffer{}; /// Main workbuffer, from which all other workbuffers here allocate into std::unique_ptr workbuffer{}; /// Size of the main workbuffer u64 workbuffer_size{}; /// Unknown buffer/marker std::span unk_2A8{}; /// Size of the above unknown buffer/marker u64 unk_2B0{}; /// Rendering time limit (percent) u32 render_time_limit_percent{}; /// Should any voices be dropped? bool drop_voice{}; /// Should the backend stream have its buffers flushed? bool reset_command_buffers{}; /// Execution mode of this system, only Auto is supported ExecutionMode execution_mode{ExecutionMode::Auto}; /// Render device, unused u32 render_device{}; /// Behaviour to check which features are supported by the user revision BehaviorInfo behavior{}; /// Total ticks the audio system has been running u64 total_ticks_elapsed{}; /// Ticks the system has spent in updates u64 ticks_spent_updating{}; /// Number of times a command list was generated u64 num_command_lists_generated{}; /// Number of times the system has updated u64 num_times_updated{}; /// Number of frames generated, written back to the game std::atomic frames_elapsed{}; /// Is the AudioRenderer running too slow? bool adsp_behind{}; /// Number of voices dropped u32 num_voices_dropped{}; /// Tick that rendering started u64 render_start_tick{}; /// Parameter to control the threshold for dropping voices if the audio graph gets too large f32 drop_voice_param{1.0f}; }; } // namespace Renderer } // namespace AudioCore