Python写的,作用为,将袅袅音源的inf.d和voice.d两个文件拆解成UTAU音源,并且还原打包之前的wav文件和inf文件,可以用袅袅音源制作器分析。
拆解出来的的文件夹可以拖到UTAU目录作为音源使用,已经自带oto。需用UTAU的自动生成frq功能生成frq。
工具及使用说明 http://files.cnblogs.com/files/bdbmb/nn2utau.zip
为了方便不想安装Python的同学,用py2exe制作了一个exe版,只能用于64位系统,32位系统和XP请下载上面那个,按照说明装Python再运行~
exe版 http://files.cnblogs.com/files/bdbmb/nn2utau.rar
代码
# coding:utf-8 #袅袅音源拆解&袅袅音源转UTAU音源工具 #已知问题:红色区域覆盖范围固定,不按实际情况变化 #已知问题:绿线始终放在红线和开始之间二分之一处(这其实是袅袅处理采样之间过渡的方式) #已知问题:扩张整音的音尾需要手动设定 import sys import os import base64 import binascii INF_FILE = ‘inf.d‘ #inf打包文件 VOICE_FILE = ‘voice.d‘ #wav打包文件 NN_DIR = ‘nn‘ #解包文件放置的目录,是当前目录的子目录 OTO_TYPE = 0 #oto中右边蓝色区域的计算方式,0为整音,1为扩张整音,2为日语单独音 RED_AREA = 55 #红色区域离红线的距离,毫秒 EX_FWD = 20 #转成扩张整音时蓝色区域比尾帧向前移动的距离,毫秒 #将inf.d内容解码,按行返回。每行内容分割成一个列表。 def rparams(): f = open(INF_FILE,‘r‘) params = f.readlines() del params[0:2] #删掉那个v1和发音总数标记 ctn = [] for line in params: line = base64.decodestring(line) line = line.split() ctn.append(line) f.close() return ctn #接受每一行转换成的列表,写入对应的inf文件 def infwriter(param): filename = param[0] + ‘.inf‘ f = open(‘nn\\‘ + filename,‘wb‘) f.write(‘0 ‘) #起始帧,因为音源制作器已经把空白切掉,所以都是0 f.write(str(int(param[2])/2) + ‘ ‘) #采样数 for i in range(3,7): f.write(param[i] + ‘ ‘) f.write(param[7]) #以上写入不需做处理的几个值和空格 f.close() #将字节数表示的长度转换成能写入wav文件头的表示方法。参见网上介绍wav文件头结构的文章。 def hexlength(length): a = hex(length)[2:].upper() #去掉0x a = ‘0‘ * (8-len(a)) + a #剩余位补0 b = [] for pn in [6,4,2,0]: #以两位为单位倒写 b.append(a[pn:pn+2]) return(binascii.a2b_hex(‘‘.join(b))) #字符串按含义转化为十六进制值 #按给定的属性列表写wav文件 def wavewriter(param): filename = param[0] + ‘.wav‘ f = open(‘nn\\‘ + filename,‘wb‘) #写入文件头,由于袅袅要求16位单声道44100Hz的wave文件,所以文件头几乎是固定的,除了长度的标识 #感谢网上介绍wav文件结构的文章~ f.write(‘RIFF‘) f.write(hexlength(int(param[2])+44)) f.write(‘WAVEfmt \x10\x00\x00\x00\x01\x00\x01\x00\x44\xac\x00\x00\x88\x58\x01\x00\x02\x00\x10\x00data‘) f.write(hexlength(int(param[2]))) #按照给定的偏移量写入数据 s = open(VOICE_FILE,‘rb‘) s.seek(int(param[1])) temp = s.read(int(param[2])) f.write(temp) f.close() s.close() #输入属性列表,返回oto文件的一行 def rotoline(param): def cvt(byte): #将字节表示的长度转换成毫秒 return int(byte)*500/44100 ctn = [‘‘,‘0‘] #没有辅助记号,左边蓝色区域为0 lt = cvt(param[2]) s = 2 * cvt(param[3]) #辅音开始 ctn.append(str(s+RED_AREA)) #红色区域 #按照生成模式不同,计算右边的蓝色区域 #本人在做中文整音oto设定时经常把蓝色区域覆盖音尾的一半,这样不至于切掉音尾也不会造成较长的低音量时间 if OTO_TYPE == 0: ctn.append(str(lt - cvt((int(param[2])+2*int(param[4]))/2))) #扩张整音将音尾完全切掉,并且用额外的音尾设定做X-Fade。额外的音尾设定需手动做,大约十几个 elif OTO_TYPE == 1: ctn.append(str(lt - cvt(2*int(param[4])) + EX_FWD)) #日语单独音,蓝色放在三分之一处一个点,个人经验 elif OTO_TYPE == 2: ctn.append(str(lt - cvt((int(param[2])+4*int(param[4]))/3))) ctn.append(str(s)) #辅音开始 ctn.append(str(s/2)) #绿线,偷懒按袅袅的方式处理了,请手动调整 return param[0] + ‘.wav=‘ + ‘,‘.join(ctn) + ‘\n‘ #主函数 def main(): print u‘袅袅音源库拆解&袅袅音源转UTAU音源工具‘ print u‘请输入oto生成方式,0为中文整音,1为扩张整音(请手动补充几个音尾设定),2为日语单独音,直接回车默认中文整音‘ global OTO_TYPE OTO_TYPE = raw_input() if OTO_TYPE not in [‘0‘,‘1‘,‘2‘]: OTO_TYPE = 0 OTO_TYPE = int(OTO_TYPE) print u‘正在处理,请稍等~‘ os.mkdir(NN_DIR) params = rparams() ctn = [] for param in params: infwriter(param) wavewriter(param) ctn.append(rotoline(param)) oto = open(‘nn\\‘ + ‘oto.ini‘,‘w‘) oto.writelines(ctn) oto.close() print u‘成功!按回车键退出‘ print u‘现在您可以将nn目录直接做UTAU音源使用,或者用袅袅音源制作工具打开了‘ print u‘不要忘了双击UTAU音源库设定对话框左下角两个按钮之间的空白区域,生成frq文件‘ raw_input() if __name__ == ‘__main__‘: main()
时间: 2024-10-13 03:07:49