Etterna 0.74.4
Loading...
Searching...
No Matches
OHJ.h
1#pragma once
2#include "../MetaIntervalHandInfo.h"
3#include "../HD_Sequencers/OHJSequencing.h"
4
9{
10 const CalcPatternMod _pmod = OHJumpMod;
11 const std::string name = "OHJumpMod";
12
13#pragma region params
14
15 float min_mod = 0.75F;
16 float max_mod = 1.F;
17
18 float max_seq_weight = 0.65F;
19 float max_seq_pool = 1.2F;
20 float max_seq_scaler = 2.F;
21
22 float prop_pool = 1.5F;
23 float prop_scaler = 1.F;
24
25 const std::vector<std::pair<std::string, float*>> _params{
26 { "min_mod", &min_mod },
27 { "max_mod", &max_mod },
28
29 { "max_seq_weight", &max_seq_weight },
30 { "max_seq_pool", &max_seq_pool },
31 { "max_seq_scaler", &max_seq_scaler },
32
33 { "prop_pool", &prop_pool },
34 { "prop_scaler", &prop_scaler },
35 };
36#pragma endregion params and param map
37
38 OHJ_Sequencer ohj;
39 int max_ohjump_seq_taps = 0;
40 int cc_taps = 0;
41
42 float floatymcfloatface = 0.F;
43 // number of jumps scaled to total taps in hand
44 float base_seq_prop = 0.F;
45 // size of sequence scaled to total taps in hand
46 float base_jump_prop = 0.F;
47
48 float max_seq_component = neutral;
49 float prop_component = neutral;
50 float pmod = neutral;
51
52#pragma region generic functions
53
54 void full_reset()
55 {
56 ohj.zero();
57
58 max_ohjump_seq_taps = 0;
59 cc_taps = 0;
60
61 floatymcfloatface = 0.F;
62 base_seq_prop = 0.F;
63 base_jump_prop = 0.F;
64
65 max_seq_component = neutral;
66 prop_component = neutral;
67 pmod = neutral;
68 }
69
70#pragma endregion
71
72 void advance_sequencing(const col_type& ct, const base_type& bt)
73 {
74 ohj(ct, bt);
75 }
76
77 // build component based on max sequence relative to hand taps
78 void set_max_seq_comp()
79 {
80 max_seq_component = max_seq_pool - (base_seq_prop * max_seq_scaler);
81 max_seq_component = max_seq_component < 0.1F ? 0.1F : max_seq_component;
82 max_seq_component = fastsqrt(max_seq_component);
83 }
84
85 // build component based on number of jumps relative to hand taps
86 void set_prop_comp()
87 {
88 prop_component = prop_pool - (base_jump_prop * prop_scaler);
89 prop_component = prop_component < 0.1F ? 0.1F : prop_component;
90 prop_component = fastsqrt(prop_component);
91 }
92
93 void set_pmod(const metaItvHandInfo& mitvhi)
94 {
95 const auto& itvhi = mitvhi._itvhi;
96
97 cc_taps = mitvhi._base_types[base_left_right] +
98 mitvhi._base_types[base_right_left];
99
100 assert(cc_taps >= 0);
101
102 // if cur_seq > max when we ended the interval, grab it
103 max_ohjump_seq_taps = ohj.cur_seq_taps > ohj.max_seq_taps
104 ? ohj.cur_seq_taps
105 : ohj.max_seq_taps;
106
107 /* case optimization start */
108
109 // nothing here or there are no ohjumps
110 if (itvhi.get_taps_nowi() == 0 ||
111 itvhi.get_col_taps_nowi(col_ohjump) == 0) {
112 pmod = neutral;
113 return;
114 }
115
116 // everything in the interval is in an ohj sequence
117 if (max_ohjump_seq_taps >= itvhi.get_taps_nowi()) {
118 pmod = min_mod;
119 return;
120 }
121
122 /* prop scaling only case */
123
124 // no repeated oh jumps, prop scale only based on jumps taps in hand
125 // taps if the jump was immediately broken by a cross column single tap
126 // we can have values of 1, otherwise 2
127 if (max_ohjump_seq_taps < 3) {
128
129 // need to set now
130 base_jump_prop =
131 itvhi.get_col_taps_nowf(col_ohjump) / itvhi.get_taps_nowf();
132 set_prop_comp();
133
134 pmod = std::clamp(prop_component, min_mod, max_mod);
135 return;
136 }
137
138 /* seq scaling only case */
139
140 // if this is true we have some combination of single notes
141 // and jumps where the single notes are all on the same
142 // column
143 if (cc_taps == 0) {
144 // we don't want to treat 2[12][12][12]2222 2222[12][12][12]2
145 // differently, so use the max sequence here exclusively
146 // shortcut mod calculations, we need the base props now
147
148 // build now
149 floatymcfloatface = static_cast<float>(max_ohjump_seq_taps);
150 base_seq_prop = floatymcfloatface / itvhi.get_taps_nowf();
151 set_max_seq_comp();
152
153 pmod = std::clamp(max_seq_component, min_mod, max_mod);
154 return;
155 }
156
157 /* case optimization end */
158
159 // for js we lean into max sequences more, since they're better
160 // indicators of inflated difficulty
161
162 // set either after case optimizations or in case optimizations, after
163 // the simple checks, for optimization
164 floatymcfloatface = static_cast<float>(max_ohjump_seq_taps);
165 base_seq_prop = floatymcfloatface / mitvhi._itvhi.get_taps_nowf();
166 set_max_seq_comp();
167 max_seq_component = std::clamp(max_seq_component, 0.1F, max_mod);
168
169 base_jump_prop =
170 itvhi.get_col_taps_nowf(col_ohjump) / itvhi.get_taps_nowf();
171 set_prop_comp();
172 prop_component = std::clamp(prop_component, 0.1F, max_mod);
173
174 pmod = weighted_average(
175 max_seq_component, prop_component, max_seq_weight, 1.F);
176 pmod = std::clamp(pmod, min_mod, max_mod);
177 }
178
179 auto operator()(const metaItvHandInfo& mitvhi) -> float
180 {
181 set_pmod(mitvhi);
182
183 interval_end();
184 return pmod;
185 }
186
187 void interval_end()
188 {
189 // reset any interval stuff here
190 cc_taps = 0;
191 ohj.max_seq_taps = 0;
192 max_ohjump_seq_taps = 0;
193 }
194};
auto get_taps_nowf() const -> float
cast to float for divisioning and clean screen
Definition IntervalHandInfo.h:141
Definition OHJSequencing.h:8
Definition OHJ.h:9
this may prove to be overkill
Definition MetaIntervalHandInfo.h:6