iT邦幫忙

2021 iThome 鐵人賽

DAY 7
1
AI & Data

AI Voice Conversion系列 第 7

【Day7】Vocoder Model 以及 WaveNet 介紹

  • 分享至 

  • xImage
  •  

聲碼器 (Vocoder)

  • 合成語音的概念最早是由貝爾實驗室的工程師 - 荷馬·達德利在 1928 年所提出,並在 1939 年 (二戰開打那年) 的紐約世界博覽會上首次展示了他取名為聲碼器的語音合成器

下面這支影片我們可以看到那時候的聲碼器是一台大型機器,在影片 39 秒的地方你可以聽聽那段慘不忍賭的合成人聲,但在那個時候卻是奇蹟。

Yes

如果你很有興趣想知道那台老古董是怎麼發出聲音的話,你可以看一下這篇文章的介紹

  • 看完最古老的 Vocoder 之後,我們廣義上的定義一下 "現在的" Vocoder 其實只要是進行聲音的分析與合成的系統不管軟硬體,我們都可以稱呼他為 Vocoder,所以用 AI 來合成人聲的 Model 才會被稱做 Vocoder。

WaveNet - 直接生成聲音訊號的神經網路

  • WaveNet 是由 DeepMind 的研究人員於 2016年 9 月的一篇論文中提出的,早在 WaveNet 出現之前也有人使用神經網路合成語音,像是 Tacotron可以生成聲音的時頻譜以及一些特徵參數,但最後從頻域回到時域還是用了 Griffin-Lim 演算法 (看來這演算還可以再戰 10 年 ),而 wavenet 不用。除此之外它除了可以用在語音合成之外,也可以用在音樂生成 (GAN Music) 以及語音辨識其他領域,其衍伸出來的 WaveNet_Vocoder,就是 Auto_VC 原本使用的 Vocoder

然而我們不會用 WaveNet_Vocoder 來做,因為它實在是太慢了。

WaveNet 的想法

  • WaveNet 是源自於 PixelCNN 的想法,如果一張圖片 P(X) 是由各像素 {x1 ~ xN} 所組合而成的,那一張圖片就可以說它是各個像素的聯合分布

想像一下不管是圖片或是聲音,下一個元素的產生或多或少都與前一個元素有關,在圖片上的話最直觀的理解就是漸層。

  • 因此如果我們用條件分布的乘積來表示的話就可以寫成這樣。

  • 在生成圖片時就把 前面的像素當作條件來逐點生成 (這個就是慢的主要原因),我們把像素換成聲音訊號就是 WaveNet 在做的事情,所以 WaveNet 要預測的目標其實是一下一個聲音樣本點的機率分布

WaveNet 的資料前處理

  • 聲音訊號通常是以 16 位元的整數儲在電腦裡的,直接用的話模型在每個時間點都要輸出 65536 個機率來表示所有可能樣本點的機率分布,為了降低建模難度 WaveNet 用 µ low 演算法,將輸入資料樣本點量化成 8 位元,變成只有 256 種可能。

WaveNet 的核心

  • WaveNet 裏使用了膨脹因果捲積(Dilated Causal Convolution) 其中膨脹捲積增加了 Respective field,而因果捲積則確保了前後輸出的因果關係

WaveNet 的 Activation Function

WaveNet 中使用了和 PixelCNN 相同的 Gated Activation Unit,這個東西就類似激勵函數,只是它是非線性的,在這裡使用會比單純做 ReLU 好 (因為 ReLU 會把小於 0 的都丟掉)。

# 把輸入分別丟進 sigmoid 跟 tanh, 然後把結果乘起來
def gate(x): 
  res_sigmoid = sigmoid(x)
  res_tanh = tanh(x)
  res = Multiply()([res_sigmoid, res_tanh]) 
  return res

WaveNet 的架構

如上圖所示, 輸入經過因果捲積之後分別進入由膨脹捲積跟 Gated Activation Unit 所組成的 Residual Block, 以及 skip-connections,最後把所有結果相加起來再過 softmax 就是輸出結果。

 def residual_block(x,filters,kernel_size,rate): 
      x = dilated_conv(filters,kernel_size,rate)(x) 
      x = gate(x)        
      x = conv_1D(32,1)(x) # 最後那個 [1*1]
      return x

WaveNet 做 Vocoder

稍微了解 WaveNet 的架構之後,我們現在來談談怎麼用 WaveNet 做 vocoder

  • 前面我們提到了用條件分布的乘積來表示一段聲音,那既然是條件分布就代表說我們還可以給他額外的條件,現在我給原本的公式加上額外的條件 h 重寫之後如下

  • 輸入的條件還可以有兩種形式分別是:

    1. 全局條件:
      整個 model 都照條件去做, 加入之後 Gated Activation Unit 變成

    2. 局部條件:
      限定 model 在什麼時候才照條件去做,加入之後 Gated Activation Unit 變成

  • 在 WaveNet 局部條件的輸入原本是一個 Transpose Conv 它在文字轉語音 (TTS)的做法是先訓練一個 CNN 的語音轉文字模型 (h = F(y)) 然後再把它 Transpose 回來 (y = f(h)), 通過這個將文字轉換成語音,但這樣生出來的語音品質非常糟糕,所以不會直接使用,而是拿來當作局部條件的輸入,而輸入的 ground truth 就是真正的語音。
    而這邊的 Vf,k*y 就是 1X1 Conv 它是拿來取代 Transpose 的,經過實驗證明效果比較好。

  • 同 TTS 的原理,你只要把局部條件換成語音特徵 (mel) 它就變成 Vocoder 了。

  • 如果有興趣想做看看的話,你可以在這裡找到我完整的 DEMO (沒有加條件的部分),這個 repo 適用在 tf2.0+ 。

  • Deep Mind 並沒有釋出他們官方的 Code,不過坊間有不少 implement (目前我看到的大多只做到全局條件),你可以在這裡找到

小結 & 碎念

今天我們談了 Vocoder 它是進行聲音分析與合成的系統,也對 WaveNet 做了簡略的介紹,其實 WaveNet 後來進化出許多快速的版本,像是 Parallel Wavenet 跟 WaveRNN,但我沒研究這些版本有沒有拿來訓練 Vocoder; 而 Vocoder 除了 WaveNet 的作法之外也有很多其他的做法,之後會在做介紹,感謝您的收看 ~ 我們明天再見。

結果 meeting 延期, 多了一個禮拜,賺爛了 XD

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


上一篇
【Day6】窗涵式,n_fft ,hop_length 到底什麼意思啊?
下一篇
【Day8】 用 MelGan 把 Mel 轉成 Waveform
系列文
AI Voice Conversion30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言