Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d51ef7a

Browse files
show the spectrum
spectrum viewer
1 parent 4ef3b80 commit d51ef7a

File tree

1 file changed

+173
-0
lines changed

1 file changed

+173
-0
lines changed
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": 40,
6+
"metadata": {
7+
"collapsed": true
8+
},
9+
"outputs": [],
10+
"source": [
11+
"\"\"\"\n",
12+
"Notebook for streaming data from a microphone in realtime\n",
13+
"\n",
14+
"audio is captured using pyaudio\n",
15+
"then converted from binary data to ints using struct\n",
16+
"then displayed using matplotlib\n",
17+
"\n",
18+
"scipy.fftpack computes the FFT\n",
19+
"\n",
20+
"if you don't have pyaudio, then run\n",
21+
"\n",
22+
">>> pip install pyaudio\n",
23+
"\n",
24+
"note: with 2048 samples per chunk, I'm getting 20FPS\n",
25+
"when also running the spectrum, its about 15FPS\n",
26+
"\"\"\"\n",
27+
"\n",
28+
"import pyaudio\n",
29+
"import os\n",
30+
"import struct\n",
31+
"import numpy as np\n",
32+
"import matplotlib.pyplot as plt\n",
33+
"from scipy.fftpack import fft\n",
34+
"import time\n",
35+
"from tkinter import TclError\n",
36+
"\n",
37+
"# to display in separate Tk window\n",
38+
"%matplotlib tk\n",
39+
"\n",
40+
"# constants\n",
41+
"CHUNK = 1024 * 2 # samples per frame\n",
42+
"FORMAT = pyaudio.paInt16 # audio format (bytes per sample?)\n",
43+
"CHANNELS = 1 # single channel for microphone\n",
44+
"RATE = 44100 # samples per second"
45+
]
46+
},
47+
{
48+
"cell_type": "code",
49+
"execution_count": 54,
50+
"metadata": {
51+
"scrolled": false
52+
},
53+
"outputs": [
54+
{
55+
"name": "stdout",
56+
"output_type": "stream",
57+
"text": [
58+
"stream started\n",
59+
"stream stopped\n",
60+
"average frame rate = 15 FPS\n"
61+
]
62+
}
63+
],
64+
"source": [
65+
"# create matplotlib figure and axes\n",
66+
"fig, (ax1, ax2) = plt.subplots(2, figsize=(15, 7))\n",
67+
"\n",
68+
"# pyaudio class instance\n",
69+
"p = pyaudio.PyAudio()\n",
70+
"\n",
71+
"# stream object to get data from microphone\n",
72+
"stream = p.open(\n",
73+
" format=FORMAT,\n",
74+
" channels=CHANNELS,\n",
75+
" rate=RATE,\n",
76+
" input=True,\n",
77+
" output=True,\n",
78+
" frames_per_buffer=CHUNK\n",
79+
")\n",
80+
"\n",
81+
"# variable for plotting\n",
82+
"x = np.arange(0, 2 * CHUNK, 2) # samples (waveform)\n",
83+
"xf = np.linspace(0, RATE, CHUNK) # frequencies (spectrum)\n",
84+
"\n",
85+
"# create a line object with random data\n",
86+
"line, = ax1.plot(x, np.random.rand(CHUNK), '-', lw=2)\n",
87+
"\n",
88+
"# create semilogx line for spectrum\n",
89+
"line_fft, = ax2.semilogx(xf, np.random.rand(CHUNK), '-', lw=2)\n",
90+
"\n",
91+
"# format waveform axes\n",
92+
"ax1.set_title('AUDIO WAVEFORM')\n",
93+
"ax1.set_xlabel('samples')\n",
94+
"ax1.set_ylabel('volume')\n",
95+
"ax1.set_ylim(0, 255)\n",
96+
"ax1.set_xlim(0, 2 * CHUNK)\n",
97+
"plt.setp(ax1, xticks=[0, CHUNK, 2 * CHUNK], yticks=[0, 128, 255])\n",
98+
"\n",
99+
"# format spectrum axes\n",
100+
"ax2.set_xlim(20, RATE / 2)\n",
101+
"\n",
102+
"print('stream started')\n",
103+
"\n",
104+
"# for measuring frame rate\n",
105+
"frame_count = 0\n",
106+
"start_time = time.time()\n",
107+
"\n",
108+
"while True:\n",
109+
" \n",
110+
" # binary data\n",
111+
" data = stream.read(CHUNK) \n",
112+
" \n",
113+
" # convert data to integers, make np array, then offset it by 127\n",
114+
" data_int = struct.unpack(str(2 * CHUNK) + 'B', data)\n",
115+
" \n",
116+
" # create np array and offset by 128\n",
117+
" data_np = np.array(data_int, dtype='b')[::2] + 128\n",
118+
" \n",
119+
" line.set_ydata(data_np)\n",
120+
" \n",
121+
" # compute FFT and update line\n",
122+
" yf = fft(data_int)\n",
123+
" line_fft.set_ydata(np.abs(yf[0:CHUNK]) / (128 * CHUNK))\n",
124+
" \n",
125+
" # update figure canvas\n",
126+
" try:\n",
127+
" fig.canvas.draw()\n",
128+
" fig.canvas.flush_events()\n",
129+
" frame_count += 1\n",
130+
" \n",
131+
" except TclError:\n",
132+
" \n",
133+
" # calculate average frame rate\n",
134+
" frame_rate = frame_count / (time.time() - start_time)\n",
135+
" \n",
136+
" print('stream stopped')\n",
137+
" print('average frame rate = {:.0f} FPS'.format(frame_rate))\n",
138+
" break"
139+
]
140+
},
141+
{
142+
"cell_type": "code",
143+
"execution_count": null,
144+
"metadata": {
145+
"collapsed": true
146+
},
147+
"outputs": [],
148+
"source": []
149+
}
150+
],
151+
"metadata": {
152+
"anaconda-cloud": {},
153+
"kernelspec": {
154+
"display_name": "Python [conda root]",
155+
"language": "python",
156+
"name": "conda-root-py"
157+
},
158+
"language_info": {
159+
"codemirror_mode": {
160+
"name": "ipython",
161+
"version": 3
162+
},
163+
"file_extension": ".py",
164+
"mimetype": "text/x-python",
165+
"name": "python",
166+
"nbconvert_exporter": "python",
167+
"pygments_lexer": "ipython3",
168+
"version": "3.5.3"
169+
}
170+
},
171+
"nbformat": 4,
172+
"nbformat_minor": 1
173+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /