Resample массив numpy

это легко пересчитать массив, как

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

со значением пересчет фактор. Например, с коэффициентом 2 :

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

но с нецелым коэффициентом пересчета, это не так легко :

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

это должно быть (с линейной интерполяцией):

[1 2.5 4 5.5 7 8.5 10]

или (взяв ближайшего соседа в массиве)

[1 3 4 6 7 9 10]

как пересчитываете массив NumPy с нецелым передискретизации фактор?

пример применения: пересчет / повторное переключение аудиосигнала

4 ответов


NumPy имеет numpy.interp что делает линейную интерполяцию:

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 имеет scipy.interpolate.interp1d который может делать линейную и ближайшую интерполяцию (хотя какая точка ближе всего может быть не очевидна):

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

поскольку вы упомянули, что это данные из аудио .WAV файл, вы можете посмотреть на scipy.signal.resample.

Resample x to num образцы с использованием метода Фурье вдоль заданной оси.

пересчитанный сигнал начинается с того же значения, что и x но выбираем с интервалом len(x) / num * (spacing of x). Потому что Используется метод Фурье, сигнал считается периодическое.

ваш линейный массив a Не могу проверить это на, поскольку он не является периодическим по внешнему виду. Но подумайте!--8--> данные:

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

сравните их с любым

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

и если вы хотите целочисленную выборку

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]

As scipy.signal.resample может быть очень медленно, Я искал другие алгоритмы, адаптированные для аудио.

кажется, что Эрик де Кастро Лопо SRC (а.к.а. Секретный код кролика.к.а. libsamplerate) является одним из лучших алгоритмов передискретизации в наличии.

  • используется , но эта библиотека кажется сложной для установки (я отказался от Windows).

  • к счастью, есть простая в использовании и простая в установке оболочка Python для libsamplerate, сделанный Тино Вагнером:https://pypi.org/project/samplerate/. Установка с pip install samplerate. Использование:

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

интересное чтение / сравнение многих решений для повторной выборки: http://signalsprocessed.blogspot.com/2016/08/audio-resampling-in-python.html


дополнение: сравнение спектрограмм пересчитанной развертки частоты (20hz до 20 кГц):

1) оригиналы

2) пересчитано с libsamplerate/samplerate модуль

3) пересчитан с numpy.interp ("одномерная линейная интерполяция"):