Reputation: 97
I was trying to load a wavefile and print its spectrum with Fourier transform. I followed some book I found and got some code from there but the result is kinda different.
def read_wave(filename):
fp=wave.open(filename,'r')
nchannels=fp.getnchannels()
framerate=fp.getframerate()
nframes=fp.getnframes()
sampwidth=fp.getsampwidth()
z_str=fp.readframes(nframes)
fp.close()
dtype_map={1:np.uint8,2:np.uint16}
ys=np.frombuffer(z_str,dtype=dtype_map[sampwidth])
waveObject=Wave(ys,framerate=framerate)
return waveObject
class Wave:
def __init__(self,ys,ts=None,framerate=None):
# ys:wave array
# ts:array of time
self.ys=np.asanyarray(ys)
self.framerate=framerate
if ts is None:
self.ts =np.arange(len(ys))/self.framerate
else:
self.ts=ts
def make_spectrum(self):
n=len(self.ys);
d=1/self.framerate;
hs = np.fft.rfft(self.ys)
fs = np.fft.rfftfreq(n, d)
return Spectrum(hs,fs,self.framerate)
class Spectrum:
def __init__(self,hs,fs,framerate):
# hs : array of amplitudes (real or complex)
# fs : array of frequencies
self.hs=np.asanyarray(hs)
self.fs=np.asanyarray(fs)
self.framerate=framerate
@property
def amps(self):
return np.absolute(self.hs)
def plot(self, high=None):
plt.plot(self.fs, self.amps)
data=read_wave('hate.wav') <br>
spectrum=data.make_spectrum()<br>
spectrum.plot()<br>
But the spectrum I get looks like this, and does not look right, any help?
Upvotes: 1
Views: 1498
Reputation: 70743
The unsigned 8-bit samples stored in WAVE files range from 0 to 255, and thus have a DC offset. Your FFT is showing this DC offset with a huge spike at the beginning. Subtracting the DC offset (should be 128, or a value somewhere around 128 due to recording errors) from each sample will remove the huge DC offset spike from the FFT, and allow plot autoscaling to show the other frequency bins better.
16-bit samples in WAVE files are in signed integer format, so reading them as unsigned values may corrupt the data.
Upvotes: 1
Reputation: 23313
There is a huge peak at f = 0, which indicates that the signal has a constant offset.
It may be related to using unsigned integer types:
dtype_map={1:np.uint8,2:np.uint16}
Try using a signed type, or subtract the average value from the signal to remove the offset.
Upvotes: 1