Solución:
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 una interpolación lineal y más cercana (aunque es posible que el punto más cercano no sea 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 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.
-
Es utilizado por scikit’s
scikit.samplerate
, pero esta biblioteca parece ser complicada de instalar (renuncié a Windows). -
Afortunadamente, existe un contenedor de Python fácil de usar y de instalar para
libsamplerate
, realizado por Tino Wagner: https://pypi.org/project/samplerate/. Instalación conpip 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')
Lectura / comparación interesante de muchas soluciones de remuestreo: http://signalsprocessed.blogspot.com/2016/08/audio-resampling-in-python.html
Apéndice: comparación de espectrogramas de un barrido de frecuencia remuestreado (20 Hz a 20 kHz):
1) Original
2) Remuestreado con libsamplerate / samplerate
módulo
3) Remuestreado con numpy.interp
(“Interpolación lineal unidimensional”):
Dado que menciona que se trata de datos de un archivo .WAV de audio, puede mirar scipy.signal.resample
.
Remuestrear
x
paranum
muestras usando el método de Fourier a lo largo del eje dado.La señal remuestreada comienza en el mismo valor que
x
pero se muestrea con un espaciado delen(x) / num * (spacing of x)
. Debido a que se utiliza un método de Fourier, se supone que la señal es periódica.
Tu matriz lineal a
no es bueno para probar esto, ya que no es periódico en apariencia. Pero considera sin
datos:
x=np.arange(10)
y=np.sin(x)
y1, x1 =signal.resample(y,15,x) # 10 pts resampled at 15
comparar estos con cualquiera
y1-np.sin(x1) # or
plot(x, y, x1, y1)