Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to convert wav file to float amplitude

so I asked everything in the title:

I have a wav file (written by PyAudio from an input audio) and I want to convert it in float data corresponding of the sound level (amplitude) to do some fourier transformation etc...

Anyone have an idea to convert WAV data to float?

like image 433
user995673 Avatar asked Oct 14 '11 15:10

user995673


People also ask

How do I change the sample rate of a WAV file?

In the General Preferences tab, click on Import Settings, located towards the bottom. Click on the menu next to Import Using > WAV Encoder. Then click to change Setting > Custom and a new window will open. In the WAV Encoder window, change the Sample Rate to 44.100 kHz and Sample Size to 16-bit.

How do I change the bit size in a WAV file?

Hit the gear icon right next to the audio file. Select the Audio section and choose WAV. Click on Settings again and choose the new bitrate for your WAV file. Click on Create to finalize the settings made.

Can you convert WAV to AAC?

How to convert a WAV to a AAC file? Choose the WAV file that you want to convert. Select AAC as the the format you want to convert your WAV file to. Click "Convert" to convert your WAV file.


2 Answers

I have identified two decent ways of doing this.

Method 1: using the wavefile module

Use this method if you don't mind installing some extra libraries which involved a bit of messing around on my Mac but which was easy on my Ubuntu server.

https://github.com/vokimon/python-wavefile

import wavefile

# returns the contents of the wav file as a double precision float array
def wav_to_floats(filename = 'file1.wav'):
    w = wavefile.load(filename)
    return w[1][0]

signal = wav_to_floats(sys.argv[1])
print "read "+str(len(signal))+" frames"
print  "in the range "+str(min(signal))+" to "+str(min(signal))

Method 2: using the wave module

Use this method if you want less module install hassles.

Reads a wav file from the filesystem and converts it into floats in the range -1 to 1. It works with 16 bit files and if they are > 1 channel, will interleave the samples in the same way they are found in the file. For other bit depths, change the 'h' in the argument to struct.unpack according to the table at the bottom of this page:

https://docs.python.org/2/library/struct.html

It will not work for 24 bit files as there is no data type that is 24 bit, so there is no way to tell struct.unpack what to do.

import wave
import struct
import sys

def wav_to_floats(wave_file):
    w = wave.open(wave_file)
    astr = w.readframes(w.getnframes())
    # convert binary chunks to short 
    a = struct.unpack("%ih" % (w.getnframes()* w.getnchannels()), astr)
    a = [float(val) / pow(2, 15) for val in a]
    return a

# read the wav file specified as first command line arg
signal = wav_to_floats(sys.argv[1])
print "read "+str(len(signal))+" frames"
print  "in the range "+str(min(signal))+" to "+str(min(signal))
like image 82
yeeking Avatar answered Oct 18 '22 07:10

yeeking


I spent hours trying to find the answer to this. The solution turns out to be really simple: struct.unpack is what you're looking for. The final code will look something like this:

rawdata=stream.read()                  # The raw PCM data in need of conversion
from struct import unpack              # Import unpack -- this is what does the conversion
npts=len(rawdata)                      # Number of data points to be converted
formatstr='%ih' % npts                 # The format to convert the data; use '%iB' for unsigned PCM
int_data=unpack(formatstr,rawdata)     # Convert from raw PCM to integer tuple

Most of the credit goes to Interpreting WAV Data. The only trick is getting the format right for unpack: it has to be the right number of bytes and the right format (signed or unsigned).

like image 7
cckerr Avatar answered Oct 18 '22 08:10

cckerr