Etterna 0.74.4
Loading...
Searching...
No Matches
FlamSequencing.h
1#pragma once
2#include <array>
3#include <cassert>
4
5static const int max_flam_jammies = 4;
6
10struct flam
11{
13 unsigned unsigned_unseen = 0U;
14
19 int size = 1;
20
23 bool flammin = false;
24
27 std::array<float, 3> ms = {
28 0.F,
29 0.F,
30 0.F,
31 };
32
34 auto comma_comma_coolmeleon(const unsigned& notes) const -> bool
35 {
36 return (unsigned_unseen & notes) == 0U;
37 }
38
40 auto get_dur() -> float
41 {
42 // cba to loop
43 switch (size) {
44 case 1:
45 // can't have 1 row flams
46 assert(0);
47 case 2:
48 return ms[0];
49 case 3:
50 return ms[0] + ms[1];
51 case 4:
52 return ms[0] + ms[1] + ms[2];
53 default:
54 assert(0);
55 break;
56 }
57 assert(0);
58 return 0.F;
59 }
60
62 void start(const float& ms_now, const unsigned& notes)
63 {
64 flammin = true;
65 unsigned_unseen = 0U;
66
67 grow(ms_now, notes);
68 }
69
71 void grow(const float& ms_now, const unsigned& notes)
72 {
73 if (size == max_flam_jammies) {
74 return;
75 }
76
77 unsigned_unseen |= notes;
78 ms.at(size - 1) = ms_now;
79
80 // adjust size after setting ms, size starts at 1
81 ++size;
82 }
83
84 void reset()
85 {
86 flammin = false;
87 size = 1;
88 }
89};
90
94{
97
99 float group_tol = 0.F;
101 float step_tol = 0.F;
102 float mod_scaler = 0.F;
103
106
112
113 std::array<float, 4> mod_parts = { 1.F, 1.F, 1.F, 1.F };
114
120
121 void set_params(const float& gt, const float& st, const float& ms)
122 {
123 group_tol = gt;
124 step_tol = st;
125 mod_scaler = ms;
126 }
127
128 void complete_seq()
129 {
130 if (flam_counter < max_flam_jammies) {
131 mod_parts.at(flam_counter) = construct_mod_part();
132 ++flam_counter;
133 } else {
134 // bro its just flams
136 }
137
138 flim.reset();
139 }
140
141 auto flammin_col_check(const unsigned& notes) -> bool
142 {
143 // this function should never be used to start a flam
144 assert(flim.flammin);
145
146 // note : in order to prevent the last row of a quad flam from being
147 // elibible to start a new flam (logically it makes no sense), instead
148 // of catching full quads and resetting when we get them, we'll let them
149 // pass throgh into the next note row, no matter what the row is it will
150 // fail the xor check and be reset then, making only the row _after_ the
151 // full flam eligible for a new start
152 return flim.comma_comma_coolmeleon(notes);
153 }
154
156 auto flammin_tol_check(const float& ms_now) -> bool
157 {
158 // check if ms from last row is greater than the group tolerance
159 if (ms_now > group_tol) {
160 return false;
161 }
162
163 // check if the new flam duration would exceed the group tolerance with
164 // the current row added
165 if (flim.get_dur() + ms_now > group_tol) {
166 return false;
167 }
168
169 // we may be able to continue the sequence, run the col check
170 return true;
171 }
172
173 void operator()(const float& ms_now, const unsigned& notes)
174 {
175 // if we already have the max number of flams
176 // (maybe should remove this shortcut optimization)
177 // seems like we never even hit it so...
179 return;
180 }
181
182 // haven't started, if we're under the step tolerance, start
183 if (!flim.flammin) {
184 // 99.99% of cases
185 if (ms_now > step_tol) {
186 return;
187 }
188 {
189 flim.start(ms_now, notes);
190 }
191 } else {
192 // passed the tolerance checks, run the col checks
193 if (flammin_tol_check(ms_now)) {
194
195 // passed col check, advance flam
196 if (flammin_col_check(notes)) {
197 flim.grow(ms_now, notes);
198 } else {
199 // we failed the col check, but we've passed the tol checks,
200 // which means this row is eligible to begin a new flam
201 // sequence, complete the one that exists and start again
202 complete_seq();
203 flim.start(ms_now, notes);
204 }
205 } else {
206 // reset if we exceed tolerance checks
207 complete_seq();
208 }
209 }
210 }
211
212 void handle_interval_end()
213 {
214 // we probably don't want to do this, just let it build potential
215 // sequences across intervals
216 // flam.reset();
217
218 the_fifth_flammament = false;
219 flam_counter = 0;
220
221 // reset everything to 1, as we build flams we will replace 1 with < 1
222 // values, the more there are, the lower (stronger) the pattern mod
223 mod_parts.fill(1.F);
224 }
225
226 auto construct_mod_part() -> float
227 {
228 // total duration of flam
229 float dur = flim.get_dur();
230
231 // scale to size of flam, we want jumpflams to punish less than quad
232 // flams (while still downscaling jumptrill flams)
233 // flams that register as 95% of the size adjusted window will be
234 // punished less than those that register at 2%
235 float dur_prop = dur / group_tol;
236 dur_prop /= (static_cast<float>(flim.size) / mod_scaler);
237 dur_prop = std::clamp(dur_prop, 0.F, 1.F);
238
239 return fastsqrt(dur_prop);
240 }
241};
Definition FlamSequencing.h:94
auto flammin_tol_check(const float &ms_now) -> bool
check for anything that would break the sequence
Definition FlamSequencing.h:156
float step_tol
tolerance for each column step
Definition FlamSequencing.h:101
flam flim
current tracking flam
Definition FlamSequencing.h:96
float group_tol
scan for flam chords in this window
Definition FlamSequencing.h:99
std::array< float, 4 > mod_parts
Definition FlamSequencing.h:113
int flam_counter
number of flams
Definition FlamSequencing.h:105
bool the_fifth_flammament
Definition FlamSequencing.h:119
Definition FlamSequencing.h:11
std::array< float, 3 > ms
Definition FlamSequencing.h:27
void start(const float &ms_now, const unsigned &notes)
begin flam sequence processing
Definition FlamSequencing.h:62
int size
Definition FlamSequencing.h:19
unsigned unsigned_unseen
columns seen
Definition FlamSequencing.h:13
auto get_dur() -> float
gather cumulative millisecond gap for entire flam
Definition FlamSequencing.h:40
auto comma_comma_coolmeleon(const unsigned &notes) const -> bool
is this row exclusively additive with the current flam sequence?
Definition FlamSequencing.h:34
bool flammin
Definition FlamSequencing.h:23
void grow(const float &ms_now, const unsigned &notes)
continue flam sequence processing
Definition FlamSequencing.h:71