diff options
Diffstat (limited to 'src/audio_core/renderer/command/command_generator.h')
-rw-r--r-- | src/audio_core/renderer/command/command_generator.h | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/src/audio_core/renderer/command/command_generator.h b/src/audio_core/renderer/command/command_generator.h new file mode 100644 index 000000000..d80d9b0d8 --- /dev/null +++ b/src/audio_core/renderer/command/command_generator.h @@ -0,0 +1,349 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <span> + +#include "audio_core/renderer/command/commands.h" +#include "audio_core/renderer/performance/performance_manager.h" +#include "common/common_types.h" + +namespace AudioCore { +struct AudioRendererSystemContext; + +namespace AudioRenderer { +class CommandBuffer; +struct CommandListHeader; +class VoiceContext; +class MixContext; +class EffectContext; +class SplitterContext; +class SinkContext; +class BehaviorInfo; +class VoiceInfo; +struct VoiceState; +class MixInfo; +class SinkInfoBase; + +/** + * Generates all commands to build up a command list, which are sent to the AudioRender for + * processing. + */ +class CommandGenerator { +public: + explicit CommandGenerator(CommandBuffer& command_buffer, + const CommandListHeader& command_list_header, + const AudioRendererSystemContext& render_context, + VoiceContext& voice_context, MixContext& mix_context, + EffectContext& effect_context, SinkContext& sink_context, + SplitterContext& splitter_context, + PerformanceManager* performance_manager); + + /** + * Calculate the buffer size needed for commands. + * + * @param behavior - Used to check what features are enabled. + * @param params - Input rendering parameters for numbers of voices/mixes/sinks etc. + */ + static u64 CalculateCommandBufferSize(const BehaviorInfo& behavior, + const AudioRendererParameterInternal& params) { + u64 size{0}; + + // Effects + size += params.effects * sizeof(EffectInfoBase); + + // Voices + u64 voice_size{0}; + if (behavior.IsWaveBufferVer2Supported()) { + voice_size = std::max(std::max(sizeof(AdpcmDataSourceVersion2Command), + sizeof(PcmInt16DataSourceVersion2Command)), + sizeof(PcmFloatDataSourceVersion2Command)); + } else { + voice_size = std::max(std::max(sizeof(AdpcmDataSourceVersion1Command), + sizeof(PcmInt16DataSourceVersion1Command)), + sizeof(PcmFloatDataSourceVersion1Command)); + } + voice_size += sizeof(BiquadFilterCommand) * MaxBiquadFilters; + voice_size += sizeof(VolumeRampCommand); + voice_size += sizeof(MixRampGroupedCommand); + + size += params.voices * (params.splitter_infos * sizeof(DepopPrepareCommand) + voice_size); + + // Sub mixes + size += sizeof(DepopForMixBuffersCommand) + + (sizeof(MixCommand) * MaxMixBuffers) * MaxMixBuffers; + + // Final mix + size += sizeof(DepopForMixBuffersCommand) + sizeof(VolumeCommand) * MaxMixBuffers; + + // Splitters + size += params.splitter_destinations * sizeof(MixRampCommand) * MaxMixBuffers; + + // Sinks + size += + params.sinks * std::max(sizeof(DeviceSinkCommand), sizeof(CircularBufferSinkCommand)); + + // Performance + size += (params.effects + params.voices + params.sinks + params.sub_mixes + 1 + + PerformanceManager::MaxDetailEntries) * + sizeof(PerformanceCommand); + return size; + } + + /** + * Get the current command buffer used to generate commands. + * + * @return The command buffer. + */ + CommandBuffer& GetCommandBuffer() { + return command_buffer; + } + + /** + * Get the current performance manager, + * + * @return The performance manager. May be nullptr. + */ + PerformanceManager* GetPerformanceManager() { + return performance_manager; + } + + /** + * Generate a data source command. + * These are the basis for all audio output. + * + * @param voice_info - Generate the command from this voice. + * @param voice_state - State used by the AudioRenderer across calls. + * @param channel - Channel index to generate the command into. + */ + void GenerateDataSourceCommand(VoiceInfo& voice_info, const VoiceState& voice_state, + s8 channel); + + /** + * Generate voice mixing commands. + * These are used to mix buffers together, to mix one input to many outputs, + * and also used as copy commands to move data around and prevent it being accidentally + * overwritten, e.g by another data source command into the same channel. + * + * @param mix_volumes - Current volumes of the mix. + * @param prev_mix_volumes - Previous volumes of the mix. + * @param voice_state - State used by the AudioRenderer across calls. + * @param output_index - Output mix buffer index. + * @param buffer_count - Number of active mix buffers. + * @param input_index - Input mix buffer index. + * @param node_id - Node id of the voice this command is generated for. + */ + void GenerateVoiceMixCommand(std::span<const f32> mix_volumes, + std::span<const f32> prev_mix_volumes, + const VoiceState& voice_state, s16 output_index, s16 buffer_count, + s16 input_index, s32 node_id); + + /** + * Generate a biquad filter command for a voice. + * + * @param voice_info - Voice info this command is generated from. + * @param voice_state - State used by the AudioRenderer across calls. + * @param buffer_count - Number of active mix buffers. + * @param channel - Channel index of this command. + * @param node_id - Node id of the voice this command is generated for. + */ + void GenerateBiquadFilterCommandForVoice(VoiceInfo& voice_info, const VoiceState& voice_state, + s16 buffer_count, s8 channel, s32 node_id); + + /** + * Generate commands for a voice. + * Includes a data source, biquad filter, volume and mixing. + * + * @param voice_info - Voice info these commands are generated from. + */ + void GenerateVoiceCommand(VoiceInfo& voice_info); + + /** + * Generate commands for all voices. + */ + void GenerateVoiceCommands(); + + /** + * Generate a mixing command. + * + * @param buffer_offset - Base mix buffer offset to use. + * @param effect_info_base - BufferMixer effect info. + * @param node_id - Node id of the mix this command is generated for. + */ + void GenerateBufferMixerCommand(s16 buffer_offset, EffectInfoBase& effect_info_base, + s32 node_id); + + /** + * Generate a delay effect command. + * + * @param buffer_offset - Base mix buffer offset to use. + * @param effect_info_base - Delay effect info. + * @param node_id - Node id of the mix this command is generated for. + */ + void GenerateDelayCommand(s16 buffer_offset, EffectInfoBase& effect_info_base, s32 node_id); + + /** + * Generate a reverb effect command. + * + * @param buffer_offset - Base mix buffer offset to use. + * @param effect_info_base - Reverb effect info. + * @param node_id - Node id of the mix this command is generated for. + * @param long_size_pre_delay_supported - Use a longer pre-delay time before reverb starts. + */ + void GenerateReverbCommand(s16 buffer_offset, EffectInfoBase& effect_info_base, s32 node_id, + bool long_size_pre_delay_supported); + + /** + * Generate an I3DL2 reverb effect command. + * + * @param buffer_offset - Base mix buffer offset to use. + * @param effect_info_base - I3DL2Reverb effect info. + * @param node_id - Node id of the mix this command is generated for. + */ + void GenerateI3dl2ReverbEffectCommand(s16 buffer_offset, EffectInfoBase& effect_info, + s32 node_id); + + /** + * Generate an aux effect command. + * + * @param buffer_offset - Base mix buffer offset to use. + * @param effect_info_base - Aux effect info. + * @param node_id - Node id of the mix this command is generated for. + */ + void GenerateAuxCommand(s16 buffer_offset, EffectInfoBase& effect_info, s32 node_id); + + /** + * Generate a biquad filter effect command. + * + * @param buffer_offset - Base mix buffer offset to use. + * @param effect_info_base - Aux effect info. + * @param node_id - Node id of the mix this command is generated for. + */ + void GenerateBiquadFilterEffectCommand(s16 buffer_offset, EffectInfoBase& effect_info, + s32 node_id); + + /** + * Generate a light limiter effect command. + * + * @param buffer_offset - Base mix buffer offset to use. + * @param effect_info_base - Limiter effect info. + * @param node_id - Node id of the mix this command is generated for. + * @param effect_index - Index for the statistics state. + */ + void GenerateLightLimiterEffectCommand(s16 buffer_offset, EffectInfoBase& effect_info, + s32 node_id, u32 effect_index); + + /** + * Generate a capture effect command. + * Writes a mix buffer back to game memory. + * + * @param buffer_offset - Base mix buffer offset to use. + * @param effect_info_base - Capture effect info. + * @param node_id - Node id of the mix this command is generated for. + */ + void GenerateCaptureCommand(s16 buffer_offset, EffectInfoBase& effect_info, s32 node_id); + + /** + * Generate a compressor effect command. + * + * @param buffer_offset - Base mix buffer offset to use. + * @param effect_info_base - Compressor effect info. + * @param node_id - Node id of the mix this command is generated for. + */ + void GenerateCompressorCommand(const s16 buffer_offset, EffectInfoBase& effect_info, + const s32 node_id); + + /** + * Generate all effect commands for a mix. + * + * @param mix_info - Mix to generate effects from. + */ + void GenerateEffectCommand(MixInfo& mix_info); + + /** + * Generate all mix commands. + * + * @param mix_info - Mix to generate effects from. + */ + void GenerateMixCommands(MixInfo& mix_info); + + /** + * Generate a submix command. + * Generates all effects and all mixing commands. + * + * @param mix_info - Mix to generate effects from. + */ + void GenerateSubMixCommand(MixInfo& mix_info); + + /** + * Generate all submix command. + */ + void GenerateSubMixCommands(); + + /** + * Generate the final mix. + */ + void GenerateFinalMixCommand(); + + /** + * Generate the final mix commands. + */ + void GenerateFinalMixCommands(); + + /** + * Generate all sink commands. + */ + void GenerateSinkCommands(); + + /** + * Generate a sink command. + * Sends samples out to the backend, or a game-supplied circular buffer. + * + * @param buffer_offset - Base mix buffer offset to use. + * @param sink_info - Sink info to generate the commands from. + */ + void GenerateSinkCommand(s16 buffer_offset, SinkInfoBase& sink_info); + + /** + * Generate a device sink command. + * Sends samples out to the backend. + * + * @param buffer_offset - Base mix buffer offset to use. + * @param sink_info - Sink info to generate the commands from. + */ + void GenerateDeviceSinkCommand(s16 buffer_offset, SinkInfoBase& sink_info); + + /** + * Generate a performance command. + * Used to report performance metrics of the AudioRenderer back to the game. + * + * @param buffer_offset - Base mix buffer offset to use. + * @param sink_info - Sink info to generate the commands from. + */ + void GeneratePerformanceCommand(s32 node_id, PerformanceState state, + const PerformanceEntryAddresses& entry_addresses); + +private: + /// Commands will be written by this buffer + CommandBuffer& command_buffer; + /// Header information for the commands generated + const CommandListHeader& command_header; + /// Various things to control generation + const AudioRendererSystemContext& render_context; + /// Used for generating voices + VoiceContext& voice_context; + /// Used for generating mixes + MixContext& mix_context; + /// Used for generating effects + EffectContext& effect_context; + /// Used for generating sinks + SinkContext& sink_context; + /// Used for generating submixes + SplitterContext& splitter_context; + /// Used for generating performance + PerformanceManager* performance_manager; +}; + +} // namespace AudioRenderer +} // namespace AudioCore |