Skip to content

Instantly share code, notes, and snippets.

@MikeiLL
Last active May 9, 2021 13:07
Show Gist options
  • Save MikeiLL/de7c602094be9173395a059d2c508bc9 to your computer and use it in GitHub Desktop.
Save MikeiLL/de7c602094be9173395a059d2c508bc9 to your computer and use it in GitHub Desktop.
Oscilloscope from File
'''
Jupyter Notebook code to generate a stream of matplotlib canvas plots
based on PyAudio data for a wav file.
original source https://stackoverflow.com/a/6951154/2223106
Also need to brew install portaudio on OSX or in an ENV perhaps
pip install --global-option='build_ext' --global-option='-I/usr/local/include' --global-option='-L/usr/local/lib' pyaudio
# ffmpeg -i song.mp3 -acodec pcm_u8 -ar 22050 song.wav
'''
import pyaudio
import wave
import sys
import struct
import numpy as np
import matplotlib.pyplot as plt
%matplotlib tk
class AudioFile:
chunk = 1024 * 4
def __init__(self, file):
""" Init audio stream """
self.wf = wave.open(file, 'rb')
self.p = pyaudio.PyAudio()
fig, ax = plt.subplots()
self.fig = fig
self.ax = ax
self.x = np.arange(0, 2 * self.chunk, 2)
self.line, = ax.plot(self.x, np.random.rand(self.chunk))
self.ax.set_ylim(-255, 255)
self.ax.set_xlim(0, self.chunk)
self.stream = self.p.open(
format = self.p.get_format_from_width(self.wf.getsampwidth()),
channels = self.wf.getnchannels(),
rate = self.wf.getframerate(),
output = True,
frames_per_buffer=self.chunk
)
def play(self):
""" Play entire file """
data = self.wf.readframes(self.chunk)
while data != '':
self.stream.write(data)
data = self.wf.readframes(self.chunk)
data_int = np.array(struct.unpack(str(2 * self.chunk) + 'B', data), dtype='b')[::2] + 127
self.line.set_ydata(data_int)
self.fig.canvas.draw()
self.fig.canvas.flush_events()
def close(self):
""" Graceful shutdown """
self.stream.close()
self.p.terminate()
# Usage example for pyaudio
a = AudioFile("BenchBendsTheSound.wav")
a.play()
a.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment