文章目录
在本文中,我想介绍一下WORLD,这是一种通常用于语音合成和语音转换的工具。
语音合成和语音转换
最终,Google Home和Amazon Echo登陆日本。
目前尚不清楚智能扬声器在日本的普及程度,但可以肯定的是,语音接口在未来将变得越来越重要。
语音接口中的重要技术之一是语音合成(文本到语音)。您可以轻松地在Mac上试用它,并说“早上好”。但是,通过say命令,您可以看到是否插入了更长的句子,这将是特定于机器的幼稚交谈方式。关于如何使类似人的话语的研究已经进行了很长时间,但是随着深度学习的发展,近来已经产生了无法与人区别的平滑话语。
还有一种称为语音转换的技术,它很接近语音合成。在这里,输入的不是文本而是语音,它是一种“交换希拉里和特朗普的声音”的技术。在娱乐领域中的使用是立即可以想到的,但实际上,这是一项具有重大社会意义的研究,因为它可以用于为失去声音的人提供原始声音。
$说“早上好”
语音合成和语音转换困难
好吧,语音合成和语音质量转换非常困难。
作为一个简单的示例,让我们考虑将声音提高一个八度(增加音调)的过程。声音只是声音,因此您可以提高频率以获得更高的音调。最简单的方法是“以2倍的速度播放”,但这意味着您获得的高音越高,就越快。
那么,如何在不改变说话速度的情况下使高音成为第一位呢?首先想到的是将音频以短间隔快速转发到2倍,然后重复两次。它是“ Aioeueo”的“ Aioe”图像。但是,仅应用此方法将导致无法说出声音。因为wave没有很好地连接。
如您所见,仅通过更改声音的音调就需要考虑很多事情,而且这样做并不容易。
从音频中提取特征
如上所述,很难直接操纵音频的波形,因此将音频转换为特征,对其进行处理并将其返回到波形早已成为惯例。语音合成和语音转换中使用的著名功能包括以下内容。
- 基本频率
代表语音的基本高度 - 光谱包络
表示音调的所谓平滑频谱 - 非周期性指数
显示声带振动和噪声污染波动的影响
每个索引可以独立调整,如果您想改变声音的音调,可以用F0演奏,如果您想改变声音的情绪或音调,则可以使用频谱包络演奏。
语音合成和语音转换工具WORLD
上面的特征并不是很容易提取,但是可以使用特定模型从原始波形中估算得出。因此,为了自己进行从头开始的特征提取,需要具备该领域的丰富知识。
WORLD是一个有用的工具,可以提取此类特征并从中合成波形。与最初在该领域广泛使用的STRAIGHT不同,拥有修改后的BSD许可证的任何人都可以使用它。
安装WORLD
WORLD正式提供C ++和Matlab版本,但还有一个名为PyWorldVocoder的Python包装器。PyWorldVocoder pip易于安装,因此我们这次将使用它。
$ pip install scipy #如果不先放置scipy,则pyworld安装可能会报错
$ pip install pyworld
很简单
尝试WORLD
让我们实际使用WORLD。在这里,我们从语音中提取特征,并从提取的特征中合成语音。
首先,阅读wav文件。
from scipy.io import wavfile
import pyworld as pw
WAV_FILE = 'path_to_the_wav_file'
fs, data = wavfile.read(WAV_FILE)
data = data.astype(np.float) # WORLDはfloat前提のコードになっているのでfloat型にしておく
接下来,使用pyworld提取功能。
_f0, t = pw.dio(data, fs) # 基本周波数の抽出
f0 = pw.stonemask(data, _f0, t, fs) # 基本周波数の修正
sp = pw.cheaptrick(data, f0, t, fs) # スペクトル包絡の抽出
ap = pw.d4c(data, f0, t, fs) # 非周期性指標の抽出
synthesize使用一种方法从获得的特征中合成语音。
synthesized = pw.synthesize(f0, sp, ap, fs)
播放WAV文件
scipy.io.wavfile.write
您可以使用导出文件并播放它,但是如果使用Jupyter,则IPython.display使用该模块会更容易。
import IPython.display as display
print('original')
display.display(
display.Audio(y, rate=fs)
)
print('synthesized')
display.display(
display.Audio(synthesized, rate=fs)
)
尝试转换语音
让我们实际转换声音。首先,如第一个示例中所示,转换为高八度的声音。您可以通过演奏F0来改变声音的音调
high_freq = pw.synthesize(f0*2.0, sp, ap, fs) # 周波数を2倍にすると1オクターブ上がる
print('high_freq')
display.display(
display.Audio(high_freq, rate=fs)
)
一个男人的声音就像一个女人,或者好像他在高音。接下来,尝试保持F0恒定。正如您在这里看到的那样,它是一种机械且无情的声音,就像机器人一样。
robot_like_f0 = np.ones_like(f0)*100 # 100は適当な数字
robot_like = pw.synthesize(robot_like_f0, sp, ap, fs)
print('robot_like')
display.display(
display.Audio(robot_like, rate=fs)
)
最后,让我们通过播放频谱包络来更改音调。
除了较早地将F0加倍外,如果将频谱包络增加1.2,您还将获得更加女性化的发音。
female_like_sp = np.zeros_like(sp)
for f in range(female_like_sp.shape[1]):
female_like_sp[:, f] = sp[:, int(f/1.2)]
female_like = pw.synthesize(f0*2, female_like_sp, ap, fs)
print('female_like')
display.display(
display.Audio(female_like, rate=fs)
)
这样,如果语音不是以原始波形数据表示,而是以一组功能表示,则可以轻松转换语音并播放。
完整代码
#此项目主要是用matlab和c,这里的python使用的是调用c接口
import pyworld as pw
from scipy.io import wavfile
import matplotlib.pyplot as plt
import numpy as np
import os
import soundfile as sf
# base_dir = "E:Python-Wrapper-for-World-Vocoder\demo"
WAV_FILE = "utterance/rmdmy.wav"
# print("WAV_FILE",WAV_FILE)
# 读取文件
# 提取语音特征
x, fs = sf.read(WAV_FILE)
print("x",x)
print("fs",fs)
# f0 : ndarray
# F0 contour. 基频等高线
# sp : ndarray
# Spectral envelope. 频谱包络
# ap : ndarray
# Aperiodicity. 非周期性
f0, sp, ap = pw.wav2world(x, fs) # use default options
#分布提取参数
#使用DIO算法计算音频的基频F0
_f0, t = pw.dio( x, fs, f0_floor= 50.0, f0_ceil= 600.0, channels_in_octave= 2, frame_period=pw.default_frame_period)
#使用CheapTrick算法计算音频的频谱包络
_sp = pw.cheaptrick( x, _f0, t, fs)
#计算aperiodic参数
_ap = pw.d4c( x, _f0, t, fs)
#基于以上参数合成音频
_y = pw.synthesize(_f0, _sp, _ap, fs, pw.default_frame_period)
#写入音频文件
sf. write( 'test1/y_without_f0_refinement.wav', _y, fs)
plt.plot(f0)
plt.show()
plt.imshow(np.log(sp), cmap='gray')
plt.show()
plt.imshow(ap, cmap='gray')
# 合成原始语音
synthesized = pw.synthesize(f0, sp, ap, fs, pw.default_frame_period)
# 1.输出原始语音
sf.write('test1/synthesized.wav', synthesized, fs)
# 2.变高频-更类似女性
high_freq = pw.synthesize(f0*2.0, sp, ap, fs) # 周波数を2倍にすると1オクターブ上がる
sf.write('test1/high_freq.wav', high_freq, fs)
# 3.直接修改基频,变为机器人发声
robot_like_f0 = np.ones_like(f0)*100 # 100は適当な数字
robot_like = pw.synthesize(robot_like_f0, sp, ap, fs)
sf.write('test1/robot_like.wav', robot_like, fs)
# 4.提高基频,同时频谱包络后移?更温柔的女性?
female_like_sp = np.zeros_like(sp)
for f in range(female_like_sp.shape[1]):
female_like_sp[:, f] = sp[:, int(f/1.2)]
female_like = pw.synthesize(f0*2, female_like_sp, ap, fs)
sf.write('test1/female_like.wav', female_like, fs)
# 5.转换基频(不能直接转换)
x2, fs2 = sf.read('utterance/rmdmy.wav')
f02, sp2, ap2 = pw.wav2world(x2, fs2)
f02 = f02[:len(f0)]
print(len(f0),len(f02))
other_like = pw.synthesize(f02, sp, ap, fs)
sf.write('test1/other_like.wav', other_like, fs)
语音合成/语音转换和机器学习
但是,由于有无数种转换每个特征的方法,因此手动调整非常困难。这就是机器学习的用武之地。如果原始数据和转换后的数据有足够的样本,则机器学习会自动调整参数。过去,使用HMM,高斯混合模型和NMF的方法似乎是主流,但是正如开头提到的那样,最近已经积极研究了使用深度学习的方法。
最后,我将介绍一些最新技术。
(这并不详尽,这是我个人关心的一种方法,因此我不会这样做)
最新技术
- 这是将VAE(一种深度学习方法)应用于语音质量转换的示例。输入频谱和扬声器信息。关于本文的有趣之处在于它使用了“非并行语料库”。在常规方法中,使用相同的语言作为用于学习的数据作为源并且在转换之后,但是该方法不需要这种措施。
- Google在2016年发布的模型,该模型使用原始波形数据代替特征值作为输入数据,并通过使用自回归模型实现极其流畅的语音合成。尽管复杂,但这绝对是一项突破。
- 显着特征是使用称为VQ-VAE(一种VAE)的方法来离散潜在空间。通过在解码器部分使用与WaveNet具有相同结构的网络,也可以将其用于语音质量转换。只要您听作者页面上的演示,它就会转换为一种非常不错的感觉。
- 它与使用最近流行的GAN进行语音转换和语音合成有关。
结论
我总结了过去两年中一直关注的语音转换和语音合成的基本方面。pyworld易于安装,易于使用且有趣,因此请尝试一下。