-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfftread.py
117 lines (97 loc) · 3.38 KB
/
fftread.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# Python 2.7 code to analyze sound and interface with Arduino
import pyaudio # from http://people.csail.mit.edu/hubert/pyaudio/
import serial # from http://pyserial.sourceforge.net/
import numpy # from http://numpy.scipy.org/
import audioop
import sys
import math
import struct
from time import sleep
'''
Sources
http://www.swharden.com/blog/2010-03-05-realtime-fft-graph-of-audio-wav-file-or-microphone-input-with-python-scipy-and-wckgraph/
http://macdevcenter.com/pub/a/python/2001/01/31/numerically.html?page=2
'''
MAX = 0
def list_devices():
# List all audio input devices
p = pyaudio.PyAudio()
i = 0
n = p.get_device_count()
while i < n:
dev = p.get_device_info_by_index(i)
if dev['maxInputChannels'] > 0:
print str(i)+'. '+dev['name']
i += 1
def light_sounds():
chunk = 2**11 # Change if too fast/slow, never less than 2**11
scale = 350 # Change if too dim/bright
exponent = .5 # Change if too little/too much difference between loud and quiet sounds
samplerate = 44100
# Change this setting if input device is different
# You may need to enable stereo mixing in your sound card
# to make your sound output an input
# Use list_devices() to list all your input devices
device = 4
p = pyaudio.PyAudio()
stream = p.open(format = pyaudio.paInt16,
channels = 2,
rate = 44100,
input = True,
frames_per_buffer = chunk,
input_device_index = device)
print "Starting, use Ctrl+C to stop"
try:
while True:
data = stream.read(chunk)
'''
# Old RMS code, will only show the volume
rms = audioop.rms(data, 2)
level = min(rms / (2.0 ** 16) * scale, 1.0)
level = level**exponent
level = int(level * 255)
print level
ser.write(chr(level))
'''
# Do FFT
levels = calculate_levels(data, chunk, samplerate)
# Make it look better and send to serial
for level in levels:
level = max(min(level / scale, 1.0), 0.0)
level = level**exponent
level = int(level * 255)
level = int(level/25)
print level
ser.write(chr(level))
#s = ser.read(6)
except KeyboardInterrupt:
pass
finally:
print "\nStopping"
stream.close()
p.terminate()
ser.close()
def calculate_levels(data, chunk, samplerate):
# Use FFT to calculate volume for each frequency
global MAX
# Convert raw sound data to Numpy array
fmt = "%dH"%(len(data)/2)
data2 = struct.unpack(fmt, data)
data2 = numpy.array(data2, dtype='h')
# Apply FFT
fourier = numpy.fft.fft(data2)
ffty = numpy.abs(fourier[0:len(fourier)/2])/1000
ffty1=ffty[:len(ffty)/2]
ffty2=ffty[len(ffty)/2::]+2
ffty2=ffty2[::-1]
ffty=ffty1+ffty2
ffty=numpy.log(ffty)-2
fourier = list(ffty)[4:-4]
fourier = fourier[:len(fourier)/2]
size = len(fourier)
levels = [sum(fourier[i:(i+size/6)]) for i in xrange(0, size, size/6)][:6]
return levels
if __name__ == '__main__':
ser = serial.Serial('/dev/tty.usbserial-DA017XZ5', 57600, timeout=1)
list_devices()
light_sounds()