Reputation: 1686
I am trying to figure out how to plot the audio visually of a wav file. In my code if I do a wavefile.readframe(-1)
I get the whole wav file plotted, the way my code works now is I just get a silver (one frame!) I'd like to show 24 frames of audio on each image plot from the wave file so I can animate it. Hopefully this is clear.
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np
import wave , sys , os , struct
waveFile = wave.open('mono.wav','r')
length = waveFile.getnframes()
for i in range(0,length):
print i # so we know where we are at.
waveData = waveFile.readframes(i)
fs = waveFile.getframerate()
signal = np.fromstring(waveData, 'Int16')
Time=np.linspace(0, len(signal)/fs, num=len(signal))
plt.axis('off')
plt.plot(Time,signal , 'w')
plt.savefig('signal' + str(i) + '.png' , facecolor='none', edgecolor='none', transparent=True, frameon=False)
plt.close
Upvotes: 3
Views: 7476
Reputation: 1686
I recoded a bit , the above answered help, but I needed to do more massaging. So if you have a need to plot audio this way in realtime just adjust the readframes for as many frames you would like to take in. To plot each frame I wound up having to make seperate plt.figure id's This code snip will get you where you want to go
wave_file = wave.open('mono.wav', 'r')
data_size = wave_file.getnframes()
sample_rate = wave_file.getframerate()
while True:
waveData = wave_file.readframes(10000)
signal = np.fromstring(waveData , 'Int16')
Time=np.linspace(0, len(signal), num=len(signal))
plt.figure()
fig = plt.figure(figsize=(xinch,yinch) , frameon=False)
#fig = plt.figure(frameon=False)
ax = fig.add_axes([0, 0, 1, 1])
#ax.axis('off')
plt.axis('off')
line = plt.plot(Time,signal , 'w')
plt.setp(line, linewidth=10)
plt.savefig('signal' + str(x) + '.png')
plt.close
x+= 1
if wave_file.tell() == data_size:
break
Will result in frames like this:
Upvotes: 0
Reputation: 74262
From the documentation:
Wave_read.readframes
(n)Reads and returns at most n frames of audio, as a string of bytes.
So to read a chunk of 24 frames you simply call
waveData = waveFile.readframes(24)
When you open the file in read ('r'
) mode, the file pointer starts out at the 0th frame. As you read frames from the file, you will advance the file pointer by the same number of frames. This means that calling waveFile.readframes(24)
repeatedly will yield consecutive chunks of 24 frames until you hit the end of the file - there's no need to pass a changing index i
.
To keep track of where you are within the file, you can call waveFile.tell()
, and to skip forwards or backwards to the k
th frame you can use waveFile.setpos(k)
.
By the way, this behaviour is very consistent with how standard file objects work in Python.
Upvotes: 1