音声合成メモ(tacotron2その3)
内部処理を見てみる。
今回は、音声ファイルから特徴量(log-mel spectrogram)を求めるところまで。
ソースでは、「mel_spectrogram」関数が該当する。
https://github.com/NVIDIA/tacotron2/blob/master/layers.py#L63
def mel_spectrogram(self, y): """Computes mel-spectrograms from a batch of waves PARAMS ------ y: Variable(torch.FloatTensor) with shape (B, T) in range [-1, 1] RETURNS ------- mel_output: torch.FloatTensor of shape (B, n_mel_channels, T)
「y」にあたる音声ファイル読み込みは「scipy.io.wavfile.read」を使っている。
処理は3つのステップ。
# 短時間フーリエ変換 # filter_length(n_fft) = 1024 # hop_length = 256 # win_length = 1024 magnitudes, phases = self.stft_fn.transform(y) # 振幅を使う magnitudes = magnitudes.data # --> (fft_bin , frame) # メル周波数変換 # n_mel_channels = 80 mel_output = torch.matmul(self.mel_basis, magnitudes) # --> (mel_bin , frame) # 対数を取る mel_output = self.spectral_normalize(mel_output)
STFTの結果は「振幅」の方を使っている。
(「librosa.feature.melspectrogram」では、STFTの「パワー」を使うので、単純な置き換えはできない)
Tensorを使わない処理に書き換えると下記のとおり。
# Load data, sr = librosa.load( audio_path, sr=22050) # STFT S_F = librosa.stft(data, n_fft=1024, win_length=1024, hop_length=256) # 複素数平面におけるユークリッド距離(振幅) amp = np.abs(S_F) # --> (513, frame) # Filterbank matrix mel_basis = librosa.filters.mel(sr=sr, n_fft=1024, n_mels=80, fmin=0.0, fmax=8000.0) # --> (80, 513) # FFT bins into Mel-frequency bins mel = np.matmul(mel_basis, amp) # --> (80, flame) # log-mel log_mel = np.log(np.clip(mel, 1e-5, None))