Nico AD Nico AD - 9 months ago 136
Python Question : can't write wavfile

I have an issue writing a 2d numpy array as a wave file (audio)

According to the doc I should write a 2d int16 numpy array

16-bit PCM -32768 +32767 int16

As my numpy array in range (-1,1) in float32 format I first convert it to 16 bits int

stereoAudio = ((stereoAudio * bits16max)).astype('int16')

print "argmax : " + str(np.amax(stereoAudio))
print "argmin : " + str(np.amin(stereoAudio))

outWaveFileName = "out/file.wav"
print "writing " + outWaveFileName

I get the following output :

argmax : 4389
argmin : -4381
writing out/file.wav
Traceback (most recent call last):
File "/Users/me/", line 132, in <module>
File "//anaconda/lib/python2.7/site-packages/scipy/io/", line 353, in write
bytes_per_second, block_align, bit_depth)
error: ushort format requires 0 <= number <= USHRT_MAX

as my values are between -4391 and 4389 in 16bits format it should be ok. but my data looks interpreted as ushort

Answer Source

The write function in expects the input array to have the shape (num_samples, num_channels). I suspect your array has shape (num_channels, num_samples). Then write tries to put num_samples in a 16 bit field in a structure that gets written to the WAV file, but the value of num_samples is too big for a 16 bit value. (Note that if num_samples were small enough, you would not get an error, but the file would not have the correct format.)

A quick fix is to write the transpose of your array:

wavfile.write(outWaveFileName, 44100, stereoAudio.T)

For example, here is some code that demonstrates the error; x and y have shape (2, 40000):

In [12]: x = (2*np.random.rand(2, 40000) - 1).astype(np.float32)

In [13]: y = (x*32767).astype('int16')

In [14]: from import wavfile

In [15]: wavfile.write('foo.wav', 44100, y)
error                                     Traceback (most recent call last)
<ipython-input-15-36b8cd0e729c> in <module>()
----> 1 wavfile.write('foo.wav', 44100, y)

/Users/warren/anaconda/lib/python2.7/site-packages/scipy/io/wavfile.pyc in write(filename, rate, data)
    352         fmt_chunk_data = struct.pack('<HHIIHH', format_tag, channels, fs,
--> 353                                      bytes_per_second, block_align, bit_depth)
    354         if not (dkind == 'i' or dkind == 'u'):
    355             # add cbSize field for non-PCM files

error: ushort format requires 0 <= number <= USHRT_MAX

Transpose the array so the input to wavfile.write has the expected shape:

In [16]: wavfile.write('foo.wav', 44100, y.T)

Read back the data to verify that it worked as expected:

In [22]: fs, z ='foo.wav')

In [23]: np.allclose(z, y.T)
Out[23]: True