Etterna 0.74.4
Loading...
Searching...
No Matches
CalcWindow.h
1#pragma once
2#include "PatternModHelpers.h"
3
4#include <array>
5
6static const int max_moving_window_size = 6;
7
9static const int ccacc_timing_check_size = 3;
10
13template<typename T>
15{
19 void operator()(const T& new_val)
20 {
21 // update the window
22 for (auto i = 1; i < max_moving_window_size; ++i) {
23 _itv_vals.at(i - 1) = _itv_vals.at(i);
24 }
25
26 // set new value at size - 1
27 _itv_vals.at(max_moving_window_size - 1) = new_val;
28 }
29
31 auto operator[](const int& pos) const -> T
32 {
33 assert(pos >= 0 && pos < max_moving_window_size);
34 return _itv_vals.at(pos);
35 }
36
38 [[nodiscard]] auto get_now() const -> T { return _itv_vals.back(); }
40 [[nodiscard]] auto get_last() const -> T
41 {
42 return _itv_vals.at(max_moving_window_size - 2);
43 }
44
46 [[nodiscard]] auto get_total_for_window(const int& window) const -> T
47 {
48 T o = static_cast<T>(0);
49 auto i = max_moving_window_size;
50 while (i > max_moving_window_size - window) {
51 --i;
52 o += _itv_vals.at(i);
53 }
54
55 return o;
56 }
57
59 [[nodiscard]] auto get_max_for_window(const int& window) const -> T
60 {
61 T o = static_cast<T>(0);
62 auto i = max_moving_window_size;
63 while (i > max_moving_window_size - window) {
64 --i;
65 o = _itv_vals.at(i) > o ? _itv_vals.at(i) : o;
66 }
67
68 return o;
69 }
70
72 [[nodiscard]] auto get_min_for_window(const int& window) const -> T
73 {
74 T o = get_now();
75 auto i = max_moving_window_size;
76 while (i > max_moving_window_size - window) {
77 --i;
78 o = _itv_vals.at(i) < o ? _itv_vals.at(i) : o;
79 }
80
81 return o;
82 }
83
85 [[nodiscard]] auto get_mean_of_window(const int& window) const -> float
86 {
87 T o = static_cast<T>(0);
88
89 auto i = max_moving_window_size;
90 while (i > max_moving_window_size - window) {
91 --i;
92 o += _itv_vals.at(i);
93 }
94
95 return static_cast<float>(o) / static_cast<float>(window);
96 }
97
100 [[nodiscard]] auto get_total_for_windowf(const int& window) const -> float
101 {
102 auto o = 0.F;
103 auto i = max_moving_window_size;
104 while (i > max_moving_window_size - window) {
105 --i;
106 o += _itv_vals.at(i);
107 }
108
109 return o;
110 }
111
113 [[nodiscard]] auto get_cv_of_window(const int& window) const -> float
114 {
115 auto sd = 0.F;
116 const auto avg = get_mean_of_window(window);
117
118 assert(avg > 0.F);
119
120 // if window is 4, we check values 6/5/4/3, since this window is always
121 // 6
122 auto i = max_moving_window_size;
123 while (i > max_moving_window_size - window) {
124 --i;
125 sd += (static_cast<float>(_itv_vals.at(i)) - avg) *
126 (static_cast<float>(_itv_vals.at(i)) - avg);
127 }
128
129 return fastsqrt(sd / static_cast<float>(window)) / avg;
130 }
131
132 /* cv checks for pattern detection */
133
134 // comment moved from wrjt
135 /* we don't want to suppress actual streams that use this pattern, so we
136 * will keep a fairly tight requirement on the ms variance we are currently
137 * assuming we have xyyx always, and are not interested in xxyy as a part of
138 * xxyyxxyyxx transitions, given these conditions we can do some pretty neat
139 * stuff seq_ms 0 and 2 will both be cross column ms values, or left->right
140 * / right->left, seq_ms 1 will always be an anchor value, so, right->right
141 * for example. our interest is in hard nerfing long chains of xyyx patterns
142 * that won't get picked up by any of the roll scalers or balance scalers,
143 * but are still jumptrillable, for this condition to be true the anchor ms
144 * length has to be within a certain ratio of the cross column ms lengths,
145 * enabling the cross columns to be hit like jumptrilled flams, the optimal
146 * ratio for inflating nps is about 3:1, this is short enough that the nps
147 * boost is still high, but long enough that it doesn't become endless
148 * minijacking on the anchor given these conditions we can divide seq_ms[1]
149 * by 3 and cv check the array, with 2 identical values cc values, even if
150 * the anchor ratio floats between 2:1 and 4:1 the cv should still be below
151 * 0.25, which is a sensible cutoff that should avoid punishing
152 * happenstances of this pattern in just regular files */
153
155 [[nodiscard]] auto ccacc_timing_check(const float& factor,
156 const float& threshold) -> bool
157 {
158 // anchor in the center, divide by factor, 4 is the middle value of the
159 // last 3
160 _itv_vals[4] /= factor;
161
162 // ccacc is always window of 3
163 const auto o = get_cv_of_window(ccacc_timing_check_size);
164
165 // set value back
166 _itv_vals[4] *= factor;
167
168 return o < threshold;
169 }
170
171 // if using these functions, it's the responsibility of whatever is filling
172 // this container to ensure that the values it's filling it with will
173 // actually produce usable results
174
176 [[nodiscard]] auto acca_timing_check(const float& factor,
177 const float& threshold) -> bool
178 {
179 // cc in the center, multiply by factor
180 _itv_vals[4] *= factor;
181 const auto o = get_cv_of_window(ccacc_timing_check_size);
182 _itv_vals[4] /= factor;
183 return o < threshold;
184 }
185
187 [[nodiscard]] auto roll_timing_check(const float& factor,
188 const float& threshold) -> bool
189 {
190 // we are looking at cccccc formation, which could be a roll or an oht,
191 // we don't know yet, but presumably whatever is calling this only cares
192 // about whether or not this is a roll, since the oht check requires no
193 // manipulation, just a vanilla cv call
194
195 // we can basically just branch to ccacc or acca checks depending on
196 // which value is higher
197 bool o;
198 if (any_ms_is_greater(_itv_vals[4], _itv_vals[5])) {
199 // if middle is higher, run the ccacc check that will divide it
200 o = ccacc_timing_check(factor, threshold);
201 } else {
202 // otherwise run acca and multiply the center
203 o = acca_timing_check(factor, threshold);
204 }
205
206 return o;
207 }
208
210 void zero() { _itv_vals.fill(static_cast<T>(0)); }
211 void fill(const T& val) { _itv_vals.fill(val); }
212
213 private:
214 std::array<T, max_moving_window_size> _itv_vals = { 0, 0, 0, 0, 0, 0 };
215};
Definition CalcWindow.h:15
void zero()
set everything to zero
Definition CalcWindow.h:210
auto get_max_for_window(const int &window) const -> T
get the max for the moving window up to a given size
Definition CalcWindow.h:59
auto get_total_for_windowf(const int &window) const -> float
Definition CalcWindow.h:100
auto operator[](const int &pos) const -> T
index moving window like an array
Definition CalcWindow.h:31
void operator()(const T &new_val)
Definition CalcWindow.h:19
auto get_min_for_window(const int &window) const -> T
get the min for the moving window up to a given size
Definition CalcWindow.h:72
auto get_total_for_window(const int &window) const -> T
get the sum for the moving window up to a given size
Definition CalcWindow.h:46
auto get_mean_of_window(const int &window) const -> float
get the mean for the moving window up to a given size
Definition CalcWindow.h:85
auto roll_timing_check(const float &factor, const float &threshold) -> bool
perform cv check internally
Definition CalcWindow.h:187
auto get_cv_of_window(const int &window) const -> float
get the coefficient of variance of the moving window up to a given size
Definition CalcWindow.h:113
auto ccacc_timing_check(const float &factor, const float &threshold) -> bool
perform cv check internally
Definition CalcWindow.h:155
auto get_now() const -> T
get most recent value in moving window
Definition CalcWindow.h:38
auto acca_timing_check(const float &factor, const float &threshold) -> bool
perform cv check internally
Definition CalcWindow.h:176
auto get_last() const -> T
get oldest value in moving window
Definition CalcWindow.h:40