// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include #include #include #include "common/assert.h" #include "common/common_funcs.h" #include "common/common_types.h" #include namespace AudioCore { constexpr u32 CurrentRevision = 15; constexpr u32 NativeCurrentRevision = 16; constexpr bool IsNativeRevision(u32 revision) { return (revision & 0xffffff) == Common::MakeMagic('R', 'E', 'v', '\0'); } constexpr u32 EncodeRevision(u32 revision, bool native) { return Common::MakeMagic('R', 'E', native ? 'v' : 'V', static_cast('0' + revision)); } enum class SupportTags { CommandProcessingTimeEstimatorVersion4, CommandProcessingTimeEstimatorVersion3, CommandProcessingTimeEstimatorVersion2, MultiTapBiquadFilterProcessing, EffectInfoVer2, WaveBufferVer2, BiquadFilterFloatProcessing, VolumeMixParameterPrecisionQ23, MixInParameterDirtyOnlyUpdate, BiquadFilterEffectStateClearBugFix, VoicePlayedSampleCountResetAtLoopPoint, VoicePitchAndSrcSkipped, SplitterBugFix, FlushVoiceWaveBuffers, ElapsedFrameCount, AudioRendererVariadicCommandBufferSize, PerformanceMetricsDataFormatVersion2, AudioRendererProcessingTimeLimit80Percent, AudioRendererProcessingTimeLimit75Percent, AudioRendererProcessingTimeLimit70Percent, AdpcmLoopContextBugFix, Splitter, LongSizePreDelay, AudioUsbDeviceOutput, DeviceApiVersion2, DelayChannelMappingChange, ReverbChannelMappingChange, I3dl2ReverbChannelMappingChange, SplitterPrevVolumeReset, SplitterBiquadFilterParameter, SplitterDestinationV2b, VoiceInParameterV2, // Not a real tag, just here to get the count. Size }; constexpr u32 GetRevisionNum(u32 user_revision) { if (user_revision < 0x100) { return user_revision; } if (!IsNativeRevision(user_revision) && (user_revision & 0xffffff) != Common::MakeMagic('R', 'E', 'V', '\0')) { return ~u32{0}; } const u32 encoded = user_revision >> 24; return encoded >= '0' ? encoded - '0' : ~u32{0}; }; constexpr bool CheckFeatureSupported(SupportTags tag, u32 user_revision) { constexpr std::array, static_cast(SupportTags::Size)> features{ { {SupportTags::AudioRendererProcessingTimeLimit70Percent, 1}, {SupportTags::Splitter, 2}, {SupportTags::AdpcmLoopContextBugFix, 2}, {SupportTags::LongSizePreDelay, 3}, {SupportTags::AudioUsbDeviceOutput, 4}, {SupportTags::AudioRendererProcessingTimeLimit75Percent, 4}, {SupportTags::VoicePlayedSampleCountResetAtLoopPoint, 5}, {SupportTags::VoicePitchAndSrcSkipped, 5}, {SupportTags::SplitterBugFix, 5}, {SupportTags::FlushVoiceWaveBuffers, 5}, {SupportTags::ElapsedFrameCount, 5}, {SupportTags::AudioRendererProcessingTimeLimit80Percent, 5}, {SupportTags::AudioRendererVariadicCommandBufferSize, 5}, {SupportTags::PerformanceMetricsDataFormatVersion2, 5}, {SupportTags::CommandProcessingTimeEstimatorVersion2, 5}, {SupportTags::BiquadFilterEffectStateClearBugFix, 6}, {SupportTags::BiquadFilterFloatProcessing, 7}, {SupportTags::VolumeMixParameterPrecisionQ23, 7}, {SupportTags::MixInParameterDirtyOnlyUpdate, 7}, {SupportTags::WaveBufferVer2, 8}, {SupportTags::CommandProcessingTimeEstimatorVersion3, 8}, {SupportTags::EffectInfoVer2, 9}, {SupportTags::CommandProcessingTimeEstimatorVersion4, 10}, {SupportTags::MultiTapBiquadFilterProcessing, 10}, {SupportTags::DelayChannelMappingChange, 11}, {SupportTags::ReverbChannelMappingChange, 11}, {SupportTags::I3dl2ReverbChannelMappingChange, 11}, {SupportTags::SplitterBiquadFilterParameter, 12}, {SupportTags::SplitterPrevVolumeReset, 13}, {SupportTags::SplitterDestinationV2b, 15}, {SupportTags::VoiceInParameterV2, 15}, }}; const auto& feature = std::ranges::find_if(features, [tag](const auto& entry) { return entry.first == tag; }); if (feature == features.cend()) { LOG_ERROR(Service_Audio, "Invalid SupportTag {}!", static_cast(tag)); return false; } user_revision = GetRevisionNum(user_revision); return user_revision != ~u32{0} && (*feature).second <= user_revision; } constexpr bool CheckValidRevision(u32 user_revision) { return GetRevisionNum(user_revision) <= (IsNativeRevision(user_revision) ? NativeCurrentRevision : CurrentRevision); }; } // namespace AudioCore