Reading *.wav files in Python
Solution 1
Per the documentation, scipy.io.wavfile.read(somefile)
returns a tuple of two items: the first is the sampling rate in samples per second, the second is a numpy
array with all the data read from the file:
from scipy.io import wavfile
samplerate, data = wavfile.read('./output/audio.wav')
Solution 2
Using the struct
module, you can take the wave frames (which are in 2's complementary binary between -32768 and 32767 (i.e. 0x8000
and 0x7FFF
). This reads a MONO, 16-BIT, WAVE file. I found this webpage quite useful in formulating this:
import wave, struct
wavefile = wave.open('sine.wav', 'r')
length = wavefile.getnframes()
for i in range(0, length):
wavedata = wavefile.readframes(1)
data = struct.unpack("<h", wavedata)
print(int(data[0]))
This snippet reads 1 frame. To read more than one frame (e.g., 13), use
wavedata = wavefile.readframes(13)
data = struct.unpack("<13h", wavedata)
Solution 3
Different Python modules to read wav:
There is at least these following libraries to read wave audio files:
- SoundFile
- scipy.io.wavfile (from scipy)
- wave (to read streams. Included in Python 2 and 3)
- scikits.audiolab (unmaintained since 2010)
- sounddevice (play and record sounds, good for streams and real-time)
- pyglet
- librosa (music and audio analysis)
- madmom (strong focus on music information retrieval (MIR) tasks)
The most simple example:
This is a simple example with SoundFile:
import soundfile as sf
data, samplerate = sf.read('existing_file.wav')
Format of the output:
Warning, the data are not always in the same format, that depends on the library. For instance:
from scikits import audiolab
from scipy.io import wavfile
from sys import argv
for filepath in argv[1:]:
x, fs, nb_bits = audiolab.wavread(filepath)
print('Reading with scikits.audiolab.wavread:', x)
fs, x = wavfile.read(filepath)
print('Reading with scipy.io.wavfile.read:', x)
Output:
Reading with scikits.audiolab.wavread: [ 0. 0. 0. ..., -0.00097656 -0.00079346 -0.00097656]
Reading with scipy.io.wavfile.read: [ 0 0 0 ..., -32 -26 -32]
SoundFile and Audiolab return floats between -1 and 1 (as matab does, that is the convention for audio signals). Scipy and wave return integers, which you can convert to floats according to the number of bits of encoding, for example:
from scipy.io.wavfile import read as wavread
samplerate, x = wavread(audiofilename) # x is a numpy array of integers, representing the samples
# scale to -1.0 -- 1.0
if x.dtype == 'int16':
nb_bits = 16 # -> 16-bit wav files
elif x.dtype == 'int32':
nb_bits = 32 # -> 32-bit wav files
max_nb_bit = float(2 ** (nb_bits - 1))
samples = x / (max_nb_bit + 1) # samples is a numpy array of floats representing the samples
Solution 4
IMHO, the easiest way to get audio data from a sound file into a NumPy array is SoundFile:
import soundfile as sf
data, fs = sf.read('/usr/share/sounds/ekiga/voicemail.wav')
This also supports 24-bit files out of the box.
There are many sound file libraries available, I've written an overview where you can see a few pros and cons.
It also features a page explaining how to read a 24-bit wav file with the wave
module.
Solution 5
You can accomplish this using the scikits.audiolab module. It requires NumPy and SciPy to function, and also libsndfile.
Note, I was only able to get it to work on Ubunutu and not on OSX.
from scikits.audiolab import wavread
filename = "testfile.wav"
data, sample_frequency,encoding = wavread(filename)
Now you have the wav data
Related videos on Youtube
Roman
Updated on February 10, 2022Comments
-
Roman over 2 years
I need to analyze sound written in a .wav file. For that I need to transform this file into set of numbers (arrays, for example). I think I need to use the wave package. However, I do not know how exactly it works. For example I did the following:
import wave w = wave.open('/usr/share/sounds/ekiga/voicemail.wav', 'r') for i in range(w.getnframes()): frame = w.readframes(i) print frame
As a result of this code I expected to see sound pressure as function of time. In contrast I see a lot of strange, mysterious symbols (which are not hexadecimal numbers). Can anybody, pleas, help me with that?
-
Roman over 14 yearsOK. I just installed the SciPy but I cannot find any example of the usage of scipy.io.wavfile.
-
Ignacio Vazquez-Abrams over 14 yearsNothing like the interactive interpreter for figuring out how things work! Be ambitious!
-
endolith over 13 yearsYou can combine this with command line conversion tools to open other formats.
-
bastibe over 13 yearsIt seriously lacks the number of channels though. How are you supposed to work with audio without knowing the number of channels?
-
Alex S almost 11 yearsthrowns some weird struct unpacking errors on my computer. I think it's using struct.unpack('<i',data) instead of the struct.unpack('<h',data) nak used below.
-
Finn Årup Nielsen over 10 yearsDoes this library work? I run into a number of problems: scipy.io.wavfile.read('/usr/lib/python2.7/dist-packages/pygame/examples/data/house_lo.wav') -> No data. scipy.io.wavfile.read('/usr/lib/python2.7/dist-packages/pygame/examples/data/secosmic_lo.wav') -> ZeroDivisionError: integer division or modulo by zero
-
Basj over 10 yearshow to handle 24bits stereo files ?
-
Coder404 over 9 yearsthis gives me the error: "struct.error: unpack requires a string argument of length 2"
-
ArthurLambert about 9 yearsIf you run this piece of code with a very big audio file. Your computer will be die to due the memory need by this program. Need to process audio file by block for big audio file
-
jmilloy almost 9 years@Coder404 You probably have a stereo wave file, or a different bit depth.
-
Dennis Golomazov over 8 yearsFor those who, like me, are wondering what is 2s complementary binary, see here stackoverflow.com/questions/1049722/what-is-2s-complement
-
optimus prime almost 8 yearsBut what about 24 bit stereo file?
-
Quetzalcoatl about 7 yearsNote: soundfile.read() normalizes by 2^(n_bits - 1) as in sandoval's scipy.io.wavfile example
-
jeromej about 7 years@Basj
<hh
maybe? -
ATOMP about 6 years@Coder404 To use
struct.unpack
, you have to specify the number of values encoded. For example, to read 11 values usingstruct.unpack
, usestruct.unpack("<11h", waveData)
-
dant about 6 yearsThis is exactly what I was looking for, thanks for doing the digging! I don't know if I would have ever figured this out on my own.
-
stenlytw about 6 yearsgithub.com/scipy/scipy/issues/1930#issuecomment-28460402 For anyone who needs to read 24 bit files, use wavio by Warren Weckesser: github.com/WarrenWeckesser/wavio
-
hobs almost 5 years@bastibe
data
is a 2-D numpy array sodata.shape
returns a tuple of (num_samples, num_channels) -
Derek Ledbetter almost 5 yearsYou can also try
struct.iter_unpack
. -
Tigran Aivazian over 4 yearsUsing scipy.io.wavfile() won't work on 24bit WAV files. It will fail with ""Unsupported bit depth: the wav file has 24-bit data" error.
-
BlackJack almost 4 years@FinnÅrupNielsen Yes it works. But WAV is a container format which can contain samples in many different formats/audio codecs.
wavfile
knows PCM samples and IEEE float samples. Thehouse_lo.wav
is 8 bit PCM and can be read on my machine. Thesecosmic_lo.wav
contains Microsoft ADPCM samples which can't be read and result in a ValueError: Unknown wave file format here. -
BlackJack almost 4 years@ArthurLambert It won't die due to memory exhaustion. It will be slow but it doesn't use much memory at all.
-
BlackJack almost 4 yearsInstead of the
struct
module I would use thearray
module or Numpy arrays. Withstruct
the "<" is wrong by the way. Thewave
module converts the endianess to ”native” endieness, so "<" makes the code platform dependent. -
Boris Verkhovskiy over 3 years
scikits.audiolab
has not been updated since 2010 and it's probably Python 2 only. -
Kedaar Rao over 3 yearsBut when executed, the read returns an error:
Error opening '../audio.wav': File contains data in an unimplemented format.
The file I’m trying to open begins with:OggS
Any idea what’s wrong here? -
EntangledLoops about 2 years@Matthias: I can see that you are the maintainer of
soundfile
, and also that you are posting on many stackoverflow audio-related posts and promotingsoundfile
as the solution everywhere. Whether or not your solution works, this isn't your personal advertising platform or Github. (You can be banned for this.) -
hobs about 2 years@hobs @bastibe correction:
wavefile.read(...)[1].data
is a np.ndarray so for a mono track it will be a 1-D array. For stereo 2-D array with.shape = (num_samples, 2)