Skip to content

Commit

Permalink
rewrite roll pmod, rewrite wrjj pmod, tune both | 488
Browse files Browse the repository at this point in the history
this brings nerfs to most files again but more harshly to certain files which abuse jumpjacky patterning
  • Loading branch information
poco0317 committed Aug 17, 2022
1 parent f9b9b4f commit d7593e0
Show file tree
Hide file tree
Showing 4 changed files with 223 additions and 103 deletions.
182 changes: 130 additions & 52 deletions src/Etterna/MinaCalc/Dependent/HD_PatternMods/Roll.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,99 +2,177 @@
#include "../IntervalHandInfo.h"
#include "../HD_Sequencers/GenericSequencing.h"

static const int max_seq_parts = 4;

// contains parts of a modifier constructed from sequences
struct mod_parts
{
std::array<int, max_seq_parts> _parts = { 0, 0, 0, 0 };
};

// contains sequence
struct RollSeq
{
};

// update logic
struct Roll_Sequencer
{
RollSeq _rs;

void advance(const meta_type& mt, SequencerGeneral& _seq) {}
};

struct RollMod
{
const CalcPatternMod _pmod = Roll;
const std::string name = "RollMod";

#pragma region params

float window_param = 2.F;
float min_mod = 0.9F;
float max_mod = 1.F;
float base = 0.1F;
float jj_scaler = .5F;

float min_mod = 0.95F;
float max_mod = 1.05F;
float base = 0.85F;
// ms apart for 2 taps to be considered a jumpjack
// 0.075 is 200 bpm 16th trills
// 0.050 is 300 bpm
// 0.037 is 400 bpm
// 0.020 is 750 bpm (375 bpm 64th)
float ms_threshold = 0.0501F;

float cv_reset = 1.F;
// changes the direction and sharpness of the result curve
// as the jumpjack width is between 0 and ms_threshold
// a higher number here makes numbers closer to ms_threshold
// worth more -- the falloff occurs late
float diff_falloff_power = 1.F;

const std::vector<std::pair<std::string, float*>> _params{
{ "window_param", &window_param },

{ "min_mod", &min_mod },
{ "max_mod", &max_mod },
{ "base", &base },

{ "jj_scaler", &jj_scaler },
{ "ms_threshold", &ms_threshold },
{ "diff_falloff_power", &diff_falloff_power },
};
#pragma endregion params and param map

int window = 0;
Roll_Sequencer _roll{};
CalcMovingWindow<float> _mw_pmod;
// indices
int lc = 0;
int rc = 0;

// a "problem" is a rough value of jumpjackyness
// whereas a 1 is 1 jump and the worst possible flam is nearly 0
// this tracks amount of "problems" in consecutive intervals
float current_problems = 0.F;

float moving_cv = cv_reset;
float pmod = min_mod;
float pmod = neutral;

// timestamps of notes in columns
std::array<float, max_rows_for_single_interval> _left_times{};
std::array<float, max_rows_for_single_interval> _right_times{};

#pragma region generic functions

void full_reset()
{
moving_cv = (moving_cv + cv_reset);
_left_times.fill(s_init);
_right_times.fill(s_init);
current_problems = 0.F;
lc = 0;
rc = 0;

pmod = neutral;
}

void setup()
void setup() {}

#pragma endregion

void check()
{
window =
std::clamp(static_cast<int>(window_param), 1, max_moving_window_size);
// check times in parallel
// any times within the window count as the jumpishjack
// just ... determine the degree of jumpy the jumpyjack is
// using ms ... or something
auto lindex = 0;
auto rindex = 0;
while (lindex < lc && rindex < rc) {
const auto& l = _left_times.at(lindex);
const auto& r = _right_times.at(rindex);
const auto diff = fabsf(l - r);

if (diff <= ms_threshold) {
lindex++;
rindex++;

// given time_scaler = 1
// diff of ms_threshold gives a v of 1
// meaning "1 jumpjack" or "1 problem"
// but a flammy one, is worth not so much of a jumpjack
// (this function at x=[0,1] begins slow and drops fast)
// using std::pow for accuracy here
const auto x = std::pow(diff / std::max(ms_threshold, 0.00001F),
diff_falloff_power);
const auto v = 1 + (x / (x - 2));
current_problems += v;
} else {
// failed case
// throw the oldest value and try again...
if (l > r) {
rindex++;
} else if (r > l) {
lindex++;
} else {
// this case exists to prevent infinite loops
// it should never happen unless you put bad values in
// params
lindex++;
rindex++;
}
}
}
}

void complete_seq() {}

void advance_sequencing(const meta_type& mt, SequencerGeneral& _seq)
void advance_sequencing(const col_type& ct, const float& time_s)
{
//_roll.advance(mt, _seq);
if (lc >= max_rows_for_single_interval ||
rc >= max_rows_for_single_interval) {
// completely impossible condition
// checking for sanity and safety
return;
}

switch (ct) {
case col_left: {
_left_times.at(lc++) = time_s;
break;
}
case col_right: {
_right_times.at(rc++) = time_s;
break;
}
case col_ohjump: {
_left_times.at(lc++) = time_s;
_right_times.at(rc++) = time_s;
break;
}
default:
break;
}
}

void set_pmod(const ItvHandInfo& itvhi, const SequencerGeneral& /*_seq*/)
void set_pmod(const ItvHandInfo& itvhi)
{
if (itvhi.get_taps_nowi() == 0) {
// no taps, no jj
if (itvhi.get_taps_nowi() == 0 || current_problems == 0.F) {
pmod = neutral;
return;
}

pmod = std::clamp(1.F, min_mod, max_mod);
pmod =
1 - (((current_problems * 2.F) * jj_scaler) / itvhi.get_taps_nowf());
pmod = std::clamp(base + pmod, min_mod, max_mod);
}

auto operator()(const ItvHandInfo& itvhi, const SequencerGeneral& _seq)
-> float
auto operator()(const ItvHandInfo& itvhi) -> float
{

set_pmod(itvhi, _seq);
check();
set_pmod(itvhi);

interval_end();
_mw_pmod(pmod);
return neutral;
//_mw_pmod.get_mean_of_window(window);
return pmod;
}

void interval_end() {}
void interval_end()
{
// reset every interval when finished
current_problems = 0.F;
_left_times.fill(s_init);
_right_times.fill(s_init);
lc = 0;
rc = 0;
}
};
#pragma once
Loading

0 comments on commit d7593e0

Please sign in to comment.