Skip to content

Instantly share code, notes, and snippets.

@jslegendre
Last active November 29, 2017 03:07
Show Gist options
  • Save jslegendre/7aa79ad79b9e05036fe3c1ba6b394a7d to your computer and use it in GitHub Desktop.
Save jslegendre/7aa79ad79b9e05036fe3c1ba6b394a7d to your computer and use it in GitHub Desktop.
WAV to Plot from scratch in Python. I know this can be done using SciPy or various other libraries but I wanted to learn more about wav data so I did this from scratch. Added bonus to doing this myself is that I could specify how accurately I wanted the data to be in order to speed up time on large files. Currently, this only works on 16bit mono…
import os
import sys
import numpy as np
import struct
import warnings
path="sample.wav"
#get the file size in bytes
fileSize=os.path.getsize(path)
f=open(path,"r")
#Go to ByteRate at offset 28
f.seek(28)
#Read in 4 bytes and convert to signed int
b = struct.unpack('i', f.read(4))
byteRate= b[0]
#Calculate duration of sound
ms=((fileSize-44)*1000)/byteRate
#Go to first byte of sound data
f.seek(44,0)
#secSize or Section Size will allow you to grab a "chunk" of
#data and find the average instead of plotting every
#individual point.Very useful for a quick analysis of
#large files. 1 = 1:1 / 16 = 16:1
secSize = 16
dValue=0 #dataValue
dVals = [] #dataValues
mVals =[] #meanValues
done = 'n'
#Generate Y values
while (done != 'y') :
q=0
while q < secSize :
try:
#Read 'short' from wav file
dValue = struct.unpack('=h', f.read(2))
except struct.error:
#If your section size extends past the last byte
#just break out of the loop
done = 'y'
break
dVals.append(dValue[0])
q += 1
#Supress NumPys "Nan" warning
warnings.simplefilter("ignore")
#Find average of section and add it to mVals
mVals.append(np.mean(dVals))
dVals=[]
dValue = 0
#Find the amount of time each
#point will represent
xInc = round(float(ms)/len(mVals), 6)
x = 0
yInc = 1
y=0
pair=[]
pairs = []
#Generate X values for Y counterparts
while (x < ms):
try:
y = round(mVals[yInc], 2)
except IndexError:
break
pair.append(round(x, 6))
pair.append(y)
pairs.append(pair)
x += xInc
yInc += 1
pair=[]
#Flush buffer just to be safe
sys.stdout.flush()
#Print 'x,y' to console.
#To write to file: ./ThisScript.py > data.txt
h = 0
while (h < len(pairs)):
sys.stdout.write(str(pairs[h][0]) + ',' + str(pairs[h][1]) + '\n')
#Uncomment next line for '(x,y)'
#sys.stdout.write('(' + str(pairs[h][0]) + ',' + str(pairs[h][1]) + ')' + '\n')
h+=1
f.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment