训练完毕了
需要注意一下,上采样的倍数是由hop_size来决定的,为什么呢?
需要明白一点,mel帧数 * 帧移 = 音频长度(采样点个数,可换算为音频时长,具体怎么做不用说了吧)
因此,对于22050采样率, hopsize大小设置为256, 那么对应的mel-spectrogram需要上采样 256倍
如果是16000采样率呢? 使用帧长是50ms,帧移 12.5ms 那么hopsize就是200啦,所以上采样倍数就是200倍啦.
现在v1是256上采样倍数,v2是200上采样倍数
放大图像(或称为上采样(upsampling)或图像插值(interpolating))的主要目的是放大原图像,从而可以显示在更高分辨率的显示设备上。
那么上采样倍数大概就是放大多少倍。一般都用插值法。原本44KHZ的,如何进行上采样后再下采样到8KHZ呢?
| 我对上下采样是这样理解的。上采样就是在奇数点插入零值。频率变高一倍。下采样就是抽取偶数点的值,奇数点的值不要。频率降低一倍。 如果我的理解没有问题的话,那么44KHz的下采样可以到11KHz,至于达到8KHz |
当采样频率fs.max大于信号中最高频率fmax的2倍时(fs.max>2fmax),采样之后的数字信号完整地保留了原始信号中的信息,一般实际应用中保证采样频率为信号最高频率的2.56~4倍。
当采样频率是原采样频率时,听到的声音是未失真的声音;当降低采样频率时,听到的声音显得比原语音信号要闷(低沉);当增加采样频率时,声音会变得更加尖锐。
用两张卡不会提升,用一张卡反而会加重。。。
MelGAN模型使用基于Mel Spectrogram的特征作为输入,逐步上采样到语音长度,在上采样之间加入卷积块计算频域到时域的变换。最后输出即为固定帧数的语音。
生成器(Generator)包括四个上采样层,四个残差卷积块,以及开头和结尾的两个过渡层。
判别器(Discriminator)采用多分辨率构造,结构包括四个下采样层和三个过渡层。
在MelGAN中,生成器需要通过四层上采样,将维度为一的输入上采样到帧移(hop length)长度的点数,论文中取256。也就是需要扩大256倍。可想而知,上采样的负担是巨大的。
因此,上采样层虽然参数量大,但实际在模型中起到的是辅助作用,主要频域到时域的转换是依赖于残差块实现的。
在每层上采样层之后经过残差网络块训练频域到时域的变换,最后得到对应帧的语音。这里四层上采样层的上采样倍率依次为 [8,8,2,2] (8*8*2*2 = 256 )
输入为mel-spectrogram,输出为raw waveform. 从 mel-spectrogram到 audio的过程很显然是一个上采样的过程。也就是采样点增多的过程。一般通过插值解决。
这里的上采样是由一维反卷积(transpose1d)实现的,上采样的倍数如何确定呢?
需要明白一点,mel帧数 * 帧移 = 音频长度。
音频采样率是指录音设备在一秒钟内对声音信号的采样次数,采样频率越高声音的还原就越真实越自然。在当今的主流采集卡上,采样频率一般共分为11025Hz、22050Hz、24000Hz、44100Hz、48000Hz五个等级
采样点个数,可换算为音频时长,所谓采样点,就是帧数个数。
那么这么说,说不定上采样层只是一个分配而已。
对于音频信号而言,必须进行编码。在这里,编码指信源编码,即数据压缩。如果,未经过数据压缩,直接量化进行传输则被称为PCM(脉冲编码调制)。要算一个PCM音频流的码率是一件很轻松的事情,采样率值×采样大小值×声道数 bps。一个采样率为44.1KHz,采样大小为16bit,双声道的PCM编码的WAV文件,它的数据速率则为 44.1K×16×2 =1411.2 Kbps。所以一般不追求码率。
生成器的输入是声音的频谱图,输出是频谱图对应的音频,在实际处理音频时,文章采用的 hop_length(帧移对应卷积中的 stride 也可以理解为连续帧分割长度)为 256,所以 Mel 频谱图的时间分辨率比原始音频低 256 倍,所以在生成器的设计上要做到总共 256× 的上采样。
那么本mel图与原始音频的倍数是多少呢?
啊这就不对了,音频长度就不对了。
但不得不说练出来的东西不错啊。。。但长度不怎么对啊。。。
# add upsampling layer
layers += [
getattr(tf.keras.layers, config.nonlinear_activation)(
**config.nonlinear_activation_params
),
TFConvTranspose1d(
filters=config.filters // (2 ** (i + 1)),
kernel_size=upsample_scale * 2,
strides=upsample_scale,
padding="same",
is_weight_norm=config.is_weight_norm,
initializer_seed=config.initializer_seed,
name="conv_transpose_._{}".format(i),
),
]
sf.write(write_wav_path, data, sample_rate, 'PCM_16')
sf.write(
os.path.join(args.outdir, f"{utt_id}.wav"),
audio[: mel_lengths[i].numpy() * config["hop_size"]],
config["sampling_rate"],
"PCM_16",
)
这是数据,这倒不假。
声音文件将音频数据表示为 NumPy 阵列。
data, samplerate = sf.read('existing_file.wav')
sf.write('new_file.flac', data, samplerate)
audio[: mel_lengths[i].numpy() * config["hop_size"]]
它为什么会截断?就是这里啊,如果不动这里,这里就是一个5s的长度。
mel_length,实际上就是mel的长度直接乘以200,就是说扩大了200倍。没问题啊,看看train吧
看不懂,它这里有重要的作用。你需要深入了解。
接下来用gnu screen吧!
# 新建一个screen并指定名称
screen -S XXX
这时候就会进入到这个会话,执行命令后,退出
在screen窗口键入Ctrl + A, D,Screen会给出detached提示
然后查看会话:
# 半个小时之后回来了,找到该screen会话:
screen -ls
There is a screen on:
16582.pts-1.tivf06 (Detached)
1 Socket in /tmp/screens/S-root.
# 重新连接会话
screen -r 16582
这时候会显示出原来screen会话中的信息.
如果原screen还是Attached的状态, 需要用 -x 参数
# 重新连接一个还在Attached状态的screen session
screen -x 16582
删除本会话:
ctrl+a,然后松开,按k即可杀掉当前窗口。
hop size是个傅立叶变换有关系的,一般固定不会变动的
MelGAN的速度明显快于其他mel谱图反演的替代方法。特别是,它比迄今为止最快的可用模型(Prenger等,2019)快10倍,而音频质量没有明显下降。
生成器,生成网络
帧移知道是啥,采样率知道是啥,帧移采样率是啥?
采样率
就是分帧,由连续变成间断,由连续变成一个个的,音频采样率是指录音设备在一秒钟内对声音信号的采样次数,采样频率越高声音的还原就越真实越自然。在当今的主流采集卡上,采样频率一般共分为11025Hz、22050Hz、24000Hz、44100Hz、48000Hz五个等级,一个帧内是等高的,好在帧长很短。一次振动中,必须有2个点的采样,人耳能够感觉到的最高频率为20kHz(频率再高人就感觉不到了),因此要满足人耳的听觉要求,则需要至少每秒进行40k次采样,用40kHz表达,这个40kHz就是采样率。我们常见的CD,采样率为44.1kHz。
帧移
由于我们常用的信号处理方法都要求信号是连续的,也就说必须是信号开始到结束,中间不能有断开。然而我们进行采样或者分帧后数据都断开了,所以要在帧与帧之间保留重叠部分数据,以满足连续的要求,这部分重叠数据就是帧移。

