2018年12月20日 星期四

[resampling] 使用 內插法 進行訊號的 sampling rate 轉換



https://stackoverflow.com/questions/51420923/resampling-a-signal-with-scipy-signal-resample

import scipy.signal
import matplotlib.pyplot as plt
import numpy as np


def resample_by_interpolation(signal, input_fs, output_fs):

scale = output_fs / input_fs
# calculate new length of sample
n = round(len(signal) * scale)

# use linear interpolation
# endpoint keyword means than linspace doesn't go all the way to 1.0
# If it did, there are some off-by-one errors
# e.g. scale=2.0, [1,2,3] should go to [1,1.5,2,2.5,3,3]
# but with endpoint=True, we get [1,1.4,1.8,2.2,2.6,3]
# Both are OK, but since resampling will often involve
# exact ratios (i.e. for 44100 to 22050 or vice versa)
# using endpoint=False gets less noise in the resampled sound
resampled_signal = np.interp(
np.linspace(0.0, 1.0, n, endpoint=False), # where to interpret
np.linspace(0.0, 1.0, len(signal), endpoint=False), # known positions
signal, # known data points
)
return resampled_signal

# upsampling example
input_fs = 10 #256
output_fs = 256 #20

# upsampling example (mass num)
input_fs = 200 #256
output_fs = 256 #20

x = np.linspace(0, 10, input_fs, endpoint=False)
y = np.cos(-x**2/6.0)
yre = scipy.signal.resample(y,output_fs)


xre = np.linspace(0, 10, output_fs, endpoint=False)

yre_polyphase = scipy.signal.resample_poly(y, output_fs, input_fs)
yre_interpolation = resample_by_interpolation(y, input_fs, output_fs) # downsampling (interpolation)

print('len x ', len(x))
print('len y ', len(y))
print('len yre_polyphase ', len(yre_polyphase))
print('len yre_interpolation ', len(yre_interpolation))

plt.figure(figsize=(10, 6))
plt.plot(x, y,'b')
plt.plot(xre, yre,'or-')

plt.plot(xre, yre_polyphase, 'og-')
plt.plot(xre, yre_interpolation, 'ok-')

plt.plot(x, y,'b')
# plt.legend(['original signal', 'scipy.signal.resample', 'scipy.signal.resample_poly', 'interpolation method'], loc='lower left')
plt.legend(['original signal', 'scipy.signal.resample', 'scipy.signal.resample_poly', 'interpolation method'], loc='lower left')
plt.show()