Tenshi
Tenshi

Reputation: 97

Power spectrum of wav file using python

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?

image

Upvotes: 1

Views: 1498

Answers (2)

hotpaw2
hotpaw2

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

mkrieger1
mkrieger1

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

Related Questions