Remuestrear una matriz numpy

Es fácil remuestrear una matriz como

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

con un factor de remuestreo entero. Por ejemplo, con un factor 2:

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

Pero con un factor de remuestreo no entero, no funciona tan fácilmente:

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

Debería ser (con interpolación lineal):

 [1 2.5 4 5.5 7 8.5 10] 

o (tomando el vecino más cercano en la matriz)

     [1 3 4 6 7 9 10] 

    ¿Cómo volver a muestrear una matriz numpy con un factor de remuestreo no entero?

    Ejemplo de aplicación: remuestreo / repitching de la señal de audio

    NumPy tiene numpy.interp que hace interpolación lineal:

     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 tiene scipy.interpolate.interp1d que puede hacer interpolación lineal y más cercana (aunque el punto más cercano podría no ser obvio):

     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.]) 

    Como menciona que se scipy.signal.resample datos de un archivo de audio .WAV, puede buscar en scipy.signal.resample .

    Volver a muestrear x a num muestras usando el método de Fourier a lo largo del eje dado.

    La señal remuestreada comienza con el mismo valor que x pero se muestrea con un espaciado de len(x) / num * (spacing of x) . Debido a que se utiliza un método de Fourier, se supone que la señal es periódica.

    Su matriz lineal a no es buena para probar esto, ya que no es periódica en apariencia. Pero considera los datos del sin :

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

    compara estos con cualquiera

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

    Y si quieres el muestreo entero

     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] 

    Como scipy.signal.resample puede ser muy lento , busqué otros algoritmos adaptados para audio.

    Parece que el SRC de Erik de Castro Lopo (también conocido como Secret Rabbit Code, también conocido como libsamplerate) es uno de los mejores algoritmos de remuestreo disponibles.

    • Lo utiliza scikit.samplerate de scikit.samplerate , pero esta biblioteca parece ser complicada de instalar (me di por vencida en Windows).

    • Afortunadamente, hay un contenedor Python fácil de usar y fácil de instalar para libsamplerate , creado por Tino Wagner: https://pypi.org/project/samplerate/ . Instalación con pip install samplerate . Uso:

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

    Interesante lectura / comparación de muchas soluciones de remuestreo: http://signalsprocessed.blogspot.com/2016/08/audio-resampling-in-python.html


    Addendum: comparación de los espectrogtwigs de un barrido de frecuencia remuestreado (20 hz a 20 kHz):

    1) Original

    2) samplerate módulo samplerate / samplerate

    3) numpy.interp con numpy.interp (“Interpolación lineal unidimensional”):