Created
June 20, 2017 03:54
-
-
Save ikapper/1fcdf912c57ec332372a538868c8e8e0 to your computer and use it in GitHub Desktop.
Using PyAudio, matplotlib, numpy and wxPython.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
""" | |
Display fft data. | |
Environment: | |
matplotlib==2.0.2 | |
numpy==1.13.0 | |
PyAudio==0.2.11 | |
wxPython==4.0.0a3 | |
""" | |
import matplotlib | |
matplotlib.interactive(True) | |
matplotlib.use('WXAgg') | |
import wx | |
import pyaudio | |
import wave | |
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg | |
from matplotlib.figure import Figure | |
import numpy as np | |
CHUNK = 1024 * 4 | |
RATE = 44100 | |
class WavePanel(wx.Panel): | |
""" | |
Display fft data. | |
""" | |
def __init__(self, parent): | |
self.parent = parent | |
wx.Panel.__init__(self, parent) | |
self.lastplot = None | |
# matplotlib figure | |
self.figure = Figure(None) | |
self.figure.set_facecolor((0.9, 0.9, 1.)) | |
self.subplot = self.figure.add_subplot(111) | |
# canvas | |
self.canvas = FigureCanvasWxAgg(self, -1, self.figure) | |
self.canvas.SetBackgroundColour(wx.Colour(100,255,255)) | |
# Layout using BoxSizer | |
sizer = wx.BoxSizer(wx.VERTICAL) | |
sizer.Add(self.canvas, 1, wx.EXPAND) | |
self.SetSizer(sizer) | |
self.init_graph() | |
# pyaudio | |
# self.wavefile = wave.open('data/musicbox.wav', 'rb') | |
self.pyaudio = pyaudio.PyAudio() | |
self.stream = self.pyaudio.open(format=pyaudio.paInt16, | |
channels=2, | |
rate=RATE, | |
input_device_index=2, # speaker(soundflower2ch) id | |
frames_per_buffer=CHUNK, | |
input=True, | |
output=True) | |
# Redraw graph with timer | |
self.timer = wx.Timer(self, 1) | |
self.Bind(wx.EVT_TIMER, self.update_graph, self.timer) | |
self.timer.Start(15) | |
def init_graph(self): | |
""" | |
Set up graph except for plotting. | |
""" | |
self.subplot.set_title('sample (fft)') | |
self.subplot.set_xlabel('freq') | |
self.subplot.set_ylabel('y') | |
self.subplot.set_xscale('log') | |
# self.subplot.set_yscale('log') # If use amplitude spectrum | |
def update_graph(self, event): | |
""" | |
Redraw graph. | |
""" | |
self.draw(event) | |
def draw(self, event=None): | |
""" | |
Draw plotting data. | |
""" | |
# Read audio data | |
# data = self.wavefile.readframes(CHUNK) | |
# if data != b'': | |
if self.stream.is_active(): | |
data = self.stream.read(CHUNK, exception_on_overflow=False) | |
if self.lastplot and self.lastplot[0]: | |
self.lastplot[0].remove() | |
# self.stream.write(data) # output audio data | |
x, y = self.fft_plot(data) | |
self.lastplot = self.subplot.plot(x, y, 'b') # 3rd param is line color | |
else: | |
# release resources | |
self.stream.stop_stream() | |
self.stream.close() | |
self.pyaudio.terminate() | |
self.timer.Stop() | |
self.canvas.draw() | |
def fft_plot(self, data): | |
""" | |
Create plotting data from data param. | |
""" | |
data1 = np.frombuffer(data, dtype='int16') / 32768.0 # Normalize | |
data = np.hamming(len(data1)) * data1 # hamming window | |
fft_data = np.fft.fft(data) | |
fft_data = np.abs(fft_data) | |
# fft_data = 20 * np.log10(fft_data) # amplitude spectrum(db) | |
x = np.fft.fftfreq(len(fft_data), d=0.5 / RATE) | |
x = np.abs(x) | |
return x, fft_data | |
def check_audio_devices(): | |
""" | |
Display valid devices on PC. Use the device id for "input_device_index" | |
on "pyaudio.open()" | |
""" | |
p = pyaudio.PyAudio() | |
info = p.get_host_api_info_by_index(0) | |
numdevices = info.get('deviceCount') | |
for i in range(0, numdevices): | |
if (p.get_device_info_by_host_api_device_index(0, i).get('maxInputChannels')) > 0: | |
print("Input Device id ", i, " - ", p.get_device_info_by_host_api_device_index(0, i).get('name')) | |
def main(): | |
app = wx.App() | |
frame = wx.Frame(None, size=(700,500)) | |
panel = WavePanel(frame) | |
frame.Show() | |
app.MainLoop() | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment