語音合成系統WORLD

WORLD是一個基於C語言的開源語音合成系統,語音合成主要包括波形拼接和參數合成兩種方法,WORLD是一種基於vocoder的參數合成方法,它相比於STRAIGHT的優勢是減少了計算複雜度,並且可以應用於實時的語音合成。由於STRAIGHT不是開源的系統,並且在WORLD論文中已經對比了WORLD相比於STRAIGHT無論是在合成的音頻質量上還是合成速度上都處於領先優勢,所以這裏我不準備介紹STRAIGHT,我們今天主要講一下WORLD語音合成系統的原理以及使用方法。

WORLD系統如下圖所示,包含三個模塊,分別是DIO、CheapTrick、PLATINUM,其中DIO的作用是用來估計一段波形的Fundamental Frequency(簡稱F0),CheapTrick算法是根據波形和F0來計算spectral envelope,PLATINUM算法是基於波形、F0和spectral envelope來計算aperiodic parameter,下面我們來分別看這些參數的計算原理。
在這裏插入圖片描述

1. F0的計算

F0在維基百科中的定義是:當發聲體由於振動而發出聲音時,聲音一般可以分解爲許多單純的正弦波,所有的自然聲音基本都是由許多頻率不同的正弦波組成的,其中頻率最低的正弦波即爲基音,而其他頻率較高的正弦波則爲泛音,即這些不同正弦波中的最低頻率稱爲基頻。F0是一種非常常用的可以表示聲音的特徵,在WORLD中,F0的計算是基於DIO算法,DIO算法主要包含如下三個步驟:
第一步:使用不同的截止頻率的低通濾波器,如果濾波後的信號只包含基頻,那麼它就是一個正弦波,由於事先我們對F0並不知曉,需要多次試探,所以在這一步中會有很多不同截止頻率的濾波器被使用;

第二步:計算每一個濾波後的信號中的候選基頻以及可信度,由於只包含基頻的信號應該是一個正弦波,因此如下圖所示,四個區間的跨度應該基本相等,我們可以計算四個跨度的平均值,用這個值的倒數來表示候選基頻。同時,計算這四個跨度的標準差來作爲衡量基頻可信度的指標,標準差越大,說明跨度長短差異較大,那麼取此頻率作爲基頻的可信度就較低。

第三步:選取可信度最高的候選基頻作爲最終的基頻。
在這裏插入圖片描述

2. 用於估計頻譜包絡的CheapTrick算法

首先,我們需要明白什麼是語音的頻譜包絡,語音是一個時序信號,例如對於一個採樣頻率爲16kHz的音頻文件,意味着在這個音頻中,每一秒包含16000個採樣點,這些採樣點在計算機中以某種數據形式進行存儲着(例如常見的有16bit整型),當我們使用矩形窗函數對一段音頻進行處理,它就被劃分成多個幀,於是得到了多個子序列,然後對每個子序列進行傅里葉變換操作,就得到了頻率-振幅圖,將這些圖在時間維度上展現出來,就得到了這個語音文件的spectrogram。一張實際的spectrogram如下圖所示。
在這裏插入圖片描述
頻譜包絡實際上是在一個頻率-振幅圖中,將每個頻率共振峯用平滑的曲線連接起來,而這個平滑的曲線就是語音的頻譜包絡,下圖展示了頻譜包絡在頻譜圖中的位置。
在這裏插入圖片描述
確定這個頻譜包絡的算法有很多,例如常見的是倒譜法(Cepstrum,有趣的是,cepstrum與spectrum兩個單詞只是開頭四個字母翻轉了位置而已,這其實也暗示了它們的物理含義有某種巧合的關聯…),在WORLD中,使用的是CheapTrick算法來估計頻譜包絡,該算法工作流程如下:

  • 首先,對信號添加Hanning window,然後對windowed之後的信號計算其功率,公式如下(1)所示;
  • 其次,使用矩形窗函數對功率譜進行平滑化,公式如下(2)所示;
  • 最後,計算功率譜的倒譜,並做倒譜提升,公式如下(3)(4)(5)(6)所示
    在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述
最終得到的Pl(w)就是我們所需要的頻譜包絡。

3. Aperiodic參數提取算法

aperiodic是與混合激勵相關的參數,爲了獲得自然的聲音,激勵源不能只使用週期信號,也需要包含一些非週期信號。在WORLD中,aperiodic參數可以直接基於波形、F0、頻譜包絡來計算得到。這種算法叫做PLATINUM,它的工作流程如下:

  • 首先,對波形添加寬度爲2T0的窗函數,並計算得到其頻譜X(w);
  • 將X(w)除以最小相譜Sm(w)得到Xp(w),公式如(11)所示;
  • 對Xp(w)進行逆iFFT,即可得到激勵信號,公式如(10)所示;

在這裏插入圖片描述
在這裏插入圖片描述
最終的語音合成是通過將最小相譜與激勵信號進行卷積得到。

最後,來看一下如何調用WORLD來合成一段語音以及合成的效果。WORLD源代碼是基於C語言的,但是WORLD也有一個Python wrapper庫——PyWorld,爲了代碼簡潔起見,這裏我們使用PyWorld來演示。

在終端運行pip install pyworld以及pip install soundfile即可安裝PyWorld庫,該庫中提供了一個demo代碼,可以用來演示語音合成。下面一段代碼就是使用WORLD庫來提取音頻特徵,並將此特徵基於vocoder合成新的音頻,原始音頻和新的音頻的波形圖對比如下圖所示。

#獲取音頻的採樣點數值以及採樣率

x, fs = sf. read( 'utterance/vaiueo2d.wav')

#使用DIO算法計算音頻的基頻F0

_f 0, t = pw.dio( x, fs, f0_floor= 50.0, f0_ceil= 600.0, channels_in_octave= 2, frame_period=args.frame_period, speed=args.speed)

#使用CheapTrick算法計算音頻的頻譜包絡

_sp = pw.cheaptrick( x, _f 0, t, fs)

#計算aperiodic參數

_ap = pw.d4c( x, _f 0, t, fs)

#基於以上參數合成音頻

_y = pw.synthesize(_f 0, _sp, _ap, fs, args.frame_period)

#寫入音頻文件

sf. write( 'test/y_without_f0_refinement.wav', _y, fs)

下圖是原始波形與合成後音頻的波形對比,上圖是原始波形,下圖是合成後的音頻波形,可以看到,基本保持一致。
在這裏插入圖片描述
WORLD語音合成系統可以根據F0、spectral envelope、aperiodic三個參數來合成一段語音,保真度很高!
項目地址:語音變調質量
在這裏插入圖片描述
以下是音頻的合成截圖
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
4.Python版代碼

import pyworld as pw
import soundfile as sf
x, fs = sf.read('chagevoice/rec1223.wav')
    # print("x",x)
    # print("fs",fs)
# 2-3 Harvest with F0 refinement (using Stonemask)
_f0_h, t_h = pw.harvest(x, fs)
f0_h = pw.stonemask(x, _f0_h, t_h, fs)
sp_h = pw.cheaptrick(x, f0_h, t_h, fs)
ap_h = pw.d4c(x, f0_h, t_h, fs)
y_h = pw.synthesize(f0_h, sp_h, ap_h, fs, pw.default_frame_period)
# librosa.output.write_wav('result/y_harvest_with_f0_refinement.wav', y_h, fs)
sf.write('result/rec12.wav', y_h, fs)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章