diff options
| author | 2020-10-25 07:30:23 -0400 | |
|---|---|---|
| committer | 2020-11-15 23:33:21 -0500 | |
| commit | 30e0d1c973290f4813b040eecf83ff4a2c7432c3 (patch) | |
| tree | 2834cf3cc9970e14608a8af0739ffcac56881332 | |
| parent | input: Disconnect a controller prior to connecting a new one (diff) | |
| download | yuzu-30e0d1c973290f4813b040eecf83ff4a2c7432c3.tar.gz yuzu-30e0d1c973290f4813b040eecf83ff4a2c7432c3.tar.xz yuzu-30e0d1c973290f4813b040eecf83ff4a2c7432c3.zip | |
controllers/npad: Remove the old vibration filter
Previously we used a vibration filter that filters out amplitudes close to each other. It turns out there are cases where this results into vibrations that are too inaccurate. Remove this and move the 100Hz vibration filter (Only allowing a maximum of 100 vibrations per second) from sdl_impl to npad when enable_accurate_vibrations is set to false.
Diffstat (limited to '')
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.cpp | 108 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.h | 4 | ||||
| -rw-r--r-- | src/core/hle/service/hid/hid.cpp | 2 | ||||
| -rw-r--r-- | src/input_common/sdl/sdl_impl.cpp | 15 |
4 files changed, 64 insertions, 65 deletions
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index ecc33bc08..cfafabbd8 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp | |||
| @@ -703,6 +703,23 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size | |||
| 703 | return false; | 703 | return false; |
| 704 | } | 704 | } |
| 705 | 705 | ||
| 706 | if (!Settings::values.enable_accurate_vibrations.GetValue()) { | ||
| 707 | using std::chrono::duration_cast; | ||
| 708 | using std::chrono::milliseconds; | ||
| 709 | using std::chrono::steady_clock; | ||
| 710 | |||
| 711 | const auto now = steady_clock::now(); | ||
| 712 | |||
| 713 | // Filter out non-zero vibrations that are within 10ms of each other. | ||
| 714 | if ((vibration_value.amp_low != 0.0f || vibration_value.amp_high != 0.0f) && | ||
| 715 | duration_cast<milliseconds>(now - last_vibration_timepoints[npad_index][device_index]) < | ||
| 716 | milliseconds(10)) { | ||
| 717 | return false; | ||
| 718 | } | ||
| 719 | |||
| 720 | last_vibration_timepoints[npad_index][device_index] = now; | ||
| 721 | } | ||
| 722 | |||
| 706 | return vibrations[npad_index][device_index]->SetRumblePlay( | 723 | return vibrations[npad_index][device_index]->SetRumblePlay( |
| 707 | std::min(vibration_value.amp_low * player.vibration_strength / 100.0f, 1.0f), | 724 | std::min(vibration_value.amp_low * player.vibration_strength / 100.0f, 1.0f), |
| 708 | vibration_value.freq_low, | 725 | vibration_value.freq_low, |
| @@ -710,66 +727,59 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size | |||
| 710 | vibration_value.freq_high); | 727 | vibration_value.freq_high); |
| 711 | } | 728 | } |
| 712 | 729 | ||
| 713 | void Controller_NPad::VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles, | 730 | void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle, |
| 714 | const std::vector<VibrationValue>& vibration_values) { | 731 | const VibrationValue& vibration_value) { |
| 715 | LOG_TRACE(Service_HID, "called"); | ||
| 716 | |||
| 717 | if (!Settings::values.vibration_enabled.GetValue()) { | 732 | if (!Settings::values.vibration_enabled.GetValue()) { |
| 718 | return; | 733 | return; |
| 719 | } | 734 | } |
| 720 | 735 | ||
| 721 | ASSERT_MSG(vibration_device_handles.size() == vibration_values.size(), | 736 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); |
| 722 | "The amount of device handles does not match with the amount of vibration values," | 737 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); |
| 723 | "this is undefined behavior!"); | ||
| 724 | 738 | ||
| 725 | for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) { | 739 | if (!vibration_devices_mounted[npad_index][device_index] || |
| 726 | const auto npad_index = NPadIdToIndex(vibration_device_handles[i].npad_id); | 740 | !connected_controllers[npad_index].is_connected) { |
| 727 | const auto device_index = | 741 | return; |
| 728 | static_cast<std::size_t>(vibration_device_handles[i].device_index); | 742 | } |
| 729 | 743 | ||
| 730 | if (!vibration_devices_mounted[npad_index][device_index] || | 744 | if (vibration_device_handle.device_index == DeviceIndex::None) { |
| 731 | !connected_controllers[npad_index].is_connected) { | 745 | UNREACHABLE_MSG("DeviceIndex should never be None!"); |
| 732 | continue; | 746 | return; |
| 733 | } | 747 | } |
| 734 | 748 | ||
| 735 | if (vibration_device_handles[i].device_index == DeviceIndex::None) { | 749 | // Some games try to send mismatched parameters in the device handle, block these. |
| 736 | UNREACHABLE_MSG("DeviceIndex should never be None!"); | 750 | if ((connected_controllers[npad_index].type == NPadControllerType::JoyLeft && |
| 737 | continue; | 751 | (vibration_device_handle.npad_type == NpadType::JoyconRight || |
| 738 | } | 752 | vibration_device_handle.device_index == DeviceIndex::Right)) || |
| 753 | (connected_controllers[npad_index].type == NPadControllerType::JoyRight && | ||
| 754 | (vibration_device_handle.npad_type == NpadType::JoyconLeft || | ||
| 755 | vibration_device_handle.device_index == DeviceIndex::Left))) { | ||
| 756 | return; | ||
| 757 | } | ||
| 739 | 758 | ||
| 740 | // Some games try to send mismatched parameters in the device handle, block these. | 759 | // Filter out vibrations with equivalent values to reduce unnecessary state changes. |
| 741 | if ((connected_controllers[npad_index].type == NPadControllerType::JoyLeft && | 760 | if (vibration_value.amp_low == latest_vibration_values[npad_index][device_index].amp_low && |
| 742 | (vibration_device_handles[i].npad_type == NpadType::JoyconRight || | 761 | vibration_value.amp_high == latest_vibration_values[npad_index][device_index].amp_high) { |
| 743 | vibration_device_handles[i].device_index == DeviceIndex::Right)) || | 762 | return; |
| 744 | (connected_controllers[npad_index].type == NPadControllerType::JoyRight && | 763 | } |
| 745 | (vibration_device_handles[i].npad_type == NpadType::JoyconLeft || | ||
| 746 | vibration_device_handles[i].device_index == DeviceIndex::Left))) { | ||
| 747 | continue; | ||
| 748 | } | ||
| 749 | 764 | ||
| 750 | // Filter out vibrations with equivalent values to reduce unnecessary state changes. | 765 | if (VibrateControllerAtIndex(npad_index, device_index, vibration_value)) { |
| 751 | if (vibration_values[i].amp_low == | 766 | latest_vibration_values[npad_index][device_index] = vibration_value; |
| 752 | latest_vibration_values[npad_index][device_index].amp_low && | 767 | } |
| 753 | vibration_values[i].amp_high == | 768 | } |
| 754 | latest_vibration_values[npad_index][device_index].amp_high) { | ||
| 755 | continue; | ||
| 756 | } | ||
| 757 | 769 | ||
| 758 | // Filter out non-zero vibrations that are within 0.015625 absolute amplitude of each other. | 770 | void Controller_NPad::VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles, |
| 759 | if (!Settings::values.enable_accurate_vibrations.GetValue() && | 771 | const std::vector<VibrationValue>& vibration_values) { |
| 760 | (vibration_values[i].amp_low != 0.0f || vibration_values[i].amp_high != 0.0f) && | 772 | if (!Settings::values.vibration_enabled.GetValue()) { |
| 761 | (latest_vibration_values[npad_index][device_index].amp_low != 0.0f || | 773 | return; |
| 762 | latest_vibration_values[npad_index][device_index].amp_high != 0.0f) && | 774 | } |
| 763 | (abs(vibration_values[i].amp_low - | ||
| 764 | latest_vibration_values[npad_index][device_index].amp_low) < 0.015625f && | ||
| 765 | abs(vibration_values[i].amp_high - | ||
| 766 | latest_vibration_values[npad_index][device_index].amp_high) < 0.015625f)) { | ||
| 767 | continue; | ||
| 768 | } | ||
| 769 | 775 | ||
| 770 | if (VibrateControllerAtIndex(npad_index, device_index, vibration_values[i])) { | 776 | ASSERT_OR_EXECUTE_MSG( |
| 771 | latest_vibration_values[npad_index][device_index] = vibration_values[i]; | 777 | vibration_device_handles.size() == vibration_values.size(), { return; }, |
| 772 | } | 778 | "The amount of device handles does not match with the amount of vibration values," |
| 779 | "this is undefined behavior!"); | ||
| 780 | |||
| 781 | for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) { | ||
| 782 | VibrateController(vibration_device_handles[i], vibration_values[i]); | ||
| 773 | } | 783 | } |
| 774 | } | 784 | } |
| 775 | 785 | ||
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 30e3cb02f..f5122124c 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h | |||
| @@ -151,6 +151,9 @@ public: | |||
| 151 | bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, | 151 | bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, |
| 152 | const VibrationValue& vibration_value = {}); | 152 | const VibrationValue& vibration_value = {}); |
| 153 | 153 | ||
| 154 | void VibrateController(const DeviceHandle& vibration_device_handle, | ||
| 155 | const VibrationValue& vibration_value); | ||
| 156 | |||
| 154 | void VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles, | 157 | void VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles, |
| 155 | const std::vector<VibrationValue>& vibration_values); | 158 | const std::vector<VibrationValue>& vibration_values); |
| 156 | 159 | ||
| @@ -421,6 +424,7 @@ private: | |||
| 421 | NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; | 424 | NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; |
| 422 | // Each controller should have their own styleset changed event | 425 | // Each controller should have their own styleset changed event |
| 423 | std::array<Kernel::EventPair, 10> styleset_changed_events; | 426 | std::array<Kernel::EventPair, 10> styleset_changed_events; |
| 427 | std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10> last_vibration_timepoints; | ||
| 424 | std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{}; | 428 | std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{}; |
| 425 | std::array<std::array<bool, 2>, 10> vibration_devices_mounted{}; | 429 | std::array<std::array<bool, 2>, 10> vibration_devices_mounted{}; |
| 426 | std::array<ControllerHolder, 10> connected_controllers{}; | 430 | std::array<ControllerHolder, 10> connected_controllers{}; |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index ecaa847b2..2e9682bed 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -1029,7 +1029,7 @@ void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { | |||
| 1029 | const auto parameters{rp.PopRaw<Parameters>()}; | 1029 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 1030 | 1030 | ||
| 1031 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | 1031 | applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 1032 | .VibrateControllers({parameters.vibration_device_handle}, {parameters.vibration_value}); | 1032 | .VibrateController(parameters.vibration_device_handle, parameters.vibration_value); |
| 1033 | 1033 | ||
| 1034 | LOG_DEBUG(Service_HID, | 1034 | LOG_DEBUG(Service_HID, |
| 1035 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | 1035 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", |
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index a2a83cdc9..a9f7e5103 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp | |||
| @@ -81,18 +81,6 @@ public: | |||
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | bool RumblePlay(u16 amp_low, u16 amp_high) { | 83 | bool RumblePlay(u16 amp_low, u16 amp_high) { |
| 84 | using std::chrono::duration_cast; | ||
| 85 | using std::chrono::milliseconds; | ||
| 86 | using std::chrono::steady_clock; | ||
| 87 | |||
| 88 | // Block non-zero vibrations less than 10ms apart from each other. | ||
| 89 | if ((amp_low != 0 || amp_high != 0) && | ||
| 90 | duration_cast<milliseconds>(steady_clock::now() - last_vibration) < milliseconds(10)) { | ||
| 91 | return false; | ||
| 92 | } | ||
| 93 | |||
| 94 | last_vibration = steady_clock::now(); | ||
| 95 | |||
| 96 | if (sdl_controller) { | 84 | if (sdl_controller) { |
| 97 | return SDL_GameControllerRumble(sdl_controller.get(), amp_low, amp_high, 0) == 0; | 85 | return SDL_GameControllerRumble(sdl_controller.get(), amp_low, amp_high, 0) == 0; |
| 98 | } else if (sdl_joystick) { | 86 | } else if (sdl_joystick) { |
| @@ -171,9 +159,6 @@ private: | |||
| 171 | std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; | 159 | std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; |
| 172 | mutable std::mutex mutex; | 160 | mutable std::mutex mutex; |
| 173 | 161 | ||
| 174 | // This is the timepoint of the last vibration and is used to ensure vibrations are 10ms apart. | ||
| 175 | std::chrono::steady_clock::time_point last_vibration; | ||
| 176 | |||
| 177 | // Motion is initialized without PID values as motion input is not aviable for SDL2 | 162 | // Motion is initialized without PID values as motion input is not aviable for SDL2 |
| 178 | MotionInput motion{0.0f, 0.0f, 0.0f}; | 163 | MotionInput motion{0.0f, 0.0f, 0.0f}; |
| 179 | }; | 164 | }; |