Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resample a numpy array

It's easy to resample an array like

 a = numpy.array([1,2,3,4,5,6,7,8,9,10]) 

with an integer resampling factor. For instance, with a factor 2 :

b = a[::2]    # [1 3 5 7 9] 

But with a non-integer resampling factor, it doesn't work so easily :

c = a[::1.5]    # [1 2 3 4 5 6 7 8 9 10]  => not what is needed... 

It should be (with linear interpolation):

[1 2.5 4 5.5 7 8.5 10] 

or (by taking the nearest neighbour in the array)

[1 3 4 6 7 9 10] 

How to resample a numpy array with a non-integer resampling factor?

Example of application: audio signal resampling / repitching

like image 326
Basj Avatar asked Mar 16 '15 19:03

Basj


People also ask

How do I resize an array in numpy?

With the help of Numpy numpy. resize(), we can resize the size of an array. Array can be of any shape but to resize it we just need the size i.e (2, 2), (2, 3) and many more. During resizing numpy append zeros if values at a particular place is missing.

Can size of numpy array be changed?

Yes, as long as the elements required for reshaping are equal in both shapes. We can reshape an 8 elements 1D array into 4 elements in 2 rows 2D array but we cannot reshape it into a 3 elements 3 rows 2D array as that would require 3x3 = 9 elements.


2 Answers

NumPy has numpy.interp which does linear interpolation:

In [1]: numpy.interp(np.arange(0, len(a), 1.5), np.arange(0, len(a)), a) Out[1]: array([  1. ,   2.5,   4. ,   5.5,   7. ,   8.5,  10. ]) 

SciPy has scipy.interpolate.interp1d which can do linear and nearest interpolation (though which point is nearest might not be obvious):

In [2]: from scipy.interpolate import interp1d In [3]: xp = np.arange(0, len(a), 1.5) In [4]: lin = interp1d(np.arange(len(a)), a)  In [5]: lin(xp) Out[5]: array([  1. ,   2.5,   4. ,   5.5,   7. ,   8.5,  10. ])  In [6]: nearest = interp1d(np.arange(len(a)), a, kind='nearest')  In [7]: nearest(xp) Out[7]: array([  1.,   2.,   4.,   5.,   7.,   8.,  10.]) 
like image 192
xnx Avatar answered Sep 17 '22 17:09

xnx


As scipy.signal.resample can be very slow, I searched for other algorithms adapted for audio.

It seems that Erik de Castro Lopo's SRC (a.k.a. Secret Rabbit Code a.k.a. libsamplerate) is one of the best resampling algorithms available.

  • It is used by scikit's scikit.samplerate, but this library seems to be complicated to install (I gave up on Windows).

  • Fortunately, there is an easy-to-use and easy-to-install Python wrapper for libsamplerate, made by Tino Wagner: https://pypi.org/project/samplerate/. Installation with pip install samplerate. Usage:

    import samplerate from scipy.io import wavfile sr, x = wavfile.read('input.wav')  # 48 khz file y = samplerate.resample(x, 44100 * 1.0 / 48000, 'sinc_best')   

Interesting reading / comparison of many resampling solutions: http://signalsprocessed.blogspot.com/2016/08/audio-resampling-in-python.html


Addendum: comparison of spectrograms of a resampled frequency sweep (20hz to 20khz):

1) Original

2) Resampled with libsamplerate / samplerate module

3) Resampled with numpy.interp ("One-dimensional linear interpolation"):

like image 21
Basj Avatar answered Sep 18 '22 17:09

Basj