Spaces:
Runtime error
Runtime error
Upload 17 files
Browse files- tools/app.py +161 -0
- tools/calc_rvc_model_similarity.py +96 -0
- tools/dlmodels.bat +348 -0
- tools/dlmodels.sh +566 -0
- tools/download_models.py +79 -0
- tools/export_onnx.py +54 -0
- tools/infer/infer-pm-index256.py +203 -0
- tools/infer/train-index-v2.py +80 -0
- tools/infer/train-index.py +43 -0
- tools/infer/trans_weights.py +18 -0
- tools/infer_batch_rvc.py +72 -0
- tools/infer_cli.py +67 -0
- tools/onnx_inference_demo.py +23 -0
- tools/rvc_for_realtime.py +443 -0
- tools/torchgate/__init__.py +13 -0
- tools/torchgate/torchgate.py +280 -0
- tools/torchgate/utils.py +70 -0
tools/app.py
ADDED
@@ -0,0 +1,161 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import logging
|
2 |
+
import os
|
3 |
+
|
4 |
+
# os.system("wget -P cvec/ https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/hubert_base.pt")
|
5 |
+
import gradio as gr
|
6 |
+
from dotenv import load_dotenv
|
7 |
+
|
8 |
+
from configs.config import Config
|
9 |
+
from i18n.i18n import I18nAuto
|
10 |
+
from infer.modules.vc.modules import VC
|
11 |
+
|
12 |
+
logging.getLogger("numba").setLevel(logging.WARNING)
|
13 |
+
logging.getLogger("markdown_it").setLevel(logging.WARNING)
|
14 |
+
logging.getLogger("urllib3").setLevel(logging.WARNING)
|
15 |
+
logging.getLogger("matplotlib").setLevel(logging.WARNING)
|
16 |
+
logger = logging.getLogger(__name__)
|
17 |
+
|
18 |
+
i18n = I18nAuto()
|
19 |
+
logger.info(i18n)
|
20 |
+
|
21 |
+
load_dotenv()
|
22 |
+
config = Config()
|
23 |
+
vc = VC(config)
|
24 |
+
|
25 |
+
weight_root = os.getenv("weight_root")
|
26 |
+
weight_uvr5_root = os.getenv("weight_uvr5_root")
|
27 |
+
index_root = os.getenv("index_root")
|
28 |
+
names = []
|
29 |
+
hubert_model = None
|
30 |
+
for name in os.listdir(weight_root):
|
31 |
+
if name.endswith(".pth"):
|
32 |
+
names.append(name)
|
33 |
+
index_paths = []
|
34 |
+
for root, dirs, files in os.walk(index_root, topdown=False):
|
35 |
+
for name in files:
|
36 |
+
if name.endswith(".index") and "trained" not in name:
|
37 |
+
index_paths.append("%s/%s" % (root, name))
|
38 |
+
|
39 |
+
|
40 |
+
app = gr.Blocks()
|
41 |
+
with app:
|
42 |
+
with gr.Tabs():
|
43 |
+
with gr.TabItem("在线demo"):
|
44 |
+
gr.Markdown(
|
45 |
+
value="""
|
46 |
+
RVC 在线demo
|
47 |
+
"""
|
48 |
+
)
|
49 |
+
sid = gr.Dropdown(label=i18n("推理音色"), choices=sorted(names))
|
50 |
+
with gr.Column():
|
51 |
+
spk_item = gr.Slider(
|
52 |
+
minimum=0,
|
53 |
+
maximum=2333,
|
54 |
+
step=1,
|
55 |
+
label=i18n("请选择说话人id"),
|
56 |
+
value=0,
|
57 |
+
visible=False,
|
58 |
+
interactive=True,
|
59 |
+
)
|
60 |
+
sid.change(fn=vc.get_vc, inputs=[sid], outputs=[spk_item])
|
61 |
+
gr.Markdown(
|
62 |
+
value=i18n(
|
63 |
+
"男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. "
|
64 |
+
)
|
65 |
+
)
|
66 |
+
vc_input3 = gr.Audio(label="上传音频(长度小于90秒)")
|
67 |
+
vc_transform0 = gr.Number(
|
68 |
+
label=i18n("变调(整数, 半音数量, 升八度12降八度-12)"), value=0
|
69 |
+
)
|
70 |
+
f0method0 = gr.Radio(
|
71 |
+
label=i18n(
|
72 |
+
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU"
|
73 |
+
),
|
74 |
+
choices=["pm", "harvest", "crepe", "rmvpe"],
|
75 |
+
value="pm",
|
76 |
+
interactive=True,
|
77 |
+
)
|
78 |
+
filter_radius0 = gr.Slider(
|
79 |
+
minimum=0,
|
80 |
+
maximum=7,
|
81 |
+
label=i18n(
|
82 |
+
">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音"
|
83 |
+
),
|
84 |
+
value=3,
|
85 |
+
step=1,
|
86 |
+
interactive=True,
|
87 |
+
)
|
88 |
+
with gr.Column():
|
89 |
+
file_index1 = gr.Textbox(
|
90 |
+
label=i18n("特征检索库文件路径,为空则使用下拉的选择结果"),
|
91 |
+
value="",
|
92 |
+
interactive=False,
|
93 |
+
visible=False,
|
94 |
+
)
|
95 |
+
file_index2 = gr.Dropdown(
|
96 |
+
label=i18n("自动检测index路径,下拉式选择(dropdown)"),
|
97 |
+
choices=sorted(index_paths),
|
98 |
+
interactive=True,
|
99 |
+
)
|
100 |
+
index_rate1 = gr.Slider(
|
101 |
+
minimum=0,
|
102 |
+
maximum=1,
|
103 |
+
label=i18n("检索特征占比"),
|
104 |
+
value=0.88,
|
105 |
+
interactive=True,
|
106 |
+
)
|
107 |
+
resample_sr0 = gr.Slider(
|
108 |
+
minimum=0,
|
109 |
+
maximum=48000,
|
110 |
+
label=i18n("后处理重采样至最终采样率,0为不进行重采样"),
|
111 |
+
value=0,
|
112 |
+
step=1,
|
113 |
+
interactive=True,
|
114 |
+
)
|
115 |
+
rms_mix_rate0 = gr.Slider(
|
116 |
+
minimum=0,
|
117 |
+
maximum=1,
|
118 |
+
label=i18n(
|
119 |
+
"输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络"
|
120 |
+
),
|
121 |
+
value=1,
|
122 |
+
interactive=True,
|
123 |
+
)
|
124 |
+
protect0 = gr.Slider(
|
125 |
+
minimum=0,
|
126 |
+
maximum=0.5,
|
127 |
+
label=i18n(
|
128 |
+
"保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果"
|
129 |
+
),
|
130 |
+
value=0.33,
|
131 |
+
step=0.01,
|
132 |
+
interactive=True,
|
133 |
+
)
|
134 |
+
f0_file = gr.File(
|
135 |
+
label=i18n("F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调")
|
136 |
+
)
|
137 |
+
but0 = gr.Button(i18n("转换"), variant="primary")
|
138 |
+
vc_output1 = gr.Textbox(label=i18n("输出信息"))
|
139 |
+
vc_output2 = gr.Audio(label=i18n("输出音频(右下角三个点,点了可以下载)"))
|
140 |
+
but0.click(
|
141 |
+
vc.vc_single,
|
142 |
+
[
|
143 |
+
spk_item,
|
144 |
+
vc_input3,
|
145 |
+
vc_transform0,
|
146 |
+
f0_file,
|
147 |
+
f0method0,
|
148 |
+
file_index1,
|
149 |
+
file_index2,
|
150 |
+
# file_big_npy1,
|
151 |
+
index_rate1,
|
152 |
+
filter_radius0,
|
153 |
+
resample_sr0,
|
154 |
+
rms_mix_rate0,
|
155 |
+
protect0,
|
156 |
+
],
|
157 |
+
[vc_output1, vc_output2],
|
158 |
+
)
|
159 |
+
|
160 |
+
|
161 |
+
app.launch()
|
tools/calc_rvc_model_similarity.py
ADDED
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# This code references https://huggingface.co/JosephusCheung/ASimilarityCalculatior/blob/main/qwerty.py
|
2 |
+
# Fill in the path of the model to be queried and the root directory of the reference models, and this script will return the similarity between the model to be queried and all reference models.
|
3 |
+
import os
|
4 |
+
import logging
|
5 |
+
|
6 |
+
logger = logging.getLogger(__name__)
|
7 |
+
|
8 |
+
import torch
|
9 |
+
import torch.nn as nn
|
10 |
+
import torch.nn.functional as F
|
11 |
+
|
12 |
+
|
13 |
+
def cal_cross_attn(to_q, to_k, to_v, rand_input):
|
14 |
+
hidden_dim, embed_dim = to_q.shape
|
15 |
+
attn_to_q = nn.Linear(hidden_dim, embed_dim, bias=False)
|
16 |
+
attn_to_k = nn.Linear(hidden_dim, embed_dim, bias=False)
|
17 |
+
attn_to_v = nn.Linear(hidden_dim, embed_dim, bias=False)
|
18 |
+
attn_to_q.load_state_dict({"weight": to_q})
|
19 |
+
attn_to_k.load_state_dict({"weight": to_k})
|
20 |
+
attn_to_v.load_state_dict({"weight": to_v})
|
21 |
+
|
22 |
+
return torch.einsum(
|
23 |
+
"ik, jk -> ik",
|
24 |
+
F.softmax(
|
25 |
+
torch.einsum("ij, kj -> ik", attn_to_q(rand_input), attn_to_k(rand_input)),
|
26 |
+
dim=-1,
|
27 |
+
),
|
28 |
+
attn_to_v(rand_input),
|
29 |
+
)
|
30 |
+
|
31 |
+
|
32 |
+
def model_hash(filename):
|
33 |
+
try:
|
34 |
+
with open(filename, "rb") as file:
|
35 |
+
import hashlib
|
36 |
+
|
37 |
+
m = hashlib.sha256()
|
38 |
+
|
39 |
+
file.seek(0x100000)
|
40 |
+
m.update(file.read(0x10000))
|
41 |
+
return m.hexdigest()[0:8]
|
42 |
+
except FileNotFoundError:
|
43 |
+
return "NOFILE"
|
44 |
+
|
45 |
+
|
46 |
+
def eval(model, n, input):
|
47 |
+
qk = f"enc_p.encoder.attn_layers.{n}.conv_q.weight"
|
48 |
+
uk = f"enc_p.encoder.attn_layers.{n}.conv_k.weight"
|
49 |
+
vk = f"enc_p.encoder.attn_layers.{n}.conv_v.weight"
|
50 |
+
atoq, atok, atov = model[qk][:, :, 0], model[uk][:, :, 0], model[vk][:, :, 0]
|
51 |
+
|
52 |
+
attn = cal_cross_attn(atoq, atok, atov, input)
|
53 |
+
return attn
|
54 |
+
|
55 |
+
|
56 |
+
def main(path, root):
|
57 |
+
torch.manual_seed(114514)
|
58 |
+
model_a = torch.load(path, map_location="cpu")["weight"]
|
59 |
+
|
60 |
+
logger.info("Query:\t\t%s\t%s" % (path, model_hash(path)))
|
61 |
+
|
62 |
+
map_attn_a = {}
|
63 |
+
map_rand_input = {}
|
64 |
+
for n in range(6):
|
65 |
+
hidden_dim, embed_dim, _ = model_a[
|
66 |
+
f"enc_p.encoder.attn_layers.{n}.conv_v.weight"
|
67 |
+
].shape
|
68 |
+
rand_input = torch.randn([embed_dim, hidden_dim])
|
69 |
+
|
70 |
+
map_attn_a[n] = eval(model_a, n, rand_input)
|
71 |
+
map_rand_input[n] = rand_input
|
72 |
+
|
73 |
+
del model_a
|
74 |
+
|
75 |
+
for name in sorted(list(os.listdir(root))):
|
76 |
+
path = "%s/%s" % (root, name)
|
77 |
+
model_b = torch.load(path, map_location="cpu")["weight"]
|
78 |
+
|
79 |
+
sims = []
|
80 |
+
for n in range(6):
|
81 |
+
attn_a = map_attn_a[n]
|
82 |
+
attn_b = eval(model_b, n, map_rand_input[n])
|
83 |
+
|
84 |
+
sim = torch.mean(torch.cosine_similarity(attn_a, attn_b))
|
85 |
+
sims.append(sim)
|
86 |
+
|
87 |
+
logger.info(
|
88 |
+
"Reference:\t%s\t%s\t%s"
|
89 |
+
% (path, model_hash(path), f"{torch.mean(torch.stack(sims)) * 1e2:.2f}%")
|
90 |
+
)
|
91 |
+
|
92 |
+
|
93 |
+
if __name__ == "__main__":
|
94 |
+
query_path = r"assets\weights\mi v3.pth"
|
95 |
+
reference_root = r"assets\weights"
|
96 |
+
main(query_path, reference_root)
|
tools/dlmodels.bat
ADDED
@@ -0,0 +1,348 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
@echo off && chcp 65001
|
2 |
+
|
3 |
+
echo working dir is %cd%
|
4 |
+
echo downloading requirement aria2 check.
|
5 |
+
echo=
|
6 |
+
dir /a:d/b | findstr "aria2" > flag.txt
|
7 |
+
findstr "aria2" flag.txt >nul
|
8 |
+
if %errorlevel% ==0 (
|
9 |
+
echo aria2 checked.
|
10 |
+
echo=
|
11 |
+
) else (
|
12 |
+
echo failed. please downloading aria2 from webpage!
|
13 |
+
echo unzip it and put in this directory!
|
14 |
+
timeout /T 5
|
15 |
+
start https://github.com/aria2/aria2/releases/tag/release-1.36.0
|
16 |
+
echo=
|
17 |
+
goto end
|
18 |
+
)
|
19 |
+
|
20 |
+
echo envfiles checking start.
|
21 |
+
echo=
|
22 |
+
|
23 |
+
for /f %%x in ('findstr /i /c:"aria2" "flag.txt"') do (set aria2=%%x)&goto endSch
|
24 |
+
:endSch
|
25 |
+
|
26 |
+
set d32=f0D32k.pth
|
27 |
+
set d40=f0D40k.pth
|
28 |
+
set d48=f0D48k.pth
|
29 |
+
set g32=f0G32k.pth
|
30 |
+
set g40=f0G40k.pth
|
31 |
+
set g48=f0G48k.pth
|
32 |
+
|
33 |
+
set d40v2=f0D40k.pth
|
34 |
+
set g40v2=f0G40k.pth
|
35 |
+
|
36 |
+
set dld32=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D32k.pth
|
37 |
+
set dld40=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D40k.pth
|
38 |
+
set dld48=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D48k.pth
|
39 |
+
set dlg32=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G32k.pth
|
40 |
+
set dlg40=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G40k.pth
|
41 |
+
set dlg48=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G48k.pth
|
42 |
+
|
43 |
+
set dld40v2=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0D40k.pth
|
44 |
+
set dlg40v2=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0G40k.pth
|
45 |
+
|
46 |
+
set hp2_all=HP2_all_vocals.pth
|
47 |
+
set hp3_all=HP3_all_vocals.pth
|
48 |
+
set hp5_only=HP5_only_main_vocal.pth
|
49 |
+
set VR_DeEchoAggressive=VR-DeEchoAggressive.pth
|
50 |
+
set VR_DeEchoDeReverb=VR-DeEchoDeReverb.pth
|
51 |
+
set VR_DeEchoNormal=VR-DeEchoNormal.pth
|
52 |
+
set onnx_dereverb=vocals.onnx
|
53 |
+
|
54 |
+
set dlhp2_all=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP2_all_vocals.pth
|
55 |
+
set dlhp3_all=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP3_all_vocals.pth
|
56 |
+
set dlhp5_only=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP5_only_main_vocal.pth
|
57 |
+
set dlVR_DeEchoAggressive=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/VR-DeEchoAggressive.pth
|
58 |
+
set dlVR_DeEchoDeReverb=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/VR-DeEchoDeReverb.pth
|
59 |
+
set dlVR_DeEchoNormal=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/VR-DeEchoNormal.pth
|
60 |
+
set dlonnx_dereverb=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/onnx_dereverb_By_FoxJoy/vocals.onnx
|
61 |
+
|
62 |
+
set hb=hubert_base.pt
|
63 |
+
|
64 |
+
set dlhb=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/hubert_base.pt
|
65 |
+
|
66 |
+
echo dir check start.
|
67 |
+
echo=
|
68 |
+
|
69 |
+
if exist "%~dp0assets\pretrained" (
|
70 |
+
echo dir .\assets\pretrained checked.
|
71 |
+
) else (
|
72 |
+
echo failed. generating dir .\assets\pretrained.
|
73 |
+
mkdir pretrained
|
74 |
+
)
|
75 |
+
if exist "%~dp0assets\pretrained_v2" (
|
76 |
+
echo dir .\assets\pretrained_v2 checked.
|
77 |
+
) else (
|
78 |
+
echo failed. generating dir .\assets\pretrained_v2.
|
79 |
+
mkdir pretrained_v2
|
80 |
+
)
|
81 |
+
if exist "%~dp0assets\uvr5_weights" (
|
82 |
+
echo dir .\assets\uvr5_weights checked.
|
83 |
+
) else (
|
84 |
+
echo failed. generating dir .\assets\uvr5_weights.
|
85 |
+
mkdir uvr5_weights
|
86 |
+
)
|
87 |
+
if exist "%~dp0assets\uvr5_weights\onnx_dereverb_By_FoxJoy" (
|
88 |
+
echo dir .\assets\uvr5_weights\onnx_dereverb_By_FoxJoy checked.
|
89 |
+
) else (
|
90 |
+
echo failed. generating dir .\assets\uvr5_weights\onnx_dereverb_By_FoxJoy.
|
91 |
+
mkdir uvr5_weights\onnx_dereverb_By_FoxJoy
|
92 |
+
)
|
93 |
+
|
94 |
+
echo=
|
95 |
+
echo dir check finished.
|
96 |
+
|
97 |
+
echo=
|
98 |
+
echo required files check start.
|
99 |
+
|
100 |
+
echo checking D32k.pth
|
101 |
+
if exist "%~dp0assets\pretrained\D32k.pth" (
|
102 |
+
echo D32k.pth in .\assets\pretrained checked.
|
103 |
+
echo=
|
104 |
+
) else (
|
105 |
+
echo failed. starting download from huggingface.
|
106 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/D32k.pth -d %~dp0assets\pretrained -o D32k.pth
|
107 |
+
if exist "%~dp0assets\pretrained\D32k.pth" (echo download successful.) else (echo please try again!
|
108 |
+
echo=)
|
109 |
+
)
|
110 |
+
echo checking D40k.pth
|
111 |
+
if exist "%~dp0assets\pretrained\D40k.pth" (
|
112 |
+
echo D40k.pth in .\assets\pretrained checked.
|
113 |
+
echo=
|
114 |
+
) else (
|
115 |
+
echo failed. starting download from huggingface.
|
116 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/D40k.pth -d %~dp0assets\pretrained -o D40k.pth
|
117 |
+
if exist "%~dp0assets\pretrained\D40k.pth" (echo download successful.) else (echo please try again!
|
118 |
+
echo=)
|
119 |
+
)
|
120 |
+
echo checking D40k.pth
|
121 |
+
if exist "%~dp0assets\pretrained_v2\D40k.pth" (
|
122 |
+
echo D40k.pth in .\assets\pretrained_v2 checked.
|
123 |
+
echo=
|
124 |
+
) else (
|
125 |
+
echo failed. starting download from huggingface.
|
126 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/D40k.pth -d %~dp0assets\pretrained_v2 -o D40k.pth
|
127 |
+
if exist "%~dp0assets\pretrained_v2\D40k.pth" (echo download successful.) else (echo please try again!
|
128 |
+
echo=)
|
129 |
+
)
|
130 |
+
echo checking D48k.pth
|
131 |
+
if exist "%~dp0assets\pretrained\D48k.pth" (
|
132 |
+
echo D48k.pth in .\assets\pretrained checked.
|
133 |
+
echo=
|
134 |
+
) else (
|
135 |
+
echo failed. starting download from huggingface.
|
136 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/D48k.pth -d %~dp0assets\pretrained -o D48k.pth
|
137 |
+
if exist "%~dp0assets\pretrained\D48k.pth" (echo download successful.) else (echo please try again!
|
138 |
+
echo=)
|
139 |
+
)
|
140 |
+
echo checking G32k.pth
|
141 |
+
if exist "%~dp0assets\pretrained\G32k.pth" (
|
142 |
+
echo G32k.pth in .\assets\pretrained checked.
|
143 |
+
echo=
|
144 |
+
) else (
|
145 |
+
echo failed. starting download from huggingface.
|
146 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/G32k.pth -d %~dp0assets\pretrained -o G32k.pth
|
147 |
+
if exist "%~dp0assets\pretrained\G32k.pth" (echo download successful.) else (echo please try again!
|
148 |
+
echo=)
|
149 |
+
)
|
150 |
+
echo checking G40k.pth
|
151 |
+
if exist "%~dp0assets\pretrained\G40k.pth" (
|
152 |
+
echo G40k.pth in .\assets\pretrained checked.
|
153 |
+
echo=
|
154 |
+
) else (
|
155 |
+
echo failed. starting download from huggingface.
|
156 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/G40k.pth -d %~dp0assets\pretrained -o G40k.pth
|
157 |
+
if exist "%~dp0assets\pretrained\G40k.pth" (echo download successful.) else (echo please try again!
|
158 |
+
echo=)
|
159 |
+
)
|
160 |
+
echo checking G40k.pth
|
161 |
+
if exist "%~dp0assets\pretrained_v2\G40k.pth" (
|
162 |
+
echo G40k.pth in .\assets\pretrained_v2 checked.
|
163 |
+
echo=
|
164 |
+
) else (
|
165 |
+
echo failed. starting download from huggingface.
|
166 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/G40k.pth -d %~dp0assets\pretrained_v2 -o G40k.pth
|
167 |
+
if exist "%~dp0assets\pretrained_v2\G40k.pth" (echo download successful.) else (echo please try again!
|
168 |
+
echo=)
|
169 |
+
)
|
170 |
+
echo checking G48k.pth
|
171 |
+
if exist "%~dp0assets\pretrained\G48k.pth" (
|
172 |
+
echo G48k.pth in .\assets\pretrained checked.
|
173 |
+
echo=
|
174 |
+
) else (
|
175 |
+
echo failed. starting download from huggingface.
|
176 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/G48k.pth -d %~dp0assets\pretrained -o G48k.pth
|
177 |
+
if exist "%~dp0assets\pretrained\G48k.pth" (echo download successful.) else (echo please try again!
|
178 |
+
echo=)
|
179 |
+
)
|
180 |
+
|
181 |
+
echo checking %d32%
|
182 |
+
if exist "%~dp0assets\pretrained\%d32%" (
|
183 |
+
echo %d32% in .\assets\pretrained checked.
|
184 |
+
echo=
|
185 |
+
) else (
|
186 |
+
echo failed. starting download from huggingface.
|
187 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dld32% -d %~dp0assets\pretrained -o %d32%
|
188 |
+
if exist "%~dp0assets\pretrained\%d32%" (echo download successful.) else (echo please try again!
|
189 |
+
echo=)
|
190 |
+
)
|
191 |
+
echo checking %d40%
|
192 |
+
if exist "%~dp0assets\pretrained\%d40%" (
|
193 |
+
echo %d40% in .\assets\pretrained checked.
|
194 |
+
echo=
|
195 |
+
) else (
|
196 |
+
echo failed. starting download from huggingface.
|
197 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dld40% -d %~dp0assets\pretrained -o %d40%
|
198 |
+
if exist "%~dp0assets\pretrained\%d40%" (echo download successful.) else (echo please try again!
|
199 |
+
echo=)
|
200 |
+
)
|
201 |
+
echo checking %d40v2%
|
202 |
+
if exist "%~dp0assets\pretrained_v2\%d40v2%" (
|
203 |
+
echo %d40v2% in .\assets\pretrained_v2 checked.
|
204 |
+
echo=
|
205 |
+
) else (
|
206 |
+
echo failed. starting download from huggingface.
|
207 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dld40v2% -d %~dp0assets\pretrained_v2 -o %d40v2%
|
208 |
+
if exist "%~dp0assets\pretrained_v2\%d40v2%" (echo download successful.) else (echo please try again!
|
209 |
+
echo=)
|
210 |
+
)
|
211 |
+
echo checking %d48%
|
212 |
+
if exist "%~dp0assets\pretrained\%d48%" (
|
213 |
+
echo %d48% in .\assets\pretrained checked.
|
214 |
+
echo=
|
215 |
+
) else (
|
216 |
+
echo failed. starting download from huggingface.
|
217 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dld48% -d %~dp0assets\pretrained -o %d48%
|
218 |
+
if exist "%~dp0assets\pretrained\%d48%" (echo download successful.) else (echo please try again!
|
219 |
+
echo=)
|
220 |
+
)
|
221 |
+
echo checking %g32%
|
222 |
+
if exist "%~dp0assets\pretrained\%g32%" (
|
223 |
+
echo %g32% in .\assets\pretrained checked.
|
224 |
+
echo=
|
225 |
+
) else (
|
226 |
+
echo failed. starting download from huggingface.
|
227 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlg32% -d %~dp0assets\pretrained -o %g32%
|
228 |
+
if exist "%~dp0assets\pretrained\%g32%" (echo download successful.) else (echo please try again!
|
229 |
+
echo=)
|
230 |
+
)
|
231 |
+
echo checking %g40%
|
232 |
+
if exist "%~dp0assets\pretrained\%g40%" (
|
233 |
+
echo %g40% in .\assets\pretrained checked.
|
234 |
+
echo=
|
235 |
+
) else (
|
236 |
+
echo failed. starting download from huggingface.
|
237 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlg40% -d %~dp0assets\pretrained -o %g40%
|
238 |
+
if exist "%~dp0assets\pretrained\%g40%" (echo download successful.) else (echo please try again!
|
239 |
+
echo=)
|
240 |
+
)
|
241 |
+
echo checking %g40v2%
|
242 |
+
if exist "%~dp0assets\pretrained_v2\%g40v2%" (
|
243 |
+
echo %g40v2% in .\assets\pretrained_v2 checked.
|
244 |
+
echo=
|
245 |
+
) else (
|
246 |
+
echo failed. starting download from huggingface.
|
247 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlg40v2% -d %~dp0assets\pretrained_v2 -o %g40v2%
|
248 |
+
if exist "%~dp0assets\pretrained_v2\%g40v2%" (echo download successful.) else (echo please try again!
|
249 |
+
echo=)
|
250 |
+
)
|
251 |
+
echo checking %g48%
|
252 |
+
if exist "%~dp0assets\pretrained\%g48%" (
|
253 |
+
echo %g48% in .\assets\pretrained checked.
|
254 |
+
echo=
|
255 |
+
) else (
|
256 |
+
echo failed. starting download from huggingface.
|
257 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlg48% -d %~dp0assets\pretrained -o %g48%
|
258 |
+
if exist "%~dp0assets\pretrained\%g48%" (echo download successful.) else (echo please try again!
|
259 |
+
echo=)
|
260 |
+
)
|
261 |
+
|
262 |
+
echo checking %hp2_all%
|
263 |
+
if exist "%~dp0assets\uvr5_weights\%hp2_all%" (
|
264 |
+
echo %hp2_all% in .\assets\uvr5_weights checked.
|
265 |
+
echo=
|
266 |
+
) else (
|
267 |
+
echo failed. starting download from huggingface.
|
268 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlhp2_all% -d %~dp0assets\uvr5_weights -o %hp2_all%
|
269 |
+
if exist "%~dp0assets\uvr5_weights\%hp2_all%" (echo download successful.) else (echo please try again!
|
270 |
+
echo=)
|
271 |
+
)
|
272 |
+
echo checking %hp3_all%
|
273 |
+
if exist "%~dp0assets\uvr5_weights\%hp3_all%" (
|
274 |
+
echo %hp3_all% in .\assets\uvr5_weights checked.
|
275 |
+
echo=
|
276 |
+
) else (
|
277 |
+
echo failed. starting download from huggingface.
|
278 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlhp3_all% -d %~dp0assets\uvr5_weights -o %hp3_all%
|
279 |
+
if exist "%~dp0assets\uvr5_weights\%hp3_all%" (echo download successful.) else (echo please try again!
|
280 |
+
echo=)
|
281 |
+
)
|
282 |
+
echo checking %hp5_only%
|
283 |
+
if exist "%~dp0assets\uvr5_weights\%hp5_only%" (
|
284 |
+
echo %hp5_only% in .\assets\uvr5_weights checked.
|
285 |
+
echo=
|
286 |
+
) else (
|
287 |
+
echo failed. starting download from huggingface.
|
288 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlhp5_only% -d %~dp0assets\uvr5_weights -o %hp5_only%
|
289 |
+
if exist "%~dp0assets\uvr5_weights\%hp5_only%" (echo download successful.) else (echo please try again!
|
290 |
+
echo=)
|
291 |
+
)
|
292 |
+
echo checking %VR_DeEchoAggressive%
|
293 |
+
if exist "%~dp0assets\uvr5_weights\%VR_DeEchoAggressive%" (
|
294 |
+
echo %VR_DeEchoAggressive% in .\assets\uvr5_weights checked.
|
295 |
+
echo=
|
296 |
+
) else (
|
297 |
+
echo failed. starting download from huggingface.
|
298 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlVR_DeEchoAggressive% -d %~dp0assets\uvr5_weights -o %VR_DeEchoAggressive%
|
299 |
+
if exist "%~dp0assets\uvr5_weights\%VR_DeEchoAggressive%" (echo download successful.) else (echo please try again!
|
300 |
+
echo=)
|
301 |
+
)
|
302 |
+
echo checking %VR_DeEchoDeReverb%
|
303 |
+
if exist "%~dp0assets\uvr5_weights\%VR_DeEchoDeReverb%" (
|
304 |
+
echo %VR_DeEchoDeReverb% in .\assets\uvr5_weights checked.
|
305 |
+
echo=
|
306 |
+
) else (
|
307 |
+
echo failed. starting download from huggingface.
|
308 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlVR_DeEchoDeReverb% -d %~dp0assets\uvr5_weights -o %VR_DeEchoDeReverb%
|
309 |
+
if exist "%~dp0assets\uvr5_weights\%VR_DeEchoDeReverb%" (echo download successful.) else (echo please try again!
|
310 |
+
echo=)
|
311 |
+
)
|
312 |
+
echo checking %VR_DeEchoNormal%
|
313 |
+
if exist "%~dp0assets\uvr5_weights\%VR_DeEchoNormal%" (
|
314 |
+
echo %VR_DeEchoNormal% in .\assets\uvr5_weights checked.
|
315 |
+
echo=
|
316 |
+
) else (
|
317 |
+
echo failed. starting download from huggingface.
|
318 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlVR_DeEchoNormal% -d %~dp0assets\uvr5_weights -o %VR_DeEchoNormal%
|
319 |
+
if exist "%~dp0assets\uvr5_weights\%VR_DeEchoNormal%" (echo download successful.) else (echo please try again!
|
320 |
+
echo=)
|
321 |
+
)
|
322 |
+
echo checking %onnx_dereverb%
|
323 |
+
if exist "%~dp0assets\uvr5_weights\onnx_dereverb_By_FoxJoy\%onnx_dereverb%" (
|
324 |
+
echo %onnx_dereverb% in .\assets\uvr5_weights\onnx_dereverb_By_FoxJoy checked.
|
325 |
+
echo=
|
326 |
+
) else (
|
327 |
+
echo failed. starting download from huggingface.
|
328 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlonnx_dereverb% -d %~dp0assets\uvr5_weights\onnx_dereverb_By_FoxJoy -o %onnx_dereverb%
|
329 |
+
if exist "%~dp0assets\uvr5_weights\onnx_dereverb_By_FoxJoy\%onnx_dereverb%" (echo download successful.) else (echo please try again!
|
330 |
+
echo=)
|
331 |
+
)
|
332 |
+
|
333 |
+
echo checking %hb%
|
334 |
+
if exist "%~dp0assets\hubert\%hb%" (
|
335 |
+
echo %hb% in .\assets\hubert\pretrained checked.
|
336 |
+
echo=
|
337 |
+
) else (
|
338 |
+
echo failed. starting download from huggingface.
|
339 |
+
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlhb% -d %~dp0assets\hubert\ -o %hb%
|
340 |
+
if exist "%~dp0assets\hubert\%hb%" (echo download successful.) else (echo please try again!
|
341 |
+
echo=)
|
342 |
+
)
|
343 |
+
|
344 |
+
echo required files check finished.
|
345 |
+
echo envfiles check complete.
|
346 |
+
pause
|
347 |
+
:end
|
348 |
+
del flag.txt
|
tools/dlmodels.sh
ADDED
@@ -0,0 +1,566 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/bin/bash
|
2 |
+
|
3 |
+
echo working dir is $(pwd)
|
4 |
+
echo downloading requirement aria2 check.
|
5 |
+
|
6 |
+
if command -v aria2c &> /dev/null
|
7 |
+
then
|
8 |
+
echo "aria2c command found"
|
9 |
+
else
|
10 |
+
echo failed. please install aria2
|
11 |
+
sleep 5
|
12 |
+
exit 1
|
13 |
+
fi
|
14 |
+
|
15 |
+
d32="f0D32k.pth"
|
16 |
+
d40="f0D40k.pth"
|
17 |
+
d48="f0D48k.pth"
|
18 |
+
g32="f0G32k.pth"
|
19 |
+
g40="f0G40k.pth"
|
20 |
+
g48="f0G48k.pth"
|
21 |
+
|
22 |
+
d40v2="f0D40k.pth"
|
23 |
+
g40v2="f0G40k.pth"
|
24 |
+
|
25 |
+
dld32="https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D32k.pth"
|
26 |
+
dld40="https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D40k.pth"
|
27 |
+
dld48="https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D48k.pth"
|
28 |
+
dlg32="https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G32k.pth"
|
29 |
+
dlg40="https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G40k.pth"
|
30 |
+
dlg48="https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G48k.pth"
|
31 |
+
|
32 |
+
dld40v2="https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0D40k.pth"
|
33 |
+
dlg40v2="https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0G40k.pth"
|
34 |
+
|
35 |
+
hp2_all="HP2_all_vocals.pth"
|
36 |
+
hp3_all="HP3_all_vocals.pth"
|
37 |
+
hp5_only="HP5_only_main_vocal.pth"
|
38 |
+
VR_DeEchoAggressive="VR-DeEchoAggressive.pth"
|
39 |
+
VR_DeEchoDeReverb="VR-DeEchoDeReverb.pth"
|
40 |
+
VR_DeEchoNormal="VR-DeEchoNormal.pth"
|
41 |
+
onnx_dereverb="vocals.onnx"
|
42 |
+
rmvpe="rmvpe.pt"
|
43 |
+
|
44 |
+
dlhp2_all="https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP2_all_vocals.pth"
|
45 |
+
dlhp3_all="https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP3_all_vocals.pth"
|
46 |
+
dlhp5_only="https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP5_only_main_vocal.pth"
|
47 |
+
dlVR_DeEchoAggressive="https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/VR-DeEchoAggressive.pth"
|
48 |
+
dlVR_DeEchoDeReverb="https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/VR-DeEchoDeReverb.pth"
|
49 |
+
dlVR_DeEchoNormal="https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/VR-DeEchoNormal.pth"
|
50 |
+
dlonnx_dereverb="https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/onnx_dereverb_By_FoxJoy/vocals.onnx"
|
51 |
+
dlrmvpe="https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/rmvpe.pt"
|
52 |
+
|
53 |
+
hb="hubert_base.pt"
|
54 |
+
|
55 |
+
dlhb="https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/hubert_base.pt"
|
56 |
+
|
57 |
+
echo dir check start.
|
58 |
+
|
59 |
+
if [ -d "./assets/pretrained" ]; then
|
60 |
+
echo dir ./assets/pretrained checked.
|
61 |
+
else
|
62 |
+
echo failed. generating dir ./assets/pretrained.
|
63 |
+
mkdir pretrained
|
64 |
+
fi
|
65 |
+
|
66 |
+
if [ -d "./assets/pretrained_v2" ]; then
|
67 |
+
echo dir ./assets/pretrained_v2 checked.
|
68 |
+
else
|
69 |
+
echo failed. generating dir ./assets/pretrained_v2.
|
70 |
+
mkdir pretrained_v2
|
71 |
+
fi
|
72 |
+
|
73 |
+
if [ -d "./assets/uvr5_weights" ]; then
|
74 |
+
echo dir ./assets/uvr5_weights checked.
|
75 |
+
else
|
76 |
+
echo failed. generating dir ./assets/uvr5_weights.
|
77 |
+
mkdir uvr5_weights
|
78 |
+
fi
|
79 |
+
|
80 |
+
if [ -d "./assets/uvr5_weights/onnx_dereverb_By_FoxJoy" ]; then
|
81 |
+
echo dir ./assets/uvr5_weights/onnx_dereverb_By_FoxJoy checked.
|
82 |
+
else
|
83 |
+
echo failed. generating dir ./assets/uvr5_weights/onnx_dereverb_By_FoxJoy.
|
84 |
+
mkdir uvr5_weights/onnx_dereverb_By_FoxJoy
|
85 |
+
fi
|
86 |
+
|
87 |
+
echo dir check finished.
|
88 |
+
|
89 |
+
echo required files check start.
|
90 |
+
|
91 |
+
echo checking D32k.pth
|
92 |
+
if [ -f "./assets/pretrained/D32k.pth" ]; then
|
93 |
+
echo D32k.pth in ./assets/pretrained checked.
|
94 |
+
else
|
95 |
+
echo failed. starting download from huggingface.
|
96 |
+
if command -v aria2c &> /dev/null; then
|
97 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/D32k.pth -d ./assets/pretrained -o D32k.pth
|
98 |
+
if [ -f "./assets/pretrained/D32k.pth" ]; then
|
99 |
+
echo download successful.
|
100 |
+
else
|
101 |
+
echo please try again!
|
102 |
+
exit 1
|
103 |
+
fi
|
104 |
+
else
|
105 |
+
echo aria2c command not found. Please install aria2c and try again.
|
106 |
+
exit 1
|
107 |
+
fi
|
108 |
+
fi
|
109 |
+
|
110 |
+
echo checking D40k.pth
|
111 |
+
if [ -f "./assets/pretrained/D40k.pth" ]; then
|
112 |
+
echo D40k.pth in ./assets/pretrained checked.
|
113 |
+
else
|
114 |
+
echo failed. starting download from huggingface.
|
115 |
+
if command -v aria2c &> /dev/null; then
|
116 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/D40k.pth -d ./assets/pretrained -o D40k.pth
|
117 |
+
if [ -f "./assets/pretrained/D40k.pth" ]; then
|
118 |
+
echo download successful.
|
119 |
+
else
|
120 |
+
echo please try again!
|
121 |
+
exit 1
|
122 |
+
fi
|
123 |
+
else
|
124 |
+
echo aria2c command not found. Please install aria2c and try again.
|
125 |
+
exit 1
|
126 |
+
fi
|
127 |
+
fi
|
128 |
+
|
129 |
+
echo checking D40k.pth
|
130 |
+
if [ -f "./assets/pretrained_v2/D40k.pth" ]; then
|
131 |
+
echo D40k.pth in ./assets/pretrained_v2 checked.
|
132 |
+
else
|
133 |
+
echo failed. starting download from huggingface.
|
134 |
+
if command -v aria2c &> /dev/null; then
|
135 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/D40k.pth -d ./assets/pretrained_v2 -o D40k.pth
|
136 |
+
if [ -f "./assets/pretrained_v2/D40k.pth" ]; then
|
137 |
+
echo download successful.
|
138 |
+
else
|
139 |
+
echo please try again!
|
140 |
+
exit 1
|
141 |
+
fi
|
142 |
+
else
|
143 |
+
echo aria2c command not found. Please install aria2c and try again.
|
144 |
+
exit 1
|
145 |
+
fi
|
146 |
+
fi
|
147 |
+
|
148 |
+
echo checking D48k.pth
|
149 |
+
if [ -f "./assets/pretrained/D48k.pth" ]; then
|
150 |
+
echo D48k.pth in ./assets/pretrained checked.
|
151 |
+
else
|
152 |
+
echo failed. starting download from huggingface.
|
153 |
+
if command -v aria2c &> /dev/null; then
|
154 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/D48k.pth -d ./assets/pretrained -o D48k.pth
|
155 |
+
if [ -f "./assets/pretrained/D48k.pth" ]; then
|
156 |
+
echo download successful.
|
157 |
+
else
|
158 |
+
echo please try again!
|
159 |
+
exit 1
|
160 |
+
fi
|
161 |
+
else
|
162 |
+
echo aria2c command not found. Please install aria2c and try again.
|
163 |
+
exit 1
|
164 |
+
fi
|
165 |
+
fi
|
166 |
+
|
167 |
+
echo checking G32k.pth
|
168 |
+
if [ -f "./assets/pretrained/G32k.pth" ]; then
|
169 |
+
echo G32k.pth in ./assets/pretrained checked.
|
170 |
+
else
|
171 |
+
echo failed. starting download from huggingface.
|
172 |
+
if command -v aria2c &> /dev/null; then
|
173 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/G32k.pth -d ./assets/pretrained -o G32k.pth
|
174 |
+
if [ -f "./assets/pretrained/G32k.pth" ]; then
|
175 |
+
echo download successful.
|
176 |
+
else
|
177 |
+
echo please try again!
|
178 |
+
exit 1
|
179 |
+
fi
|
180 |
+
else
|
181 |
+
echo aria2c command not found. Please install aria2c and try again.
|
182 |
+
exit 1
|
183 |
+
fi
|
184 |
+
fi
|
185 |
+
|
186 |
+
echo checking G40k.pth
|
187 |
+
if [ -f "./assets/pretrained/G40k.pth" ]; then
|
188 |
+
echo G40k.pth in ./assets/pretrained checked.
|
189 |
+
else
|
190 |
+
echo failed. starting download from huggingface.
|
191 |
+
if command -v aria2c &> /dev/null; then
|
192 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/G40k.pth -d ./assets/pretrained -o G40k.pth
|
193 |
+
if [ -f "./assets/pretrained/G40k.pth" ]; then
|
194 |
+
echo download successful.
|
195 |
+
else
|
196 |
+
echo please try again!
|
197 |
+
exit 1
|
198 |
+
fi
|
199 |
+
else
|
200 |
+
echo aria2c command not found. Please install aria2c and try again.
|
201 |
+
exit 1
|
202 |
+
fi
|
203 |
+
fi
|
204 |
+
|
205 |
+
echo checking G40k.pth
|
206 |
+
if [ -f "./assets/pretrained_v2/G40k.pth" ]; then
|
207 |
+
echo G40k.pth in ./assets/pretrained_v2 checked.
|
208 |
+
else
|
209 |
+
echo failed. starting download from huggingface.
|
210 |
+
if command -v aria2c &> /dev/null; then
|
211 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/G40k.pth -d ./assets/pretrained_v2 -o G40k.pth
|
212 |
+
if [ -f "./assets/pretrained_v2/G40k.pth" ]; then
|
213 |
+
echo download successful.
|
214 |
+
else
|
215 |
+
echo please try again!
|
216 |
+
exit 1
|
217 |
+
fi
|
218 |
+
else
|
219 |
+
echo aria2c command not found. Please install aria2c and try again.
|
220 |
+
exit 1
|
221 |
+
fi
|
222 |
+
fi
|
223 |
+
|
224 |
+
echo checking G48k.pth
|
225 |
+
if [ -f "./assets/pretrained/G48k.pth" ]; then
|
226 |
+
echo G48k.pth in ./assets/pretrained checked.
|
227 |
+
else
|
228 |
+
echo failed. starting download from huggingface.
|
229 |
+
if command -v aria2c &> /dev/null; then
|
230 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/G48k.pth -d ./assets/pretrained -o G48k.pth
|
231 |
+
if [ -f "./assets/pretrained/G48k.pth" ]; then
|
232 |
+
echo download successful.
|
233 |
+
else
|
234 |
+
echo please try again!
|
235 |
+
exit 1
|
236 |
+
fi
|
237 |
+
else
|
238 |
+
echo aria2c command not found. Please install aria2c and try again.
|
239 |
+
exit 1
|
240 |
+
fi
|
241 |
+
fi
|
242 |
+
|
243 |
+
echo checking $d32
|
244 |
+
if [ -f "./assets/pretrained/$d32" ]; then
|
245 |
+
echo $d32 in ./assets/pretrained checked.
|
246 |
+
else
|
247 |
+
echo failed. starting download from huggingface.
|
248 |
+
if command -v aria2c &> /dev/null; then
|
249 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M $dld32 -d ./assets/pretrained -o $d32
|
250 |
+
if [ -f "./assets/pretrained/$d32" ]; then
|
251 |
+
echo download successful.
|
252 |
+
else
|
253 |
+
echo please try again!
|
254 |
+
exit 1
|
255 |
+
fi
|
256 |
+
else
|
257 |
+
echo aria2c command not found. Please install aria2c and try again.
|
258 |
+
exit 1
|
259 |
+
fi
|
260 |
+
fi
|
261 |
+
|
262 |
+
echo checking $d40
|
263 |
+
if [ -f "./assets/pretrained/$d40" ]; then
|
264 |
+
echo $d40 in ./assets/pretrained checked.
|
265 |
+
else
|
266 |
+
echo failed. starting download from huggingface.
|
267 |
+
if command -v aria2c &> /dev/null; then
|
268 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M $dld40 -d ./assets/pretrained -o $d40
|
269 |
+
if [ -f "./assets/pretrained/$d40" ]; then
|
270 |
+
echo download successful.
|
271 |
+
else
|
272 |
+
echo please try again!
|
273 |
+
exit 1
|
274 |
+
fi
|
275 |
+
else
|
276 |
+
echo aria2c command not found. Please install aria2c and try again.
|
277 |
+
exit 1
|
278 |
+
fi
|
279 |
+
fi
|
280 |
+
|
281 |
+
echo checking $d40v2
|
282 |
+
if [ -f "./assets/pretrained_v2/$d40v2" ]; then
|
283 |
+
echo $d40v2 in ./assets/pretrained_v2 checked.
|
284 |
+
else
|
285 |
+
echo failed. starting download from huggingface.
|
286 |
+
if command -v aria2c &> /dev/null; then
|
287 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M $dld40v2 -d ./assets/pretrained_v2 -o $d40v2
|
288 |
+
if [ -f "./assets/pretrained_v2/$d40v2" ]; then
|
289 |
+
echo download successful.
|
290 |
+
else
|
291 |
+
echo please try again!
|
292 |
+
exit 1
|
293 |
+
fi
|
294 |
+
else
|
295 |
+
echo aria2c command not found. Please install aria2c and try again.
|
296 |
+
exit 1
|
297 |
+
fi
|
298 |
+
fi
|
299 |
+
|
300 |
+
echo checking $d48
|
301 |
+
if [ -f "./assets/pretrained/$d48" ]; then
|
302 |
+
echo $d48 in ./assets/pretrained checked.
|
303 |
+
else
|
304 |
+
echo failed. starting download from huggingface.
|
305 |
+
if command -v aria2c &> /dev/null; then
|
306 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M $dld48 -d ./assets/pretrained -o $d48
|
307 |
+
if [ -f "./assets/pretrained/$d48" ]; then
|
308 |
+
echo download successful.
|
309 |
+
else
|
310 |
+
echo please try again!
|
311 |
+
exit 1
|
312 |
+
fi
|
313 |
+
else
|
314 |
+
echo aria2c command not found. Please install aria2c and try again.
|
315 |
+
exit 1
|
316 |
+
fi
|
317 |
+
fi
|
318 |
+
|
319 |
+
echo checking $g32
|
320 |
+
if [ -f "./assets/pretrained/$g32" ]; then
|
321 |
+
echo $g32 in ./assets/pretrained checked.
|
322 |
+
else
|
323 |
+
echo failed. starting download from huggingface.
|
324 |
+
if command -v aria2c &> /dev/null; then
|
325 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M $dlg32 -d ./assets/pretrained -o $g32
|
326 |
+
if [ -f "./assets/pretrained/$g32" ]; then
|
327 |
+
echo download successful.
|
328 |
+
else
|
329 |
+
echo please try again!
|
330 |
+
exit 1
|
331 |
+
fi
|
332 |
+
else
|
333 |
+
echo aria2c command not found. Please install aria2c and try again.
|
334 |
+
exit 1
|
335 |
+
fi
|
336 |
+
fi
|
337 |
+
|
338 |
+
echo checking $g40
|
339 |
+
if [ -f "./assets/pretrained/$g40" ]; then
|
340 |
+
echo $g40 in ./assets/pretrained checked.
|
341 |
+
else
|
342 |
+
echo failed. starting download from huggingface.
|
343 |
+
if command -v aria2c &> /dev/null; then
|
344 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M $dlg40 -d ./assets/pretrained -o $g40
|
345 |
+
if [ -f "./assets/pretrained/$g40" ]; then
|
346 |
+
echo download successful.
|
347 |
+
else
|
348 |
+
echo please try again!
|
349 |
+
exit 1
|
350 |
+
fi
|
351 |
+
else
|
352 |
+
echo aria2c command not found. Please install aria2c and try again.
|
353 |
+
exit 1
|
354 |
+
fi
|
355 |
+
fi
|
356 |
+
|
357 |
+
echo checking $g40v2
|
358 |
+
if [ -f "./assets/pretrained_v2/$g40v2" ]; then
|
359 |
+
echo $g40v2 in ./assets/pretrained_v2 checked.
|
360 |
+
else
|
361 |
+
echo failed. starting download from huggingface.
|
362 |
+
if command -v aria2c &> /dev/null; then
|
363 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M $dlg40v2 -d ./assets/pretrained_v2 -o $g40v2
|
364 |
+
if [ -f "./assets/pretrained_v2/$g40v2" ]; then
|
365 |
+
echo download successful.
|
366 |
+
else
|
367 |
+
echo please try again!
|
368 |
+
exit 1
|
369 |
+
fi
|
370 |
+
else
|
371 |
+
echo aria2c command not found. Please install aria2c and try again.
|
372 |
+
exit 1
|
373 |
+
fi
|
374 |
+
fi
|
375 |
+
|
376 |
+
echo checking $g48
|
377 |
+
if [ -f "./assets/pretrained/$g48" ]; then
|
378 |
+
echo $g48 in ./assets/pretrained checked.
|
379 |
+
else
|
380 |
+
echo failed. starting download from huggingface.
|
381 |
+
if command -v aria2c &> /dev/null; then
|
382 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M $dlg48 -d ./assets/pretrained -o $g48
|
383 |
+
if [ -f "./assets/pretrained/$g48" ]; then
|
384 |
+
echo download successful.
|
385 |
+
else
|
386 |
+
echo please try again!
|
387 |
+
exit 1
|
388 |
+
fi
|
389 |
+
else
|
390 |
+
echo aria2c command not found. Please install aria2c and try again.
|
391 |
+
exit 1
|
392 |
+
fi
|
393 |
+
fi
|
394 |
+
|
395 |
+
echo checking $hp2_all
|
396 |
+
if [ -f "./assets/uvr5_weights/$hp2_all" ]; then
|
397 |
+
echo $hp2_all in ./assets/uvr5_weights checked.
|
398 |
+
else
|
399 |
+
echo failed. starting download from huggingface.
|
400 |
+
if command -v aria2c &> /dev/null; then
|
401 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M $dlhp2_all -d ./assets/uvr5_weights -o $hp2_all
|
402 |
+
if [ -f "./assets/uvr5_weights/$hp2_all" ]; then
|
403 |
+
echo download successful.
|
404 |
+
else
|
405 |
+
echo please try again!
|
406 |
+
exit 1
|
407 |
+
fi
|
408 |
+
else
|
409 |
+
echo aria2c command not found. Please install aria2c and try again.
|
410 |
+
exit 1
|
411 |
+
fi
|
412 |
+
fi
|
413 |
+
|
414 |
+
echo checking $hp3_all
|
415 |
+
if [ -f "./assets/uvr5_weights/$hp3_all" ]; then
|
416 |
+
echo $hp3_all in ./assets/uvr5_weights checked.
|
417 |
+
else
|
418 |
+
echo failed. starting download from huggingface.
|
419 |
+
if command -v aria2c &> /dev/null; then
|
420 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M $dlhp3_all -d ./assets/uvr5_weights -o $hp3_all
|
421 |
+
if [ -f "./assets/uvr5_weights/$hp3_all" ]; then
|
422 |
+
echo download successful.
|
423 |
+
else
|
424 |
+
echo please try again!
|
425 |
+
exit 1
|
426 |
+
fi
|
427 |
+
else
|
428 |
+
echo aria2c command not found. Please install aria2c and try again.
|
429 |
+
exit 1
|
430 |
+
fi
|
431 |
+
fi
|
432 |
+
|
433 |
+
echo checking $hp5_only
|
434 |
+
if [ -f "./assets/uvr5_weights/$hp5_only" ]; then
|
435 |
+
echo $hp5_only in ./assets/uvr5_weights checked.
|
436 |
+
else
|
437 |
+
echo failed. starting download from huggingface.
|
438 |
+
if command -v aria2c &> /dev/null; then
|
439 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M $dlhp5_only -d ./assets/uvr5_weights -o $hp5_only
|
440 |
+
if [ -f "./assets/uvr5_weights/$hp5_only" ]; then
|
441 |
+
echo download successful.
|
442 |
+
else
|
443 |
+
echo please try again!
|
444 |
+
exit 1
|
445 |
+
fi
|
446 |
+
else
|
447 |
+
echo aria2c command not found. Please install aria2c and try again.
|
448 |
+
exit 1
|
449 |
+
fi
|
450 |
+
fi
|
451 |
+
|
452 |
+
echo checking $VR_DeEchoAggressive
|
453 |
+
if [ -f "./assets/uvr5_weights/$VR_DeEchoAggressive" ]; then
|
454 |
+
echo $VR_DeEchoAggressive in ./assets/uvr5_weights checked.
|
455 |
+
else
|
456 |
+
echo failed. starting download from huggingface.
|
457 |
+
if command -v aria2c &> /dev/null; then
|
458 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M $dlVR_DeEchoAggressive -d ./assets/uvr5_weights -o $VR_DeEchoAggressive
|
459 |
+
if [ -f "./assets/uvr5_weights/$VR_DeEchoAggressive" ]; then
|
460 |
+
echo download successful.
|
461 |
+
else
|
462 |
+
echo please try again!
|
463 |
+
exit 1
|
464 |
+
fi
|
465 |
+
else
|
466 |
+
echo aria2c command not found. Please install aria2c and try again.
|
467 |
+
exit 1
|
468 |
+
fi
|
469 |
+
fi
|
470 |
+
|
471 |
+
echo checking $VR_DeEchoDeReverb
|
472 |
+
if [ -f "./assets/uvr5_weights/$VR_DeEchoDeReverb" ]; then
|
473 |
+
echo $VR_DeEchoDeReverb in ./assets/uvr5_weights checked.
|
474 |
+
else
|
475 |
+
echo failed. starting download from huggingface.
|
476 |
+
if command -v aria2c &> /dev/null; then
|
477 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M $dlVR_DeEchoDeReverb -d ./assets/uvr5_weights -o $VR_DeEchoDeReverb
|
478 |
+
if [ -f "./assets/uvr5_weights/$VR_DeEchoDeReverb" ]; then
|
479 |
+
echo download successful.
|
480 |
+
else
|
481 |
+
echo please try again!
|
482 |
+
exit 1
|
483 |
+
fi
|
484 |
+
else
|
485 |
+
echo aria2c command not found. Please install aria2c and try again.
|
486 |
+
exit 1
|
487 |
+
fi
|
488 |
+
fi
|
489 |
+
|
490 |
+
echo checking $VR_DeEchoNormal
|
491 |
+
if [ -f "./assets/uvr5_weights/$VR_DeEchoNormal" ]; then
|
492 |
+
echo $VR_DeEchoNormal in ./assets/uvr5_weights checked.
|
493 |
+
else
|
494 |
+
echo failed. starting download from huggingface.
|
495 |
+
if command -v aria2c &> /dev/null; then
|
496 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M $dlVR_DeEchoNormal -d ./assets/uvr5_weights -o $VR_DeEchoNormal
|
497 |
+
if [ -f "./assets/uvr5_weights/$VR_DeEchoNormal" ]; then
|
498 |
+
echo download successful.
|
499 |
+
else
|
500 |
+
echo please try again!
|
501 |
+
exit 1
|
502 |
+
fi
|
503 |
+
else
|
504 |
+
echo aria2c command not found. Please install aria2c and try again.
|
505 |
+
exit 1
|
506 |
+
fi
|
507 |
+
fi
|
508 |
+
|
509 |
+
echo checking $onnx_dereverb
|
510 |
+
if [ -f "./assets/uvr5_weights/onnx_dereverb_By_FoxJoy/$onnx_dereverb" ]; then
|
511 |
+
echo $onnx_dereverb in ./assets/uvr5_weights/onnx_dereverb_By_FoxJoy checked.
|
512 |
+
else
|
513 |
+
echo failed. starting download from huggingface.
|
514 |
+
if command -v aria2c &> /dev/null; then
|
515 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M $dlonnx_dereverb -d ./assets/uvr5_weights/onnx_dereverb_By_FoxJoy -o $onnx_dereverb
|
516 |
+
if [ -f "./assets/uvr5_weights/onnx_dereverb_By_FoxJoy/$onnx_dereverb" ]; then
|
517 |
+
echo download successful.
|
518 |
+
else
|
519 |
+
echo please try again!
|
520 |
+
exit 1
|
521 |
+
fi
|
522 |
+
else
|
523 |
+
echo aria2c command not found. Please install aria2c and try again.
|
524 |
+
exit 1
|
525 |
+
fi
|
526 |
+
fi
|
527 |
+
|
528 |
+
echo checking $rmvpe
|
529 |
+
if [ -f "./assets/rmvpe/$rmvpe" ]; then
|
530 |
+
echo $rmvpe in ./assets/rmvpe checked.
|
531 |
+
else
|
532 |
+
echo failed. starting download from huggingface.
|
533 |
+
if command -v aria2c &> /dev/null; then
|
534 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M $dlrmvpe -d ./assets/rmvpe -o $rmvpe
|
535 |
+
if [ -f "./assets/rmvpe/$rmvpe" ]; then
|
536 |
+
echo download successful.
|
537 |
+
else
|
538 |
+
echo please try again!
|
539 |
+
exit 1
|
540 |
+
fi
|
541 |
+
else
|
542 |
+
echo aria2c command not found. Please install aria2c and try again.
|
543 |
+
exit 1
|
544 |
+
fi
|
545 |
+
fi
|
546 |
+
|
547 |
+
echo checking $hb
|
548 |
+
if [ -f "./assets/hubert/$hb" ]; then
|
549 |
+
echo $hb in ./assets/hubert/pretrained checked.
|
550 |
+
else
|
551 |
+
echo failed. starting download from huggingface.
|
552 |
+
if command -v aria2c &> /dev/null; then
|
553 |
+
aria2c --console-log-level=error -c -x 16 -s 16 -k 1M $dlhb -d ./assets/hubert/ -o $hb
|
554 |
+
if [ -f "./assets/hubert/$hb" ]; then
|
555 |
+
echo download successful.
|
556 |
+
else
|
557 |
+
echo please try again!
|
558 |
+
exit 1
|
559 |
+
fi
|
560 |
+
else
|
561 |
+
echo aria2c command not found. Please install aria2c and try again.
|
562 |
+
exit 1
|
563 |
+
fi
|
564 |
+
fi
|
565 |
+
|
566 |
+
echo required files check finished.
|
tools/download_models.py
ADDED
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from pathlib import Path
|
3 |
+
import requests
|
4 |
+
|
5 |
+
RVC_DOWNLOAD_LINK = "https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/"
|
6 |
+
|
7 |
+
BASE_DIR = Path(__file__).resolve().parent.parent
|
8 |
+
|
9 |
+
|
10 |
+
def dl_model(link, model_name, dir_name):
|
11 |
+
with requests.get(f"{link}{model_name}") as r:
|
12 |
+
r.raise_for_status()
|
13 |
+
os.makedirs(os.path.dirname(dir_name / model_name), exist_ok=True)
|
14 |
+
with open(dir_name / model_name, "wb") as f:
|
15 |
+
for chunk in r.iter_content(chunk_size=8192):
|
16 |
+
f.write(chunk)
|
17 |
+
|
18 |
+
|
19 |
+
if __name__ == "__main__":
|
20 |
+
print("Downloading hubert_base.pt...")
|
21 |
+
dl_model(RVC_DOWNLOAD_LINK, "hubert_base.pt", BASE_DIR / "assets/hubert")
|
22 |
+
print("Downloading rmvpe.pt...")
|
23 |
+
dl_model(RVC_DOWNLOAD_LINK, "rmvpe.pt", BASE_DIR / "assets/rmvpe")
|
24 |
+
print("Downloading vocals.onnx...")
|
25 |
+
dl_model(
|
26 |
+
RVC_DOWNLOAD_LINK + "uvr5_weights/onnx_dereverb_By_FoxJoy/",
|
27 |
+
"vocals.onnx",
|
28 |
+
BASE_DIR / "assets/uvr5_weights/onnx_dereverb_By_FoxJoy",
|
29 |
+
)
|
30 |
+
|
31 |
+
rvc_models_dir = BASE_DIR / "assets/pretrained"
|
32 |
+
|
33 |
+
print("Downloading pretrained models:")
|
34 |
+
|
35 |
+
model_names = [
|
36 |
+
"D32k.pth",
|
37 |
+
"D40k.pth",
|
38 |
+
"D48k.pth",
|
39 |
+
"G32k.pth",
|
40 |
+
"G40k.pth",
|
41 |
+
"G48k.pth",
|
42 |
+
"f0D32k.pth",
|
43 |
+
"f0D40k.pth",
|
44 |
+
"f0D48k.pth",
|
45 |
+
"f0G32k.pth",
|
46 |
+
"f0G40k.pth",
|
47 |
+
"f0G48k.pth",
|
48 |
+
]
|
49 |
+
for model in model_names:
|
50 |
+
print(f"Downloading {model}...")
|
51 |
+
dl_model(RVC_DOWNLOAD_LINK + "pretrained/", model, rvc_models_dir)
|
52 |
+
|
53 |
+
rvc_models_dir = BASE_DIR / "assets/pretrained_v2"
|
54 |
+
|
55 |
+
print("Downloading pretrained models v2:")
|
56 |
+
|
57 |
+
for model in model_names:
|
58 |
+
print(f"Downloading {model}...")
|
59 |
+
dl_model(RVC_DOWNLOAD_LINK + "pretrained_v2/", model, rvc_models_dir)
|
60 |
+
|
61 |
+
print("Downloading uvr5_weights:")
|
62 |
+
|
63 |
+
rvc_models_dir = BASE_DIR / "assets/uvr5_weights"
|
64 |
+
|
65 |
+
model_names = [
|
66 |
+
"HP2-%E4%BA%BA%E5%A3%B0vocals%2B%E9%9D%9E%E4%BA%BA%E5%A3%B0instrumentals.pth",
|
67 |
+
"HP2_all_vocals.pth",
|
68 |
+
"HP3_all_vocals.pth",
|
69 |
+
"HP5-%E4%B8%BB%E6%97%8B%E5%BE%8B%E4%BA%BA%E5%A3%B0vocals%2B%E5%85%B6%E4%BB%96instrumentals.pth",
|
70 |
+
"HP5_only_main_vocal.pth",
|
71 |
+
"VR-DeEchoAggressive.pth",
|
72 |
+
"VR-DeEchoDeReverb.pth",
|
73 |
+
"VR-DeEchoNormal.pth",
|
74 |
+
]
|
75 |
+
for model in model_names:
|
76 |
+
print(f"Downloading {model}...")
|
77 |
+
dl_model(RVC_DOWNLOAD_LINK + "uvr5_weights/", model, rvc_models_dir)
|
78 |
+
|
79 |
+
print("All models downloaded!")
|
tools/export_onnx.py
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
from infer.lib.infer_pack.models_onnx import SynthesizerTrnMsNSFsidM
|
3 |
+
|
4 |
+
if __name__ == "__main__":
|
5 |
+
MoeVS = True # 模型是否为MoeVoiceStudio(原MoeSS)使用
|
6 |
+
|
7 |
+
ModelPath = "Shiroha/shiroha.pth" # 模型路径
|
8 |
+
ExportedPath = "model.onnx" # 输出路径
|
9 |
+
hidden_channels = 256 # hidden_channels,为768Vec做准备
|
10 |
+
cpt = torch.load(ModelPath, map_location="cpu")
|
11 |
+
cpt["config"][-3] = cpt["weight"]["emb_g.weight"].shape[0] # n_spk
|
12 |
+
print(*cpt["config"])
|
13 |
+
|
14 |
+
test_phone = torch.rand(1, 200, hidden_channels) # hidden unit
|
15 |
+
test_phone_lengths = torch.tensor([200]).long() # hidden unit 长度(貌似没啥用)
|
16 |
+
test_pitch = torch.randint(size=(1, 200), low=5, high=255) # 基频(单位赫兹)
|
17 |
+
test_pitchf = torch.rand(1, 200) # nsf基频
|
18 |
+
test_ds = torch.LongTensor([0]) # 说话人ID
|
19 |
+
test_rnd = torch.rand(1, 192, 200) # 噪声(加入随机因子)
|
20 |
+
|
21 |
+
device = "cpu" # 导出时设备(不影响使用模型)
|
22 |
+
|
23 |
+
net_g = SynthesizerTrnMsNSFsidM(
|
24 |
+
*cpt["config"], is_half=False
|
25 |
+
) # fp32导出(C++要支持fp16必须手动将内存重新排列所以暂时不用fp16)
|
26 |
+
net_g.load_state_dict(cpt["weight"], strict=False)
|
27 |
+
input_names = ["phone", "phone_lengths", "pitch", "pitchf", "ds", "rnd"]
|
28 |
+
output_names = [
|
29 |
+
"audio",
|
30 |
+
]
|
31 |
+
# net_g.construct_spkmixmap(n_speaker) 多角色混合轨道导出
|
32 |
+
torch.onnx.export(
|
33 |
+
net_g,
|
34 |
+
(
|
35 |
+
test_phone.to(device),
|
36 |
+
test_phone_lengths.to(device),
|
37 |
+
test_pitch.to(device),
|
38 |
+
test_pitchf.to(device),
|
39 |
+
test_ds.to(device),
|
40 |
+
test_rnd.to(device),
|
41 |
+
),
|
42 |
+
ExportedPath,
|
43 |
+
dynamic_axes={
|
44 |
+
"phone": [1],
|
45 |
+
"pitch": [1],
|
46 |
+
"pitchf": [1],
|
47 |
+
"rnd": [2],
|
48 |
+
},
|
49 |
+
do_constant_folding=False,
|
50 |
+
opset_version=16,
|
51 |
+
verbose=False,
|
52 |
+
input_names=input_names,
|
53 |
+
output_names=output_names,
|
54 |
+
)
|
tools/infer/infer-pm-index256.py
ADDED
@@ -0,0 +1,203 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
|
3 |
+
对源特征进行检索
|
4 |
+
"""
|
5 |
+
|
6 |
+
import os
|
7 |
+
import logging
|
8 |
+
|
9 |
+
logger = logging.getLogger(__name__)
|
10 |
+
|
11 |
+
import parselmouth
|
12 |
+
import torch
|
13 |
+
|
14 |
+
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
|
15 |
+
# import torchcrepe
|
16 |
+
from time import time as ttime
|
17 |
+
|
18 |
+
# import pyworld
|
19 |
+
import librosa
|
20 |
+
import numpy as np
|
21 |
+
import soundfile as sf
|
22 |
+
import torch.nn.functional as F
|
23 |
+
from fairseq import checkpoint_utils
|
24 |
+
|
25 |
+
# from models import SynthesizerTrn256#hifigan_nonsf
|
26 |
+
# from lib.infer_pack.models import SynthesizerTrn256NSF as SynthesizerTrn256#hifigan_nsf
|
27 |
+
from infer.lib.infer_pack.models import (
|
28 |
+
SynthesizerTrnMs256NSFsid as SynthesizerTrn256,
|
29 |
+
) # hifigan_nsf
|
30 |
+
from scipy.io import wavfile
|
31 |
+
|
32 |
+
# from lib.infer_pack.models import SynthesizerTrnMs256NSFsid_sim as SynthesizerTrn256#hifigan_nsf
|
33 |
+
# from models import SynthesizerTrn256NSFsim as SynthesizerTrn256#hifigan_nsf
|
34 |
+
# from models import SynthesizerTrn256NSFsimFlow as SynthesizerTrn256#hifigan_nsf
|
35 |
+
|
36 |
+
|
37 |
+
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
38 |
+
model_path = r"E:\codes\py39\vits_vc_gpu_train\assets\hubert\hubert_base.pt" #
|
39 |
+
logger.info("Load model(s) from {}".format(model_path))
|
40 |
+
models, saved_cfg, task = checkpoint_utils.load_model_ensemble_and_task(
|
41 |
+
[model_path],
|
42 |
+
suffix="",
|
43 |
+
)
|
44 |
+
model = models[0]
|
45 |
+
model = model.to(device)
|
46 |
+
model = model.half()
|
47 |
+
model.eval()
|
48 |
+
|
49 |
+
# net_g = SynthesizerTrn256(1025,32,192,192,768,2,6,3,0.1,"1", [3,7,11],[[1,3,5], [1,3,5], [1,3,5]],[10,10,2,2],512,[16,16,4,4],183,256,is_half=True)#hifigan#512#256
|
50 |
+
# net_g = SynthesizerTrn256(1025,32,192,192,768,2,6,3,0.1,"1", [3,7,11],[[1,3,5], [1,3,5], [1,3,5]],[10,10,2,2],512,[16,16,4,4],109,256,is_half=True)#hifigan#512#256
|
51 |
+
net_g = SynthesizerTrn256(
|
52 |
+
1025,
|
53 |
+
32,
|
54 |
+
192,
|
55 |
+
192,
|
56 |
+
768,
|
57 |
+
2,
|
58 |
+
6,
|
59 |
+
3,
|
60 |
+
0,
|
61 |
+
"1",
|
62 |
+
[3, 7, 11],
|
63 |
+
[[1, 3, 5], [1, 3, 5], [1, 3, 5]],
|
64 |
+
[10, 10, 2, 2],
|
65 |
+
512,
|
66 |
+
[16, 16, 4, 4],
|
67 |
+
183,
|
68 |
+
256,
|
69 |
+
is_half=True,
|
70 |
+
) # hifigan#512#256#no_dropout
|
71 |
+
# net_g = SynthesizerTrn256(1025,32,192,192,768,2,3,3,0.1,"1", [3,7,11],[[1,3,5], [1,3,5], [1,3,5]],[10,10,2,2],512,[16,16,4,4],0)#ts3
|
72 |
+
# net_g = SynthesizerTrn256(1025,32,192,192,768,2,6,3,0.1,"1", [3,7,11],[[1,3,5], [1,3,5], [1,3,5]],[10,10,2],512,[16,16,4],0)#hifigan-ps-sr
|
73 |
+
#
|
74 |
+
# net_g = SynthesizerTrn(1025, 32, 192, 192, 768, 2, 6, 3, 0.1, "1", [3, 7, 11], [[1, 3, 5], [1, 3, 5], [1, 3, 5]], [5,5], 512, [15,15], 0)#ms
|
75 |
+
# net_g = SynthesizerTrn(1025, 32, 192, 192, 768, 2, 6, 3, 0.1, "1", [3, 7, 11], [[1, 3, 5], [1, 3, 5], [1, 3, 5]], [10,10], 512, [16,16], 0)#idwt2
|
76 |
+
|
77 |
+
# weights=torch.load("infer/ft-mi_1k-noD.pt")
|
78 |
+
# weights=torch.load("infer/ft-mi-freeze-vocoder-flow-enc_q_1k.pt")
|
79 |
+
# weights=torch.load("infer/ft-mi-freeze-vocoder_true_1k.pt")
|
80 |
+
# weights=torch.load("infer/ft-mi-sim1k.pt")
|
81 |
+
weights = torch.load("infer/ft-mi-no_opt-no_dropout.pt")
|
82 |
+
logger.debug(net_g.load_state_dict(weights, strict=True))
|
83 |
+
|
84 |
+
net_g.eval().to(device)
|
85 |
+
net_g.half()
|
86 |
+
|
87 |
+
|
88 |
+
def get_f0(x, p_len, f0_up_key=0):
|
89 |
+
time_step = 160 / 16000 * 1000
|
90 |
+
f0_min = 50
|
91 |
+
f0_max = 1100
|
92 |
+
f0_mel_min = 1127 * np.log(1 + f0_min / 700)
|
93 |
+
f0_mel_max = 1127 * np.log(1 + f0_max / 700)
|
94 |
+
|
95 |
+
f0 = (
|
96 |
+
parselmouth.Sound(x, 16000)
|
97 |
+
.to_pitch_ac(
|
98 |
+
time_step=time_step / 1000,
|
99 |
+
voicing_threshold=0.6,
|
100 |
+
pitch_floor=f0_min,
|
101 |
+
pitch_ceiling=f0_max,
|
102 |
+
)
|
103 |
+
.selected_array["frequency"]
|
104 |
+
)
|
105 |
+
|
106 |
+
pad_size = (p_len - len(f0) + 1) // 2
|
107 |
+
if pad_size > 0 or p_len - len(f0) - pad_size > 0:
|
108 |
+
f0 = np.pad(f0, [[pad_size, p_len - len(f0) - pad_size]], mode="constant")
|
109 |
+
f0 *= pow(2, f0_up_key / 12)
|
110 |
+
f0bak = f0.copy()
|
111 |
+
|
112 |
+
f0_mel = 1127 * np.log(1 + f0 / 700)
|
113 |
+
f0_mel[f0_mel > 0] = (f0_mel[f0_mel > 0] - f0_mel_min) * 254 / (
|
114 |
+
f0_mel_max - f0_mel_min
|
115 |
+
) + 1
|
116 |
+
f0_mel[f0_mel <= 1] = 1
|
117 |
+
f0_mel[f0_mel > 255] = 255
|
118 |
+
# f0_mel[f0_mel > 188] = 188
|
119 |
+
f0_coarse = np.rint(f0_mel).astype(np.int32)
|
120 |
+
return f0_coarse, f0bak
|
121 |
+
|
122 |
+
|
123 |
+
import faiss
|
124 |
+
|
125 |
+
index = faiss.read_index("infer/added_IVF512_Flat_mi_baseline_src_feat.index")
|
126 |
+
big_npy = np.load("infer/big_src_feature_mi.npy")
|
127 |
+
ta0 = ta1 = ta2 = 0
|
128 |
+
for idx, name in enumerate(
|
129 |
+
[
|
130 |
+
"冬之花clip1.wav",
|
131 |
+
]
|
132 |
+
): ##
|
133 |
+
wav_path = "todo-songs/%s" % name #
|
134 |
+
f0_up_key = -2 #
|
135 |
+
audio, sampling_rate = sf.read(wav_path)
|
136 |
+
if len(audio.shape) > 1:
|
137 |
+
audio = librosa.to_mono(audio.transpose(1, 0))
|
138 |
+
if sampling_rate != 16000:
|
139 |
+
audio = librosa.resample(audio, orig_sr=sampling_rate, target_sr=16000)
|
140 |
+
|
141 |
+
feats = torch.from_numpy(audio).float()
|
142 |
+
if feats.dim() == 2: # double channels
|
143 |
+
feats = feats.mean(-1)
|
144 |
+
assert feats.dim() == 1, feats.dim()
|
145 |
+
feats = feats.view(1, -1)
|
146 |
+
padding_mask = torch.BoolTensor(feats.shape).fill_(False)
|
147 |
+
inputs = {
|
148 |
+
"source": feats.half().to(device),
|
149 |
+
"padding_mask": padding_mask.to(device),
|
150 |
+
"output_layer": 9, # layer 9
|
151 |
+
}
|
152 |
+
if torch.cuda.is_available():
|
153 |
+
torch.cuda.synchronize()
|
154 |
+
t0 = ttime()
|
155 |
+
with torch.no_grad():
|
156 |
+
logits = model.extract_features(**inputs)
|
157 |
+
feats = model.final_proj(logits[0])
|
158 |
+
|
159 |
+
####索引优化
|
160 |
+
npy = feats[0].cpu().numpy().astype("float32")
|
161 |
+
D, I = index.search(npy, 1)
|
162 |
+
feats = (
|
163 |
+
torch.from_numpy(big_npy[I.squeeze()].astype("float16")).unsqueeze(0).to(device)
|
164 |
+
)
|
165 |
+
|
166 |
+
feats = F.interpolate(feats.permute(0, 2, 1), scale_factor=2).permute(0, 2, 1)
|
167 |
+
if torch.cuda.is_available():
|
168 |
+
torch.cuda.synchronize()
|
169 |
+
t1 = ttime()
|
170 |
+
# p_len = min(feats.shape[1],10000,pitch.shape[0])#太大了爆显存
|
171 |
+
p_len = min(feats.shape[1], 10000) #
|
172 |
+
pitch, pitchf = get_f0(audio, p_len, f0_up_key)
|
173 |
+
p_len = min(feats.shape[1], 10000, pitch.shape[0]) # 太大了爆显存
|
174 |
+
if torch.cuda.is_available():
|
175 |
+
torch.cuda.synchronize()
|
176 |
+
t2 = ttime()
|
177 |
+
feats = feats[:, :p_len, :]
|
178 |
+
pitch = pitch[:p_len]
|
179 |
+
pitchf = pitchf[:p_len]
|
180 |
+
p_len = torch.LongTensor([p_len]).to(device)
|
181 |
+
pitch = torch.LongTensor(pitch).unsqueeze(0).to(device)
|
182 |
+
sid = torch.LongTensor([0]).to(device)
|
183 |
+
pitchf = torch.FloatTensor(pitchf).unsqueeze(0).to(device)
|
184 |
+
with torch.no_grad():
|
185 |
+
audio = (
|
186 |
+
net_g.infer(feats, p_len, pitch, pitchf, sid)[0][0, 0]
|
187 |
+
.data.cpu()
|
188 |
+
.float()
|
189 |
+
.numpy()
|
190 |
+
) # nsf
|
191 |
+
if torch.cuda.is_available():
|
192 |
+
torch.cuda.synchronize()
|
193 |
+
t3 = ttime()
|
194 |
+
ta0 += t1 - t0
|
195 |
+
ta1 += t2 - t1
|
196 |
+
ta2 += t3 - t2
|
197 |
+
# wavfile.write("ft-mi_1k-index256-noD-%s.wav"%name, 40000, audio)##
|
198 |
+
# wavfile.write("ft-mi-freeze-vocoder-flow-enc_q_1k-%s.wav"%name, 40000, audio)##
|
199 |
+
# wavfile.write("ft-mi-sim1k-%s.wav"%name, 40000, audio)##
|
200 |
+
wavfile.write("ft-mi-no_opt-no_dropout-%s.wav" % name, 40000, audio) ##
|
201 |
+
|
202 |
+
|
203 |
+
logger.debug("%.2fs %.2fs %.2fs", ta0, ta1, ta2) #
|
tools/infer/train-index-v2.py
ADDED
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
格式:直接cid为自带的index位;aid放不下了,通过字典来查,反正就5w个
|
3 |
+
"""
|
4 |
+
|
5 |
+
import os
|
6 |
+
import traceback
|
7 |
+
import logging
|
8 |
+
|
9 |
+
logger = logging.getLogger(__name__)
|
10 |
+
|
11 |
+
from multiprocessing import cpu_count
|
12 |
+
|
13 |
+
import faiss
|
14 |
+
import numpy as np
|
15 |
+
from sklearn.cluster import MiniBatchKMeans
|
16 |
+
|
17 |
+
# ###########如果是原始特征要先写save
|
18 |
+
n_cpu = 0
|
19 |
+
if n_cpu == 0:
|
20 |
+
n_cpu = cpu_count()
|
21 |
+
inp_root = r"./logs/anz/3_feature768"
|
22 |
+
npys = []
|
23 |
+
listdir_res = list(os.listdir(inp_root))
|
24 |
+
for name in sorted(listdir_res):
|
25 |
+
phone = np.load("%s/%s" % (inp_root, name))
|
26 |
+
npys.append(phone)
|
27 |
+
big_npy = np.concatenate(npys, 0)
|
28 |
+
big_npy_idx = np.arange(big_npy.shape[0])
|
29 |
+
np.random.shuffle(big_npy_idx)
|
30 |
+
big_npy = big_npy[big_npy_idx]
|
31 |
+
logger.debug(big_npy.shape) # (6196072, 192)#fp32#4.43G
|
32 |
+
if big_npy.shape[0] > 2e5:
|
33 |
+
# if(1):
|
34 |
+
info = "Trying doing kmeans %s shape to 10k centers." % big_npy.shape[0]
|
35 |
+
logger.info(info)
|
36 |
+
try:
|
37 |
+
big_npy = (
|
38 |
+
MiniBatchKMeans(
|
39 |
+
n_clusters=10000,
|
40 |
+
verbose=True,
|
41 |
+
batch_size=256 * n_cpu,
|
42 |
+
compute_labels=False,
|
43 |
+
init="random",
|
44 |
+
)
|
45 |
+
.fit(big_npy)
|
46 |
+
.cluster_centers_
|
47 |
+
)
|
48 |
+
except:
|
49 |
+
info = traceback.format_exc()
|
50 |
+
logger.warning(info)
|
51 |
+
|
52 |
+
np.save("tools/infer/big_src_feature_mi.npy", big_npy)
|
53 |
+
|
54 |
+
##################train+add
|
55 |
+
# big_npy=np.load("/bili-coeus/jupyter/jupyterhub-liujing04/vits_ch/inference_f0/big_src_feature_mi.npy")
|
56 |
+
n_ivf = min(int(16 * np.sqrt(big_npy.shape[0])), big_npy.shape[0] // 39)
|
57 |
+
index = faiss.index_factory(768, "IVF%s,Flat" % n_ivf) # mi
|
58 |
+
logger.info("Training...")
|
59 |
+
index_ivf = faiss.extract_index_ivf(index) #
|
60 |
+
index_ivf.nprobe = 1
|
61 |
+
index.train(big_npy)
|
62 |
+
faiss.write_index(
|
63 |
+
index, "tools/infer/trained_IVF%s_Flat_baseline_src_feat_v2.index" % (n_ivf)
|
64 |
+
)
|
65 |
+
logger.info("Adding...")
|
66 |
+
batch_size_add = 8192
|
67 |
+
for i in range(0, big_npy.shape[0], batch_size_add):
|
68 |
+
index.add(big_npy[i : i + batch_size_add])
|
69 |
+
faiss.write_index(
|
70 |
+
index, "tools/infer/added_IVF%s_Flat_mi_baseline_src_feat.index" % (n_ivf)
|
71 |
+
)
|
72 |
+
"""
|
73 |
+
大小(都是FP32)
|
74 |
+
big_src_feature 2.95G
|
75 |
+
(3098036, 256)
|
76 |
+
big_emb 4.43G
|
77 |
+
(6196072, 192)
|
78 |
+
big_emb双倍是因为求特征要repeat后再加pitch
|
79 |
+
|
80 |
+
"""
|
tools/infer/train-index.py
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
格式:直接cid为自带的index位;aid放不下了,通过字典来查,反正就5w个
|
3 |
+
"""
|
4 |
+
|
5 |
+
import os
|
6 |
+
import logging
|
7 |
+
|
8 |
+
logger = logging.getLogger(__name__)
|
9 |
+
|
10 |
+
import faiss
|
11 |
+
import numpy as np
|
12 |
+
|
13 |
+
# ###########如果是原始特征要先写save
|
14 |
+
inp_root = r"E:\codes\py39\dataset\mi\2-co256"
|
15 |
+
npys = []
|
16 |
+
for name in sorted(list(os.listdir(inp_root))):
|
17 |
+
phone = np.load("%s/%s" % (inp_root, name))
|
18 |
+
npys.append(phone)
|
19 |
+
big_npy = np.concatenate(npys, 0)
|
20 |
+
logger.debug(big_npy.shape) # (6196072, 192)#fp32#4.43G
|
21 |
+
np.save("infer/big_src_feature_mi.npy", big_npy)
|
22 |
+
|
23 |
+
##################train+add
|
24 |
+
# big_npy=np.load("/bili-coeus/jupyter/jupyterhub-liujing04/vits_ch/inference_f0/big_src_feature_mi.npy")
|
25 |
+
logger.debug(big_npy.shape)
|
26 |
+
index = faiss.index_factory(256, "IVF512,Flat") # mi
|
27 |
+
logger.info("Training...")
|
28 |
+
index_ivf = faiss.extract_index_ivf(index) #
|
29 |
+
index_ivf.nprobe = 9
|
30 |
+
index.train(big_npy)
|
31 |
+
faiss.write_index(index, "infer/trained_IVF512_Flat_mi_baseline_src_feat.index")
|
32 |
+
logger.info("Adding...")
|
33 |
+
index.add(big_npy)
|
34 |
+
faiss.write_index(index, "infer/added_IVF512_Flat_mi_baseline_src_feat.index")
|
35 |
+
"""
|
36 |
+
大小(都是FP32)
|
37 |
+
big_src_feature 2.95G
|
38 |
+
(3098036, 256)
|
39 |
+
big_emb 4.43G
|
40 |
+
(6196072, 192)
|
41 |
+
big_emb双倍是因为求特征要repeat后再加pitch
|
42 |
+
|
43 |
+
"""
|
tools/infer/trans_weights.py
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pdb
|
2 |
+
|
3 |
+
import torch
|
4 |
+
|
5 |
+
# a=torch.load(r"E:\codes\py39\vits_vc_gpu_train\logs\ft-mi-suc\G_1000.pth")["model"]#sim_nsf#
|
6 |
+
# a=torch.load(r"E:\codes\py39\vits_vc_gpu_train\logs\ft-mi-freeze-vocoder-flow-enc_q\G_1000.pth")["model"]#sim_nsf#
|
7 |
+
# a=torch.load(r"E:\codes\py39\vits_vc_gpu_train\logs\ft-mi-freeze-vocoder\G_1000.pth")["model"]#sim_nsf#
|
8 |
+
# a=torch.load(r"E:\codes\py39\vits_vc_gpu_train\logs\ft-mi-test\G_1000.pth")["model"]#sim_nsf#
|
9 |
+
a = torch.load(
|
10 |
+
r"E:\codes\py39\vits_vc_gpu_train\logs\ft-mi-no_opt-no_dropout\G_1000.pth"
|
11 |
+
)[
|
12 |
+
"model"
|
13 |
+
] # sim_nsf#
|
14 |
+
for key in a.keys():
|
15 |
+
a[key] = a[key].half()
|
16 |
+
# torch.save(a,"ft-mi-freeze-vocoder_true_1k.pt")#
|
17 |
+
# torch.save(a,"ft-mi-sim1k.pt")#
|
18 |
+
torch.save(a, "ft-mi-no_opt-no_dropout.pt") #
|
tools/infer_batch_rvc.py
ADDED
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import argparse
|
2 |
+
import os
|
3 |
+
import sys
|
4 |
+
|
5 |
+
print("Command-line arguments:", sys.argv)
|
6 |
+
|
7 |
+
now_dir = os.getcwd()
|
8 |
+
sys.path.append(now_dir)
|
9 |
+
import sys
|
10 |
+
|
11 |
+
import tqdm as tq
|
12 |
+
from dotenv import load_dotenv
|
13 |
+
from scipy.io import wavfile
|
14 |
+
|
15 |
+
from configs.config import Config
|
16 |
+
from infer.modules.vc.modules import VC
|
17 |
+
|
18 |
+
|
19 |
+
def arg_parse() -> tuple:
|
20 |
+
parser = argparse.ArgumentParser()
|
21 |
+
parser.add_argument("--f0up_key", type=int, default=0)
|
22 |
+
parser.add_argument("--input_path", type=str, help="input path")
|
23 |
+
parser.add_argument("--index_path", type=str, help="index path")
|
24 |
+
parser.add_argument("--f0method", type=str, default="harvest", help="harvest or pm")
|
25 |
+
parser.add_argument("--opt_path", type=str, help="opt path")
|
26 |
+
parser.add_argument("--model_name", type=str, help="store in assets/weight_root")
|
27 |
+
parser.add_argument("--index_rate", type=float, default=0.66, help="index rate")
|
28 |
+
parser.add_argument("--device", type=str, help="device")
|
29 |
+
parser.add_argument("--is_half", type=bool, help="use half -> True")
|
30 |
+
parser.add_argument("--filter_radius", type=int, default=3, help="filter radius")
|
31 |
+
parser.add_argument("--resample_sr", type=int, default=0, help="resample sr")
|
32 |
+
parser.add_argument("--rms_mix_rate", type=float, default=1, help="rms mix rate")
|
33 |
+
parser.add_argument("--protect", type=float, default=0.33, help="protect")
|
34 |
+
|
35 |
+
args = parser.parse_args()
|
36 |
+
sys.argv = sys.argv[:1]
|
37 |
+
|
38 |
+
return args
|
39 |
+
|
40 |
+
|
41 |
+
def main():
|
42 |
+
load_dotenv()
|
43 |
+
args = arg_parse()
|
44 |
+
config = Config()
|
45 |
+
config.device = args.device if args.device else config.device
|
46 |
+
config.is_half = args.is_half if args.is_half else config.is_half
|
47 |
+
vc = VC(config)
|
48 |
+
vc.get_vc(args.model_name)
|
49 |
+
audios = os.listdir(args.input_path)
|
50 |
+
for file in tq.tqdm(audios):
|
51 |
+
if file.endswith(".wav"):
|
52 |
+
file_path = os.path.join(args.input_path, file)
|
53 |
+
_, wav_opt = vc.vc_single(
|
54 |
+
0,
|
55 |
+
file_path,
|
56 |
+
args.f0up_key,
|
57 |
+
None,
|
58 |
+
args.f0method,
|
59 |
+
args.index_path,
|
60 |
+
None,
|
61 |
+
args.index_rate,
|
62 |
+
args.filter_radius,
|
63 |
+
args.resample_sr,
|
64 |
+
args.rms_mix_rate,
|
65 |
+
args.protect,
|
66 |
+
)
|
67 |
+
out_path = os.path.join(args.opt_path, file)
|
68 |
+
wavfile.write(out_path, wav_opt[0], wav_opt[1])
|
69 |
+
|
70 |
+
|
71 |
+
if __name__ == "__main__":
|
72 |
+
main()
|
tools/infer_cli.py
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import argparse
|
2 |
+
import os
|
3 |
+
import sys
|
4 |
+
|
5 |
+
now_dir = os.getcwd()
|
6 |
+
sys.path.append(now_dir)
|
7 |
+
from dotenv import load_dotenv
|
8 |
+
from scipy.io import wavfile
|
9 |
+
|
10 |
+
from configs.config import Config
|
11 |
+
from infer.modules.vc.modules import VC
|
12 |
+
|
13 |
+
####
|
14 |
+
# USAGE
|
15 |
+
#
|
16 |
+
# In your Terminal or CMD or whatever
|
17 |
+
|
18 |
+
|
19 |
+
def arg_parse() -> tuple:
|
20 |
+
parser = argparse.ArgumentParser()
|
21 |
+
parser.add_argument("--f0up_key", type=int, default=0)
|
22 |
+
parser.add_argument("--input_path", type=str, help="input path")
|
23 |
+
parser.add_argument("--index_path", type=str, help="index path")
|
24 |
+
parser.add_argument("--f0method", type=str, default="harvest", help="harvest or pm")
|
25 |
+
parser.add_argument("--opt_path", type=str, help="opt path")
|
26 |
+
parser.add_argument("--model_name", type=str, help="store in assets/weight_root")
|
27 |
+
parser.add_argument("--index_rate", type=float, default=0.66, help="index rate")
|
28 |
+
parser.add_argument("--device", type=str, help="device")
|
29 |
+
parser.add_argument("--is_half", type=bool, help="use half -> True")
|
30 |
+
parser.add_argument("--filter_radius", type=int, default=3, help="filter radius")
|
31 |
+
parser.add_argument("--resample_sr", type=int, default=0, help="resample sr")
|
32 |
+
parser.add_argument("--rms_mix_rate", type=float, default=1, help="rms mix rate")
|
33 |
+
parser.add_argument("--protect", type=float, default=0.33, help="protect")
|
34 |
+
|
35 |
+
args = parser.parse_args()
|
36 |
+
sys.argv = sys.argv[:1]
|
37 |
+
|
38 |
+
return args
|
39 |
+
|
40 |
+
|
41 |
+
def main():
|
42 |
+
load_dotenv()
|
43 |
+
args = arg_parse()
|
44 |
+
config = Config()
|
45 |
+
config.device = args.device if args.device else config.device
|
46 |
+
config.is_half = args.is_half if args.is_half else config.is_half
|
47 |
+
vc = VC(config)
|
48 |
+
vc.get_vc(args.model_name)
|
49 |
+
_, wav_opt = vc.vc_single(
|
50 |
+
0,
|
51 |
+
args.input_path,
|
52 |
+
args.f0up_key,
|
53 |
+
None,
|
54 |
+
args.f0method,
|
55 |
+
args.index_path,
|
56 |
+
None,
|
57 |
+
args.index_rate,
|
58 |
+
args.filter_radius,
|
59 |
+
args.resample_sr,
|
60 |
+
args.rms_mix_rate,
|
61 |
+
args.protect,
|
62 |
+
)
|
63 |
+
wavfile.write(args.opt_path, wav_opt[0], wav_opt[1])
|
64 |
+
|
65 |
+
|
66 |
+
if __name__ == "__main__":
|
67 |
+
main()
|
tools/onnx_inference_demo.py
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import soundfile
|
2 |
+
|
3 |
+
from ..infer.lib.infer_pack.onnx_inference import OnnxRVC
|
4 |
+
|
5 |
+
hop_size = 512
|
6 |
+
sampling_rate = 40000 # 采样率
|
7 |
+
f0_up_key = 0 # 升降调
|
8 |
+
sid = 0 # 角色ID
|
9 |
+
f0_method = "dio" # F0提取算法
|
10 |
+
model_path = "ShirohaRVC.onnx" # 模型的完整路径
|
11 |
+
vec_name = (
|
12 |
+
"vec-256-layer-9" # 内部自动补齐为 f"pretrained/{vec_name}.onnx" 需要onnx的vec模型
|
13 |
+
)
|
14 |
+
wav_path = "123.wav" # 输入路径或ByteIO实例
|
15 |
+
out_path = "out.wav" # 输出路径或ByteIO实例
|
16 |
+
|
17 |
+
model = OnnxRVC(
|
18 |
+
model_path, vec_path=vec_name, sr=sampling_rate, hop_size=hop_size, device="cuda"
|
19 |
+
)
|
20 |
+
|
21 |
+
audio = model.inference(wav_path, sid, f0_method=f0_method, f0_up_key=f0_up_key)
|
22 |
+
|
23 |
+
soundfile.write(out_path, audio, sampling_rate)
|
tools/rvc_for_realtime.py
ADDED
@@ -0,0 +1,443 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from io import BytesIO
|
2 |
+
import os
|
3 |
+
import pickle
|
4 |
+
import sys
|
5 |
+
import traceback
|
6 |
+
from infer.lib import jit
|
7 |
+
from infer.lib.jit.get_synthesizer import get_synthesizer
|
8 |
+
from time import time as ttime
|
9 |
+
import fairseq
|
10 |
+
import faiss
|
11 |
+
import numpy as np
|
12 |
+
import parselmouth
|
13 |
+
import pyworld
|
14 |
+
import scipy.signal as signal
|
15 |
+
import torch
|
16 |
+
import torch.nn as nn
|
17 |
+
import torch.nn.functional as F
|
18 |
+
import torchcrepe
|
19 |
+
|
20 |
+
from infer.lib.infer_pack.models import (
|
21 |
+
SynthesizerTrnMs256NSFsid,
|
22 |
+
SynthesizerTrnMs256NSFsid_nono,
|
23 |
+
SynthesizerTrnMs768NSFsid,
|
24 |
+
SynthesizerTrnMs768NSFsid_nono,
|
25 |
+
)
|
26 |
+
|
27 |
+
now_dir = os.getcwd()
|
28 |
+
sys.path.append(now_dir)
|
29 |
+
from multiprocessing import Manager as M
|
30 |
+
|
31 |
+
from configs.config import Config
|
32 |
+
|
33 |
+
# config = Config()
|
34 |
+
|
35 |
+
mm = M()
|
36 |
+
|
37 |
+
|
38 |
+
def printt(strr, *args):
|
39 |
+
if len(args) == 0:
|
40 |
+
print(strr)
|
41 |
+
else:
|
42 |
+
print(strr % args)
|
43 |
+
|
44 |
+
|
45 |
+
# config.device=torch.device("cpu")########强制cpu测试
|
46 |
+
# config.is_half=False########强制cpu测试
|
47 |
+
class RVC:
|
48 |
+
def __init__(
|
49 |
+
self,
|
50 |
+
key,
|
51 |
+
pth_path,
|
52 |
+
index_path,
|
53 |
+
index_rate,
|
54 |
+
n_cpu,
|
55 |
+
inp_q,
|
56 |
+
opt_q,
|
57 |
+
config: Config,
|
58 |
+
last_rvc=None,
|
59 |
+
) -> None:
|
60 |
+
"""
|
61 |
+
初始化
|
62 |
+
"""
|
63 |
+
try:
|
64 |
+
if config.dml == True:
|
65 |
+
|
66 |
+
def forward_dml(ctx, x, scale):
|
67 |
+
ctx.scale = scale
|
68 |
+
res = x.clone().detach()
|
69 |
+
return res
|
70 |
+
|
71 |
+
fairseq.modules.grad_multiply.GradMultiply.forward = forward_dml
|
72 |
+
# global config
|
73 |
+
self.config = config
|
74 |
+
self.inp_q = inp_q
|
75 |
+
self.opt_q = opt_q
|
76 |
+
# device="cpu"########强制cpu测试
|
77 |
+
self.device = config.device
|
78 |
+
self.f0_up_key = key
|
79 |
+
self.f0_min = 50
|
80 |
+
self.f0_max = 1100
|
81 |
+
self.f0_mel_min = 1127 * np.log(1 + self.f0_min / 700)
|
82 |
+
self.f0_mel_max = 1127 * np.log(1 + self.f0_max / 700)
|
83 |
+
self.n_cpu = n_cpu
|
84 |
+
self.use_jit = self.config.use_jit
|
85 |
+
self.is_half = config.is_half
|
86 |
+
|
87 |
+
if index_rate != 0:
|
88 |
+
self.index = faiss.read_index(index_path)
|
89 |
+
self.big_npy = self.index.reconstruct_n(0, self.index.ntotal)
|
90 |
+
printt("Index search enabled")
|
91 |
+
self.pth_path: str = pth_path
|
92 |
+
self.index_path = index_path
|
93 |
+
self.index_rate = index_rate
|
94 |
+
self.cache_pitch: np.ndarray = np.zeros(1024, dtype="int32")
|
95 |
+
self.cache_pitchf = np.zeros(1024, dtype="float32")
|
96 |
+
|
97 |
+
if last_rvc is None:
|
98 |
+
models, _, _ = fairseq.checkpoint_utils.load_model_ensemble_and_task(
|
99 |
+
["assets/hubert/hubert_base.pt"],
|
100 |
+
suffix="",
|
101 |
+
)
|
102 |
+
hubert_model = models[0]
|
103 |
+
hubert_model = hubert_model.to(self.device)
|
104 |
+
if self.is_half:
|
105 |
+
hubert_model = hubert_model.half()
|
106 |
+
else:
|
107 |
+
hubert_model = hubert_model.float()
|
108 |
+
hubert_model.eval()
|
109 |
+
self.model = hubert_model
|
110 |
+
else:
|
111 |
+
self.model = last_rvc.model
|
112 |
+
|
113 |
+
self.net_g: nn.Module = None
|
114 |
+
|
115 |
+
def set_default_model():
|
116 |
+
self.net_g, cpt = get_synthesizer(self.pth_path, self.device)
|
117 |
+
self.tgt_sr = cpt["config"][-1]
|
118 |
+
cpt["config"][-3] = cpt["weight"]["emb_g.weight"].shape[0]
|
119 |
+
self.if_f0 = cpt.get("f0", 1)
|
120 |
+
self.version = cpt.get("version", "v1")
|
121 |
+
if self.is_half:
|
122 |
+
self.net_g = self.net_g.half()
|
123 |
+
else:
|
124 |
+
self.net_g = self.net_g.float()
|
125 |
+
|
126 |
+
def set_jit_model():
|
127 |
+
jit_pth_path = self.pth_path.rstrip(".pth")
|
128 |
+
jit_pth_path += ".half.jit" if self.is_half else ".jit"
|
129 |
+
reload = False
|
130 |
+
if str(self.device) == "cuda":
|
131 |
+
self.device = torch.device("cuda:0")
|
132 |
+
if os.path.exists(jit_pth_path):
|
133 |
+
cpt = jit.load(jit_pth_path)
|
134 |
+
model_device = cpt["device"]
|
135 |
+
if model_device != str(self.device):
|
136 |
+
reload = True
|
137 |
+
else:
|
138 |
+
reload = True
|
139 |
+
|
140 |
+
if reload:
|
141 |
+
cpt = jit.synthesizer_jit_export(
|
142 |
+
self.pth_path,
|
143 |
+
"script",
|
144 |
+
None,
|
145 |
+
device=self.device,
|
146 |
+
is_half=self.is_half,
|
147 |
+
)
|
148 |
+
|
149 |
+
self.tgt_sr = cpt["config"][-1]
|
150 |
+
self.if_f0 = cpt.get("f0", 1)
|
151 |
+
self.version = cpt.get("version", "v1")
|
152 |
+
self.net_g = torch.jit.load(
|
153 |
+
BytesIO(cpt["model"]), map_location=self.device
|
154 |
+
)
|
155 |
+
self.net_g.infer = self.net_g.forward
|
156 |
+
self.net_g.eval().to(self.device)
|
157 |
+
|
158 |
+
def set_synthesizer():
|
159 |
+
if self.use_jit and not config.dml:
|
160 |
+
if self.is_half and "cpu" in str(self.device):
|
161 |
+
printt(
|
162 |
+
"Use default Synthesizer model. \
|
163 |
+
Jit is not supported on the CPU for half floating point"
|
164 |
+
)
|
165 |
+
set_default_model()
|
166 |
+
else:
|
167 |
+
set_jit_model()
|
168 |
+
else:
|
169 |
+
set_default_model()
|
170 |
+
|
171 |
+
if last_rvc is None or last_rvc.pth_path != self.pth_path:
|
172 |
+
set_synthesizer()
|
173 |
+
else:
|
174 |
+
self.tgt_sr = last_rvc.tgt_sr
|
175 |
+
self.if_f0 = last_rvc.if_f0
|
176 |
+
self.version = last_rvc.version
|
177 |
+
self.is_half = last_rvc.is_half
|
178 |
+
if last_rvc.use_jit != self.use_jit:
|
179 |
+
set_synthesizer()
|
180 |
+
else:
|
181 |
+
self.net_g = last_rvc.net_g
|
182 |
+
|
183 |
+
if last_rvc is not None and hasattr(last_rvc, "model_rmvpe"):
|
184 |
+
self.model_rmvpe = last_rvc.model_rmvpe
|
185 |
+
if last_rvc is not None and hasattr(last_rvc, "model_fcpe"):
|
186 |
+
self.device_fcpe = last_rvc.device_fcpe
|
187 |
+
self.model_fcpe = last_rvc.model_fcpe
|
188 |
+
except:
|
189 |
+
printt(traceback.format_exc())
|
190 |
+
|
191 |
+
def change_key(self, new_key):
|
192 |
+
self.f0_up_key = new_key
|
193 |
+
|
194 |
+
def change_index_rate(self, new_index_rate):
|
195 |
+
if new_index_rate != 0 and self.index_rate == 0:
|
196 |
+
self.index = faiss.read_index(self.index_path)
|
197 |
+
self.big_npy = self.index.reconstruct_n(0, self.index.ntotal)
|
198 |
+
printt("Index search enabled")
|
199 |
+
self.index_rate = new_index_rate
|
200 |
+
|
201 |
+
def get_f0_post(self, f0):
|
202 |
+
f0bak = f0.copy()
|
203 |
+
f0_mel = 1127 * np.log(1 + f0 / 700)
|
204 |
+
f0_mel[f0_mel > 0] = (f0_mel[f0_mel > 0] - self.f0_mel_min) * 254 / (
|
205 |
+
self.f0_mel_max - self.f0_mel_min
|
206 |
+
) + 1
|
207 |
+
f0_mel[f0_mel <= 1] = 1
|
208 |
+
f0_mel[f0_mel > 255] = 255
|
209 |
+
f0_coarse = np.rint(f0_mel).astype(np.int32)
|
210 |
+
return f0_coarse, f0bak
|
211 |
+
|
212 |
+
def get_f0(self, x, f0_up_key, n_cpu, method="harvest"):
|
213 |
+
n_cpu = int(n_cpu)
|
214 |
+
if method == "crepe":
|
215 |
+
return self.get_f0_crepe(x, f0_up_key)
|
216 |
+
if method == "rmvpe":
|
217 |
+
return self.get_f0_rmvpe(x, f0_up_key)
|
218 |
+
if method == "fcpe":
|
219 |
+
return self.get_f0_fcpe(x, f0_up_key)
|
220 |
+
x = x.cpu().numpy()
|
221 |
+
if method == "pm":
|
222 |
+
p_len = x.shape[0] // 160 + 1
|
223 |
+
f0_min = 65
|
224 |
+
l_pad = int(np.ceil(1.5 / f0_min * 16000))
|
225 |
+
r_pad = l_pad + 1
|
226 |
+
s = parselmouth.Sound(np.pad(x, (l_pad, r_pad)), 16000).to_pitch_ac(
|
227 |
+
time_step=0.01,
|
228 |
+
voicing_threshold=0.6,
|
229 |
+
pitch_floor=f0_min,
|
230 |
+
pitch_ceiling=1100,
|
231 |
+
)
|
232 |
+
assert np.abs(s.t1 - 1.5 / f0_min) < 0.001
|
233 |
+
f0 = s.selected_array["frequency"]
|
234 |
+
if len(f0) < p_len:
|
235 |
+
f0 = np.pad(f0, (0, p_len - len(f0)))
|
236 |
+
f0 = f0[:p_len]
|
237 |
+
f0 *= pow(2, f0_up_key / 12)
|
238 |
+
return self.get_f0_post(f0)
|
239 |
+
if n_cpu == 1:
|
240 |
+
f0, t = pyworld.harvest(
|
241 |
+
x.astype(np.double),
|
242 |
+
fs=16000,
|
243 |
+
f0_ceil=1100,
|
244 |
+
f0_floor=50,
|
245 |
+
frame_period=10,
|
246 |
+
)
|
247 |
+
f0 = signal.medfilt(f0, 3)
|
248 |
+
f0 *= pow(2, f0_up_key / 12)
|
249 |
+
return self.get_f0_post(f0)
|
250 |
+
f0bak = np.zeros(x.shape[0] // 160 + 1, dtype=np.float64)
|
251 |
+
length = len(x)
|
252 |
+
part_length = 160 * ((length // 160 - 1) // n_cpu + 1)
|
253 |
+
n_cpu = (length // 160 - 1) // (part_length // 160) + 1
|
254 |
+
ts = ttime()
|
255 |
+
res_f0 = mm.dict()
|
256 |
+
for idx in range(n_cpu):
|
257 |
+
tail = part_length * (idx + 1) + 320
|
258 |
+
if idx == 0:
|
259 |
+
self.inp_q.put((idx, x[:tail], res_f0, n_cpu, ts))
|
260 |
+
else:
|
261 |
+
self.inp_q.put(
|
262 |
+
(idx, x[part_length * idx - 320 : tail], res_f0, n_cpu, ts)
|
263 |
+
)
|
264 |
+
while 1:
|
265 |
+
res_ts = self.opt_q.get()
|
266 |
+
if res_ts == ts:
|
267 |
+
break
|
268 |
+
f0s = [i[1] for i in sorted(res_f0.items(), key=lambda x: x[0])]
|
269 |
+
for idx, f0 in enumerate(f0s):
|
270 |
+
if idx == 0:
|
271 |
+
f0 = f0[:-3]
|
272 |
+
elif idx != n_cpu - 1:
|
273 |
+
f0 = f0[2:-3]
|
274 |
+
else:
|
275 |
+
f0 = f0[2:]
|
276 |
+
f0bak[part_length * idx // 160 : part_length * idx // 160 + f0.shape[0]] = (
|
277 |
+
f0
|
278 |
+
)
|
279 |
+
f0bak = signal.medfilt(f0bak, 3)
|
280 |
+
f0bak *= pow(2, f0_up_key / 12)
|
281 |
+
return self.get_f0_post(f0bak)
|
282 |
+
|
283 |
+
def get_f0_crepe(self, x, f0_up_key):
|
284 |
+
if "privateuseone" in str(
|
285 |
+
self.device
|
286 |
+
): ###不支持dml,cpu又太慢用不成���拿fcpe顶替
|
287 |
+
return self.get_f0(x, f0_up_key, 1, "fcpe")
|
288 |
+
# printt("using crepe,device:%s"%self.device)
|
289 |
+
f0, pd = torchcrepe.predict(
|
290 |
+
x.unsqueeze(0).float(),
|
291 |
+
16000,
|
292 |
+
160,
|
293 |
+
self.f0_min,
|
294 |
+
self.f0_max,
|
295 |
+
"full",
|
296 |
+
batch_size=512,
|
297 |
+
# device=self.device if self.device.type!="privateuseone" else "cpu",###crepe不用半精度全部是全精度所以不愁###cpu延迟高到没法用
|
298 |
+
device=self.device,
|
299 |
+
return_periodicity=True,
|
300 |
+
)
|
301 |
+
pd = torchcrepe.filter.median(pd, 3)
|
302 |
+
f0 = torchcrepe.filter.mean(f0, 3)
|
303 |
+
f0[pd < 0.1] = 0
|
304 |
+
f0 = f0[0].cpu().numpy()
|
305 |
+
f0 *= pow(2, f0_up_key / 12)
|
306 |
+
return self.get_f0_post(f0)
|
307 |
+
|
308 |
+
def get_f0_rmvpe(self, x, f0_up_key):
|
309 |
+
if hasattr(self, "model_rmvpe") == False:
|
310 |
+
from infer.lib.rmvpe import RMVPE
|
311 |
+
|
312 |
+
printt("Loading rmvpe model")
|
313 |
+
self.model_rmvpe = RMVPE(
|
314 |
+
"assets/rmvpe/rmvpe.pt",
|
315 |
+
is_half=self.is_half,
|
316 |
+
device=self.device,
|
317 |
+
use_jit=self.config.use_jit,
|
318 |
+
)
|
319 |
+
f0 = self.model_rmvpe.infer_from_audio(x, thred=0.03)
|
320 |
+
f0 *= pow(2, f0_up_key / 12)
|
321 |
+
return self.get_f0_post(f0)
|
322 |
+
|
323 |
+
def get_f0_fcpe(self, x, f0_up_key):
|
324 |
+
if hasattr(self, "model_fcpe") == False:
|
325 |
+
from torchfcpe import spawn_bundled_infer_model
|
326 |
+
|
327 |
+
printt("Loading fcpe model")
|
328 |
+
if "privateuseone" in str(self.device):
|
329 |
+
self.device_fcpe = "cpu"
|
330 |
+
else:
|
331 |
+
self.device_fcpe = self.device
|
332 |
+
self.model_fcpe = spawn_bundled_infer_model(self.device_fcpe)
|
333 |
+
f0 = self.model_fcpe.infer(
|
334 |
+
x.to(self.device_fcpe).unsqueeze(0).float(),
|
335 |
+
sr=16000,
|
336 |
+
decoder_mode="local_argmax",
|
337 |
+
threshold=0.006,
|
338 |
+
)
|
339 |
+
f0 *= pow(2, f0_up_key / 12)
|
340 |
+
f0 = f0.squeeze().cpu().numpy()
|
341 |
+
return self.get_f0_post(f0)
|
342 |
+
|
343 |
+
def infer(
|
344 |
+
self,
|
345 |
+
input_wav: torch.Tensor,
|
346 |
+
block_frame_16k,
|
347 |
+
skip_head,
|
348 |
+
return_length,
|
349 |
+
f0method,
|
350 |
+
) -> np.ndarray:
|
351 |
+
t1 = ttime()
|
352 |
+
with torch.no_grad():
|
353 |
+
if self.config.is_half:
|
354 |
+
feats = input_wav.half().view(1, -1)
|
355 |
+
else:
|
356 |
+
feats = input_wav.float().view(1, -1)
|
357 |
+
padding_mask = torch.BoolTensor(feats.shape).to(self.device).fill_(False)
|
358 |
+
inputs = {
|
359 |
+
"source": feats,
|
360 |
+
"padding_mask": padding_mask,
|
361 |
+
"output_layer": 9 if self.version == "v1" else 12,
|
362 |
+
}
|
363 |
+
logits = self.model.extract_features(**inputs)
|
364 |
+
feats = (
|
365 |
+
self.model.final_proj(logits[0]) if self.version == "v1" else logits[0]
|
366 |
+
)
|
367 |
+
feats = torch.cat((feats, feats[:, -1:, :]), 1)
|
368 |
+
t2 = ttime()
|
369 |
+
try:
|
370 |
+
if hasattr(self, "index") and self.index_rate != 0:
|
371 |
+
npy = feats[0][skip_head // 2 :].cpu().numpy().astype("float32")
|
372 |
+
score, ix = self.index.search(npy, k=8)
|
373 |
+
weight = np.square(1 / score)
|
374 |
+
weight /= weight.sum(axis=1, keepdims=True)
|
375 |
+
npy = np.sum(self.big_npy[ix] * np.expand_dims(weight, axis=2), axis=1)
|
376 |
+
if self.config.is_half:
|
377 |
+
npy = npy.astype("float16")
|
378 |
+
feats[0][skip_head // 2 :] = (
|
379 |
+
torch.from_numpy(npy).unsqueeze(0).to(self.device) * self.index_rate
|
380 |
+
+ (1 - self.index_rate) * feats[0][skip_head // 2 :]
|
381 |
+
)
|
382 |
+
else:
|
383 |
+
printt("Index search FAILED or disabled")
|
384 |
+
except:
|
385 |
+
traceback.print_exc()
|
386 |
+
printt("Index search FAILED")
|
387 |
+
t3 = ttime()
|
388 |
+
if self.if_f0 == 1:
|
389 |
+
f0_extractor_frame = block_frame_16k + 800
|
390 |
+
if f0method == "rmvpe":
|
391 |
+
f0_extractor_frame = 5120 * ((f0_extractor_frame - 1) // 5120 + 1) - 160
|
392 |
+
pitch, pitchf = self.get_f0(
|
393 |
+
input_wav[-f0_extractor_frame:], self.f0_up_key, self.n_cpu, f0method
|
394 |
+
)
|
395 |
+
start_frame = block_frame_16k // 160
|
396 |
+
end_frame = len(self.cache_pitch) - (pitch.shape[0] - 4) + start_frame
|
397 |
+
self.cache_pitch[:] = np.append(
|
398 |
+
self.cache_pitch[start_frame:end_frame], pitch[3:-1]
|
399 |
+
)
|
400 |
+
self.cache_pitchf[:] = np.append(
|
401 |
+
self.cache_pitchf[start_frame:end_frame], pitchf[3:-1]
|
402 |
+
)
|
403 |
+
t4 = ttime()
|
404 |
+
p_len = input_wav.shape[0] // 160
|
405 |
+
if self.if_f0 == 1:
|
406 |
+
cache_pitch = (
|
407 |
+
torch.LongTensor(self.cache_pitch[-p_len:]).to(self.device).unsqueeze(0)
|
408 |
+
)
|
409 |
+
cache_pitchf = (
|
410 |
+
torch.FloatTensor(self.cache_pitchf[-p_len:])
|
411 |
+
.to(self.device)
|
412 |
+
.unsqueeze(0)
|
413 |
+
)
|
414 |
+
feats = F.interpolate(feats.permute(0, 2, 1), scale_factor=2).permute(0, 2, 1)
|
415 |
+
feats = feats[:, :p_len, :]
|
416 |
+
p_len = torch.LongTensor([p_len]).to(self.device)
|
417 |
+
sid = torch.LongTensor([0]).to(self.device)
|
418 |
+
skip_head = torch.LongTensor([skip_head])
|
419 |
+
return_length = torch.LongTensor([return_length])
|
420 |
+
with torch.no_grad():
|
421 |
+
if self.if_f0 == 1:
|
422 |
+
infered_audio, _, _ = self.net_g.infer(
|
423 |
+
feats,
|
424 |
+
p_len,
|
425 |
+
cache_pitch,
|
426 |
+
cache_pitchf,
|
427 |
+
sid,
|
428 |
+
skip_head,
|
429 |
+
return_length,
|
430 |
+
)
|
431 |
+
else:
|
432 |
+
infered_audio, _, _ = self.net_g.infer(
|
433 |
+
feats, p_len, sid, skip_head, return_length
|
434 |
+
)
|
435 |
+
t5 = ttime()
|
436 |
+
printt(
|
437 |
+
"Spent time: fea = %.3fs, index = %.3fs, f0 = %.3fs, model = %.3fs",
|
438 |
+
t2 - t1,
|
439 |
+
t3 - t2,
|
440 |
+
t4 - t3,
|
441 |
+
t5 - t4,
|
442 |
+
)
|
443 |
+
return infered_audio.squeeze().float()
|
tools/torchgate/__init__.py
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
TorchGating is a PyTorch-based implementation of Spectral Gating
|
3 |
+
================================================
|
4 |
+
Author: Asaf Zorea
|
5 |
+
|
6 |
+
Contents
|
7 |
+
--------
|
8 |
+
torchgate imports all the functions from PyTorch, and in addition provides:
|
9 |
+
TorchGating --- A PyTorch module that applies a spectral gate to an input signal
|
10 |
+
|
11 |
+
"""
|
12 |
+
|
13 |
+
from .torchgate import TorchGate
|
tools/torchgate/torchgate.py
ADDED
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
from infer.lib.rmvpe import STFT
|
3 |
+
from torch.nn.functional import conv1d, conv2d
|
4 |
+
from typing import Union, Optional
|
5 |
+
from .utils import linspace, temperature_sigmoid, amp_to_db
|
6 |
+
|
7 |
+
|
8 |
+
class TorchGate(torch.nn.Module):
|
9 |
+
"""
|
10 |
+
A PyTorch module that applies a spectral gate to an input signal.
|
11 |
+
|
12 |
+
Arguments:
|
13 |
+
sr {int} -- Sample rate of the input signal.
|
14 |
+
nonstationary {bool} -- Whether to use non-stationary or stationary masking (default: {False}).
|
15 |
+
n_std_thresh_stationary {float} -- Number of standard deviations above mean to threshold noise for
|
16 |
+
stationary masking (default: {1.5}).
|
17 |
+
n_thresh_nonstationary {float} -- Number of multiplies above smoothed magnitude spectrogram. for
|
18 |
+
non-stationary masking (default: {1.3}).
|
19 |
+
temp_coeff_nonstationary {float} -- Temperature coefficient for non-stationary masking (default: {0.1}).
|
20 |
+
n_movemean_nonstationary {int} -- Number of samples for moving average smoothing in non-stationary masking
|
21 |
+
(default: {20}).
|
22 |
+
prop_decrease {float} -- Proportion to decrease signal by where the mask is zero (default: {1.0}).
|
23 |
+
n_fft {int} -- Size of FFT for STFT (default: {1024}).
|
24 |
+
win_length {[int]} -- Window length for STFT. If None, defaults to `n_fft` (default: {None}).
|
25 |
+
hop_length {[int]} -- Hop length for STFT. If None, defaults to `win_length` // 4 (default: {None}).
|
26 |
+
freq_mask_smooth_hz {float} -- Frequency smoothing width for mask (in Hz). If None, no smoothing is applied
|
27 |
+
(default: {500}).
|
28 |
+
time_mask_smooth_ms {float} -- Time smoothing width for mask (in ms). If None, no smoothing is applied
|
29 |
+
(default: {50}).
|
30 |
+
"""
|
31 |
+
|
32 |
+
@torch.no_grad()
|
33 |
+
def __init__(
|
34 |
+
self,
|
35 |
+
sr: int,
|
36 |
+
nonstationary: bool = False,
|
37 |
+
n_std_thresh_stationary: float = 1.5,
|
38 |
+
n_thresh_nonstationary: float = 1.3,
|
39 |
+
temp_coeff_nonstationary: float = 0.1,
|
40 |
+
n_movemean_nonstationary: int = 20,
|
41 |
+
prop_decrease: float = 1.0,
|
42 |
+
n_fft: int = 1024,
|
43 |
+
win_length: bool = None,
|
44 |
+
hop_length: int = None,
|
45 |
+
freq_mask_smooth_hz: float = 500,
|
46 |
+
time_mask_smooth_ms: float = 50,
|
47 |
+
):
|
48 |
+
super().__init__()
|
49 |
+
|
50 |
+
# General Params
|
51 |
+
self.sr = sr
|
52 |
+
self.nonstationary = nonstationary
|
53 |
+
assert 0.0 <= prop_decrease <= 1.0
|
54 |
+
self.prop_decrease = prop_decrease
|
55 |
+
|
56 |
+
# STFT Params
|
57 |
+
self.n_fft = n_fft
|
58 |
+
self.win_length = self.n_fft if win_length is None else win_length
|
59 |
+
self.hop_length = self.win_length // 4 if hop_length is None else hop_length
|
60 |
+
|
61 |
+
# Stationary Params
|
62 |
+
self.n_std_thresh_stationary = n_std_thresh_stationary
|
63 |
+
|
64 |
+
# Non-Stationary Params
|
65 |
+
self.temp_coeff_nonstationary = temp_coeff_nonstationary
|
66 |
+
self.n_movemean_nonstationary = n_movemean_nonstationary
|
67 |
+
self.n_thresh_nonstationary = n_thresh_nonstationary
|
68 |
+
|
69 |
+
# Smooth Mask Params
|
70 |
+
self.freq_mask_smooth_hz = freq_mask_smooth_hz
|
71 |
+
self.time_mask_smooth_ms = time_mask_smooth_ms
|
72 |
+
self.register_buffer("smoothing_filter", self._generate_mask_smoothing_filter())
|
73 |
+
|
74 |
+
@torch.no_grad()
|
75 |
+
def _generate_mask_smoothing_filter(self) -> Union[torch.Tensor, None]:
|
76 |
+
"""
|
77 |
+
A PyTorch module that applies a spectral gate to an input signal using the STFT.
|
78 |
+
|
79 |
+
Returns:
|
80 |
+
smoothing_filter (torch.Tensor): a 2D tensor representing the smoothing filter,
|
81 |
+
with shape (n_grad_freq, n_grad_time), where n_grad_freq is the number of frequency
|
82 |
+
bins to smooth and n_grad_time is the number of time frames to smooth.
|
83 |
+
If both self.freq_mask_smooth_hz and self.time_mask_smooth_ms are None, returns None.
|
84 |
+
"""
|
85 |
+
if self.freq_mask_smooth_hz is None and self.time_mask_smooth_ms is None:
|
86 |
+
return None
|
87 |
+
|
88 |
+
n_grad_freq = (
|
89 |
+
1
|
90 |
+
if self.freq_mask_smooth_hz is None
|
91 |
+
else int(self.freq_mask_smooth_hz / (self.sr / (self.n_fft / 2)))
|
92 |
+
)
|
93 |
+
if n_grad_freq < 1:
|
94 |
+
raise ValueError(
|
95 |
+
f"freq_mask_smooth_hz needs to be at least {int((self.sr / (self._n_fft / 2)))} Hz"
|
96 |
+
)
|
97 |
+
|
98 |
+
n_grad_time = (
|
99 |
+
1
|
100 |
+
if self.time_mask_smooth_ms is None
|
101 |
+
else int(self.time_mask_smooth_ms / ((self.hop_length / self.sr) * 1000))
|
102 |
+
)
|
103 |
+
if n_grad_time < 1:
|
104 |
+
raise ValueError(
|
105 |
+
f"time_mask_smooth_ms needs to be at least {int((self.hop_length / self.sr) * 1000)} ms"
|
106 |
+
)
|
107 |
+
|
108 |
+
if n_grad_time == 1 and n_grad_freq == 1:
|
109 |
+
return None
|
110 |
+
|
111 |
+
v_f = torch.cat(
|
112 |
+
[
|
113 |
+
linspace(0, 1, n_grad_freq + 1, endpoint=False),
|
114 |
+
linspace(1, 0, n_grad_freq + 2),
|
115 |
+
]
|
116 |
+
)[1:-1]
|
117 |
+
v_t = torch.cat(
|
118 |
+
[
|
119 |
+
linspace(0, 1, n_grad_time + 1, endpoint=False),
|
120 |
+
linspace(1, 0, n_grad_time + 2),
|
121 |
+
]
|
122 |
+
)[1:-1]
|
123 |
+
smoothing_filter = torch.outer(v_f, v_t).unsqueeze(0).unsqueeze(0)
|
124 |
+
|
125 |
+
return smoothing_filter / smoothing_filter.sum()
|
126 |
+
|
127 |
+
@torch.no_grad()
|
128 |
+
def _stationary_mask(
|
129 |
+
self, X_db: torch.Tensor, xn: Optional[torch.Tensor] = None
|
130 |
+
) -> torch.Tensor:
|
131 |
+
"""
|
132 |
+
Computes a stationary binary mask to filter out noise in a log-magnitude spectrogram.
|
133 |
+
|
134 |
+
Arguments:
|
135 |
+
X_db (torch.Tensor): 2D tensor of shape (frames, freq_bins) containing the log-magnitude spectrogram.
|
136 |
+
xn (torch.Tensor): 1D tensor containing the audio signal corresponding to X_db.
|
137 |
+
|
138 |
+
Returns:
|
139 |
+
sig_mask (torch.Tensor): Binary mask of the same shape as X_db, where values greater than the threshold
|
140 |
+
are set to 1, and the rest are set to 0.
|
141 |
+
"""
|
142 |
+
if xn is not None:
|
143 |
+
if "privateuseone" in str(xn.device):
|
144 |
+
if not hasattr(self, "stft"):
|
145 |
+
self.stft = STFT(
|
146 |
+
filter_length=self.n_fft,
|
147 |
+
hop_length=self.hop_length,
|
148 |
+
win_length=self.win_length,
|
149 |
+
window="hann",
|
150 |
+
).to(xn.device)
|
151 |
+
XN = self.stft.transform(xn)
|
152 |
+
else:
|
153 |
+
XN = torch.stft(
|
154 |
+
xn,
|
155 |
+
n_fft=self.n_fft,
|
156 |
+
hop_length=self.hop_length,
|
157 |
+
win_length=self.win_length,
|
158 |
+
return_complex=True,
|
159 |
+
pad_mode="constant",
|
160 |
+
center=True,
|
161 |
+
window=torch.hann_window(self.win_length).to(xn.device),
|
162 |
+
)
|
163 |
+
XN_db = amp_to_db(XN).to(dtype=X_db.dtype)
|
164 |
+
else:
|
165 |
+
XN_db = X_db
|
166 |
+
|
167 |
+
# calculate mean and standard deviation along the frequency axis
|
168 |
+
std_freq_noise, mean_freq_noise = torch.std_mean(XN_db, dim=-1)
|
169 |
+
|
170 |
+
# compute noise threshold
|
171 |
+
noise_thresh = mean_freq_noise + std_freq_noise * self.n_std_thresh_stationary
|
172 |
+
|
173 |
+
# create binary mask by thresholding the spectrogram
|
174 |
+
sig_mask = X_db > noise_thresh.unsqueeze(2)
|
175 |
+
return sig_mask
|
176 |
+
|
177 |
+
@torch.no_grad()
|
178 |
+
def _nonstationary_mask(self, X_abs: torch.Tensor) -> torch.Tensor:
|
179 |
+
"""
|
180 |
+
Computes a non-stationary binary mask to filter out noise in a log-magnitude spectrogram.
|
181 |
+
|
182 |
+
Arguments:
|
183 |
+
X_abs (torch.Tensor): 2D tensor of shape (frames, freq_bins) containing the magnitude spectrogram.
|
184 |
+
|
185 |
+
Returns:
|
186 |
+
sig_mask (torch.Tensor): Binary mask of the same shape as X_abs, where values greater than the threshold
|
187 |
+
are set to 1, and the rest are set to 0.
|
188 |
+
"""
|
189 |
+
X_smoothed = (
|
190 |
+
conv1d(
|
191 |
+
X_abs.reshape(-1, 1, X_abs.shape[-1]),
|
192 |
+
torch.ones(
|
193 |
+
self.n_movemean_nonstationary,
|
194 |
+
dtype=X_abs.dtype,
|
195 |
+
device=X_abs.device,
|
196 |
+
).view(1, 1, -1),
|
197 |
+
padding="same",
|
198 |
+
).view(X_abs.shape)
|
199 |
+
/ self.n_movemean_nonstationary
|
200 |
+
)
|
201 |
+
|
202 |
+
# Compute slowness ratio and apply temperature sigmoid
|
203 |
+
slowness_ratio = (X_abs - X_smoothed) / (X_smoothed + 1e-6)
|
204 |
+
sig_mask = temperature_sigmoid(
|
205 |
+
slowness_ratio, self.n_thresh_nonstationary, self.temp_coeff_nonstationary
|
206 |
+
)
|
207 |
+
|
208 |
+
return sig_mask
|
209 |
+
|
210 |
+
def forward(
|
211 |
+
self, x: torch.Tensor, xn: Optional[torch.Tensor] = None
|
212 |
+
) -> torch.Tensor:
|
213 |
+
"""
|
214 |
+
Apply the proposed algorithm to the input signal.
|
215 |
+
|
216 |
+
Arguments:
|
217 |
+
x (torch.Tensor): The input audio signal, with shape (batch_size, signal_length).
|
218 |
+
xn (Optional[torch.Tensor]): The noise signal used for stationary noise reduction. If `None`, the input
|
219 |
+
signal is used as the noise signal. Default: `None`.
|
220 |
+
|
221 |
+
Returns:
|
222 |
+
torch.Tensor: The denoised audio signal, with the same shape as the input signal.
|
223 |
+
"""
|
224 |
+
|
225 |
+
# Compute short-time Fourier transform (STFT)
|
226 |
+
if "privateuseone" in str(x.device):
|
227 |
+
if not hasattr(self, "stft"):
|
228 |
+
self.stft = STFT(
|
229 |
+
filter_length=self.n_fft,
|
230 |
+
hop_length=self.hop_length,
|
231 |
+
win_length=self.win_length,
|
232 |
+
window="hann",
|
233 |
+
).to(x.device)
|
234 |
+
X, phase = self.stft.transform(x, return_phase=True)
|
235 |
+
else:
|
236 |
+
X = torch.stft(
|
237 |
+
x,
|
238 |
+
n_fft=self.n_fft,
|
239 |
+
hop_length=self.hop_length,
|
240 |
+
win_length=self.win_length,
|
241 |
+
return_complex=True,
|
242 |
+
pad_mode="constant",
|
243 |
+
center=True,
|
244 |
+
window=torch.hann_window(self.win_length).to(x.device),
|
245 |
+
)
|
246 |
+
|
247 |
+
# Compute signal mask based on stationary or nonstationary assumptions
|
248 |
+
if self.nonstationary:
|
249 |
+
sig_mask = self._nonstationary_mask(X.abs())
|
250 |
+
else:
|
251 |
+
sig_mask = self._stationary_mask(amp_to_db(X), xn)
|
252 |
+
|
253 |
+
# Propagate decrease in signal power
|
254 |
+
sig_mask = self.prop_decrease * (sig_mask.float() - 1.0) + 1.0
|
255 |
+
|
256 |
+
# Smooth signal mask with 2D convolution
|
257 |
+
if self.smoothing_filter is not None:
|
258 |
+
sig_mask = conv2d(
|
259 |
+
sig_mask.unsqueeze(1),
|
260 |
+
self.smoothing_filter.to(sig_mask.dtype),
|
261 |
+
padding="same",
|
262 |
+
)
|
263 |
+
|
264 |
+
# Apply signal mask to STFT magnitude and phase components
|
265 |
+
Y = X * sig_mask.squeeze(1)
|
266 |
+
|
267 |
+
# Inverse STFT to obtain time-domain signal
|
268 |
+
if "privateuseone" in str(Y.device):
|
269 |
+
y = self.stft.inverse(Y, phase)
|
270 |
+
else:
|
271 |
+
y = torch.istft(
|
272 |
+
Y,
|
273 |
+
n_fft=self.n_fft,
|
274 |
+
hop_length=self.hop_length,
|
275 |
+
win_length=self.win_length,
|
276 |
+
center=True,
|
277 |
+
window=torch.hann_window(self.win_length).to(Y.device),
|
278 |
+
)
|
279 |
+
|
280 |
+
return y.to(dtype=x.dtype)
|
tools/torchgate/utils.py
ADDED
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
from torch.types import Number
|
3 |
+
|
4 |
+
|
5 |
+
@torch.no_grad()
|
6 |
+
def amp_to_db(
|
7 |
+
x: torch.Tensor, eps=torch.finfo(torch.float64).eps, top_db=40
|
8 |
+
) -> torch.Tensor:
|
9 |
+
"""
|
10 |
+
Convert the input tensor from amplitude to decibel scale.
|
11 |
+
|
12 |
+
Arguments:
|
13 |
+
x {[torch.Tensor]} -- [Input tensor.]
|
14 |
+
|
15 |
+
Keyword Arguments:
|
16 |
+
eps {[float]} -- [Small value to avoid numerical instability.]
|
17 |
+
(default: {torch.finfo(torch.float64).eps})
|
18 |
+
top_db {[float]} -- [threshold the output at ``top_db`` below the peak]
|
19 |
+
` (default: {40})
|
20 |
+
|
21 |
+
Returns:
|
22 |
+
[torch.Tensor] -- [Output tensor in decibel scale.]
|
23 |
+
"""
|
24 |
+
x_db = 20 * torch.log10(x.abs() + eps)
|
25 |
+
return torch.max(x_db, (x_db.max(-1).values - top_db).unsqueeze(-1))
|
26 |
+
|
27 |
+
|
28 |
+
@torch.no_grad()
|
29 |
+
def temperature_sigmoid(x: torch.Tensor, x0: float, temp_coeff: float) -> torch.Tensor:
|
30 |
+
"""
|
31 |
+
Apply a sigmoid function with temperature scaling.
|
32 |
+
|
33 |
+
Arguments:
|
34 |
+
x {[torch.Tensor]} -- [Input tensor.]
|
35 |
+
x0 {[float]} -- [Parameter that controls the threshold of the sigmoid.]
|
36 |
+
temp_coeff {[float]} -- [Parameter that controls the slope of the sigmoid.]
|
37 |
+
|
38 |
+
Returns:
|
39 |
+
[torch.Tensor] -- [Output tensor after applying the sigmoid with temperature scaling.]
|
40 |
+
"""
|
41 |
+
return torch.sigmoid((x - x0) / temp_coeff)
|
42 |
+
|
43 |
+
|
44 |
+
@torch.no_grad()
|
45 |
+
def linspace(
|
46 |
+
start: Number, stop: Number, num: int = 50, endpoint: bool = True, **kwargs
|
47 |
+
) -> torch.Tensor:
|
48 |
+
"""
|
49 |
+
Generate a linearly spaced 1-D tensor.
|
50 |
+
|
51 |
+
Arguments:
|
52 |
+
start {[Number]} -- [The starting value of the sequence.]
|
53 |
+
stop {[Number]} -- [The end value of the sequence, unless `endpoint` is set to False.
|
54 |
+
In that case, the sequence consists of all but the last of ``num + 1``
|
55 |
+
evenly spaced samples, so that `stop` is excluded. Note that the step
|
56 |
+
size changes when `endpoint` is False.]
|
57 |
+
|
58 |
+
Keyword Arguments:
|
59 |
+
num {[int]} -- [Number of samples to generate. Default is 50. Must be non-negative.]
|
60 |
+
endpoint {[bool]} -- [If True, `stop` is the last sample. Otherwise, it is not included.
|
61 |
+
Default is True.]
|
62 |
+
**kwargs -- [Additional arguments to be passed to the underlying PyTorch `linspace` function.]
|
63 |
+
|
64 |
+
Returns:
|
65 |
+
[torch.Tensor] -- [1-D tensor of `num` equally spaced samples from `start` to `stop`.]
|
66 |
+
"""
|
67 |
+
if endpoint:
|
68 |
+
return torch.linspace(start, stop, num, **kwargs)
|
69 |
+
else:
|
70 |
+
return torch.linspace(start, stop, num + 1, **kwargs)[:-1]
|