【项目实战】AUTOVC 代码解析 —— conversion.py

AUTOVC 代码解析 —— conversion.py

  简介

       本项目一个基于 AUTOVC 模型的语音转换项目,它是使用 PyTorch 实现的(项目地址)。
       
        AUTOVC 遵循自动编码器框架,只对自动编码器损耗进行训练,但它引入了精心调整的降维和时间下采样来约束信息流,这个简单的方案带来了显著的性能提高。(详情请参阅 AUTOVC 的详细介绍)。
       
       由于 AUTOVC 项目较大,代码较多。为了方便学习与整理,将按照工程文件的结构依次介绍。
       
       本文将介绍项目中的 conversion.py 文件:语音音色转换处理脚本
       

  函数解析

    pad_seq

          该函数的作用是: 计算数据 x 以 base 个元素为一份划分,若最后一组不足一份则补齐

          输入参数:

		x		:	待处理数据
		base	:	一份中的元素数量

          输出参数:

		np.pad(x, ((0,len_pad),(0,0)), 'constant'), len_pad	:	补齐后的数据,以及补齐用的长度

          代码详解:

		def pad_seq(x, base=32):
		    # ceil 向上取整,计算数据 x 以 base 划分为多少份,若最后一组不足一份则补齐
		    len_out = int(base * ceil(float(x.shape[0])/base))
		    # 计算需要补齐的长度
		    len_pad = len_out - x.shape[0]
		    # 当长度小于 0 时抛出警告
		    assert len_pad >= 0
		    # 返回补齐后的数据,以及补齐用的长度
		    return np.pad(x, ((0,len_pad),(0,0)), 'constant'), len_pad

    main

          该函数的作用是: 选取转换路径,执行语音转换,并将转换结果保存

          输入参数:

          输出参数:

          代码详解:

		# 设置设备为第一个 GPU 设备
		device = 'cuda:0'
		# 创建生成器模型,内容编码长度为 32 ,说话人编码长度为 256 ,后置网络输出长度为 512 
		# 采样系数为 32 ,设置为生成模式,并移入设备 device 
		G = Generator(32, 256, 512, 32).eval().to(device)
		
		# 加载训练好的参数至变量 g_checkpoint
		g_checkpoint = torch.load('autovc.ckpt')
		# 生成器模型加载训练好的数据
		G.load_state_dict(g_checkpoint['model'])
		
		# 打开事先准备包括说话人信息(包括说话人民,说话人编码,说话梅尔数据)的训练数据
		metadata = pickle.load(open('metadata.pkl', "rb"))
		
		# 创建转换信息与语音梅尔频谱列表
		spect_vc = []
		
		# 遍历说话人信息,取源说话人信息 sbmt_i
		for sbmt_i in metadata:
		
		    # 取说话人说话梅尔数据
		    x_org = sbmt_i[2]
		    # 处理去除的梅尔数据,得到补齐后的说话数据与补齐长度
		    x_org, len_pad = pad_seq(x_org)
		    # 在补齐的说话数据前增加新的维度,将说话数据转为 Tensor ,接着移入设备 device ,得到源说话人说话数据 uttr_org 
		    uttr_org = torch.from_numpy(x_org[np.newaxis, :, :]).to(device)
		    # sbmt_i[1] 取出说话人编码,并在数据前增加新的维度
		    # 将说话数据转为 Tensor ,接着移入设备 device ,得到源说话人说话人编码 emb_org
		    emb_org = torch.from_numpy(sbmt_i[1][np.newaxis, :]).to(device)
		
		    # 遍历说话人信息,取目标说话人信息 sbmt_j
		    for sbmt_j in metadata:
		
		        # sbmt_j[1] 取出说话人编码,并在数据前增加新的维度
		    	# 将说话数据转为 Tensor ,接着移入设备 device ,得到目标说话人说话人编码 emb_trg
		        emb_trg = torch.from_numpy(sbmt_j[1][np.newaxis, :]).to(device)
		
		        # torch.no_grad 是一个上下文管理器,被该语句 wrap 起来的部分将不会 track 梯度。
		        with torch.no_grad():
		            # 输入源说话人说话数据 uttr_org ,源说话人说话人编码 emb_org 与目标说话人说话人编码 emb_trg ,得到最终转换结果 x_identic_psnt
		            _, x_identic_psnt, _ = G(uttr_org, emb_org, emb_trg)
		
		        # 若补齐所用的长度 len_pad 为 0
		        if len_pad == 0:
		            # 取最终转换结果的全部数据,移入 cpu 中,转为 numpy 数据,得到目标语音数据 uttr_trg
		            uttr_trg = x_identic_psnt[0, 0, :, :].cpu().numpy()
		        # 若补齐所用的长度 len_pad 不为 0
		        else:
		            # 取最终转换结果的部分数据(将补齐的部分剪切),移入 cpu 中,转为 numpy 数据,得到目标语音数据 uttr_trg
		            uttr_trg = x_identic_psnt[0, 0, :-len_pad, :].cpu().numpy()
		
		        # 将转换路径 sbmt_i[0], sbmt_j[0] 与转换后的语音数据 uttr_trg 合并,接着添加至转换信息与语音梅尔频谱列表 spect_vc
		        spect_vc.append(('{}x{}'.format(sbmt_i[0], sbmt_j[0]), uttr_trg))
		
		# 打开最终结果文件 results.pkl 准备写入
		with open('results.pkl', 'wb') as handle:
		    # 将转换信息与语音梅尔频谱列表 spect_vc 写入文件
		    pickle.dump(spect_vc, handle)
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值