-
Notifications
You must be signed in to change notification settings - Fork 0
/
ffttest.py
116 lines (94 loc) · 3.21 KB
/
ffttest.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
# From http://julip.co/2012/05/arduino-python-soundlight-spectrum/
# 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
'''
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
NUM = 20
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 fft():
chunk = 2**11 # Change if too fast/slow, never less than 2**11
scale = 25 # Change if too dim/bright
exponent = 3 # Change if too little/too much difference between loud and quiet sounds
samplerate = 44100
# CHANGE THIS TO CORRECT INPUT DEVICE
# Enable stereo mixing in your sound card
# to make you sound output an input
# Use list_devices() to list all your input devices
device = 1 # Mic
#device = 4 # SF2
p = pyaudio.PyAudio()
stream = p.open(format = pyaudio.paInt16,
channels = 1,
rate = 44100,
input = True,
frames_per_buffer = chunk,
input_device_index = device)
print "Starting, use Ctrl+C to stop"
try:
ser = serial.Serial(
port='/dev/ttyS0',
timeout=1
)
while True:
data = stream.read(chunk)
# 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)
#ser.write(chr(level))
#sys.stdout.write(str(level)+' ')
#sys.stdout.write('\n')
#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)
# Add up for 6 lights
levels = [sum(fourier[i:(i+size/NUM)]) for i in xrange(0, size, size/NUM)][:NUM]
return levels
if __name__ == '__main__':
#list_devices()
fft()