forked from markjay4k/Audio-Spectrum-Analyzer-in-Python
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaudio_spectrum.py
125 lines (97 loc) · 3.48 KB
/
audio_spectrum.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
118
119
120
121
122
123
124
125
"""
Notebook for streaming data from a microphone in realtime
audio is captured using pyaudio
then converted from binary data to ints using struct
then displayed using matplotlib
scipy.fftpack computes the FFT
if you don't have pyaudio, then run
>>> pip install pyaudio
note: with 2048 samples per chunk, I'm getting 20FPS
when also running the spectrum, its about 15FPS
"""
import matplotlib.pyplot as plt
import numpy as np
import pyaudio
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
import struct
from scipy.fftpack import fft
import sys
import time
class AudioStream(object):
def __init__(self):
# stream constants
self.CHUNK = 1024 * 2
self.FORMAT = pyaudio.paInt16
self.CHANNELS = 1
self.RATE = 44100
self.pause = False
# stream object
self.p = pyaudio.PyAudio()
self.stream = self.p.open(
format=self.FORMAT,
channels=self.CHANNELS,
rate=self.RATE,
input=True,
output=True,
frames_per_buffer=self.CHUNK,
)
self.init_plots()
self.start_plot()
def init_plots(self):
# x variables for plotting
x = np.arange(0, 2 * self.CHUNK, 2)
xf = np.linspace(0, self.RATE, self.CHUNK)
# create matplotlib figure and axes
self.fig, (ax1, ax2) = plt.subplots(2, figsize=(15, 7))
self.fig.canvas.mpl_connect('button_press_event', self.onClick)
# create a line object with random data
self.line, = ax1.plot(x, np.random.rand(self.CHUNK), '-', lw=2)
# create semilogx line for spectrum
self.line_fft, = ax2.semilogx(
xf, np.random.rand(self.CHUNK), '-', lw=2)
# format waveform axes
ax1.set_title('AUDIO WAVEFORM')
ax1.set_xlabel('samples')
ax1.set_ylabel('volume')
ax1.set_ylim(0, 255)
ax1.set_xlim(0, 2 * self.CHUNK)
plt.setp(
ax1, yticks=[0, 128, 255],
xticks=[0, self.CHUNK, 2 * self.CHUNK],
)
plt.setp(ax2, yticks=[0, 1],)
# format spectrum axes
ax2.set_xlim(20, self.RATE / 2)
# show axes
thismanager = plt.get_current_fig_manager()
thismanager.window.setGeometry(5, 120, 1910, 1070)
plt.show(block=False)
def start_plot(self):
print('stream started')
frame_count = 0
start_time = time.time()
while not self.pause:
data = self.stream.read(self.CHUNK)
data_int = struct.unpack(str(2 * self.CHUNK) + 'B', data)
data_np = np.array(data_int, dtype='b')[::2] + 128
self.line.set_ydata(data_np)
# compute FFT and update line
yf = fft(data_int)
self.line_fft.set_ydata(
np.abs(yf[0:self.CHUNK]) / (128 * self.CHUNK))
# update figure canvas
self.fig.canvas.draw()
self.fig.canvas.flush_events()
frame_count += 1
else:
self.fr = frame_count / (time.time() - start_time)
print('average frame rate = {:.0f} FPS'.format(self.fr))
self.exit_app()
def exit_app(self):
print('stream closed')
self.p.close(self.stream)
def onClick(self, event):
self.pause = True
if __name__ == '__main__':
AudioStream()