// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include #include #include "audio_core/common/common.h" #include "common/common_types.h" #include "core/hle/service/audio/errors.h" namespace AudioCore::Renderer { /** * Holds host and user revisions, checks whether render features can be enabled, and reports errors. */ class BehaviorInfo { static constexpr u32 MaxErrors = 10; public: struct ErrorInfo { /* 0x00 */ Result error_code{0}; /* 0x04 */ u32 unk_04; /* 0x08 */ CpuAddr address; }; static_assert(sizeof(ErrorInfo) == 0x10, "BehaviorInfo::ErrorInfo has the wrong size!"); struct Flags { u64 IsMemoryForceMappingEnabled : 1; }; struct InParameter { /* 0x00 */ u32 revision; /* 0x08 */ Flags flags; }; static_assert(sizeof(InParameter) == 0x10, "BehaviorInfo::InParameter has the wrong size!"); struct OutStatus { /* 0x00 */ std::array errors; /* 0xA0 */ u32 error_count; /* 0xA4 */ char unkA4[0xC]; }; static_assert(sizeof(OutStatus) == 0xB0, "BehaviorInfo::OutStatus has the wrong size!"); BehaviorInfo(); /** * Get the host revision as a number. * * @return The host revision. */ u32 GetProcessRevisionNum() const; /** * Get the host revision in chars, e.g REV8. * Rev 10 and higher use the ascii characters above 9. * E.g: * Rev 10 = REV: * Rev 11 = REV; * * @return The host revision. */ u32 GetProcessRevision() const; /** * Get the user revision as a number. * * @return The user revision. */ u32 GetUserRevisionNum() const; /** * Get the user revision in chars, e.g REV8. * Rev 10 and higher use the ascii characters above 9. REV: REV; etc. * * @return The user revision. */ u32 GetUserRevision() const; /** * Set the user revision. * * @param user_revision - The user's revision. */ void SetUserLibRevision(u32 user_revision); /** * Clear the current error count. */ void ClearError(); /** * Append an error to the error list. * * @param error - The new error. */ void AppendError(const ErrorInfo& error); /** * Copy errors to the given output container. * * @param out_errors - Output container to receive the errors. * @param out_count - The number of errors written. */ void CopyErrorInfo(std::span out_errors, u32& out_count) const; /** * Update the behaviour flags. * * @param flags - New flags to use. */ void UpdateFlags(Flags flags); /** * Check if memory pools can be forcibly mapped. * * @return True if enabled, otherwise false. */ bool IsMemoryForceMappingEnabled() const; /** * Check if the ADPCM context bug is fixed. * The ADPCM context was not being sent to the AudioRenderer, leading to incorrect scaling being * used. * * @return True if fixed, otherwise false. */ bool IsAdpcmLoopContextBugFixed() const; /** * Check if the splitter is supported. * * @return True if supported, otherwise false. */ bool IsSplitterSupported() const; /** * Check if the splitter bug is fixed. * Update is given the wrong number of splitter destinations, leading to invalid data * being processed. * * @return True if supported, otherwise false. */ bool IsSplitterBugFixed() const; /** * Check if effects version 2 are supported. * This gives support for returning effect states from the AudioRenderer, currently only used * for Limiter statistics. * * @return True if supported, otherwise false. */ bool IsEffectInfoVersion2Supported() const; /** * Check if a variadic command buffer is supported. * As of Rev 5 with the added optional performance metric logging, the command * buffer can be a variable size, so take that into account for calculating its size. * * @return True if supported, otherwise false. */ bool IsVariadicCommandBufferSizeSupported() const; /** * Check if wave buffers version 2 are supported. * See WaveBufferVersion1 and WaveBufferVersion2. * * @return True if supported, otherwise false. */ bool IsWaveBufferVer2Supported() const; /** * Check if long size pre delay is supported. * This allows a longer initial delay time for the Reverb command. * * @return True if supported, otherwise false. */ bool IsLongSizePreDelaySupported() const; /** * Check if the command time estimator version 2 is supported. * * @return True if supported, otherwise false. */ bool IsCommandProcessingTimeEstimatorVersion2Supported() const; /** * Check if the command time estimator version 3 is supported. * * @return True if supported, otherwise false. */ bool IsCommandProcessingTimeEstimatorVersion3Supported() const; /** * Check if the command time estimator version 4 is supported. * * @return True if supported, otherwise false. */ bool IsCommandProcessingTimeEstimatorVersion4Supported() const; /** * Check if the command time estimator version 5 is supported. * * @return True if supported, otherwise false. */ bool IsCommandProcessingTimeEstimatorVersion5Supported() const; /** * Check if the AudioRenderer can use up to 70% of the allocated processing timeslice. * * @return True if supported, otherwise false. */ bool IsAudioRendererProcessingTimeLimit70PercentSupported() const; /** * Check if the AudioRenderer can use up to 75% of the allocated processing timeslice. * * @return True if supported, otherwise false. */ bool IsAudioRendererProcessingTimeLimit75PercentSupported() const; /** * Check if the AudioRenderer can use up to 80% of the allocated processing timeslice. * * @return True if supported, otherwise false. */ bool IsAudioRendererProcessingTimeLimit80PercentSupported() const; /** * Check if voice flushing is supported * This allowws low-priority voices to be dropped if the AudioRenderer is running behind. * * @return True if supported, otherwise false. */ bool IsFlushVoiceWaveBuffersSupported() const; /** * Check if counting the number of elapsed frames is supported. * This adds extra output to RequestUpdate, returning the number of times the AudioRenderer * processed a command list. * * @return True if supported, otherwise false. */ bool IsElapsedFrameCountSupported() const; /** * Check if performance metrics version 2 are supported. * This adds extra output to RequestUpdate, returning the number of times the AudioRenderer * (Unused?). * * @return True if supported, otherwise false. */ bool IsPerformanceMetricsDataFormatVersion2Supported() const; /** * Get the supported performance metrics version. * Version 2 logs some extra fields in output, such as number of voices dropped, * processing start time, if the AudioRenderer exceeded its time, etc. * * @return Version supported, either 1 or 2. */ size_t GetPerformanceMetricsDataFormat() const; /** * Check if skipping voice pitch and sample rate conversion is supported. * This speeds up the data source commands by skipping resampling if unwanted. * See AudioCore::Renderer::DecodeFromWaveBuffers * * @return True if supported, otherwise false. */ bool IsVoicePitchAndSrcSkippedSupported() const; /** * Check if resetting played sample count at loop points is supported. * This resets the number of samples played in a voice state when a loop point is reached. * See AudioCore::Renderer::DecodeFromWaveBuffers * * @return True if supported, otherwise false. */ bool IsVoicePlayedSampleCountResetAtLoopPointSupported() const; /** * Check if the clear state bug for biquad filters is fixed. * The biquad state was not marked as needing re-initialisation when the effect was updated, it * was only initialized once with a new effect. * * @return True if fixed, otherwise false. */ bool IsBiquadFilterEffectStateClearBugFixed() const; /** * Check if Q23 precision is supported for fixed point. * * @return True if supported, otherwise false. */ bool IsVolumeMixParameterPrecisionQ23Supported() const; /** * Check if float processing for biuad filters is supported. * * @return True if supported, otherwise false. */ bool UseBiquadFilterFloatProcessing() const; /** * Check if dirty-only mix updates are supported. * This saves a lot of buffer size as mixes can be large and not change much. * * @return True if supported, otherwise false. */ bool IsMixInParameterDirtyOnlyUpdateSupported() const; /** * Check if multi-tap biquad filters are supported. * * @return True if supported, otherwise false. */ bool UseMultiTapBiquadFilterProcessing() const; /** * Check if device api version 2 is supported. * In the SDK but not in any sysmodule? Not sure, left here for completeness anyway. * * @return True if supported, otherwise false. */ bool IsDeviceApiVersion2Supported() const; /** * Check if new channel mappings are used for Delay commands. * Older commands used: * front left/front right/back left/back right/center/lfe * Whereas everywhere else in the code uses: * front left/front right/center/lfe/back left/back right * This corrects that and makes everything standardised. * * @return True if supported, otherwise false. */ bool IsDelayChannelMappingChanged() const; /** * Check if new channel mappings are used for Reverb commands. * Older commands used: * front left/front right/back left/back right/center/lfe * Whereas everywhere else in the code uses: * front left/front right/center/lfe/back left/back right * This corrects that and makes everything standardised. * * @return True if supported, otherwise false. */ bool IsReverbChannelMappingChanged() const; /** * Check if new channel mappings are used for I3dl2Reverb commands. * Older commands used: * front left/front right/back left/back right/center/lfe * Whereas everywhere else in the code uses: * front left/front right/center/lfe/back left/back right * This corrects that and makes everything standardised. * * @return True if supported, otherwise false. */ bool IsI3dl2ReverbChannelMappingChanged() const; /// Host version u32 process_revision; /// User version u32 user_revision{}; /// Behaviour flags Flags flags{}; /// Errors generated and reported during Update std::array errors{}; /// Error count u32 error_count{}; }; } // namespace AudioCore::Renderer