mirror of
https://github.com/RawAccelOfficial/rawaccel.git
synced 2025-05-10 18:06:38 +02:00
Change motivity type to use syncrhonous framework
This commit is contained in:
parent
7427404ea0
commit
428f4e8b49
8 changed files with 163 additions and 23 deletions
|
@ -8,21 +8,67 @@ namespace rawaccel {
|
|||
|
||||
template <>
|
||||
struct loglog_sigmoid<LEGACY> {
|
||||
double accel;
|
||||
double motivity;
|
||||
double midpoint;
|
||||
double constant;
|
||||
double log_motivity;
|
||||
double gamma_const;
|
||||
double log_syncspeed;
|
||||
double syncspeed;
|
||||
double sharpness;
|
||||
double sharpness_recip;
|
||||
bool use_linear_clamp;
|
||||
double minimum_sens;
|
||||
double maximum_sens;
|
||||
|
||||
loglog_sigmoid(const accel_args& args) :
|
||||
accel(exp(args.growth_rate)),
|
||||
motivity(2 * log(args.motivity)),
|
||||
midpoint(log(args.midpoint)),
|
||||
constant(-motivity / 2) {}
|
||||
log_motivity(log(args.motivity)),
|
||||
gamma_const(args.gamma / log_motivity),
|
||||
log_syncspeed(log(args.sync_speed)),
|
||||
syncspeed(args.sync_speed),
|
||||
sharpness(args.smooth == 0 ? 16 : 0.5 / args.smooth),
|
||||
sharpness_recip(1 / sharpness),
|
||||
use_linear_clamp(sharpness >= 16),
|
||||
minimum_sens(1 / args.motivity),
|
||||
maximum_sens(args.motivity) {}
|
||||
|
||||
double operator()(double x, const accel_args&) const
|
||||
{
|
||||
double denom = exp(accel * (midpoint - log(x))) + 1;
|
||||
return exp(motivity / denom + constant);
|
||||
// if sharpness >= 16, use linear clamp for activation function.
|
||||
// linear clamp means: clamp(x, -1, 1).
|
||||
if (use_linear_clamp)
|
||||
{
|
||||
double log_space = gamma_const * (log(x) - log_syncspeed);
|
||||
|
||||
if (log_space < -1)
|
||||
{
|
||||
return minimum_sens;
|
||||
}
|
||||
|
||||
if (log_space > 1)
|
||||
{
|
||||
return maximum_sens;
|
||||
}
|
||||
|
||||
return exp(log_space * log_motivity);
|
||||
}
|
||||
|
||||
if (x == syncspeed) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
double log_x = log(x);
|
||||
double log_diff = log_x - log_syncspeed;
|
||||
|
||||
if (log_diff > 0)
|
||||
{
|
||||
double log_space = gamma_const * log_diff;
|
||||
double exponent = pow(tanh(pow(log_space, sharpness)), sharpness_recip);
|
||||
return exp(exponent * log_motivity);
|
||||
}
|
||||
else
|
||||
{
|
||||
double log_space = -gamma_const * log_diff;
|
||||
double exponent = -pow(tanh(pow(log_space, sharpness)), sharpness_recip);
|
||||
return exp(exponent * log_motivity);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -49,13 +49,13 @@ namespace rawaccel {
|
|||
double output_offset = 0;
|
||||
double acceleration = 0.005;
|
||||
double decay_rate = 0.1;
|
||||
double growth_rate = 1;
|
||||
double gamma = 1;
|
||||
double motivity = 1.5;
|
||||
double exponent_classic = 2;
|
||||
double scale = 1;
|
||||
double exponent_power = 0.05;
|
||||
double limit = 1.5;
|
||||
double midpoint = 5;
|
||||
double sync_speed = 5;
|
||||
double smooth = 0.5;
|
||||
|
||||
vec2d cap = { 15, 1.5 };
|
||||
|
|
|
@ -96,8 +96,8 @@ namespace rawaccel {
|
|||
error("scale"" must be positive");
|
||||
}
|
||||
|
||||
if (args.growth_rate <= 0) {
|
||||
error("growth rate"" must be positive");
|
||||
if (args.gamma <= 0) {
|
||||
error("gamma"" must be positive");
|
||||
}
|
||||
|
||||
if (args.decay_rate <= 0) {
|
||||
|
@ -120,8 +120,8 @@ namespace rawaccel {
|
|||
error("limit"" must be positive");
|
||||
}
|
||||
|
||||
if (args.midpoint <= 0) {
|
||||
error("midpoint"" must be positive");
|
||||
if (args.sync_speed <= 0) {
|
||||
error("synchronous speed"" must be positive");
|
||||
}
|
||||
|
||||
if (args.smooth < 0 || args.smooth > 1) {
|
||||
|
|
|
@ -420,7 +420,6 @@ namespace rawaccel {
|
|||
if (flags.apply_dir_mul_y && in.y < 0) {
|
||||
in.y *= args.ud_output_dpi_ratio;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
modifier(modifier_settings& settings)
|
||||
|
|
|
@ -281,12 +281,12 @@ namespace grapher
|
|||
OutputOffset.SetActiveValue(args.outputOffset);
|
||||
InputOffset.SetActiveValue(args.inputOffset);
|
||||
DecayRate.SetActiveValue(args.decayRate);
|
||||
GrowthRate.SetActiveValue(args.growthRate);
|
||||
GrowthRate.SetActiveValue(args.gamma);
|
||||
Smooth.SetActiveValue(args.smooth);
|
||||
Limit.SetActiveValue((args.mode == AccelMode.motivity) ? args.motivity : args.limit);
|
||||
PowerClassic.SetActiveValue(args.exponentClassic);
|
||||
Exponent.SetActiveValue(args.exponentPower);
|
||||
Midpoint.SetActiveValue(args.midpoint);
|
||||
Midpoint.SetActiveValue(args.syncSpeed);
|
||||
LutPanel.SetActiveValues(args.data, args.length, args.mode);
|
||||
LutApply.SetActiveValue(args.gain);
|
||||
}
|
||||
|
@ -326,7 +326,7 @@ namespace grapher
|
|||
GainSwitch.CheckBox.Checked;
|
||||
|
||||
if (DecayRate.Visible) args.decayRate = DecayRate.Field.Data;
|
||||
if (GrowthRate.Visible) args.growthRate = GrowthRate.Field.Data;
|
||||
if (GrowthRate.Visible) args.gamma = GrowthRate.Field.Data;
|
||||
if (Smooth.Visible) args.smooth = Smooth.Field.Data;
|
||||
if (ClassicCap.Visible)
|
||||
{
|
||||
|
@ -360,7 +360,7 @@ namespace grapher
|
|||
if (InputOffset.Visible) args.inputOffset = InputOffset.Field.Data;
|
||||
if (OutputOffset.Visible) args.outputOffset = OutputOffset.Field.Data;
|
||||
|
||||
if (Midpoint.Visible) args.midpoint = Midpoint.Field.Data;
|
||||
if (Midpoint.Visible) args.syncSpeed = Midpoint.Field.Data;
|
||||
if (LutPanel.Visible)
|
||||
{
|
||||
(var points, var length) = LutPanel.GetPoints();
|
||||
|
|
94
wrapper-tests/SynchronousAccelTests.cs
Normal file
94
wrapper-tests/SynchronousAccelTests.cs
Normal file
|
@ -0,0 +1,94 @@
|
|||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace wrapper_tests
|
||||
{
|
||||
[TestClass]
|
||||
public class SynchronousAccelTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void GivenSpeeds_SynchronousAccel_YieldsCorrectSens()
|
||||
{
|
||||
double syncSpeed = 20;
|
||||
double gamma = 0.5;
|
||||
double motivity = 1.3;
|
||||
double smooth = 0.5;
|
||||
|
||||
var profile = new Profile();
|
||||
profile.outputDPI = 1000;
|
||||
profile.argsX.mode = AccelMode.motivity;
|
||||
profile.argsX.gain = false;
|
||||
profile.argsX.syncSpeed = syncSpeed;
|
||||
profile.argsX.gamma = gamma;
|
||||
profile.argsX.motivity = motivity;
|
||||
profile.argsX.smooth = smooth;
|
||||
var accel = new ManagedAccel(profile);
|
||||
var accelSimulator = new SynchronousAccelSimulator(syncSpeed, motivity, gamma, smooth);
|
||||
|
||||
List<int> inputs = new List<int>()
|
||||
{
|
||||
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181,
|
||||
};
|
||||
|
||||
foreach (int input in inputs)
|
||||
{
|
||||
Tuple<double, double> output = accel.Accelerate(input, 0, 1, 10);
|
||||
double expectedOutput = input * accelSimulator.Accelerate(input / 10.0);
|
||||
Assert.AreEqual(expectedOutput, output.Item1, expectedOutput * 0.0001);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains definition of how synchronous accel is expected to accelerate inputs
|
||||
/// No optimization tricks are used for clarity of behavior.
|
||||
/// </summary>
|
||||
public class SynchronousAccelSimulator
|
||||
{
|
||||
public SynchronousAccelSimulator(
|
||||
double syncSpeed,
|
||||
double motivity,
|
||||
double gamma,
|
||||
double smooth)
|
||||
{
|
||||
SyncSpeed = syncSpeed;
|
||||
Motivity = motivity;
|
||||
Gamma = gamma;
|
||||
Sharpness = smooth <= 0 ? 16 : 0.5 / smooth;
|
||||
}
|
||||
|
||||
public double SyncSpeed { get; }
|
||||
|
||||
public double Motivity { get; }
|
||||
|
||||
public double Gamma { get; }
|
||||
|
||||
public double Sharpness { get; }
|
||||
|
||||
public double Accelerate(double inputSpeed)
|
||||
{
|
||||
double logSpace = CalculateLogSpace(inputSpeed);
|
||||
double activation = ActivationFunction(logSpace);
|
||||
return Math.Pow(Motivity, activation);
|
||||
}
|
||||
|
||||
public double CalculateLogSpace(double x)
|
||||
{
|
||||
double syncRatio = x / SyncSpeed;
|
||||
double logSpaceUnadjusted = Math.Log(syncRatio, Motivity);
|
||||
double gammaAdjusted = Gamma * logSpaceUnadjusted;
|
||||
return gammaAdjusted;
|
||||
}
|
||||
|
||||
public double ActivationFunction(double x)
|
||||
{
|
||||
if (Sharpness >= 16)
|
||||
{
|
||||
return Math.Min(1, Math.Max(-1, x));
|
||||
}
|
||||
|
||||
return Math.Sign(x) * Math.Pow(Math.Tanh(Math.Pow(Math.Abs(x), Sharpness)), 1 / Sharpness);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -53,6 +53,7 @@
|
|||
<Compile Include="EndToEndTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SpeedTests.cs" />
|
||||
<Compile Include="SynchronousAccelTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
|
|
@ -68,13 +68,13 @@ public value struct AccelArgs
|
|||
double outputOffset;
|
||||
double acceleration;
|
||||
double decayRate;
|
||||
double growthRate;
|
||||
double gamma;
|
||||
double motivity;
|
||||
double exponentClassic;
|
||||
double scale;
|
||||
double exponentPower;
|
||||
double limit;
|
||||
double midpoint;
|
||||
double syncSpeed;
|
||||
double smooth;
|
||||
|
||||
[JsonProperty("Cap / Jump")]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue