C0MPL3X commited on
Commit
d1872f1
·
verified ·
1 Parent(s): c1b89c8

Upload 14 files

Browse files
.gitattributes CHANGED
@@ -25,7 +25,6 @@
25
  *.safetensors filter=lfs diff=lfs merge=lfs -text
26
  saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
  *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
  *.tflite filter=lfs diff=lfs merge=lfs -text
30
  *.tgz filter=lfs diff=lfs merge=lfs -text
31
  *.wasm filter=lfs diff=lfs merge=lfs -text
@@ -33,3 +32,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
25
  *.safetensors filter=lfs diff=lfs merge=lfs -text
26
  saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
  *.tar.* filter=lfs diff=lfs merge=lfs -text
 
28
  *.tflite filter=lfs diff=lfs merge=lfs -text
29
  *.tgz filter=lfs diff=lfs merge=lfs -text
30
  *.wasm filter=lfs diff=lfs merge=lfs -text
 
32
  *.zip filter=lfs diff=lfs merge=lfs -text
33
  *.zst filter=lfs diff=lfs merge=lfs -text
34
  *tfevents* filter=lfs diff=lfs merge=lfs -text
35
+ ffmpeg.exe filter=lfs diff=lfs merge=lfs -text
36
+ ffprobe.exe filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -1,3 +1,3 @@
1
  ---
2
- license: unknown
3
  ---
 
1
  ---
2
+ license: mit
3
  ---
config.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############离线VC参数
2
+ inp_root=r"白鹭霜华长条"#对输入目录下所有音频进行转换,别放非音频文件
3
+ opt_root=r"opt"#输出目录
4
+ f0_up_key=0#升降调,整数,男转女12,女转男-12
5
+ person=r"weights\洛天依v3.pt"#目前只有洛天依v3
6
+ ############硬件参数
7
+ device = "cuda:0"#填写cuda:x或cpu,x指代第几张卡,只支持N卡加速
8
+ is_half=True#9-10-20-30-40系显卡无脑True,不影响质量,>=20显卡开启有加速
9
+ n_cpu=0#默认0用上所有线程,写数字限制CPU资源使用
10
+ ############下头别动
11
+ import torch
12
+ if(torch.cuda.is_available()==False):
13
+ print("没有发现支持的N卡,使用CPU进行推理")
14
+ device="cpu"
15
+ is_half=False
16
+ if(device!="cpu"):
17
+ gpu_name=torch.cuda.get_device_name(int(device.split(":")[-1]))
18
+ if("16"in gpu_name):
19
+ print("16系显卡强制单精度")
20
+ is_half=False
21
+ from multiprocessing import cpu_count
22
+ if(n_cpu==0):n_cpu=cpu_count()
23
+ if(is_half==True):
24
+ #6G显存配置
25
+ x_pad = 3
26
+ x_query = 10
27
+ x_center = 60
28
+ x_max = 65
29
+ else:
30
+ #5G显存配置
31
+ x_pad = 1
32
+ # x_query = 6
33
+ # x_center = 30
34
+ # x_max = 32
35
+ #6G显存配置
36
+ x_query = 6
37
+ x_center = 38
38
+ x_max = 41
go-web.bat ADDED
@@ -0,0 +1 @@
 
 
1
+ runtime\python.exe infer-web.py
go.bat ADDED
@@ -0,0 +1 @@
 
 
1
+ runtime\python.exe infer.py
infer-web.py ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch, pdb, os,traceback,sys,warnings,shutil
2
+ now_dir=os.getcwd()
3
+ sys.path.append(now_dir)
4
+ tmp=os.path.join(now_dir,"TEMP")
5
+ shutil.rmtree(tmp,ignore_errors=True)
6
+ os.makedirs(tmp,exist_ok=True)
7
+ os.environ["TEMP"]=tmp
8
+ warnings.filterwarnings("ignore")
9
+ torch.manual_seed(114514)
10
+ from infer_pack.models import SynthesizerTrnMs256NSF as SynthesizerTrn256
11
+ from scipy.io import wavfile
12
+ from fairseq import checkpoint_utils
13
+ import gradio as gr
14
+ import librosa
15
+ import logging
16
+ from vc_infer_pipeline import VC
17
+ import soundfile as sf
18
+ from config import is_half,device,is_half
19
+ from infer_uvr5 import _audio_pre_
20
+ logging.getLogger('numba').setLevel(logging.WARNING)
21
+
22
+ models, saved_cfg, task = checkpoint_utils.load_model_ensemble_and_task(["hubert_base.pt"],suffix="",)
23
+ hubert_model = models[0]
24
+ hubert_model = hubert_model.to(device)
25
+ if(is_half):hubert_model = hubert_model.half()
26
+ else:hubert_model = hubert_model.float()
27
+ hubert_model.eval()
28
+
29
+
30
+ weight_root="weights"
31
+ weight_uvr5_root="uvr5_weights"
32
+ names=[]
33
+ for name in os.listdir(weight_root):names.append(name.replace(".pt",""))
34
+ uvr5_names=[]
35
+ for name in os.listdir(weight_uvr5_root):uvr5_names.append(name.replace(".pth",""))
36
+
37
+ def get_vc(sid):
38
+ person = "%s/%s.pt" % (weight_root, sid)
39
+ cpt = torch.load(person, map_location="cpu")
40
+ dv = cpt["dv"]
41
+ tgt_sr = cpt["config"][-1]
42
+ net_g = SynthesizerTrn256(*cpt["config"], is_half=is_half)
43
+ net_g.load_state_dict(cpt["weight"], strict=True)
44
+ net_g.eval().to(device)
45
+ if (is_half):net_g = net_g.half()
46
+ else:net_g = net_g.float()
47
+ vc = VC(tgt_sr, device, is_half)
48
+ return dv,tgt_sr,net_g,vc
49
+
50
+ def vc_single(sid,input_audio,f0_up_key,f0_file):
51
+ if input_audio is None:return "You need to upload an audio", None
52
+ f0_up_key = int(f0_up_key)
53
+ try:
54
+ if(type(input_audio)==str):
55
+ print("processing %s" % input_audio)
56
+ audio, sampling_rate = sf.read(input_audio)
57
+ else:
58
+ sampling_rate, audio = input_audio
59
+ audio = audio.astype("float32") / 32768
60
+ if(type(sid)==str):dv, tgt_sr, net_g, vc=get_vc(sid)
61
+ else:dv,tgt_sr,net_g,vc=sid
62
+ if len(audio.shape) > 1:
63
+ audio = librosa.to_mono(audio.transpose(1, 0))
64
+ if sampling_rate != 16000:
65
+ audio = librosa.resample(audio, orig_sr=sampling_rate, target_sr=16000)
66
+ times = [0, 0, 0]
67
+ audio_opt=vc.pipeline(hubert_model,net_g,dv,audio,times,f0_up_key,f0_file=f0_file)
68
+ print(times)
69
+ return "Success", (tgt_sr, audio_opt)
70
+ except:
71
+ info=traceback.format_exc()
72
+ print(info)
73
+ return info,(None,None)
74
+ finally:
75
+ print("clean_empty_cache")
76
+ del net_g,dv,vc
77
+ torch.cuda.empty_cache()
78
+
79
+ def vc_multi(sid,dir_path,opt_root,paths,f0_up_key):
80
+ try:
81
+ dir_path=dir_path.strip(" ")#防止小白拷路径头尾带了空格
82
+ opt_root=opt_root.strip(" ")
83
+ os.makedirs(opt_root, exist_ok=True)
84
+ dv, tgt_sr, net_g, vc = get_vc(sid)
85
+ try:
86
+ if(dir_path!=""):paths=[os.path.join(dir_path,name)for name in os.listdir(dir_path)]
87
+ else:paths=[path.name for path in paths]
88
+ except:
89
+ traceback.print_exc()
90
+ paths = [path.name for path in paths]
91
+ infos=[]
92
+ for path in paths:
93
+ info,opt=vc_single([dv,tgt_sr,net_g,vc],path,f0_up_key,f0_file=None)
94
+ if(info=="Success"):
95
+ try:
96
+ tgt_sr,audio_opt=opt
97
+ wavfile.write("%s/%s" % (opt_root, os.path.basename(path)), tgt_sr, audio_opt)
98
+ except:
99
+ info=traceback.format_exc()
100
+ infos.append("%s->%s"%(os.path.basename(path),info))
101
+ return "\n".join(infos)
102
+ except:
103
+ return traceback.format_exc()
104
+ finally:
105
+ print("clean_empty_cache")
106
+ del net_g,dv,vc
107
+ torch.cuda.empty_cache()
108
+
109
+ def uvr(model_name,inp_root,save_root_vocal,save_root_ins):
110
+ infos = []
111
+ try:
112
+ inp_root = inp_root.strip(" ")# 防止小白拷路径头尾带了空格
113
+ save_root_vocal = save_root_vocal.strip(" ")
114
+ save_root_ins = save_root_ins.strip(" ")
115
+ pre_fun = _audio_pre_(model_path=os.path.join(weight_uvr5_root,model_name+".pth"), device=device, is_half=is_half)
116
+ for name in os.listdir(inp_root):
117
+ inp_path=os.path.join(inp_root,name)
118
+ try:
119
+ pre_fun._path_audio_(inp_path , save_root_ins,save_root_vocal)
120
+ infos.append("%s->Success"%(os.path.basename(inp_path)))
121
+ except:
122
+ infos.append("%s->%s" % (os.path.basename(inp_path),traceback.format_exc()))
123
+ except:
124
+ infos.append(traceback.format_exc())
125
+ finally:
126
+ try:
127
+ del pre_fun.model
128
+ del pre_fun
129
+ except:
130
+ traceback.print_exc()
131
+ print("clean_empty_cache")
132
+ torch.cuda.empty_cache()
133
+ return "\n".join(infos)
134
+
135
+ with gr.Blocks() as app:
136
+ with gr.Tabs():
137
+ with gr.TabItem("推理"):
138
+ with gr.Group():
139
+ gr.Markdown(value="""
140
+ 使用软件者、传播软件导出的声音者自负全责。如不认可该条款,则不能使用/引用软件包内所有代码和文件。<br>
141
+ 目前仅开放白菜音色,后续将扩展为本地训练推理工具,用户可训练自己的音色进行社区共享。<br>
142
+ 男转女推荐+12key,女转男推荐-12key,如果音域爆炸导致音色失真也可以自己调整到合适音域
143
+ """)
144
+ with gr.Row():
145
+ with gr.Column():
146
+ sid0 = gr.Dropdown(label="音色", choices=names)
147
+ vc_transform0 = gr.Number(label="变调(整数,半音数量,升八度12降八度-12)", value=12)
148
+ f0_file = gr.File(label="F0曲线文件,可选,一行一个音高,代替默认F0及升降调")
149
+ input_audio0 = gr.Audio(label="上传音频")
150
+ but0=gr.Button("转换", variant="primary")
151
+ with gr.Column():
152
+ vc_output1 = gr.Textbox(label="输出信息")
153
+ vc_output2 = gr.Audio(label="输出音频")
154
+ but0.click(vc_single, [sid0, input_audio0, vc_transform0,f0_file], [vc_output1, vc_output2])
155
+ with gr.Group():
156
+ gr.Markdown(value="""
157
+ 批量转换,上传多个音频文件,在指定文件夹(默认opt)下输出转换的音频。<br>
158
+ 合格的文件夹路径格式举例:E:\codes\py39\\vits_vc_gpu\白鹭霜华测试样例(去文件管理器地址栏拷就行了)
159
+ """)
160
+ with gr.Row():
161
+ with gr.Column():
162
+ sid1 = gr.Dropdown(label="音色", choices=names)
163
+ vc_transform1 = gr.Number(label="变调(整数,半音数量,升八度12降八度-12)", value=12)
164
+ opt_input = gr.Textbox(label="指定输出文件夹",value="opt")
165
+ with gr.Column():
166
+ dir_input = gr.Textbox(label="输入待处理音频文件夹路径")
167
+ inputs = gr.File(file_count="multiple", label="也可批量输入音频文件,二选一,优先读文件夹")
168
+ but1=gr.Button("转换", variant="primary")
169
+ vc_output3 = gr.Textbox(label="输出信息")
170
+ but1.click(vc_multi, [sid1, dir_input,opt_input,inputs, vc_transform1], [vc_output3])
171
+
172
+ with gr.TabItem("数据处理"):
173
+ with gr.Group():
174
+ gr.Markdown(value="""
175
+ 人声伴奏分离批量处理,使用UVR5模型。<br>
176
+ 不带和声用HP2,带和声且提取的人声不需要和声用HP5<br>
177
+ 合格的文件夹路径格式举例:E:\codes\py39\\vits_vc_gpu\白鹭霜华测试样例(去文件管理器地址栏拷就行了)
178
+ """)
179
+ with gr.Row():
180
+ with gr.Column():
181
+ dir_wav_input = gr.Textbox(label="输入待处理音频文件夹路径")
182
+ wav_inputs = gr.File(file_count="multiple", label="也可批量输入音频文件,二选一,优先读文件夹")
183
+ with gr.Column():
184
+ model_choose = gr.Dropdown(label="模型", choices=uvr5_names)
185
+ opt_vocal_root = gr.Textbox(label="指定输出人声文件夹",value="opt")
186
+ opt_ins_root = gr.Textbox(label="指定输出乐器文件夹",value="opt")
187
+ but2=gr.Button("转换", variant="primary")
188
+ vc_output4 = gr.Textbox(label="输出信息")
189
+ but2.click(uvr, [model_choose, dir_wav_input,opt_vocal_root,opt_ins_root], [vc_output4])
190
+ with gr.TabItem("训练-待开放"):pass
191
+
192
+ # app.launch(server_name="0.0.0.0",server_port=7860)
193
+ app.launch(server_name="127.0.0.1",server_port=7860)
infer.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch, pdb, os,sys,librosa,warnings,traceback
2
+ warnings.filterwarnings("ignore")
3
+ torch.manual_seed(114514)
4
+ sys.path.append(os.getcwd())
5
+ from config import inp_root,opt_root,f0_up_key,person,is_half,device
6
+ os.makedirs(opt_root,exist_ok=True)
7
+ import soundfile as sf
8
+ from infer_pack.models import SynthesizerTrnMs256NSF as SynthesizerTrn256
9
+ from scipy.io import wavfile
10
+ from fairseq import checkpoint_utils
11
+ import scipy.signal as signal
12
+ from vc_infer_pipeline import VC
13
+
14
+ models, saved_cfg, task = checkpoint_utils.load_model_ensemble_and_task(["hubert_base.pt"],suffix="",)
15
+ model = models[0]
16
+ model = model.to(device)
17
+ if(is_half):model = model.half()
18
+ else:model = model.float()
19
+ model.eval()
20
+
21
+ cpt=torch.load(person,map_location="cpu")
22
+ dv=cpt["dv"]
23
+ tgt_sr=cpt["config"][-1]
24
+ net_g = SynthesizerTrn256(*cpt["config"],is_half=is_half)
25
+ net_g.load_state_dict(cpt["weight"],strict=True)
26
+ net_g.eval().to(device)
27
+ if(is_half):net_g = net_g.half()
28
+ else:net_g = net_g.float()
29
+
30
+ vc=VC(tgt_sr,device,is_half)
31
+
32
+ for name in os.listdir(inp_root):
33
+ try:
34
+ wav_path="%s\%s"%(inp_root,name)
35
+ print("processing %s"%wav_path)
36
+ audio, sampling_rate = sf.read(wav_path)
37
+ if len(audio.shape) > 1:
38
+ audio = librosa.to_mono(audio.transpose(1, 0))
39
+ if sampling_rate != vc.sr:
40
+ audio = librosa.resample(audio, orig_sr=sampling_rate, target_sr=vc.sr)
41
+
42
+ times = [0, 0, 0]
43
+ audio_opt=vc.pipeline(model,net_g,dv,audio,times,f0_up_key,f0_file=None)
44
+ wavfile.write("%s/%s"%(opt_root,name), tgt_sr, audio_opt)
45
+ except:
46
+ traceback.print_exc()
47
+
48
+ print(times)
infer_uvr5.py ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os,sys,torch,warnings,pdb
2
+ warnings.filterwarnings("ignore")
3
+ import librosa
4
+ import importlib
5
+ import numpy as np
6
+ import hashlib , math
7
+ from tqdm import tqdm
8
+ from uvr5_pack.lib_v5 import spec_utils
9
+ from uvr5_pack.utils import _get_name_params,inference
10
+ from uvr5_pack.lib_v5.model_param_init import ModelParameters
11
+ from scipy.io import wavfile
12
+
13
+ class _audio_pre_():
14
+ def __init__(self, model_path,device,is_half):
15
+ self.model_path = model_path
16
+ self.device = device
17
+ self.data = {
18
+ # Processing Options
19
+ 'postprocess': False,
20
+ 'tta': False,
21
+ # Constants
22
+ 'window_size': 512,
23
+ 'agg': 10,
24
+ 'high_end_process': 'mirroring',
25
+ }
26
+ nn_arch_sizes = [
27
+ 31191, # default
28
+ 33966,61968, 123821, 123812, 537238 # custom
29
+ ]
30
+ self.nn_architecture = list('{}KB'.format(s) for s in nn_arch_sizes)
31
+ model_size = math.ceil(os.stat(model_path ).st_size / 1024)
32
+ nn_architecture = '{}KB'.format(min(nn_arch_sizes, key=lambda x:abs(x-model_size)))
33
+ nets = importlib.import_module('uvr5_pack.lib_v5.nets' + f'_{nn_architecture}'.replace('_{}KB'.format(nn_arch_sizes[0]), ''), package=None)
34
+ model_hash = hashlib.md5(open(model_path,'rb').read()).hexdigest()
35
+ param_name ,model_params_d = _get_name_params(model_path , model_hash)
36
+
37
+ mp = ModelParameters(model_params_d)
38
+ model = nets.CascadedASPPNet(mp.param['bins'] * 2)
39
+ cpk = torch.load( model_path , map_location='cpu')
40
+ model.load_state_dict(cpk)
41
+ model.eval()
42
+ if(is_half==True):model = model.half().to(device)
43
+ else:model = model.to(device)
44
+
45
+ self.mp = mp
46
+ self.model = model
47
+
48
+ def _path_audio_(self, music_file ,ins_root=None,vocal_root=None):
49
+ if(ins_root is None and vocal_root is None):return "No save root."
50
+ name=os.path.basename(music_file)
51
+ if(ins_root is not None):os.makedirs(ins_root, exist_ok=True)
52
+ if(vocal_root is not None):os.makedirs(vocal_root , exist_ok=True)
53
+ X_wave, y_wave, X_spec_s, y_spec_s = {}, {}, {}, {}
54
+ bands_n = len(self.mp.param['band'])
55
+ # print(bands_n)
56
+ for d in range(bands_n, 0, -1):
57
+ bp = self.mp.param['band'][d]
58
+ if d == bands_n: # high-end band
59
+ X_wave[d], _ = librosa.core.load(
60
+ music_file, bp['sr'], False, dtype=np.float32, res_type=bp['res_type'])
61
+ if X_wave[d].ndim == 1:
62
+ X_wave[d] = np.asfortranarray([X_wave[d], X_wave[d]])
63
+ else: # lower bands
64
+ X_wave[d] = librosa.core.resample(X_wave[d+1], self.mp.param['band'][d+1]['sr'], bp['sr'], res_type=bp['res_type'])
65
+ # Stft of wave source
66
+ X_spec_s[d] = spec_utils.wave_to_spectrogram_mt(X_wave[d], bp['hl'], bp['n_fft'], self.mp.param['mid_side'], self.mp.param['mid_side_b2'], self.mp.param['reverse'])
67
+ # pdb.set_trace()
68
+ if d == bands_n and self.data['high_end_process'] != 'none':
69
+ input_high_end_h = (bp['n_fft']//2 - bp['crop_stop']) + ( self.mp.param['pre_filter_stop'] - self.mp.param['pre_filter_start'])
70
+ input_high_end = X_spec_s[d][:, bp['n_fft']//2-input_high_end_h:bp['n_fft']//2, :]
71
+
72
+ X_spec_m = spec_utils.combine_spectrograms(X_spec_s, self.mp)
73
+ aggresive_set = float(self.data['agg']/100)
74
+ aggressiveness = {'value': aggresive_set, 'split_bin': self.mp.param['band'][1]['crop_stop']}
75
+ with torch.no_grad():
76
+ pred, X_mag, X_phase = inference(X_spec_m,self.device,self.model, aggressiveness,self.data)
77
+ # Postprocess
78
+ if self.data['postprocess']:
79
+ pred_inv = np.clip(X_mag - pred, 0, np.inf)
80
+ pred = spec_utils.mask_silence(pred, pred_inv)
81
+ y_spec_m = pred * X_phase
82
+ v_spec_m = X_spec_m - y_spec_m
83
+
84
+ if (ins_root is not None):
85
+ if self.data['high_end_process'].startswith('mirroring'):
86
+ input_high_end_ = spec_utils.mirroring(self.data['high_end_process'], y_spec_m, input_high_end, self.mp)
87
+ wav_instrument = spec_utils.cmb_spectrogram_to_wave(y_spec_m, self.mp,input_high_end_h, input_high_end_)
88
+ else:
89
+ wav_instrument = spec_utils.cmb_spectrogram_to_wave(y_spec_m, self.mp)
90
+ print ('%s instruments done'%name)
91
+ wavfile.write(os.path.join(ins_root, 'instrument_{}.wav'.format(name) ), self.mp.param['sr'], (np.array(wav_instrument)*32768).astype("int16")) #
92
+ if (vocal_root is not None):
93
+ if self.data['high_end_process'].startswith('mirroring'):
94
+ input_high_end_ = spec_utils.mirroring(self.data['high_end_process'], v_spec_m, input_high_end, self.mp)
95
+ wav_vocals = spec_utils.cmb_spectrogram_to_wave(v_spec_m, self.mp, input_high_end_h, input_high_end_)
96
+ else:
97
+ wav_vocals = spec_utils.cmb_spectrogram_to_wave(v_spec_m, self.mp)
98
+ print ('%s vocals done'%name)
99
+ wavfile.write(os.path.join(vocal_root , 'vocal_{}.wav'.format(name) ), self.mp.param['sr'], (np.array(wav_vocals)*32768).astype("int16"))
100
+
101
+ if __name__ == '__main__':
102
+ device = 'cuda'
103
+ is_half=True
104
+ model_path='uvr5_weights/2_HP-UVR.pth'
105
+ pre_fun = _audio_pre_(model_path=model_path,device=device,is_half=True)
106
+ audio_path = '神女劈观.aac'
107
+ save_path = 'opt'
108
+ pre_fun._path_audio_(audio_path , save_path,save_path)
myinfer-v2-0528.py ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ '''
2
+ v1
3
+ runtime\python.exe myinfer-v2-0528.py 0 "E:\codes\py39\RVC-beta\todo-songs\1111.wav" "E:\codes\py39\logs\mi-test\added_IVF677_Flat_nprobe_7.index" harvest "test.wav" "E:\codes\py39\test-20230416b\weights\mi-test.pth" 0.66 cuda:0 True 3 0 1 0.33
4
+ v2
5
+ runtime\python.exe myinfer-v2-0528.py 0 "E:\codes\py39\RVC-beta\todo-songs\1111.wav" "E:\codes\py39\test-20230416b\logs\mi-test-v2\aadded_IVF677_Flat_nprobe_1_v2.index" harvest "test_v2.wav" "E:\codes\py39\test-20230416b\weights\mi-test-v2.pth" 0.66 cuda:0 True 3 0 1 0.33
6
+ '''
7
+ import os,sys,pdb,torch
8
+ now_dir = os.getcwd()
9
+ sys.path.append(now_dir)
10
+ import argparse
11
+ import glob
12
+ import sys
13
+ import torch
14
+ from multiprocessing import cpu_count
15
+ class Config:
16
+ def __init__(self,device,is_half):
17
+ self.device = device
18
+ self.is_half = is_half
19
+ self.n_cpu = 0
20
+ self.gpu_name = None
21
+ self.gpu_mem = None
22
+ self.x_pad, self.x_query, self.x_center, self.x_max = self.device_config()
23
+
24
+ def device_config(self) -> tuple:
25
+ if torch.cuda.is_available():
26
+ i_device = int(self.device.split(":")[-1])
27
+ self.gpu_name = torch.cuda.get_device_name(i_device)
28
+ if (
29
+ ("16" in self.gpu_name and "V100" not in self.gpu_name.upper())
30
+ or "P40" in self.gpu_name.upper()
31
+ or "1060" in self.gpu_name
32
+ or "1070" in self.gpu_name
33
+ or "1080" in self.gpu_name
34
+ ):
35
+ print("16系/10系显卡和P40强制单精度")
36
+ self.is_half = False
37
+ for config_file in ["32k.json", "40k.json", "48k.json"]:
38
+ with open(f"configs/{config_file}", "r") as f:
39
+ strr = f.read().replace("true", "false")
40
+ with open(f"configs/{config_file}", "w") as f:
41
+ f.write(strr)
42
+ with open("trainset_preprocess_pipeline_print.py", "r") as f:
43
+ strr = f.read().replace("3.7", "3.0")
44
+ with open("trainset_preprocess_pipeline_print.py", "w") as f:
45
+ f.write(strr)
46
+ else:
47
+ self.gpu_name = None
48
+ self.gpu_mem = int(
49
+ torch.cuda.get_device_properties(i_device).total_memory
50
+ / 1024
51
+ / 1024
52
+ / 1024
53
+ + 0.4
54
+ )
55
+ if self.gpu_mem <= 4:
56
+ with open("trainset_preprocess_pipeline_print.py", "r") as f:
57
+ strr = f.read().replace("3.7", "3.0")
58
+ with open("trainset_preprocess_pipeline_print.py", "w") as f:
59
+ f.write(strr)
60
+ elif torch.backends.mps.is_available():
61
+ print("没有发现支持的N卡, 使用MPS进行推理")
62
+ self.device = "mps"
63
+ else:
64
+ print("没有发现支持的N卡, 使用CPU进行推理")
65
+ self.device = "cpu"
66
+ self.is_half = True
67
+
68
+ if self.n_cpu == 0:
69
+ self.n_cpu = cpu_count()
70
+
71
+ if self.is_half:
72
+ # 6G显存配置
73
+ x_pad = 3
74
+ x_query = 10
75
+ x_center = 60
76
+ x_max = 65
77
+ else:
78
+ # 5G显存配置
79
+ x_pad = 1
80
+ x_query = 6
81
+ x_center = 38
82
+ x_max = 41
83
+
84
+ if self.gpu_mem != None and self.gpu_mem <= 4:
85
+ x_pad = 1
86
+ x_query = 5
87
+ x_center = 30
88
+ x_max = 32
89
+
90
+ return x_pad, x_query, x_center, x_max
91
+
92
+ f0up_key=sys.argv[1]
93
+ input_path=sys.argv[2]
94
+ index_path=sys.argv[3]
95
+ f0method=sys.argv[4]#harvest or pm
96
+ opt_path=sys.argv[5]
97
+ model_path=sys.argv[6]
98
+ index_rate=float(sys.argv[7])
99
+ device=sys.argv[8]
100
+ is_half=bool(sys.argv[9])
101
+ filter_radius=int(sys.argv[10])
102
+ resample_sr=int(sys.argv[11])
103
+ rms_mix_rate=float(sys.argv[12])
104
+ protect=float(sys.argv[13])
105
+ print(sys.argv)
106
+ config=Config(device,is_half)
107
+ now_dir=os.getcwd()
108
+ sys.path.append(now_dir)
109
+ from vc_infer_pipeline import VC
110
+ from lib.infer_pack.models import (
111
+ SynthesizerTrnMs256NSFsid,
112
+ SynthesizerTrnMs256NSFsid_nono,
113
+ SynthesizerTrnMs768NSFsid,
114
+ SynthesizerTrnMs768NSFsid_nono,
115
+ )
116
+ from lib.audio import load_audio
117
+ from fairseq import checkpoint_utils
118
+ from scipy.io import wavfile
119
+
120
+ hubert_model=None
121
+ def load_hubert():
122
+ global hubert_model
123
+ models, saved_cfg, task = checkpoint_utils.load_model_ensemble_and_task(["hubert_base.pt"],suffix="",)
124
+ hubert_model = models[0]
125
+ hubert_model = hubert_model.to(device)
126
+ if(is_half):hubert_model = hubert_model.half()
127
+ else:hubert_model = hubert_model.float()
128
+ hubert_model.eval()
129
+
130
+ def vc_single(sid,input_audio,f0_up_key,f0_file,f0_method,file_index,index_rate):
131
+ global tgt_sr,net_g,vc,hubert_model,version
132
+ if input_audio is None:return "You need to upload an audio", None
133
+ f0_up_key = int(f0_up_key)
134
+ audio=load_audio(input_audio,16000)
135
+ times = [0, 0, 0]
136
+ if(hubert_model==None):load_hubert()
137
+ if_f0 = cpt.get("f0", 1)
138
+ # audio_opt=vc.pipeline(hubert_model,net_g,sid,audio,times,f0_up_key,f0_method,file_index,file_big_npy,index_rate,if_f0,f0_file=f0_file)
139
+ audio_opt=vc.pipeline(hubert_model,net_g,sid,audio,input_audio,times,f0_up_key,f0_method,file_index,index_rate,if_f0,filter_radius,tgt_sr,resample_sr,rms_mix_rate,version,protect,f0_file=f0_file)
140
+ print(times)
141
+ return audio_opt
142
+
143
+
144
+ def get_vc(model_path):
145
+ global n_spk,tgt_sr,net_g,vc,cpt,device,is_half,version
146
+ print("loading pth %s"%model_path)
147
+ cpt = torch.load(model_path, map_location="cpu")
148
+ tgt_sr = cpt["config"][-1]
149
+ cpt["config"][-3]=cpt["weight"]["emb_g.weight"].shape[0]#n_spk
150
+ if_f0=cpt.get("f0",1)
151
+ version = cpt.get("version", "v1")
152
+ if version == "v1":
153
+ if if_f0 == 1:
154
+ net_g = SynthesizerTrnMs256NSFsid(*cpt["config"], is_half=is_half)
155
+ else:
156
+ net_g = SynthesizerTrnMs256NSFsid_nono(*cpt["config"])
157
+ elif version == "v2":
158
+ if if_f0 == 1:#
159
+ net_g = SynthesizerTrnMs768NSFsid(*cpt["config"], is_half=is_half)
160
+ else:
161
+ net_g = SynthesizerTrnMs768NSFsid_nono(*cpt["config"])
162
+ del net_g.enc_q
163
+ print(net_g.load_state_dict(cpt["weight"], strict=False)) # 不加这一行清不干净,真奇葩
164
+ net_g.eval().to(device)
165
+ if (is_half):net_g = net_g.half()
166
+ else:net_g = net_g.float()
167
+ vc = VC(tgt_sr, config)
168
+ n_spk=cpt["config"][-3]
169
+ # return {"visible": True,"maximum": n_spk, "__type__": "update"}
170
+
171
+
172
+ get_vc(model_path)
173
+ wav_opt=vc_single(0,input_path,f0up_key,None,f0method,index_path,index_rate)
174
+ wavfile.write(opt_path, tgt_sr, wav_opt)
175
+
myinfer.py ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ '''
2
+ runtime\python.exe myinfer.py 0 "E:\codes\py39\RVC-beta\todo-songs\1111.wav" "E:\codes\py39\logs\mi-test\added_IVF677_Flat_nprobe_7.index" harvest "test.wav" "weights/mi-test.pth" 0.6 cuda:0 True
3
+ '''
4
+ import os,sys,pdb,torch
5
+ now_dir = os.getcwd()
6
+ sys.path.append(now_dir)
7
+ import argparse
8
+ import glob
9
+ import sys
10
+ import torch
11
+ from multiprocessing import cpu_count
12
+ class Config:
13
+ def __init__(self,device,is_half):
14
+ self.device = device
15
+ self.is_half = is_half
16
+ self.n_cpu = 0
17
+ self.gpu_name = None
18
+ self.gpu_mem = None
19
+ self.x_pad, self.x_query, self.x_center, self.x_max = self.device_config()
20
+
21
+ def device_config(self) -> tuple:
22
+ if torch.cuda.is_available():
23
+ i_device = int(self.device.split(":")[-1])
24
+ self.gpu_name = torch.cuda.get_device_name(i_device)
25
+ if (
26
+ ("16" in self.gpu_name and "V100" not in self.gpu_name.upper())
27
+ or "P40" in self.gpu_name.upper()
28
+ or "1060" in self.gpu_name
29
+ or "1070" in self.gpu_name
30
+ or "1080" in self.gpu_name
31
+ ):
32
+ print("16系/10系显卡和P40强制单精度")
33
+ self.is_half = False
34
+ for config_file in ["32k.json", "40k.json", "48k.json"]:
35
+ with open(f"configs/{config_file}", "r") as f:
36
+ strr = f.read().replace("true", "false")
37
+ with open(f"configs/{config_file}", "w") as f:
38
+ f.write(strr)
39
+ with open("trainset_preprocess_pipeline_print.py", "r") as f:
40
+ strr = f.read().replace("3.7", "3.0")
41
+ with open("trainset_preprocess_pipeline_print.py", "w") as f:
42
+ f.write(strr)
43
+ else:
44
+ self.gpu_name = None
45
+ self.gpu_mem = int(
46
+ torch.cuda.get_device_properties(i_device).total_memory
47
+ / 1024
48
+ / 1024
49
+ / 1024
50
+ + 0.4
51
+ )
52
+ if self.gpu_mem <= 4:
53
+ with open("trainset_preprocess_pipeline_print.py", "r") as f:
54
+ strr = f.read().replace("3.7", "3.0")
55
+ with open("trainset_preprocess_pipeline_print.py", "w") as f:
56
+ f.write(strr)
57
+ elif torch.backends.mps.is_available():
58
+ print("没有发现支持的N卡, 使用MPS进行推理")
59
+ self.device = "mps"
60
+ else:
61
+ print("没有发现支持的N卡, 使用CPU进行推理")
62
+ self.device = "cpu"
63
+ self.is_half = True
64
+
65
+ if self.n_cpu == 0:
66
+ self.n_cpu = cpu_count()
67
+
68
+ if self.is_half:
69
+ # 6G显存配置
70
+ x_pad = 3
71
+ x_query = 10
72
+ x_center = 60
73
+ x_max = 65
74
+ else:
75
+ # 5G显存配置
76
+ x_pad = 1
77
+ x_query = 6
78
+ x_center = 38
79
+ x_max = 41
80
+
81
+ if self.gpu_mem != None and self.gpu_mem <= 4:
82
+ x_pad = 1
83
+ x_query = 5
84
+ x_center = 30
85
+ x_max = 32
86
+
87
+ return x_pad, x_query, x_center, x_max
88
+
89
+ f0up_key=sys.argv[1]
90
+ input_path=sys.argv[2]
91
+ index_path=sys.argv[3]
92
+ f0method=sys.argv[4]#harvest or pm
93
+ opt_path=sys.argv[5]
94
+ model_path=sys.argv[6]
95
+ index_rate=float(sys.argv[7])
96
+ device=sys.argv[8]
97
+ is_half=bool(sys.argv[9])
98
+ print(sys.argv)
99
+ config=Config(device,is_half)
100
+ now_dir=os.getcwd()
101
+ sys.path.append(now_dir)
102
+ from vc_infer_pipeline import VC
103
+ from lib.infer_pack.models import SynthesizerTrnMs256NSFsid, SynthesizerTrnMs256NSFsid_nono
104
+ from lib.audio import load_audio
105
+ from fairseq import checkpoint_utils
106
+ from scipy.io import wavfile
107
+
108
+ hubert_model=None
109
+ def load_hubert():
110
+ global hubert_model
111
+ models, saved_cfg, task = checkpoint_utils.load_model_ensemble_and_task(["hubert_base.pt"],suffix="",)
112
+ hubert_model = models[0]
113
+ hubert_model = hubert_model.to(device)
114
+ if(is_half):hubert_model = hubert_model.half()
115
+ else:hubert_model = hubert_model.float()
116
+ hubert_model.eval()
117
+
118
+ def vc_single(sid,input_audio,f0_up_key,f0_file,f0_method,file_index,index_rate):
119
+ global tgt_sr,net_g,vc,hubert_model
120
+ if input_audio is None:return "You need to upload an audio", None
121
+ f0_up_key = int(f0_up_key)
122
+ audio=load_audio(input_audio,16000)
123
+ times = [0, 0, 0]
124
+ if(hubert_model==None):load_hubert()
125
+ if_f0 = cpt.get("f0", 1)
126
+ # audio_opt=vc.pipeline(hubert_model,net_g,sid,audio,times,f0_up_key,f0_method,file_index,file_big_npy,index_rate,if_f0,f0_file=f0_file)
127
+ audio_opt=vc.pipeline(hubert_model,net_g,sid,audio,times,f0_up_key,f0_method,file_index,index_rate,if_f0,f0_file=f0_file)
128
+ print(times)
129
+ return audio_opt
130
+
131
+
132
+ def get_vc(model_path):
133
+ global n_spk,tgt_sr,net_g,vc,cpt,device,is_half
134
+ print("loading pth %s"%model_path)
135
+ cpt = torch.load(model_path, map_location="cpu")
136
+ tgt_sr = cpt["config"][-1]
137
+ cpt["config"][-3]=cpt["weight"]["emb_g.weight"].shape[0]#n_spk
138
+ if_f0=cpt.get("f0",1)
139
+ if(if_f0==1):
140
+ net_g = SynthesizerTrnMs256NSFsid(*cpt["config"], is_half=is_half)
141
+ else:
142
+ net_g = SynthesizerTrnMs256NSFsid_nono(*cpt["config"])
143
+ del net_g.enc_q
144
+ print(net_g.load_state_dict(cpt["weight"], strict=False)) # 不加这一行清不干净,真奇葩
145
+ net_g.eval().to(device)
146
+ if (is_half):net_g = net_g.half()
147
+ else:net_g = net_g.float()
148
+ vc = VC(tgt_sr, config)
149
+ n_spk=cpt["config"][-3]
150
+ # return {"visible": True,"maximum": n_spk, "__type__": "update"}
151
+
152
+
153
+ get_vc(model_path)
154
+ wav_opt=vc_single(0,input_path,f0up_key,None,f0method,index_path,index_rate)
155
+ wavfile.write(opt_path, tgt_sr, wav_opt)
156
+
slicer.py ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os.path
2
+ from argparse import ArgumentParser
3
+ import time
4
+
5
+ import librosa
6
+ import numpy as np
7
+ import soundfile
8
+ from scipy.ndimage import maximum_filter1d, uniform_filter1d
9
+
10
+
11
+ def timeit(func):
12
+ def run(*args, **kwargs):
13
+ t = time.time()
14
+ res = func(*args, **kwargs)
15
+ print('executing \'%s\' costed %.3fs' % (func.__name__, time.time() - t))
16
+ return res
17
+ return run
18
+
19
+
20
+ # @timeit
21
+ def _window_maximum(arr, win_sz):
22
+ return maximum_filter1d(arr, size=win_sz)[win_sz // 2: win_sz // 2 + arr.shape[0] - win_sz + 1]
23
+
24
+
25
+ # @timeit
26
+ def _window_rms(arr, win_sz):
27
+ filtered = np.sqrt(uniform_filter1d(np.power(arr, 2), win_sz) - np.power(uniform_filter1d(arr, win_sz), 2))
28
+ return filtered[win_sz // 2: win_sz // 2 + arr.shape[0] - win_sz + 1]
29
+
30
+
31
+ def level2db(levels, eps=1e-12):
32
+ return 20 * np.log10(np.clip(levels, a_min=eps, a_max=1))
33
+
34
+
35
+ def _apply_slice(audio, begin, end):
36
+ if len(audio.shape) > 1:
37
+ return audio[:, begin: end]
38
+ else:
39
+ return audio[begin: end]
40
+
41
+
42
+ class Slicer:
43
+ def __init__(self,
44
+ sr: int,
45
+ db_threshold: float = -40,
46
+ min_length: int = 5000,
47
+ win_l: int = 300,
48
+ win_s: int = 20,
49
+ max_silence_kept: int = 500):
50
+ self.db_threshold = db_threshold
51
+ self.min_samples = round(sr * min_length / 1000)
52
+ self.win_ln = round(sr * win_l / 1000)
53
+ self.win_sn = round(sr * win_s / 1000)
54
+ self.max_silence = round(sr * max_silence_kept / 1000)
55
+ if not self.min_samples >= self.win_ln >= self.win_sn:
56
+ raise ValueError('The following condition must be satisfied: min_length >= win_l >= win_s')
57
+ if not self.max_silence >= self.win_sn:
58
+ raise ValueError('The following condition must be satisfied: max_silence_kept >= win_s')
59
+
60
+ @timeit
61
+ def slice(self, audio):
62
+ if len(audio.shape) > 1:
63
+ samples = librosa.to_mono(audio)
64
+ else:
65
+ samples = audio
66
+ if samples.shape[0] <= self.min_samples:
67
+ return [audio]
68
+ # get absolute amplitudes
69
+ abs_amp = np.abs(samples - np.mean(samples))
70
+ # calculate local maximum with large window
71
+ win_max_db = level2db(_window_maximum(abs_amp, win_sz=self.win_ln))
72
+ sil_tags = []
73
+ left = right = 0
74
+ while right < win_max_db.shape[0]:
75
+ if win_max_db[right] < self.db_threshold:
76
+ right += 1
77
+ elif left == right:
78
+ left += 1
79
+ right += 1
80
+ else:
81
+ if left == 0:
82
+ split_loc_l = left
83
+ else:
84
+ sil_left_n = min(self.max_silence, (right + self.win_ln - left) // 2)
85
+ rms_db_left = level2db(_window_rms(samples[left: left + sil_left_n], win_sz=self.win_sn))
86
+ split_win_l = left + np.argmin(rms_db_left)
87
+ split_loc_l = split_win_l + np.argmin(abs_amp[split_win_l: split_win_l + self.win_sn])
88
+ if len(sil_tags) != 0 and split_loc_l - sil_tags[-1][1] < self.min_samples and right < win_max_db.shape[0] - 1:
89
+ right += 1
90
+ left = right
91
+ continue
92
+ if right == win_max_db.shape[0] - 1:
93
+ split_loc_r = right + self.win_ln
94
+ else:
95
+ sil_right_n = min(self.max_silence, (right + self.win_ln - left) // 2)
96
+ rms_db_right = level2db(_window_rms(samples[right + self.win_ln - sil_right_n: right + self.win_ln], win_sz=self.win_sn))
97
+ split_win_r = right + self.win_ln - sil_right_n + np.argmin(rms_db_right)
98
+ split_loc_r = split_win_r + np.argmin(abs_amp[split_win_r: split_win_r + self.win_sn])
99
+ sil_tags.append((split_loc_l, split_loc_r))
100
+ right += 1
101
+ left = right
102
+ if left != right:
103
+ sil_left_n = min(self.max_silence, (right + self.win_ln - left) // 2)
104
+ rms_db_left = level2db(_window_rms(samples[left: left + sil_left_n], win_sz=self.win_sn))
105
+ split_win_l = left + np.argmin(rms_db_left)
106
+ split_loc_l = split_win_l + np.argmin(abs_amp[split_win_l: split_win_l + self.win_sn])
107
+ sil_tags.append((split_loc_l, samples.shape[0]))
108
+ if len(sil_tags) == 0:
109
+ return [audio]
110
+ else:
111
+ chunks = []
112
+ if sil_tags[0][0] > 0:
113
+ chunks.append(_apply_slice(audio, 0, sil_tags[0][0]))
114
+ for i in range(0, len(sil_tags) - 1):
115
+ chunks.append(_apply_slice(audio, sil_tags[i][1], sil_tags[i + 1][0]))
116
+ if sil_tags[-1][1] < samples.shape[0] - 1:
117
+ chunks.append(_apply_slice(audio, sil_tags[-1][1], samples.shape[0]))
118
+ return chunks
119
+
120
+
121
+ def main():
122
+ parser = ArgumentParser()
123
+ parser.add_argument('audio', type=str, help='The audio to be sliced')
124
+ parser.add_argument('--out', type=str, help='Output directory of the sliced audio clips')
125
+ parser.add_argument('--db_thresh', type=float, required=False, default=-40, help='The dB threshold for silence detection')
126
+ parser.add_argument('--min_len', type=int, required=False, default=5000, help='The minimum milliseconds required for each sliced audio clip')
127
+ parser.add_argument('--win_l', type=int, required=False, default=300, help='Size of the large sliding window, presented in milliseconds')
128
+ parser.add_argument('--win_s', type=int, required=False, default=20, help='Size of the small sliding window, presented in milliseconds')
129
+ parser.add_argument('--max_sil_kept', type=int, required=False, default=500, help='The maximum silence length kept around the sliced audio, presented in milliseconds')
130
+ args = parser.parse_args()
131
+ out = args.out
132
+ if out is None:
133
+ out = os.path.dirname(os.path.abspath(args.audio))
134
+ audio, sr = librosa.load(args.audio, sr=None)
135
+ slicer = Slicer(
136
+ sr=sr,
137
+ db_threshold=args.db_thresh,
138
+ min_length=args.min_len,
139
+ win_l=args.win_l,
140
+ win_s=args.win_s,
141
+ max_silence_kept=args.max_sil_kept
142
+ )
143
+ chunks = slicer.slice(audio)
144
+ if not os.path.exists(args.out):
145
+ os.makedirs(args.out)
146
+ for i, chunk in enumerate(chunks):
147
+ soundfile.write(os.path.join(out, f'%s_%d.wav' % (os.path.basename(args.audio).rsplit('.', maxsplit=1)[0], i)), chunk, sr)
148
+
149
+
150
+ if __name__ == '__main__':
151
+ main()
trainset_preprocess_pipeline.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np,ffmpeg,os,traceback
2
+ from slicer import Slicer
3
+ slicer = Slicer(
4
+ sr=40000,
5
+ db_threshold=-32,
6
+ min_length=800,
7
+ win_l=400,
8
+ win_s=20,
9
+ max_silence_kept=150
10
+ )
11
+
12
+
13
+
14
+
15
+ def p0_load_audio(file, sr):#str-ing
16
+ try:
17
+ out, _ = (
18
+ ffmpeg.input(file, threads=0)
19
+ .output("-", format="s16le", acodec="pcm_s16le", ac=1, ar=sr)
20
+ .run(cmd=["ffmpeg", "-nostdin"], capture_stdout=True, capture_stderr=True)
21
+ )
22
+ except ffmpeg.Error as e:
23
+ raise RuntimeError(f"Failed to load audio: {e.stderr.decode()}") from e
24
+ return np.frombuffer(out, np.int16).flatten().astype(np.float32) / 32768.0
25
+
26
+ def p1_trim_audio(slicer,audio):return slicer.slice(audio)
27
+
28
+ def p2_avg_cut(audio,sr,per=3.7,overlap=0.3,tail=4):
29
+ i = 0
30
+ audios=[]
31
+ while (1):
32
+ start = int(sr * (per - overlap) * i)
33
+ i += 1
34
+ if (len(audio[start:]) > tail * sr):
35
+ audios.append(audio[start:start + int(per * sr)])
36
+ else:
37
+ audios.append(audio[start:])
38
+ break
39
+ return audios
40
+
41
+ def p2b_get_vol(audio):return np.square(audio).mean()
42
+
43
+ def p3_norm(audio,alpha=0.8,maxx=0.95):return audio / np.abs(audio).max() * (maxx * alpha) + (1-alpha) * audio
44
+
45
+ def pipeline(inp_root,sr1=40000,sr2=16000,if_trim=True,if_avg_cut=True,if_norm=True,save_root1=None,save_root2=None):
46
+ if(save_root1==None and save_root2==None):return "No save root."
47
+ name2vol={}
48
+ infos=[]
49
+ names=[]
50
+ for name in os.listdir(inp_root):
51
+ try:
52
+ inp_path=os.path.join(inp_root,name)
53
+ audio=p0_load_audio(inp_path)
54
+ except:
55
+ infos.append("%s\t%s"%(name,traceback.format_exc()))
56
+ continue
57
+ if(if_trim==True):res1s=p1_trim_audio(audio)
58
+ else:res1s=[audio]
59
+ for i0,res1 in res1s:
60
+ if(if_avg_cut==True):res2=p2_avg_cut(res1)
61
+ else:res2=[res1]
62
+
63
+
vc_infer_pipeline.py ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np,parselmouth,torch,pdb
2
+ from time import time as ttime
3
+ import torch.nn.functional as F
4
+ from config import x_pad,x_query,x_center,x_max
5
+ from sklearn.cluster import KMeans
6
+
7
+ def resize2d(x, target_len,is1):
8
+ minn=1 if is1==True else 0
9
+ ss = np.array(x).astype("float32")
10
+ ss[ss <=minn] = np.nan
11
+ target = np.interp(np.arange(0, len(ss) * target_len, len(ss)) / target_len, np.arange(0, len(ss)), ss)
12
+ res = np.nan_to_num(target)
13
+ return res
14
+
15
+ class VC(object):
16
+ def __init__(self,tgt_sr,device,is_half):
17
+ self.sr=16000#hubert输入采样率
18
+ self.window=160#每帧点数
19
+ self.t_pad=self.sr*x_pad#每条前后pad时间
20
+ self.t_pad_tgt=tgt_sr*x_pad
21
+ self.t_pad2=self.t_pad*2
22
+ self.t_query=self.sr*x_query#查询切点前后查询时间
23
+ self.t_center=self.sr*x_center#查询切点位置
24
+ self.t_max=self.sr*x_max#免查询时长阈值
25
+ self.device=device
26
+ self.is_half=is_half
27
+
28
+ def get_f0(self,x, p_len,f0_up_key=0,inp_f0=None):
29
+ time_step = self.window / self.sr * 1000
30
+ f0_min = 50
31
+ f0_max = 1100
32
+ f0_mel_min = 1127 * np.log(1 + f0_min / 700)
33
+ f0_mel_max = 1127 * np.log(1 + f0_max / 700)
34
+ f0 = parselmouth.Sound(x, self.sr).to_pitch_ac(
35
+ time_step=time_step / 1000, voicing_threshold=0.6,
36
+ pitch_floor=f0_min, pitch_ceiling=f0_max).selected_array['frequency']
37
+ pad_size=(p_len - len(f0) + 1) // 2
38
+ if(pad_size>0 or p_len - len(f0) - pad_size>0):
39
+ f0 = np.pad(f0,[[pad_size,p_len - len(f0) - pad_size]], mode='constant')
40
+ f0 *= pow(2, f0_up_key / 12)
41
+ # with open("test.txt","w")as f:f.write("\n".join([str(i)for i in f0.tolist()]))
42
+ tf0=self.sr//self.window#每秒f0点数
43
+ if (inp_f0 is not None):
44
+ delta_t=np.round((inp_f0[:,0].max()-inp_f0[:,0].min())*tf0+1).astype("int16")
45
+ replace_f0=np.interp(list(range(delta_t)), inp_f0[:, 0]*100, inp_f0[:, 1])
46
+ shape=f0[x_pad*tf0:x_pad*tf0+len(replace_f0)].shape[0]
47
+ f0[x_pad*tf0:x_pad*tf0+len(replace_f0)]=replace_f0[:shape]
48
+ # with open("test_opt.txt","w")as f:f.write("\n".join([str(i)for i in f0.tolist()]))
49
+ f0bak = f0.copy()
50
+ f0_mel = 1127 * np.log(1 + f0 / 700)
51
+ f0_mel[f0_mel > 0] = (f0_mel[f0_mel > 0] - f0_mel_min) * 254 / (f0_mel_max - f0_mel_min) + 1
52
+ f0_mel[f0_mel <= 1] = 1
53
+ f0_mel[f0_mel > 255] = 255
54
+ f0_coarse = np.rint(f0_mel).astype(np.int)
55
+ return f0_coarse, f0bak#1-0
56
+
57
+ def vc(self,model,net_g,dv,audio0,pitch,pitchf,times):
58
+ feats = torch.from_numpy(audio0)
59
+ if(self.is_half==True):feats=feats.half()
60
+ else:feats=feats.float()
61
+ if feats.dim() == 2: # double channels
62
+ feats = feats.mean(-1)
63
+ assert feats.dim() == 1, feats.dim()
64
+ feats = feats.view(1, -1)
65
+ padding_mask = torch.BoolTensor(feats.shape).fill_(False)
66
+
67
+ inputs = {
68
+ "source": feats.to(self.device),
69
+ "padding_mask": padding_mask.to(self.device),
70
+ "output_layer": 9, # layer 9
71
+ }
72
+ t0 = ttime()
73
+ with torch.no_grad():
74
+ logits = model.extract_features(**inputs)
75
+ feats = model.final_proj(logits[0])
76
+ feats = F.interpolate(feats.permute(0, 2, 1), scale_factor=2).permute(0, 2, 1)
77
+ t1 = ttime()
78
+ p_len = audio0.shape[0]//self.window
79
+ if(feats.shape[1]<p_len):
80
+ p_len=feats.shape[1]
81
+ pitch=pitch[:,:p_len]
82
+ pitchf=pitchf[:,:p_len]
83
+ p_len=torch.LongTensor([p_len]).to(self.device)
84
+ with torch.no_grad():
85
+ audio1 = (net_g.infer(feats, p_len, pitch, pitchf, dv)[0][0, 0] * 32768).data.cpu().float().numpy().astype(np.int16)
86
+ del feats,p_len,padding_mask
87
+ torch.cuda.empty_cache()
88
+ t2 = ttime()
89
+ times[0] += (t1 - t0)
90
+ times[2] += (t2 - t1)
91
+ return audio1
92
+ def vc_km(self,model,net_g,dv,audio0,pitch,pitchf,times):
93
+ kmeans = KMeans(500)
94
+ def get_cluster_result(x):
95
+ """x: np.array [t, 256]"""
96
+ return kmeans.predict(x)
97
+ checkpoint = torch.load("lulu_contentvec_kmeans_500.pt")
98
+ kmeans.__dict__["n_features_in_"] = checkpoint["n_features_in_"]
99
+ kmeans.__dict__["_n_threads"] = checkpoint["_n_threads"]
100
+ kmeans.__dict__["cluster_centers_"] = checkpoint["cluster_centers_"]
101
+ feats = torch.from_numpy(audio0).float()
102
+ if feats.dim() == 2: # double channels
103
+ feats = feats.mean(-1)
104
+ assert feats.dim() == 1, feats.dim()
105
+ feats = feats.view(1, -1)
106
+ padding_mask = torch.BoolTensor(feats.shape).fill_(False)
107
+ inputs = {
108
+ "source": feats.half().to(self.device),
109
+ "padding_mask": padding_mask.to(self.device),
110
+ "output_layer": 9, # layer 9
111
+ }
112
+ torch.cuda.synchronize()
113
+ t0 = ttime()
114
+ with torch.no_grad():
115
+ logits = model.extract_features(**inputs)
116
+ feats = model.final_proj(logits[0])
117
+ feats = get_cluster_result(feats.cpu().numpy()[0].astype("float32"))
118
+ feats = torch.from_numpy(feats).to(self.device)
119
+ feats = F.interpolate(feats.half().unsqueeze(0).unsqueeze(0), scale_factor=2).long().squeeze(0)
120
+ t1 = ttime()
121
+ p_len = audio0.shape[0]//self.window
122
+ if(feats.shape[1]<p_len):
123
+ p_len=feats.shape[1]
124
+ pitch=pitch[:,:p_len]
125
+ pitchf=pitchf[:,:p_len]
126
+ p_len=torch.LongTensor([p_len]).to(self.device)
127
+ with torch.no_grad():
128
+ audio1 = (net_g.infer(feats, p_len, pitch, pitchf, dv)[0][0, 0] * 32768).data.cpu().float().numpy().astype(np.int16)
129
+ del feats,p_len,padding_mask
130
+ torch.cuda.empty_cache()
131
+ t2 = ttime()
132
+ times[0] += (t1 - t0)
133
+ times[2] += (t2 - t1)
134
+ return audio1
135
+
136
+ def pipeline(self,model,net_g,dv,audio,times,f0_up_key,f0_file=None):
137
+ audio_pad = np.pad(audio, (self.window // 2, self.window // 2), mode='reflect')
138
+ opt_ts = []
139
+ if(audio_pad.shape[0]>self.t_max):
140
+ audio_sum = np.zeros_like(audio)
141
+ for i in range(self.window): audio_sum += audio_pad[i:i - self.window]
142
+ for t in range(self.t_center, audio.shape[0],self.t_center):opt_ts.append(t - self.t_query + np.where(np.abs(audio_sum[t - self.t_query:t + self.t_query]) == np.abs(audio_sum[t - self.t_query:t + self.t_query]).min())[0][0])
143
+ s = 0
144
+ audio_opt=[]
145
+ t=None
146
+ t1=ttime()
147
+ audio_pad = np.pad(audio, (self.t_pad, self.t_pad), mode='reflect')
148
+ p_len=audio_pad.shape[0]//self.window
149
+ inp_f0=None
150
+ if(hasattr(f0_file,'name') ==True):
151
+ try:
152
+ with open(f0_file.name,"r")as f:
153
+ lines=f.read().strip("\n").split("\n")
154
+ inp_f0=[]
155
+ for line in lines:inp_f0.append([float(i)for i in line.split(",")])
156
+ inp_f0=np.array(inp_f0,dtype="float32")
157
+ except:
158
+ traceback.print_exc()
159
+ pitch, pitchf = self.get_f0(audio_pad, p_len, f0_up_key,inp_f0)
160
+
161
+ pitch = pitch[:p_len]
162
+ pitchf = pitchf[:p_len]
163
+ # if(inp_f0 is None):
164
+ # pitch = pitch[:p_len]
165
+ # pitchf = pitchf[:p_len]
166
+ # else:
167
+ # pitch=resize2d(pitch,p_len,is1=True)
168
+ # pitchf=resize2d(pitchf,p_len,is1=False)
169
+ pitch = torch.LongTensor(pitch).unsqueeze(0).to(self.device)
170
+ pitchf = torch.FloatTensor(pitchf).unsqueeze(0).to(self.device)
171
+ t2=ttime()
172
+ times[1] += (t2 - t1)
173
+ for t in opt_ts:
174
+ t=t//self.window*self.window
175
+ audio_opt.append(self.vc(model,net_g,dv,audio_pad[s:t+self.t_pad2+self.window],pitch[:,s//self.window:(t+self.t_pad2)//self.window],pitchf[:,s//self.window:(t+self.t_pad2)//self.window],times)[self.t_pad_tgt:-self.t_pad_tgt])
176
+ s = t
177
+ audio_opt.append(self.vc(model,net_g,dv,audio_pad[t:],pitch[:,t//self.window:]if t is not None else pitch,pitchf[:,t//self.window:]if t is not None else pitchf,times)[self.t_pad_tgt:-self.t_pad_tgt])
178
+ audio_opt=np.concatenate(audio_opt)
179
+ del pitch,pitchf
180
+ return audio_opt
181
+ def pipeline_km(self,model,net_g,dv,audio,times,f0_up_key,f0_file=None):
182
+ audio_pad = np.pad(audio, (self.window // 2, self.window // 2), mode='reflect')
183
+ opt_ts = []
184
+ if(audio_pad.shape[0]>self.t_max):
185
+ audio_sum = np.zeros_like(audio)
186
+ for i in range(self.window): audio_sum += audio_pad[i:i - self.window]
187
+ for t in range(self.t_center, audio.shape[0],self.t_center):opt_ts.append(t - self.t_query + np.where(np.abs(audio_sum[t - self.t_query:t + self.t_query]) == np.abs(audio_sum[t - self.t_query:t + self.t_query]).min())[0][0])
188
+ s = 0
189
+ audio_opt=[]
190
+ t=None
191
+ t1=ttime()
192
+ audio_pad = np.pad(audio, (self.t_pad, self.t_pad), mode='reflect')
193
+ p_len=audio_pad.shape[0]//self.window
194
+ inp_f0=None
195
+ if(hasattr(f0_file,'name') ==True):
196
+ try:
197
+ with open(f0_file.name,"r")as f:
198
+ lines=f.read().strip("\n").split("\n")
199
+ inp_f0=[]
200
+ for line in lines:inp_f0.append([float(i)for i in line.split(",")])
201
+ inp_f0=np.array(inp_f0,dtype="float32")
202
+ except:
203
+ traceback.print_exc()
204
+ pitch, pitchf = self.get_f0(audio_pad, p_len, f0_up_key,inp_f0)
205
+
206
+ pitch = pitch[:p_len]
207
+ pitchf = pitchf[:p_len]
208
+ # if(inp_f0 is None):
209
+ # pitch = pitch[:p_len]
210
+ # pitchf = pitchf[:p_len]
211
+ # else:
212
+ # pitch=resize2d(pitch,p_len,is1=True)
213
+ # pitchf=resize2d(pitchf,p_len,is1=False)
214
+ pitch = torch.LongTensor(pitch).unsqueeze(0).to(self.device)
215
+ pitchf = torch.FloatTensor(pitchf).unsqueeze(0).to(self.device)
216
+ t2=ttime()
217
+ times[1] += (t2 - t1)
218
+ for t in opt_ts:
219
+ t=t//self.window*self.window
220
+ audio_opt.append(self.vc_km(model,net_g,dv,audio_pad[s:t+self.t_pad2+self.window],pitch[:,s//self.window:(t+self.t_pad2)//self.window],pitchf[:,s//self.window:(t+self.t_pad2)//self.window],times)[self.t_pad_tgt:-self.t_pad_tgt])
221
+ s = t
222
+ audio_opt.append(self.vc_km(model,net_g,dv,audio_pad[t:],pitch[:,t//self.window:]if t is not None else pitch,pitchf[:,t//self.window:]if t is not None else pitchf,times)[self.t_pad_tgt:-self.t_pad_tgt])
223
+ audio_opt=np.concatenate(audio_opt)
224
+ del pitch,pitchf
225
+ return audio_opt
使用需遵守的协议-LICENSE.txt ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2022 lj1995
4
+
5
+ 本软件仅供研究使用,使用软件者、传播软件导出的声音者自负全责。如不认可该条款,则不能使用/引用软件包内所有代码和文件。
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
24
+ #################
25
+ ContentVec
26
+ https://github.com/auspicious3000/contentvec/blob/main/LICENSE
27
+ MIT License
28
+ #################
29
+ VITS
30
+ https://github.com/jaywalnut310/vits/blob/main/LICENSE
31
+ MIT License
32
+ #################
33
+ HIFIGAN
34
+ https://github.com/jik876/hifi-gan/blob/master/LICENSE
35
+ MIT License
36
+ #################
37
+ gradio
38
+ https://github.com/gradio-app/gradio/blob/main/LICENSE
39
+ Apache License 2.0
40
+ #################
41
+ ffmpeg
42
+ https://github.com/FFmpeg/FFmpeg/blob/master/COPYING.LGPLv3
43
+ https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2021-02-28-12-32/ffmpeg-n4.3.2-160-gfbb9368226-win64-lgpl-4.3.zip
44
+ LPGLv3 License
45
+ MIT License
46
+ #################
47
+ ultimatevocalremovergui
48
+ https://github.com/Anjok07/ultimatevocalremovergui/blob/master/LICENSE
49
+ https://github.com/yang123qwe/vocal_separation_by_uvr5
50
+ MIT License
51
+ #################
52
+ audio-slicer
53
+ https://github.com/openvpi/audio-slicer/blob/main/LICENSE
54
+ MIT License