Question

I am a very beginner in programming and I use Ubuntu.

But now I am trying to perform sound analysis with Python.

In the following code I used wav package to open the wav file and the struct to convert the information:

from wav import *
from struct import *
fp = wave.open(sound.wav, "rb")
total_num_samps = fp.getnframes()
num_fft = (total_num_samps / 512) - 2 #for a fft lenght of 512
for i in range(num_fft):
  tempb = fp.readframes(512);
  tempb2 = struct.unpack('f', tempb)
print (tempb2)

So in terminal the message that appears is:

struct.error: unpack requires a string argument of length 4

Please, can someone help me to solve this? Someone have a suggestion of other strategy to interpret the sound file?

Was it helpful?

Solution

The format string provided to struct has to tell it exactly the format of the second argument. For example, "there are one hundred and three unsigned shorts". The way you've written it, the format string says "there is exactly one float". But then you provide it a string with way more data than that, and it barfs.

So issue one is that you need to specify the exact number of packed c types in your byte string. In this case, 512 (the number of frames) times the number of channels (likely 2, but your code doesn't take this into account).

The second issue is that your .wav file simply doesn't contain floats. If it's 8-bit, it contains unsigned chars, if it's 16 bit it contains signed shorts, etc. You can check the actual sample width for your .wav by doing fp.getsampwidth().

So then: let's assume you have 512 frames of two-channel 16 bit audio; you would write the call to struct as something like:

channels = fp.getnchannels()
...

tempb = fp.readframes(512);
tempb2 = struct.unpack('{}h'.format(512*channels), tempb)

OTHER TIPS

Using SciPy, you could load the .wav file into a NumPy array using:

import scipy.io.wavfile as wavfile
sample_rate, data = wavfile.read(FILENAME)

NumPy/SciPy will also be useful for computing the FFT.


Tips:

  • On Ubuntu, you can install NumPy/SciPy with

    sudo apt-get install python-scipy
    

    This will install NumPy as well, since NumPy is a dependency of SciPy.

  • Avoid using * imports such as from struct import *. This copies names from the struct namespace into the current module's global namespace. Although it saves you a bit of typing, you pay an awful price later when the script becomes more complex and you lose track of where variables are coming from (or worse, the imported variables mask the value of other variables with the same name).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top