Etterna 0.74.4
Loading...
Searching...
No Matches
GenericChordstream.h
1#pragma once
2#include "../../PatternModHelpers.h"
3
7{
8 const CalcPatternMod _pmod = GChordStream;
9 // const std::vector<CalcPatternMod> _dbg = { JSS, JSJ };
10 const std::string name = "GenericChordStreamMod";
11 const int min_tap_size = jump;
12
13#pragma region params
14 float min_mod = 0.6F;
15 float max_mod = 1.1F;
16 float mod_base = 0.F;
17 float prop_buffer = 1.F;
18
19 float total_prop_min = min_mod;
20 float total_prop_max = max_mod;
21 float total_prop_scaler = 2.714F; // ~19/7
22
23 float split_hand_pool = 1.5F;
24 float split_hand_min = 0.9F;
25 float split_hand_max = 1.F;
26 float split_hand_scaler = 1.F;
27
28 float jack_pool = 1.35F;
29 float jack_min = 0.5F;
30 float jack_max = 1.F;
31 float jack_scaler = 1.F;
32
33 float decay_factor = 0.05F;
34
35 const std::vector<std::pair<std::string, float*>> _params{
36 { "min_mod", &min_mod },
37 { "max_mod", &max_mod },
38 { "mod_base", &mod_base },
39 { "prop_buffer", &prop_buffer },
40
41 { "total_prop_scaler", &total_prop_scaler },
42 { "total_prop_min", &total_prop_min },
43 { "total_prop_max", &total_prop_max },
44
45 { "split_hand_pool", &split_hand_pool },
46 { "split_hand_min", &split_hand_min },
47 { "split_hand_max", &split_hand_max },
48 { "split_hand_scaler", &split_hand_scaler },
49
50 { "jack_pool", &jack_pool },
51 { "jack_min", &jack_min },
52 { "jack_max", &jack_max },
53 { "jack_scaler", &jack_scaler },
54
55 { "decay_factor", &decay_factor },
56 };
57#pragma endregion params and param map
58
59 float total_prop = 0.F;
60 float jumptrill_prop = 0.F;
61 float jack_prop = 0.F;
62 float last_mod = min_mod;
63 float pmod = min_mod;
64 float t_taps = 0.F;
65
66 // inline void set_dbg(std::vector<float> doot[], const int& i)
67 //{
68 // doot[JSS][i] = jumptrill_prop;
69 // doot[JSJ][i] = jack_prop;
70 //}
71
72 void full_reset()
73 {
74 last_mod = min_mod;
75 }
76
77 void decay_mod()
78 {
79 pmod = std::clamp(last_mod - decay_factor, min_mod, max_mod);
80 last_mod = pmod;
81 }
82
83 auto operator()(const metaItvInfo& mitvi) -> float
84 {
85 const auto& itvi = mitvi._itvi;
86
87 // empty interval, don't decay js mod or update last_mod
88 if (itvi.total_taps == 0) {
89 return neutral;
90 }
91
92 // at least 1 tap but no jumps
93 if (itvi.taps_by_size.at(min_tap_size) == 0) {
94 decay_mod();
95 return pmod;
96 }
97
98 /* end case optimizations */
99
100 t_taps = static_cast<float>(itvi.total_taps);
101
102 // creepy banana
103 total_prop =
104 static_cast<float>(itvi.taps_by_size.at(min_tap_size) + prop_buffer) /
105 (t_taps - prop_buffer) * total_prop_scaler;
106 total_prop =
107 std::clamp(fastsqrt(total_prop), total_prop_min, total_prop_max);
108
109 // punish lots splithand jumptrills
110 // uhh this might also catch oh jumptrills can't remember
111 jumptrill_prop = std::clamp(
112 split_hand_pool - (static_cast<float>(mitvi.not_js) / t_taps),
113 split_hand_min,
114 split_hand_max);
115
116 // downscale by jack density rather than upscale like cj
117 // theoretically the ohjump downscaler should handle
118 // this but handling it here gives us more flexbility
119 // with the ohjump mod
120 jack_prop = std::clamp(
121 jack_pool - (static_cast<float>(mitvi.actual_jacks) / t_taps),
122 jack_min,
123 jack_max);
124
125 pmod =
126 std::clamp(total_prop * jumptrill_prop * jack_prop, min_mod, max_mod);
127
128 if (mitvi.dunk_it) {
129 pmod *= 0.99F;
130 }
131
132 // set last mod, we're using it to create a decaying mod that won't
133 // result in extreme spikiness if files alternate between js and
134 // hs/stream
135 last_mod = pmod;
136
137 return pmod;
138 }
139};
Definition GenericChordstream.h:7
Definition MetaIntervalInfo.h:20