Skip to content

Commit

Permalink
Use normal distribution for randomization
Browse files Browse the repository at this point in the history
  • Loading branch information
fs-c committed Apr 7, 2023
1 parent 79d52e1 commit 1b46ea2
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 21 deletions.
8 changes: 4 additions & 4 deletions app/app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ int main(int, char **) {

set_priority_class(HIGH_PRIORITY_CLASS);

maniac::randomize(hit_objects, maniac::config.randomization_range);
maniac::randomize(hit_objects, maniac::config.randomization_mean, maniac::config.randomization_stddev);

if (maniac::config.humanization_type == maniac::config::STATIC_HUMANIZATION) {
maniac::humanize_static(hit_objects, maniac::config.humanization_modifier);
Expand Down Expand Up @@ -113,10 +113,10 @@ int main(int, char **) {
ImGui::SameLine();
help_marker("Advanced hit-time randomization based on hit density.");

ImGui::DragIntRange2("Randomization", &maniac::config.randomization_range.first,
&maniac::config.randomization_range.second);
ImGui::InputInt("Randomization Mean", &maniac::config.randomization_mean);
ImGui::InputInt("Randomization Stddev", &maniac::config.randomization_stddev);
ImGui::SameLine();
help_marker("Adds a random hit-time offset between the first and last value, in milliseconds.");
help_marker("Adds a random hit-time offset generated using a normal distribution with given mean and standard deviation.");

ImGui::InputInt("Compensation", &maniac::config.compensation_offset);
ImGui::SameLine();
Expand Down
4 changes: 2 additions & 2 deletions app/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ void window::start(const std::function<void()> &body) {
WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL,
NULL, NULL, NULL, _T("maniac"), NULL};
::RegisterClassEx(&wc);
HWND hwnd = ::CreateWindow(wc.lpszClassName, _T("maniac"), WS_OVERLAPPEDWINDOW, 100, 100, 500,
300, NULL, NULL, wc.hInstance, NULL);
HWND hwnd = ::CreateWindow(wc.lpszClassName, _T("maniac"), WS_OVERLAPPEDWINDOW, 100, 100, 550,
350, NULL, NULL, wc.hInstance, NULL);

// Initialize Direct3D
if (!CreateDeviceD3D(hwnd)) {
Expand Down
24 changes: 15 additions & 9 deletions lib/humanization.cpp
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
#include <maniac/common.h>
#include <maniac/maniac.h>

void maniac::randomize(std::vector<osu::HitObject> &hit_objects, std::pair<int, int> range) {
if (!range.first && !range.second)
return;
void maniac::randomize(std::vector<osu::HitObject> &hit_objects, int mean, int stddev) {
if (stddev <= 0) {
return;
}

std::random_device rd;
std::mt19937 gen(rd());
std::mt19937 gen{rd()};

std::uniform_int_distribution<> distr(range.first, range.second);
std::normal_distribution<> distr{static_cast<double>(mean), static_cast<double>(stddev)};

for (auto &hit_object : hit_objects) {
// if it's a slider we want to randomize start and end, if it's not we ignore end anyway
hit_object.start_time += distr(gen);
hit_object.end_time += distr(gen);
hit_object.start_time += std::round(distr(gen));
hit_object.end_time += std::round(distr(gen));
}

debug("randomized %d hit objects with a range of [%d, %d]", hit_objects.size(), range.first,
range.second);
debug("randomized %d hit objects with offsets along a normal distribution with mean %d and stddev %d",
hit_objects.size(), mean, stddev);
}

void maniac::humanize_static(std::vector<osu::HitObject> &hit_objects, int modifier) {
Expand Down Expand Up @@ -65,6 +66,11 @@ void maniac::humanize_dynamic(std::vector<osu::HitObject> &hit_objects, int modi

constexpr auto max_delta = 1000;

std::random_device rd;
std::mt19937 gen(rd());

std::uniform_int_distribution<> distr(0, 1);

for (int i = 0; i < hit_objects.size(); i++) {
auto &cur = hit_objects.at(i);

Expand Down
27 changes: 22 additions & 5 deletions lib/include/maniac/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@

namespace maniac {
struct config {
static constexpr int VERSION = 2;

static constexpr auto STATIC_HUMANIZATION = 0;
static constexpr auto DYNAMIC_HUMANIZATION = 1;

int tap_time = 20;
bool mirror_mod = false;
int compensation_offset = -15;
int humanization_modifier = 0;
std::pair<int, int> randomization_range = { 0, 0 };
int randomization_mean = 0;
int randomization_stddev = 0;
int humanization_type = DYNAMIC_HUMANIZATION;

// TODO: This isn't configurable yet, use a non-shit config format
Expand All @@ -31,12 +34,23 @@ namespace maniac {
return;
}

int version = -1;

file.read(reinterpret_cast<char *>(&version), sizeof version);

if (version != VERSION) {
// TODO: Use a non-shit config format
debug("config has outdated version, ignoring");

return;
}

file.read(reinterpret_cast<char *>(&tap_time), sizeof tap_time);
file.read(reinterpret_cast<char *>(&mirror_mod), sizeof mirror_mod);
file.read(reinterpret_cast<char *>(&compensation_offset), sizeof compensation_offset);
file.read(reinterpret_cast<char *>(&humanization_modifier), sizeof humanization_modifier);
file.read(reinterpret_cast<char *>(&randomization_range.first), sizeof randomization_range.first);
file.read(reinterpret_cast<char *>(&randomization_range.second), sizeof randomization_range.second);
file.read(reinterpret_cast<char *>(&randomization_mean), sizeof randomization_mean);
file.read(reinterpret_cast<char *>(&randomization_stddev), sizeof randomization_stddev);
file.read(reinterpret_cast<char *>(&humanization_type), sizeof humanization_type);

debug("loaded config from file");
Expand All @@ -51,12 +65,15 @@ namespace maniac {
return;
}

int version = VERSION;

file.write(reinterpret_cast<char *>(&version), sizeof version);
file.write(reinterpret_cast<char *>(&tap_time), sizeof tap_time);
file.write(reinterpret_cast<char *>(&mirror_mod), sizeof mirror_mod);
file.write(reinterpret_cast<char *>(&compensation_offset), sizeof compensation_offset);
file.write(reinterpret_cast<char *>(&humanization_modifier), sizeof humanization_modifier);
file.write(reinterpret_cast<char *>(&randomization_range.first), sizeof randomization_range.first);
file.write(reinterpret_cast<char *>(&randomization_range.second), sizeof randomization_range.second);
file.write(reinterpret_cast<char *>(&randomization_mean), sizeof randomization_mean);
file.write(reinterpret_cast<char *>(&randomization_stddev), sizeof randomization_stddev);
file.write(reinterpret_cast<char *>(&humanization_type), sizeof humanization_type);

debug("wrote config to file");
Expand Down
2 changes: 1 addition & 1 deletion lib/include/maniac/maniac.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ namespace maniac {

void block_until_playing();

void randomize(std::vector<osu::HitObject> &hit_objects, std::pair<int, int> range);
void randomize(std::vector<osu::HitObject> &hit_objects, int mean, int stddev);
void humanize_static(std::vector<osu::HitObject> &hit_objects, int modifier);
void humanize_dynamic(std::vector<osu::HitObject> &hit_objects, int modifier);

Expand Down

0 comments on commit 1b46ea2

Please sign in to comment.