你以为这是连续的,其实这是简短的,由采样点组成的,明白?
那这噪音哪里来的啊???
音频信号必然由几个单频声波组成。 傅立叶变换可以将信号分解为单个频率和频率幅度。 换句话说,它将信号从时域转换到频域。 结果称为频谱。也就是说,完全用各种波的表达式来代替这一段时间的波形表示。
快速傅里叶变换不是短时傅里叶变换,这里我们加窗口变成短时傅里叶变换,好处是
我们处理信号的方法都要求信号是连续条件,但是分帧处理的时候中间断开了(不仅变成了阶跃式的,在每一帧之间变成阶跃式的),为了满足条件我们就将分好的帧数据乘一段同长度的数据,这段数据就是窗函数整个周期内的数据,从最小变化到最大,然后最小。

如果只是采样率的话,波的表示是不用分帧的啊,实际上采样率就是分帧,帧之间怎么重叠?啊,帧之间的重叠是这样的(帧之间重叠吗?),加窗必然是需要重叠的,
您可以将频谱图视为一堆相互堆叠的FFT。 当信号在不同频率下随时间变化时,这是一种直观地表示信号响度或幅度的方法。 计算频谱图时,
还有一些其他细节。 y轴转换为对数刻度(是什么频率的波),颜色尺寸转换为分贝(您可以将其视为振幅的对数刻度)。 这是因为人类只能感知到非常小的集中频率和幅度范围。
x轴就是时间。
关于melgan的训练以及与fs2的对照解码,有什么参数对应呢?
不同频率波的分布随时间的变化,这就是短时傅里叶的作用。STFT的原理非常简单,把一段长信号分帧、加窗,再对每一帧做傅里叶变换(FFT),最后把每一帧的结果(各种基频波)沿另一个维度(y轴)堆叠起来,得到类似于一幅图的二维信号形式。
傅里叶变换要求输入信号是平稳的(意味着它能用很少的基频表示),而语音在宏观上来看是不平稳的(能分解出很多很多的基频,太多就没使用价值了)——你的嘴巴一动,信号的特征就变了。但是从微观上来看,在比较短的时间内,嘴巴动得是没有那么快的,语音信号就可以看成平稳的,就可以截取出来做傅里叶变换了。这就是为什么语音信号要分帧处理,截取出来的一小段信号就叫一「帧」。这不是加窗吗。。。
那么一帧有多长呢?帧长要满足两个条件:
- 从宏观上看,它必须足够短来保证帧内信号是平稳的。前面说过,口型的变化是导致信号不平稳的原因,所以在一帧的期间内口型不能有明显变化,即一帧的长度应当小于一个音素的长度。正常语速下,音素的持续时间大约是 50~200 毫秒,所以帧长一般取为小于 50 毫秒。
- 从微观上来看,它又必须包括足够多的振动周期,因为傅里叶变换是要分析频率的,只有重复足够多次才能分析频率。语音的基频,男声在 100 赫兹左右,女声在 200 赫兹左右,换算成周期就是 10 毫秒和 5 毫秒。既然一帧要包含多个周期,所以一般取至少 20 毫秒。
而采样率,基本上是微秒级别的,这样,我们就知道了帧长一般取为 20 ~ 50 毫秒,20、25、30、40、50 都是比较常用的数值,帧之间是不重叠的。
取出来的一帧信号,在做傅里叶变换之前,要先进行「加窗」的操作,即与一个「窗函数」相乘,如下图所示:

