iT邦幫忙

2021 iThome 鐵人賽

DAY 8
1
AI & Data

AI Voice Conversion系列 第 8

【Day8】 用 MelGan 把 Mel 轉成 Waveform

  • 分享至 

  • xImage
  •  

MelGan

  • 誠如昨天所說的,使用 Wavenet_Vocoder 生成聲音的速度實在是太慢了,所以我們改用 MelGan

你可以從他的名字中看出一些端倪,MelGan 顧名思義就是用 GAN 去達成的

  • 如果還不太清楚 GAN 是什麼的朋友,可以先看一下另一個邦友寫的這篇

Generator

  • 輸入是 melspectrogram,輸出是 waveform,模型架構如下圖

  • 比較需要解釋的是這邊做 Upsampling Layer 的方法,它是透過 ConvTranspose1d 來實現的,在 Keras 的 Layer 中也有一個叫做 Upsampling 的 Layer,但它只是單純的把輸入 Repeat 2 次,並沒有任何參數可以訓練。

  • ConvTranspose 做的事情用一句話解釋的話就是,它在正向與反向傳播中做與 Conv 相反的運算。因此如果前面先過了一層 Conv,再過了 ConvTranspose 之後就可以得到與原始輸入大小一樣的 feature Map (參數設定一樣的話),它的 Upsampling 指的就會是對 feature Map 做的 Upsampling,而不是對原始的輸入。

  • 重點在於,怎麼 Upsampling 才是比較合理的,其實就是靠 hop_length 來決定的

就是在 Day6 中介紹的那個 hop_length

再看一次上面的圖,因為 MelGan 用的輸入聲音 Sampling rate 為 22.05Khz, 而它的 n_fft = 1024 和 librosa 預設的不同,所以 hop_length = 256,看一下上面的 Upsampling 數等於

[8X] X [8X] X [2X] X [2X] = 256
  • 一個細節就是最後的 Conv 是 1X1 加上 tanh 的 Activate,輸出範圍在[-1~1] 來滿足取值範圍

Discriminator

  • 輸入是 Ground_truth waveform + Generator 生成的 waveform

  • 在 MelGan 裡面用到的 Discriminator 是 multi-scale discriminator,這種架構就是原本只用一個 Discriminator 現在改用 N 個 (這邊是 3),然後把輸入做 average pooling 然後送到各個 Discriminator (如下圖所示),這樣做的原因是 MelGan 假設了接收不同 scale 資料的 discriminator 可以學習到不同頻段的特徵

  • 每個 Discriminator 的結構如下圖所示,這邊的 DownSampling 一樣不是 keras.layer 裡面DownSampling,只是單純用 Conv 然後 stride 控制 DownSampling 的 shape 而已。接著只拿最後一層的 Output 跟倒數第二層的 Feature maps 去算 hinge loss

  • 最後拿 LOSS 去最小化 Ground_truth 與 1 的差距,以及 Generator 生成的 waveform 與 0 的差距,讓 Generator 生出來的聲音可以騙過 Discriminator 就完成了。

但是要訓練這東西,據說在 V100 上面要訓練半個月

所以我們不會自己訓練這個 XD,我們就直接拿來用,去官方上的 Github 下載完整的 code 還包含 Pre-trained model (預設是使用 multi_speaker.pt 這個)。

Inference

在使用之前,請先確保你的 waveform 資料經過了這些處理,而且 sampling_rate 是 22.05khz

# 不是 22.05khz 的話請先 resample
x = librosa.resample(x, fs, target_fs)

def mel_gan_handler(x, fft_length = 1024, hop_length = 256,sr = 22050):
    wav = normalize(x)
    p = (fft_length - hop_length) // 2
    wav = np.squeeze(np.pad(wav, (p, p), "reflect"))
    fft = librosa.stft(
                       wav, 
                       n_fft = fft_length, 
                       hop_length = hop_length,
                       window = 'hann',
                       center = False
                     )
    # 這裡的 abs 是 sqrt(實部**2 + 虛部**2)
    mag = abs(fft)
    mel_basis = mel(sr, 1024, fmin = 0.0 , fmax=None, n_mels=80)
    mel_output = np.dot(mel_basis,mag)
    log_mel_spec = np.log10(np.maximum(1e-5,mel_output)).astype(np.float32)
    return log_mel_spec

注意,這裡輸入的 mel shape = ( 1,80,x ) 而且是 torch tensor

import IPython.display as ipd
import torch
import numpy as np
from interface import *
vocoder = MelVocoder()
audio = np.squeeze(vocoder.inverse(mel).cpu().numpy())
ipd.Audio(audio,rate = 22050)

這樣就完成了!

小結

今天我們簡單介紹了 MelGan,也在 pytorch 上 Inference 它,雖然還有很多其他不同的 Vocoder,但接下來要介紹的是另一個在 Auto_VC 上用到的 Model 所以 Vocoder 的部分就先暫時告一段落吧 ~~~

參考資料

MelGan 原始論文

/images/emoticon/emoticon09.gif/images/emoticon/emoticon13.gif/images/emoticon/emoticon14.gif/images/emoticon/emoticon22.gif/images/emoticon/emoticon28.gif


上一篇
【Day7】Vocoder Model 以及 WaveNet 介紹
下一篇
【Day9】 Speaker Identification 介紹與 D_VECTOR 實做
系列文
AI Voice Conversion30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言