Skip to content

Commit 786da4a

Browse files
committed
first commit
0 parents  commit 786da4a

File tree

3 files changed

+273
-0
lines changed

3 files changed

+273
-0
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/.idea
2+
/tool
3+
rsync.sh

LEDStrip.py

+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
import spidev
2+
import time
3+
import threading
4+
5+
6+
def convertToStripData(colors):
7+
for color in colors:
8+
# If it comes with the brightness bytes, use it, otherwise use full brightness 0xff
9+
yield 0xff if color.bit_length() != 32 else int(color >> 24)
10+
color = int(color % 0x1000000)
11+
yield color & 0x0000FF # blue
12+
yield (color & 0x00FF00) >> 8 # green
13+
yield color >> 16 # red
14+
15+
16+
def adjust_brightness(color, amount):
17+
if color.bit_length() == 32:
18+
brightness = color >> 24
19+
brightness = min(max(0xE0, brightness + amount), 0xFF)
20+
return (color % 0x1000000) | (brightness << 24)
21+
else:
22+
return color
23+
24+
def getColors():
25+
for i in xrange(20):
26+
yield 0xFFff0000
27+
yield 0xFF00ff00
28+
yield 0xFF0000ff
29+
30+
31+
def getSteep():
32+
brightness = 0xE0
33+
for i in xrange(60):
34+
if i % 2 == 0:
35+
brightness += 1
36+
yield (brightness << 24) + 0xff55ff
37+
38+
39+
class RotateThread(threading.Thread):
40+
def __init__(self, strip):
41+
threading.Thread.__init__(self)
42+
self.strip = strip
43+
44+
def run(self):
45+
self.strip.is_rotating = True
46+
while self.strip.is_rotating:
47+
self.strip.colorCache = self.strip.colorCache[-1:] + self.strip.colorCache[:-1]
48+
self.strip.show()
49+
time.sleep(1.0 / 4)
50+
51+
52+
class LEDStrip:
53+
start_frame = [0x00, 0x00, 0x00, 0x00]
54+
stop_frame = [0xFF, 0xFF, 0xFF, 0xFF]
55+
56+
def __init__(self, pixelNum):
57+
self.spi = spidev.SpiDev()
58+
self.spi.open(0, 0)
59+
self.spi.max_speed_hz = 8000000
60+
self.colorCache = [0xff000000] * pixelNum
61+
self.rotateThread = RotateThread(self)
62+
self.is_rotating = False
63+
self.pixelNum = pixelNum
64+
65+
def start_rotate(self):
66+
self.rotateThread = RotateThread(self)
67+
self.rotateThread.start()
68+
69+
def stop_rotate(self):
70+
self.is_rotating = False
71+
self.rotateThread.join()
72+
73+
def show(self):
74+
self.spi.xfer2(LEDStrip.start_frame)
75+
self.spi.xfer2(list(convertToStripData(self.colorCache)))
76+
self.spi.xfer2(LEDStrip.stop_frame)
77+
78+
def set_color(self, pixel, color):
79+
self.colorCache[pixel] = color
80+
81+
def show_colors(self, colors):
82+
self.colorCache = colors[:self.pixelNum] + self.colorCache[self.pixelNum:]
83+
self.show()
84+
85+
def fill(self, length, color):
86+
self.colorCache = [color] * min(self.pixelNum, length) + [0x000000] * (self.pixelNum - length)
87+
self.show()
88+
89+
def fill_range(self, start, end, colors):
90+
offset = abs(start - end)
91+
step = 1 if start < end else -1
92+
j = 0
93+
for i in range(start, end, step):
94+
self.colorCache[i] = colors[j]
95+
j += 1
96+
97+
def fill_smooth(self, length, start, speed, color):
98+
for i in xrange(start, length, 1 if start < length else -1):
99+
self.fill(i, color)
100+
time.sleep(1.0 / speed)
101+
self.fill(length, color)
102+
103+
def dim(self, length):
104+
self.colorCache = map(lambda c: adjust_brightness(c, -1), self.colorCache[:length]) + self.colorCache[length:]
105+
self.show()
106+
107+
def brighten(self, length):
108+
self.colorCache = map(lambda c: adjust_brightness(c, 1), self.colorCache[:length]) + self.colorCache[length:]
109+
self.show()
110+
111+
def dark(self):
112+
self.colorCache = [0x000000] * self.pixelNum
113+
self.show()
114+
115+
def set_dark(self):
116+
self.colorCache = [0x000000] * self.pixelNum
117+
118+
def getColor(self, index):
119+
return self.colorCache[index]
120+
121+
def get_brightness(self, index):
122+
color = self.colorCache[index]
123+
return color >> 24
124+
125+
class LEDScreen:
126+
# row * column <= ledStrip.pixelNum
127+
def __init__(self, ledStrip, row, column):
128+
self.strip = ledStrip
129+
self.row = row
130+
self.column = column
131+
132+
def show(self, pixelArray):
133+
for index in range(0, len(pixelArray)):
134+
row = pixelArray[index]
135+
self.showRow(index, row)
136+
137+
def showRow(self, index, colors):
138+
if index % 2 == 0:
139+
start = index * self.column
140+
end = start + len(colors)
141+
else:
142+
start = (index + 1) * self.column - 1
143+
end = start - len(colors)
144+
self.strip.fill_range(start, end, colors)
145+
146+
def refresh(self):
147+
self.strip.show()
148+
149+
if __name__ == '__main__':
150+
c = 0xffff0000
151+
print hex()

