スポンサーリンク

【PyTorch/librosa】Pythonで音声/音楽データをリサンプリングする

librosa

librosaとPyTorchを用いて、Pythonで音声/音楽データ(波形)のリサンプリングを行う。Numpyのndarray配列をリサンプリングしたい場合はlibrosaを用い、PyTorchのTensor配列をリサンプリングしたい場合は、PyTorchを用いる。

用いるサンプル音源を、_sample_dataフォルダにダウンロードする。

import os
import requests

_SAMPLE_DIR = "_sample_data"
SAMPLE_WAV_URL = "https://pytorch-tutorial-assets.s3.amazonaws.com/steam-train-whistle-daniel_simon.wav"
SAMPLE_WAV_PATH = os.path.join(_SAMPLE_DIR, "steam.wav")

os.makedirs(_SAMPLE_DIR, exist_ok=True)

with open(SAMPLE_WAV_PATH, 'wb') as f:
    f.write(requests.get(SAMPLE_WAV_URL).content)

librosa.resampleの使い方【Numpy ndarray】

librosaでリサンプルするには、librosa.resampleを使う。第一引数yにリサンプルするndarray配列、第二引数orig_srに元のサンプリング周波数、第三引数target_srにリサンプル後のサンプリング周波数を指定する。リサンプル後の波形がndarray配列として返ってくる。

import librosa

y, sr = librosa.load(SAMPLE_WAV_PATH, sr=None, mono=False)
print(y.shape)
# (2, 109368)
print(sr)
# 44100

re_sr = 8000
y_8k = librosa.resample(y=y, orig_sr=sr, target_sr=re_sr)
print(y_8k.shape)
# (2, 19840)

サンプリング周波数を44100Hzから8000Hzにリサンプリングしたことによって、信号長が短くなっていることが確認できる。

第四引数res_typeを指定することで、リサンプリングの手法変えることができる。デフォルトは、‘kaiser_best’で他以下方法から選択が可能である。

  • ‘kaiser_best’ (default)
  • ‘kaiser_fast’
  • ‘fft’ or ‘scipy’
  • ‘polyphase’
  • ‘linear’
  • ‘zero_order_hold’
  • ‘sinc_best’, ‘sinc_medium’ or ‘sinc_fastest’
  • ‘soxr_vhq’, ‘soxr_hq’, ‘soxr_mq’ or ‘soxr_lq’
  • ‘soxr_qq’
y_8k_kaiser_fast = librosa.resample(y=y, orig_sr=sr, target_sr=re_sr, res_type='kaiser_fast')

torchaudio.functional.resample/torchaudio.transforms.Resampleの使い方【PyTorch Tensor】

PyTorch Tensor配列として音源を読み込む。

import torch
import torchaudio

waveform, sample_rate = torchaudio.load(filepath=SAMPLE_WAV_PATH)

print(waveform.shape)
# torch.Size([2, 109368])
print(sample_rate)
# 44100

torchaudio.functional.resample

torchaudio.functional.resampleの第一引数waveformにリサンプルするTensor配列、第二引数orig_freqに元のサンプリング周波数、第三引数new_freqにリサンプル後のサンプリング周波数を指定する。リサンプル後の波形がTensor配列として返ってくる。

import torchaudio.functional as F

re_sample_rate = 8000

resampled_waveform = F.resample(waveform=waveform, orig_freq=sample_rate, new_freq=re_sample_rate)

print(resampled_waveform.shape)
# torch.Size([2, 19840])

リサンプルの補間方法は、引数resampling_methodを指定する。以下から選択できる。

  • sinc_interpolation(default)
  • kaiser_window
resampled_waveform_kaiser = F.resample(waveform=waveform, orig_freq=sample_rate, new_freq=re_sample_rate, resampling_method='kaiser_window')

torchaudio.transforms.Resample

torchaudio.transforms.Resampleもtorchaudio.functional.resampleとほぼ同様の使い方で、インスタンスを事前に生成して使う。

import torchaudio.transforms as T

resampler = T.Resample(orig_freq=sample_rate, new_freq=re_sample_rate, resampling_method='kaiser_window')
resampled_waveform = resampler(waveform)
print(resampled_waveform.shape)
# torch.Size([2, 19840])

torchaudio.transforms.Resampleは、リサンプリングに使用されるカーネルを事前計算してキャッシュして使うため、都度計算するtorchaudio.functional.resampleよりも、同じパラメータで計算を複数回行うときに早くなります。下記、速度計測結果でもかなり速度に差があることが分かります。

%%timeit

for _ in range(10):
    resampled_waveform_kaiser = F.resample(waveform=waveform, orig_freq=sample_rate, new_freq=re_sample_rate, resampling_method='kaiser_window')
# 10 loops, best of 5: 198 ms per loop
%%timeit

for _ in range(10):
    resampled_waveform = resampler(waveform)
# 100 loops, best of 5: 11.7 ms per loop

関連記事、参考資料

コメント