耳听也不为实了,基于谷歌SV2TTS算法的开源项目在GITHUB登顶

     近日谷歌的论文SV2TTS(https://arxiv.org/pdf/1806.04558.pdf)在不论是在学术界还是在开源社区都引发热议,SV2TTS号称可以使用低分辨率的原音信息,在短时间内完成转换,生成新的声音。而且最近依据这个算法已经登陆到了github的趋势榜首位置(https://github.com/CorentinJ/Real-Time-Voice-Cloning)。

   

    SV2TTS论文摘要

    我们把原语音定义为v1,原语音内容定义为c1,原语音的speaker定义为s1,目标语音定义为v2,目标内容定义为c2。以便下文解释。

    SV2TTS定义了三层模型: 

    模型1:针对s1的声音特征的encoder网络,利用数千个人声样本,只从对于S1语音语调的嵌入工作,生成嵌入向量。至于什么是嵌入之前介绍很多了,具体可参考(https://blog.csdn.net/BEYONDMA/article/details/90114016)这里不加赘述了。

    模型2:基于Tacotron 2的合成网络,我们知道Tacotron 2是基于注意力的模型,依据c2与s1的相关特征,生成梅尔(mel)谱图;

    模型3:基于自回归波的语音生成网络,将mel谱图数据转换为时域的声音样本

     下图是模型图:

耳听也不为实了,基于谷歌SV2TTS算法的开源项目在GITHUB登顶_第1张图片

    其具体的工作原理如下:

  1.利用模型1将s1和phoneme sequence(单词发音序列,如我、你等单个字的发音)的合成器进行结合。

  2.利用模型2对于模型1的输出结果进行解码。生成梅尔频谱数据。

  3.利用模型3将梅尔频谱转化为波型文件。

    SV2TTS代码导读

SV2TTS其实刚刚发布不久,github就已经有程序员大神贴出了实现网址在:https://github.com/CorentinJ/Real-Time-Voice-Cloning,而我初步读了一下,代码质量颇高,值得大家一读。

这里要详细讲一下的是这个文件,属于编码器部分(与模型1对应)的audio部分:https://github.com/CorentinJ/Real-Time-Voice-Cloning/blob/master/encoder/audio.py

import webrtcvad
import librosa

其中用到了两个重要的库webrtcvad和librosa,其中webrtcvad是语音检测的重要库之一,具体在这个项目中是在这里用到的代码及注释如下,他用到的检测模式是3也就是最激进的模式 webrtcvad.Vad(mode=3),然后使用vad.is_speech检测是否为人声。

def trim_long_silences(wav):
    """
    Ensures that segments without voice in the waveform remain no longer than a 
    threshold determined by the VAD parameters in params.py.

    :param wav: the raw waveform as a numpy array of floats 
    :return: the same waveform with silences trimmed away (length <= original wav length)
    """
    # Compute the voice detection window size
    samples_per_window = (vad_window_length * sampling_rate) // 1000
    
    # Trim the end of the audio to have a multiple of the window size
    wav = wav[:len(wav) - (len(wav) % samples_per_window)]
    
    # Convert the float waveform to 16-bit mono PCM
    pcm_wave = struct.pack("%dh" % len(wav), *(np.round(wav * int16_max)).astype(np.int16))
    
    # Perform voice activation detection
    voice_flags = []
    vad = webrtcvad.Vad(mode=3)#将检测模式设为3,也就是最激进的模式
    for window_start in range(0, len(wav), samples_per_window):
        window_end = window_start + samples_per_window
        voice_flags.append(vad.is_speech(pcm_wave[window_start * 2:window_end * 2],
                                         sample_rate=sampling_rate))#检测是否为人声
    voice_flags = np.array(voice_flags)
    
    # Smooth the voice detection with a moving average
    def moving_average(array, width):
        array_padded = np.concatenate((np.zeros((width - 1) // 2), array, np.zeros(width // 2)))
        ret = np.cumsum(array_padded, dtype=float)
        ret[width:] = ret[width:] - ret[:-width]
        return ret[width - 1:] / width
    
    audio_mask = moving_average(voice_flags, vad_moving_average_width)
    audio_mask = np.round(audio_mask).astype(np.bool)
    
    # Dilate the voiced regions
    audio_mask = binary_dilation(audio_mask, np.ones(vad_max_silence_length + 1))
    audio_mask = np.repeat(audio_mask, samples_per_window)
    
    return wav[audio_mask == True]

然后是librosa库,这个是语音识别中最重要的库没有之一。下面重点介绍一下这个库,他的安装十分简单:

pip install librosa

安装完成后,就可以直接import使用了,计算梅尔频谱的代码如下:

import librosa
import librosa.display
import matplotlib.pyplot as plt
y, sr = librosa.load('e:/tts/Explanation.wav', sr=None)
melspec = librosa.feature.melspectrogram(y, sr, n_fft=1024, hop_length=512, n_mels=128)#计算梅尔频谱
logmelspec = librosa.power_to_db(melspec)#计算log-mel
plt.figure()
librosa.display.specshow(logmelspec, sr=sr, x_axis='time', y_axis='mel')
plt.title('Beat wavform')
plt.show()

运行效果如下:

耳听也不为实了,基于谷歌SV2TTS算法的开源项目在GITHUB登顶_第2张图片

我们知道梅尔(mel)频谱本质是模板人耳的滤波器所以在TTS当中使用非常广泛。

在这个项目中也是同样,直接调用了librosa.feature.melspectrogram方法来计算梅尔频谱:

def wav_to_mel_spectrogram(wav):
    """
    Derives a mel spectrogram ready to be used by the encoder from a preprocessed audio waveform.
    Note: this not a log-mel spectrogram.
    """
    frames = librosa.feature.melspectrogram(
        wav,
        sampling_rate,
        n_fft=int(sampling_rate * mel_window_length / 1000),
        hop_length=int(sampling_rate * mel_window_step / 1000),
        n_mels=mel_n_channels
    )
    return frames.astype(np.float32).T

当然其它部分比如https://github.com/CorentinJ/Real-Time-Voice-Cloning/blob/master/synthesizer/models/tacotron.py也有tacotron模型的完整实现,非常推荐大家读一下

你可能感兴趣的:(python)