soundsa.py

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import pyaudio
2+
import sys
3+
import numpy
4+
import random
5+
from LEDStrip import LEDStrip, LEDScreen
6+
7+
p = pyaudio.PyAudio()
8+
row = 8
9+
column = 72 * 4 / row
10+
led_screen = LEDScreen(LEDStrip(row * column), row, column)
11+
max_db = 50.0
12+
sample_rate = 44100 #Hz
13+
sample_per_buffer = 2**11
14+
db_per_pixel = float(max_db) / column
15+
currentColor = 0xe1ff00ff
16+
17+
frequency_per_sample = sample_rate / sample_per_buffer
18+
19+
def getLedIndex(index, pixel):
20+
if index % 2 == 0:
21+
return index / 2 * 72 + pixel
22+
else:
23+
return (index+1) / 2 * 72 - 1 -pixel
24+
25+
def fillLedIndex(index, pixel, color):
26+
colors = list(0 for _ in range(0, column))
27+
for i in range(0, pixel):
28+
colors[i] = color
29+
led_screen.showRow(index, colors)
30+
31+
def frequencyToIndex(frequency):
32+
return int(frequency / frequency_per_sample)
33+
34+
def normalize(x):
35+
return 20 * numpy.log10(numpy.abs(x)) - 50 - 10
36+
37+
def avg(list):
38+
return sum(list) / float(len(list))
39+
40+
def getDb(fft, start, end):
41+
from_index = frequencyToIndex(start)
42+
until_index = frequencyToIndex(end) + 1
43+
return avg(fft[from_index:until_index])
44+
45+
def getRandomColor():
46+
r = random.randint(0, 255)
47+
g = random.randint(0, 255)
48+
b = random.randint(0, 255)
49+
return ((((r << 8) + g) << 8) + b) + (0xe5 << 24)
50+
51+
52+
def getMaxDb(fft, start, end):
53+
from_index = frequencyToIndex(start)
54+
until_index = frequencyToIndex(end) + 1
55+
return max(fft[from_index:until_index])
56+
57+
def dbToPixel(db):
58+
db = min(max_db, db)
59+
pixel = int(db / db_per_pixel)
60+
pixel = min(max(0, pixel), column-1)
61+
return pixel
62+
63+
def dbToColor(db):
64+
db = min(max(0, db), max_db)
65+
color = long(db / max_db * 255)
66+
return color + 0xff0000
67+
68+
def print_spectrum(fft):
69+
out_str = ''
70+
for i in range(0, len(fft), 50):
71+
db = getDb(fft, i, i + 50)
72+
out_str += "{0:g}\t ".format(db)
73+
print out_str
74+
75+
76+
def handleData(in_data):
77+
samples = numpy.fromstring(in_data, dtype=numpy.int16)
78+
fft = numpy.fft.fft(samples)
79+
fft = normalize(fft)
80+
maxDb = getMaxDb(fft, 1000, 5000)
81+
maxPixel = dbToPixel(maxDb)
82+
global currentColor
83+
if (maxPixel > column - 2):
84+
currentColor = getRandomColor()
85+
for i in range(0, row):
86+
db = getDb(fft, i * 500 + 200, (i+1) * 500)
87+
print db
88+
fillLedIndex(i, dbToPixel(db), currentColor)
89+
led_screen.refresh()
90+
return (None, pyaudio.paContinue)
91+
92+
93+
# This is to release mic when the program exit
94+
def interrupt_callback():
95+
print "interrupted manually"
96+
stream.stop_stream()
97+
stream.close()
98+
p.terminate()
99+
sys.exit()
100+
101+
try:
102+
stream = p.open(format=pyaudio.paInt16,
103+
channels=1,
104+
rate=sample_rate,
105+
input=True,
106+
# input_device_index=2,
107+
output=False)
108+
stream.start_stream()
109+
while True:
110+
stream.start_stream()
111+
in_data = stream.read(sample_per_buffer, exception_on_overflow=False)
112+
stream.stop_stream()
113+
handleData(in_data)
114+
# time.sleep(0.1)
115+
except Exception as e:
116+
print e
117+
finally:
118+
interrupt_callback()
119+

0 commit comments

Comments
 (0)