[SciPy-user] Create a spectrogram from a waveform

Matthieu Brucher matthieu.brucher@gmail....
Sun Aug 31 14:19:30 CDT 2008


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


More information about the SciPy-user mailing list