SugarCubes sketch initial code dump
[SugarCubes.git] / MarkSlee.pde
1 class 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);
6 float sat = 0;
7
8 BasicKnob rateKnob = new BasicKnob("RATE", 0.5);
9 BasicKnob sizeKnob = new BasicKnob("SIZE", 0.5);
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);
17 addKnob(rateKnob);
18 addKnob(sizeKnob);
19 }
20
21 public void onKnobChange(Knob knob) {
22 if (knob == rateKnob) {
23 rate.stop().setValue(9000 - 8000*knob.getValuef());
24 } else if (knob == sizeKnob) {
25 falloff.stop().setValue(70 - 60*knob.getValuef());
26 }
27 }
28
29 void run(int deltaMs) {
30 sat += deltaMs * 0.00004;
31 float sVal1 = Strip.list.size() * (0.5 + 0.5*sin(sat));
32 float sVal2 = Strip.list.size() * (0.5 + 0.5*cos(sat));
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(
42 (lx.getBaseHuef() + s*.2 + i*3) % 360,
43 min(100, min(abs(s - sVal1), abs(s - sVal2))),
44 max(0, 100 - fVal*abs(i - pVal))
45 );
46 ++i;
47 }
48 }
49 }
50 }
51
52 class Swarm extends SCPattern {
53
54 SawLFO offset = new SawLFO(0, 16, 1000);
55 SinLFO rate = new SinLFO(350, 1200, 63000);
56 SinLFO falloff = new SinLFO(15, 50, 17000);
57 SinLFO fY = new SinLFO(0, 250, 19000);
58 SinLFO fZ = new SinLFO(0, 127, 11000);
59 SinLFO hOffY = new SinLFO(0, 255, 13000);
60
61 public Swarm(GLucose glucose) {
62 super(glucose);
63 addModulator(offset).trigger();
64 addModulator(rate).trigger();
65 addModulator(falloff).trigger();
66 addModulator(fY).trigger();
67 addModulator(fZ).trigger();
68 addModulator(hOffY).trigger();
69 offset.modulateDurationBy(rate);
70 }
71
72 float modDist(float v1, float v2, float mod) {
73 v1 = v1 % mod;
74 v2 = v2 % mod;
75 if (v2 > v1) {
76 return min(v2-v1, v1+mod-v2);
77 }
78 else {
79 return min(v1-v2, v2+mod-v1);
80 }
81 }
82
83 void run(int deltaMs) {
84 float s = 0;
85 for (Strip strip : Strip.list) {
86 int i = 0;
87 for (Point p : strip.points) {
88 float fV = max(-1, 1 - dist(p.fy/2., p.fz, fY.getValuef()/2., fZ.getValuef()) / 64.);
89 colors[p.index] = color(
90 (lx.getBaseHuef() + 0.3 * abs(p.fy - hOffY.getValuef())) % 360,
91 constrain(80 + 40 * fV, 0, 100),
92 constrain(100 - (30 - fV * falloff.getValuef()) * modDist(i + (s*63)%61, offset.getValuef(), 16), 0, 100)
93 );
94 ++i;
95 }
96 ++s;
97 }
98 }
99 }
100
101 class SwipeTransition extends SCTransition {
102 SwipeTransition(GLucose glucose) {
103 super(glucose);
104 setDuration(5000);
105 }
106
107 void computeBlend(int[] c1, int[] c2, double progress) {
108 float bleed = 50.;
109 float yPos = (float) (-bleed + progress * (255. + bleed));
110 for (Point p : Point.list) {
111 float d = (p.fy - yPos) / 50.;
112 if (d < 0) {
113 colors[p.index] = c2[p.index];
114 } else if (d > 1) {
115 colors[p.index] = c1[p.index];
116 } else {
117 colors[p.index] = lerpColor(c2[p.index], c1[p.index], d, RGB);
118 }
119 }
120 }
121 }
122
123 class CubeEQ extends SCPattern {
124
125 private FFT fft = null;
126 private LinearEnvelope[] bandVals = null;
127 private int avgSize;
128
129 private final BasicKnob thrsh = new BasicKnob("LVL", 0.35);
130 private final BasicKnob range = new BasicKnob("RANG", 0.45);
131 private final BasicKnob edge = new BasicKnob("EDGE", 0.5);
132 private final BasicKnob speed = new BasicKnob("SPD", 0.5);
133 private final BasicKnob tone = new BasicKnob("TONE", 0.5);
134 private final BasicKnob clr = new BasicKnob("CLR", 0.5);
135
136 public CubeEQ(GLucose glucose) {
137 super(glucose);
138 addKnob(thrsh);
139 addKnob(range);
140 addKnob(edge);
141 addKnob(speed);
142 addKnob(tone);
143 addKnob(clr);
144 }
145
146 protected void onActive() {
147 if (this.fft == null) {
148 this.fft = new FFT(lx.audioInput().bufferSize(), lx.audioInput().sampleRate());
149 this.fft.window(FFT.HAMMING);
150 this.fft.logAverages(40, 1);
151 this.avgSize = this.fft.avgSize();
152 this.bandVals = new LinearEnvelope[this.avgSize];
153 for (int i = 0; i < this.bandVals.length; ++i) {
154 this.addModulator(this.bandVals[i] = (new LinearEnvelope(0, 0, 700+i*4))).trigger();
155 }
156 }
157 }
158
159 public void run(int deltaMs) {
160 this.fft.forward(this.lx.audioInput().mix);
161 float toneConst = .35 + .4 * (tone.getValuef() - 0.5);
162 float edgeConst = 2 + 30*(edge.getValuef()*edge.getValuef()*edge.getValuef());
163
164 for (int i = 0; i < avgSize; ++i) {
165 float value = this.fft.getAvg(i);
166 value = 20*log(1 + sqrt(value));
167 float sqdist = avgSize - i;
168 value -= toneConst*sqdist*sqdist + .5*sqdist;
169 value *= 6;
170 if (value > this.bandVals[i].getValue()) {
171 this.bandVals[i].setEndVal(value, 40).trigger();
172 } else {
173 this.bandVals[i].setEndVal(value, 1000 - 900*speed.getValuef()).trigger();
174 }
175 }
176
177 float jBase = 120 - 360*thrsh.getValuef();
178 float jConst = 300.*(1-range.getValuef());
179 float clrConst = 1.1 + clr.getValuef();
180
181 for (Point p : Point.list) {
182 float avgIndex = constrain((p.fy / 256. * avgSize), 0, avgSize-2);
183 int avgFloor = (int) avgIndex;
184 float j = jBase + jConst * (p.fz / 128.);
185 float value = lerp(
186 this.bandVals[avgFloor].getValuef(),
187 this.bandVals[avgFloor+1].getValuef(),
188 avgIndex-avgFloor
189 );
190
191 float b = constrain(edgeConst * (value - j), 0, 100);
192 colors[p.index] = color(
193 (480 + lx.getBaseHuef() - min(clrConst*p.fz, 120)) % 360,
194 100,
195 b);
196 }
197 }
198 }
199