Il est facile de rééchantillonner un tableau comme
a = numpy.array([1,2,3,4,5,6,7,8,9,10])
avec un entier facteur de rééchantillonnage . Par exemple, avec un facteur 2:
b = a[::2] # [1 3 5 7 9]
Mais avec un facteur de rééchantillonnage non entier, cela ne fonctionne pas aussi facilement:
c = a[::1.5] # [1 2 3 4 5 6 7 8 9 10] => not what is needed...
Il doit être (avec interpolation linéaire):
[1 2.5 4 5.5 7 8.5 10]
ou (en prenant le plus proche voisin dans le tableau)
[1 3 4 6 7 9 10]
Comment rééchantillonner un tableau numpy avec un facteur de rééchantillonnage non entier?
Exemple d'application: rééchantillonnage/repitching du signal audio
Comme scipy.signal.resample
peut être très lent , j'ai cherché d'autres algorithmes adaptés à l'audio.
Il semble que Erik de Castro Lopo SRC (a.k.a. Secret Rabbit Code a.k.a. libsamplerate) est l'un des meilleurs algorithmes de rééchantillonnage disponibles.
Il est utilisé par scikit.samplerate
, mais cette bibliothèque semble compliquée à installer (j'ai abandonné sous Windows).
Heureusement, il existe une enveloppe facile à utiliser et à installer Python pour libsamplerate
, faite par Tino Wagner: https: // pypi. org/project/samplerate / . Installation avec 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')
Lecture/comparaison intéressante de nombreuses solutions de rééchantillonnage: http://signalsprocessed.blogspot.com/2016/08/audio-resampling-in-python.html
Addendum: comparaison des spectrogrammes d'un balayage de fréquence rééchantillonné (20hz à 20khz):
1) Original
2) Rééchantillonné avec le module libsamplerate/samplerate
3) Rééchantillonné avec numpy.interp
("Interpolation linéaire unidimensionnelle"):
NumPy a numpy.interp
qui fait une interpolation linéaire:
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 a scipy.interpolate.interp1d
qui peut effectuer une interpolation linéaire et la plus proche (bien que le point le plus proche ne soit pas évident):
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.])
Puisque vous mentionnez qu'il s'agit de données d'un fichier audio .WAV, vous pouvez regarder scipy.signal.resample
.
Rééchantillonner les échantillons
x
ennum
en utilisant la méthode de Fourier le long de l'axe donné.Le signal rééchantillonné commence à la même valeur que
x
mais est échantillonné avec un espacement delen(x) / num * (spacing of x)
. Parce qu'une méthode de Fourier est utilisée, le signal est supposé être périodique.
Votre tableau linéaire a
n'est pas bon pour le tester, car il n'est pas périodique en apparence. Mais considérons les données sin
:
x=np.arange(10)
y=np.sin(x)
y1, x1 =signal.resample(y,15,x) # 10 pts resampled at 15
comparer ceux-ci avec
y1-np.sin(x1) # or
plot(x, y, x1, y1)
Et si vous voulez l'échantillonnage entier
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]
Dans le traitement du signal, vous pouvez considérer le rééchantillonnage comme un redimensionnement du tableau et une interpolation des valeurs manquantes ou des valeurs avec un indice non entier en utilisant les méthodes les plus proches, linéaires, cubiques, etc.
En utilisant scipy.interpolate.interp1d
, vous pouvez réaliser un rééchantillonnage unidimensionnel en utilisant la fonction suivante
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))
par exemple.:
a = np.array([1,2,3,4,5,6,7,8,9,10])
resample(a, factor=1.5, kind='linear')
les rendements
array([ 1. , 2.5, 4. , 5.5, 7. , 8.5, 10. ])
et
a = np.array([1,2,3,4,5,6,7,8,9,10])
resample(a, factor=1.5, kind='nearest')
les rendements
array([ 1., 2., 4., 5., 7., 8., 10.])