diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/audio_core/renderer/system.cpp | 85 | ||||
| -rw-r--r-- | src/audio_core/renderer/system.h | 16 | ||||
| -rw-r--r-- | src/audio_core/renderer/voice/voice_context.cpp | 4 | ||||
| -rw-r--r-- | src/common/concepts.h | 8 | ||||
| -rw-r--r-- | src/common/fixed_point.h | 187 | ||||
| -rw-r--r-- | src/core/hle/service/audio/audctl.cpp | 16 | ||||
| -rw-r--r-- | src/core/hle/service/audio/audren_u.cpp | 26 | ||||
| -rw-r--r-- | src/yuzu/applets/qt_controller.ui | 2 |
8 files changed, 195 insertions, 149 deletions
diff --git a/src/audio_core/renderer/system.cpp b/src/audio_core/renderer/system.cpp index bde794cd1..4fac30c7c 100644 --- a/src/audio_core/renderer/system.cpp +++ b/src/audio_core/renderer/system.cpp | |||
| @@ -98,9 +98,8 @@ System::System(Core::System& core_, Kernel::KEvent* adsp_rendered_event_) | |||
| 98 | : core{core_}, adsp{core.AudioCore().GetADSP()}, adsp_rendered_event{adsp_rendered_event_} {} | 98 | : core{core_}, adsp{core.AudioCore().GetADSP()}, adsp_rendered_event{adsp_rendered_event_} {} |
| 99 | 99 | ||
| 100 | Result System::Initialize(const AudioRendererParameterInternal& params, | 100 | Result System::Initialize(const AudioRendererParameterInternal& params, |
| 101 | Kernel::KTransferMemory* transfer_memory, const u64 transfer_memory_size, | 101 | Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, |
| 102 | const u32 process_handle_, const u64 applet_resource_user_id_, | 102 | u32 process_handle_, u64 applet_resource_user_id_, s32 session_id_) { |
| 103 | const s32 session_id_) { | ||
| 104 | if (!CheckValidRevision(params.revision)) { | 103 | if (!CheckValidRevision(params.revision)) { |
| 105 | return Service::Audio::ERR_INVALID_REVISION; | 104 | return Service::Audio::ERR_INVALID_REVISION; |
| 106 | } | 105 | } |
| @@ -354,6 +353,8 @@ Result System::Initialize(const AudioRendererParameterInternal& params, | |||
| 354 | 353 | ||
| 355 | render_time_limit_percent = 100; | 354 | render_time_limit_percent = 100; |
| 356 | drop_voice = params.voice_drop_enabled && params.execution_mode == ExecutionMode::Auto; | 355 | drop_voice = params.voice_drop_enabled && params.execution_mode == ExecutionMode::Auto; |
| 356 | drop_voice_param = 1.0f; | ||
| 357 | num_voices_dropped = 0; | ||
| 357 | 358 | ||
| 358 | allocator.Align(0x40); | 359 | allocator.Align(0x40); |
| 359 | command_workbuffer_size = allocator.GetRemainingSize(); | 360 | command_workbuffer_size = allocator.GetRemainingSize(); |
| @@ -547,7 +548,7 @@ u32 System::GetRenderingTimeLimit() const { | |||
| 547 | return render_time_limit_percent; | 548 | return render_time_limit_percent; |
| 548 | } | 549 | } |
| 549 | 550 | ||
| 550 | void System::SetRenderingTimeLimit(const u32 limit) { | 551 | void System::SetRenderingTimeLimit(u32 limit) { |
| 551 | render_time_limit_percent = limit; | 552 | render_time_limit_percent = limit; |
| 552 | } | 553 | } |
| 553 | 554 | ||
| @@ -635,7 +636,7 @@ void System::SendCommandToDsp() { | |||
| 635 | } | 636 | } |
| 636 | 637 | ||
| 637 | u64 System::GenerateCommand(std::span<u8> in_command_buffer, | 638 | u64 System::GenerateCommand(std::span<u8> in_command_buffer, |
| 638 | [[maybe_unused]] const u64 command_buffer_size_) { | 639 | [[maybe_unused]] u64 command_buffer_size_) { |
| 639 | PoolMapper::ClearUseState(memory_pool_workbuffer, memory_pool_count); | 640 | PoolMapper::ClearUseState(memory_pool_workbuffer, memory_pool_count); |
| 640 | const auto start_time{core.CoreTiming().GetClockTicks()}; | 641 | const auto start_time{core.CoreTiming().GetClockTicks()}; |
| 641 | 642 | ||
| @@ -693,7 +694,8 @@ u64 System::GenerateCommand(std::span<u8> in_command_buffer, | |||
| 693 | 694 | ||
| 694 | voice_context.SortInfo(); | 695 | voice_context.SortInfo(); |
| 695 | 696 | ||
| 696 | const auto start_estimated_time{command_buffer.estimated_process_time}; | 697 | const auto start_estimated_time{drop_voice_param * |
| 698 | static_cast<f32>(command_buffer.estimated_process_time)}; | ||
| 697 | 699 | ||
| 698 | command_generator.GenerateVoiceCommands(); | 700 | command_generator.GenerateVoiceCommands(); |
| 699 | command_generator.GenerateSubMixCommands(); | 701 | command_generator.GenerateSubMixCommands(); |
| @@ -712,11 +714,16 @@ u64 System::GenerateCommand(std::span<u8> in_command_buffer, | |||
| 712 | render_context.behavior->IsAudioRendererProcessingTimeLimit70PercentSupported(); | 714 | render_context.behavior->IsAudioRendererProcessingTimeLimit70PercentSupported(); |
| 713 | time_limit_percent = 70.0f; | 715 | time_limit_percent = 70.0f; |
| 714 | } | 716 | } |
| 717 | |||
| 718 | const auto end_estimated_time{drop_voice_param * | ||
| 719 | static_cast<f32>(command_buffer.estimated_process_time)}; | ||
| 720 | const auto estimated_time{start_estimated_time - end_estimated_time}; | ||
| 721 | |||
| 715 | const auto time_limit{static_cast<u32>( | 722 | const auto time_limit{static_cast<u32>( |
| 716 | static_cast<f32>(start_estimated_time - command_buffer.estimated_process_time) + | 723 | estimated_time + (((time_limit_percent / 100.0f) * 2'880'000.0) * |
| 717 | (((time_limit_percent / 100.0f) * 2'880'000.0) * | 724 | (static_cast<f32>(render_time_limit_percent) / 100.0f)))}; |
| 718 | (static_cast<f32>(render_time_limit_percent) / 100.0f)))}; | 725 | num_voices_dropped = |
| 719 | num_voices_dropped = DropVoices(command_buffer, start_estimated_time, time_limit); | 726 | DropVoices(command_buffer, static_cast<u32>(start_estimated_time), time_limit); |
| 720 | } | 727 | } |
| 721 | 728 | ||
| 722 | command_list_header->buffer_size = command_buffer.size; | 729 | command_list_header->buffer_size = command_buffer.size; |
| @@ -737,24 +744,33 @@ u64 System::GenerateCommand(std::span<u8> in_command_buffer, | |||
| 737 | return command_buffer.size; | 744 | return command_buffer.size; |
| 738 | } | 745 | } |
| 739 | 746 | ||
| 740 | u32 System::DropVoices(CommandBuffer& command_buffer, const u32 estimated_process_time, | 747 | f32 System::GetVoiceDropParameter() const { |
| 741 | const u32 time_limit) { | 748 | return drop_voice_param; |
| 749 | } | ||
| 750 | |||
| 751 | void System::SetVoiceDropParameter(f32 voice_drop_) { | ||
| 752 | drop_voice_param = voice_drop_; | ||
| 753 | } | ||
| 754 | |||
| 755 | u32 System::DropVoices(CommandBuffer& command_buffer, u32 estimated_process_time, u32 time_limit) { | ||
| 742 | u32 i{0}; | 756 | u32 i{0}; |
| 743 | auto command_list{command_buffer.command_list.data() + sizeof(CommandListHeader)}; | 757 | auto command_list{command_buffer.command_list.data() + sizeof(CommandListHeader)}; |
| 744 | ICommand* cmd{}; | 758 | ICommand* cmd{nullptr}; |
| 745 | 759 | ||
| 746 | for (; i < command_buffer.count; i++) { | 760 | // Find a first valid voice to drop |
| 761 | while (i < command_buffer.count) { | ||
| 747 | cmd = reinterpret_cast<ICommand*>(command_list); | 762 | cmd = reinterpret_cast<ICommand*>(command_list); |
| 748 | if (cmd->type != CommandId::Performance && | 763 | if (cmd->type == CommandId::Performance || |
| 749 | cmd->type != CommandId::DataSourcePcmInt16Version1 && | 764 | cmd->type == CommandId::DataSourcePcmInt16Version1 || |
| 750 | cmd->type != CommandId::DataSourcePcmInt16Version2 && | 765 | cmd->type == CommandId::DataSourcePcmInt16Version2 || |
| 751 | cmd->type != CommandId::DataSourcePcmFloatVersion1 && | 766 | cmd->type == CommandId::DataSourcePcmFloatVersion1 || |
| 752 | cmd->type != CommandId::DataSourcePcmFloatVersion2 && | 767 | cmd->type == CommandId::DataSourcePcmFloatVersion2 || |
| 753 | cmd->type != CommandId::DataSourceAdpcmVersion1 && | 768 | cmd->type == CommandId::DataSourceAdpcmVersion1 || |
| 754 | cmd->type != CommandId::DataSourceAdpcmVersion2) { | 769 | cmd->type == CommandId::DataSourceAdpcmVersion2) { |
| 755 | break; | 770 | break; |
| 756 | } | 771 | } |
| 757 | command_list += cmd->size; | 772 | command_list += cmd->size; |
| 773 | i++; | ||
| 758 | } | 774 | } |
| 759 | 775 | ||
| 760 | if (cmd == nullptr || command_buffer.count == 0 || i >= command_buffer.count) { | 776 | if (cmd == nullptr || command_buffer.count == 0 || i >= command_buffer.count) { |
| @@ -767,6 +783,7 @@ u32 System::DropVoices(CommandBuffer& command_buffer, const u32 estimated_proces | |||
| 767 | const auto node_id_type{cmd->node_id >> 28}; | 783 | const auto node_id_type{cmd->node_id >> 28}; |
| 768 | const auto node_id_base{cmd->node_id & 0xFFF}; | 784 | const auto node_id_base{cmd->node_id & 0xFFF}; |
| 769 | 785 | ||
| 786 | // If the new estimated process time falls below the limit, we're done dropping. | ||
| 770 | if (estimated_process_time <= time_limit) { | 787 | if (estimated_process_time <= time_limit) { |
| 771 | break; | 788 | break; |
| 772 | } | 789 | } |
| @@ -775,6 +792,7 @@ u32 System::DropVoices(CommandBuffer& command_buffer, const u32 estimated_proces | |||
| 775 | break; | 792 | break; |
| 776 | } | 793 | } |
| 777 | 794 | ||
| 795 | // Don't drop voices marked with the highest priority. | ||
| 778 | auto& voice_info{voice_context.GetInfo(node_id_base)}; | 796 | auto& voice_info{voice_context.GetInfo(node_id_base)}; |
| 779 | if (voice_info.priority == HighestVoicePriority) { | 797 | if (voice_info.priority == HighestVoicePriority) { |
| 780 | break; | 798 | break; |
| @@ -783,18 +801,23 @@ u32 System::DropVoices(CommandBuffer& command_buffer, const u32 estimated_proces | |||
| 783 | voices_dropped++; | 801 | voices_dropped++; |
| 784 | voice_info.voice_dropped = true; | 802 | voice_info.voice_dropped = true; |
| 785 | 803 | ||
| 786 | if (i < command_buffer.count) { | 804 | // First iteration should drop the voice, and then iterate through all of the commands tied |
| 787 | while (cmd->node_id == node_id) { | 805 | // to the voice. We don't need reverb on a voice which we've just removed, for example. |
| 788 | if (cmd->type == CommandId::DepopPrepare) { | 806 | // Depops can't be removed otherwise we'll introduce audio popping, and we don't |
| 789 | cmd->enabled = true; | 807 | // remove perf commands. Lower the estimated time for each command dropped. |
| 790 | } else if (cmd->type == CommandId::Performance || !cmd->enabled) { | 808 | while (i < command_buffer.count && cmd->node_id == node_id) { |
| 791 | cmd->enabled = false; | 809 | if (cmd->type == CommandId::DepopPrepare) { |
| 792 | } | 810 | cmd->enabled = true; |
| 793 | i++; | 811 | } else if (cmd->enabled && cmd->type != CommandId::Performance) { |
| 794 | command_list += cmd->size; | 812 | cmd->enabled = false; |
| 795 | cmd = reinterpret_cast<ICommand*>(command_list); | 813 | estimated_process_time -= static_cast<u32>( |
| 814 | drop_voice_param * static_cast<f32>(cmd->estimated_process_time)); | ||
| 796 | } | 815 | } |
| 816 | command_list += cmd->size; | ||
| 817 | cmd = reinterpret_cast<ICommand*>(command_list); | ||
| 818 | i++; | ||
| 797 | } | 819 | } |
| 820 | i++; | ||
| 798 | } | 821 | } |
| 799 | return voices_dropped; | 822 | return voices_dropped; |
| 800 | } | 823 | } |
diff --git a/src/audio_core/renderer/system.h b/src/audio_core/renderer/system.h index bcbe65b07..429196e41 100644 --- a/src/audio_core/renderer/system.h +++ b/src/audio_core/renderer/system.h | |||
| @@ -196,6 +196,20 @@ public: | |||
| 196 | */ | 196 | */ |
| 197 | u32 DropVoices(CommandBuffer& command_buffer, u32 estimated_process_time, u32 time_limit); | 197 | u32 DropVoices(CommandBuffer& command_buffer, u32 estimated_process_time, u32 time_limit); |
| 198 | 198 | ||
| 199 | /** | ||
| 200 | * Get the current voice drop parameter. | ||
| 201 | * | ||
| 202 | * @return The current voice drop. | ||
| 203 | */ | ||
| 204 | f32 GetVoiceDropParameter() const; | ||
| 205 | |||
| 206 | /** | ||
| 207 | * Set the voice drop parameter. | ||
| 208 | * | ||
| 209 | * @param The new voice drop. | ||
| 210 | */ | ||
| 211 | void SetVoiceDropParameter(f32 voice_drop); | ||
| 212 | |||
| 199 | private: | 213 | private: |
| 200 | /// Core system | 214 | /// Core system |
| 201 | Core::System& core; | 215 | Core::System& core; |
| @@ -301,6 +315,8 @@ private: | |||
| 301 | u32 num_voices_dropped{}; | 315 | u32 num_voices_dropped{}; |
| 302 | /// Tick that rendering started | 316 | /// Tick that rendering started |
| 303 | u64 render_start_tick{}; | 317 | u64 render_start_tick{}; |
| 318 | /// Parameter to control the threshold for dropping voices if the audio graph gets too large | ||
| 319 | f32 drop_voice_param{1.0f}; | ||
| 304 | }; | 320 | }; |
| 305 | 321 | ||
| 306 | } // namespace AudioRenderer | 322 | } // namespace AudioRenderer |
diff --git a/src/audio_core/renderer/voice/voice_context.cpp b/src/audio_core/renderer/voice/voice_context.cpp index eafb51b01..a501a677d 100644 --- a/src/audio_core/renderer/voice/voice_context.cpp +++ b/src/audio_core/renderer/voice/voice_context.cpp | |||
| @@ -74,8 +74,8 @@ void VoiceContext::SortInfo() { | |||
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | std::ranges::sort(sorted_voice_info, [](const VoiceInfo* a, const VoiceInfo* b) { | 76 | std::ranges::sort(sorted_voice_info, [](const VoiceInfo* a, const VoiceInfo* b) { |
| 77 | return a->priority != b->priority ? a->priority < b->priority | 77 | return a->priority != b->priority ? a->priority > b->priority |
| 78 | : a->sort_order < b->sort_order; | 78 | : a->sort_order > b->sort_order; |
| 79 | }); | 79 | }); |
| 80 | } | 80 | } |
| 81 | 81 | ||
diff --git a/src/common/concepts.h b/src/common/concepts.h index a97555f6a..e8ce30dfe 100644 --- a/src/common/concepts.h +++ b/src/common/concepts.h | |||
| @@ -34,4 +34,12 @@ concept DerivedFrom = requires { | |||
| 34 | template <typename From, typename To> | 34 | template <typename From, typename To> |
| 35 | concept ConvertibleTo = std::is_convertible_v<From, To>; | 35 | concept ConvertibleTo = std::is_convertible_v<From, To>; |
| 36 | 36 | ||
| 37 | // No equivalents in the stdlib | ||
| 38 | |||
| 39 | template <typename T> | ||
| 40 | concept IsArithmetic = std::is_arithmetic_v<T>; | ||
| 41 | |||
| 42 | template <typename T> | ||
| 43 | concept IsIntegral = std::is_integral_v<T>; | ||
| 44 | |||
| 37 | } // namespace Common | 45 | } // namespace Common |
diff --git a/src/common/fixed_point.h b/src/common/fixed_point.h index 6eb6afe2f..f899b0d54 100644 --- a/src/common/fixed_point.h +++ b/src/common/fixed_point.h | |||
| @@ -12,6 +12,8 @@ | |||
| 12 | #include <ostream> | 12 | #include <ostream> |
| 13 | #include <type_traits> | 13 | #include <type_traits> |
| 14 | 14 | ||
| 15 | #include <common/concepts.h> | ||
| 16 | |||
| 15 | namespace Common { | 17 | namespace Common { |
| 16 | 18 | ||
| 17 | template <size_t I, size_t F> | 19 | template <size_t I, size_t F> |
| @@ -50,8 +52,8 @@ struct type_from_size<64> { | |||
| 50 | static constexpr size_t size = 64; | 52 | static constexpr size_t size = 64; |
| 51 | 53 | ||
| 52 | using value_type = int64_t; | 54 | using value_type = int64_t; |
| 53 | using unsigned_type = std::make_unsigned<value_type>::type; | 55 | using unsigned_type = std::make_unsigned_t<value_type>; |
| 54 | using signed_type = std::make_signed<value_type>::type; | 56 | using signed_type = std::make_signed_t<value_type>; |
| 55 | using next_size = type_from_size<128>; | 57 | using next_size = type_from_size<128>; |
| 56 | }; | 58 | }; |
| 57 | 59 | ||
| @@ -61,8 +63,8 @@ struct type_from_size<32> { | |||
| 61 | static constexpr size_t size = 32; | 63 | static constexpr size_t size = 32; |
| 62 | 64 | ||
| 63 | using value_type = int32_t; | 65 | using value_type = int32_t; |
| 64 | using unsigned_type = std::make_unsigned<value_type>::type; | 66 | using unsigned_type = std::make_unsigned_t<value_type>; |
| 65 | using signed_type = std::make_signed<value_type>::type; | 67 | using signed_type = std::make_signed_t<value_type>; |
| 66 | using next_size = type_from_size<64>; | 68 | using next_size = type_from_size<64>; |
| 67 | }; | 69 | }; |
| 68 | 70 | ||
| @@ -72,8 +74,8 @@ struct type_from_size<16> { | |||
| 72 | static constexpr size_t size = 16; | 74 | static constexpr size_t size = 16; |
| 73 | 75 | ||
| 74 | using value_type = int16_t; | 76 | using value_type = int16_t; |
| 75 | using unsigned_type = std::make_unsigned<value_type>::type; | 77 | using unsigned_type = std::make_unsigned_t<value_type>; |
| 76 | using signed_type = std::make_signed<value_type>::type; | 78 | using signed_type = std::make_signed_t<value_type>; |
| 77 | using next_size = type_from_size<32>; | 79 | using next_size = type_from_size<32>; |
| 78 | }; | 80 | }; |
| 79 | 81 | ||
| @@ -83,8 +85,8 @@ struct type_from_size<8> { | |||
| 83 | static constexpr size_t size = 8; | 85 | static constexpr size_t size = 8; |
| 84 | 86 | ||
| 85 | using value_type = int8_t; | 87 | using value_type = int8_t; |
| 86 | using unsigned_type = std::make_unsigned<value_type>::type; | 88 | using unsigned_type = std::make_unsigned_t<value_type>; |
| 87 | using signed_type = std::make_signed<value_type>::type; | 89 | using signed_type = std::make_signed_t<value_type>; |
| 88 | using next_size = type_from_size<16>; | 90 | using next_size = type_from_size<16>; |
| 89 | }; | 91 | }; |
| 90 | 92 | ||
| @@ -101,7 +103,7 @@ struct divide_by_zero : std::exception {}; | |||
| 101 | template <size_t I, size_t F> | 103 | template <size_t I, size_t F> |
| 102 | constexpr FixedPoint<I, F> divide( | 104 | constexpr FixedPoint<I, F> divide( |
| 103 | FixedPoint<I, F> numerator, FixedPoint<I, F> denominator, FixedPoint<I, F>& remainder, | 105 | FixedPoint<I, F> numerator, FixedPoint<I, F> denominator, FixedPoint<I, F>& remainder, |
| 104 | typename std::enable_if<type_from_size<I + F>::next_size::is_specialized>::type* = nullptr) { | 106 | std::enable_if_t<type_from_size<I + F>::next_size::is_specialized>* = nullptr) { |
| 105 | 107 | ||
| 106 | using next_type = typename FixedPoint<I, F>::next_type; | 108 | using next_type = typename FixedPoint<I, F>::next_type; |
| 107 | using base_type = typename FixedPoint<I, F>::base_type; | 109 | using base_type = typename FixedPoint<I, F>::base_type; |
| @@ -121,7 +123,7 @@ constexpr FixedPoint<I, F> divide( | |||
| 121 | template <size_t I, size_t F> | 123 | template <size_t I, size_t F> |
| 122 | constexpr FixedPoint<I, F> divide( | 124 | constexpr FixedPoint<I, F> divide( |
| 123 | FixedPoint<I, F> numerator, FixedPoint<I, F> denominator, FixedPoint<I, F>& remainder, | 125 | FixedPoint<I, F> numerator, FixedPoint<I, F> denominator, FixedPoint<I, F>& remainder, |
| 124 | typename std::enable_if<!type_from_size<I + F>::next_size::is_specialized>::type* = nullptr) { | 126 | std::enable_if_t<!type_from_size<I + F>::next_size::is_specialized>* = nullptr) { |
| 125 | 127 | ||
| 126 | using unsigned_type = typename FixedPoint<I, F>::unsigned_type; | 128 | using unsigned_type = typename FixedPoint<I, F>::unsigned_type; |
| 127 | 129 | ||
| @@ -191,7 +193,7 @@ constexpr FixedPoint<I, F> divide( | |||
| 191 | template <size_t I, size_t F> | 193 | template <size_t I, size_t F> |
| 192 | constexpr FixedPoint<I, F> multiply( | 194 | constexpr FixedPoint<I, F> multiply( |
| 193 | FixedPoint<I, F> lhs, FixedPoint<I, F> rhs, | 195 | FixedPoint<I, F> lhs, FixedPoint<I, F> rhs, |
| 194 | typename std::enable_if<type_from_size<I + F>::next_size::is_specialized>::type* = nullptr) { | 196 | std::enable_if_t<type_from_size<I + F>::next_size::is_specialized>* = nullptr) { |
| 195 | 197 | ||
| 196 | using next_type = typename FixedPoint<I, F>::next_type; | 198 | using next_type = typename FixedPoint<I, F>::next_type; |
| 197 | using base_type = typename FixedPoint<I, F>::base_type; | 199 | using base_type = typename FixedPoint<I, F>::base_type; |
| @@ -210,7 +212,7 @@ constexpr FixedPoint<I, F> multiply( | |||
| 210 | template <size_t I, size_t F> | 212 | template <size_t I, size_t F> |
| 211 | constexpr FixedPoint<I, F> multiply( | 213 | constexpr FixedPoint<I, F> multiply( |
| 212 | FixedPoint<I, F> lhs, FixedPoint<I, F> rhs, | 214 | FixedPoint<I, F> lhs, FixedPoint<I, F> rhs, |
| 213 | typename std::enable_if<!type_from_size<I + F>::next_size::is_specialized>::type* = nullptr) { | 215 | std::enable_if_t<!type_from_size<I + F>::next_size::is_specialized>* = nullptr) { |
| 214 | 216 | ||
| 215 | using base_type = typename FixedPoint<I, F>::base_type; | 217 | using base_type = typename FixedPoint<I, F>::base_type; |
| 216 | 218 | ||
| @@ -265,15 +267,16 @@ public: | |||
| 265 | static constexpr base_type one = base_type(1) << fractional_bits; | 267 | static constexpr base_type one = base_type(1) << fractional_bits; |
| 266 | 268 | ||
| 267 | public: // constructors | 269 | public: // constructors |
| 268 | FixedPoint() = default; | 270 | constexpr FixedPoint() = default; |
| 269 | FixedPoint(const FixedPoint&) = default; | 271 | |
| 270 | FixedPoint(FixedPoint&&) = default; | 272 | constexpr FixedPoint(const FixedPoint&) = default; |
| 271 | FixedPoint& operator=(const FixedPoint&) = default; | 273 | constexpr FixedPoint& operator=(const FixedPoint&) = default; |
| 272 | 274 | ||
| 273 | template <class Number> | 275 | constexpr FixedPoint(FixedPoint&&) noexcept = default; |
| 274 | constexpr FixedPoint( | 276 | constexpr FixedPoint& operator=(FixedPoint&&) noexcept = default; |
| 275 | Number n, typename std::enable_if<std::is_arithmetic<Number>::value>::type* = nullptr) | 277 | |
| 276 | : data_(static_cast<base_type>(n * one)) {} | 278 | template <IsArithmetic Number> |
| 279 | constexpr FixedPoint(Number n) : data_(static_cast<base_type>(n * one)) {} | ||
| 277 | 280 | ||
| 278 | public: // conversion | 281 | public: // conversion |
| 279 | template <size_t I2, size_t F2> | 282 | template <size_t I2, size_t F2> |
| @@ -301,36 +304,14 @@ public: | |||
| 301 | } | 304 | } |
| 302 | 305 | ||
| 303 | public: // comparison operators | 306 | public: // comparison operators |
| 304 | constexpr bool operator==(FixedPoint rhs) const { | 307 | friend constexpr auto operator<=>(FixedPoint lhs, FixedPoint rhs) = default; |
| 305 | return data_ == rhs.data_; | ||
| 306 | } | ||
| 307 | |||
| 308 | constexpr bool operator!=(FixedPoint rhs) const { | ||
| 309 | return data_ != rhs.data_; | ||
| 310 | } | ||
| 311 | |||
| 312 | constexpr bool operator<(FixedPoint rhs) const { | ||
| 313 | return data_ < rhs.data_; | ||
| 314 | } | ||
| 315 | |||
| 316 | constexpr bool operator>(FixedPoint rhs) const { | ||
| 317 | return data_ > rhs.data_; | ||
| 318 | } | ||
| 319 | |||
| 320 | constexpr bool operator<=(FixedPoint rhs) const { | ||
| 321 | return data_ <= rhs.data_; | ||
| 322 | } | ||
| 323 | |||
| 324 | constexpr bool operator>=(FixedPoint rhs) const { | ||
| 325 | return data_ >= rhs.data_; | ||
| 326 | } | ||
| 327 | 308 | ||
| 328 | public: // unary operators | 309 | public: // unary operators |
| 329 | constexpr bool operator!() const { | 310 | [[nodiscard]] constexpr bool operator!() const { |
| 330 | return !data_; | 311 | return !data_; |
| 331 | } | 312 | } |
| 332 | 313 | ||
| 333 | constexpr FixedPoint operator~() const { | 314 | [[nodiscard]] constexpr FixedPoint operator~() const { |
| 334 | // NOTE(eteran): this will often appear to "just negate" the value | 315 | // NOTE(eteran): this will often appear to "just negate" the value |
| 335 | // that is not an error, it is because -x == (~x+1) | 316 | // that is not an error, it is because -x == (~x+1) |
| 336 | // and that "+1" is adding an infinitesimally small fraction to the | 317 | // and that "+1" is adding an infinitesimally small fraction to the |
| @@ -338,11 +319,11 @@ public: // unary operators | |||
| 338 | return FixedPoint::from_base(~data_); | 319 | return FixedPoint::from_base(~data_); |
| 339 | } | 320 | } |
| 340 | 321 | ||
| 341 | constexpr FixedPoint operator-() const { | 322 | [[nodiscard]] constexpr FixedPoint operator-() const { |
| 342 | return FixedPoint::from_base(-data_); | 323 | return FixedPoint::from_base(-data_); |
| 343 | } | 324 | } |
| 344 | 325 | ||
| 345 | constexpr FixedPoint operator+() const { | 326 | [[nodiscard]] constexpr FixedPoint operator+() const { |
| 346 | return FixedPoint::from_base(+data_); | 327 | return FixedPoint::from_base(+data_); |
| 347 | } | 328 | } |
| 348 | 329 | ||
| @@ -411,15 +392,13 @@ public: // binary math operators, effects underlying bit pattern since these | |||
| 411 | return *this; | 392 | return *this; |
| 412 | } | 393 | } |
| 413 | 394 | ||
| 414 | template <class Integer, | 395 | template <IsIntegral Integer> |
| 415 | class = typename std::enable_if<std::is_integral<Integer>::value>::type> | ||
| 416 | constexpr FixedPoint& operator>>=(Integer n) { | 396 | constexpr FixedPoint& operator>>=(Integer n) { |
| 417 | data_ >>= n; | 397 | data_ >>= n; |
| 418 | return *this; | 398 | return *this; |
| 419 | } | 399 | } |
| 420 | 400 | ||
| 421 | template <class Integer, | 401 | template <IsIntegral Integer> |
| 422 | class = typename std::enable_if<std::is_integral<Integer>::value>::type> | ||
| 423 | constexpr FixedPoint& operator<<=(Integer n) { | 402 | constexpr FixedPoint& operator<<=(Integer n) { |
| 424 | data_ <<= n; | 403 | data_ <<= n; |
| 425 | return *this; | 404 | return *this; |
| @@ -430,42 +409,42 @@ public: // conversion to basic types | |||
| 430 | data_ += (data_ & fractional_mask) >> 1; | 409 | data_ += (data_ & fractional_mask) >> 1; |
| 431 | } | 410 | } |
| 432 | 411 | ||
| 433 | constexpr int to_int() { | 412 | [[nodiscard]] constexpr int to_int() { |
| 434 | round_up(); | 413 | round_up(); |
| 435 | return static_cast<int>((data_ & integer_mask) >> fractional_bits); | 414 | return static_cast<int>((data_ & integer_mask) >> fractional_bits); |
| 436 | } | 415 | } |
| 437 | 416 | ||
| 438 | constexpr unsigned int to_uint() const { | 417 | [[nodiscard]] constexpr unsigned int to_uint() { |
| 439 | round_up(); | 418 | round_up(); |
| 440 | return static_cast<unsigned int>((data_ & integer_mask) >> fractional_bits); | 419 | return static_cast<unsigned int>((data_ & integer_mask) >> fractional_bits); |
| 441 | } | 420 | } |
| 442 | 421 | ||
| 443 | constexpr int64_t to_long() { | 422 | [[nodiscard]] constexpr int64_t to_long() { |
| 444 | round_up(); | 423 | round_up(); |
| 445 | return static_cast<int64_t>((data_ & integer_mask) >> fractional_bits); | 424 | return static_cast<int64_t>((data_ & integer_mask) >> fractional_bits); |
| 446 | } | 425 | } |
| 447 | 426 | ||
| 448 | constexpr int to_int_floor() const { | 427 | [[nodiscard]] constexpr int to_int_floor() const { |
| 449 | return static_cast<int>((data_ & integer_mask) >> fractional_bits); | 428 | return static_cast<int>((data_ & integer_mask) >> fractional_bits); |
| 450 | } | 429 | } |
| 451 | 430 | ||
| 452 | constexpr int64_t to_long_floor() { | 431 | [[nodiscard]] constexpr int64_t to_long_floor() const { |
| 453 | return static_cast<int64_t>((data_ & integer_mask) >> fractional_bits); | 432 | return static_cast<int64_t>((data_ & integer_mask) >> fractional_bits); |
| 454 | } | 433 | } |
| 455 | 434 | ||
| 456 | constexpr unsigned int to_uint_floor() const { | 435 | [[nodiscard]] constexpr unsigned int to_uint_floor() const { |
| 457 | return static_cast<unsigned int>((data_ & integer_mask) >> fractional_bits); | 436 | return static_cast<unsigned int>((data_ & integer_mask) >> fractional_bits); |
| 458 | } | 437 | } |
| 459 | 438 | ||
| 460 | constexpr float to_float() const { | 439 | [[nodiscard]] constexpr float to_float() const { |
| 461 | return static_cast<float>(data_) / FixedPoint::one; | 440 | return static_cast<float>(data_) / FixedPoint::one; |
| 462 | } | 441 | } |
| 463 | 442 | ||
| 464 | constexpr double to_double() const { | 443 | [[nodiscard]] constexpr double to_double() const { |
| 465 | return static_cast<double>(data_) / FixedPoint::one; | 444 | return static_cast<double>(data_) / FixedPoint::one; |
| 466 | } | 445 | } |
| 467 | 446 | ||
| 468 | constexpr base_type to_raw() const { | 447 | [[nodiscard]] constexpr base_type to_raw() const { |
| 469 | return data_; | 448 | return data_; |
| 470 | } | 449 | } |
| 471 | 450 | ||
| @@ -473,27 +452,27 @@ public: // conversion to basic types | |||
| 473 | data_ &= fractional_mask; | 452 | data_ &= fractional_mask; |
| 474 | } | 453 | } |
| 475 | 454 | ||
| 476 | constexpr base_type get_frac() const { | 455 | [[nodiscard]] constexpr base_type get_frac() const { |
| 477 | return data_ & fractional_mask; | 456 | return data_ & fractional_mask; |
| 478 | } | 457 | } |
| 479 | 458 | ||
| 480 | public: | 459 | public: |
| 481 | constexpr void swap(FixedPoint& rhs) { | 460 | constexpr void swap(FixedPoint& rhs) noexcept { |
| 482 | using std::swap; | 461 | using std::swap; |
| 483 | swap(data_, rhs.data_); | 462 | swap(data_, rhs.data_); |
| 484 | } | 463 | } |
| 485 | 464 | ||
| 486 | public: | 465 | public: |
| 487 | base_type data_; | 466 | base_type data_{}; |
| 488 | }; | 467 | }; |
| 489 | 468 | ||
| 490 | // if we have the same fractional portion, but differing integer portions, we trivially upgrade the | 469 | // if we have the same fractional portion, but differing integer portions, we trivially upgrade the |
| 491 | // smaller type | 470 | // smaller type |
| 492 | template <size_t I1, size_t I2, size_t F> | 471 | template <size_t I1, size_t I2, size_t F> |
| 493 | constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type operator+( | 472 | constexpr std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>> operator+( |
| 494 | FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { | 473 | FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { |
| 495 | 474 | ||
| 496 | using T = typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type; | 475 | using T = std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>; |
| 497 | 476 | ||
| 498 | const T l = T::from_base(lhs.to_raw()); | 477 | const T l = T::from_base(lhs.to_raw()); |
| 499 | const T r = T::from_base(rhs.to_raw()); | 478 | const T r = T::from_base(rhs.to_raw()); |
| @@ -501,10 +480,10 @@ constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, | |||
| 501 | } | 480 | } |
| 502 | 481 | ||
| 503 | template <size_t I1, size_t I2, size_t F> | 482 | template <size_t I1, size_t I2, size_t F> |
| 504 | constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type operator-( | 483 | constexpr std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>> operator-( |
| 505 | FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { | 484 | FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { |
| 506 | 485 | ||
| 507 | using T = typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type; | 486 | using T = std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>; |
| 508 | 487 | ||
| 509 | const T l = T::from_base(lhs.to_raw()); | 488 | const T l = T::from_base(lhs.to_raw()); |
| 510 | const T r = T::from_base(rhs.to_raw()); | 489 | const T r = T::from_base(rhs.to_raw()); |
| @@ -512,10 +491,10 @@ constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, | |||
| 512 | } | 491 | } |
| 513 | 492 | ||
| 514 | template <size_t I1, size_t I2, size_t F> | 493 | template <size_t I1, size_t I2, size_t F> |
| 515 | constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type operator*( | 494 | constexpr std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>> operator*( |
| 516 | FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { | 495 | FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { |
| 517 | 496 | ||
| 518 | using T = typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type; | 497 | using T = std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>; |
| 519 | 498 | ||
| 520 | const T l = T::from_base(lhs.to_raw()); | 499 | const T l = T::from_base(lhs.to_raw()); |
| 521 | const T r = T::from_base(rhs.to_raw()); | 500 | const T r = T::from_base(rhs.to_raw()); |
| @@ -523,10 +502,10 @@ constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, | |||
| 523 | } | 502 | } |
| 524 | 503 | ||
| 525 | template <size_t I1, size_t I2, size_t F> | 504 | template <size_t I1, size_t I2, size_t F> |
| 526 | constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type operator/( | 505 | constexpr std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>> operator/( |
| 527 | FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { | 506 | FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { |
| 528 | 507 | ||
| 529 | using T = typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type; | 508 | using T = std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>; |
| 530 | 509 | ||
| 531 | const T l = T::from_base(lhs.to_raw()); | 510 | const T l = T::from_base(lhs.to_raw()); |
| 532 | const T r = T::from_base(rhs.to_raw()); | 511 | const T r = T::from_base(rhs.to_raw()); |
| @@ -561,54 +540,46 @@ constexpr FixedPoint<I, F> operator/(FixedPoint<I, F> lhs, FixedPoint<I, F> rhs) | |||
| 561 | return lhs; | 540 | return lhs; |
| 562 | } | 541 | } |
| 563 | 542 | ||
| 564 | template <size_t I, size_t F, class Number, | 543 | template <size_t I, size_t F, IsArithmetic Number> |
| 565 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 566 | constexpr FixedPoint<I, F> operator+(FixedPoint<I, F> lhs, Number rhs) { | 544 | constexpr FixedPoint<I, F> operator+(FixedPoint<I, F> lhs, Number rhs) { |
| 567 | lhs += FixedPoint<I, F>(rhs); | 545 | lhs += FixedPoint<I, F>(rhs); |
| 568 | return lhs; | 546 | return lhs; |
| 569 | } | 547 | } |
| 570 | template <size_t I, size_t F, class Number, | 548 | template <size_t I, size_t F, IsArithmetic Number> |
| 571 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 572 | constexpr FixedPoint<I, F> operator-(FixedPoint<I, F> lhs, Number rhs) { | 549 | constexpr FixedPoint<I, F> operator-(FixedPoint<I, F> lhs, Number rhs) { |
| 573 | lhs -= FixedPoint<I, F>(rhs); | 550 | lhs -= FixedPoint<I, F>(rhs); |
| 574 | return lhs; | 551 | return lhs; |
| 575 | } | 552 | } |
| 576 | template <size_t I, size_t F, class Number, | 553 | template <size_t I, size_t F, IsArithmetic Number> |
| 577 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 578 | constexpr FixedPoint<I, F> operator*(FixedPoint<I, F> lhs, Number rhs) { | 554 | constexpr FixedPoint<I, F> operator*(FixedPoint<I, F> lhs, Number rhs) { |
| 579 | lhs *= FixedPoint<I, F>(rhs); | 555 | lhs *= FixedPoint<I, F>(rhs); |
| 580 | return lhs; | 556 | return lhs; |
| 581 | } | 557 | } |
| 582 | template <size_t I, size_t F, class Number, | 558 | template <size_t I, size_t F, IsArithmetic Number> |
| 583 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 584 | constexpr FixedPoint<I, F> operator/(FixedPoint<I, F> lhs, Number rhs) { | 559 | constexpr FixedPoint<I, F> operator/(FixedPoint<I, F> lhs, Number rhs) { |
| 585 | lhs /= FixedPoint<I, F>(rhs); | 560 | lhs /= FixedPoint<I, F>(rhs); |
| 586 | return lhs; | 561 | return lhs; |
| 587 | } | 562 | } |
| 588 | 563 | ||
| 589 | template <size_t I, size_t F, class Number, | 564 | template <size_t I, size_t F, IsArithmetic Number> |
| 590 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 591 | constexpr FixedPoint<I, F> operator+(Number lhs, FixedPoint<I, F> rhs) { | 565 | constexpr FixedPoint<I, F> operator+(Number lhs, FixedPoint<I, F> rhs) { |
| 592 | FixedPoint<I, F> tmp(lhs); | 566 | FixedPoint<I, F> tmp(lhs); |
| 593 | tmp += rhs; | 567 | tmp += rhs; |
| 594 | return tmp; | 568 | return tmp; |
| 595 | } | 569 | } |
| 596 | template <size_t I, size_t F, class Number, | 570 | template <size_t I, size_t F, IsArithmetic Number> |
| 597 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 598 | constexpr FixedPoint<I, F> operator-(Number lhs, FixedPoint<I, F> rhs) { | 571 | constexpr FixedPoint<I, F> operator-(Number lhs, FixedPoint<I, F> rhs) { |
| 599 | FixedPoint<I, F> tmp(lhs); | 572 | FixedPoint<I, F> tmp(lhs); |
| 600 | tmp -= rhs; | 573 | tmp -= rhs; |
| 601 | return tmp; | 574 | return tmp; |
| 602 | } | 575 | } |
| 603 | template <size_t I, size_t F, class Number, | 576 | template <size_t I, size_t F, IsArithmetic Number> |
| 604 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 605 | constexpr FixedPoint<I, F> operator*(Number lhs, FixedPoint<I, F> rhs) { | 577 | constexpr FixedPoint<I, F> operator*(Number lhs, FixedPoint<I, F> rhs) { |
| 606 | FixedPoint<I, F> tmp(lhs); | 578 | FixedPoint<I, F> tmp(lhs); |
| 607 | tmp *= rhs; | 579 | tmp *= rhs; |
| 608 | return tmp; | 580 | return tmp; |
| 609 | } | 581 | } |
| 610 | template <size_t I, size_t F, class Number, | 582 | template <size_t I, size_t F, IsArithmetic Number> |
| 611 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 612 | constexpr FixedPoint<I, F> operator/(Number lhs, FixedPoint<I, F> rhs) { | 583 | constexpr FixedPoint<I, F> operator/(Number lhs, FixedPoint<I, F> rhs) { |
| 613 | FixedPoint<I, F> tmp(lhs); | 584 | FixedPoint<I, F> tmp(lhs); |
| 614 | tmp /= rhs; | 585 | tmp /= rhs; |
| @@ -616,78 +587,64 @@ constexpr FixedPoint<I, F> operator/(Number lhs, FixedPoint<I, F> rhs) { | |||
| 616 | } | 587 | } |
| 617 | 588 | ||
| 618 | // shift operators | 589 | // shift operators |
| 619 | template <size_t I, size_t F, class Integer, | 590 | template <size_t I, size_t F, IsIntegral Integer> |
| 620 | class = typename std::enable_if<std::is_integral<Integer>::value>::type> | ||
| 621 | constexpr FixedPoint<I, F> operator<<(FixedPoint<I, F> lhs, Integer rhs) { | 591 | constexpr FixedPoint<I, F> operator<<(FixedPoint<I, F> lhs, Integer rhs) { |
| 622 | lhs <<= rhs; | 592 | lhs <<= rhs; |
| 623 | return lhs; | 593 | return lhs; |
| 624 | } | 594 | } |
| 625 | template <size_t I, size_t F, class Integer, | 595 | template <size_t I, size_t F, IsIntegral Integer> |
| 626 | class = typename std::enable_if<std::is_integral<Integer>::value>::type> | ||
| 627 | constexpr FixedPoint<I, F> operator>>(FixedPoint<I, F> lhs, Integer rhs) { | 596 | constexpr FixedPoint<I, F> operator>>(FixedPoint<I, F> lhs, Integer rhs) { |
| 628 | lhs >>= rhs; | 597 | lhs >>= rhs; |
| 629 | return lhs; | 598 | return lhs; |
| 630 | } | 599 | } |
| 631 | 600 | ||
| 632 | // comparison operators | 601 | // comparison operators |
| 633 | template <size_t I, size_t F, class Number, | 602 | template <size_t I, size_t F, IsArithmetic Number> |
| 634 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 635 | constexpr bool operator>(FixedPoint<I, F> lhs, Number rhs) { | 603 | constexpr bool operator>(FixedPoint<I, F> lhs, Number rhs) { |
| 636 | return lhs > FixedPoint<I, F>(rhs); | 604 | return lhs > FixedPoint<I, F>(rhs); |
| 637 | } | 605 | } |
| 638 | template <size_t I, size_t F, class Number, | 606 | template <size_t I, size_t F, IsArithmetic Number> |
| 639 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 640 | constexpr bool operator<(FixedPoint<I, F> lhs, Number rhs) { | 607 | constexpr bool operator<(FixedPoint<I, F> lhs, Number rhs) { |
| 641 | return lhs < FixedPoint<I, F>(rhs); | 608 | return lhs < FixedPoint<I, F>(rhs); |
| 642 | } | 609 | } |
| 643 | template <size_t I, size_t F, class Number, | 610 | template <size_t I, size_t F, IsArithmetic Number> |
| 644 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 645 | constexpr bool operator>=(FixedPoint<I, F> lhs, Number rhs) { | 611 | constexpr bool operator>=(FixedPoint<I, F> lhs, Number rhs) { |
| 646 | return lhs >= FixedPoint<I, F>(rhs); | 612 | return lhs >= FixedPoint<I, F>(rhs); |
| 647 | } | 613 | } |
| 648 | template <size_t I, size_t F, class Number, | 614 | template <size_t I, size_t F, IsArithmetic Number> |
| 649 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 650 | constexpr bool operator<=(FixedPoint<I, F> lhs, Number rhs) { | 615 | constexpr bool operator<=(FixedPoint<I, F> lhs, Number rhs) { |
| 651 | return lhs <= FixedPoint<I, F>(rhs); | 616 | return lhs <= FixedPoint<I, F>(rhs); |
| 652 | } | 617 | } |
| 653 | template <size_t I, size_t F, class Number, | 618 | template <size_t I, size_t F, IsArithmetic Number> |
| 654 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 655 | constexpr bool operator==(FixedPoint<I, F> lhs, Number rhs) { | 619 | constexpr bool operator==(FixedPoint<I, F> lhs, Number rhs) { |
| 656 | return lhs == FixedPoint<I, F>(rhs); | 620 | return lhs == FixedPoint<I, F>(rhs); |
| 657 | } | 621 | } |
| 658 | template <size_t I, size_t F, class Number, | 622 | template <size_t I, size_t F, IsArithmetic Number> |
| 659 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 660 | constexpr bool operator!=(FixedPoint<I, F> lhs, Number rhs) { | 623 | constexpr bool operator!=(FixedPoint<I, F> lhs, Number rhs) { |
| 661 | return lhs != FixedPoint<I, F>(rhs); | 624 | return lhs != FixedPoint<I, F>(rhs); |
| 662 | } | 625 | } |
| 663 | 626 | ||
| 664 | template <size_t I, size_t F, class Number, | 627 | template <size_t I, size_t F, IsArithmetic Number> |
| 665 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 666 | constexpr bool operator>(Number lhs, FixedPoint<I, F> rhs) { | 628 | constexpr bool operator>(Number lhs, FixedPoint<I, F> rhs) { |
| 667 | return FixedPoint<I, F>(lhs) > rhs; | 629 | return FixedPoint<I, F>(lhs) > rhs; |
| 668 | } | 630 | } |
| 669 | template <size_t I, size_t F, class Number, | 631 | template <size_t I, size_t F, IsArithmetic Number> |
| 670 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 671 | constexpr bool operator<(Number lhs, FixedPoint<I, F> rhs) { | 632 | constexpr bool operator<(Number lhs, FixedPoint<I, F> rhs) { |
| 672 | return FixedPoint<I, F>(lhs) < rhs; | 633 | return FixedPoint<I, F>(lhs) < rhs; |
| 673 | } | 634 | } |
| 674 | template <size_t I, size_t F, class Number, | 635 | template <size_t I, size_t F, IsArithmetic Number> |
| 675 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 676 | constexpr bool operator>=(Number lhs, FixedPoint<I, F> rhs) { | 636 | constexpr bool operator>=(Number lhs, FixedPoint<I, F> rhs) { |
| 677 | return FixedPoint<I, F>(lhs) >= rhs; | 637 | return FixedPoint<I, F>(lhs) >= rhs; |
| 678 | } | 638 | } |
| 679 | template <size_t I, size_t F, class Number, | 639 | template <size_t I, size_t F, IsArithmetic Number> |
| 680 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 681 | constexpr bool operator<=(Number lhs, FixedPoint<I, F> rhs) { | 640 | constexpr bool operator<=(Number lhs, FixedPoint<I, F> rhs) { |
| 682 | return FixedPoint<I, F>(lhs) <= rhs; | 641 | return FixedPoint<I, F>(lhs) <= rhs; |
| 683 | } | 642 | } |
| 684 | template <size_t I, size_t F, class Number, | 643 | template <size_t I, size_t F, IsArithmetic Number> |
| 685 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 686 | constexpr bool operator==(Number lhs, FixedPoint<I, F> rhs) { | 644 | constexpr bool operator==(Number lhs, FixedPoint<I, F> rhs) { |
| 687 | return FixedPoint<I, F>(lhs) == rhs; | 645 | return FixedPoint<I, F>(lhs) == rhs; |
| 688 | } | 646 | } |
| 689 | template <size_t I, size_t F, class Number, | 647 | template <size_t I, size_t F, IsArithmetic Number> |
| 690 | class = typename std::enable_if<std::is_arithmetic<Number>::value>::type> | ||
| 691 | constexpr bool operator!=(Number lhs, FixedPoint<I, F> rhs) { | 648 | constexpr bool operator!=(Number lhs, FixedPoint<I, F> rhs) { |
| 692 | return FixedPoint<I, F>(lhs) != rhs; | 649 | return FixedPoint<I, F>(lhs) != rhs; |
| 693 | } | 650 | } |
diff --git a/src/core/hle/service/audio/audctl.cpp b/src/core/hle/service/audio/audctl.cpp index 4a2ae5f88..5abf22ba4 100644 --- a/src/core/hle/service/audio/audctl.cpp +++ b/src/core/hle/service/audio/audctl.cpp | |||
| @@ -45,9 +45,25 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} { | |||
| 45 | {32, nullptr, "GetActiveOutputTarget"}, | 45 | {32, nullptr, "GetActiveOutputTarget"}, |
| 46 | {33, nullptr, "GetTargetDeviceInfo"}, | 46 | {33, nullptr, "GetTargetDeviceInfo"}, |
| 47 | {34, nullptr, "AcquireTargetNotification"}, | 47 | {34, nullptr, "AcquireTargetNotification"}, |
| 48 | {35, nullptr, "SetHearingProtectionSafeguardTimerRemainingTimeForDebug"}, | ||
| 49 | {36, nullptr, "GetHearingProtectionSafeguardTimerRemainingTimeForDebug"}, | ||
| 50 | {37, nullptr, "SetHearingProtectionSafeguardEnabled"}, | ||
| 51 | {38, nullptr, "IsHearingProtectionSafeguardEnabled"}, | ||
| 52 | {39, nullptr, "IsHearingProtectionSafeguardMonitoringOutputForDebug"}, | ||
| 53 | {40, nullptr, "GetSystemInformationForDebug"}, | ||
| 54 | {41, nullptr, "SetVolumeButtonLongPressTime"}, | ||
| 55 | {42, nullptr, "SetNativeVolumeForDebug"}, | ||
| 48 | {10000, nullptr, "NotifyAudioOutputTargetForPlayReport"}, | 56 | {10000, nullptr, "NotifyAudioOutputTargetForPlayReport"}, |
| 49 | {10001, nullptr, "NotifyAudioOutputChannelCountForPlayReport"}, | 57 | {10001, nullptr, "NotifyAudioOutputChannelCountForPlayReport"}, |
| 50 | {10002, nullptr, "NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport"}, | 58 | {10002, nullptr, "NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport"}, |
| 59 | {10100, nullptr, "GetAudioVolumeDataForPlayReport"}, | ||
| 60 | {10101, nullptr, "BindAudioVolumeUpdateEventForPlayReport"}, | ||
| 61 | {10102, nullptr, "BindAudioOutputTargetUpdateEventForPlayReport"}, | ||
| 62 | {10103, nullptr, "GetAudioOutputTargetForPlayReport"}, | ||
| 63 | {10104, nullptr, "GetAudioOutputChannelCountForPlayReport"}, | ||
| 64 | {10105, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, | ||
| 65 | {10106, nullptr, "GetDefaultAudioOutputTargetForPlayReport"}, | ||
| 66 | {50000, nullptr, "SetAnalogInputBoostGainForPrototyping"}, | ||
| 51 | }; | 67 | }; |
| 52 | // clang-format on | 68 | // clang-format on |
| 53 | 69 | ||
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 60c30cd5b..13423dca6 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp | |||
| @@ -52,6 +52,8 @@ public: | |||
| 52 | {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"}, | 52 | {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"}, |
| 53 | {10, &IAudioRenderer::RequestUpdate, "RequestUpdateAuto"}, | 53 | {10, &IAudioRenderer::RequestUpdate, "RequestUpdateAuto"}, |
| 54 | {11, nullptr, "ExecuteAudioRendererRendering"}, | 54 | {11, nullptr, "ExecuteAudioRendererRendering"}, |
| 55 | {12, &IAudioRenderer::SetVoiceDropParameter, "SetVoiceDropParameter"}, | ||
| 56 | {13, &IAudioRenderer::GetVoiceDropParameter, "GetVoiceDropParameter"}, | ||
| 55 | }; | 57 | }; |
| 56 | // clang-format on | 58 | // clang-format on |
| 57 | RegisterHandlers(functions); | 59 | RegisterHandlers(functions); |
| @@ -205,6 +207,30 @@ private: | |||
| 205 | LOG_DEBUG(Service_Audio, "called"); | 207 | LOG_DEBUG(Service_Audio, "called"); |
| 206 | } | 208 | } |
| 207 | 209 | ||
| 210 | void SetVoiceDropParameter(Kernel::HLERequestContext& ctx) { | ||
| 211 | LOG_DEBUG(Service_Audio, "called"); | ||
| 212 | |||
| 213 | IPC::RequestParser rp{ctx}; | ||
| 214 | auto voice_drop_param{rp.Pop<f32>()}; | ||
| 215 | |||
| 216 | auto& system_ = impl->GetSystem(); | ||
| 217 | system_.SetVoiceDropParameter(voice_drop_param); | ||
| 218 | |||
| 219 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 220 | rb.Push(ResultSuccess); | ||
| 221 | } | ||
| 222 | |||
| 223 | void GetVoiceDropParameter(Kernel::HLERequestContext& ctx) { | ||
| 224 | LOG_DEBUG(Service_Audio, "called"); | ||
| 225 | |||
| 226 | auto& system_ = impl->GetSystem(); | ||
| 227 | auto voice_drop_param{system_.GetVoiceDropParameter()}; | ||
| 228 | |||
| 229 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 230 | rb.Push(ResultSuccess); | ||
| 231 | rb.Push(voice_drop_param); | ||
| 232 | } | ||
| 233 | |||
| 208 | KernelHelpers::ServiceContext service_context; | 234 | KernelHelpers::ServiceContext service_context; |
| 209 | Kernel::KEvent* rendered_event; | 235 | Kernel::KEvent* rendered_event; |
| 210 | Manager& manager; | 236 | Manager& manager; |
diff --git a/src/yuzu/applets/qt_controller.ui b/src/yuzu/applets/qt_controller.ui index c8cb6bcf3..f5eccba70 100644 --- a/src/yuzu/applets/qt_controller.ui +++ b/src/yuzu/applets/qt_controller.ui | |||
| @@ -2300,7 +2300,7 @@ | |||
| 2300 | <item> | 2300 | <item> |
| 2301 | <widget class="QRadioButton" name="radioUndocked"> | 2301 | <widget class="QRadioButton" name="radioUndocked"> |
| 2302 | <property name="text"> | 2302 | <property name="text"> |
| 2303 | <string>Undocked</string> | 2303 | <string>Handheld</string> |
| 2304 | </property> | 2304 | </property> |
| 2305 | </widget> | 2305 | </widget> |
| 2306 | </item> | 2306 | </item> |