或者说,帧或加窗实际上是一个量级,只不过前后关系而已,加窗的目的是让一帧信号的幅度在两端渐变到 0。渐变对傅里叶变换有好处,加窗的代价是一帧信号两端的部分被削弱了,没有像中央的部分那样得到重视。弥补的办法是,帧不要背靠背地截取,而是相互重叠一部分。相邻两帧的起始位置的时间差叫做帧移,常见的取法是取为帧长的一半,或者固定取为 10 毫秒。我终于明白了。。。
复合振动或波形(如信号)的谐波成分,它具有最低频率,且通常具有最大振幅——亦称“基谐波”;
在每秒钟发生的周期数量会决定该波形的基础音高(basic pitch),通常被我们称为“频率”(frequency)。
一个声音的频率被称作它的基音或基频(fundamental tone),而除了简单正弦波之外,大部分的声音都包含基频与其他不同的频率。这些Non Fundamental tones如果是基频的整数倍,则被称为泛音(overtones)或谐波(harmonics);如果是非正整数倍,例如2.5倍,则被称为分音(partials);而若为基频的几分之几,则称为subharmonic。
明白了,那么hop_size=256,,,是一个帧的偏移量,乘以它还真的是时长。。。如果整体扩大,只是说话比较慢而不是会在后面补足。
既然ljspeech都很流畅不卡顿(在concat_256的demo wave中,很流畅的),那么一顿一顿的我认为是aishell的melgan的问题。多训练训练就好了。
我感觉这个speaker_id它摆明了就是为了过拟合设计的参数啊,它应该只是为了闭集训练。
我们知道,我们处理的语音其实是一种声波,声波是一种物质波。滤波的字面意思理解为过滤一些不同频率的波。根据傅里叶变换,我们知道任意波可以分解为几种正弦波和余弦波的叠加,从概率论的角度,滤波即加权。 滤波的作用就是给不同的信号分量不同的权重。最简单的loss pass filter, 就是直接把低频的信号给0权重,而给高频部分1权重。对于更复杂的滤波,比如维纳滤波, 则要根据信号的统计知识来设计权重。为什么要滤波,还不是为了要减少基波的条数。
降噪
从统计信号处理的角度,降噪可以看成滤波的一种。降噪的目的在于突出信号本身而抑制噪声影响。从这个角度,降噪就是给信号一个高的权重而给噪声一个低的权重。维纳滤波就是一个典型的降噪滤波器。
合成
一般的语音处理过程,先分帧,再在频域分成各个子带处理,处理后转成时域,合成语声。从描述上看,语音合成就是和分帧相反的过程,保证信号数据经过我们变换处理后能够回到原来的状态。把每帧各个子带转换成时间序列后相互叠加合成为一帧数据。
那么关卷积放大什么事?
很明显,又升又降后没有改变大小,没有降采样。。。升了256倍之后就是wav了。那么最后为什么还要乘以256?
生成网络
结构:我们的生成器是一个完全卷积的前馈网络,输入的频谱图为s,原始波形x为输出。由于梅尔频谱图(用于所有实验)的帧移采样率为256,因此我们使用一堆转置的卷积层对输入序列进行上采样。每个转置的卷积层后面是一堆带有膨胀卷积的残差块。这个256究竟是什么?
audio[: mel_lengths[i].numpy() * 256],说实话,这里明显代表声音长度了,从0到最后,我估计整体是一个定值。果然是8秒,它最多合成8秒语音。audio就是原音频,mel_lengths其实也很好理解了,反正最后是音频时长,这个东西是几万的,但与时长成正比,你需要知道这个audio的单位是什么?这个mel_length应该是整个mel谱的长度,乘以256就是wav的长度,就是如此。
hop_size是什么?帧移,关键是,这里采样率不是帧啊。。。
现在训练的aishell比原来的ljspeech真的好一点了,更流畅,清晰度更高。

8683

被折叠的 条评论
为什么被折叠?



