core/hid: Fix rumble too strong at 1%

This commit is contained in:
german77 2021-10-20 14:41:56 -05:00 committed by Narr the Reg
parent 601ac43495
commit c3ff0a8ac0
3 changed files with 48 additions and 13 deletions

View File

@ -60,6 +60,12 @@ enum class PollingError {
Unknown, Unknown,
}; };
// Hint for amplification curve to be used
enum class VibrationAmplificationType {
Linear,
Exponential,
};
struct AnalogProperties { struct AnalogProperties {
float deadzone{}; float deadzone{};
float range{1.0f}; float range{1.0f};
@ -126,6 +132,7 @@ struct VibrationStatus {
f32 low_frequency{}; f32 low_frequency{};
f32 high_amplitude{}; f32 high_amplitude{};
f32 high_frequency{}; f32 high_frequency{};
VibrationAmplificationType type;
}; };
struct LedStatus { struct LedStatus {

View File

@ -54,7 +54,6 @@ Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadType type
} }
void EmulatedController::ReloadFromSettings() { void EmulatedController::ReloadFromSettings() {
//LOG_ERROR(Service_HID, "reload config from settings {}", NpadIdTypeToIndex(npad_id_type));
const auto player_index = NpadIdTypeToIndex(npad_id_type); const auto player_index = NpadIdTypeToIndex(npad_id_type);
const auto& player = Settings::values.players.GetValue()[player_index]; const auto& player = Settings::values.players.GetValue()[player_index];
@ -640,12 +639,22 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
if (!output_devices[device_index]) { if (!output_devices[device_index]) {
return false; return false;
} }
const auto player_index = NpadIdTypeToIndex(npad_id_type);
const auto& player = Settings::values.players.GetValue()[player_index];
const f32 strength = static_cast<f32>(player.vibration_strength) / 100.0f;
// Exponential amplification is too strong at low amplitudes. Switch to a linear
// amplification if strength is set below 0.7f
const Input::VibrationAmplificationType type =
strength > 0.7f ? Input::VibrationAmplificationType::Exponential
: Input::VibrationAmplificationType::Linear;
const Input::VibrationStatus status = { const Input::VibrationStatus status = {
.low_amplitude = vibration.high_amplitude, .low_amplitude = std::min(vibration.low_amplitude * strength, 1.0f),
.low_frequency = vibration.high_amplitude, .low_frequency = vibration.low_frequency,
.high_amplitude = vibration.high_amplitude, .high_amplitude = std::min(vibration.high_amplitude * strength, 1.0f),
.high_frequency = vibration.high_amplitude, .high_frequency = vibration.high_frequency,
.type = type,
}; };
return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None; return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None;
} }
@ -661,6 +670,7 @@ bool EmulatedController::TestVibration(std::size_t device_index) {
.low_frequency = 160.0f, .low_frequency = 160.0f,
.high_amplitude = 0.001f, .high_amplitude = 0.001f,
.high_frequency = 320.0f, .high_frequency = 320.0f,
.type = Input::VibrationAmplificationType::Linear,
}; };
return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None; return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None;
} }

View File

@ -107,6 +107,14 @@ public:
return false; return false;
} }
bool HasHDRumble() const {
if (sdl_controller) {
return (SDL_GameControllerGetType(sdl_controller.get()) ==
SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO);
}
return false;
}
/** /**
* The Pad identifier of the joystick * The Pad identifier of the joystick
*/ */
@ -515,16 +523,26 @@ Input::VibrationError SDLDriver::SetRumble(const PadIdentifier& identifier,
const auto process_amplitude = [](f32 amplitude) { const auto process_amplitude = [](f32 amplitude) {
return (amplitude + std::pow(amplitude, 0.3f)) * 0.5f * 0xFFFF; return (amplitude + std::pow(amplitude, 0.3f)) * 0.5f * 0xFFFF;
}; };
const Input::VibrationStatus new_vibration{ const Input::VibrationStatus exponential_vibration{
.low_amplitude = process_amplitude(vibration.low_amplitude), .low_amplitude = process_amplitude(vibration.low_amplitude),
.low_frequency = vibration.low_frequency, .low_frequency = vibration.low_frequency,
.high_amplitude = process_amplitude(vibration.high_amplitude), .high_amplitude = process_amplitude(vibration.high_amplitude),
.high_frequency = vibration.high_frequency, .high_frequency = vibration.high_frequency,
.type = Input::VibrationAmplificationType::Exponential,
}; };
Input::VibrationStatus new_vibration{};
if (vibration.type == Input::VibrationAmplificationType::Linear || joystick->HasHDRumble()) {
new_vibration = vibration;
} else {
new_vibration = exponential_vibration;
}
if (!joystick->RumblePlay(new_vibration)) { if (!joystick->RumblePlay(new_vibration)) {
return Input::VibrationError::Unknown; return Input::VibrationError::Unknown;
} }
return Input::VibrationError::None; return Input::VibrationError::None;
} }
Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid, Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid,