Python, resampling tools dont work as expected

I've tried both using scikit.samplerate.resample and scipy.signal.resample. With neither of them can I achieve the result I want.

Scipy.samplerate:

file1 = '../machine_learning/voice_snippets_stepvoices/t10_9steps.wav'
file2 = '../random_data/t10_9steps.wav'

secs = len(y)/sr # Number of seconds in signal X

samps = secs*16000 # Number of samples to downsample
Y = scipy.signal.resample(y, samps)

scipy.io.wavfile.write(file2, 16000, Y)
#librosa.output.write_wav(file2, Y, 16000)


With both the outputs from scipy/librosa-write_wav() I can't listen to the file. So I assume the file is corrupted and this would be a result of the scipy.resample step. Yet I cannot work out why. I have no error logs to go off. I've tried plotting y and Y on wavplots and they are both the same except for different length x-axis(samples).

Any ideas?

Scikit.resample:

file = '../machine_learning/voice_snippets_stepvoices/t10_9steps.wav'
new_file = '../testing/random_data/t10_9steps.wav'
ratio = 16000/48000

y_new = resample(y, ratio, 'sinc_best', True)
scipy.io.wavfile.write(new_file, 16000, y_new)


In this one I do get an output but it changes somewhat noisy audio of someone speaking to what sounds like Skrillex... (Joking. but look at the graphs).

I didn't expect the resampling to have this effect especially since scikit.resample is supposed to be the best resampling tool for python. (and yes it does apply anti-aliasing).

Anyone have any idea why these techniques aren't working?

Thanks a lot (:

EDIT:

Thanks @hulappa for the solution. It was related to the output I got from scipy.io.wavfile.read. I used this code to solve:

 # scale to -1.0 -- 1.0 - https://stackoverflow.com/questions/2060628/reading-wav-files-in-python

if y.dtype == 'int16':
nb_bits = 16 # -> 16-bit wav files
elif y.dtype == 'int32':
nb_bits = 32 # -> 32-bit wav files
max_nb_bit = float(2 ** (nb_bits - 1))
samples = y / (max_nb_bit + 1.0) # samples is a numpy array of float representing

#--------------


Alas, this only worked for scikit.samplerate.resample(). I still get an unreadable file from using scipy.signal.resample().

I have tried running scipy.signal.resample() on a sine wave like so:

fs = 48000 # sample rate
f = 5 # the frequency of the signal
x = np.arange(fs) # the points on the x axis for plotting
# compute the value (amplitude) of the sin wave at the for each sample
y = [ np.sin(2*np.pi*f * (i/float(fs))) for i in x]

secs = len(y)/fs # Number of seconds in signal X
samps = secs*16000 # Number of samples to downsample
Y = scipy.signal.resample(y, samps)

file1 = '../random_data/sine48000.wav'
file2 = '../random_data/sine16000.wav'

scipy.io.wavfile.write(file2, 16000, Y)
scipy.io.wavfile.write(file1, 48000, np.array(y))


I cannot listen to both the resampled wav file or the sine wav file. I assume this is a careless error but I will put this here in case an answer helps future readers.

• What do the resamplers give if the input is a pure sinusoid? – AnonSubmitter85 Feb 14 '18 at 15:55
• Could it be related to the fact that scipy.io.wavfile.read typically returns an array of integers, depending on the data type used in the file? You could try converting y to a floating point representation before applying resampling. For a N bit signed wav file that would be something along the lines of: y_float = y / 2.0**(N-1). – hulappa Feb 15 '18 at 1:12
• Can I please ask you to post the solution as a "self-answer" and accept it too, so the question is closed gracefully and it does not get re-cycled in the system as "un-answered" (?). (Or, @hulappa does it maybe (?)) – A_A Feb 15 '18 at 11:20
• Got it. I posted the solution as an answer now so OP can accept it. – hulappa Feb 15 '18 at 20:22

The problem is that if your wav file stores samples as integers (typically 16 bit signed), $\texttt{scipy.io.wavfile.read()}$ returns an array of integers. If this is the case, you want to convert your signal into a floating point representation before applying resampling. For a wav file which stores values as N bit signed integers, this can be done by:

// Convert y to float array, with values in the interval [-1.0,1.0]
y_float = float(y / (2.0**(N-1) + 1))