|
@@ -1,11 +1,15 @@
|
1
|
1
|
"""
|
2
|
2
|
Spectroshaker by The Dod:
|
3
|
3
|
Adafruit CircuitPlayground Bluefruit dual-mode "bling"
|
4
|
|
-(selectable via the slider switch).
|
5
|
4
|
The RGB levels of neopixels around the circuit indicate:
|
6
|
5
|
- Low/Mid/High sound levels (spectrogram mode)
|
7
|
6
|
- X/Y/Z acceleration (shaker mode)
|
8
|
|
-TO BE CONTINUED ...
|
|
7
|
+
|
|
8
|
+Controls:
|
|
9
|
+ slider switch: normal/standby mode
|
|
10
|
+ button a: toggle between spectrogram/shaker mode
|
|
11
|
+ button b: cycle between 4 brightness levels
|
|
12
|
+
|
9
|
13
|
"""
|
10
|
14
|
import math
|
11
|
15
|
import time
|
|
@@ -21,48 +25,77 @@ LED_ANGLES = [
|
21
|
25
|
minx = miny = minz = -5.0
|
22
|
26
|
maxx = maxy = maxz = 5.0
|
23
|
27
|
|
24
|
|
-fft_size = 8 # power of 2
|
|
28
|
+fft_size = 8 # power of 2
|
25
|
29
|
samples = [0.0+0.0j]*fft_size
|
26
|
|
-MAX_2FREQ = 10.0 # After testing this a bit in the wild
|
|
30
|
+MAX_2FREQ = 10.0 # After testing this a bit in the wild
|
27
|
31
|
|
28
|
32
|
cp.pixels.brightness = 0.1
|
29
|
33
|
|
|
34
|
+MODE_SPECTRO = 1
|
|
35
|
+MODE_SHAKER = 2
|
|
36
|
+current_mode = MODE_SHAKER
|
|
37
|
+is_standby = cp.switch
|
|
38
|
+last_click = 0
|
|
39
|
+DEBOUNCE = 0.25
|
|
40
|
+
|
30
|
41
|
def angles2level(led, val):
|
31
|
42
|
led_angle = LED_ANGLES[led]
|
32
|
43
|
val_angle = val * 2.0 * math.pi
|
33
|
44
|
angle = led_angle - val_angle
|
34
|
|
- while angle>2*math.pi:
|
|
45
|
+ while angle > 2 * math.pi:
|
35
|
46
|
angle -= 2*math.pi
|
36
|
47
|
# the pow() makes sin() values sharper
|
37
|
48
|
return int(255*pow(math.sin(angle/2), 4))
|
38
|
49
|
|
39
|
50
|
while True:
|
40
|
|
- if cp.button_a:
|
41
|
|
- cp.pixels.brightness = max(0.05, cp.pixels.brightness*0.9)
|
42
|
|
- elif cp.button_b:
|
43
|
|
- cp.pixels.brightness = min(0.95, 1.0-(1.0-cp.pixels.brightness)*0.9)
|
|
51
|
+ if time.monotonic() > last_click+DEBOUNCE:
|
|
52
|
+ if is_standby != cp.switch:
|
|
53
|
+ is_standby = cp.switch
|
|
54
|
+ last_click = time.monotonic()
|
|
55
|
+ if is_standby:
|
|
56
|
+ for i in range(NUM_PIXELS):
|
|
57
|
+ cp.pixels[i] = (0, 0, 0)
|
|
58
|
+ if cp.button_a:
|
|
59
|
+ last_click = time.monotonic()
|
|
60
|
+ current_mode = (
|
|
61
|
+ current_mode == MODE_SHAKER and MODE_SPECTRO
|
|
62
|
+ or MODE_SHAKER)
|
|
63
|
+ elif cp.button_b:
|
|
64
|
+ last_click = time.monotonic()
|
|
65
|
+ is_standby = False
|
|
66
|
+ if cp.pixels.brightness >= 0.4:
|
|
67
|
+ cp.pixels.brightness = 0.1
|
|
68
|
+ else:
|
|
69
|
+ cp.pixels.brightness += 0.1
|
44
|
70
|
|
45
|
|
- samples.pop(0)
|
46
|
|
- samples.append(cp.sound_level+0.0j)
|
47
|
|
- x, y, z = cp.acceleration
|
48
|
|
- if x<minx: minx = x
|
49
|
|
- if y<miny: miny = y
|
50
|
|
- if z<minz: minz = z
|
51
|
|
- if x>maxx: maxx = x
|
52
|
|
- if y>maxy: maxy = y
|
53
|
|
- if z>maxx: maxz = z
|
54
|
|
- if cp.switch: # accelerometer mode
|
55
|
|
- vals = (
|
56
|
|
- (x-minx)/(maxx-minx),
|
57
|
|
- (y-miny)/(maxy-miny),
|
58
|
|
- (z-minz)/(maxz-minz))
|
59
|
|
- else: # spectrogram mode
|
60
|
|
- raw_freqs = spectrogram(samples)
|
61
|
|
- pairs = [raw_freqs[i]+raw_freqs[i+1] for i in range(fft_size//2)]
|
62
|
|
- vals = [min(1.0, abs(x/MAX_2FREQ)) for x in pairs[:3]]
|
63
|
|
- for i in range(NUM_PIXELS):
|
64
|
|
- cp.pixels[i] = (
|
65
|
|
- angles2level(i, vals[0]),
|
66
|
|
- angles2level(i, vals[1]),
|
67
|
|
- angles2level(i, vals[2]))
|
68
|
|
- time.sleep(0.01)
|
|
71
|
+ if not is_standby:
|
|
72
|
+ samples.pop(0)
|
|
73
|
+ samples.append(cp.sound_level+0.0j)
|
|
74
|
+ x, y, z = cp.acceleration
|
|
75
|
+ if x < minx:
|
|
76
|
+ minx = x
|
|
77
|
+ if y < miny:
|
|
78
|
+ miny = y
|
|
79
|
+ if z < minz:
|
|
80
|
+ minz = z
|
|
81
|
+ if x > maxx:
|
|
82
|
+ maxx = x
|
|
83
|
+ if y > maxy:
|
|
84
|
+ maxy = y
|
|
85
|
+ if z > maxz:
|
|
86
|
+ maxz = z
|
|
87
|
+ if current_mode == MODE_SHAKER: # accelerometer mode
|
|
88
|
+ vals = (
|
|
89
|
+ (x-minx)/(maxx-minx),
|
|
90
|
+ (y-miny)/(maxy-miny),
|
|
91
|
+ (z-minz)/(maxz-minz))
|
|
92
|
+ else: # spectrogram mode
|
|
93
|
+ raw_freqs = spectrogram(samples)
|
|
94
|
+ pairs = [raw_freqs[i]+raw_freqs[i+1] for i in range(fft_size//2)]
|
|
95
|
+ vals = [min(1.0, abs(x/MAX_2FREQ)) for x in pairs[:3]]
|
|
96
|
+ for i in range(NUM_PIXELS):
|
|
97
|
+ cp.pixels[i] = (
|
|
98
|
+ angles2level(i, vals[0]),
|
|
99
|
+ angles2level(i, vals[1]),
|
|
100
|
+ angles2level(i, vals[2]))
|
|
101
|
+ time.sleep(0.01)
|