Scipy Write Audio Issue
<p>I'm doing an ICA application where I aim to separate signals from within a mixed signal observation. It seems to work in theory, when I look at the ICA recovered signal in numpy ndarray from, the signal is clearly visible. However, when I try to write this ndarray to a .wav for play back, the signal disappears altogether. This can be easily seen in the following picture:
<a href="http://i.stack.imgur.com/hp2Gn.png" rel="nofollow"><img src="http://i.stack.imgur.com/hp2Gn.png" alt="enter image description here"></a></p>

<p>The first graph shows the numpy ndarray signal of the ICA recovered signal. The second graph shows where I simply loaded the file that was supposedly written by scipy .wav write, as you can see it's silent.</p>

<p>This behavior is puzzling because earlier on I used the exact same procedure in generating my mixed signal observations using a mixing matrix (also in the same format, numpy ndarrays). In the following picture, you'll notice every thing is exactly the same, and yet, for whatever reason, the scipy write .wav <em>worked</em> -- the second graph does verify the signal was loaded from the .wav that was written from the first graph (the numpy nd array).</p>

<p><a href="http://i.stack.imgur.com/gQ2GG.png" rel="nofollow"><img src="http://i.stack.imgur.com/gQ2GG.png" alt="enter image description here"></a></p>

<p>I'd like to know what's behind the conditional success for this. I know that floats and integers need to be handled carefully, but I'm pretty sure I have not overlooked anything. </p>

<p>The pictures explain it pretty well, the only thing I'd like to clarify is what the <code>play_wav</code> function is doing, it basically just writes the .wav and creates an audio object:</p>

<pre><code>def play_wav(file, fs, data):
    wavfile.write(file, fs, data.astype(np.dtype('i2')))
    display(Audio(filename=file))
</code></pre>

<p>imports:</p>

<pre><code>import numpy as np
from scipy.io import wavfile
from IPython.display import display, Audio
from sklearn.decomposition import FastICA
</code></pre>

<p>It looks as though the array you're trying to write contains values in the range [-0.02, 0.02]. When you cast the array to 16bit ints before writing it to the WAV file, all of these values will be truncated to zero!</p>

<p><code>wavfile.write</code> supports float32 arrays, so you could just skip the casting step altogether. Alternatively, rescale the array to fall between 2<sup>15</sup> and -2<sup>15</sup> before casting it to int16, e.g.:</p>

<pre><code>((data + data.min()) * (2 ** 15) / data.ptp()).astype(np.int16)
</code></pre>

python audio scipy scikit-learn signal-processing