[SciPy-user] Create a spectrogram from a waveform
Ed McCaffrey
ed@edmccaffrey....
Sun Aug 31 15:52:40 CDT 2008
Thanks for the reply. I had not heard of audiolab before, but I just tried
using it.
Looking at audiolab made me realize that I had forgotten how a .wav stores
the data for multiple channels, so that was why the spectrogram I generated
before looked so odd.
Here's the program, in case anyone else wants it or if I made another
mistake:
from scipy import *
from pylab import *
from numpy import *
import scikits.audiolab as audiolab
import struct
wav = audiolab.sndfile('song.wav', 'read')
data = wav.read_frames(wav.get_nframes())
data = data[:,0]
spectrogram = specgram(data)
title('Spectrogram')
show();
On Sun, Aug 31, 2008 at 3:19 PM, Matthieu Brucher <
matthieu.brucher@gmail.com> wrote:
> If yu delete samples without replacing it with something, you're in
> trouble, you can not make an FFT or IFFT on that kind of data, it is
> not uniformely sampled anymore !
>
> Try :
> data = numpy.array(data) (why don't you use audiolab for this ? or
> data = numpy.fromfile('song.wav').reshape(-1, 2)[0])
> data[numpy.isnan(data)] = 0
>
> instead. It just replaces NaN with 0, not the best course of action.
>
> Matthieu
>
> 2008/8/31 Ed McCaffrey <ed@edmccaffrey.net>:
> > I've found what is creating the solid blue screen. That code gives a few
> > NaNs in the list, if I remove them then I get actual output.
> >
> > However, I think that something is wrong if I am getting NaNs, and the
> > spectrogram just doesn't look right. Here is updated code:
> >
> > from scipy import *
> > from pylab import *
> > from wave import *
> > import struct
> >
> > wav = open('song.wav')
> > length = wav.getnframes()
> >
> > tmp = [struct.unpack('f', wav.readframes(1))[0] for x in range(length)]
> > data = [x for x in tmp if isnan(x) == False]
> >
> > spectrogram = specgram(data)
> > title('Spectrogram')
> >
> > show();
> >
> >
> >
> > On Sun, Aug 31, 2008 at 9:49 AM, Ed McCaffrey <ed@edmccaffrey.net>
> wrote:
> >>
> >> Thanks for the replies. I think that now I am heading towards the right
> >> direction, but I have one problem. When I run my program all I get for
> the
> >> spectrogram is a solid blue graph.
> >>
> >> The program is:
> >>
> >> from scipy import *
> >> from pylab import *
> >> from wave import *
> >> import struct
> >>
> >> wav = open('song.wav')
> >> length = wav.getnframes()
> >>
> >> data = [struct.unpack('f', wav.readframes(1))[0] for x in range(length)]
> >>
> >> spectrogram = specgram(data)
> >> title('Spectrogram')
> >>
> >> show();
> >>
> >> I tried it with a few different short clips with the same result. One
> of
> >> them can be found: http://edmccaffrey.net/misc/song.wav
> >>
> >>
> >> Thanks.
> >>
> >>
> >>
> >> On Sat, Aug 30, 2008 at 9:28 PM, Peter Wang <pwang@enthought.com>
> wrote:
> >>>
> >>> Quoting Ed McCaffrey <ed@edmccaffrey.net>:
> >>>
> >>> > I wrote a program in C# that creates a spectrogram from the waveform
> of
> >>> > a
> >>> > .wav music file. I now want to port it to Python, and I want to try
> to
> >>> > use
> >>> > SciPy instead of a direct port of the existing code, because I am not
> >>> > sure
> >>> > that it is perfectly accurate, and it is probably slow.
> >>> >
> >>> > I am having a hard time finding out how to do this with SciPy. With
> my
> >>> > code, I had a FFT function that took an array of real and imaginary
> >>> > components for each sample, and a second function taking both that
> >>> > produced
> >>> > the amplitude. The FFT function in SciPy just takes one array.
> >>> >
> >>> > Has anyone done this task in SciPy?
> >>>
> >>> We have a realtime spectrogram plot in the Audio Spectrum example for
> >>> Chaco. (See the very last screenshot on the gallery page here:
> >>> http://code.enthought.com/projects/chaco/gallery.php)
> >>>
> >>> You can see the full source code of the example here:
> >>>
> >>>
> https://svn.enthought.com/enthought/browser/Chaco/trunk/examples/advanced/spectrum.py
> >>>
> >>> The lines you would be interested in are the last few:
> >>>
> >>> def get_audio_data():
> >>> pa = PyAudio()
> >>> stream = pa.open(format=paInt16, channels=1, rate=SAMPLING_RATE,
> >>> input=True,
> >>> frames_per_buffer=NUM_SAMPLES)
> >>> string_audio_data = stream.read(NUM_SAMPLES)
> >>> audio_data = fromstring(string_audio_data, dtype=short)
> >>> normalized_data = audio_data / 32768.0
> >>> return (abs(fft(normalized_data))[:NUM_SAMPLES/2], normalized_data)
> >>>
> >>> Here we are using the PyAudio library to directly read from the sound
> >>> card, normalize the 16-bit data, and perform an FFT on it.
> >>>
> >>> In your case, since you are reading a WAV file, you might be
> >>> interested in the zoomed_plot example:
> >>> http://code.enthought.com/projects/chaco/pu-zooming-plot.html
> >>>
> >>> This displays the time-space signal but can easily be modified to show
> >>> the FFT. Here is the relevant code that uses the built-in python
> >>> 'wave' module to read the data:
> >>>
> >>>
> https://svn.enthought.com/enthought/browser/Chaco/trunk/examples/zoomed_plot/wav_to_numeric.py
> >>>
> >>> You should be able to take the 'data' array in the wav_to_numeric
> >>> function and hand that in to the fft function.
> >>>
> >>>
> >>> -Peter
> >>>
> >>> _______________________________________________
> >>> SciPy-user mailing list
> >>> SciPy-user@scipy.org
> >>> http://projects.scipy.org/mailman/listinfo/scipy-user
> >>
> >
> >
> > _______________________________________________
> > SciPy-user mailing list
> > SciPy-user@scipy.org
> > http://projects.scipy.org/mailman/listinfo/scipy-user
> >
> >
>
>
>
> --
> French PhD student
> Website : http://matthieu-brucher.developpez.com/
> Blogs : http://matt.eifelle.com and http://blog.developpez.com/?blog=92
> LinkedIn : http://www.linkedin.com/in/matthieubrucher
> _______________________________________________
> SciPy-user mailing list
> SciPy-user@scipy.org
> http://projects.scipy.org/mailman/listinfo/scipy-user
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://projects.scipy.org/pipermail/scipy-user/attachments/20080831/d56195dd/attachment-0001.html
More information about the SciPy-user
mailing list