【Day8】 用 MelGan 把 Mel 转成 Waveform

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


<<:  day8 : logging集中(中)

>>:  寝室的秘密授课(二):程序概念

[05] 挂telegram机器人的hook

把上一篇刚打得code删一删 指留下需要的 post 有 data 的部分来呼叫 hook 相关功能...

Day23 Methods (Ⅰ)

假如说要让程序重复执行的话,有二种方法:1.剪下贴上2.使用方法 是宣告一个函数的意思,int、vo...

[Day30] Pentesting CheatSheet Meow Meow

终於到了最後一天了,感觉这阵子打了好多好多的靶机哦,希望过去的这些文章可以对大家有一些帮助。非常感谢...

Day22 Redis架构实战-高可用性使用Sentinel机制

Redis高可用性 # 高可用配置 ---> Redis (Replica) client -...

4套最佳 Instagram 影片下载器-PC端〖2022亲测〗

作为最受欢迎的社交媒体平台之一,Instagram 绝对是在线分享媒体的最佳场所,例如照片、视频、直...