Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scipy.io : 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

https://docs.scipy.org/doc/scipy-0.18.1/reference/generated/scipy.io.wavfile.write.html

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
wavfile.write(outWaveFileName,44100,stereoAudio)

I get the following output :

argmax : 4389
argmin : -4381
writing out/file.wav
Traceback (most recent call last):
  File "/Users/me/file.py", line 132, in <module>
wavfile.write(outWaveFileName,44100,stereoAudio)
  File "//anaconda/lib/python2.7/site-packages/scipy/io/wavfile.py", 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

like image 331
Nico AD Avatar asked Nov 26 '16 20:11

Nico AD


People also ask

How do I write a WAV file in Python?

The function needs two parameters - first the file name and second the mode. The mode can be 'wb' for writing audio data or 'rb' for reading. A mode of 'rb' returns a Wave_read object, while a mode of 'wb' returns a Wave_write object. Close the file if it was opened by wave.

What does Wavfile read return?

The documentation of scipy. io. wavfile. read says that it returns sample rate and data.

What is Scipy io?

The Scipy.io (Input and Output) package provides a wide range of functions to work around with different format of files. Some of these formats are − Matlab. IDL.


1 Answers

The write function in scipy.io.wavfile 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 scipy.io 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)
    351 
    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 = wavfile.read('foo.wav')

In [23]: np.allclose(z, y.T)
Out[23]: True
like image 190
Warren Weckesser Avatar answered Oct 22 '22 01:10

Warren Weckesser