Retry numpy array

It's easy to remake an array like

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

with integer resampling coefficient. For example, with a coefficient of 2:

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

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

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

This should be (with linear interpolation):

 [1 2.5 4 5.5 7 8.5 10] 

or (taking the nearest neighbor in the array)

 [1 3 4 6 7 9 10] 

How to reconfigure a numpy array with a non-integer resampling rate?

Application example: re-fetch / retransmit audio

+9
source share
5 answers

Since scipy.signal.resample can be very slow , I was looking for other algorithms adapted for audio.

It seems that Erik de Castro Lopo SRC (aka rabbit secret code aka libsamplerate) is one of the best resampling algorithms available.

  • It is used by scikit scikit.samplerate , but this library seems complicated to install (I refused Windows).

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

     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') 

An interesting read / compare of many resampling solutions: http://signalsprocessed.blogspot.com/2016/08/audio-resampling-in-python.html


Addendum: comparison of frequency re-scanning spectrograms (20 Hz - 20 kHz):

1) Original

RiOLd.jpg

2) Sampled using the libsamplerate / samplerate module

rJj7H.jpg

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

WE1HG.jpg

+4
source

NumPy has numpy.interp that 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 perform linear and closest interpolation (although the closest point may 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.]) 
+15
source

Since you mention that this is data from a .WAV audio file, you can look at scipy.signal.resample .

Sample x to num using the Fourier method along this axis.

The re-selected signal starts with the same value as x , but is sampled with the interval len(x) / num * (spacing of x) . Because the Fourier method is used, the signal is considered periodic.

Your linear array a not good to test this, since it is not periodic in appearance. But consider sin data:

 x=np.arange(10) y=np.sin(x) y1, x1 =signal.resample(y,15,x) # 10 pts resampled at 15 

compare them with

 y1-np.sin(x1) # or plot(x, y, x1, y1) 
+9
source

And if you selected an integer sample

 a = numpy.array([1,2,3,4,5,6,7,8,9,10]) factor = 1.5 x = map(int,numpy.round(numpy.arange(0,len(a),factor))) sampled = a[x] 
+4
source

When processing signals, you can think of resampling as the main scaling of the array and interpolation of the missing values ​​or values ​​with a non-integer index using the methods of nearest, linear, cubic, etc.

Using scipy.interpolate.interp1d , you can achieve one-dimensional oversampling using the following function

 def resample(x, factor, kind='linear'): n = np.ceil(x.size / factor) f = interp1d(np.linspace(0, 1, x.size), x, kind) return f(np.linspace(0, 1, n)) 

eg:

 a = np.array([1,2,3,4,5,6,7,8,9,10]) resample(a, factor=1.5, kind='linear') 

profitability

 array([ 1. , 2.5, 4. , 5.5, 7. , 8.5, 10. ]) 

and

 a = np.array([1,2,3,4,5,6,7,8,9,10]) resample(a, factor=1.5, kind='nearest') 

profitability

 array([ 1., 2., 4., 5., 7., 8., 10.]) 
0
source

Source: https://habr.com/ru/post/1215474/


All Articles