Implement pattern knobs here
[SugarCubes.git] / MarkSlee.pde
CommitLineData
49815cc0
MS
1class SpaceTime extends SCPattern {
2
3 SinLFO pos = new SinLFO(0, 15, 3000);
4 SinLFO rate = new SinLFO(1000, 9000, 13000);
5 SinLFO falloff = new SinLFO(10, 70, 5000);
3f8be614
MS
6 float angle = 0;
7
8 BasicParameter rateParameter = new BasicParameter("RATE", 0.5);
9 BasicParameter sizeParameter = new BasicParameter("SIZE", 0.5);
49815cc0
MS
10
11 public SpaceTime(GLucose glucose) {
12 super(glucose);
13 addModulator(pos).trigger();
14 addModulator(rate).trigger();
15 addModulator(falloff).trigger();
16 pos.modulateDurationBy(rate);
3f8be614
MS
17 addParameter(rateParameter);
18 addParameter(sizeParameter);
49815cc0 19 }
3f8be614
MS
20
21 public void onParameterChanged(LXParameter parameter) {
22 if (parameter == rateParameter) {
23 rate.stop().setValue(9000 - 8000*parameter.getValuef());
24 } else if (parameter == sizeParameter) {
25 falloff.stop().setValue(70 - 60*parameter.getValuef());
49815cc0
MS
26 }
27 }
28
29 void run(int deltaMs) {
3f8be614
MS
30 angle += deltaMs * 0.0007;
31 float sVal1 = Strip.list.size() * (0.5 + 0.5*sin(angle));
32 float sVal2 = Strip.list.size() * (0.5 + 0.5*cos(angle));
49815cc0
MS
33
34 float pVal = pos.getValuef();
35 float fVal = falloff.getValuef();
36
37 int s = 0;
38 for (Strip strip : Strip.list) {
39 int i = 0;
40 for (Point p : strip.points) {
41 colors[p.index] = color(
3f8be614
MS
42 (lx.getBaseHuef() + 360 - p.fy*.2 + p.fz * .3) % 360,
43 constrain(.4 * min(abs(s - sVal1), abs(s - sVal2)), 20, 100),
49815cc0
MS
44 max(0, 100 - fVal*abs(i - pVal))
45 );
46 ++i;
47 }
3f8be614 48 ++s;
49815cc0
MS
49 }
50 }
51}
52
53class Swarm extends SCPattern {
54
55 SawLFO offset = new SawLFO(0, 16, 1000);
56 SinLFO rate = new SinLFO(350, 1200, 63000);
57 SinLFO falloff = new SinLFO(15, 50, 17000);
58 SinLFO fY = new SinLFO(0, 250, 19000);
59 SinLFO fZ = new SinLFO(0, 127, 11000);
60 SinLFO hOffY = new SinLFO(0, 255, 13000);
61
62 public Swarm(GLucose glucose) {
63 super(glucose);
64 addModulator(offset).trigger();
65 addModulator(rate).trigger();
66 addModulator(falloff).trigger();
67 addModulator(fY).trigger();
68 addModulator(fZ).trigger();
69 addModulator(hOffY).trigger();
70 offset.modulateDurationBy(rate);
71 }
72
73 float modDist(float v1, float v2, float mod) {
74 v1 = v1 % mod;
75 v2 = v2 % mod;
76 if (v2 > v1) {
77 return min(v2-v1, v1+mod-v2);
78 }
79 else {
80 return min(v1-v2, v2+mod-v1);
81 }
82 }
83
84 void run(int deltaMs) {
85 float s = 0;
86 for (Strip strip : Strip.list) {
87 int i = 0;
88 for (Point p : strip.points) {
89 float fV = max(-1, 1 - dist(p.fy/2., p.fz, fY.getValuef()/2., fZ.getValuef()) / 64.);
90 colors[p.index] = color(
91 (lx.getBaseHuef() + 0.3 * abs(p.fy - hOffY.getValuef())) % 360,
92 constrain(80 + 40 * fV, 0, 100),
93 constrain(100 - (30 - fV * falloff.getValuef()) * modDist(i + (s*63)%61, offset.getValuef(), 16), 0, 100)
94 );
95 ++i;
96 }
97 ++s;
98 }
99 }
100}
101
102class SwipeTransition extends SCTransition {
3f8be614
MS
103
104 final BasicParameter bleed = new BasicParameter("WIDTH", 0.5);
105
49815cc0
MS
106 SwipeTransition(GLucose glucose) {
107 super(glucose);
108 setDuration(5000);
3f8be614 109 addParameter(bleed);
49815cc0
MS
110 }
111
112 void computeBlend(int[] c1, int[] c2, double progress) {
3f8be614
MS
113 float bleedf = 10 + bleed.getValuef() * 200.;
114 float yPos = (float) (-bleedf + progress * (255. + bleedf));
49815cc0 115 for (Point p : Point.list) {
3f8be614 116 float d = (p.fy - yPos) / bleedf;
49815cc0
MS
117 if (d < 0) {
118 colors[p.index] = c2[p.index];
3f8be614
MS
119 }
120 else if (d > 1) {
49815cc0 121 colors[p.index] = c1[p.index];
3f8be614
MS
122 }
123 else {
49815cc0
MS
124 colors[p.index] = lerpColor(c2[p.index], c1[p.index], d, RGB);
125 }
126 }
127 }
128}
129
130class CubeEQ extends SCPattern {
131
132 private FFT fft = null;
133 private LinearEnvelope[] bandVals = null;
134 private int avgSize;
135
3f8be614
MS
136 private final BasicParameter thrsh = new BasicParameter("LVL", 0.35);
137 private final BasicParameter range = new BasicParameter("RANG", 0.45);
138 private final BasicParameter edge = new BasicParameter("EDGE", 0.5);
139 private final BasicParameter speed = new BasicParameter("SPD", 0.5);
140 private final BasicParameter tone = new BasicParameter("TONE", 0.5);
141 private final BasicParameter clr = new BasicParameter("CLR", 0.5);
49815cc0
MS
142
143 public CubeEQ(GLucose glucose) {
144 super(glucose);
3f8be614
MS
145 addParameter(thrsh);
146 addParameter(range);
147 addParameter(edge);
148 addParameter(speed);
149 addParameter(tone);
150 addParameter(clr);
49815cc0 151 }
3f8be614 152
49815cc0
MS
153 protected void onActive() {
154 if (this.fft == null) {
155 this.fft = new FFT(lx.audioInput().bufferSize(), lx.audioInput().sampleRate());
156 this.fft.window(FFT.HAMMING);
157 this.fft.logAverages(40, 1);
158 this.avgSize = this.fft.avgSize();
159 this.bandVals = new LinearEnvelope[this.avgSize];
160 for (int i = 0; i < this.bandVals.length; ++i) {
161 this.addModulator(this.bandVals[i] = (new LinearEnvelope(0, 0, 700+i*4))).trigger();
162 }
163 }
164 }
165
166 public void run(int deltaMs) {
167 this.fft.forward(this.lx.audioInput().mix);
168 float toneConst = .35 + .4 * (tone.getValuef() - 0.5);
169 float edgeConst = 2 + 30*(edge.getValuef()*edge.getValuef()*edge.getValuef());
3f8be614 170
49815cc0
MS
171 for (int i = 0; i < avgSize; ++i) {
172 float value = this.fft.getAvg(i);
173 value = 20*log(1 + sqrt(value));
174 float sqdist = avgSize - i;
175 value -= toneConst*sqdist*sqdist + .5*sqdist;
176 value *= 6;
177 if (value > this.bandVals[i].getValue()) {
178 this.bandVals[i].setEndVal(value, 40).trigger();
3f8be614
MS
179 }
180 else {
49815cc0
MS
181 this.bandVals[i].setEndVal(value, 1000 - 900*speed.getValuef()).trigger();
182 }
183 }
3f8be614 184
49815cc0
MS
185 float jBase = 120 - 360*thrsh.getValuef();
186 float jConst = 300.*(1-range.getValuef());
187 float clrConst = 1.1 + clr.getValuef();
188
189 for (Point p : Point.list) {
190 float avgIndex = constrain((p.fy / 256. * avgSize), 0, avgSize-2);
191 int avgFloor = (int) avgIndex;
192 float j = jBase + jConst * (p.fz / 128.);
193 float value = lerp(
3f8be614
MS
194 this.bandVals[avgFloor].getValuef(),
195 this.bandVals[avgFloor+1].getValuef(),
196 avgIndex-avgFloor
197 );
198
49815cc0
MS
199 float b = constrain(edgeConst * (value - j), 0, 100);
200 colors[p.index] = color(
3f8be614
MS
201 (480 + lx.getBaseHuef() - min(clrConst*p.fz, 120)) % 360,
202 100,
203 b);
204 }
205 }
206}
207
208class BoomEffect extends SCEffect {
209
210 final BasicParameter falloff = new BasicParameter("WIDTH", 0.5);
211 final BasicParameter speed = new BasicParameter("SPD", 0.5);
212 final BasicParameter bright = new BasicParameter("BRT", 1.0);
213 final BasicParameter sat = new BasicParameter("SAT", 0.2);
214 List<Layer> layers = new ArrayList<Layer>();
215
216 class Layer {
217 LinearEnvelope boom = new LinearEnvelope(-40, 500, 1300);
218
219 Layer() {
220 addModulator(boom);
221 trigger();
222 }
223
224 void trigger() {
225 float falloffv = falloffv();
226 boom.setRange(-100 / falloffv, 500 + 100/falloffv, 4000 - speed.getValuef() * 3300);
227 boom.trigger();
228 }
229
230 void doApply(int[] colors) {
231 float brightv = 100 * bright.getValuef();
232 float falloffv = falloffv();
233 float satv = sat.getValuef() * 100;
234 float huev = lx.getBaseHuef();
235 for (Point p : Point.list) {
236 colors[p.index] = blendColor(
237 colors[p.index],
238 color(huev, satv, constrain(brightv - falloffv*abs(boom.getValuef() - dist(2*p.fx, p.fy, 2*p.fz, 128, 128, 128)), 0, 100)),
239 ADD);
240 }
241 }
242 }
243
244 BoomEffect(GLucose glucose) {
245 super(glucose, true);
246 addParameter(falloff);
247 addParameter(speed);
248 addParameter(bright);
249 addParameter(sat);
250 }
251
252 public void onEnable() {
253 for (Layer l : layers) {
254 if (!l.boom.isRunning()) {
255 l.trigger();
256 return;
257 }
258 }
259 layers.add(new Layer());
260 }
261
262 private float falloffv() {
263 return 20 - 19 * falloff.getValuef();
264 }
265
266 public void onTrigger() {
267 onEnable();
268 }
269
270 public void doApply(int[] colors) {
271 for (Layer l : layers) {
272 if (l.boom.isRunning()) {
273 l.doApply(colors);
274 }
49815cc0
MS
275 }
276 }
277}
278