Search code examples
pythonnumpyaudiomatplotlibwave

Plot a Wave files Audio Visually In Python


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

Code generates just this minute sliver of the audio spectrum

waveFile.readframes(-1) gives me the whole wave file audio spectrum


Solution

  • 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: wave form plot real time example