ichou1のブログ

主に音声認識、時々、データ分析のことを書く

音声合成メモ(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))