mirror of
https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI.git
synced 2026-01-25 05:21:45 +00:00
Compare commits
66 Commits
v1
...
2.0.230528
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
95a14b734d | ||
|
|
f0a798c53f | ||
|
|
e435b3bb8a | ||
|
|
e569477457 | ||
|
|
d0249262b3 | ||
|
|
0841d1341b | ||
|
|
7bd25c4623 | ||
|
|
e8d92c3e91 | ||
|
|
619e9060aa | ||
|
|
35aa864daa | ||
|
|
e53118c60f | ||
|
|
c93940a25d | ||
|
|
f1730d42d4 | ||
|
|
7789c46ded | ||
|
|
4b0c86fbeb | ||
|
|
2280f3e392 | ||
|
|
7816761bee | ||
|
|
a2ef4cca76 | ||
|
|
0729c9d6f2 | ||
|
|
039e7afb85 | ||
|
|
e0813eb282 | ||
|
|
8efb101401 | ||
|
|
a4c86a3aa1 | ||
|
|
9cee20f402 | ||
|
|
cfd9848128 | ||
|
|
067731db9b | ||
|
|
c3de24f2e0 | ||
|
|
f6e55485d9 | ||
|
|
615c30c17b | ||
|
|
79a79c3b99 | ||
|
|
28948f8961 | ||
|
|
19cc9062b0 | ||
|
|
50a121fc74 | ||
|
|
3f17356c11 | ||
|
|
563bf7af6d | ||
|
|
41d2d72f39 | ||
|
|
080b7cdc31 | ||
|
|
563c64ded9 | ||
|
|
0fbfa1d62b | ||
|
|
c2039b6eca | ||
|
|
aadf7443c3 | ||
|
|
6fb1f8c1b1 | ||
|
|
e5374b2041 | ||
|
|
30c7e417e8 | ||
|
|
da0b599fa7 | ||
|
|
2ec95ab288 | ||
|
|
5bf26dadca | ||
|
|
0b0bd911d9 | ||
|
|
8a9909bdd1 | ||
|
|
9d949118c0 | ||
|
|
1c01099dbc | ||
|
|
b07dedd744 | ||
|
|
137447bdc9 | ||
|
|
f4c2a63a5e | ||
|
|
2d845e5222 | ||
|
|
e06994f473 | ||
|
|
6a3eaef090 | ||
|
|
32437314b8 | ||
|
|
ac807575ad | ||
|
|
b42f4bf6df | ||
|
|
1f63abe3e2 | ||
|
|
bbc3bcba3b | ||
|
|
60919b9b02 | ||
|
|
77ff5b08b6 | ||
|
|
404ce9338f | ||
|
|
3b5a2298d7 |
70
.github/workflows/docker.yml
vendored
Normal file
70
.github/workflows/docker.yml
vendored
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
name: Build And Push Docker Image
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
# Sequence of patterns matched against refs/tags
|
||||||
|
tags:
|
||||||
|
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
packages: write
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Set time zone
|
||||||
|
uses: szenius/set-timezone@v1.0
|
||||||
|
with:
|
||||||
|
timezoneLinux: "Asia/Shanghai"
|
||||||
|
timezoneMacos: "Asia/Shanghai"
|
||||||
|
timezoneWindows: "China Standard Time"
|
||||||
|
|
||||||
|
# # 如果有 dockerhub 账户,可以在github的secrets中配置下面两个,然后取消下面注释的这几行,并在meta步骤的images增加一行 ${{ github.repository }}
|
||||||
|
# - name: Login to DockerHub
|
||||||
|
# uses: docker/login-action@v1
|
||||||
|
# with:
|
||||||
|
# username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
# password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Login to GHCR
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Extract metadata (tags, labels) for Docker
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v4
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
ghcr.io/${{ github.repository }}
|
||||||
|
# generate Docker tags based on the following events/attributes
|
||||||
|
# nightly, master, pr-2, 1.2.3, 1.2, 1
|
||||||
|
tags: |
|
||||||
|
type=schedule,pattern=nightly
|
||||||
|
type=edge
|
||||||
|
type=ref,event=branch
|
||||||
|
type=ref,event=pr
|
||||||
|
type=semver,pattern={{version}}
|
||||||
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
|
type=semver,pattern={{major}}
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
id: docker_build
|
||||||
|
uses: docker/build-push-action@v4
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
8
.github/workflows/genlocale.yml
vendored
8
.github/workflows/genlocale.yml
vendored
@@ -1,11 +1,11 @@
|
|||||||
name: genlocale_v1
|
name: genlocale
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- v1
|
- main
|
||||||
jobs:
|
jobs:
|
||||||
genlocale_v1:
|
golangci:
|
||||||
name: genlocale_v1
|
name: genlocale
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out
|
- name: Check out
|
||||||
|
|||||||
9
.github/workflows/pull_format.yml
vendored
9
.github/workflows/pull_format.yml
vendored
@@ -1,14 +1,11 @@
|
|||||||
name: pull format v1
|
name: pull format
|
||||||
|
|
||||||
on:
|
on: [pull_request]
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- v1
|
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
jobs:
|
jobs:
|
||||||
pull_format_v1:
|
pull_format:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
10
.github/workflows/push_format.yml
vendored
10
.github/workflows/push_format.yml
vendored
@@ -1,20 +1,20 @@
|
|||||||
name: push format v1
|
name: push format
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- v1
|
- main
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
jobs:
|
jobs:
|
||||||
push_format_v1:
|
push_format:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
ref: v1
|
ref: ${{github.ref_name}}
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v4
|
||||||
@@ -44,5 +44,3 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
body: Apply Code Formatter Change
|
body: Apply Code Formatter Change
|
||||||
commit-message: Automatic code format
|
commit-message: Automatic code format
|
||||||
branch: create-pull-request/patchv1
|
|
||||||
delete-branch: true
|
|
||||||
|
|||||||
16
.github/workflows/unitest.yml
vendored
16
.github/workflows/unitest.yml
vendored
@@ -1,15 +1,7 @@
|
|||||||
name: unitest_v1
|
name: unitest
|
||||||
|
on: [ push, pull_request ]
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- v1
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- v1
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build_v1:
|
build:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
@@ -41,4 +33,4 @@ jobs:
|
|||||||
python trainset_preprocess_pipeline_print.py logs/mute/0_gt_wavs 48000 8 logs/mi-test True
|
python trainset_preprocess_pipeline_print.py logs/mute/0_gt_wavs 48000 8 logs/mi-test True
|
||||||
touch logs/mi-test/extract_f0_feature.log
|
touch logs/mi-test/extract_f0_feature.log
|
||||||
python extract_f0_print.py logs/mi-test $(nproc) pm
|
python extract_f0_print.py logs/mi-test $(nproc) pm
|
||||||
python extract_feature_print.py cpu 1 0 0 logs/mi-test
|
python extract_feature_print.py cpu 1 0 0 logs/mi-test v1
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -4,5 +4,3 @@ __pycache__
|
|||||||
*.pyd
|
*.pyd
|
||||||
hubert_base.pt
|
hubert_base.pt
|
||||||
/logs
|
/logs
|
||||||
.venv
|
|
||||||
/pretrained_v2
|
|
||||||
|
|||||||
@@ -1,5 +1,22 @@
|
|||||||
|
### 20230528更新
|
||||||
|
- 增加v2的jupyter notebook,韩文changelog,增加一些环境依赖
|
||||||
|
- 增加呼吸、清辅音、齿音保护模式
|
||||||
|
- 支持crepe-full推理
|
||||||
|
- UVR5人声伴奏分离加上3个去延迟模型和MDX-Net去混响模型,增加HP3人声提取模型
|
||||||
|
- 索引名称增加版本和实验名称
|
||||||
|
- 人声伴奏分离、推理批量导出增加音频导出格式选项
|
||||||
|
- 废弃32k模型的训练
|
||||||
|
|
||||||
|
todolist:
|
||||||
|
- 特征检索增加时序维度
|
||||||
|
- 特征检索增加pre-kmeans可选项
|
||||||
|
- 特征检索增加PCAR降维可选项
|
||||||
|
- 支持onnx推理(附带仅推理的小压缩包)
|
||||||
|
- 训练时在音高、gender、eq、噪声等方面对输入进行随机增强
|
||||||
|
- 补全v2版本的48k预训练模型
|
||||||
|
|
||||||
|
|
||||||
### 20230513更新
|
### 20230513更新
|
||||||
功能更新:
|
|
||||||
- 清除一键包内部老版本runtime内残留的infer_pack和uvr5_pack
|
- 清除一键包内部老版本runtime内残留的infer_pack和uvr5_pack
|
||||||
- 修复训练集预处理伪多进程的bug
|
- 修复训练集预处理伪多进程的bug
|
||||||
- 增加harvest识别音高可选通过中值滤波削弱哑音现象,可调整中值滤波半径
|
- 增加harvest识别音高可选通过中值滤波削弱哑音现象,可调整中值滤波半径
|
||||||
@@ -7,13 +24,16 @@
|
|||||||
- 训练n_cpu进程数从"仅调整f0提取"改为"调整数据预处理和f0提取"
|
- 训练n_cpu进程数从"仅调整f0提取"改为"调整数据预处理和f0提取"
|
||||||
- 自动检测logs文件夹下的index路径,提供下拉列表功能
|
- 自动检测logs文件夹下的index路径,提供下拉列表功能
|
||||||
- tab页增加"常见问题解答"(也可参考github-rvc-wiki)
|
- tab页增加"常见问题解答"(也可参考github-rvc-wiki)
|
||||||
|
- 相同路径的输入音频推理增加了音高缓存(用途:使用harvest音高提取,整个pipeline会经历漫长且重复的音高提取过程,如果不使用缓存,实验不同音色、索引、音高中值滤波半径参数的用户在第一次测试后的等待结果会非常痛苦)
|
||||||
|
|
||||||
待完成:
|
### 20230514更新
|
||||||
- 推理音量预处理归一化
|
- 音量包络对齐输入混合(可以缓解“输入静音输出小幅度噪声”的问题。如果输入音频背景底噪大则不建议开启,默认不开启(值为1可视为不开启))
|
||||||
- 推理后处理音量包络融合输入音频的音量包络
|
- 支持按照指定频率保存提取的小模型(假如你想尝试不同epoch下的推理效果,但是不想保存所有大checkpoint并且每次都要ckpt手工处理提取小模型,这项功能会非常实用)
|
||||||
- 增加选项:每次epoch保存的小模型均进行提取
|
- 通过设置环境变量解决服务端开了系统全局代理导致浏览器连接错误的问题
|
||||||
|
- 支持v2预训练模型(目前只公开了40k版本进行测试,另外2个采样率还没有训练完全)
|
||||||
|
- 推理前限制超过1的过大音量
|
||||||
|
- 微调数据预处理参数
|
||||||
|
|
||||||
RVC很快会陆续更新v2版的新底模(先发40k采样率的,32k和48k的仍在训练中)!大幅改善呼吸、清辅音(唇齿音)的电音和撕裂伪影,请期待!
|
|
||||||
|
|
||||||
### 20230409更新
|
### 20230409更新
|
||||||
- 修正训练参数,提升显卡平均利用率,A100最高从25%提升至90%左右,V100:50%->90%左右,2060S:60%->85%左右,P40:25%->95%左右,训练速度显著提升
|
- 修正训练参数,提升显卡平均利用率,A100最高从25%提升至90%左右,V100:50%->90%左右,2060S:60%->85%左右,P40:25%->95%左右,训练速度显著提升
|
||||||
@@ -40,12 +60,9 @@ RVC很快会陆续更新v2版的新底模(先发40k采样率的,32k和48k的
|
|||||||
|
|
||||||
### 后续计划:
|
### 后续计划:
|
||||||
功能:
|
功能:
|
||||||
- 增加选项:每次epoch保存的小模型均进行提取
|
|
||||||
- 增加选项:推理额外导出mp3至填写的路径(批量推理)
|
|
||||||
- 支持多人训练选项卡(至多4人)
|
- 支持多人训练选项卡(至多4人)
|
||||||
|
|
||||||
底模:
|
底模:
|
||||||
- 收集呼吸wav加入训练集修正呼吸变声电音的问题
|
- 收集呼吸wav加入训练集修正呼吸变声电音的问题
|
||||||
- 我们正在训练增加了歌声训练集的底模,未来会公开
|
- 我们正在训练增加了歌声训练集的底模,未来会公开
|
||||||
- 升级鉴别器(尝试MRD)
|
|
||||||
- 升级自监督特征结构
|
|
||||||
|
|||||||
@@ -1,3 +1,43 @@
|
|||||||
|
### 2023-05-28
|
||||||
|
- Add v2 jupyter notebook, korean changelog, fix some environment requirments
|
||||||
|
- Add voiceless consonant and breath protection mode
|
||||||
|
- Support crepe-full pitch detect
|
||||||
|
- UVR5 vocal separation: support dereverb models and de-echo models
|
||||||
|
- Add experiment name and version on the name of index
|
||||||
|
- Support users to manually select export format of output audios when batch voice conversion processing and UVR5 vocal separation
|
||||||
|
- 32k model training is no more supported
|
||||||
|
|
||||||
|
todolist:
|
||||||
|
- Feature retrieval: add temporal feature retrieval
|
||||||
|
- Feature retrieval: add pre-kmeans option
|
||||||
|
- Feature retrieval: add PCAR dimensionality reduction
|
||||||
|
- Add onnx inference support
|
||||||
|
- Random data augmentation when training: pitch, gender, eq, noise
|
||||||
|
- Add v2 version pretrained-models
|
||||||
|
|
||||||
|
### 2023-05-13
|
||||||
|
- Clear the redundant codes in the old version of runtime in the one-click-package: infer_pack and uvr5_pack
|
||||||
|
- Fix pseudo multiprocessing bug in training set preprocessing
|
||||||
|
- Adding median filtering radius adjustment for harvest pitch recognize algorithm
|
||||||
|
- Support post processing resampling for exporting audio
|
||||||
|
- Multi processing "n_cpu" setting for training is changed from "f0 extraction" to "data preprocessing and f0 extraction"
|
||||||
|
- Automatically detect the index paths under the logs folder and provide a drop-down list function
|
||||||
|
- Add "Frequently Asked Questions and Answers" on the tab page (you can also refer to github RVC wiki)
|
||||||
|
- When inference, harvest pitch is cached when using same input audio path (purpose: using harvest pitch extraction, the entire pipeline will go through a long and repetitive pitch extraction process. If caching is not used, users who experiment with different timbre, index, and pitch median filtering radius settings will experience a very painful waiting process after the first inference)
|
||||||
|
|
||||||
|
### 2023-05-14
|
||||||
|
- Use volume envelope of input to mix or replace the volume envelope of output (can alleviate the problem of "input muting and output small amplitude noise". If the input audio background noise is high, it is not recommended to turn it on, and it is not turned on by default (1 can be considered as not turned on)
|
||||||
|
- Support saving extracted small models at a specified frequency (if you want to see the performance under different epochs, but do not want to save all large checkpoints and manually extract small models by ckpt-processing every time, this feature will be very practical)
|
||||||
|
- Resolve the issue of "connection errors" caused by the server's global proxy by setting environment variables
|
||||||
|
- Supports pre-trained v2 models (currently only 40k versions are publicly available for testing, and the other two sampling rates have not been fully trained yet)
|
||||||
|
- Limit excessive volume exceeding 1 before inference
|
||||||
|
- Slightly adjusted the settings of training-set preprocessing
|
||||||
|
|
||||||
|
|
||||||
|
#######################
|
||||||
|
|
||||||
|
History changelogs:
|
||||||
|
|
||||||
### 2023-04-09
|
### 2023-04-09
|
||||||
- Fixed training parameters to improve GPU utilization rate: A100 increased from 25% to around 90%, V100: 50% to around 90%, 2060S: 60% to around 85%, P40: 25% to around 95%; significantly improved training speed
|
- Fixed training parameters to improve GPU utilization rate: A100 increased from 25% to around 90%, V100: 50% to around 90%, 2060S: 60% to around 85%, P40: 25% to around 95%; significantly improved training speed
|
||||||
- Changed parameter: total batch_size is now per GPU batch_size
|
- Changed parameter: total batch_size is now per GPU batch_size
|
||||||
@@ -30,5 +70,3 @@ Features:
|
|||||||
Base model:
|
Base model:
|
||||||
- Collect breathing wav files to add to the training dataset to fix the issue of distorted breath sounds
|
- Collect breathing wav files to add to the training dataset to fix the issue of distorted breath sounds
|
||||||
- We are currently training a base model with an extended singing dataset, which will be released in the future
|
- We are currently training a base model with an extended singing dataset, which will be released in the future
|
||||||
- Upgrade discriminator
|
|
||||||
- Upgrade self-supervised feature structure
|
|
||||||
|
|||||||
69
Changelog_KO.md
Normal file
69
Changelog_KO.md
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
### 2023년 5월 13일 업데이트
|
||||||
|
|
||||||
|
- 원클릭 패키지의 이전 버전 런타임 내, 불필요한 코드(infer_pack 및 uvr5_pack) 제거.
|
||||||
|
- 훈련 세트 전처리의 유사 다중 처리 버그 수정.
|
||||||
|
- Harvest 피치 인식 알고리즘에 대한 중위수 필터링 반경 조정 추가.
|
||||||
|
- 오디오 내보낼 때, 후처리 리샘플링 지원.
|
||||||
|
- 훈련에 대한 다중 처리 "n_cpu" 설정이 "f0 추출"에서 "데이터 전처리 및 f0 추출"로 변경.
|
||||||
|
- logs 폴더 하의 인덱스 경로를 자동으로 감지 및 드롭다운 목록 기능 제공.
|
||||||
|
- 탭 페이지에 "자주 묻는 질문과 답변" 추가. (github RVC wiki 참조 가능)
|
||||||
|
- 동일한 입력 오디오 경로를 사용할 때 추론, Harvest 피치를 캐시.
|
||||||
|
(주의: Harvest 피치 추출을 사용하면 전체 파이프라인은 길고 반복적인 피치 추출 과정을 거치게됩니다. 캐싱을 하지 않는다면, 첫 inference 이후의 단계에서 timbre, 인덱스, 피치 중위수 필터링 반경 설정 등 대기시간이 엄청나게 길어집니다!)
|
||||||
|
|
||||||
|
### 2023년 5월 14일 업데이트
|
||||||
|
|
||||||
|
- 입력의 볼륨 캡슐을 사용하여 출력의 볼륨 캡슐을 혼합하거나 대체. (입력이 무음이거나 출력의 노이즈 문제를 최소화 할 수 있습니다. 입력 오디오의 배경 노이즈(소음)가 큰 경우 해당 기능을 사용하지 않는 것이 좋습니다. 기본적으로 비활성화 되어있는 옵션입니다. (1: 비활성화 상태))
|
||||||
|
- 추출된 소형 모델을 지정된 빈도로 저장하는 기능을 지원. (다양한 에폭 하에서의 성능을 보려고 하지만 모든 대형 체크포인트를 저장하고 매번 ckpt 처리를 통해 소형 모델을 수동으로 추출하고 싶지 않은 경우 이 기능은 매우 유용합니다)
|
||||||
|
- 환경 변수를 설정하여 서버의 전역 프록시로 인한 "연결 오류" 문제 해결.
|
||||||
|
- 사전 훈련된 v2 모델 지원. (현재 40k 버전만 테스트를 위해 공개적으로 사용 가능하며, 다른 두 개의 샘플링 비율은 아직 완전히 훈련되지 않아 보류되었습니다.)
|
||||||
|
- 추론 전, 1을 초과하는 과도한 볼륨 제한.
|
||||||
|
- 데이터 전처리 매개변수 미세 조정.
|
||||||
|
|
||||||
|
추후 업데이트 목록:
|
||||||
|
|
||||||
|
- 일괄 음성 변환 처리 시, 사용자가 수동으로 출력 오디오의 내보내기 형식 선택기능 지원.
|
||||||
|
- Crepe 피치 감지 지원.
|
||||||
|
|
||||||
|
이전 변경 로그:
|
||||||
|
|
||||||
|
### 2023년 4월 9일
|
||||||
|
|
||||||
|
- GPU 이용률 향상을 위해 훈련 파라미터 수정: A100은 25%에서 약 90%로 증가, V100: 50%에서 약 90%로 증가, 2060S: 60%에서 약 85%로 증가, P40: 25%에서 약 95%로 증가.
|
||||||
|
훈련 속도가 크게 향상.
|
||||||
|
- 매개변수 기준 변경: total batch_size는 GPU당 batch_size를 의미.
|
||||||
|
- total_epoch 변경: 최대 한도가 100에서 1000으로 증가. 기본값이 10에서 20으로 증가.
|
||||||
|
- ckpt 추출이 피치를 잘못 인식하여 비정상적인 추론을 유발하는 문제 수정.
|
||||||
|
- 분산 훈련 과정에서 각 랭크마다 ckpt를 저장하는 문제 수정.
|
||||||
|
- 특성 추출 과정에 나노 특성 필터링 적용.
|
||||||
|
- 무음 입력/출력이 랜덤하게 소음을 생성하는 문제 수정. (이전 모델은 새 데이터셋으로 다시 훈련해야 합니다)
|
||||||
|
|
||||||
|
### 2023년 4월 16일 업데이트
|
||||||
|
|
||||||
|
- 로컬 실시간 음성 변경 미니-GUI 추가, go-realtime-gui.bat를 더블 클릭하여 시작.
|
||||||
|
- 훈련 및 추론 중 50Hz 이하의 주파수 대역에 대해 필터링 적용.
|
||||||
|
- 훈련 및 추론의 pyworld 최소 피치 추출을 기본 80에서 50으로 낮춤. 이로 인해, 50-80Hz 사이의 남성 저음이 무음화되지 않습니다.
|
||||||
|
- 시스템 지역에 따른 WebUI 언어 변경 지원. (현재 en_US, ja_JP, zh_CN, zh_HK, zh_SG, zh_TW를 지원하며, 지원되지 않는 경우 기본값은 en_US)
|
||||||
|
- 일부 GPU의 인식 수정. (예: V100-16G 인식 실패, P4 인식 실패)
|
||||||
|
|
||||||
|
### 2023년 4월 28일 업데이트
|
||||||
|
|
||||||
|
- Faiss 인덱스 설정 업그레이드로 속도가 더 빨라지고 품질이 향상.
|
||||||
|
- total_npy에 대한 의존성 제거. 추후의 모델 공유는 total_npy 입력을 필요로 하지 않습니다.
|
||||||
|
- 16 시리즈 GPU에 대한 제한 해제, 4GB VRAM GPU에 대한 4GB 추론 설정 제공.
|
||||||
|
- 일부 오디오 형식에 대한 UVR5 보컬 동반 분리에서의 버그 수정.
|
||||||
|
- 실시간 음성 변경 미니-GUI는 이제 non-40k 및 non-lazy 피치 모델을 지원합니다.
|
||||||
|
|
||||||
|
### 미래 계획
|
||||||
|
|
||||||
|
Features:
|
||||||
|
|
||||||
|
- 각 에폭 저장에 대해 소형 모델 추출 옵션 추가.
|
||||||
|
- 추론 중 지정된 경로로 추가 mp3 내보내기 옵션 추가.
|
||||||
|
- 다중 사용자 훈련 탭 지원.(최대 4명)
|
||||||
|
|
||||||
|
Base model:
|
||||||
|
|
||||||
|
- 호흡 wav 파일을 수집하여 훈련 데이터셋에 추가, 이로써 왜곡된 호흡 소리 문제를 해결.
|
||||||
|
- 현재 확장된 노래 데이터셋을 이용하여 기본 모델을 훈련 중이며, 이는 미래에 발표될 예정.
|
||||||
|
- Discriminator 업그레이드.
|
||||||
|
- self-supervised 특성 구조 업그레이드.
|
||||||
253
MDXNet.py
Normal file
253
MDXNet.py
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
import soundfile as sf
|
||||||
|
import torch, pdb, time, argparse, os, warnings, sys, librosa
|
||||||
|
import numpy as np
|
||||||
|
import onnxruntime as ort
|
||||||
|
from scipy.io.wavfile import write
|
||||||
|
from tqdm import tqdm
|
||||||
|
import torch
|
||||||
|
import torch.nn as nn
|
||||||
|
|
||||||
|
dim_c = 4
|
||||||
|
|
||||||
|
|
||||||
|
class Conv_TDF_net_trim:
|
||||||
|
def __init__(
|
||||||
|
self, device, model_name, target_name, L, dim_f, dim_t, n_fft, hop=1024
|
||||||
|
):
|
||||||
|
super(Conv_TDF_net_trim, self).__init__()
|
||||||
|
|
||||||
|
self.dim_f = dim_f
|
||||||
|
self.dim_t = 2**dim_t
|
||||||
|
self.n_fft = n_fft
|
||||||
|
self.hop = hop
|
||||||
|
self.n_bins = self.n_fft // 2 + 1
|
||||||
|
self.chunk_size = hop * (self.dim_t - 1)
|
||||||
|
self.window = torch.hann_window(window_length=self.n_fft, periodic=True).to(
|
||||||
|
device
|
||||||
|
)
|
||||||
|
self.target_name = target_name
|
||||||
|
self.blender = "blender" in model_name
|
||||||
|
|
||||||
|
out_c = dim_c * 4 if target_name == "*" else dim_c
|
||||||
|
self.freq_pad = torch.zeros(
|
||||||
|
[1, out_c, self.n_bins - self.dim_f, self.dim_t]
|
||||||
|
).to(device)
|
||||||
|
|
||||||
|
self.n = L // 2
|
||||||
|
|
||||||
|
def stft(self, x):
|
||||||
|
x = x.reshape([-1, self.chunk_size])
|
||||||
|
x = torch.stft(
|
||||||
|
x,
|
||||||
|
n_fft=self.n_fft,
|
||||||
|
hop_length=self.hop,
|
||||||
|
window=self.window,
|
||||||
|
center=True,
|
||||||
|
return_complex=True,
|
||||||
|
)
|
||||||
|
x = torch.view_as_real(x)
|
||||||
|
x = x.permute([0, 3, 1, 2])
|
||||||
|
x = x.reshape([-1, 2, 2, self.n_bins, self.dim_t]).reshape(
|
||||||
|
[-1, dim_c, self.n_bins, self.dim_t]
|
||||||
|
)
|
||||||
|
return x[:, :, : self.dim_f]
|
||||||
|
|
||||||
|
def istft(self, x, freq_pad=None):
|
||||||
|
freq_pad = (
|
||||||
|
self.freq_pad.repeat([x.shape[0], 1, 1, 1])
|
||||||
|
if freq_pad is None
|
||||||
|
else freq_pad
|
||||||
|
)
|
||||||
|
x = torch.cat([x, freq_pad], -2)
|
||||||
|
c = 4 * 2 if self.target_name == "*" else 2
|
||||||
|
x = x.reshape([-1, c, 2, self.n_bins, self.dim_t]).reshape(
|
||||||
|
[-1, 2, self.n_bins, self.dim_t]
|
||||||
|
)
|
||||||
|
x = x.permute([0, 2, 3, 1])
|
||||||
|
x = x.contiguous()
|
||||||
|
x = torch.view_as_complex(x)
|
||||||
|
x = torch.istft(
|
||||||
|
x, n_fft=self.n_fft, hop_length=self.hop, window=self.window, center=True
|
||||||
|
)
|
||||||
|
return x.reshape([-1, c, self.chunk_size])
|
||||||
|
|
||||||
|
|
||||||
|
def get_models(device, dim_f, dim_t, n_fft):
|
||||||
|
return Conv_TDF_net_trim(
|
||||||
|
device=device,
|
||||||
|
model_name="Conv-TDF",
|
||||||
|
target_name="vocals",
|
||||||
|
L=11,
|
||||||
|
dim_f=dim_f,
|
||||||
|
dim_t=dim_t,
|
||||||
|
n_fft=n_fft,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
warnings.filterwarnings("ignore")
|
||||||
|
cpu = torch.device("cpu")
|
||||||
|
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
|
||||||
|
|
||||||
|
|
||||||
|
class Predictor:
|
||||||
|
def __init__(self, args):
|
||||||
|
self.args = args
|
||||||
|
self.model_ = get_models(
|
||||||
|
device=cpu, dim_f=args.dim_f, dim_t=args.dim_t, n_fft=args.n_fft
|
||||||
|
)
|
||||||
|
self.model = ort.InferenceSession(
|
||||||
|
os.path.join(args.onnx, self.model_.target_name + ".onnx"),
|
||||||
|
providers=["CUDAExecutionProvider", "CPUExecutionProvider"],
|
||||||
|
)
|
||||||
|
print("onnx load done")
|
||||||
|
|
||||||
|
def demix(self, mix):
|
||||||
|
samples = mix.shape[-1]
|
||||||
|
margin = self.args.margin
|
||||||
|
chunk_size = self.args.chunks * 44100
|
||||||
|
assert not margin == 0, "margin cannot be zero!"
|
||||||
|
if margin > chunk_size:
|
||||||
|
margin = chunk_size
|
||||||
|
|
||||||
|
segmented_mix = {}
|
||||||
|
|
||||||
|
if self.args.chunks == 0 or samples < chunk_size:
|
||||||
|
chunk_size = samples
|
||||||
|
|
||||||
|
counter = -1
|
||||||
|
for skip in range(0, samples, chunk_size):
|
||||||
|
counter += 1
|
||||||
|
|
||||||
|
s_margin = 0 if counter == 0 else margin
|
||||||
|
end = min(skip + chunk_size + margin, samples)
|
||||||
|
|
||||||
|
start = skip - s_margin
|
||||||
|
|
||||||
|
segmented_mix[skip] = mix[:, start:end].copy()
|
||||||
|
if end == samples:
|
||||||
|
break
|
||||||
|
|
||||||
|
sources = self.demix_base(segmented_mix, margin_size=margin)
|
||||||
|
"""
|
||||||
|
mix:(2,big_sample)
|
||||||
|
segmented_mix:offset->(2,small_sample)
|
||||||
|
sources:(1,2,big_sample)
|
||||||
|
"""
|
||||||
|
return sources
|
||||||
|
|
||||||
|
def demix_base(self, mixes, margin_size):
|
||||||
|
chunked_sources = []
|
||||||
|
progress_bar = tqdm(total=len(mixes))
|
||||||
|
progress_bar.set_description("Processing")
|
||||||
|
for mix in mixes:
|
||||||
|
cmix = mixes[mix]
|
||||||
|
sources = []
|
||||||
|
n_sample = cmix.shape[1]
|
||||||
|
model = self.model_
|
||||||
|
trim = model.n_fft // 2
|
||||||
|
gen_size = model.chunk_size - 2 * trim
|
||||||
|
pad = gen_size - n_sample % gen_size
|
||||||
|
mix_p = np.concatenate(
|
||||||
|
(np.zeros((2, trim)), cmix, np.zeros((2, pad)), np.zeros((2, trim))), 1
|
||||||
|
)
|
||||||
|
mix_waves = []
|
||||||
|
i = 0
|
||||||
|
while i < n_sample + pad:
|
||||||
|
waves = np.array(mix_p[:, i : i + model.chunk_size])
|
||||||
|
mix_waves.append(waves)
|
||||||
|
i += gen_size
|
||||||
|
mix_waves = torch.tensor(mix_waves, dtype=torch.float32).to(cpu)
|
||||||
|
with torch.no_grad():
|
||||||
|
_ort = self.model
|
||||||
|
spek = model.stft(mix_waves)
|
||||||
|
if self.args.denoise:
|
||||||
|
spec_pred = (
|
||||||
|
-_ort.run(None, {"input": -spek.cpu().numpy()})[0] * 0.5
|
||||||
|
+ _ort.run(None, {"input": spek.cpu().numpy()})[0] * 0.5
|
||||||
|
)
|
||||||
|
tar_waves = model.istft(torch.tensor(spec_pred))
|
||||||
|
else:
|
||||||
|
tar_waves = model.istft(
|
||||||
|
torch.tensor(_ort.run(None, {"input": spek.cpu().numpy()})[0])
|
||||||
|
)
|
||||||
|
tar_signal = (
|
||||||
|
tar_waves[:, :, trim:-trim]
|
||||||
|
.transpose(0, 1)
|
||||||
|
.reshape(2, -1)
|
||||||
|
.numpy()[:, :-pad]
|
||||||
|
)
|
||||||
|
|
||||||
|
start = 0 if mix == 0 else margin_size
|
||||||
|
end = None if mix == list(mixes.keys())[::-1][0] else -margin_size
|
||||||
|
if margin_size == 0:
|
||||||
|
end = None
|
||||||
|
sources.append(tar_signal[:, start:end])
|
||||||
|
|
||||||
|
progress_bar.update(1)
|
||||||
|
|
||||||
|
chunked_sources.append(sources)
|
||||||
|
_sources = np.concatenate(chunked_sources, axis=-1)
|
||||||
|
# del self.model
|
||||||
|
progress_bar.close()
|
||||||
|
return _sources
|
||||||
|
|
||||||
|
def prediction(self, m, vocal_root, others_root, format):
|
||||||
|
os.makedirs(vocal_root, exist_ok=True)
|
||||||
|
os.makedirs(others_root, exist_ok=True)
|
||||||
|
basename = os.path.basename(m)
|
||||||
|
mix, rate = librosa.load(m, mono=False, sr=44100)
|
||||||
|
if mix.ndim == 1:
|
||||||
|
mix = np.asfortranarray([mix, mix])
|
||||||
|
mix = mix.T
|
||||||
|
sources = self.demix(mix.T)
|
||||||
|
opt = sources[0].T
|
||||||
|
sf.write(
|
||||||
|
"%s/%s_main_vocal.%s" % (vocal_root, basename, format), mix - opt, rate
|
||||||
|
)
|
||||||
|
sf.write("%s/%s_others.%s" % (others_root, basename, format), opt, rate)
|
||||||
|
|
||||||
|
|
||||||
|
class MDXNetDereverb:
|
||||||
|
def __init__(self, chunks):
|
||||||
|
self.onnx = "uvr5_weights/onnx_dereverb_By_FoxJoy"
|
||||||
|
self.shifts = 10 #'Predict with randomised equivariant stabilisation'
|
||||||
|
self.mixing = "min_mag" # ['default','min_mag','max_mag']
|
||||||
|
self.chunks = chunks
|
||||||
|
self.margin = 44100
|
||||||
|
self.dim_t = 9
|
||||||
|
self.dim_f = 3072
|
||||||
|
self.n_fft = 6144
|
||||||
|
self.denoise = True
|
||||||
|
self.pred = Predictor(self)
|
||||||
|
|
||||||
|
def _path_audio_(self, input, vocal_root, others_root, format):
|
||||||
|
self.pred.prediction(input, vocal_root, others_root, format)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
dereverb = MDXNetDereverb(15)
|
||||||
|
from time import time as ttime
|
||||||
|
|
||||||
|
t0 = ttime()
|
||||||
|
dereverb._path_audio_(
|
||||||
|
"雪雪伴奏对消HP5.wav",
|
||||||
|
"vocal",
|
||||||
|
"others",
|
||||||
|
)
|
||||||
|
t1 = ttime()
|
||||||
|
print(t1 - t0)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
runtime\python.exe MDXNet.py
|
||||||
|
|
||||||
|
6G:
|
||||||
|
15/9:0.8G->6.8G
|
||||||
|
14:0.8G->6.5G
|
||||||
|
25:炸
|
||||||
|
|
||||||
|
half15:0.7G->6.6G,22.69s
|
||||||
|
fp32-15:0.7G->6.6G,20.85s
|
||||||
|
|
||||||
|
"""
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
<h1>Retrieval-based-Voice-Conversion-WebUI</h1>
|
<h1>Retrieval-based-Voice-Conversion-WebUI</h1>
|
||||||
一个基于VITS的简单易用的语音转换(变声器)框架<br><br>
|
一个基于VITS的简单易用的语音转换(变声器)框架<br><br>
|
||||||
|
|
||||||
[](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI)
|
[](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI)
|
||||||
|
|
||||||
<img src="https://counter.seku.su/cmoe?name=rvc&theme=r34" /><br>
|
<img src="https://counter.seku.su/cmoe?name=rvc&theme=r34" /><br>
|
||||||
|
|
||||||
@@ -85,6 +85,10 @@ hubert_base.pt
|
|||||||
|
|
||||||
./uvr5_weights
|
./uvr5_weights
|
||||||
|
|
||||||
|
想测试v2版本模型的话(v2版本模型将特征从 9层hubert+final_proj的256维输入 变更为 12层hubert的768维输入,并且增加了3个周期鉴别器),需要额外下载
|
||||||
|
|
||||||
|
./pretrained_v2
|
||||||
|
|
||||||
#如果你正在使用Windows,则你可能需要这个文件,若ffmpeg和ffprobe已安装则跳过; ubuntu/debian 用户可以通过apt install ffmpeg来安装这2个库
|
#如果你正在使用Windows,则你可能需要这个文件,若ffmpeg和ffprobe已安装则跳过; ubuntu/debian 用户可以通过apt install ffmpeg来安装这2个库
|
||||||
./ffmpeg
|
./ffmpeg
|
||||||
|
|
||||||
|
|||||||
400
Retrieval_based_Voice_Conversion_WebUI_v2.ipynb
Normal file
400
Retrieval_based_Voice_Conversion_WebUI_v2.ipynb
Normal file
@@ -0,0 +1,400 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"attachments": {},
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"id": "ZFFCx5J80SGa"
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"[](https://colab.research.google.com/github/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/Retrieval_based_Voice_Conversion_WebUI_v2.ipynb)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"id": "GmFP6bN9dvOq"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#@title 查看显卡\n",
|
||||||
|
"!nvidia-smi"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"id": "wjddIFr1oS3W"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#@title 安装依赖\n",
|
||||||
|
"!apt-get -y install build-essential python3-dev ffmpeg\n",
|
||||||
|
"!pip3 install --upgrade setuptools wheel\n",
|
||||||
|
"!pip3 install --upgrade pip\n",
|
||||||
|
"!pip3 install faiss-gpu fairseq gradio ffmpeg ffmpeg-python praat-parselmouth pyworld numpy==1.23.5 numba==0.56.4 librosa==0.9.2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"id": "ge_97mfpgqTm"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#@title 克隆仓库\n",
|
||||||
|
"\n",
|
||||||
|
"!git init\n",
|
||||||
|
"!git remote add origin https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI.git\n",
|
||||||
|
"!git fetch origin cfd984812804ddc9247d65b14c82cd32e56c1133 --depth=1 \n",
|
||||||
|
"!git reset --hard FETCH_HEAD\n",
|
||||||
|
"%cd /content/Retrieval-based-Voice-Conversion-WebUI"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"id": "BLDEZADkvlw1"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#@title 更新仓库(一般无需执行)\n",
|
||||||
|
"!git pull"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"id": "pqE0PrnuRqI2"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#@title 安装aria2\n",
|
||||||
|
"!apt -y install -qq aria2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"id": "UG3XpUwEomUz"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#@title 下载底模\n",
|
||||||
|
"\n",
|
||||||
|
"# v1\n",
|
||||||
|
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/D32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o D32k.pth\n",
|
||||||
|
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/D40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o D40k.pth\n",
|
||||||
|
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/D48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o D48k.pth\n",
|
||||||
|
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/G32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o G32k.pth\n",
|
||||||
|
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/G40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o G40k.pth\n",
|
||||||
|
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/G48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o G48k.pth\n",
|
||||||
|
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0D32k.pth\n",
|
||||||
|
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0D40k.pth\n",
|
||||||
|
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0D48k.pth\n",
|
||||||
|
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0G32k.pth\n",
|
||||||
|
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0G40k.pth\n",
|
||||||
|
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0G48k.pth\n",
|
||||||
|
"\n",
|
||||||
|
"#v2\n",
|
||||||
|
"# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/D32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o D32k.pth\n",
|
||||||
|
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/D40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o D40k.pth\n",
|
||||||
|
"# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/D48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o D48k.pth\n",
|
||||||
|
"# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/G32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o G32k.pth\n",
|
||||||
|
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/G40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o G40k.pth\n",
|
||||||
|
"# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/G48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o G48k.pth\n",
|
||||||
|
"# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0D32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o f0D32k.pth\n",
|
||||||
|
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0D40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o f0D40k.pth\n",
|
||||||
|
"# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0D48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o f0D48k.pth\n",
|
||||||
|
"# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0G32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o f0G32k.pth\n",
|
||||||
|
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0G40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o f0G40k.pth\n",
|
||||||
|
"# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0G48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o f0G48k.pth"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"id": "HugjmZqZRuiF"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#@title 下载人声分离模型\n",
|
||||||
|
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP2-人声vocals+非人声instrumentals.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/uvr5_weights -o HP2-人声vocals+非人声instrumentals.pth\n",
|
||||||
|
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP5-主旋律人声vocals+其他instrumentals.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/uvr5_weights -o HP5-主旋律人声vocals+其他instrumentals.pth"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"id": "2RCaT9FTR0ej"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#@title 下载hubert_base\n",
|
||||||
|
"!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/hubert_base.pt -d /content/Retrieval-based-Voice-Conversion-WebUI -o hubert_base.pt"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"id": "jwu07JgqoFON"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#@title 挂载谷歌云盘\n",
|
||||||
|
"\n",
|
||||||
|
"from google.colab import drive\n",
|
||||||
|
"drive.mount('/content/drive')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"id": "Mwk7Q0Loqzjx"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#@title 从谷歌云盘加载打包好的数据集到/content/dataset\n",
|
||||||
|
"\n",
|
||||||
|
"#@markdown 数据集位置\n",
|
||||||
|
"DATASET = \"/content/drive/MyDrive/dataset/lulu20230327_32k.zip\" #@param {type:\"string\"}\n",
|
||||||
|
"\n",
|
||||||
|
"!mkdir -p /content/dataset\n",
|
||||||
|
"!unzip -d /content/dataset -B {DATASET}"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"id": "PDlFxWHWEynD"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#@title 重命名数据集中的重名文件\n",
|
||||||
|
"!ls -a /content/dataset/\n",
|
||||||
|
"!rename 's/(\\w+)\\.(\\w+)~(\\d*)/$1_$3.$2/' /content/dataset/*.*~*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"id": "7vh6vphDwO0b"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#@title 启动web\n",
|
||||||
|
"%cd /content/Retrieval-based-Voice-Conversion-WebUI\n",
|
||||||
|
"# %load_ext tensorboard\n",
|
||||||
|
"# %tensorboard --logdir /content/Retrieval-based-Voice-Conversion-WebUI/logs\n",
|
||||||
|
"!python3 infer-web.py --colab --pycmd python3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"id": "FgJuNeAwx5Y_"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#@title 手动将训练后的模型文件备份到谷歌云盘\n",
|
||||||
|
"#@markdown 需要自己查看logs文件夹下模型的文件名,手动修改下方命令末尾的文件名\n",
|
||||||
|
"\n",
|
||||||
|
"#@markdown 模型名\n",
|
||||||
|
"MODELNAME = \"lulu\" #@param {type:\"string\"}\n",
|
||||||
|
"#@markdown 模型epoch\n",
|
||||||
|
"MODELEPOCH = 9600 #@param {type:\"integer\"}\n",
|
||||||
|
"\n",
|
||||||
|
"!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth /content/drive/MyDrive/{MODELNAME}_D_{MODELEPOCH}.pth\n",
|
||||||
|
"!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth /content/drive/MyDrive/{MODELNAME}_G_{MODELEPOCH}.pth\n",
|
||||||
|
"!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/added_*.index /content/drive/MyDrive/\n",
|
||||||
|
"!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/total_*.npy /content/drive/MyDrive/\n",
|
||||||
|
"\n",
|
||||||
|
"!cp /content/Retrieval-based-Voice-Conversion-WebUI/weights/{MODELNAME}.pth /content/drive/MyDrive/{MODELNAME}{MODELEPOCH}.pth"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"id": "OVQoLQJXS7WX"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#@title 从谷歌云盘恢复pth\n",
|
||||||
|
"#@markdown 需要自己查看logs文件夹下模型的文件名,手动修改下方命令末尾的文件名\n",
|
||||||
|
"\n",
|
||||||
|
"#@markdown 模型名\n",
|
||||||
|
"MODELNAME = \"lulu\" #@param {type:\"string\"}\n",
|
||||||
|
"#@markdown 模型epoch\n",
|
||||||
|
"MODELEPOCH = 7500 #@param {type:\"integer\"}\n",
|
||||||
|
"\n",
|
||||||
|
"!mkdir -p /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}\n",
|
||||||
|
"\n",
|
||||||
|
"!cp /content/drive/MyDrive/{MODELNAME}_D_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth\n",
|
||||||
|
"!cp /content/drive/MyDrive/{MODELNAME}_G_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth\n",
|
||||||
|
"!cp /content/drive/MyDrive/*.index /content/\n",
|
||||||
|
"!cp /content/drive/MyDrive/*.npy /content/\n",
|
||||||
|
"!cp /content/drive/MyDrive/{MODELNAME}{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/weights/{MODELNAME}.pth"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"id": "ZKAyuKb9J6dz"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#@title 手动预处理(不推荐)\n",
|
||||||
|
"#@markdown 模型名\n",
|
||||||
|
"MODELNAME = \"lulu\" #@param {type:\"string\"}\n",
|
||||||
|
"#@markdown 采样率\n",
|
||||||
|
"BITRATE = 48000 #@param {type:\"integer\"}\n",
|
||||||
|
"#@markdown 使用的进程数\n",
|
||||||
|
"THREADCOUNT = 8 #@param {type:\"integer\"}\n",
|
||||||
|
"\n",
|
||||||
|
"!python3 trainset_preprocess_pipeline_print.py /content/dataset {BITRATE} {THREADCOUNT} logs/{MODELNAME} True\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"id": "CrxJqzAUKmPJ"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#@title 手动提取特征(不推荐)\n",
|
||||||
|
"#@markdown 模型名\n",
|
||||||
|
"MODELNAME = \"lulu\" #@param {type:\"string\"}\n",
|
||||||
|
"#@markdown 使用的进程数\n",
|
||||||
|
"THREADCOUNT = 8 #@param {type:\"integer\"}\n",
|
||||||
|
"#@markdown 音高提取算法\n",
|
||||||
|
"ALGO = \"harvest\" #@param {type:\"string\"}\n",
|
||||||
|
"\n",
|
||||||
|
"!python3 extract_f0_print.py logs/{MODELNAME} {THREADCOUNT} {ALGO}\n",
|
||||||
|
"\n",
|
||||||
|
"!python3 extract_feature_print.py cpu 1 0 0 logs/{MODELNAME}\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"id": "IMLPLKOaKj58"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#@title 手动训练(不推荐)\n",
|
||||||
|
"#@markdown 模型名\n",
|
||||||
|
"MODELNAME = \"lulu\" #@param {type:\"string\"}\n",
|
||||||
|
"#@markdown 使用的GPU\n",
|
||||||
|
"USEGPU = \"0\" #@param {type:\"string\"}\n",
|
||||||
|
"#@markdown 批大小\n",
|
||||||
|
"BATCHSIZE = 32 #@param {type:\"integer\"}\n",
|
||||||
|
"#@markdown 停止的epoch\n",
|
||||||
|
"MODELEPOCH = 3200 #@param {type:\"integer\"}\n",
|
||||||
|
"#@markdown 保存epoch间隔\n",
|
||||||
|
"EPOCHSAVE = 100 #@param {type:\"integer\"}\n",
|
||||||
|
"#@markdown 采样率\n",
|
||||||
|
"MODELSAMPLE = \"48k\" #@param {type:\"string\"}\n",
|
||||||
|
"#@markdown 是否缓存训练集\n",
|
||||||
|
"CACHEDATA = 1 #@param {type:\"integer\"}\n",
|
||||||
|
"#@markdown 是否仅保存最新的ckpt文件\n",
|
||||||
|
"ONLYLATEST = 0 #@param {type:\"integer\"}\n",
|
||||||
|
"\n",
|
||||||
|
"!python3 train_nsf_sim_cache_sid_load_pretrain.py -e lulu -sr {MODELSAMPLE} -f0 1 -bs {BATCHSIZE} -g {USEGPU} -te {MODELEPOCH} -se {EPOCHSAVE} -pg pretrained/f0G{MODELSAMPLE}.pth -pd pretrained/f0D{MODELSAMPLE}.pth -l {ONLYLATEST} -c {CACHEDATA}\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"id": "haYA81hySuDl"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#@title 删除其它pth,只留选中的(慎点,仔细看代码)\n",
|
||||||
|
"#@markdown 模型名\n",
|
||||||
|
"MODELNAME = \"lulu\" #@param {type:\"string\"}\n",
|
||||||
|
"#@markdown 选中模型epoch\n",
|
||||||
|
"MODELEPOCH = 9600 #@param {type:\"integer\"}\n",
|
||||||
|
"\n",
|
||||||
|
"!echo \"备份选中的模型。。。\"\n",
|
||||||
|
"!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth /content/{MODELNAME}_D_{MODELEPOCH}.pth\n",
|
||||||
|
"!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth /content/{MODELNAME}_G_{MODELEPOCH}.pth\n",
|
||||||
|
"\n",
|
||||||
|
"!echo \"正在删除。。。\"\n",
|
||||||
|
"!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}\n",
|
||||||
|
"!rm /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/*.pth\n",
|
||||||
|
"\n",
|
||||||
|
"!echo \"恢复选中的模型。。。\"\n",
|
||||||
|
"!mv /content/{MODELNAME}_D_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth \n",
|
||||||
|
"!mv /content/{MODELNAME}_G_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth\n",
|
||||||
|
"\n",
|
||||||
|
"!echo \"删除完成\"\n",
|
||||||
|
"!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"id": "QhSiPTVPoIRh"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#@title 清除项目下所有文件,只留选中的模型(慎点,仔细看代码)\n",
|
||||||
|
"#@markdown 模型名\n",
|
||||||
|
"MODELNAME = \"lulu\" #@param {type:\"string\"}\n",
|
||||||
|
"#@markdown 选中模型epoch\n",
|
||||||
|
"MODELEPOCH = 9600 #@param {type:\"integer\"}\n",
|
||||||
|
"\n",
|
||||||
|
"!echo \"备份选中的模型。。。\"\n",
|
||||||
|
"!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth /content/{MODELNAME}_D_{MODELEPOCH}.pth\n",
|
||||||
|
"!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth /content/{MODELNAME}_G_{MODELEPOCH}.pth\n",
|
||||||
|
"\n",
|
||||||
|
"!echo \"正在删除。。。\"\n",
|
||||||
|
"!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}\n",
|
||||||
|
"!rm -rf /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/*\n",
|
||||||
|
"\n",
|
||||||
|
"!echo \"恢复选中的模型。。。\"\n",
|
||||||
|
"!mv /content/{MODELNAME}_D_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth \n",
|
||||||
|
"!mv /content/{MODELNAME}_G_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth\n",
|
||||||
|
"\n",
|
||||||
|
"!echo \"删除完成\"\n",
|
||||||
|
"!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"accelerator": "GPU",
|
||||||
|
"colab": {
|
||||||
|
"private_outputs": true,
|
||||||
|
"provenance": []
|
||||||
|
},
|
||||||
|
"gpuClass": "standard",
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"name": "python"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 0
|
||||||
|
}
|
||||||
24
config.py
24
config.py
@@ -3,6 +3,18 @@ import torch
|
|||||||
from multiprocessing import cpu_count
|
from multiprocessing import cpu_count
|
||||||
|
|
||||||
|
|
||||||
|
def config_file_change_fp32():
|
||||||
|
for config_file in ["32k.json", "40k.json", "48k.json"]:
|
||||||
|
with open(f"configs/{config_file}", "r") as f:
|
||||||
|
strr = f.read().replace("true", "false")
|
||||||
|
with open(f"configs/{config_file}", "w") as f:
|
||||||
|
f.write(strr)
|
||||||
|
with open("trainset_preprocess_pipeline_print.py", "r") as f:
|
||||||
|
strr = f.read().replace("3.7", "3.0")
|
||||||
|
with open("trainset_preprocess_pipeline_print.py", "w") as f:
|
||||||
|
f.write(strr)
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.device = "cuda:0"
|
self.device = "cuda:0"
|
||||||
@@ -60,15 +72,7 @@ class Config:
|
|||||||
):
|
):
|
||||||
print("16系/10系显卡和P40强制单精度")
|
print("16系/10系显卡和P40强制单精度")
|
||||||
self.is_half = False
|
self.is_half = False
|
||||||
for config_file in ["32k.json", "40k.json", "48k.json"]:
|
config_file_change_fp32()
|
||||||
with open(f"configs/{config_file}", "r") as f:
|
|
||||||
strr = f.read().replace("true", "false")
|
|
||||||
with open(f"configs/{config_file}", "w") as f:
|
|
||||||
f.write(strr)
|
|
||||||
with open("trainset_preprocess_pipeline_print.py", "r") as f:
|
|
||||||
strr = f.read().replace("3.7", "3.0")
|
|
||||||
with open("trainset_preprocess_pipeline_print.py", "w") as f:
|
|
||||||
f.write(strr)
|
|
||||||
else:
|
else:
|
||||||
self.gpu_name = None
|
self.gpu_name = None
|
||||||
self.gpu_mem = int(
|
self.gpu_mem = int(
|
||||||
@@ -87,10 +91,12 @@ class Config:
|
|||||||
print("没有发现支持的N卡, 使用MPS进行推理")
|
print("没有发现支持的N卡, 使用MPS进行推理")
|
||||||
self.device = "mps"
|
self.device = "mps"
|
||||||
self.is_half = False
|
self.is_half = False
|
||||||
|
config_file_change_fp32()
|
||||||
else:
|
else:
|
||||||
print("没有发现支持的N卡, 使用CPU进行推理")
|
print("没有发现支持的N卡, 使用CPU进行推理")
|
||||||
self.device = "cpu"
|
self.device = "cpu"
|
||||||
self.is_half = False
|
self.is_half = False
|
||||||
|
config_file_change_fp32()
|
||||||
|
|
||||||
if self.n_cpu == 0:
|
if self.n_cpu == 0:
|
||||||
self.n_cpu = cpu_count()
|
self.n_cpu = cpu_count()
|
||||||
|
|||||||
@@ -75,6 +75,10 @@ hubert_base.pt
|
|||||||
|
|
||||||
./uvr5_weights
|
./uvr5_weights
|
||||||
|
|
||||||
|
If you want to test the v2 version model (the v2 version model has changed the input from the 256 dimensional feature of 9-layer Hubert+final_proj to the 768 dimensional feature of 12-layer Hubert, and has added 3 period discriminators), you will need to download additional features
|
||||||
|
|
||||||
|
./pretrained_v2
|
||||||
|
|
||||||
#If you are using Windows, you may also need this dictionary, skip if FFmpeg is installed
|
#If you are using Windows, you may also need this dictionary, skip if FFmpeg is installed
|
||||||
ffmpeg.exe
|
ffmpeg.exe
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -15,8 +15,9 @@ VITS 기반의 간단하고 사용하기 쉬운 음성 변환 프레임워크.<b
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
------
|
---
|
||||||
[**업데이트 로그**](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI/blob/main/Changelog_CN.md)
|
|
||||||
|
[**업데이트 로그**](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI/blob/main/Changelog_KO.md)
|
||||||
|
|
||||||
[**English**](./README.en.md) | [**中文简体**](../README.md) | [**日本語**](./README.ja.md) | [**한국어**](./README.ko.md) ([**韓國語**](./README.ko.han.md))
|
[**English**](./README.en.md) | [**中文简体**](../README.md) | [**日本語**](./README.ja.md) | [**한국어**](./README.ko.md) ([**韓國語**](./README.ko.han.md))
|
||||||
|
|
||||||
@@ -29,18 +30,22 @@ VITS 기반의 간단하고 사용하기 쉬운 음성 변환 프레임워크.<b
|
|||||||
> 저작권 문제가 없는 고퀄리티의 노래를 이후에도 계속해서 훈련할 예정입니다.
|
> 저작권 문제가 없는 고퀄리티의 노래를 이후에도 계속해서 훈련할 예정입니다.
|
||||||
|
|
||||||
## 소개
|
## 소개
|
||||||
|
|
||||||
본 Repo는 다음과 같은 특징을 가지고 있습니다:
|
본 Repo는 다음과 같은 특징을 가지고 있습니다:
|
||||||
+ top1 검색을 이용하여 입력 음색 특징을 훈련 세트 음색 특징으로 대체하여 음색의 누출을 방지;
|
|
||||||
+ 상대적으로 낮은 성능의 GPU에서도 빠른 훈련 가능;
|
- top1 검색을 이용하여 입력 음색 특징을 훈련 세트 음색 특징으로 대체하여 음색의 누출을 방지;
|
||||||
+ 적은 양의 데이터로 훈련해도 좋은 결과를 얻을 수 있음 (최소 10분 이상의 저잡음 음성 데이터를 사용하는 것을 권장);
|
- 상대적으로 낮은 성능의 GPU에서도 빠른 훈련 가능;
|
||||||
+ 모델 융합을 통한 음색의 변조 가능 (ckpt 처리 탭->ckpt 병합 선택);
|
- 적은 양의 데이터로 훈련해도 좋은 결과를 얻을 수 있음 (최소 10분 이상의 저잡음 음성 데이터를 사용하는 것을 권장);
|
||||||
+ 사용하기 쉬운 WebUI (웹 인터페이스);
|
- 모델 융합을 통한 음색의 변조 가능 (ckpt 처리 탭->ckpt 병합 선택);
|
||||||
+ UVR5 모델을 이용하여 목소리와 배경음악의 빠른 분리;
|
- 사용하기 쉬운 WebUI (웹 인터페이스);
|
||||||
|
- UVR5 모델을 이용하여 목소리와 배경음악의 빠른 분리;
|
||||||
|
|
||||||
## 환경의 준비
|
## 환경의 준비
|
||||||
|
|
||||||
poetry를 통해 dependecies를 설치하는 것을 권장합니다.
|
poetry를 통해 dependecies를 설치하는 것을 권장합니다.
|
||||||
|
|
||||||
다음 명령은 Python 버전 3.8 이상의 환경에서 실행되어야 합니다:
|
다음 명령은 Python 버전 3.8 이상의 환경에서 실행되어야 합니다:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# PyTorch 관련 주요 dependencies 설치, 이미 설치되어 있는 경우 건너뛰기 가능
|
# PyTorch 관련 주요 dependencies 설치, 이미 설치되어 있는 경우 건너뛰기 가능
|
||||||
# 참조: https://pytorch.org/get-started/locally/
|
# 참조: https://pytorch.org/get-started/locally/
|
||||||
@@ -56,6 +61,7 @@ curl -sSL https://install.python-poetry.org | python3 -
|
|||||||
# Dependecies 설치
|
# Dependecies 설치
|
||||||
poetry install
|
poetry install
|
||||||
```
|
```
|
||||||
|
|
||||||
pip를 활용하여 dependencies를 설치하여도 무방합니다.
|
pip를 활용하여 dependencies를 설치하여도 무방합니다.
|
||||||
|
|
||||||
**공지**: `MacOS`에서 `faiss 1.7.2`를 사용하면 Segmentation Fault: 11 오류가 발생할 수 있습니다. 수동으로 pip를 사용하여 설치하는 경우 `pip install faiss-cpu==1.7.0`을 사용해야 합니다.
|
**공지**: `MacOS`에서 `faiss 1.7.2`를 사용하면 Segmentation Fault: 11 오류가 발생할 수 있습니다. 수동으로 pip를 사용하여 설치하는 경우 `pip install faiss-cpu==1.7.0`을 사용해야 합니다.
|
||||||
@@ -65,11 +71,13 @@ pip install -r requirements.txt
|
|||||||
```
|
```
|
||||||
|
|
||||||
## 기타 사전 모델 준비
|
## 기타 사전 모델 준비
|
||||||
|
|
||||||
RVC 모델은 추론과 훈련을 위하여 다른 사전 모델이 필요합니다.
|
RVC 모델은 추론과 훈련을 위하여 다른 사전 모델이 필요합니다.
|
||||||
|
|
||||||
[Huggingface space](https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main/)를 통해서 다운로드 할 수 있습니다.
|
[Huggingface space](https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main/)를 통해서 다운로드 할 수 있습니다.
|
||||||
|
|
||||||
다음은 RVC에 필요한 사전 모델 및 기타 파일 목록입니다:
|
다음은 RVC에 필요한 사전 모델 및 기타 파일 목록입니다:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
hubert_base.pt
|
hubert_base.pt
|
||||||
|
|
||||||
@@ -80,23 +88,27 @@ hubert_base.pt
|
|||||||
# Windows를 사용하는 경우 이 사전도 필요할 수 있습니다. FFmpeg가 설치되어 있으면 건너뛰어도 됩니다.
|
# Windows를 사용하는 경우 이 사전도 필요할 수 있습니다. FFmpeg가 설치되어 있으면 건너뛰어도 됩니다.
|
||||||
ffmpeg.exe
|
ffmpeg.exe
|
||||||
```
|
```
|
||||||
|
|
||||||
그 후 이하의 명령을 사용하여 WebUI를 시작할 수 있습니다:
|
그 후 이하의 명령을 사용하여 WebUI를 시작할 수 있습니다:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python infer-web.py
|
python infer-web.py
|
||||||
```
|
```
|
||||||
|
|
||||||
Windows를 사용하는 경우 `RVC-beta.7z`를 다운로드 및 압축 해제하여 RVC를 직접 사용하거나 `go-web.bat`을 사용하여 WebUi를 시작할 수 있습니다.
|
Windows를 사용하는 경우 `RVC-beta.7z`를 다운로드 및 압축 해제하여 RVC를 직접 사용하거나 `go-web.bat`을 사용하여 WebUi를 시작할 수 있습니다.
|
||||||
|
|
||||||
## 참고
|
## 참고
|
||||||
+ [ContentVec](https://github.com/auspicious3000/contentvec/)
|
|
||||||
+ [VITS](https://github.com/jaywalnut310/vits)
|
- [ContentVec](https://github.com/auspicious3000/contentvec/)
|
||||||
+ [HIFIGAN](https://github.com/jik876/hifi-gan)
|
- [VITS](https://github.com/jaywalnut310/vits)
|
||||||
+ [Gradio](https://github.com/gradio-app/gradio)
|
- [HIFIGAN](https://github.com/jik876/hifi-gan)
|
||||||
+ [FFmpeg](https://github.com/FFmpeg/FFmpeg)
|
- [Gradio](https://github.com/gradio-app/gradio)
|
||||||
+ [Ultimate Vocal Remover](https://github.com/Anjok07/ultimatevocalremovergui)
|
- [FFmpeg](https://github.com/FFmpeg/FFmpeg)
|
||||||
+ [audio-slicer](https://github.com/openvpi/audio-slicer)
|
- [Ultimate Vocal Remover](https://github.com/Anjok07/ultimatevocalremovergui)
|
||||||
|
- [audio-slicer](https://github.com/openvpi/audio-slicer)
|
||||||
|
|
||||||
## 모든 기여자 분들의 노력에 감사드립니다.
|
## 모든 기여자 분들의 노력에 감사드립니다.
|
||||||
|
|
||||||
<a href="https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI/graphs/contributors" target="_blank">
|
<a href="https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI/graphs/contributors" target="_blank">
|
||||||
<img src="https://contrib.rocks/image?repo=liujing04/Retrieval-based-Voice-Conversion-WebUI" />
|
<img src="https://contrib.rocks/image?repo=liujing04/Retrieval-based-Voice-Conversion-WebUI" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ Save via model extraction at the bottom of the ckpt processing tab.
|
|||||||
## Q14:File/memory error(when training)?
|
## Q14:File/memory error(when training)?
|
||||||
Too many processes and your memory is not enough. You may fix it by:
|
Too many processes and your memory is not enough. You may fix it by:
|
||||||
|
|
||||||
1、decrease "Number of CPU threads".
|
1、decrease the input in field "Threads of CPU".
|
||||||
|
|
||||||
2、pre-cut trainset to shorter audio files.
|
2、pre-cut trainset to shorter audio files.
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ set g32=f0G32k.pth
|
|||||||
set g40=f0G40k.pth
|
set g40=f0G40k.pth
|
||||||
set g48=f0G48k.pth
|
set g48=f0G48k.pth
|
||||||
|
|
||||||
|
set d40v2=f0D40k.pth
|
||||||
|
set g40v2=f0G40k.pth
|
||||||
|
|
||||||
set dld32=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D32k.pth
|
set dld32=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D32k.pth
|
||||||
set dld40=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D40k.pth
|
set dld40=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D40k.pth
|
||||||
set dld48=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D48k.pth
|
set dld48=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D48k.pth
|
||||||
@@ -37,11 +40,24 @@ set dlg32=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretra
|
|||||||
set dlg40=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G40k.pth
|
set dlg40=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G40k.pth
|
||||||
set dlg48=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G48k.pth
|
set dlg48=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G48k.pth
|
||||||
|
|
||||||
set hp2=HP2-人声vocals+非人声instrumentals.pth
|
set dld40v2=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0D40k.pth
|
||||||
set hp5=HP5-主旋律人声vocals+其他instrumentals.pth
|
set dlg40v2=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0G40k.pth
|
||||||
|
|
||||||
set dlhp2=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP2-人声vocals+非人声instrumentals.pth
|
set hp2_all=HP2_all_vocals.pth
|
||||||
set dlhp5=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP5-主旋律人声vocals+其他instrumentals.pth
|
set hp3_all=HP3_all_vocals.pth
|
||||||
|
set hp5_only=HP5_only_main_vocal.pth
|
||||||
|
set VR_DeEchoAggressive=VR-DeEchoAggressive.pth
|
||||||
|
set VR_DeEchoDeReverb=VR-DeEchoDeReverb.pth
|
||||||
|
set VR_DeEchoNormal=VR-DeEchoNormal.pth
|
||||||
|
set onnx_dereverb=vocals.onnx
|
||||||
|
|
||||||
|
set dlhp2_all=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP2_all_vocals.pth
|
||||||
|
set dlhp3_all=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP3_all_vocals.pth
|
||||||
|
set dlhp5_only=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP5_only_main_vocal.pth
|
||||||
|
set dlVR_DeEchoAggressive=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/VR-DeEchoAggressive.pth
|
||||||
|
set dlVR_DeEchoDeReverb=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/VR-DeEchoDeReverb.pth
|
||||||
|
set dlVR_DeEchoNormal=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/VR-DeEchoNormal.pth
|
||||||
|
set dlonnx_dereverb=https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/onnx_dereverb_By_FoxJoy/vocals.onnx
|
||||||
|
|
||||||
set hb=hubert_base.pt
|
set hb=hubert_base.pt
|
||||||
|
|
||||||
@@ -56,12 +72,24 @@ if exist "%~dp0pretrained" (
|
|||||||
echo failed. generating dir .\pretrained.
|
echo failed. generating dir .\pretrained.
|
||||||
mkdir pretrained
|
mkdir pretrained
|
||||||
)
|
)
|
||||||
|
if exist "%~dp0pretrained_v2" (
|
||||||
|
echo dir .\pretrained_v2 checked.
|
||||||
|
) else (
|
||||||
|
echo failed. generating dir .\pretrained_v2.
|
||||||
|
mkdir pretrained_v2
|
||||||
|
)
|
||||||
if exist "%~dp0uvr5_weights" (
|
if exist "%~dp0uvr5_weights" (
|
||||||
echo dir .\uvr5_weights checked.
|
echo dir .\uvr5_weights checked.
|
||||||
) else (
|
) else (
|
||||||
echo failed. generating dir .\uvr5_weights.
|
echo failed. generating dir .\uvr5_weights.
|
||||||
mkdir uvr5_weights
|
mkdir uvr5_weights
|
||||||
)
|
)
|
||||||
|
if exist "%~dp0uvr5_weights\onnx_dereverb_By_FoxJoy" (
|
||||||
|
echo dir .\uvr5_weights\onnx_dereverb_By_FoxJoy checked.
|
||||||
|
) else (
|
||||||
|
echo failed. generating dir .\uvr5_weights\onnx_dereverb_By_FoxJoy.
|
||||||
|
mkdir uvr5_weights\onnx_dereverb_By_FoxJoy
|
||||||
|
)
|
||||||
|
|
||||||
echo=
|
echo=
|
||||||
echo dir check finished.
|
echo dir check finished.
|
||||||
@@ -89,7 +117,17 @@ if exist "%~dp0pretrained\D40k.pth" (
|
|||||||
if exist "%~dp0pretrained\D40k.pth" (echo download successful.) else (echo please try again!
|
if exist "%~dp0pretrained\D40k.pth" (echo download successful.) else (echo please try again!
|
||||||
echo=)
|
echo=)
|
||||||
)
|
)
|
||||||
echo checking D48k.pth
|
echo checking D40k.pth
|
||||||
|
if exist "%~dp0pretrained_v2\D40k.pth" (
|
||||||
|
echo D40k.pth in .\pretrained_v2 checked.
|
||||||
|
echo=
|
||||||
|
) else (
|
||||||
|
echo failed. starting download from huggingface.
|
||||||
|
%~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 %~dp0pretrained_v2 -o D40k.pth
|
||||||
|
if exist "%~dp0pretrained_v2\D40k.pth" (echo download successful.) else (echo please try again!
|
||||||
|
echo=)
|
||||||
|
)
|
||||||
|
echo checking D48k.pth
|
||||||
if exist "%~dp0pretrained\D48k.pth" (
|
if exist "%~dp0pretrained\D48k.pth" (
|
||||||
echo D48k.pth in .\pretrained checked.
|
echo D48k.pth in .\pretrained checked.
|
||||||
echo=
|
echo=
|
||||||
@@ -99,7 +137,7 @@ if exist "%~dp0pretrained\D48k.pth" (
|
|||||||
if exist "%~dp0pretrained\D48k.pth" (echo download successful.) else (echo please try again!
|
if exist "%~dp0pretrained\D48k.pth" (echo download successful.) else (echo please try again!
|
||||||
echo=)
|
echo=)
|
||||||
)
|
)
|
||||||
echo checking G32k.pth
|
echo checking G32k.pth
|
||||||
if exist "%~dp0pretrained\G32k.pth" (
|
if exist "%~dp0pretrained\G32k.pth" (
|
||||||
echo G32k.pth in .\pretrained checked.
|
echo G32k.pth in .\pretrained checked.
|
||||||
echo=
|
echo=
|
||||||
@@ -109,7 +147,7 @@ if exist "%~dp0pretrained\G32k.pth" (
|
|||||||
if exist "%~dp0pretrained\G32k.pth" (echo download successful.) else (echo please try again!
|
if exist "%~dp0pretrained\G32k.pth" (echo download successful.) else (echo please try again!
|
||||||
echo=)
|
echo=)
|
||||||
)
|
)
|
||||||
echo checking G40k.pth
|
echo checking G40k.pth
|
||||||
if exist "%~dp0pretrained\G40k.pth" (
|
if exist "%~dp0pretrained\G40k.pth" (
|
||||||
echo G40k.pth in .\pretrained checked.
|
echo G40k.pth in .\pretrained checked.
|
||||||
echo=
|
echo=
|
||||||
@@ -119,7 +157,17 @@ if exist "%~dp0pretrained\G40k.pth" (
|
|||||||
if exist "%~dp0pretrained\G40k.pth" (echo download successful.) else (echo please try again!
|
if exist "%~dp0pretrained\G40k.pth" (echo download successful.) else (echo please try again!
|
||||||
echo=)
|
echo=)
|
||||||
)
|
)
|
||||||
echo checking G48k.pth
|
echo checking G40k.pth
|
||||||
|
if exist "%~dp0pretrained_v2\G40k.pth" (
|
||||||
|
echo G40k.pth in .\pretrained_v2 checked.
|
||||||
|
echo=
|
||||||
|
) else (
|
||||||
|
echo failed. starting download from huggingface.
|
||||||
|
%~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 %~dp0pretrained_v2 -o G40k.pth
|
||||||
|
if exist "%~dp0pretrained_v2\G40k.pth" (echo download successful.) else (echo please try again!
|
||||||
|
echo=)
|
||||||
|
)
|
||||||
|
echo checking G48k.pth
|
||||||
if exist "%~dp0pretrained\G48k.pth" (
|
if exist "%~dp0pretrained\G48k.pth" (
|
||||||
echo G48k.pth in .\pretrained checked.
|
echo G48k.pth in .\pretrained checked.
|
||||||
echo=
|
echo=
|
||||||
@@ -150,6 +198,16 @@ if exist "%~dp0pretrained\%d40%" (
|
|||||||
if exist "%~dp0pretrained\%d40%" (echo download successful.) else (echo please try again!
|
if exist "%~dp0pretrained\%d40%" (echo download successful.) else (echo please try again!
|
||||||
echo=)
|
echo=)
|
||||||
)
|
)
|
||||||
|
echo checking %d40v2%
|
||||||
|
if exist "%~dp0pretrained_v2\%d40v2%" (
|
||||||
|
echo %d40v2% in .\pretrained_v2 checked.
|
||||||
|
echo=
|
||||||
|
) else (
|
||||||
|
echo failed. starting download from huggingface.
|
||||||
|
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dld40v2% -d %~dp0pretrained_v2 -o %d40v2%
|
||||||
|
if exist "%~dp0pretrained_v2\%d40v2%" (echo download successful.) else (echo please try again!
|
||||||
|
echo=)
|
||||||
|
)
|
||||||
echo checking %d48%
|
echo checking %d48%
|
||||||
if exist "%~dp0pretrained\%d48%" (
|
if exist "%~dp0pretrained\%d48%" (
|
||||||
echo %d48% in .\pretrained checked.
|
echo %d48% in .\pretrained checked.
|
||||||
@@ -180,6 +238,16 @@ if exist "%~dp0pretrained\%g40%" (
|
|||||||
if exist "%~dp0pretrained\%g40%" (echo download successful.) else (echo please try again!
|
if exist "%~dp0pretrained\%g40%" (echo download successful.) else (echo please try again!
|
||||||
echo=)
|
echo=)
|
||||||
)
|
)
|
||||||
|
echo checking %g40v2%
|
||||||
|
if exist "%~dp0pretrained_v2\%g40v2%" (
|
||||||
|
echo %g40v2% in .\pretrained_v2 checked.
|
||||||
|
echo=
|
||||||
|
) else (
|
||||||
|
echo failed. starting download from huggingface.
|
||||||
|
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlg40v2% -d %~dp0pretrained_v2 -o %g40v2%
|
||||||
|
if exist "%~dp0pretrained_v2\%g40v2%" (echo download successful.) else (echo please try again!
|
||||||
|
echo=)
|
||||||
|
)
|
||||||
echo checking %g48%
|
echo checking %g48%
|
||||||
if exist "%~dp0pretrained\%g48%" (
|
if exist "%~dp0pretrained\%g48%" (
|
||||||
echo %g48% in .\pretrained checked.
|
echo %g48% in .\pretrained checked.
|
||||||
@@ -191,24 +259,74 @@ if exist "%~dp0pretrained\%g48%" (
|
|||||||
echo=)
|
echo=)
|
||||||
)
|
)
|
||||||
|
|
||||||
echo checking %hp2%
|
echo checking %hp2_all%
|
||||||
if exist "%~dp0uvr5_weights\%hp2%" (
|
if exist "%~dp0uvr5_weights\%hp2_all%" (
|
||||||
echo %hp2% in .\uvr5_weights checked.
|
echo %hp2_all% in .\uvr5_weights checked.
|
||||||
echo=
|
echo=
|
||||||
) else (
|
) else (
|
||||||
echo failed. starting download from huggingface.
|
echo failed. starting download from huggingface.
|
||||||
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlhp2% -d %~dp0\uvr5_weights -o %hp2%
|
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlhp2_all% -d %~dp0\uvr5_weights -o %hp2_all%
|
||||||
if exist "%~dp0uvr5_weights\%hp2%" (echo download successful.) else (echo please try again!
|
if exist "%~dp0uvr5_weights\%hp2_all%" (echo download successful.) else (echo please try again!
|
||||||
echo=)
|
echo=)
|
||||||
)
|
)
|
||||||
echo checking %hp5%
|
echo checking %hp3_all%
|
||||||
if exist "%~dp0uvr5_weights\%hp5%" (
|
if exist "%~dp0uvr5_weights\%hp3_all%" (
|
||||||
echo %hp5% in .\uvr5_weights checked.
|
echo %hp3_all% in .\uvr5_weights checked.
|
||||||
echo=
|
echo=
|
||||||
) else (
|
) else (
|
||||||
echo failed. starting download from huggingface.
|
echo failed. starting download from huggingface.
|
||||||
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlhp5% -d %~dp0\uvr5_weights -o %HP5%
|
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlhp3_all% -d %~dp0\uvr5_weights -o %hp3_all%
|
||||||
if exist "%~dp0uvr5_weights\%hp5%" (echo download successful.) else (echo please try again!
|
if exist "%~dp0uvr5_weights\%hp3_all%" (echo download successful.) else (echo please try again!
|
||||||
|
echo=)
|
||||||
|
)
|
||||||
|
echo checking %hp5_only%
|
||||||
|
if exist "%~dp0uvr5_weights\%hp5_only%" (
|
||||||
|
echo %hp5_only% in .\uvr5_weights checked.
|
||||||
|
echo=
|
||||||
|
) else (
|
||||||
|
echo failed. starting download from huggingface.
|
||||||
|
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlhp5_only% -d %~dp0\uvr5_weights -o %hp5_only%
|
||||||
|
if exist "%~dp0uvr5_weights\%hp5_only%" (echo download successful.) else (echo please try again!
|
||||||
|
echo=)
|
||||||
|
)
|
||||||
|
echo checking %VR_DeEchoAggressive%
|
||||||
|
if exist "%~dp0uvr5_weights\%VR_DeEchoAggressive%" (
|
||||||
|
echo %VR_DeEchoAggressive% in .\uvr5_weights checked.
|
||||||
|
echo=
|
||||||
|
) else (
|
||||||
|
echo failed. starting download from huggingface.
|
||||||
|
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlVR_DeEchoAggressive% -d %~dp0\uvr5_weights -o %VR_DeEchoAggressive%
|
||||||
|
if exist "%~dp0uvr5_weights\%VR_DeEchoAggressive%" (echo download successful.) else (echo please try again!
|
||||||
|
echo=)
|
||||||
|
)
|
||||||
|
echo checking %VR_DeEchoDeReverb%
|
||||||
|
if exist "%~dp0uvr5_weights\%VR_DeEchoDeReverb%" (
|
||||||
|
echo %VR_DeEchoDeReverb% in .\uvr5_weights checked.
|
||||||
|
echo=
|
||||||
|
) else (
|
||||||
|
echo failed. starting download from huggingface.
|
||||||
|
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlVR_DeEchoDeReverb% -d %~dp0\uvr5_weights -o %VR_DeEchoDeReverb%
|
||||||
|
if exist "%~dp0uvr5_weights\%VR_DeEchoDeReverb%" (echo download successful.) else (echo please try again!
|
||||||
|
echo=)
|
||||||
|
)
|
||||||
|
echo checking %VR_DeEchoNormal%
|
||||||
|
if exist "%~dp0uvr5_weights\%VR_DeEchoNormal%" (
|
||||||
|
echo %VR_DeEchoNormal% in .\uvr5_weights checked.
|
||||||
|
echo=
|
||||||
|
) else (
|
||||||
|
echo failed. starting download from huggingface.
|
||||||
|
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlVR_DeEchoNormal% -d %~dp0\uvr5_weights -o %VR_DeEchoNormal%
|
||||||
|
if exist "%~dp0uvr5_weights\%VR_DeEchoNormal%" (echo download successful.) else (echo please try again!
|
||||||
|
echo=)
|
||||||
|
)
|
||||||
|
echo checking %onnx_dereverb%
|
||||||
|
if exist "%~dp0uvr5_weights\onnx_dereverb_By_FoxJoy\%onnx_dereverb%" (
|
||||||
|
echo %onnx_dereverb% in .\uvr5_weights\onnx_dereverb_By_FoxJoy checked.
|
||||||
|
echo=
|
||||||
|
) else (
|
||||||
|
echo failed. starting download from huggingface.
|
||||||
|
%~dp0%aria2%\aria2c --console-log-level=error -c -x 16 -s 16 -k 1M %dlonnx_dereverb% -d %~dp0\uvr5_weights\onnx_dereverb_By_FoxJoy -o %onnx_dereverb%
|
||||||
|
if exist "%~dp0uvr5_weights\onnx_dereverb_By_FoxJoy\%onnx_dereverb%" (echo download successful.) else (echo please try again!
|
||||||
echo=)
|
echo=)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
from infer_pack.models_onnx_moess import SynthesizerTrnMs256NSFsidM
|
from infer_pack.models_onnx import SynthesizerTrnMsNSFsidM
|
||||||
from infer_pack.models_onnx import SynthesizerTrnMs256NSFsidO
|
|
||||||
import torch
|
import torch
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
@@ -21,65 +20,35 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
device = "cpu" # 导出时设备(不影响使用模型)
|
device = "cpu" # 导出时设备(不影响使用模型)
|
||||||
|
|
||||||
if MoeVS:
|
net_g = SynthesizerTrnMsNSFsidM(
|
||||||
net_g = SynthesizerTrnMs256NSFsidM(
|
*cpt["config"], is_half=False
|
||||||
*cpt["config"], is_half=False
|
) # fp32导出(C++要支持fp16必须手动将内存重新排列所以暂时不用fp16)
|
||||||
) # fp32导出(C++要支持fp16必须手动将内存重新排列所以暂时不用fp16)
|
net_g.load_state_dict(cpt["weight"], strict=False)
|
||||||
net_g.load_state_dict(cpt["weight"], strict=False)
|
input_names = ["phone", "phone_lengths", "pitch", "pitchf", "ds", "rnd"]
|
||||||
input_names = ["phone", "phone_lengths", "pitch", "pitchf", "ds", "rnd"]
|
output_names = [
|
||||||
output_names = [
|
"audio",
|
||||||
"audio",
|
]
|
||||||
]
|
# net_g.construct_spkmixmap(n_speaker) 多角色混合轨道导出
|
||||||
torch.onnx.export(
|
torch.onnx.export(
|
||||||
net_g,
|
net_g,
|
||||||
(
|
(
|
||||||
test_phone.to(device),
|
test_phone.to(device),
|
||||||
test_phone_lengths.to(device),
|
test_phone_lengths.to(device),
|
||||||
test_pitch.to(device),
|
test_pitch.to(device),
|
||||||
test_pitchf.to(device),
|
test_pitchf.to(device),
|
||||||
test_ds.to(device),
|
test_ds.to(device),
|
||||||
test_rnd.to(device),
|
test_rnd.to(device),
|
||||||
),
|
),
|
||||||
ExportedPath,
|
ExportedPath,
|
||||||
dynamic_axes={
|
dynamic_axes={
|
||||||
"phone": [1],
|
"phone": [1],
|
||||||
"pitch": [1],
|
"pitch": [1],
|
||||||
"pitchf": [1],
|
"pitchf": [1],
|
||||||
"rnd": [2],
|
"rnd": [2],
|
||||||
},
|
},
|
||||||
do_constant_folding=False,
|
do_constant_folding=False,
|
||||||
opset_version=16,
|
opset_version=16,
|
||||||
verbose=False,
|
verbose=False,
|
||||||
input_names=input_names,
|
input_names=input_names,
|
||||||
output_names=output_names,
|
output_names=output_names,
|
||||||
)
|
)
|
||||||
else:
|
|
||||||
net_g = SynthesizerTrnMs256NSFsidO(
|
|
||||||
*cpt["config"], is_half=False
|
|
||||||
) # fp32导出(C++要支持fp16必须手动将内存重新排列所以暂时不用fp16)
|
|
||||||
net_g.load_state_dict(cpt["weight"], strict=False)
|
|
||||||
input_names = ["phone", "phone_lengths", "pitch", "pitchf", "ds"]
|
|
||||||
output_names = [
|
|
||||||
"audio",
|
|
||||||
]
|
|
||||||
torch.onnx.export(
|
|
||||||
net_g,
|
|
||||||
(
|
|
||||||
test_phone.to(device),
|
|
||||||
test_phone_lengths.to(device),
|
|
||||||
test_pitch.to(device),
|
|
||||||
test_pitchf.to(device),
|
|
||||||
test_ds.to(device),
|
|
||||||
),
|
|
||||||
ExportedPath,
|
|
||||||
dynamic_axes={
|
|
||||||
"phone": [1],
|
|
||||||
"pitch": [1],
|
|
||||||
"pitchf": [1],
|
|
||||||
},
|
|
||||||
do_constant_folding=False,
|
|
||||||
opset_version=16,
|
|
||||||
verbose=False,
|
|
||||||
input_names=input_names,
|
|
||||||
output_names=output_names,
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
from infer_pack.models_onnx_moess import SynthesizerTrnMs256NSFsidM
|
|
||||||
import torch
|
|
||||||
|
|
||||||
person = "Shiroha/shiroha.pth"
|
|
||||||
exported_path = "model.onnx"
|
|
||||||
|
|
||||||
|
|
||||||
cpt = torch.load(person, map_location="cpu")
|
|
||||||
cpt["config"][-3] = cpt["weight"]["emb_g.weight"].shape[0] # n_spk
|
|
||||||
print(*cpt["config"])
|
|
||||||
net_g = SynthesizerTrnMs256NSFsidM(*cpt["config"], is_half=False)
|
|
||||||
net_g.load_state_dict(cpt["weight"], strict=False)
|
|
||||||
|
|
||||||
test_phone = torch.rand(1, 200, 256)
|
|
||||||
test_phone_lengths = torch.tensor([200]).long()
|
|
||||||
test_pitch = torch.randint(size=(1, 200), low=5, high=255)
|
|
||||||
test_pitchf = torch.rand(1, 200)
|
|
||||||
test_ds = torch.LongTensor([0])
|
|
||||||
test_rnd = torch.rand(1, 192, 200)
|
|
||||||
input_names = ["phone", "phone_lengths", "pitch", "pitchf", "ds", "rnd"]
|
|
||||||
output_names = [
|
|
||||||
"audio",
|
|
||||||
]
|
|
||||||
device = "cpu"
|
|
||||||
torch.onnx.export(
|
|
||||||
net_g,
|
|
||||||
(
|
|
||||||
test_phone.to(device),
|
|
||||||
test_phone_lengths.to(device),
|
|
||||||
test_pitch.to(device),
|
|
||||||
test_pitchf.to(device),
|
|
||||||
test_ds.to(device),
|
|
||||||
test_rnd.to(device),
|
|
||||||
),
|
|
||||||
exported_path,
|
|
||||||
dynamic_axes={
|
|
||||||
"phone": [1],
|
|
||||||
"pitch": [1],
|
|
||||||
"pitchf": [1],
|
|
||||||
"rnd": [2],
|
|
||||||
},
|
|
||||||
do_constant_folding=False,
|
|
||||||
opset_version=16,
|
|
||||||
verbose=False,
|
|
||||||
input_names=input_names,
|
|
||||||
output_names=output_names,
|
|
||||||
)
|
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
import os, traceback, sys, parselmouth
|
import os, traceback, sys, parselmouth
|
||||||
import librosa
|
|
||||||
|
now_dir = os.getcwd()
|
||||||
|
sys.path.append(now_dir)
|
||||||
|
from my_utils import load_audio
|
||||||
import pyworld
|
import pyworld
|
||||||
from scipy.io import wavfile
|
from scipy.io import wavfile
|
||||||
import numpy as np, logging
|
import numpy as np, logging
|
||||||
@@ -33,17 +36,14 @@ class FeatureInput(object):
|
|||||||
self.f0_mel_max = 1127 * np.log(1 + self.f0_max / 700)
|
self.f0_mel_max = 1127 * np.log(1 + self.f0_max / 700)
|
||||||
|
|
||||||
def compute_f0(self, path, f0_method):
|
def compute_f0(self, path, f0_method):
|
||||||
# default resample type of librosa.resample is "soxr_hq".
|
x = load_audio(path, self.fs)
|
||||||
# Quality: soxr_vhq > soxr_hq
|
|
||||||
x, sr = librosa.load(path, self.fs) # , res_type='soxr_vhq'
|
|
||||||
p_len = x.shape[0] // self.hop
|
p_len = x.shape[0] // self.hop
|
||||||
assert sr == self.fs
|
|
||||||
if f0_method == "pm":
|
if f0_method == "pm":
|
||||||
time_step = 160 / 16000 * 1000
|
time_step = 160 / 16000 * 1000
|
||||||
f0_min = 50
|
f0_min = 50
|
||||||
f0_max = 1100
|
f0_max = 1100
|
||||||
f0 = (
|
f0 = (
|
||||||
parselmouth.Sound(x, sr)
|
parselmouth.Sound(x, self.fs)
|
||||||
.to_pitch_ac(
|
.to_pitch_ac(
|
||||||
time_step=time_step / 1000,
|
time_step=time_step / 1000,
|
||||||
voicing_threshold=0.6,
|
voicing_threshold=0.6,
|
||||||
@@ -60,19 +60,19 @@ class FeatureInput(object):
|
|||||||
elif f0_method == "harvest":
|
elif f0_method == "harvest":
|
||||||
f0, t = pyworld.harvest(
|
f0, t = pyworld.harvest(
|
||||||
x.astype(np.double),
|
x.astype(np.double),
|
||||||
fs=sr,
|
fs=self.fs,
|
||||||
f0_ceil=self.f0_max,
|
f0_ceil=self.f0_max,
|
||||||
f0_floor=self.f0_min,
|
f0_floor=self.f0_min,
|
||||||
frame_period=1000 * self.hop / sr,
|
frame_period=1000 * self.hop / self.fs,
|
||||||
)
|
)
|
||||||
f0 = pyworld.stonemask(x.astype(np.double), f0, t, self.fs)
|
f0 = pyworld.stonemask(x.astype(np.double), f0, t, self.fs)
|
||||||
elif f0_method == "dio":
|
elif f0_method == "dio":
|
||||||
f0, t = pyworld.dio(
|
f0, t = pyworld.dio(
|
||||||
x.astype(np.double),
|
x.astype(np.double),
|
||||||
fs=sr,
|
fs=self.fs,
|
||||||
f0_ceil=self.f0_max,
|
f0_ceil=self.f0_max,
|
||||||
f0_floor=self.f0_min,
|
f0_floor=self.f0_min,
|
||||||
frame_period=1000 * self.hop / sr,
|
frame_period=1000 * self.hop / self.fs,
|
||||||
)
|
)
|
||||||
f0 = pyworld.stonemask(x.astype(np.double), f0, t, self.fs)
|
f0 = pyworld.stonemask(x.astype(np.double), f0, t, self.fs)
|
||||||
return f0
|
return f0
|
||||||
@@ -154,7 +154,7 @@ if __name__ == "__main__":
|
|||||||
f0method,
|
f0method,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
p.start()
|
|
||||||
ps.append(p)
|
ps.append(p)
|
||||||
for p in ps:
|
p.start()
|
||||||
p.join()
|
for i in range(n_p):
|
||||||
|
ps[i].join()
|
||||||
|
|||||||
@@ -5,11 +5,12 @@ n_part = int(sys.argv[2])
|
|||||||
i_part = int(sys.argv[3])
|
i_part = int(sys.argv[3])
|
||||||
if len(sys.argv) == 5:
|
if len(sys.argv) == 5:
|
||||||
exp_dir = sys.argv[4]
|
exp_dir = sys.argv[4]
|
||||||
|
version = sys.argv[5]
|
||||||
else:
|
else:
|
||||||
i_gpu = sys.argv[4]
|
i_gpu = sys.argv[4]
|
||||||
exp_dir = sys.argv[5]
|
exp_dir = sys.argv[5]
|
||||||
os.environ["CUDA_VISIBLE_DEVICES"] = str(i_gpu)
|
os.environ["CUDA_VISIBLE_DEVICES"] = str(i_gpu)
|
||||||
|
version = sys.argv[6]
|
||||||
import torch
|
import torch
|
||||||
import torch.nn.functional as F
|
import torch.nn.functional as F
|
||||||
import soundfile as sf
|
import soundfile as sf
|
||||||
@@ -39,7 +40,9 @@ model_path = "hubert_base.pt"
|
|||||||
|
|
||||||
printt(exp_dir)
|
printt(exp_dir)
|
||||||
wavPath = "%s/1_16k_wavs" % exp_dir
|
wavPath = "%s/1_16k_wavs" % exp_dir
|
||||||
outPath = "%s/3_feature256" % exp_dir
|
outPath = (
|
||||||
|
"%s/3_feature256" % exp_dir if version == "v1" else "%s/3_feature768" % exp_dir
|
||||||
|
)
|
||||||
os.makedirs(outPath, exist_ok=True)
|
os.makedirs(outPath, exist_ok=True)
|
||||||
|
|
||||||
|
|
||||||
@@ -93,11 +96,13 @@ else:
|
|||||||
if device not in ["mps", "cpu"]
|
if device not in ["mps", "cpu"]
|
||||||
else feats.to(device),
|
else feats.to(device),
|
||||||
"padding_mask": padding_mask.to(device),
|
"padding_mask": padding_mask.to(device),
|
||||||
"output_layer": 9, # layer 9
|
"output_layer": 9 if version == "v1" else 12, # layer 9
|
||||||
}
|
}
|
||||||
with torch.no_grad():
|
with torch.no_grad():
|
||||||
logits = model.extract_features(**inputs)
|
logits = model.extract_features(**inputs)
|
||||||
feats = model.final_proj(logits[0])
|
feats = (
|
||||||
|
model.final_proj(logits[0]) if version == "v1" else logits[0]
|
||||||
|
)
|
||||||
|
|
||||||
feats = feats.squeeze(0).float().cpu().numpy()
|
feats = feats.squeeze(0).float().cpu().numpy()
|
||||||
if np.isnan(feats).sum() == 0:
|
if np.isnan(feats).sum() == 0:
|
||||||
|
|||||||
103
gui.py
103
gui.py
@@ -1,7 +1,22 @@
|
|||||||
|
"""
|
||||||
|
0416后的更新:
|
||||||
|
引入config中half
|
||||||
|
重建npy而不用填写
|
||||||
|
v2支持
|
||||||
|
无f0模型支持
|
||||||
|
修复
|
||||||
|
|
||||||
|
int16:
|
||||||
|
增加无索引支持
|
||||||
|
f0算法改harvest(怎么看就只有这个会影响CPU占用),但是不这么改效果不好
|
||||||
|
"""
|
||||||
import os, sys, traceback
|
import os, sys, traceback
|
||||||
|
|
||||||
now_dir = os.getcwd()
|
now_dir = os.getcwd()
|
||||||
sys.path.append(now_dir)
|
sys.path.append(now_dir)
|
||||||
|
from config import Config
|
||||||
|
|
||||||
|
Config = Config()
|
||||||
import PySimpleGUI as sg
|
import PySimpleGUI as sg
|
||||||
import sounddevice as sd
|
import sounddevice as sd
|
||||||
import noisereduce as nr
|
import noisereduce as nr
|
||||||
@@ -13,7 +28,12 @@ import torchaudio.transforms as tat
|
|||||||
import scipy.signal as signal
|
import scipy.signal as signal
|
||||||
|
|
||||||
# import matplotlib.pyplot as plt
|
# import matplotlib.pyplot as plt
|
||||||
from infer_pack.models import SynthesizerTrnMs256NSFsid, SynthesizerTrnMs256NSFsid_nono
|
from infer_pack.models import (
|
||||||
|
SynthesizerTrnMs256NSFsid,
|
||||||
|
SynthesizerTrnMs256NSFsid_nono,
|
||||||
|
SynthesizerTrnMs768NSFsid,
|
||||||
|
SynthesizerTrnMs768NSFsid_nono,
|
||||||
|
)
|
||||||
from i18n import I18nAuto
|
from i18n import I18nAuto
|
||||||
|
|
||||||
i18n = I18nAuto()
|
i18n = I18nAuto()
|
||||||
@@ -50,20 +70,37 @@ class RVC:
|
|||||||
)
|
)
|
||||||
self.model = models[0]
|
self.model = models[0]
|
||||||
self.model = self.model.to(device)
|
self.model = self.model.to(device)
|
||||||
self.model = self.model.half()
|
if Config.is_half:
|
||||||
|
self.model = self.model.half()
|
||||||
|
else:
|
||||||
|
self.model = self.model.float()
|
||||||
self.model.eval()
|
self.model.eval()
|
||||||
cpt = torch.load(pth_path, map_location="cpu")
|
cpt = torch.load(pth_path, map_location="cpu")
|
||||||
self.tgt_sr = cpt["config"][-1]
|
self.tgt_sr = cpt["config"][-1]
|
||||||
cpt["config"][-3] = cpt["weight"]["emb_g.weight"].shape[0] # n_spk
|
cpt["config"][-3] = cpt["weight"]["emb_g.weight"].shape[0] # n_spk
|
||||||
self.if_f0 = cpt.get("f0", 1)
|
self.if_f0 = cpt.get("f0", 1)
|
||||||
if self.if_f0 == 1:
|
self.version = cpt.get("version", "v1")
|
||||||
self.net_g = SynthesizerTrnMs256NSFsid(*cpt["config"], is_half=True)
|
if self.version == "v1":
|
||||||
else:
|
if self.if_f0 == 1:
|
||||||
self.net_g = SynthesizerTrnMs256NSFsid_nono(*cpt["config"])
|
self.net_g = SynthesizerTrnMs256NSFsid(
|
||||||
|
*cpt["config"], is_half=Config.is_half
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.net_g = SynthesizerTrnMs256NSFsid_nono(*cpt["config"])
|
||||||
|
elif self.version == "v2":
|
||||||
|
if self.if_f0 == 1:
|
||||||
|
self.net_g = SynthesizerTrnMs768NSFsid(
|
||||||
|
*cpt["config"], is_half=Config.is_half
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.net_g = SynthesizerTrnMs768NSFsid_nono(*cpt["config"])
|
||||||
del self.net_g.enc_q
|
del self.net_g.enc_q
|
||||||
print(self.net_g.load_state_dict(cpt["weight"], strict=False))
|
print(self.net_g.load_state_dict(cpt["weight"], strict=False))
|
||||||
self.net_g.eval().to(device)
|
self.net_g.eval().to(device)
|
||||||
self.net_g.half()
|
if Config.is_half:
|
||||||
|
self.net_g = self.net_g.half()
|
||||||
|
else:
|
||||||
|
self.net_g = self.net_g.float()
|
||||||
except:
|
except:
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
|
|
||||||
@@ -116,34 +153,38 @@ class RVC:
|
|||||||
inputs = {
|
inputs = {
|
||||||
"source": feats.half().to(device),
|
"source": feats.half().to(device),
|
||||||
"padding_mask": padding_mask.to(device),
|
"padding_mask": padding_mask.to(device),
|
||||||
"output_layer": 9, # layer 9
|
"output_layer": 9 if self.version == "v1" else 12,
|
||||||
}
|
}
|
||||||
torch.cuda.synchronize()
|
torch.cuda.synchronize()
|
||||||
with torch.no_grad():
|
with torch.no_grad():
|
||||||
logits = self.model.extract_features(**inputs)
|
logits = self.model.extract_features(**inputs)
|
||||||
feats = self.model.final_proj(logits[0])
|
feats = (
|
||||||
|
self.model.final_proj(logits[0]) if self.version == "v1" else logits[0]
|
||||||
|
)
|
||||||
|
|
||||||
####索引优化
|
####索引优化
|
||||||
if hasattr(self, "index") and hasattr(self, "big_npy") and self.index_rate != 0:
|
try:
|
||||||
npy = feats[0].cpu().numpy().astype("float32")
|
if (
|
||||||
|
hasattr(self, "index")
|
||||||
# _, I = self.index.search(npy, 1)
|
and hasattr(self, "big_npy")
|
||||||
# npy = self.big_npy[I.squeeze()].astype("float16")
|
and self.index_rate != 0
|
||||||
|
):
|
||||||
score, ix = self.index.search(npy, k=8)
|
npy = feats[0].cpu().numpy().astype("float32")
|
||||||
weight = np.square(1 / score)
|
score, ix = self.index.search(npy, k=8)
|
||||||
weight /= weight.sum(axis=1, keepdims=True)
|
weight = np.square(1 / score)
|
||||||
npy = np.sum(
|
weight /= weight.sum(axis=1, keepdims=True)
|
||||||
self.big_npy[ix] * np.expand_dims(weight, axis=2), axis=1
|
npy = np.sum(self.big_npy[ix] * np.expand_dims(weight, axis=2), axis=1)
|
||||||
).astype("float16")
|
if Config.is_half:
|
||||||
|
npy = npy.astype("float16")
|
||||||
feats = (
|
feats = (
|
||||||
torch.from_numpy(npy).unsqueeze(0).to(device) * self.index_rate
|
torch.from_numpy(npy).unsqueeze(0).to(device) * self.index_rate
|
||||||
+ (1 - self.index_rate) * feats
|
+ (1 - self.index_rate) * feats
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
print("index search FAIL or disabled")
|
print("index search FAIL or disabled")
|
||||||
|
except:
|
||||||
|
traceback.print_exc()
|
||||||
|
print("index search FAIL")
|
||||||
feats = F.interpolate(feats.permute(0, 2, 1), scale_factor=2).permute(0, 2, 1)
|
feats = F.interpolate(feats.permute(0, 2, 1), scale_factor=2).permute(0, 2, 1)
|
||||||
torch.cuda.synchronize()
|
torch.cuda.synchronize()
|
||||||
print(feats.shape)
|
print(feats.shape)
|
||||||
@@ -179,7 +220,7 @@ class RVC:
|
|||||||
return infered_audio
|
return infered_audio
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
class GUIConfig:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.hubert_path: str = ""
|
self.hubert_path: str = ""
|
||||||
self.pth_path: str = ""
|
self.pth_path: str = ""
|
||||||
@@ -199,7 +240,7 @@ class Config:
|
|||||||
|
|
||||||
class GUI:
|
class GUI:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.config = Config()
|
self.config = GUIConfig()
|
||||||
self.flag_vc = False
|
self.flag_vc = False
|
||||||
|
|
||||||
self.launcher()
|
self.launcher()
|
||||||
|
|||||||
5
i18n.py
5
i18n.py
@@ -18,8 +18,11 @@ class I18nAuto:
|
|||||||
if not os.path.exists(f"./i18n/{language}.json"):
|
if not os.path.exists(f"./i18n/{language}.json"):
|
||||||
language = "en_US"
|
language = "en_US"
|
||||||
self.language = language
|
self.language = language
|
||||||
print("Use Language:", language)
|
# print("Use Language:", language)
|
||||||
self.language_map = load_language_list(language)
|
self.language_map = load_language_list(language)
|
||||||
|
|
||||||
def __call__(self, key):
|
def __call__(self, key):
|
||||||
return self.language_map.get(key, key)
|
return self.language_map.get(key, key)
|
||||||
|
|
||||||
|
def print(self):
|
||||||
|
print("Use Language:", self.language)
|
||||||
|
|||||||
145
i18n/en_US.json
145
i18n/en_US.json
@@ -1,97 +1,101 @@
|
|||||||
{
|
{
|
||||||
"很遗憾您这没有能用的显卡来支持您训练": "Unfortunately, you don't have a GPU to help you train",
|
"很遗憾您这没有能用的显卡来支持您训练": "No supported GPU is found. Training may be slow or unavailable.",
|
||||||
"是": "yes",
|
"是": "yes",
|
||||||
"step1:正在处理数据": "step 1: processing data",
|
"step1:正在处理数据": "step 1: processing data",
|
||||||
"step2a:无需提取音高": "step 2a: skipped extracting pitch",
|
"step2a:无需提取音高": "step 2a: skipping pitch extraction",
|
||||||
"step2b:正在提取特征": "step 2b: extracting features",
|
"step2b:正在提取特征": "step 2b: extracting features",
|
||||||
"step3a:正在训练模型": "step 3a: training the model",
|
"step3a:正在训练模型": "step 3a: model traning started",
|
||||||
"训练结束, 您可查看控制台训练日志或实验文件夹下的train.log": "Training completed, you can view the training logs in the console or the train.log within the experiement folder",
|
"训练结束, 您可查看控制台训练日志或实验文件夹下的train.log": "Training complete. Logs are available in the console, or the 'train.log' under experiment folder",
|
||||||
"全流程结束!": "all processes have been completed!",
|
"全流程结束!": "all processes have been completed!",
|
||||||
"本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.": "This software is open source under the MIT license, the author does not have any control over the software, and those who use the software and spread the sounds exported by the software are solely responsible. <br>If you do not agree with this clause, you cannot use or quote any codes and files in the software package. See root directory <b>Agreement-LICENSE.txt</b> for details.",
|
"本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.": "This software is open source under the MIT license, the author does not have any control over the software, and those who use the software and spread the sounds exported by the software are solely responsible. <br>If you do not agree with this clause, you cannot use or quote any codes and files in the software package. See root directory <b>Agreement-LICENSE.txt</b> for details.",
|
||||||
"模型推理": "Model inference",
|
"模型推理": "Model Inference",
|
||||||
"推理音色": "Inferencing timbre",
|
"推理音色": "Inferencing voice:",
|
||||||
"刷新音色列表和索引路径": "Refresh timbre list and index path",
|
"刷新音色列表和索引路径": "Refresh voice list and index path",
|
||||||
"卸载音色省显存": "Unload timbre to save GPU memory",
|
"卸载音色省显存": "Unload voice to save GPU memory:",
|
||||||
"请选择说话人id": "Please select a speaker id",
|
"请选择说话人id": "Select Singer/Speaker ID:",
|
||||||
"男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "It is recommended +12key for male to female conversion, and -12key for female to male conversion. If the sound range explodes and the timbre is distorted, you can also adjust it to the appropriate range by yourself. ",
|
"男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "It is recommended +12key for male to female conversion, and -12key for female to male conversion. If the sound range goes too far and the voice is distorted, you can also adjust it to the appropriate range by yourself. ",
|
||||||
"变调(整数, 半音数量, 升八度12降八度-12)": "transpose(integer, number of semitones, octave sharp 12 octave flat -12)",
|
"变调(整数, 半音数量, 升八度12降八度-12)": "transpose(Input must be integer, represents number of semitones. Example: octave sharp: 12;octave flat: -12):",
|
||||||
"输入待处理音频文件路径(默认是正确格式示例)": "Enter the path of the audio file to be processed (the default is the correct format example)",
|
"输入待处理音频文件路径(默认是正确格式示例)": "Enter the path of the audio file to be processed (the default is example of the correct format(Windows)):",
|
||||||
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比": "Select the algorithm for pitch extraction. Use 'pm' to speed up for singing voices, or use 'harvest' for better low-pitched voices, but it is extremely slow.",
|
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比": "Select the algorithm for pitch extraction.('pm': fast conversions; 'harvest': better pitch accuracy, but conversion might be extremely slow):",
|
||||||
">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音": ">=3:using median filter for f0. The number is median filter radius.",
|
">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音": "If >=3: using median filter for f0. The number is median filter radius.",
|
||||||
"特征检索库文件路径,为空则使用下拉的选择结果": "Feature file path. If null, use dropdown result.",
|
"特征检索库文件路径,为空则使用下拉的选择结果": "Path to Feature index file(If null, use dropdown result):",
|
||||||
"自动检测index路径,下拉式选择(dropdown)": "Auto detect index path in logs directory. Dropdown.",
|
"自动检测index路径,下拉式选择(dropdown)": "Path to the '.index' file in 'logs' directory is auto detected. Pick the matching file from the dropdown:",
|
||||||
"特征文件路径": "Feature file path",
|
"特征文件路径": "Path to Feature file:",
|
||||||
"检索特征占比": "Search feature ratio",
|
"检索特征占比": "Search feature ratio:",
|
||||||
"后处理重采样至最终采样率,0为不进行重采样": "Post resample the audio to the final sample rate. Default: don't use post resample.",
|
"后处理重采样至最终采样率,0为不进行重采样": "Resample the audio in post-processing to a different sample rate.(Default(0): No post-resampling):",
|
||||||
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0 curve file, optional, one pitch per line, instead of the default F0 and ups and downs",
|
"输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络": "Use volume envelope of input to mix or replace the volume envelope of output, the closer the rate is to 1, the more output envelope is used.(Default(1): don't mix input envelope):",
|
||||||
|
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0 curve file(optional),one pitch per line. Overrides the default F0 and ups and downs :",
|
||||||
"转换": "Convert",
|
"转换": "Convert",
|
||||||
"输出信息": "Export message",
|
"输出信息": "Output message",
|
||||||
"输出音频(右下角三个点,点了可以下载)": "Export audio (three dots in the lower right corner, click to download)",
|
"输出音频(右下角三个点,点了可以下载)": "Export audio (Click on the three dots in the bottom right corner to download)",
|
||||||
"批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ": "For batch conversion, input the audio folder to be converted, or upload multiple audio files, and output the converted audio in the specified folder (opt by default). ",
|
"批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ": "For batch conversion, input the audio folder to be converted, or upload multiple audio files, and output the converted audio in the specified folder ('opt' by default). ",
|
||||||
"指定输出文件夹": "Specify output folder",
|
"指定输出文件夹": "Path to output folder:",
|
||||||
"输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "Enter the path of the audio folder to be processed (just go to the address bar of the file manager and copy it)",
|
"输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)": "Enter the path of the audio folder to be processed (just go to the address bar of the file manager and copy it)",
|
||||||
"也可批量输入音频文件, 二选一, 优先读文件夹": "You can also input audio files in batches, choose one of the two, and read the folder first",
|
"也可批量输入音频文件, 二选一, 优先读文件夹": "You can also input audio files in batches, choose one of the two, and read the folder first",
|
||||||
"伴奏人声分离": "Accompaniment and vocal separation",
|
"伴奏人声分离": "Seperation of Accompaniment and Vocal",
|
||||||
"人声伴奏分离批量处理, 使用UVR5模型. <br>不带和声用HP2, 带和声且提取的人声不需要和声用HP5<br>合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)": "Batch processing of vocal accompaniment separation, using UVR5 model. <br>Without harmony, use HP2, with harmony and extracted vocals do not need harmony, use HP5<br>Example of qualified folder path format: E:\\ codes\\py39\\vits_vc_gpu\\Egret Shuanghua test sample (just go to the address bar of the file manager and copy it)",
|
"人声伴奏分离批量处理, 使用UVR5模型. <br>不带和声用HP2, 带和声且提取的人声不需要和声用HP5<br>合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)": "Batch processing of vocal accompaniment separation using UVR5 Model. <br>If input is without harmony, use HP2; If with harmony and the extracted vocals do not need harmony, use HP5<br>Example of legal folder path format: E:\\ codes\\py39\\vits_vc_gpu\\Egret Shuanghua test sample (just go to the address bar of the file manager and copy it)",
|
||||||
"输入待处理音频文件夹路径": "Input audio folder path",
|
"输入待处理音频文件夹路径": "Path to Input audio folder:",
|
||||||
"模型": "Model",
|
"模型": "Model",
|
||||||
"指定输出人声文件夹": "Specify vocals output folder",
|
"指定输出人声文件夹": "Path to vocals output folder:",
|
||||||
"指定输出乐器文件夹": "Specify instrumentals output folder",
|
"指定输出乐器文件夹": "Path to instrumentals output folder:",
|
||||||
"训练": "Train",
|
"训练": "Train",
|
||||||
"step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "step1: Fill in the experimental configuration. The experimental data is placed under logs, and each experiment has a folder. You need to manually enter the experimental name path, which contains the experimental configuration, logs, and model files obtained from training. ",
|
"step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "step1: Fill in the experimental configuration. The experimental data is placed under 'logs', and each experiment has a folder. You need to manually enter the experimental name path, which contains the experimental configuration, logs, and model files obtained from training. ",
|
||||||
"输入实验名": "Input experiment name",
|
"输入实验名": "Experiment name:",
|
||||||
"目标采样率": "Target sample rate",
|
"目标采样率": "Target sample rate:",
|
||||||
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "Does the model have pitch guidance (singing must, voice can not.)",
|
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "If the model have pitch guidance (Required for singing as Input; Optional for speech as Input, but recommended):",
|
||||||
"提取音高和处理数据使用的CPU进程数": "Number of CPU threads to use for pitch extraction and dataset processing",
|
"版本(目前仅40k支持了v2)": "Model architecture version (v2 version only supports 40k sample rate for testing purposes):",
|
||||||
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a: Automatically traverse all files that can be decoded into audio in the training folder and perform slice normalization, and generate 2 wav folders in the experiment directory; only single-person training is supported for the time being. ",
|
"提取音高和处理数据使用的CPU进程数": "Threads of CPU, for pitch extraction and dataset processing:",
|
||||||
"输入训练文件夹路径": "Input training folder path",
|
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a: Automatically traverse all files that can be decoded into audio in the training folder and perform slice normalization. Generates 2 wav folders in the experiment directory; Only single-singer/speaker training is supported for the time being. ",
|
||||||
"请指定说话人id": "Please specify speaker ID",
|
"输入训练文件夹路径": "Path to training folder:",
|
||||||
|
"请指定说话人id": "Specify Singer/Speaker ID:",
|
||||||
"处理数据": "Process data",
|
"处理数据": "Process data",
|
||||||
"step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)": "step2b: Use CPU to extract pitch (if the model has pitch), use GPU to extract features (select card number)",
|
"step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)": "step2b: Use CPU to extract pitch (if the model has pitch), use GPU to extract features (must specify GPU)",
|
||||||
"以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2": "Enter the card numbers used separated by -, for example 0-1-2 use card 0 and card 1 and card 2",
|
"以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2": "Enter GPU Index(es),separated by '-'.(Example: 0-1-2 to select card 1, 2 and 3):",
|
||||||
"显卡信息": "GPU information",
|
"显卡信息": "GPU Information",
|
||||||
"选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢": "Select pitch extraction algorithm: Use 'pm' for faster processing of singing voice, 'dio' for high-quality speech but slower processing, and 'harvest' for the best quality but slowest processing.",
|
"选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢": "Select pitch extraction algorithm.('pm': fastest extraction but lower-quality speech; 'dio': improved speech but slower extraction; 'harvest': best quality but slowest extraction):",
|
||||||
"特征提取": "Feature extraction",
|
"特征提取": "Feature extraction",
|
||||||
"step3: 填写训练设置, 开始训练模型和索引": "step3: Fill in the training settings, start training the model and index",
|
"step3: 填写训练设置, 开始训练模型和索引": "step3: Fill in the training settings, start training the model and index",
|
||||||
"保存频率save_every_epoch": "Save frequency (save_every_epoch)",
|
"保存频率save_every_epoch": "Saving frequency (save_every_epoch):",
|
||||||
"总训练轮数total_epoch": "Total training epochs (total_epoch)",
|
"总训练轮数total_epoch": "Total training epochs (total_epoch):",
|
||||||
"每张显卡的batch_size": "batch_size for every GPU",
|
"每张显卡的batch_size": "batch_size for every GPU:",
|
||||||
"是否仅保存最新的ckpt文件以节省硬盘空间": "Whether to save only the latest ckpt file to save disk space",
|
"是否仅保存最新的ckpt文件以节省硬盘空间": "Save only the latest ckpt file to reduce disk usage:",
|
||||||
"否": "no",
|
"否": "no",
|
||||||
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "Whether to cache all training sets to video memory. Small data under 10 minutes can be cached to speed up training, and large data cache will blow up video memory and not increase the speed much",
|
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "Cache all training sets to GPU Memory. Small data(~under 10 minutes) can be cached to speed up training, but large data caching will eats up the GPU Memory and may not increase the speed :",
|
||||||
|
"是否在每次保存时间点将最终小模型保存至weights文件夹": "Save a small finished model to the 'weights' directory for every epoch matching the specified 'save frequency' :",
|
||||||
"加载预训练底模G路径": "Load pre-trained base model G path.",
|
"加载预训练底模G路径": "Load pre-trained base model G path.",
|
||||||
"加载预训练底模D路径": "Load pre-trained base model D path.",
|
"加载预训练底模D路径": "Load pre-trained base model D path.",
|
||||||
"训练模型": "Train model.",
|
"训练模型": "Train model.",
|
||||||
"训练特征索引": "Train feature index.",
|
"训练特征索引": "Train feature index",
|
||||||
"一键训练": "One-click training.",
|
"一键训练": "One-click training",
|
||||||
"ckpt处理": "ckpt processing.",
|
"ckpt处理": "ckpt Processing",
|
||||||
"模型融合, 可用于测试音色融合": "Model Fusion, which can be used to test sound fusion",
|
"模型融合, 可用于测试音色融合": "Model Fusion, which can be used to test timbre fusion",
|
||||||
"A模型路径": "A model path.",
|
"A模型路径": "Path to Model A:",
|
||||||
"B模型路径": "B model path.",
|
"B模型路径": "Path to Model B:",
|
||||||
"A模型权重": "A model weight for model A.",
|
"A模型权重": "Weight(w) for model A:",
|
||||||
"模型是否带音高指导": "Whether the model has pitch guidance.",
|
"模型是否带音高指导": "Whether the model has pitch guidance:",
|
||||||
"要置入的模型信息": "Model information to be placed.",
|
"要置入的模型信息": "Model information to be placed:",
|
||||||
"保存的模型名不带后缀": "Saved model name without extension.",
|
"保存的模型名不带后缀": "Saved modelname(without extension):",
|
||||||
"融合": "Fusion.",
|
"模型版本型号": "Model architecture version:",
|
||||||
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "Modify model information (only small model files extracted from the weights folder are supported)",
|
"融合": "Fusion",
|
||||||
"模型路径": "Model path",
|
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "Modify model information (only small model files extracted from the 'weights' folder are supported)",
|
||||||
"要改的模型信息": "Model information to be modified",
|
"模型路径": "Path to Model:",
|
||||||
"保存的文件名, 默认空为和源文件同名": "The saved file name, the default is empty and the same name as the source file",
|
"要改的模型信息": "Model information to be modified:",
|
||||||
|
"保存的文件名, 默认空为和源文件同名": "Savefile Name. Default(empty): Name is the same as the source file :",
|
||||||
"修改": "Modify",
|
"修改": "Modify",
|
||||||
"查看模型信息(仅支持weights文件夹下提取的小模型文件)": "View model information (only small model files extracted from the weights folder are supported)",
|
"查看模型信息(仅支持weights文件夹下提取的小模型文件)": "View model information (only small model files extracted from the 'weights' folder are supported)",
|
||||||
"查看": "View",
|
"查看": "View",
|
||||||
"模型提取(输入logs文件夹下大文件模型路径),适用于训一半不想训了模型没有自动提取保存小文件模型,或者想测试中间模型的情况": "Model extraction (enter the path of the large file model under the logs folder), which is suitable for half of the training and does not want to train the model without automatically extracting and saving the small file model, or if you want to test the intermediate model",
|
"模型提取(输入logs文件夹下大文件模型路径),适用于训一半不想训了模型没有自动提取保存小文件模型,或者想测试中间模型的情况": "Model extraction (enter the path of the large file model under the logs folder), which is suitable for half of the training and does not want to train the model without automatically extracting and saving the small file model, or if you want to test the intermediate model",
|
||||||
"保存名": "Save Name",
|
"保存名": "Savefile Name:",
|
||||||
"模型是否带音高指导,1是0否": "Whether the model has pitch guidance, 1 for yes, 0 for no",
|
"模型是否带音高指导,1是0否": "Whether the model has pitch guidance(1: yes, 0: no):",
|
||||||
"提取": "Extract",
|
"提取": "Extract",
|
||||||
"Onnx导出": "Export Onnx",
|
"Onnx导出": "Export Onnx",
|
||||||
"RVC模型路径": "RVC Model Path",
|
"RVC模型路径": "RVC Model Path:",
|
||||||
"Onnx输出路径": "Onnx Export Path",
|
"Onnx输出路径": "Onnx Export Path:",
|
||||||
"MoeVS模型": "MoeVS Model",
|
"MoeVS模型": "MoeVS Model",
|
||||||
"导出Onnx模型": "Export Onnx Model",
|
"导出Onnx模型": "Export Onnx Model",
|
||||||
"常见问题解答": "FAQ (Frequently Asked Questions)",
|
"常见问题解答": "FAQ (Frequently Asked Questions)",
|
||||||
"招募音高曲线前端编辑器": "Recruit front-end editors for pitch curves",
|
"招募音高曲线前端编辑器": "Recruit front-end editors for pitch curves",
|
||||||
"加开发群联系我xxxxx": "Add development group to contact me xxxxx",
|
"加开发群联系我xxxxx": "Want to join the development chat group? contact me xxxxx",
|
||||||
"点击查看交流、问题反馈群号": "Click to view the communication and problem feedback group number",
|
"点击查看交流、问题反馈群号": "Click to view the communication and problem feedback group number",
|
||||||
"xxxxx": "xxxxx",
|
"xxxxx": "xxxxx",
|
||||||
"加载模型": "load model",
|
"加载模型": "load model",
|
||||||
@@ -111,8 +115,11 @@
|
|||||||
"额外推理时长": "extra inference time",
|
"额外推理时长": "extra inference time",
|
||||||
"输入降噪": "Input Noise Reduction",
|
"输入降噪": "Input Noise Reduction",
|
||||||
"输出降噪": "Output Noise Reduction",
|
"输出降噪": "Output Noise Reduction",
|
||||||
"性能设置": "performance settings",
|
"性能设置": "Compute Performance settings",
|
||||||
"开始音频转换": "start audio conversion",
|
"开始音频转换": "start audio conversion",
|
||||||
"停止音频转换": "stop audio conversion",
|
"停止音频转换": "stop audio conversion",
|
||||||
"推理时间(ms):": "Infer Time(ms):"
|
"导出文件格式": "output file format",
|
||||||
|
"保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果": "Protect voiceless consonant and breath, less artifact. 0.5: don' use it. The number smaller, the stronger protection.",
|
||||||
|
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "Select pitch extraction algorithm.('pm': fastest extraction but lower-quality speech; 'dio': improved speech but slower extraction; 'harvest': better quality but slowest extraction; 'crepe': best quality but GPU needed. )",
|
||||||
|
"推理时间(ms):": "Inference Time(ms):"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
"特征文件路径": "Ruta del archivo de características",
|
"特征文件路径": "Ruta del archivo de características",
|
||||||
"检索特征占比": "Proporción de función de búsqueda",
|
"检索特征占比": "Proporción de función de búsqueda",
|
||||||
"后处理重采样至最终采样率,0为不进行重采样": "后处理重采样至最终采样率,0为不进行重采样",
|
"后处理重采样至最终采样率,0为不进行重采样": "后处理重采样至最终采样率,0为不进行重采样",
|
||||||
|
"输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络": "输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络",
|
||||||
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "Archivo de curva F0, opcional, un tono por línea, en lugar de F0 predeterminado y cambio de tono",
|
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "Archivo de curva F0, opcional, un tono por línea, en lugar de F0 predeterminado y cambio de tono",
|
||||||
"转换": "Conversión",
|
"转换": "Conversión",
|
||||||
"输出信息": "Información de salida",
|
"输出信息": "Información de salida",
|
||||||
@@ -42,6 +43,7 @@
|
|||||||
"输入实验名": "Ingrese el nombre del modelo",
|
"输入实验名": "Ingrese el nombre del modelo",
|
||||||
"目标采样率": "Tasa de muestreo objetivo",
|
"目标采样率": "Tasa de muestreo objetivo",
|
||||||
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "Si el modelo tiene guía de tono (necesaria para cantar, pero no para hablar)",
|
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "Si el modelo tiene guía de tono (necesaria para cantar, pero no para hablar)",
|
||||||
|
"版本(目前仅40k支持了v2)": "版本(目前仅40k支持了v2)",
|
||||||
"提取音高和处理数据使用的CPU进程数": "提取音高和处理数据使用的CPU进程数",
|
"提取音高和处理数据使用的CPU进程数": "提取音高和处理数据使用的CPU进程数",
|
||||||
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "paso 2a: recorra automáticamente la carpeta de capacitación y corte y normalice todos los archivos de audio que se pueden decodificar en audio. Se generarán dos carpetas 'wav' en el directorio del experimento. Actualmente, solo se admite la capacitación de una sola persona.",
|
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "paso 2a: recorra automáticamente la carpeta de capacitación y corte y normalice todos los archivos de audio que se pueden decodificar en audio. Se generarán dos carpetas 'wav' en el directorio del experimento. Actualmente, solo se admite la capacitación de una sola persona.",
|
||||||
"输入训练文件夹路径": "Introduzca la ruta de la carpeta de entrenamiento",
|
"输入训练文件夹路径": "Introduzca la ruta de la carpeta de entrenamiento",
|
||||||
@@ -59,6 +61,7 @@
|
|||||||
"是否仅保存最新的ckpt文件以节省硬盘空间": "Si guardar solo el archivo ckpt más reciente para ahorrar espacio en disco",
|
"是否仅保存最新的ckpt文件以节省硬盘空间": "Si guardar solo el archivo ckpt más reciente para ahorrar espacio en disco",
|
||||||
"否": "否",
|
"否": "否",
|
||||||
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "Si almacenar en caché todos los conjuntos de entrenamiento en la memoria de la GPU. Los conjuntos de datos pequeños (menos de 10 minutos) se pueden almacenar en caché para acelerar el entrenamiento, pero el almacenamiento en caché de conjuntos de datos grandes puede causar errores de memoria en la GPU y no aumenta la velocidad de manera significativa.",
|
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "Si almacenar en caché todos los conjuntos de entrenamiento en la memoria de la GPU. Los conjuntos de datos pequeños (menos de 10 minutos) se pueden almacenar en caché para acelerar el entrenamiento, pero el almacenamiento en caché de conjuntos de datos grandes puede causar errores de memoria en la GPU y no aumenta la velocidad de manera significativa.",
|
||||||
|
"是否在每次保存时间点将最终小模型保存至weights文件夹": "是否在每次保存时间点将最终小模型保存至weights文件夹",
|
||||||
"加载预训练底模G路径": "Cargue la ruta G del modelo base preentrenada.",
|
"加载预训练底模G路径": "Cargue la ruta G del modelo base preentrenada.",
|
||||||
"加载预训练底模D路径": "Cargue la ruta del modelo D base preentrenada.",
|
"加载预训练底模D路径": "Cargue la ruta del modelo D base preentrenada.",
|
||||||
"训练模型": "Entrenar Modelo",
|
"训练模型": "Entrenar Modelo",
|
||||||
@@ -72,6 +75,7 @@
|
|||||||
"模型是否带音高指导": "Si el modelo tiene guía de tono.",
|
"模型是否带音高指导": "Si el modelo tiene guía de tono.",
|
||||||
"要置入的模型信息": "Información del modelo a colocar.",
|
"要置入的模型信息": "Información del modelo a colocar.",
|
||||||
"保存的模型名不带后缀": "Nombre del modelo guardado sin extensión.",
|
"保存的模型名不带后缀": "Nombre del modelo guardado sin extensión.",
|
||||||
|
"模型版本型号": "模型版本型号",
|
||||||
"融合": "Fusión.",
|
"融合": "Fusión.",
|
||||||
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "Modificar la información del modelo (solo admite archivos de modelos pequeños extraídos en la carpeta de pesos).",
|
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "Modificar la información del modelo (solo admite archivos de modelos pequeños extraídos en la carpeta de pesos).",
|
||||||
"模型路径": "Ruta del modelo",
|
"模型路径": "Ruta del modelo",
|
||||||
|
|||||||
@@ -1,28 +1,29 @@
|
|||||||
{
|
{
|
||||||
"很遗憾您这没有能用的显卡来支持您训练": "トレーニングに対応したGPUが動作しないのは残念です。",
|
"很遗憾您这没有能用的显卡来支持您训练": "トレーニングに対応したGPUが動作しないのは残念です。",
|
||||||
"是": "Yes",
|
"是": "はい",
|
||||||
"step1:正在处理数据": "step1:処理中のデータ",
|
"step1:正在处理数据": "step1:処理中のデータ",
|
||||||
"step2a:无需提取音高": "step2a:ピッチの抽出は不要",
|
"step2a:无需提取音高": "step2a:ピッチの抽出は不要",
|
||||||
"step2b:正在提取特征": "step2b:抽出される特徴量",
|
"step2b:正在提取特征": "step2b:抽出される特徴量",
|
||||||
"step3a:正在训练模型": "step3a:トレーニング中のモデル",
|
"step3a:正在训练模型": "step3a:トレーニング中のモデル",
|
||||||
"训练结束, 您可查看控制台训练日志或实验文件夹下的train.log": "トレーニング終了時に、トレーニングログやフォルダ内のtrain.logを確認することができます",
|
"训练结束, 您可查看控制台训练日志或实验文件夹下的train.log": "トレーニング終了時に、トレーニングログやフォルダ内のtrain.logを確認することができます",
|
||||||
"全流程结束!": "全流程结束!",
|
"全流程结束!": "全工程が完了!",
|
||||||
"本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.": "本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.",
|
"本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>使用需遵守的协议-LICENSE.txt</b>.": "本ソフトウェアはMITライセンスに基づくオープンソースであり、作者は本ソフトウェアに対していかなる強制力も持ちません。本ソフトウェアの利用者および本ソフトウェアから派生した音源(成果物)を配布する者は、本ソフトウェアに対して自身で責任を負うものとします。 <br>この条項に同意しない場合、パッケージ内のコードやファイルを使用や参照を禁じます。詳しくは<b>使用需遵守的协议-LICENSE.txt</b>をご覧ください.",
|
||||||
"模型推理": "モデル推論",
|
"模型推理": "モデル推論",
|
||||||
"推理音色": "音源推論",
|
"推理音色": "音源推論",
|
||||||
"刷新音色列表和索引路径": "刷新音色列表和索引路径",
|
"刷新音色列表和索引路径": "音源リストとインデックスパスの更新",
|
||||||
"卸载音色省显存": "音源を削除してメモリを節約",
|
"卸载音色省显存": "音源を削除してメモリを節約",
|
||||||
"请选择说话人id": "話者IDを選択してください",
|
"请选择说话人id": "話者IDを選択してください",
|
||||||
"男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "男性から女性へは+12キーをお勧めします。女性から男性へは-12キーをお勧めします。音域が広すぎて音質が劣化した場合は、適切な音域に自分で調整することもできます。",
|
"男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ": "男性から女性へは+12キーをお勧めします。女性から男性へは-12キーをお勧めします。音域が広すぎて音質が劣化した場合は、適切な音域に自分で調整することもできます。",
|
||||||
"变调(整数, 半音数量, 升八度12降八度-12)": "ピッチ変更(整数、半音数、上下オクターブ12-12)",
|
"变调(整数, 半音数量, 升八度12降八度-12)": "ピッチ変更(整数、半音数、上下オクターブ12-12)",
|
||||||
"输入待处理音频文件路径(默认是正确格式示例)": "処理対象音声ファイルのパスを入力してください(デフォルトは正しいフォーマットの例です)",
|
"输入待处理音频文件路径(默认是正确格式示例)": "処理対象音声ファイルのパスを入力してください(デフォルトは正しいフォーマットの例です)",
|
||||||
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比": "ピッチ抽出アルゴリズムを選択してください。歌声の場合は、pmを使用して速度を上げることができます。低音が重要な場合は、harvestを使用できますが、非常に遅くなります。",
|
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比": "ピッチ抽出アルゴリズムを選択してください。歌声の場合は、pmを使用して速度を上げることができます。低音が重要な場合は、harvestを使用できますが、非常に遅くなります。",
|
||||||
">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音": ">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音",
|
">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音": ">=3 次に、harvestピッチの認識結果に対してメディアンフィルタを使用します。値はフィルター半径で、ミュートを減衰させるために使用します。",
|
||||||
"特征检索库文件路径,为空则使用下拉的选择结果": "特征检索库文件路径,为空则使用下拉的选择结果",
|
"特征检索库文件路径,为空则使用下拉的选择结果": "特徴検索ライブラリへのパス 空の場合はドロップダウンで選択",
|
||||||
"自动检测index路径,下拉式选择(dropdown)": "自动检测index路径,下拉式选择(dropdown)",
|
"自动检测index路径,下拉式选择(dropdown)": "インデックスパスの自動検出 ドロップダウンで選択",
|
||||||
"特征文件路径": "特徴量ファイルのパス",
|
"特征文件路径": "特徴量ファイルのパス",
|
||||||
"检索特征占比": "検索特徴率",
|
"检索特征占比": "検索特徴率",
|
||||||
"后处理重采样至最终采样率,0为不进行重采样": "后处理重采样至最终采样率,0为不进行重采样",
|
"后处理重采样至最终采样率,0为不进行重采样": "最終的なサンプリングレートへのポストプロセッシングのリサンプリング リサンプリングしない場合は0",
|
||||||
|
"输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络": "入力ソースの音量エンベロープと出力音量エンベロープの融合率 1に近づくほど、出力音量エンベロープの割合が高くなる",
|
||||||
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0(最低共振周波数)カーブファイル(オプション、1行に1ピッチ、デフォルトのF0(最低共振周波数)とエレベーションを置き換えます。)",
|
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0(最低共振周波数)カーブファイル(オプション、1行に1ピッチ、デフォルトのF0(最低共振周波数)とエレベーションを置き換えます。)",
|
||||||
"转换": "変換",
|
"转换": "変換",
|
||||||
"输出信息": "出力情報",
|
"输出信息": "出力情報",
|
||||||
@@ -39,28 +40,30 @@
|
|||||||
"指定输出乐器文件夹": "楽器の出力フォルダを指定してください",
|
"指定输出乐器文件夹": "楽器の出力フォルダを指定してください",
|
||||||
"训练": "トレーニング",
|
"训练": "トレーニング",
|
||||||
"step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "ステップ1:実験設定を入力します。実験データはlogsに保存され、各実験にはフォルダーがあります。実験名のパスを手動で入力する必要があり、実験設定、ログ、トレーニングされたモデルファイルが含まれます。",
|
"step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. ": "ステップ1:実験設定を入力します。実験データはlogsに保存され、各実験にはフォルダーがあります。実験名のパスを手動で入力する必要があり、実験設定、ログ、トレーニングされたモデルファイルが含まれます。",
|
||||||
"输入实验名": "実験名を入力してください",
|
"输入实验名": "モデル名",
|
||||||
"目标采样率": "目標サンプリングレート",
|
"目标采样率": "目標サンプリングレート",
|
||||||
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "モデルに音高ガイドがあるかどうか(歌唱には必要ですが、音声には必要ありません)",
|
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "モデルに音高ガイドがあるかどうか(歌唱には必要ですが、音声には必要ありません)",
|
||||||
"提取音高和处理数据使用的CPU进程数": "提取音高和处理数据使用的CPU进程数",
|
"版本(目前仅40k支持了v2)": "バージョン(現在v2をサポートしているのは40kのみ)",
|
||||||
|
"提取音高和处理数据使用的CPU进程数": "ピッチの抽出やデータ処理に使用するCPUスレッド数",
|
||||||
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "ステップ2a: 訓練フォルダー内のすべての音声ファイルを自動的に探索し、スライスと正規化を行い、2つのwavフォルダーを実験ディレクトリに生成します。現在は一人でのトレーニングのみをサポートしています。",
|
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "ステップ2a: 訓練フォルダー内のすべての音声ファイルを自動的に探索し、スライスと正規化を行い、2つのwavフォルダーを実験ディレクトリに生成します。現在は一人でのトレーニングのみをサポートしています。",
|
||||||
"输入训练文件夹路径": "トレーニング用フォルダのパスを入力してください",
|
"输入训练文件夹路径": "トレーニング用フォルダのパスを入力してください",
|
||||||
"请指定说话人id": "話者IDを指定してください",
|
"请指定说话人id": "話者IDを指定してください",
|
||||||
"处理数据": "データ処理",
|
"处理数据": "データ処理",
|
||||||
"step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)": "ステップ2b: CPUを使用して音高を抽出する(モデルに音高がある場合)、GPUを使用して特徴を抽出する(カード番号を選択する)",
|
"step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)": "ステップ2b: CPUを使用して音高を抽出する(モデルに音高がある場合)、GPUを使用して特徴を抽出する(GPUの番号を選択する)",
|
||||||
"以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2": "ハイフンで区切って使用するカード番号を入力します。例えば0-1-2はカード0、カード1、カード2を使用します",
|
"以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2": "ハイフンで区切って使用するGPUの番号を入力します。例えば0-1-2はGPU0、GPU1、GPU2を使用します",
|
||||||
"显卡信息": "カード情報",
|
"显卡信息": "GPU情報",
|
||||||
"选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢": "音高抽出アルゴリズムの選択:歌声を入力する場合は、pmを使用して速度を上げることができます。CPUが低い場合はdioを使用して速度を上げることができます。harvestは品質が高く、精度が高いですが、遅いです。",
|
"选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢": "音高抽出アルゴリズムの選択:歌声を入力する場合は、pmを使用して速度を上げることができます。CPUが低い場合はdioを使用して速度を上げることができます。harvestは品質が高く、精度が高いですが、遅いです。",
|
||||||
"特征提取": "特徴抽出",
|
"特征提取": "特徴抽出",
|
||||||
"step3: 填写训练设置, 开始训练模型和索引": "ステップ3: トレーニング設定を入力して、モデルとインデックスのトレーニングを開始します",
|
"step3: 填写训练设置, 开始训练模型和索引": "ステップ3: トレーニング設定を入力して、モデルとインデックスのトレーニングを開始します",
|
||||||
"保存频率save_every_epoch": "エポックごとの保存頻度",
|
"保存频率save_every_epoch": "エポックごとの保存頻度",
|
||||||
"总训练轮数total_epoch": "総トレーニング回数",
|
"总训练轮数total_epoch": "総エポック数",
|
||||||
"每张显卡的batch_size": "每张显卡的batch_size",
|
"每张显卡的batch_size": "GPUごとのバッチサイズ",
|
||||||
"是否仅保存最新的ckpt文件以节省硬盘空间": "ハードディスク容量を節約するため、最新のckptファイルのみを保存するかどうか",
|
"是否仅保存最新的ckpt文件以节省硬盘空间": "ハードディスク容量を節約するため、最新のckptファイルのみを保存するかどうか",
|
||||||
"否": "否",
|
"否": "いいえ",
|
||||||
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "すべてのトレーニングデータをメモリにキャッシュするかどうか。10分以下の小さなデータはキャッシュしてトレーニングを高速化できますが、大きなデータをキャッシュするとメモリが破裂し、あまり速度が上がりません。",
|
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "すべてのトレーニングデータをメモリにキャッシュするかどうか。10分以下の小さなデータはキャッシュしてトレーニングを高速化できますが、大きなデータをキャッシュするとメモリが破裂し、あまり速度が上がりません。",
|
||||||
"加载预训练底模G路径": "事前学習済みのGモデルのパスをロードしてください",
|
"是否在每次保存时间点将最终小模型保存至weights文件夹": "各保存時点の小モデルを全部weightsフォルダに保存するかどうか",
|
||||||
"加载预训练底模D路径": "事前学習済みのDモデルのパスをロードしてください",
|
"加载预训练底模G路径": "事前学習済みのGモデルのパス",
|
||||||
|
"加载预训练底模D路径": "事前学習済みのDモデルのパス",
|
||||||
"训练模型": "モデルのトレーニング",
|
"训练模型": "モデルのトレーニング",
|
||||||
"训练特征索引": "特徴インデックスのトレーニング",
|
"训练特征索引": "特徴インデックスのトレーニング",
|
||||||
"一键训练": "ワンクリックトレーニング",
|
"一键训练": "ワンクリックトレーニング",
|
||||||
@@ -72,6 +75,7 @@
|
|||||||
"模型是否带音高指导": "モデルに音高ガイドを付けるかどうか",
|
"模型是否带音高指导": "モデルに音高ガイドを付けるかどうか",
|
||||||
"要置入的模型信息": "挿入するモデル情報",
|
"要置入的模型信息": "挿入するモデル情報",
|
||||||
"保存的模型名不带后缀": "拡張子のない保存するモデル名",
|
"保存的模型名不带后缀": "拡張子のない保存するモデル名",
|
||||||
|
"模型版本型号": "モデルのバージョン",
|
||||||
"融合": "フュージョン",
|
"融合": "フュージョン",
|
||||||
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "モデル情報の修正(weightsフォルダから抽出された小さなモデルファイルのみ対応)",
|
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "モデル情報の修正(weightsフォルダから抽出された小さなモデルファイルのみ対応)",
|
||||||
"模型路径": "モデルパス",
|
"模型路径": "モデルパス",
|
||||||
@@ -85,17 +89,17 @@
|
|||||||
"模型是否带音高指导,1是0否": "モデルに音高ガイドを付けるかどうか、1は付ける、0は付けない",
|
"模型是否带音高指导,1是0否": "モデルに音高ガイドを付けるかどうか、1は付ける、0は付けない",
|
||||||
"提取": "抽出",
|
"提取": "抽出",
|
||||||
"Onnx导出": "Onnx",
|
"Onnx导出": "Onnx",
|
||||||
"RVC模型路径": "RVCルパス",
|
"RVC模型路径": "RVCモデルパス",
|
||||||
"Onnx输出路径": "Onnx出力パス",
|
"Onnx输出路径": "Onnx出力パス",
|
||||||
"MoeVS模型": "MoeSS?",
|
"MoeVS模型": "MoeSS?",
|
||||||
"导出Onnx模型": "Onnxに変換",
|
"导出Onnx模型": "Onnxに変換",
|
||||||
"常见问题解答": "常见问题解答",
|
"常见问题解答": "よくある質問",
|
||||||
"招募音高曲线前端编辑器": "音高曲線フロントエンドエディターを募集",
|
"招募音高曲线前端编辑器": "音高曲線フロントエンドエディターを募集",
|
||||||
"加开发群联系我xxxxx": "開発グループに参加して私に連絡してくださいxxxxx",
|
"加开发群联系我xxxxx": "開発グループに参加して私に連絡してくださいxxxxx",
|
||||||
"点击查看交流、问题反馈群号": "クリックして交流、問題フィードバックグループ番号を表示",
|
"点击查看交流、问题反馈群号": "クリックして交流、問題フィードバックグループ番号を表示",
|
||||||
"xxxxx": "xxxxx",
|
"xxxxx": "xxxxx",
|
||||||
"加载模型": "モデルをロード",
|
"加载模型": "モデルをロード",
|
||||||
"Hubert模型": "Hubert模型",
|
"Hubert模型": "Hubertモデル",
|
||||||
"选择.pth文件": ".pthファイルを選択",
|
"选择.pth文件": ".pthファイルを選択",
|
||||||
"选择.index文件": ".indexファイルを選択",
|
"选择.index文件": ".indexファイルを選択",
|
||||||
"选择.npy文件": ".npyファイルを選択",
|
"选择.npy文件": ".npyファイルを選択",
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
"特征文件路径": "特征文件路径",
|
"特征文件路径": "特征文件路径",
|
||||||
"检索特征占比": "检索特征占比",
|
"检索特征占比": "检索特征占比",
|
||||||
"后处理重采样至最终采样率,0为不进行重采样": "后处理重采样至最终采样率,0为不进行重采样",
|
"后处理重采样至最终采样率,0为不进行重采样": "后处理重采样至最终采样率,0为不进行重采样",
|
||||||
|
"输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络": "输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络",
|
||||||
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调",
|
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调",
|
||||||
"转换": "转换",
|
"转换": "转换",
|
||||||
"输出信息": "输出信息",
|
"输出信息": "输出信息",
|
||||||
@@ -42,6 +43,7 @@
|
|||||||
"输入实验名": "输入实验名",
|
"输入实验名": "输入实验名",
|
||||||
"目标采样率": "目标采样率",
|
"目标采样率": "目标采样率",
|
||||||
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "模型是否带音高指导(唱歌一定要, 语音可以不要)",
|
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "模型是否带音高指导(唱歌一定要, 语音可以不要)",
|
||||||
|
"版本(目前仅40k支持了v2)": "版本(目前仅40k支持了v2)",
|
||||||
"提取音高和处理数据使用的CPU进程数": "提取音高和处理数据使用的CPU进程数",
|
"提取音高和处理数据使用的CPU进程数": "提取音高和处理数据使用的CPU进程数",
|
||||||
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ",
|
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ",
|
||||||
"输入训练文件夹路径": "输入训练文件夹路径",
|
"输入训练文件夹路径": "输入训练文件夹路径",
|
||||||
@@ -59,6 +61,7 @@
|
|||||||
"是否仅保存最新的ckpt文件以节省硬盘空间": "是否仅保存最新的ckpt文件以节省硬盘空间",
|
"是否仅保存最新的ckpt文件以节省硬盘空间": "是否仅保存最新的ckpt文件以节省硬盘空间",
|
||||||
"否": "否",
|
"否": "否",
|
||||||
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速",
|
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速",
|
||||||
|
"是否在每次保存时间点将最终小模型保存至weights文件夹": "是否在每次保存时间点将最终小模型保存至weights文件夹",
|
||||||
"加载预训练底模G路径": "加载预训练底模G路径",
|
"加载预训练底模G路径": "加载预训练底模G路径",
|
||||||
"加载预训练底模D路径": "加载预训练底模D路径",
|
"加载预训练底模D路径": "加载预训练底模D路径",
|
||||||
"训练模型": "训练模型",
|
"训练模型": "训练模型",
|
||||||
@@ -72,6 +75,7 @@
|
|||||||
"模型是否带音高指导": "模型是否带音高指导",
|
"模型是否带音高指导": "模型是否带音高指导",
|
||||||
"要置入的模型信息": "要置入的模型信息",
|
"要置入的模型信息": "要置入的模型信息",
|
||||||
"保存的模型名不带后缀": "保存的模型名不带后缀",
|
"保存的模型名不带后缀": "保存的模型名不带后缀",
|
||||||
|
"模型版本型号": "模型版本型号",
|
||||||
"融合": "融合",
|
"融合": "融合",
|
||||||
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "修改模型信息(仅支持weights文件夹下提取的小模型文件)",
|
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "修改模型信息(仅支持weights文件夹下提取的小模型文件)",
|
||||||
"模型路径": "模型路径",
|
"模型路径": "模型路径",
|
||||||
@@ -114,5 +118,8 @@
|
|||||||
"性能设置": "性能设置",
|
"性能设置": "性能设置",
|
||||||
"开始音频转换": "开始音频转换",
|
"开始音频转换": "开始音频转换",
|
||||||
"停止音频转换": "停止音频转换",
|
"停止音频转换": "停止音频转换",
|
||||||
|
"导出文件格式": "导出文件格式",
|
||||||
|
"保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果": "保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果",
|
||||||
|
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU",
|
||||||
"推理时间(ms):": "推理时间(ms):"
|
"推理时间(ms):": "推理时间(ms):"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
"特征文件路径": "特徵檔案路徑",
|
"特征文件路径": "特徵檔案路徑",
|
||||||
"检索特征占比": "檢索特徵佔比",
|
"检索特征占比": "檢索特徵佔比",
|
||||||
"后处理重采样至最终采样率,0为不进行重采样": "後處理重採樣至最終採樣率,0為不進行重採樣",
|
"后处理重采样至最终采样率,0为不进行重采样": "後處理重採樣至最終採樣率,0為不進行重採樣",
|
||||||
|
"输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络": "輸入源音量包絡替換輸出音量包絡融合比例,越靠近1越使用輸出包絡",
|
||||||
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0曲線檔案,可選,一行一個音高,代替預設的F0及升降調",
|
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0曲線檔案,可選,一行一個音高,代替預設的F0及升降調",
|
||||||
"转换": "轉換",
|
"转换": "轉換",
|
||||||
"输出信息": "輸出訊息",
|
"输出信息": "輸出訊息",
|
||||||
@@ -42,6 +43,7 @@
|
|||||||
"输入实验名": "輸入實驗名稱",
|
"输入实验名": "輸入實驗名稱",
|
||||||
"目标采样率": "目標取樣率",
|
"目标采样率": "目標取樣率",
|
||||||
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "模型是否帶音高指導(唱歌一定要,語音可以不要)",
|
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "模型是否帶音高指導(唱歌一定要,語音可以不要)",
|
||||||
|
"版本(目前仅40k支持了v2)": "版本(目前僅40k支持了v2)",
|
||||||
"提取音高和处理数据使用的CPU进程数": "提取音高和處理數據使用的CPU進程數",
|
"提取音高和处理数据使用的CPU进程数": "提取音高和處理數據使用的CPU進程數",
|
||||||
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a:自動遍歷訓練資料夾下所有可解碼成音頻的檔案並進行切片歸一化,在實驗目錄下生成2個wav資料夾;暫時只支援單人訓練。",
|
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a:自動遍歷訓練資料夾下所有可解碼成音頻的檔案並進行切片歸一化,在實驗目錄下生成2個wav資料夾;暫時只支援單人訓練。",
|
||||||
"输入训练文件夹路径": "輸入訓練檔案夾路徑",
|
"输入训练文件夹路径": "輸入訓練檔案夾路徑",
|
||||||
@@ -59,6 +61,7 @@
|
|||||||
"是否仅保存最新的ckpt文件以节省硬盘空间": "是否僅保存最新的ckpt檔案以節省硬碟空間",
|
"是否仅保存最新的ckpt文件以节省硬盘空间": "是否僅保存最新的ckpt檔案以節省硬碟空間",
|
||||||
"否": "否",
|
"否": "否",
|
||||||
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "是否緩存所有訓練集至 VRAM。小於10分鐘的小數據可緩存以加速訓練,大數據緩存會爆 VRAM 也加不了多少速度",
|
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "是否緩存所有訓練集至 VRAM。小於10分鐘的小數據可緩存以加速訓練,大數據緩存會爆 VRAM 也加不了多少速度",
|
||||||
|
"是否在每次保存时间点将最终小模型保存至weights文件夹": "是否在每次保存時間點將最終小模型保存至weights檔夾",
|
||||||
"加载预训练底模G路径": "加載預訓練底模G路徑",
|
"加载预训练底模G路径": "加載預訓練底模G路徑",
|
||||||
"加载预训练底模D路径": "加載預訓練底模D路徑",
|
"加载预训练底模D路径": "加載預訓練底模D路徑",
|
||||||
"训练模型": "訓練模型",
|
"训练模型": "訓練模型",
|
||||||
@@ -72,6 +75,7 @@
|
|||||||
"模型是否带音高指导": "模型是否帶音高指導",
|
"模型是否带音高指导": "模型是否帶音高指導",
|
||||||
"要置入的模型信息": "要置入的模型資訊",
|
"要置入的模型信息": "要置入的模型資訊",
|
||||||
"保存的模型名不带后缀": "儲存的模型名不帶副檔名",
|
"保存的模型名不带后缀": "儲存的模型名不帶副檔名",
|
||||||
|
"模型版本型号": "模型版本型號",
|
||||||
"融合": "融合",
|
"融合": "融合",
|
||||||
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "修改模型資訊(僅支援weights資料夾下提取的小模型檔案)",
|
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "修改模型資訊(僅支援weights資料夾下提取的小模型檔案)",
|
||||||
"模型路径": "模型路徑",
|
"模型路径": "模型路徑",
|
||||||
@@ -114,5 +118,8 @@
|
|||||||
"性能设置": "效能設定",
|
"性能设置": "效能設定",
|
||||||
"开始音频转换": "開始音訊轉換",
|
"开始音频转换": "開始音訊轉換",
|
||||||
"停止音频转换": "停止音訊轉換",
|
"停止音频转换": "停止音訊轉換",
|
||||||
|
"导出文件格式": "導出檔格式",
|
||||||
|
"保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果": "保護清輔音和呼吸聲,防止電音撕裂等artifact,拉滿0.5不開啟,調低加大保護力度但可能降低索引效果",
|
||||||
|
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "選擇音高提取演算法,輸入歌聲可用pm提速,harvest低音好但巨慢無比,crepe效果好但吃GPU",
|
||||||
"推理时间(ms):": "推理時間(ms):"
|
"推理时间(ms):": "推理時間(ms):"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
"特征文件路径": "特徵檔案路徑",
|
"特征文件路径": "特徵檔案路徑",
|
||||||
"检索特征占比": "檢索特徵佔比",
|
"检索特征占比": "檢索特徵佔比",
|
||||||
"后处理重采样至最终采样率,0为不进行重采样": "後處理重採樣至最終採樣率,0為不進行重採樣",
|
"后处理重采样至最终采样率,0为不进行重采样": "後處理重採樣至最終採樣率,0為不進行重採樣",
|
||||||
|
"输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络": "輸入源音量包絡替換輸出音量包絡融合比例,越靠近1越使用輸出包絡",
|
||||||
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0曲線檔案,可選,一行一個音高,代替預設的F0及升降調",
|
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0曲線檔案,可選,一行一個音高,代替預設的F0及升降調",
|
||||||
"转换": "轉換",
|
"转换": "轉換",
|
||||||
"输出信息": "輸出訊息",
|
"输出信息": "輸出訊息",
|
||||||
@@ -42,6 +43,7 @@
|
|||||||
"输入实验名": "輸入實驗名稱",
|
"输入实验名": "輸入實驗名稱",
|
||||||
"目标采样率": "目標取樣率",
|
"目标采样率": "目標取樣率",
|
||||||
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "模型是否帶音高指導(唱歌一定要,語音可以不要)",
|
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "模型是否帶音高指導(唱歌一定要,語音可以不要)",
|
||||||
|
"版本(目前仅40k支持了v2)": "版本(目前僅40k支持了v2)",
|
||||||
"提取音高和处理数据使用的CPU进程数": "提取音高和處理數據使用的CPU進程數",
|
"提取音高和处理数据使用的CPU进程数": "提取音高和處理數據使用的CPU進程數",
|
||||||
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a:自動遍歷訓練資料夾下所有可解碼成音頻的檔案並進行切片歸一化,在實驗目錄下生成2個wav資料夾;暫時只支援單人訓練。",
|
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a:自動遍歷訓練資料夾下所有可解碼成音頻的檔案並進行切片歸一化,在實驗目錄下生成2個wav資料夾;暫時只支援單人訓練。",
|
||||||
"输入训练文件夹路径": "輸入訓練檔案夾路徑",
|
"输入训练文件夹路径": "輸入訓練檔案夾路徑",
|
||||||
@@ -59,6 +61,7 @@
|
|||||||
"是否仅保存最新的ckpt文件以节省硬盘空间": "是否僅保存最新的ckpt檔案以節省硬碟空間",
|
"是否仅保存最新的ckpt文件以节省硬盘空间": "是否僅保存最新的ckpt檔案以節省硬碟空間",
|
||||||
"否": "否",
|
"否": "否",
|
||||||
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "是否緩存所有訓練集至 VRAM。小於10分鐘的小數據可緩存以加速訓練,大數據緩存會爆 VRAM 也加不了多少速度",
|
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "是否緩存所有訓練集至 VRAM。小於10分鐘的小數據可緩存以加速訓練,大數據緩存會爆 VRAM 也加不了多少速度",
|
||||||
|
"是否在每次保存时间点将最终小模型保存至weights文件夹": "是否在每次保存時間點將最終小模型保存至weights檔夾",
|
||||||
"加载预训练底模G路径": "加載預訓練底模G路徑",
|
"加载预训练底模G路径": "加載預訓練底模G路徑",
|
||||||
"加载预训练底模D路径": "加載預訓練底模D路徑",
|
"加载预训练底模D路径": "加載預訓練底模D路徑",
|
||||||
"训练模型": "訓練模型",
|
"训练模型": "訓練模型",
|
||||||
@@ -72,6 +75,7 @@
|
|||||||
"模型是否带音高指导": "模型是否帶音高指導",
|
"模型是否带音高指导": "模型是否帶音高指導",
|
||||||
"要置入的模型信息": "要置入的模型資訊",
|
"要置入的模型信息": "要置入的模型資訊",
|
||||||
"保存的模型名不带后缀": "儲存的模型名不帶副檔名",
|
"保存的模型名不带后缀": "儲存的模型名不帶副檔名",
|
||||||
|
"模型版本型号": "模型版本型號",
|
||||||
"融合": "融合",
|
"融合": "融合",
|
||||||
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "修改模型資訊(僅支援weights資料夾下提取的小模型檔案)",
|
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "修改模型資訊(僅支援weights資料夾下提取的小模型檔案)",
|
||||||
"模型路径": "模型路徑",
|
"模型路径": "模型路徑",
|
||||||
@@ -114,5 +118,8 @@
|
|||||||
"性能设置": "效能設定",
|
"性能设置": "效能設定",
|
||||||
"开始音频转换": "開始音訊轉換",
|
"开始音频转换": "開始音訊轉換",
|
||||||
"停止音频转换": "停止音訊轉換",
|
"停止音频转换": "停止音訊轉換",
|
||||||
|
"导出文件格式": "導出檔格式",
|
||||||
|
"保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果": "保護清輔音和呼吸聲,防止電音撕裂等artifact,拉滿0.5不開啟,調低加大保護力度但可能降低索引效果",
|
||||||
|
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "選擇音高提取演算法,輸入歌聲可用pm提速,harvest低音好但巨慢無比,crepe效果好但吃GPU",
|
||||||
"推理时间(ms):": "推理時間(ms):"
|
"推理时间(ms):": "推理時間(ms):"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
"特征文件路径": "特徵檔案路徑",
|
"特征文件路径": "特徵檔案路徑",
|
||||||
"检索特征占比": "檢索特徵佔比",
|
"检索特征占比": "檢索特徵佔比",
|
||||||
"后处理重采样至最终采样率,0为不进行重采样": "後處理重採樣至最終採樣率,0為不進行重採樣",
|
"后处理重采样至最终采样率,0为不进行重采样": "後處理重採樣至最終採樣率,0為不進行重採樣",
|
||||||
|
"输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络": "輸入源音量包絡替換輸出音量包絡融合比例,越靠近1越使用輸出包絡",
|
||||||
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0曲線檔案,可選,一行一個音高,代替預設的F0及升降調",
|
"F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调": "F0曲線檔案,可選,一行一個音高,代替預設的F0及升降調",
|
||||||
"转换": "轉換",
|
"转换": "轉換",
|
||||||
"输出信息": "輸出訊息",
|
"输出信息": "輸出訊息",
|
||||||
@@ -42,6 +43,7 @@
|
|||||||
"输入实验名": "輸入實驗名稱",
|
"输入实验名": "輸入實驗名稱",
|
||||||
"目标采样率": "目標取樣率",
|
"目标采样率": "目標取樣率",
|
||||||
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "模型是否帶音高指導(唱歌一定要,語音可以不要)",
|
"模型是否带音高指导(唱歌一定要, 语音可以不要)": "模型是否帶音高指導(唱歌一定要,語音可以不要)",
|
||||||
|
"版本(目前仅40k支持了v2)": "版本(目前僅40k支持了v2)",
|
||||||
"提取音高和处理数据使用的CPU进程数": "提取音高和處理數據使用的CPU進程數",
|
"提取音高和处理数据使用的CPU进程数": "提取音高和處理數據使用的CPU進程數",
|
||||||
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a:自動遍歷訓練資料夾下所有可解碼成音頻的檔案並進行切片歸一化,在實驗目錄下生成2個wav資料夾;暫時只支援單人訓練。",
|
"step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. ": "step2a:自動遍歷訓練資料夾下所有可解碼成音頻的檔案並進行切片歸一化,在實驗目錄下生成2個wav資料夾;暫時只支援單人訓練。",
|
||||||
"输入训练文件夹路径": "輸入訓練檔案夾路徑",
|
"输入训练文件夹路径": "輸入訓練檔案夾路徑",
|
||||||
@@ -59,6 +61,7 @@
|
|||||||
"是否仅保存最新的ckpt文件以节省硬盘空间": "是否僅保存最新的ckpt檔案以節省硬碟空間",
|
"是否仅保存最新的ckpt文件以节省硬盘空间": "是否僅保存最新的ckpt檔案以節省硬碟空間",
|
||||||
"否": "否",
|
"否": "否",
|
||||||
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "是否緩存所有訓練集至 VRAM。小於10分鐘的小數據可緩存以加速訓練,大數據緩存會爆 VRAM 也加不了多少速度",
|
"是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速": "是否緩存所有訓練集至 VRAM。小於10分鐘的小數據可緩存以加速訓練,大數據緩存會爆 VRAM 也加不了多少速度",
|
||||||
|
"是否在每次保存时间点将最终小模型保存至weights文件夹": "是否在每次保存時間點將最終小模型保存至weights檔夾",
|
||||||
"加载预训练底模G路径": "加載預訓練底模G路徑",
|
"加载预训练底模G路径": "加載預訓練底模G路徑",
|
||||||
"加载预训练底模D路径": "加載預訓練底模D路徑",
|
"加载预训练底模D路径": "加載預訓練底模D路徑",
|
||||||
"训练模型": "訓練模型",
|
"训练模型": "訓練模型",
|
||||||
@@ -72,6 +75,7 @@
|
|||||||
"模型是否带音高指导": "模型是否帶音高指導",
|
"模型是否带音高指导": "模型是否帶音高指導",
|
||||||
"要置入的模型信息": "要置入的模型資訊",
|
"要置入的模型信息": "要置入的模型資訊",
|
||||||
"保存的模型名不带后缀": "儲存的模型名不帶副檔名",
|
"保存的模型名不带后缀": "儲存的模型名不帶副檔名",
|
||||||
|
"模型版本型号": "模型版本型號",
|
||||||
"融合": "融合",
|
"融合": "融合",
|
||||||
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "修改模型資訊(僅支援weights資料夾下提取的小模型檔案)",
|
"修改模型信息(仅支持weights文件夹下提取的小模型文件)": "修改模型資訊(僅支援weights資料夾下提取的小模型檔案)",
|
||||||
"模型路径": "模型路徑",
|
"模型路径": "模型路徑",
|
||||||
@@ -114,5 +118,8 @@
|
|||||||
"性能设置": "效能設定",
|
"性能设置": "效能設定",
|
||||||
"开始音频转换": "開始音訊轉換",
|
"开始音频转换": "開始音訊轉換",
|
||||||
"停止音频转换": "停止音訊轉換",
|
"停止音频转换": "停止音訊轉換",
|
||||||
|
"导出文件格式": "導出檔格式",
|
||||||
|
"保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果": "保護清輔音和呼吸聲,防止電音撕裂等artifact,拉滿0.5不開啟,調低加大保護力度但可能降低索引效果",
|
||||||
|
"选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU": "選擇音高提取演算法,輸入歌聲可用pm提速,harvest低音好但巨慢無比,crepe效果好但吃GPU",
|
||||||
"推理时间(ms):": "推理時間(ms):"
|
"推理时间(ms):": "推理時間(ms):"
|
||||||
}
|
}
|
||||||
|
|||||||
585
infer-web.py
585
infer-web.py
File diff suppressed because it is too large
Load Diff
44
infer/train-index -v2.py
Normal file
44
infer/train-index -v2.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
"""
|
||||||
|
格式:直接cid为自带的index位;aid放不下了,通过字典来查,反正就5w个
|
||||||
|
"""
|
||||||
|
import faiss, numpy as np, os
|
||||||
|
|
||||||
|
# ###########如果是原始特征要先写save
|
||||||
|
inp_root = r"./logs/nene/3_feature768"
|
||||||
|
npys = []
|
||||||
|
listdir_res = list(os.listdir(inp_root))
|
||||||
|
for name in sorted(listdir_res):
|
||||||
|
phone = np.load("%s/%s" % (inp_root, name))
|
||||||
|
npys.append(phone)
|
||||||
|
big_npy = np.concatenate(npys, 0)
|
||||||
|
big_npy_idx = np.arange(big_npy.shape[0])
|
||||||
|
np.random.shuffle(big_npy_idx)
|
||||||
|
big_npy = big_npy[big_npy_idx]
|
||||||
|
print(big_npy.shape) # (6196072, 192)#fp32#4.43G
|
||||||
|
np.save("infer/big_src_feature_mi.npy", big_npy)
|
||||||
|
|
||||||
|
##################train+add
|
||||||
|
# big_npy=np.load("/bili-coeus/jupyter/jupyterhub-liujing04/vits_ch/inference_f0/big_src_feature_mi.npy")
|
||||||
|
n_ivf = min(int(16 * np.sqrt(big_npy.shape[0])), big_npy.shape[0] // 39)
|
||||||
|
index = faiss.index_factory(768, "IVF%s,Flat" % n_ivf) # mi
|
||||||
|
print("training")
|
||||||
|
index_ivf = faiss.extract_index_ivf(index) #
|
||||||
|
index_ivf.nprobe = 1
|
||||||
|
index.train(big_npy)
|
||||||
|
faiss.write_index(
|
||||||
|
index, "infer/trained_IVF%s_Flat_baseline_src_feat_v2.index" % (n_ivf)
|
||||||
|
)
|
||||||
|
print("adding")
|
||||||
|
batch_size_add = 8192
|
||||||
|
for i in range(0, big_npy.shape[0], batch_size_add):
|
||||||
|
index.add(big_npy[i : i + batch_size_add])
|
||||||
|
faiss.write_index(index, "infer/added_IVF%s_Flat_mi_baseline_src_feat.index" % (n_ivf))
|
||||||
|
"""
|
||||||
|
大小(都是FP32)
|
||||||
|
big_src_feature 2.95G
|
||||||
|
(3098036, 256)
|
||||||
|
big_emb 4.43G
|
||||||
|
(6196072, 192)
|
||||||
|
big_emb双倍是因为求特征要repeat后再加pitch
|
||||||
|
|
||||||
|
"""
|
||||||
@@ -61,7 +61,7 @@ class TextEncoder256(nn.Module):
|
|||||||
return m, logs, x_mask
|
return m, logs, x_mask
|
||||||
|
|
||||||
|
|
||||||
class TextEncoder256Sim(nn.Module):
|
class TextEncoder768(nn.Module):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
out_channels,
|
out_channels,
|
||||||
@@ -81,14 +81,14 @@ class TextEncoder256Sim(nn.Module):
|
|||||||
self.n_layers = n_layers
|
self.n_layers = n_layers
|
||||||
self.kernel_size = kernel_size
|
self.kernel_size = kernel_size
|
||||||
self.p_dropout = p_dropout
|
self.p_dropout = p_dropout
|
||||||
self.emb_phone = nn.Linear(256, hidden_channels)
|
self.emb_phone = nn.Linear(768, hidden_channels)
|
||||||
self.lrelu = nn.LeakyReLU(0.1, inplace=True)
|
self.lrelu = nn.LeakyReLU(0.1, inplace=True)
|
||||||
if f0 == True:
|
if f0 == True:
|
||||||
self.emb_pitch = nn.Embedding(256, hidden_channels) # pitch 256
|
self.emb_pitch = nn.Embedding(256, hidden_channels) # pitch 256
|
||||||
self.encoder = attentions.Encoder(
|
self.encoder = attentions.Encoder(
|
||||||
hidden_channels, filter_channels, n_heads, n_layers, kernel_size, p_dropout
|
hidden_channels, filter_channels, n_heads, n_layers, kernel_size, p_dropout
|
||||||
)
|
)
|
||||||
self.proj = nn.Conv1d(hidden_channels, out_channels, 1)
|
self.proj = nn.Conv1d(hidden_channels, out_channels * 2, 1)
|
||||||
|
|
||||||
def forward(self, phone, pitch, lengths):
|
def forward(self, phone, pitch, lengths):
|
||||||
if pitch == None:
|
if pitch == None:
|
||||||
@@ -102,8 +102,10 @@ class TextEncoder256Sim(nn.Module):
|
|||||||
x.dtype
|
x.dtype
|
||||||
)
|
)
|
||||||
x = self.encoder(x * x_mask, x_mask)
|
x = self.encoder(x * x_mask, x_mask)
|
||||||
x = self.proj(x) * x_mask
|
stats = self.proj(x) * x_mask
|
||||||
return x, x_mask
|
|
||||||
|
m, logs = torch.split(stats, self.out_channels, dim=1)
|
||||||
|
return m, logs, x_mask
|
||||||
|
|
||||||
|
|
||||||
class ResidualCouplingBlock(nn.Module):
|
class ResidualCouplingBlock(nn.Module):
|
||||||
@@ -638,6 +640,117 @@ class SynthesizerTrnMs256NSFsid(nn.Module):
|
|||||||
return o, x_mask, (z, z_p, m_p, logs_p)
|
return o, x_mask, (z, z_p, m_p, logs_p)
|
||||||
|
|
||||||
|
|
||||||
|
class SynthesizerTrnMs768NSFsid(nn.Module):
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
spec_channels,
|
||||||
|
segment_size,
|
||||||
|
inter_channels,
|
||||||
|
hidden_channels,
|
||||||
|
filter_channels,
|
||||||
|
n_heads,
|
||||||
|
n_layers,
|
||||||
|
kernel_size,
|
||||||
|
p_dropout,
|
||||||
|
resblock,
|
||||||
|
resblock_kernel_sizes,
|
||||||
|
resblock_dilation_sizes,
|
||||||
|
upsample_rates,
|
||||||
|
upsample_initial_channel,
|
||||||
|
upsample_kernel_sizes,
|
||||||
|
spk_embed_dim,
|
||||||
|
gin_channels,
|
||||||
|
sr,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
|
super().__init__()
|
||||||
|
if type(sr) == type("strr"):
|
||||||
|
sr = sr2sr[sr]
|
||||||
|
self.spec_channels = spec_channels
|
||||||
|
self.inter_channels = inter_channels
|
||||||
|
self.hidden_channels = hidden_channels
|
||||||
|
self.filter_channels = filter_channels
|
||||||
|
self.n_heads = n_heads
|
||||||
|
self.n_layers = n_layers
|
||||||
|
self.kernel_size = kernel_size
|
||||||
|
self.p_dropout = p_dropout
|
||||||
|
self.resblock = resblock
|
||||||
|
self.resblock_kernel_sizes = resblock_kernel_sizes
|
||||||
|
self.resblock_dilation_sizes = resblock_dilation_sizes
|
||||||
|
self.upsample_rates = upsample_rates
|
||||||
|
self.upsample_initial_channel = upsample_initial_channel
|
||||||
|
self.upsample_kernel_sizes = upsample_kernel_sizes
|
||||||
|
self.segment_size = segment_size
|
||||||
|
self.gin_channels = gin_channels
|
||||||
|
# self.hop_length = hop_length#
|
||||||
|
self.spk_embed_dim = spk_embed_dim
|
||||||
|
self.enc_p = TextEncoder768(
|
||||||
|
inter_channels,
|
||||||
|
hidden_channels,
|
||||||
|
filter_channels,
|
||||||
|
n_heads,
|
||||||
|
n_layers,
|
||||||
|
kernel_size,
|
||||||
|
p_dropout,
|
||||||
|
)
|
||||||
|
self.dec = GeneratorNSF(
|
||||||
|
inter_channels,
|
||||||
|
resblock,
|
||||||
|
resblock_kernel_sizes,
|
||||||
|
resblock_dilation_sizes,
|
||||||
|
upsample_rates,
|
||||||
|
upsample_initial_channel,
|
||||||
|
upsample_kernel_sizes,
|
||||||
|
gin_channels=gin_channels,
|
||||||
|
sr=sr,
|
||||||
|
is_half=kwargs["is_half"],
|
||||||
|
)
|
||||||
|
self.enc_q = PosteriorEncoder(
|
||||||
|
spec_channels,
|
||||||
|
inter_channels,
|
||||||
|
hidden_channels,
|
||||||
|
5,
|
||||||
|
1,
|
||||||
|
16,
|
||||||
|
gin_channels=gin_channels,
|
||||||
|
)
|
||||||
|
self.flow = ResidualCouplingBlock(
|
||||||
|
inter_channels, hidden_channels, 5, 1, 3, gin_channels=gin_channels
|
||||||
|
)
|
||||||
|
self.emb_g = nn.Embedding(self.spk_embed_dim, gin_channels)
|
||||||
|
print("gin_channels:", gin_channels, "self.spk_embed_dim:", self.spk_embed_dim)
|
||||||
|
|
||||||
|
def remove_weight_norm(self):
|
||||||
|
self.dec.remove_weight_norm()
|
||||||
|
self.flow.remove_weight_norm()
|
||||||
|
self.enc_q.remove_weight_norm()
|
||||||
|
|
||||||
|
def forward(
|
||||||
|
self, phone, phone_lengths, pitch, pitchf, y, y_lengths, ds
|
||||||
|
): # 这里ds是id,[bs,1]
|
||||||
|
# print(1,pitch.shape)#[bs,t]
|
||||||
|
g = self.emb_g(ds).unsqueeze(-1) # [b, 256, 1]##1是t,广播的
|
||||||
|
m_p, logs_p, x_mask = self.enc_p(phone, pitch, phone_lengths)
|
||||||
|
z, m_q, logs_q, y_mask = self.enc_q(y, y_lengths, g=g)
|
||||||
|
z_p = self.flow(z, y_mask, g=g)
|
||||||
|
z_slice, ids_slice = commons.rand_slice_segments(
|
||||||
|
z, y_lengths, self.segment_size
|
||||||
|
)
|
||||||
|
# print(-1,pitchf.shape,ids_slice,self.segment_size,self.hop_length,self.segment_size//self.hop_length)
|
||||||
|
pitchf = commons.slice_segments2(pitchf, ids_slice, self.segment_size)
|
||||||
|
# print(-2,pitchf.shape,z_slice.shape)
|
||||||
|
o = self.dec(z_slice, pitchf, g=g)
|
||||||
|
return o, ids_slice, x_mask, y_mask, (z, z_p, m_p, logs_p, m_q, logs_q)
|
||||||
|
|
||||||
|
def infer(self, phone, phone_lengths, pitch, nsff0, sid, max_len=None):
|
||||||
|
g = self.emb_g(sid).unsqueeze(-1)
|
||||||
|
m_p, logs_p, x_mask = self.enc_p(phone, pitch, phone_lengths)
|
||||||
|
z_p = (m_p + torch.exp(logs_p) * torch.randn_like(m_p) * 0.66666) * x_mask
|
||||||
|
z = self.flow(z_p, x_mask, g=g, reverse=True)
|
||||||
|
o = self.dec((z * x_mask)[:, :, :max_len], nsff0, g=g)
|
||||||
|
return o, x_mask, (z, z_p, m_p, logs_p)
|
||||||
|
|
||||||
|
|
||||||
class SynthesizerTrnMs256NSFsid_nono(nn.Module):
|
class SynthesizerTrnMs256NSFsid_nono(nn.Module):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -740,11 +853,7 @@ class SynthesizerTrnMs256NSFsid_nono(nn.Module):
|
|||||||
return o, x_mask, (z, z_p, m_p, logs_p)
|
return o, x_mask, (z, z_p, m_p, logs_p)
|
||||||
|
|
||||||
|
|
||||||
class SynthesizerTrnMs256NSFsid_sim(nn.Module):
|
class SynthesizerTrnMs768NSFsid_nono(nn.Module):
|
||||||
"""
|
|
||||||
Synthesizer for Training
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
spec_channels,
|
spec_channels,
|
||||||
@@ -763,9 +872,8 @@ class SynthesizerTrnMs256NSFsid_sim(nn.Module):
|
|||||||
upsample_initial_channel,
|
upsample_initial_channel,
|
||||||
upsample_kernel_sizes,
|
upsample_kernel_sizes,
|
||||||
spk_embed_dim,
|
spk_embed_dim,
|
||||||
# hop_length,
|
gin_channels,
|
||||||
gin_channels=0,
|
sr=None,
|
||||||
use_sdp=True,
|
|
||||||
**kwargs
|
**kwargs
|
||||||
):
|
):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -787,7 +895,7 @@ class SynthesizerTrnMs256NSFsid_sim(nn.Module):
|
|||||||
self.gin_channels = gin_channels
|
self.gin_channels = gin_channels
|
||||||
# self.hop_length = hop_length#
|
# self.hop_length = hop_length#
|
||||||
self.spk_embed_dim = spk_embed_dim
|
self.spk_embed_dim = spk_embed_dim
|
||||||
self.enc_p = TextEncoder256Sim(
|
self.enc_p = TextEncoder768(
|
||||||
inter_channels,
|
inter_channels,
|
||||||
hidden_channels,
|
hidden_channels,
|
||||||
filter_channels,
|
filter_channels,
|
||||||
@@ -795,8 +903,9 @@ class SynthesizerTrnMs256NSFsid_sim(nn.Module):
|
|||||||
n_layers,
|
n_layers,
|
||||||
kernel_size,
|
kernel_size,
|
||||||
p_dropout,
|
p_dropout,
|
||||||
|
f0=False,
|
||||||
)
|
)
|
||||||
self.dec = GeneratorNSF(
|
self.dec = Generator(
|
||||||
inter_channels,
|
inter_channels,
|
||||||
resblock,
|
resblock,
|
||||||
resblock_kernel_sizes,
|
resblock_kernel_sizes,
|
||||||
@@ -805,9 +914,16 @@ class SynthesizerTrnMs256NSFsid_sim(nn.Module):
|
|||||||
upsample_initial_channel,
|
upsample_initial_channel,
|
||||||
upsample_kernel_sizes,
|
upsample_kernel_sizes,
|
||||||
gin_channels=gin_channels,
|
gin_channels=gin_channels,
|
||||||
is_half=kwargs["is_half"],
|
|
||||||
)
|
)
|
||||||
|
self.enc_q = PosteriorEncoder(
|
||||||
|
spec_channels,
|
||||||
|
inter_channels,
|
||||||
|
hidden_channels,
|
||||||
|
5,
|
||||||
|
1,
|
||||||
|
16,
|
||||||
|
gin_channels=gin_channels,
|
||||||
|
)
|
||||||
self.flow = ResidualCouplingBlock(
|
self.flow = ResidualCouplingBlock(
|
||||||
inter_channels, hidden_channels, 5, 1, 3, gin_channels=gin_channels
|
inter_channels, hidden_channels, 5, 1, 3, gin_channels=gin_channels
|
||||||
)
|
)
|
||||||
@@ -819,28 +935,24 @@ class SynthesizerTrnMs256NSFsid_sim(nn.Module):
|
|||||||
self.flow.remove_weight_norm()
|
self.flow.remove_weight_norm()
|
||||||
self.enc_q.remove_weight_norm()
|
self.enc_q.remove_weight_norm()
|
||||||
|
|
||||||
def forward(
|
def forward(self, phone, phone_lengths, y, y_lengths, ds): # 这里ds是id,[bs,1]
|
||||||
self, phone, phone_lengths, pitch, pitchf, y_lengths, ds
|
|
||||||
): # y是spec不需要了现在
|
|
||||||
g = self.emb_g(ds).unsqueeze(-1) # [b, 256, 1]##1是t,广播的
|
g = self.emb_g(ds).unsqueeze(-1) # [b, 256, 1]##1是t,广播的
|
||||||
x, x_mask = self.enc_p(phone, pitch, phone_lengths)
|
m_p, logs_p, x_mask = self.enc_p(phone, None, phone_lengths)
|
||||||
x = self.flow(x, x_mask, g=g, reverse=True)
|
z, m_q, logs_q, y_mask = self.enc_q(y, y_lengths, g=g)
|
||||||
|
z_p = self.flow(z, y_mask, g=g)
|
||||||
z_slice, ids_slice = commons.rand_slice_segments(
|
z_slice, ids_slice = commons.rand_slice_segments(
|
||||||
x, y_lengths, self.segment_size
|
z, y_lengths, self.segment_size
|
||||||
)
|
)
|
||||||
|
o = self.dec(z_slice, g=g)
|
||||||
|
return o, ids_slice, x_mask, y_mask, (z, z_p, m_p, logs_p, m_q, logs_q)
|
||||||
|
|
||||||
pitchf = commons.slice_segments2(pitchf, ids_slice, self.segment_size)
|
def infer(self, phone, phone_lengths, sid, max_len=None):
|
||||||
o = self.dec(z_slice, pitchf, g=g)
|
g = self.emb_g(sid).unsqueeze(-1)
|
||||||
return o, ids_slice
|
m_p, logs_p, x_mask = self.enc_p(phone, None, phone_lengths)
|
||||||
|
z_p = (m_p + torch.exp(logs_p) * torch.randn_like(m_p) * 0.66666) * x_mask
|
||||||
def infer(
|
z = self.flow(z_p, x_mask, g=g, reverse=True)
|
||||||
self, phone, phone_lengths, pitch, pitchf, ds, max_len=None
|
o = self.dec((z * x_mask)[:, :, :max_len], g=g)
|
||||||
): # y是spec不需要了现在
|
return o, x_mask, (z, z_p, m_p, logs_p)
|
||||||
g = self.emb_g(ds).unsqueeze(-1) # [b, 256, 1]##1是t,广播的
|
|
||||||
x, x_mask = self.enc_p(phone, pitch, phone_lengths)
|
|
||||||
x = self.flow(x, x_mask, g=g, reverse=True)
|
|
||||||
o = self.dec((x * x_mask)[:, :, :max_len], pitchf, g=g)
|
|
||||||
return o, o
|
|
||||||
|
|
||||||
|
|
||||||
class MultiPeriodDiscriminator(torch.nn.Module):
|
class MultiPeriodDiscriminator(torch.nn.Module):
|
||||||
@@ -873,6 +985,36 @@ class MultiPeriodDiscriminator(torch.nn.Module):
|
|||||||
return y_d_rs, y_d_gs, fmap_rs, fmap_gs
|
return y_d_rs, y_d_gs, fmap_rs, fmap_gs
|
||||||
|
|
||||||
|
|
||||||
|
class MultiPeriodDiscriminatorV2(torch.nn.Module):
|
||||||
|
def __init__(self, use_spectral_norm=False):
|
||||||
|
super(MultiPeriodDiscriminatorV2, self).__init__()
|
||||||
|
# periods = [2, 3, 5, 7, 11, 17]
|
||||||
|
periods = [2, 3, 5, 7, 11, 17, 23, 37]
|
||||||
|
|
||||||
|
discs = [DiscriminatorS(use_spectral_norm=use_spectral_norm)]
|
||||||
|
discs = discs + [
|
||||||
|
DiscriminatorP(i, use_spectral_norm=use_spectral_norm) for i in periods
|
||||||
|
]
|
||||||
|
self.discriminators = nn.ModuleList(discs)
|
||||||
|
|
||||||
|
def forward(self, y, y_hat):
|
||||||
|
y_d_rs = [] #
|
||||||
|
y_d_gs = []
|
||||||
|
fmap_rs = []
|
||||||
|
fmap_gs = []
|
||||||
|
for i, d in enumerate(self.discriminators):
|
||||||
|
y_d_r, fmap_r = d(y)
|
||||||
|
y_d_g, fmap_g = d(y_hat)
|
||||||
|
# for j in range(len(fmap_r)):
|
||||||
|
# print(i,j,y.shape,y_hat.shape,fmap_r[j].shape,fmap_g[j].shape)
|
||||||
|
y_d_rs.append(y_d_r)
|
||||||
|
y_d_gs.append(y_d_g)
|
||||||
|
fmap_rs.append(fmap_r)
|
||||||
|
fmap_gs.append(fmap_g)
|
||||||
|
|
||||||
|
return y_d_rs, y_d_gs, fmap_rs, fmap_gs
|
||||||
|
|
||||||
|
|
||||||
class DiscriminatorS(torch.nn.Module):
|
class DiscriminatorS(torch.nn.Module):
|
||||||
def __init__(self, use_spectral_norm=False):
|
def __init__(self, use_spectral_norm=False):
|
||||||
super(DiscriminatorS, self).__init__()
|
super(DiscriminatorS, self).__init__()
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ class TextEncoder256(nn.Module):
|
|||||||
return m, logs, x_mask
|
return m, logs, x_mask
|
||||||
|
|
||||||
|
|
||||||
class TextEncoder256Sim(nn.Module):
|
class TextEncoder768(nn.Module):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
out_channels,
|
out_channels,
|
||||||
@@ -81,14 +81,14 @@ class TextEncoder256Sim(nn.Module):
|
|||||||
self.n_layers = n_layers
|
self.n_layers = n_layers
|
||||||
self.kernel_size = kernel_size
|
self.kernel_size = kernel_size
|
||||||
self.p_dropout = p_dropout
|
self.p_dropout = p_dropout
|
||||||
self.emb_phone = nn.Linear(256, hidden_channels)
|
self.emb_phone = nn.Linear(768, hidden_channels)
|
||||||
self.lrelu = nn.LeakyReLU(0.1, inplace=True)
|
self.lrelu = nn.LeakyReLU(0.1, inplace=True)
|
||||||
if f0 == True:
|
if f0 == True:
|
||||||
self.emb_pitch = nn.Embedding(256, hidden_channels) # pitch 256
|
self.emb_pitch = nn.Embedding(256, hidden_channels) # pitch 256
|
||||||
self.encoder = attentions.Encoder(
|
self.encoder = attentions.Encoder(
|
||||||
hidden_channels, filter_channels, n_heads, n_layers, kernel_size, p_dropout
|
hidden_channels, filter_channels, n_heads, n_layers, kernel_size, p_dropout
|
||||||
)
|
)
|
||||||
self.proj = nn.Conv1d(hidden_channels, out_channels, 1)
|
self.proj = nn.Conv1d(hidden_channels, out_channels * 2, 1)
|
||||||
|
|
||||||
def forward(self, phone, pitch, lengths):
|
def forward(self, phone, pitch, lengths):
|
||||||
if pitch == None:
|
if pitch == None:
|
||||||
@@ -102,8 +102,10 @@ class TextEncoder256Sim(nn.Module):
|
|||||||
x.dtype
|
x.dtype
|
||||||
)
|
)
|
||||||
x = self.encoder(x * x_mask, x_mask)
|
x = self.encoder(x * x_mask, x_mask)
|
||||||
x = self.proj(x) * x_mask
|
stats = self.proj(x) * x_mask
|
||||||
return x, x_mask
|
|
||||||
|
m, logs = torch.split(stats, self.out_channels, dim=1)
|
||||||
|
return m, logs, x_mask
|
||||||
|
|
||||||
|
|
||||||
class ResidualCouplingBlock(nn.Module):
|
class ResidualCouplingBlock(nn.Module):
|
||||||
@@ -527,7 +529,7 @@ sr2sr = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class SynthesizerTrnMs256NSFsidO(nn.Module):
|
class SynthesizerTrnMsNSFsidM(nn.Module):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
spec_channels,
|
spec_channels,
|
||||||
@@ -571,15 +573,26 @@ class SynthesizerTrnMs256NSFsidO(nn.Module):
|
|||||||
self.gin_channels = gin_channels
|
self.gin_channels = gin_channels
|
||||||
# self.hop_length = hop_length#
|
# self.hop_length = hop_length#
|
||||||
self.spk_embed_dim = spk_embed_dim
|
self.spk_embed_dim = spk_embed_dim
|
||||||
self.enc_p = TextEncoder256(
|
if self.gin_channels == 256:
|
||||||
inter_channels,
|
self.enc_p = TextEncoder256(
|
||||||
hidden_channels,
|
inter_channels,
|
||||||
filter_channels,
|
hidden_channels,
|
||||||
n_heads,
|
filter_channels,
|
||||||
n_layers,
|
n_heads,
|
||||||
kernel_size,
|
n_layers,
|
||||||
p_dropout,
|
kernel_size,
|
||||||
)
|
p_dropout,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.enc_p = TextEncoder768(
|
||||||
|
inter_channels,
|
||||||
|
hidden_channels,
|
||||||
|
filter_channels,
|
||||||
|
n_heads,
|
||||||
|
n_layers,
|
||||||
|
kernel_size,
|
||||||
|
p_dropout,
|
||||||
|
)
|
||||||
self.dec = GeneratorNSF(
|
self.dec = GeneratorNSF(
|
||||||
inter_channels,
|
inter_channels,
|
||||||
resblock,
|
resblock,
|
||||||
@@ -605,6 +618,7 @@ class SynthesizerTrnMs256NSFsidO(nn.Module):
|
|||||||
inter_channels, hidden_channels, 5, 1, 3, gin_channels=gin_channels
|
inter_channels, hidden_channels, 5, 1, 3, gin_channels=gin_channels
|
||||||
)
|
)
|
||||||
self.emb_g = nn.Embedding(self.spk_embed_dim, gin_channels)
|
self.emb_g = nn.Embedding(self.spk_embed_dim, gin_channels)
|
||||||
|
self.speaker_map = None
|
||||||
print("gin_channels:", gin_channels, "self.spk_embed_dim:", self.spk_embed_dim)
|
print("gin_channels:", gin_channels, "self.spk_embed_dim:", self.spk_embed_dim)
|
||||||
|
|
||||||
def remove_weight_norm(self):
|
def remove_weight_norm(self):
|
||||||
@@ -612,10 +626,24 @@ class SynthesizerTrnMs256NSFsidO(nn.Module):
|
|||||||
self.flow.remove_weight_norm()
|
self.flow.remove_weight_norm()
|
||||||
self.enc_q.remove_weight_norm()
|
self.enc_q.remove_weight_norm()
|
||||||
|
|
||||||
def forward(self, phone, phone_lengths, pitch, nsff0, sid, max_len=None):
|
def construct_spkmixmap(self, n_speaker):
|
||||||
g = self.emb_g(sid).unsqueeze(-1)
|
self.speaker_map = torch.zeros((n_speaker, 1, 1, self.gin_channels))
|
||||||
|
for i in range(n_speaker):
|
||||||
|
self.speaker_map[i] = self.emb_g(torch.LongTensor([[i]]))
|
||||||
|
self.speaker_map = self.speaker_map.unsqueeze(0)
|
||||||
|
|
||||||
|
def forward(self, phone, phone_lengths, pitch, nsff0, g, rnd, max_len=None):
|
||||||
|
if self.speaker_map is not None: # [N, S] * [S, B, 1, H]
|
||||||
|
g = g.reshape((g.shape[0], g.shape[1], 1, 1, 1)) # [N, S, B, 1, 1]
|
||||||
|
g = g * self.speaker_map # [N, S, B, 1, H]
|
||||||
|
g = torch.sum(g, dim=1) # [N, 1, B, 1, H]
|
||||||
|
g = g.transpose(0, -1).transpose(0, -2).squeeze(0) # [B, H, N]
|
||||||
|
else:
|
||||||
|
g = g.unsqueeze(0)
|
||||||
|
g = self.emb_g(g).transpose(1, 2)
|
||||||
|
|
||||||
m_p, logs_p, x_mask = self.enc_p(phone, pitch, phone_lengths)
|
m_p, logs_p, x_mask = self.enc_p(phone, pitch, phone_lengths)
|
||||||
z_p = (m_p + torch.exp(logs_p) * torch.randn_like(m_p) * 0.66666) * x_mask
|
z_p = (m_p + torch.exp(logs_p) * rnd) * x_mask
|
||||||
z = self.flow(z_p, x_mask, g=g, reverse=True)
|
z = self.flow(z_p, x_mask, g=g, reverse=True)
|
||||||
o = self.dec((z * x_mask)[:, :, :max_len], nsff0, g=g)
|
o = self.dec((z * x_mask)[:, :, :max_len], nsff0, g=g)
|
||||||
return o
|
return o
|
||||||
@@ -651,6 +679,36 @@ class MultiPeriodDiscriminator(torch.nn.Module):
|
|||||||
return y_d_rs, y_d_gs, fmap_rs, fmap_gs
|
return y_d_rs, y_d_gs, fmap_rs, fmap_gs
|
||||||
|
|
||||||
|
|
||||||
|
class MultiPeriodDiscriminatorV2(torch.nn.Module):
|
||||||
|
def __init__(self, use_spectral_norm=False):
|
||||||
|
super(MultiPeriodDiscriminatorV2, self).__init__()
|
||||||
|
# periods = [2, 3, 5, 7, 11, 17]
|
||||||
|
periods = [2, 3, 5, 7, 11, 17, 23, 37]
|
||||||
|
|
||||||
|
discs = [DiscriminatorS(use_spectral_norm=use_spectral_norm)]
|
||||||
|
discs = discs + [
|
||||||
|
DiscriminatorP(i, use_spectral_norm=use_spectral_norm) for i in periods
|
||||||
|
]
|
||||||
|
self.discriminators = nn.ModuleList(discs)
|
||||||
|
|
||||||
|
def forward(self, y, y_hat):
|
||||||
|
y_d_rs = [] #
|
||||||
|
y_d_gs = []
|
||||||
|
fmap_rs = []
|
||||||
|
fmap_gs = []
|
||||||
|
for i, d in enumerate(self.discriminators):
|
||||||
|
y_d_r, fmap_r = d(y)
|
||||||
|
y_d_g, fmap_g = d(y_hat)
|
||||||
|
# for j in range(len(fmap_r)):
|
||||||
|
# print(i,j,y.shape,y_hat.shape,fmap_r[j].shape,fmap_g[j].shape)
|
||||||
|
y_d_rs.append(y_d_r)
|
||||||
|
y_d_gs.append(y_d_g)
|
||||||
|
fmap_rs.append(fmap_r)
|
||||||
|
fmap_gs.append(fmap_g)
|
||||||
|
|
||||||
|
return y_d_rs, y_d_gs, fmap_rs, fmap_gs
|
||||||
|
|
||||||
|
|
||||||
class DiscriminatorS(torch.nn.Module):
|
class DiscriminatorS(torch.nn.Module):
|
||||||
def __init__(self, use_spectral_norm=False):
|
def __init__(self, use_spectral_norm=False):
|
||||||
super(DiscriminatorS, self).__init__()
|
super(DiscriminatorS, self).__init__()
|
||||||
|
|||||||
@@ -1,849 +0,0 @@
|
|||||||
import math, pdb, os
|
|
||||||
from time import time as ttime
|
|
||||||
import torch
|
|
||||||
from torch import nn
|
|
||||||
from torch.nn import functional as F
|
|
||||||
from infer_pack import modules
|
|
||||||
from infer_pack import attentions
|
|
||||||
from infer_pack import commons
|
|
||||||
from infer_pack.commons import init_weights, get_padding
|
|
||||||
from torch.nn import Conv1d, ConvTranspose1d, AvgPool1d, Conv2d
|
|
||||||
from torch.nn.utils import weight_norm, remove_weight_norm, spectral_norm
|
|
||||||
from infer_pack.commons import init_weights
|
|
||||||
import numpy as np
|
|
||||||
from infer_pack import commons
|
|
||||||
|
|
||||||
|
|
||||||
class TextEncoder256(nn.Module):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
out_channels,
|
|
||||||
hidden_channels,
|
|
||||||
filter_channels,
|
|
||||||
n_heads,
|
|
||||||
n_layers,
|
|
||||||
kernel_size,
|
|
||||||
p_dropout,
|
|
||||||
f0=True,
|
|
||||||
):
|
|
||||||
super().__init__()
|
|
||||||
self.out_channels = out_channels
|
|
||||||
self.hidden_channels = hidden_channels
|
|
||||||
self.filter_channels = filter_channels
|
|
||||||
self.n_heads = n_heads
|
|
||||||
self.n_layers = n_layers
|
|
||||||
self.kernel_size = kernel_size
|
|
||||||
self.p_dropout = p_dropout
|
|
||||||
self.emb_phone = nn.Linear(256, hidden_channels)
|
|
||||||
self.lrelu = nn.LeakyReLU(0.1, inplace=True)
|
|
||||||
if f0 == True:
|
|
||||||
self.emb_pitch = nn.Embedding(256, hidden_channels) # pitch 256
|
|
||||||
self.encoder = attentions.Encoder(
|
|
||||||
hidden_channels, filter_channels, n_heads, n_layers, kernel_size, p_dropout
|
|
||||||
)
|
|
||||||
self.proj = nn.Conv1d(hidden_channels, out_channels * 2, 1)
|
|
||||||
|
|
||||||
def forward(self, phone, pitch, lengths):
|
|
||||||
if pitch == None:
|
|
||||||
x = self.emb_phone(phone)
|
|
||||||
else:
|
|
||||||
x = self.emb_phone(phone) + self.emb_pitch(pitch)
|
|
||||||
x = x * math.sqrt(self.hidden_channels) # [b, t, h]
|
|
||||||
x = self.lrelu(x)
|
|
||||||
x = torch.transpose(x, 1, -1) # [b, h, t]
|
|
||||||
x_mask = torch.unsqueeze(commons.sequence_mask(lengths, x.size(2)), 1).to(
|
|
||||||
x.dtype
|
|
||||||
)
|
|
||||||
x = self.encoder(x * x_mask, x_mask)
|
|
||||||
stats = self.proj(x) * x_mask
|
|
||||||
|
|
||||||
m, logs = torch.split(stats, self.out_channels, dim=1)
|
|
||||||
return m, logs, x_mask
|
|
||||||
|
|
||||||
|
|
||||||
class TextEncoder256Sim(nn.Module):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
out_channels,
|
|
||||||
hidden_channels,
|
|
||||||
filter_channels,
|
|
||||||
n_heads,
|
|
||||||
n_layers,
|
|
||||||
kernel_size,
|
|
||||||
p_dropout,
|
|
||||||
f0=True,
|
|
||||||
):
|
|
||||||
super().__init__()
|
|
||||||
self.out_channels = out_channels
|
|
||||||
self.hidden_channels = hidden_channels
|
|
||||||
self.filter_channels = filter_channels
|
|
||||||
self.n_heads = n_heads
|
|
||||||
self.n_layers = n_layers
|
|
||||||
self.kernel_size = kernel_size
|
|
||||||
self.p_dropout = p_dropout
|
|
||||||
self.emb_phone = nn.Linear(256, hidden_channels)
|
|
||||||
self.lrelu = nn.LeakyReLU(0.1, inplace=True)
|
|
||||||
if f0 == True:
|
|
||||||
self.emb_pitch = nn.Embedding(256, hidden_channels) # pitch 256
|
|
||||||
self.encoder = attentions.Encoder(
|
|
||||||
hidden_channels, filter_channels, n_heads, n_layers, kernel_size, p_dropout
|
|
||||||
)
|
|
||||||
self.proj = nn.Conv1d(hidden_channels, out_channels, 1)
|
|
||||||
|
|
||||||
def forward(self, phone, pitch, lengths):
|
|
||||||
if pitch == None:
|
|
||||||
x = self.emb_phone(phone)
|
|
||||||
else:
|
|
||||||
x = self.emb_phone(phone) + self.emb_pitch(pitch)
|
|
||||||
x = x * math.sqrt(self.hidden_channels) # [b, t, h]
|
|
||||||
x = self.lrelu(x)
|
|
||||||
x = torch.transpose(x, 1, -1) # [b, h, t]
|
|
||||||
x_mask = torch.unsqueeze(commons.sequence_mask(lengths, x.size(2)), 1).to(
|
|
||||||
x.dtype
|
|
||||||
)
|
|
||||||
x = self.encoder(x * x_mask, x_mask)
|
|
||||||
x = self.proj(x) * x_mask
|
|
||||||
return x, x_mask
|
|
||||||
|
|
||||||
|
|
||||||
class ResidualCouplingBlock(nn.Module):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
channels,
|
|
||||||
hidden_channels,
|
|
||||||
kernel_size,
|
|
||||||
dilation_rate,
|
|
||||||
n_layers,
|
|
||||||
n_flows=4,
|
|
||||||
gin_channels=0,
|
|
||||||
):
|
|
||||||
super().__init__()
|
|
||||||
self.channels = channels
|
|
||||||
self.hidden_channels = hidden_channels
|
|
||||||
self.kernel_size = kernel_size
|
|
||||||
self.dilation_rate = dilation_rate
|
|
||||||
self.n_layers = n_layers
|
|
||||||
self.n_flows = n_flows
|
|
||||||
self.gin_channels = gin_channels
|
|
||||||
|
|
||||||
self.flows = nn.ModuleList()
|
|
||||||
for i in range(n_flows):
|
|
||||||
self.flows.append(
|
|
||||||
modules.ResidualCouplingLayer(
|
|
||||||
channels,
|
|
||||||
hidden_channels,
|
|
||||||
kernel_size,
|
|
||||||
dilation_rate,
|
|
||||||
n_layers,
|
|
||||||
gin_channels=gin_channels,
|
|
||||||
mean_only=True,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.flows.append(modules.Flip())
|
|
||||||
|
|
||||||
def forward(self, x, x_mask, g=None, reverse=False):
|
|
||||||
if not reverse:
|
|
||||||
for flow in self.flows:
|
|
||||||
x, _ = flow(x, x_mask, g=g, reverse=reverse)
|
|
||||||
else:
|
|
||||||
for flow in reversed(self.flows):
|
|
||||||
x = flow(x, x_mask, g=g, reverse=reverse)
|
|
||||||
return x
|
|
||||||
|
|
||||||
def remove_weight_norm(self):
|
|
||||||
for i in range(self.n_flows):
|
|
||||||
self.flows[i * 2].remove_weight_norm()
|
|
||||||
|
|
||||||
|
|
||||||
class PosteriorEncoder(nn.Module):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
in_channels,
|
|
||||||
out_channels,
|
|
||||||
hidden_channels,
|
|
||||||
kernel_size,
|
|
||||||
dilation_rate,
|
|
||||||
n_layers,
|
|
||||||
gin_channels=0,
|
|
||||||
):
|
|
||||||
super().__init__()
|
|
||||||
self.in_channels = in_channels
|
|
||||||
self.out_channels = out_channels
|
|
||||||
self.hidden_channels = hidden_channels
|
|
||||||
self.kernel_size = kernel_size
|
|
||||||
self.dilation_rate = dilation_rate
|
|
||||||
self.n_layers = n_layers
|
|
||||||
self.gin_channels = gin_channels
|
|
||||||
|
|
||||||
self.pre = nn.Conv1d(in_channels, hidden_channels, 1)
|
|
||||||
self.enc = modules.WN(
|
|
||||||
hidden_channels,
|
|
||||||
kernel_size,
|
|
||||||
dilation_rate,
|
|
||||||
n_layers,
|
|
||||||
gin_channels=gin_channels,
|
|
||||||
)
|
|
||||||
self.proj = nn.Conv1d(hidden_channels, out_channels * 2, 1)
|
|
||||||
|
|
||||||
def forward(self, x, x_lengths, g=None):
|
|
||||||
x_mask = torch.unsqueeze(commons.sequence_mask(x_lengths, x.size(2)), 1).to(
|
|
||||||
x.dtype
|
|
||||||
)
|
|
||||||
x = self.pre(x) * x_mask
|
|
||||||
x = self.enc(x, x_mask, g=g)
|
|
||||||
stats = self.proj(x) * x_mask
|
|
||||||
m, logs = torch.split(stats, self.out_channels, dim=1)
|
|
||||||
z = (m + torch.randn_like(m) * torch.exp(logs)) * x_mask
|
|
||||||
return z, m, logs, x_mask
|
|
||||||
|
|
||||||
def remove_weight_norm(self):
|
|
||||||
self.enc.remove_weight_norm()
|
|
||||||
|
|
||||||
|
|
||||||
class Generator(torch.nn.Module):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
initial_channel,
|
|
||||||
resblock,
|
|
||||||
resblock_kernel_sizes,
|
|
||||||
resblock_dilation_sizes,
|
|
||||||
upsample_rates,
|
|
||||||
upsample_initial_channel,
|
|
||||||
upsample_kernel_sizes,
|
|
||||||
gin_channels=0,
|
|
||||||
):
|
|
||||||
super(Generator, self).__init__()
|
|
||||||
self.num_kernels = len(resblock_kernel_sizes)
|
|
||||||
self.num_upsamples = len(upsample_rates)
|
|
||||||
self.conv_pre = Conv1d(
|
|
||||||
initial_channel, upsample_initial_channel, 7, 1, padding=3
|
|
||||||
)
|
|
||||||
resblock = modules.ResBlock1 if resblock == "1" else modules.ResBlock2
|
|
||||||
|
|
||||||
self.ups = nn.ModuleList()
|
|
||||||
for i, (u, k) in enumerate(zip(upsample_rates, upsample_kernel_sizes)):
|
|
||||||
self.ups.append(
|
|
||||||
weight_norm(
|
|
||||||
ConvTranspose1d(
|
|
||||||
upsample_initial_channel // (2**i),
|
|
||||||
upsample_initial_channel // (2 ** (i + 1)),
|
|
||||||
k,
|
|
||||||
u,
|
|
||||||
padding=(k - u) // 2,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
self.resblocks = nn.ModuleList()
|
|
||||||
for i in range(len(self.ups)):
|
|
||||||
ch = upsample_initial_channel // (2 ** (i + 1))
|
|
||||||
for j, (k, d) in enumerate(
|
|
||||||
zip(resblock_kernel_sizes, resblock_dilation_sizes)
|
|
||||||
):
|
|
||||||
self.resblocks.append(resblock(ch, k, d))
|
|
||||||
|
|
||||||
self.conv_post = Conv1d(ch, 1, 7, 1, padding=3, bias=False)
|
|
||||||
self.ups.apply(init_weights)
|
|
||||||
|
|
||||||
if gin_channels != 0:
|
|
||||||
self.cond = nn.Conv1d(gin_channels, upsample_initial_channel, 1)
|
|
||||||
|
|
||||||
def forward(self, x, g=None):
|
|
||||||
x = self.conv_pre(x)
|
|
||||||
if g is not None:
|
|
||||||
x = x + self.cond(g)
|
|
||||||
|
|
||||||
for i in range(self.num_upsamples):
|
|
||||||
x = F.leaky_relu(x, modules.LRELU_SLOPE)
|
|
||||||
x = self.ups[i](x)
|
|
||||||
xs = None
|
|
||||||
for j in range(self.num_kernels):
|
|
||||||
if xs is None:
|
|
||||||
xs = self.resblocks[i * self.num_kernels + j](x)
|
|
||||||
else:
|
|
||||||
xs += self.resblocks[i * self.num_kernels + j](x)
|
|
||||||
x = xs / self.num_kernels
|
|
||||||
x = F.leaky_relu(x)
|
|
||||||
x = self.conv_post(x)
|
|
||||||
x = torch.tanh(x)
|
|
||||||
|
|
||||||
return x
|
|
||||||
|
|
||||||
def remove_weight_norm(self):
|
|
||||||
for l in self.ups:
|
|
||||||
remove_weight_norm(l)
|
|
||||||
for l in self.resblocks:
|
|
||||||
l.remove_weight_norm()
|
|
||||||
|
|
||||||
|
|
||||||
class SineGen(torch.nn.Module):
|
|
||||||
"""Definition of sine generator
|
|
||||||
SineGen(samp_rate, harmonic_num = 0,
|
|
||||||
sine_amp = 0.1, noise_std = 0.003,
|
|
||||||
voiced_threshold = 0,
|
|
||||||
flag_for_pulse=False)
|
|
||||||
samp_rate: sampling rate in Hz
|
|
||||||
harmonic_num: number of harmonic overtones (default 0)
|
|
||||||
sine_amp: amplitude of sine-wavefrom (default 0.1)
|
|
||||||
noise_std: std of Gaussian noise (default 0.003)
|
|
||||||
voiced_thoreshold: F0 threshold for U/V classification (default 0)
|
|
||||||
flag_for_pulse: this SinGen is used inside PulseGen (default False)
|
|
||||||
Note: when flag_for_pulse is True, the first time step of a voiced
|
|
||||||
segment is always sin(np.pi) or cos(0)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
samp_rate,
|
|
||||||
harmonic_num=0,
|
|
||||||
sine_amp=0.1,
|
|
||||||
noise_std=0.003,
|
|
||||||
voiced_threshold=0,
|
|
||||||
flag_for_pulse=False,
|
|
||||||
):
|
|
||||||
super(SineGen, self).__init__()
|
|
||||||
self.sine_amp = sine_amp
|
|
||||||
self.noise_std = noise_std
|
|
||||||
self.harmonic_num = harmonic_num
|
|
||||||
self.dim = self.harmonic_num + 1
|
|
||||||
self.sampling_rate = samp_rate
|
|
||||||
self.voiced_threshold = voiced_threshold
|
|
||||||
|
|
||||||
def _f02uv(self, f0):
|
|
||||||
# generate uv signal
|
|
||||||
uv = torch.ones_like(f0)
|
|
||||||
uv = uv * (f0 > self.voiced_threshold)
|
|
||||||
return uv
|
|
||||||
|
|
||||||
def forward(self, f0, upp):
|
|
||||||
"""sine_tensor, uv = forward(f0)
|
|
||||||
input F0: tensor(batchsize=1, length, dim=1)
|
|
||||||
f0 for unvoiced steps should be 0
|
|
||||||
output sine_tensor: tensor(batchsize=1, length, dim)
|
|
||||||
output uv: tensor(batchsize=1, length, 1)
|
|
||||||
"""
|
|
||||||
with torch.no_grad():
|
|
||||||
f0 = f0[:, None].transpose(1, 2)
|
|
||||||
f0_buf = torch.zeros(f0.shape[0], f0.shape[1], self.dim, device=f0.device)
|
|
||||||
# fundamental component
|
|
||||||
f0_buf[:, :, 0] = f0[:, :, 0]
|
|
||||||
for idx in np.arange(self.harmonic_num):
|
|
||||||
f0_buf[:, :, idx + 1] = f0_buf[:, :, 0] * (
|
|
||||||
idx + 2
|
|
||||||
) # idx + 2: the (idx+1)-th overtone, (idx+2)-th harmonic
|
|
||||||
rad_values = (f0_buf / self.sampling_rate) % 1 ###%1意味着n_har的乘积无法后处理优化
|
|
||||||
rand_ini = torch.rand(
|
|
||||||
f0_buf.shape[0], f0_buf.shape[2], device=f0_buf.device
|
|
||||||
)
|
|
||||||
rand_ini[:, 0] = 0
|
|
||||||
rad_values[:, 0, :] = rad_values[:, 0, :] + rand_ini
|
|
||||||
tmp_over_one = torch.cumsum(rad_values, 1) # % 1 #####%1意味着后面的cumsum无法再优化
|
|
||||||
tmp_over_one *= upp
|
|
||||||
tmp_over_one = F.interpolate(
|
|
||||||
tmp_over_one.transpose(2, 1),
|
|
||||||
scale_factor=upp,
|
|
||||||
mode="linear",
|
|
||||||
align_corners=True,
|
|
||||||
).transpose(2, 1)
|
|
||||||
rad_values = F.interpolate(
|
|
||||||
rad_values.transpose(2, 1), scale_factor=upp, mode="nearest"
|
|
||||||
).transpose(
|
|
||||||
2, 1
|
|
||||||
) #######
|
|
||||||
tmp_over_one %= 1
|
|
||||||
tmp_over_one_idx = (tmp_over_one[:, 1:, :] - tmp_over_one[:, :-1, :]) < 0
|
|
||||||
cumsum_shift = torch.zeros_like(rad_values)
|
|
||||||
cumsum_shift[:, 1:, :] = tmp_over_one_idx * -1.0
|
|
||||||
sine_waves = torch.sin(
|
|
||||||
torch.cumsum(rad_values + cumsum_shift, dim=1) * 2 * np.pi
|
|
||||||
)
|
|
||||||
sine_waves = sine_waves * self.sine_amp
|
|
||||||
uv = self._f02uv(f0)
|
|
||||||
uv = F.interpolate(
|
|
||||||
uv.transpose(2, 1), scale_factor=upp, mode="nearest"
|
|
||||||
).transpose(2, 1)
|
|
||||||
noise_amp = uv * self.noise_std + (1 - uv) * self.sine_amp / 3
|
|
||||||
noise = noise_amp * torch.randn_like(sine_waves)
|
|
||||||
sine_waves = sine_waves * uv + noise
|
|
||||||
return sine_waves, uv, noise
|
|
||||||
|
|
||||||
|
|
||||||
class SourceModuleHnNSF(torch.nn.Module):
|
|
||||||
"""SourceModule for hn-nsf
|
|
||||||
SourceModule(sampling_rate, harmonic_num=0, sine_amp=0.1,
|
|
||||||
add_noise_std=0.003, voiced_threshod=0)
|
|
||||||
sampling_rate: sampling_rate in Hz
|
|
||||||
harmonic_num: number of harmonic above F0 (default: 0)
|
|
||||||
sine_amp: amplitude of sine source signal (default: 0.1)
|
|
||||||
add_noise_std: std of additive Gaussian noise (default: 0.003)
|
|
||||||
note that amplitude of noise in unvoiced is decided
|
|
||||||
by sine_amp
|
|
||||||
voiced_threshold: threhold to set U/V given F0 (default: 0)
|
|
||||||
Sine_source, noise_source = SourceModuleHnNSF(F0_sampled)
|
|
||||||
F0_sampled (batchsize, length, 1)
|
|
||||||
Sine_source (batchsize, length, 1)
|
|
||||||
noise_source (batchsize, length 1)
|
|
||||||
uv (batchsize, length, 1)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
sampling_rate,
|
|
||||||
harmonic_num=0,
|
|
||||||
sine_amp=0.1,
|
|
||||||
add_noise_std=0.003,
|
|
||||||
voiced_threshod=0,
|
|
||||||
is_half=True,
|
|
||||||
):
|
|
||||||
super(SourceModuleHnNSF, self).__init__()
|
|
||||||
|
|
||||||
self.sine_amp = sine_amp
|
|
||||||
self.noise_std = add_noise_std
|
|
||||||
self.is_half = is_half
|
|
||||||
# to produce sine waveforms
|
|
||||||
self.l_sin_gen = SineGen(
|
|
||||||
sampling_rate, harmonic_num, sine_amp, add_noise_std, voiced_threshod
|
|
||||||
)
|
|
||||||
|
|
||||||
# to merge source harmonics into a single excitation
|
|
||||||
self.l_linear = torch.nn.Linear(harmonic_num + 1, 1)
|
|
||||||
self.l_tanh = torch.nn.Tanh()
|
|
||||||
|
|
||||||
def forward(self, x, upp=None):
|
|
||||||
sine_wavs, uv, _ = self.l_sin_gen(x, upp)
|
|
||||||
if self.is_half:
|
|
||||||
sine_wavs = sine_wavs.half()
|
|
||||||
sine_merge = self.l_tanh(self.l_linear(sine_wavs))
|
|
||||||
return sine_merge, None, None # noise, uv
|
|
||||||
|
|
||||||
|
|
||||||
class GeneratorNSF(torch.nn.Module):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
initial_channel,
|
|
||||||
resblock,
|
|
||||||
resblock_kernel_sizes,
|
|
||||||
resblock_dilation_sizes,
|
|
||||||
upsample_rates,
|
|
||||||
upsample_initial_channel,
|
|
||||||
upsample_kernel_sizes,
|
|
||||||
gin_channels,
|
|
||||||
sr,
|
|
||||||
is_half=False,
|
|
||||||
):
|
|
||||||
super(GeneratorNSF, self).__init__()
|
|
||||||
self.num_kernels = len(resblock_kernel_sizes)
|
|
||||||
self.num_upsamples = len(upsample_rates)
|
|
||||||
|
|
||||||
self.f0_upsamp = torch.nn.Upsample(scale_factor=np.prod(upsample_rates))
|
|
||||||
self.m_source = SourceModuleHnNSF(
|
|
||||||
sampling_rate=sr, harmonic_num=0, is_half=is_half
|
|
||||||
)
|
|
||||||
self.noise_convs = nn.ModuleList()
|
|
||||||
self.conv_pre = Conv1d(
|
|
||||||
initial_channel, upsample_initial_channel, 7, 1, padding=3
|
|
||||||
)
|
|
||||||
resblock = modules.ResBlock1 if resblock == "1" else modules.ResBlock2
|
|
||||||
|
|
||||||
self.ups = nn.ModuleList()
|
|
||||||
for i, (u, k) in enumerate(zip(upsample_rates, upsample_kernel_sizes)):
|
|
||||||
c_cur = upsample_initial_channel // (2 ** (i + 1))
|
|
||||||
self.ups.append(
|
|
||||||
weight_norm(
|
|
||||||
ConvTranspose1d(
|
|
||||||
upsample_initial_channel // (2**i),
|
|
||||||
upsample_initial_channel // (2 ** (i + 1)),
|
|
||||||
k,
|
|
||||||
u,
|
|
||||||
padding=(k - u) // 2,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if i + 1 < len(upsample_rates):
|
|
||||||
stride_f0 = np.prod(upsample_rates[i + 1 :])
|
|
||||||
self.noise_convs.append(
|
|
||||||
Conv1d(
|
|
||||||
1,
|
|
||||||
c_cur,
|
|
||||||
kernel_size=stride_f0 * 2,
|
|
||||||
stride=stride_f0,
|
|
||||||
padding=stride_f0 // 2,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
self.noise_convs.append(Conv1d(1, c_cur, kernel_size=1))
|
|
||||||
|
|
||||||
self.resblocks = nn.ModuleList()
|
|
||||||
for i in range(len(self.ups)):
|
|
||||||
ch = upsample_initial_channel // (2 ** (i + 1))
|
|
||||||
for j, (k, d) in enumerate(
|
|
||||||
zip(resblock_kernel_sizes, resblock_dilation_sizes)
|
|
||||||
):
|
|
||||||
self.resblocks.append(resblock(ch, k, d))
|
|
||||||
|
|
||||||
self.conv_post = Conv1d(ch, 1, 7, 1, padding=3, bias=False)
|
|
||||||
self.ups.apply(init_weights)
|
|
||||||
|
|
||||||
if gin_channels != 0:
|
|
||||||
self.cond = nn.Conv1d(gin_channels, upsample_initial_channel, 1)
|
|
||||||
|
|
||||||
self.upp = np.prod(upsample_rates)
|
|
||||||
|
|
||||||
def forward(self, x, f0, g=None):
|
|
||||||
har_source, noi_source, uv = self.m_source(f0, self.upp)
|
|
||||||
har_source = har_source.transpose(1, 2)
|
|
||||||
x = self.conv_pre(x)
|
|
||||||
if g is not None:
|
|
||||||
x = x + self.cond(g)
|
|
||||||
|
|
||||||
for i in range(self.num_upsamples):
|
|
||||||
x = F.leaky_relu(x, modules.LRELU_SLOPE)
|
|
||||||
x = self.ups[i](x)
|
|
||||||
x_source = self.noise_convs[i](har_source)
|
|
||||||
x = x + x_source
|
|
||||||
xs = None
|
|
||||||
for j in range(self.num_kernels):
|
|
||||||
if xs is None:
|
|
||||||
xs = self.resblocks[i * self.num_kernels + j](x)
|
|
||||||
else:
|
|
||||||
xs += self.resblocks[i * self.num_kernels + j](x)
|
|
||||||
x = xs / self.num_kernels
|
|
||||||
x = F.leaky_relu(x)
|
|
||||||
x = self.conv_post(x)
|
|
||||||
x = torch.tanh(x)
|
|
||||||
return x
|
|
||||||
|
|
||||||
def remove_weight_norm(self):
|
|
||||||
for l in self.ups:
|
|
||||||
remove_weight_norm(l)
|
|
||||||
for l in self.resblocks:
|
|
||||||
l.remove_weight_norm()
|
|
||||||
|
|
||||||
|
|
||||||
sr2sr = {
|
|
||||||
"32k": 32000,
|
|
||||||
"40k": 40000,
|
|
||||||
"48k": 48000,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class SynthesizerTrnMs256NSFsidM(nn.Module):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
spec_channels,
|
|
||||||
segment_size,
|
|
||||||
inter_channels,
|
|
||||||
hidden_channels,
|
|
||||||
filter_channels,
|
|
||||||
n_heads,
|
|
||||||
n_layers,
|
|
||||||
kernel_size,
|
|
||||||
p_dropout,
|
|
||||||
resblock,
|
|
||||||
resblock_kernel_sizes,
|
|
||||||
resblock_dilation_sizes,
|
|
||||||
upsample_rates,
|
|
||||||
upsample_initial_channel,
|
|
||||||
upsample_kernel_sizes,
|
|
||||||
spk_embed_dim,
|
|
||||||
gin_channels,
|
|
||||||
sr,
|
|
||||||
**kwargs
|
|
||||||
):
|
|
||||||
super().__init__()
|
|
||||||
if type(sr) == type("strr"):
|
|
||||||
sr = sr2sr[sr]
|
|
||||||
self.spec_channels = spec_channels
|
|
||||||
self.inter_channels = inter_channels
|
|
||||||
self.hidden_channels = hidden_channels
|
|
||||||
self.filter_channels = filter_channels
|
|
||||||
self.n_heads = n_heads
|
|
||||||
self.n_layers = n_layers
|
|
||||||
self.kernel_size = kernel_size
|
|
||||||
self.p_dropout = p_dropout
|
|
||||||
self.resblock = resblock
|
|
||||||
self.resblock_kernel_sizes = resblock_kernel_sizes
|
|
||||||
self.resblock_dilation_sizes = resblock_dilation_sizes
|
|
||||||
self.upsample_rates = upsample_rates
|
|
||||||
self.upsample_initial_channel = upsample_initial_channel
|
|
||||||
self.upsample_kernel_sizes = upsample_kernel_sizes
|
|
||||||
self.segment_size = segment_size
|
|
||||||
self.gin_channels = gin_channels
|
|
||||||
# self.hop_length = hop_length#
|
|
||||||
self.spk_embed_dim = spk_embed_dim
|
|
||||||
self.enc_p = TextEncoder256(
|
|
||||||
inter_channels,
|
|
||||||
hidden_channels,
|
|
||||||
filter_channels,
|
|
||||||
n_heads,
|
|
||||||
n_layers,
|
|
||||||
kernel_size,
|
|
||||||
p_dropout,
|
|
||||||
)
|
|
||||||
self.dec = GeneratorNSF(
|
|
||||||
inter_channels,
|
|
||||||
resblock,
|
|
||||||
resblock_kernel_sizes,
|
|
||||||
resblock_dilation_sizes,
|
|
||||||
upsample_rates,
|
|
||||||
upsample_initial_channel,
|
|
||||||
upsample_kernel_sizes,
|
|
||||||
gin_channels=gin_channels,
|
|
||||||
sr=sr,
|
|
||||||
is_half=kwargs["is_half"],
|
|
||||||
)
|
|
||||||
self.enc_q = PosteriorEncoder(
|
|
||||||
spec_channels,
|
|
||||||
inter_channels,
|
|
||||||
hidden_channels,
|
|
||||||
5,
|
|
||||||
1,
|
|
||||||
16,
|
|
||||||
gin_channels=gin_channels,
|
|
||||||
)
|
|
||||||
self.flow = ResidualCouplingBlock(
|
|
||||||
inter_channels, hidden_channels, 5, 1, 3, gin_channels=gin_channels
|
|
||||||
)
|
|
||||||
self.emb_g = nn.Embedding(self.spk_embed_dim, gin_channels)
|
|
||||||
print("gin_channels:", gin_channels, "self.spk_embed_dim:", self.spk_embed_dim)
|
|
||||||
|
|
||||||
def remove_weight_norm(self):
|
|
||||||
self.dec.remove_weight_norm()
|
|
||||||
self.flow.remove_weight_norm()
|
|
||||||
self.enc_q.remove_weight_norm()
|
|
||||||
|
|
||||||
def forward(self, phone, phone_lengths, pitch, nsff0, sid, rnd, max_len=None):
|
|
||||||
g = self.emb_g(sid).unsqueeze(-1)
|
|
||||||
m_p, logs_p, x_mask = self.enc_p(phone, pitch, phone_lengths)
|
|
||||||
z_p = (m_p + torch.exp(logs_p) * rnd) * x_mask
|
|
||||||
z = self.flow(z_p, x_mask, g=g, reverse=True)
|
|
||||||
o = self.dec((z * x_mask)[:, :, :max_len], nsff0, g=g)
|
|
||||||
return o
|
|
||||||
|
|
||||||
|
|
||||||
class SynthesizerTrnMs256NSFsid_sim(nn.Module):
|
|
||||||
"""
|
|
||||||
Synthesizer for Training
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
spec_channels,
|
|
||||||
segment_size,
|
|
||||||
inter_channels,
|
|
||||||
hidden_channels,
|
|
||||||
filter_channels,
|
|
||||||
n_heads,
|
|
||||||
n_layers,
|
|
||||||
kernel_size,
|
|
||||||
p_dropout,
|
|
||||||
resblock,
|
|
||||||
resblock_kernel_sizes,
|
|
||||||
resblock_dilation_sizes,
|
|
||||||
upsample_rates,
|
|
||||||
upsample_initial_channel,
|
|
||||||
upsample_kernel_sizes,
|
|
||||||
spk_embed_dim,
|
|
||||||
# hop_length,
|
|
||||||
gin_channels=0,
|
|
||||||
use_sdp=True,
|
|
||||||
**kwargs
|
|
||||||
):
|
|
||||||
super().__init__()
|
|
||||||
self.spec_channels = spec_channels
|
|
||||||
self.inter_channels = inter_channels
|
|
||||||
self.hidden_channels = hidden_channels
|
|
||||||
self.filter_channels = filter_channels
|
|
||||||
self.n_heads = n_heads
|
|
||||||
self.n_layers = n_layers
|
|
||||||
self.kernel_size = kernel_size
|
|
||||||
self.p_dropout = p_dropout
|
|
||||||
self.resblock = resblock
|
|
||||||
self.resblock_kernel_sizes = resblock_kernel_sizes
|
|
||||||
self.resblock_dilation_sizes = resblock_dilation_sizes
|
|
||||||
self.upsample_rates = upsample_rates
|
|
||||||
self.upsample_initial_channel = upsample_initial_channel
|
|
||||||
self.upsample_kernel_sizes = upsample_kernel_sizes
|
|
||||||
self.segment_size = segment_size
|
|
||||||
self.gin_channels = gin_channels
|
|
||||||
# self.hop_length = hop_length#
|
|
||||||
self.spk_embed_dim = spk_embed_dim
|
|
||||||
self.enc_p = TextEncoder256Sim(
|
|
||||||
inter_channels,
|
|
||||||
hidden_channels,
|
|
||||||
filter_channels,
|
|
||||||
n_heads,
|
|
||||||
n_layers,
|
|
||||||
kernel_size,
|
|
||||||
p_dropout,
|
|
||||||
)
|
|
||||||
self.dec = GeneratorNSF(
|
|
||||||
inter_channels,
|
|
||||||
resblock,
|
|
||||||
resblock_kernel_sizes,
|
|
||||||
resblock_dilation_sizes,
|
|
||||||
upsample_rates,
|
|
||||||
upsample_initial_channel,
|
|
||||||
upsample_kernel_sizes,
|
|
||||||
gin_channels=gin_channels,
|
|
||||||
is_half=kwargs["is_half"],
|
|
||||||
)
|
|
||||||
|
|
||||||
self.flow = ResidualCouplingBlock(
|
|
||||||
inter_channels, hidden_channels, 5, 1, 3, gin_channels=gin_channels
|
|
||||||
)
|
|
||||||
self.emb_g = nn.Embedding(self.spk_embed_dim, gin_channels)
|
|
||||||
print("gin_channels:", gin_channels, "self.spk_embed_dim:", self.spk_embed_dim)
|
|
||||||
|
|
||||||
def remove_weight_norm(self):
|
|
||||||
self.dec.remove_weight_norm()
|
|
||||||
self.flow.remove_weight_norm()
|
|
||||||
self.enc_q.remove_weight_norm()
|
|
||||||
|
|
||||||
def forward(
|
|
||||||
self, phone, phone_lengths, pitch, pitchf, ds, max_len=None
|
|
||||||
): # y是spec不需要了现在
|
|
||||||
g = self.emb_g(ds.unsqueeze(0)).unsqueeze(-1) # [b, 256, 1]##1是t,广播的
|
|
||||||
x, x_mask = self.enc_p(phone, pitch, phone_lengths)
|
|
||||||
x = self.flow(x, x_mask, g=g, reverse=True)
|
|
||||||
o = self.dec((x * x_mask)[:, :, :max_len], pitchf, g=g)
|
|
||||||
return o
|
|
||||||
|
|
||||||
|
|
||||||
class MultiPeriodDiscriminator(torch.nn.Module):
|
|
||||||
def __init__(self, use_spectral_norm=False):
|
|
||||||
super(MultiPeriodDiscriminator, self).__init__()
|
|
||||||
periods = [2, 3, 5, 7, 11, 17]
|
|
||||||
# periods = [3, 5, 7, 11, 17, 23, 37]
|
|
||||||
|
|
||||||
discs = [DiscriminatorS(use_spectral_norm=use_spectral_norm)]
|
|
||||||
discs = discs + [
|
|
||||||
DiscriminatorP(i, use_spectral_norm=use_spectral_norm) for i in periods
|
|
||||||
]
|
|
||||||
self.discriminators = nn.ModuleList(discs)
|
|
||||||
|
|
||||||
def forward(self, y, y_hat):
|
|
||||||
y_d_rs = [] #
|
|
||||||
y_d_gs = []
|
|
||||||
fmap_rs = []
|
|
||||||
fmap_gs = []
|
|
||||||
for i, d in enumerate(self.discriminators):
|
|
||||||
y_d_r, fmap_r = d(y)
|
|
||||||
y_d_g, fmap_g = d(y_hat)
|
|
||||||
# for j in range(len(fmap_r)):
|
|
||||||
# print(i,j,y.shape,y_hat.shape,fmap_r[j].shape,fmap_g[j].shape)
|
|
||||||
y_d_rs.append(y_d_r)
|
|
||||||
y_d_gs.append(y_d_g)
|
|
||||||
fmap_rs.append(fmap_r)
|
|
||||||
fmap_gs.append(fmap_g)
|
|
||||||
|
|
||||||
return y_d_rs, y_d_gs, fmap_rs, fmap_gs
|
|
||||||
|
|
||||||
|
|
||||||
class DiscriminatorS(torch.nn.Module):
|
|
||||||
def __init__(self, use_spectral_norm=False):
|
|
||||||
super(DiscriminatorS, self).__init__()
|
|
||||||
norm_f = weight_norm if use_spectral_norm == False else spectral_norm
|
|
||||||
self.convs = nn.ModuleList(
|
|
||||||
[
|
|
||||||
norm_f(Conv1d(1, 16, 15, 1, padding=7)),
|
|
||||||
norm_f(Conv1d(16, 64, 41, 4, groups=4, padding=20)),
|
|
||||||
norm_f(Conv1d(64, 256, 41, 4, groups=16, padding=20)),
|
|
||||||
norm_f(Conv1d(256, 1024, 41, 4, groups=64, padding=20)),
|
|
||||||
norm_f(Conv1d(1024, 1024, 41, 4, groups=256, padding=20)),
|
|
||||||
norm_f(Conv1d(1024, 1024, 5, 1, padding=2)),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
self.conv_post = norm_f(Conv1d(1024, 1, 3, 1, padding=1))
|
|
||||||
|
|
||||||
def forward(self, x):
|
|
||||||
fmap = []
|
|
||||||
|
|
||||||
for l in self.convs:
|
|
||||||
x = l(x)
|
|
||||||
x = F.leaky_relu(x, modules.LRELU_SLOPE)
|
|
||||||
fmap.append(x)
|
|
||||||
x = self.conv_post(x)
|
|
||||||
fmap.append(x)
|
|
||||||
x = torch.flatten(x, 1, -1)
|
|
||||||
|
|
||||||
return x, fmap
|
|
||||||
|
|
||||||
|
|
||||||
class DiscriminatorP(torch.nn.Module):
|
|
||||||
def __init__(self, period, kernel_size=5, stride=3, use_spectral_norm=False):
|
|
||||||
super(DiscriminatorP, self).__init__()
|
|
||||||
self.period = period
|
|
||||||
self.use_spectral_norm = use_spectral_norm
|
|
||||||
norm_f = weight_norm if use_spectral_norm == False else spectral_norm
|
|
||||||
self.convs = nn.ModuleList(
|
|
||||||
[
|
|
||||||
norm_f(
|
|
||||||
Conv2d(
|
|
||||||
1,
|
|
||||||
32,
|
|
||||||
(kernel_size, 1),
|
|
||||||
(stride, 1),
|
|
||||||
padding=(get_padding(kernel_size, 1), 0),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
norm_f(
|
|
||||||
Conv2d(
|
|
||||||
32,
|
|
||||||
128,
|
|
||||||
(kernel_size, 1),
|
|
||||||
(stride, 1),
|
|
||||||
padding=(get_padding(kernel_size, 1), 0),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
norm_f(
|
|
||||||
Conv2d(
|
|
||||||
128,
|
|
||||||
512,
|
|
||||||
(kernel_size, 1),
|
|
||||||
(stride, 1),
|
|
||||||
padding=(get_padding(kernel_size, 1), 0),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
norm_f(
|
|
||||||
Conv2d(
|
|
||||||
512,
|
|
||||||
1024,
|
|
||||||
(kernel_size, 1),
|
|
||||||
(stride, 1),
|
|
||||||
padding=(get_padding(kernel_size, 1), 0),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
norm_f(
|
|
||||||
Conv2d(
|
|
||||||
1024,
|
|
||||||
1024,
|
|
||||||
(kernel_size, 1),
|
|
||||||
1,
|
|
||||||
padding=(get_padding(kernel_size, 1), 0),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
self.conv_post = norm_f(Conv2d(1024, 1, (3, 1), 1, padding=(1, 0)))
|
|
||||||
|
|
||||||
def forward(self, x):
|
|
||||||
fmap = []
|
|
||||||
|
|
||||||
# 1d to 2d
|
|
||||||
b, c, t = x.shape
|
|
||||||
if t % self.period != 0: # pad first
|
|
||||||
n_pad = self.period - (t % self.period)
|
|
||||||
x = F.pad(x, (0, n_pad), "reflect")
|
|
||||||
t = t + n_pad
|
|
||||||
x = x.view(b, c, t // self.period, self.period)
|
|
||||||
|
|
||||||
for l in self.convs:
|
|
||||||
x = l(x)
|
|
||||||
x = F.leaky_relu(x, modules.LRELU_SLOPE)
|
|
||||||
fmap.append(x)
|
|
||||||
x = self.conv_post(x)
|
|
||||||
fmap.append(x)
|
|
||||||
x = torch.flatten(x, 1, -1)
|
|
||||||
|
|
||||||
return x, fmap
|
|
||||||
192
infer_uvr5.py
192
infer_uvr5.py
@@ -1,5 +1,9 @@
|
|||||||
import os, sys, torch, warnings, pdb
|
import os, sys, torch, warnings, pdb
|
||||||
|
|
||||||
|
now_dir = os.getcwd()
|
||||||
|
sys.path.append(now_dir)
|
||||||
|
from json import load as ll
|
||||||
|
|
||||||
warnings.filterwarnings("ignore")
|
warnings.filterwarnings("ignore")
|
||||||
import librosa
|
import librosa
|
||||||
import importlib
|
import importlib
|
||||||
@@ -9,7 +13,9 @@ from tqdm import tqdm
|
|||||||
from uvr5_pack.lib_v5 import spec_utils
|
from uvr5_pack.lib_v5 import spec_utils
|
||||||
from uvr5_pack.utils import _get_name_params, inference
|
from uvr5_pack.utils import _get_name_params, inference
|
||||||
from uvr5_pack.lib_v5.model_param_init import ModelParameters
|
from uvr5_pack.lib_v5.model_param_init import ModelParameters
|
||||||
from scipy.io import wavfile
|
import soundfile as sf
|
||||||
|
from uvr5_pack.lib_v5.nets_new import CascadedNet
|
||||||
|
from uvr5_pack.lib_v5 import nets_61968KB as nets
|
||||||
|
|
||||||
|
|
||||||
class _audio_pre_:
|
class _audio_pre_:
|
||||||
@@ -25,28 +31,7 @@ class _audio_pre_:
|
|||||||
"agg": agg,
|
"agg": agg,
|
||||||
"high_end_process": "mirroring",
|
"high_end_process": "mirroring",
|
||||||
}
|
}
|
||||||
nn_arch_sizes = [
|
mp = ModelParameters("uvr5_pack/lib_v5/modelparams/4band_v2.json")
|
||||||
31191, # default
|
|
||||||
33966,
|
|
||||||
61968,
|
|
||||||
123821,
|
|
||||||
123812,
|
|
||||||
537238, # custom
|
|
||||||
]
|
|
||||||
self.nn_architecture = list("{}KB".format(s) for s in nn_arch_sizes)
|
|
||||||
model_size = math.ceil(os.stat(model_path).st_size / 1024)
|
|
||||||
nn_architecture = "{}KB".format(
|
|
||||||
min(nn_arch_sizes, key=lambda x: abs(x - model_size))
|
|
||||||
)
|
|
||||||
nets = importlib.import_module(
|
|
||||||
"uvr5_pack.lib_v5.nets"
|
|
||||||
+ f"_{nn_architecture}".replace("_{}KB".format(nn_arch_sizes[0]), ""),
|
|
||||||
package=None,
|
|
||||||
)
|
|
||||||
model_hash = hashlib.md5(open(model_path, "rb").read()).hexdigest()
|
|
||||||
param_name, model_params_d = _get_name_params(model_path, model_hash)
|
|
||||||
|
|
||||||
mp = ModelParameters(model_params_d)
|
|
||||||
model = nets.CascadedASPPNet(mp.param["bins"] * 2)
|
model = nets.CascadedASPPNet(mp.param["bins"] * 2)
|
||||||
cpk = torch.load(model_path, map_location="cpu")
|
cpk = torch.load(model_path, map_location="cpu")
|
||||||
model.load_state_dict(cpk)
|
model.load_state_dict(cpk)
|
||||||
@@ -59,7 +44,7 @@ class _audio_pre_:
|
|||||||
self.mp = mp
|
self.mp = mp
|
||||||
self.model = model
|
self.model = model
|
||||||
|
|
||||||
def _path_audio_(self, music_file, ins_root=None, vocal_root=None):
|
def _path_audio_(self, music_file, ins_root=None, vocal_root=None, format="flac"):
|
||||||
if ins_root is None and vocal_root is None:
|
if ins_root is None and vocal_root is None:
|
||||||
return "No save root."
|
return "No save root."
|
||||||
name = os.path.basename(music_file)
|
name = os.path.basename(music_file)
|
||||||
@@ -138,12 +123,13 @@ class _audio_pre_:
|
|||||||
else:
|
else:
|
||||||
wav_instrument = spec_utils.cmb_spectrogram_to_wave(y_spec_m, self.mp)
|
wav_instrument = spec_utils.cmb_spectrogram_to_wave(y_spec_m, self.mp)
|
||||||
print("%s instruments done" % name)
|
print("%s instruments done" % name)
|
||||||
wavfile.write(
|
sf.write(
|
||||||
os.path.join(
|
os.path.join(
|
||||||
ins_root, "instrument_{}_{}.wav".format(name, self.data["agg"])
|
ins_root,
|
||||||
|
"instrument_{}_{}.{}".format(name, self.data["agg"], format),
|
||||||
),
|
),
|
||||||
self.mp.param["sr"],
|
|
||||||
(np.array(wav_instrument) * 32768).astype("int16"),
|
(np.array(wav_instrument) * 32768).astype("int16"),
|
||||||
|
self.mp.param["sr"],
|
||||||
) #
|
) #
|
||||||
if vocal_root is not None:
|
if vocal_root is not None:
|
||||||
if self.data["high_end_process"].startswith("mirroring"):
|
if self.data["high_end_process"].startswith("mirroring"):
|
||||||
@@ -156,20 +142,160 @@ class _audio_pre_:
|
|||||||
else:
|
else:
|
||||||
wav_vocals = spec_utils.cmb_spectrogram_to_wave(v_spec_m, self.mp)
|
wav_vocals = spec_utils.cmb_spectrogram_to_wave(v_spec_m, self.mp)
|
||||||
print("%s vocals done" % name)
|
print("%s vocals done" % name)
|
||||||
wavfile.write(
|
sf.write(
|
||||||
os.path.join(
|
os.path.join(
|
||||||
vocal_root, "vocal_{}_{}.wav".format(name, self.data["agg"])
|
vocal_root, "vocal_{}_{}.{}".format(name, self.data["agg"], format)
|
||||||
),
|
),
|
||||||
self.mp.param["sr"],
|
|
||||||
(np.array(wav_vocals) * 32768).astype("int16"),
|
(np.array(wav_vocals) * 32768).astype("int16"),
|
||||||
|
self.mp.param["sr"],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class _audio_pre_new:
|
||||||
|
def __init__(self, agg, model_path, device, is_half):
|
||||||
|
self.model_path = model_path
|
||||||
|
self.device = device
|
||||||
|
self.data = {
|
||||||
|
# Processing Options
|
||||||
|
"postprocess": False,
|
||||||
|
"tta": False,
|
||||||
|
# Constants
|
||||||
|
"window_size": 512,
|
||||||
|
"agg": agg,
|
||||||
|
"high_end_process": "mirroring",
|
||||||
|
}
|
||||||
|
mp = ModelParameters("uvr5_pack/lib_v5/modelparams/4band_v3.json")
|
||||||
|
nout = 64 if "DeReverb" in model_path else 48
|
||||||
|
model = CascadedNet(mp.param["bins"] * 2, nout)
|
||||||
|
cpk = torch.load(model_path, map_location="cpu")
|
||||||
|
model.load_state_dict(cpk)
|
||||||
|
model.eval()
|
||||||
|
if is_half:
|
||||||
|
model = model.half().to(device)
|
||||||
|
else:
|
||||||
|
model = model.to(device)
|
||||||
|
|
||||||
|
self.mp = mp
|
||||||
|
self.model = model
|
||||||
|
|
||||||
|
def _path_audio_(
|
||||||
|
self, music_file, vocal_root=None, ins_root=None, format="flac"
|
||||||
|
): # 3个VR模型vocal和ins是反的
|
||||||
|
if ins_root is None and vocal_root is None:
|
||||||
|
return "No save root."
|
||||||
|
name = os.path.basename(music_file)
|
||||||
|
if ins_root is not None:
|
||||||
|
os.makedirs(ins_root, exist_ok=True)
|
||||||
|
if vocal_root is not None:
|
||||||
|
os.makedirs(vocal_root, exist_ok=True)
|
||||||
|
X_wave, y_wave, X_spec_s, y_spec_s = {}, {}, {}, {}
|
||||||
|
bands_n = len(self.mp.param["band"])
|
||||||
|
# print(bands_n)
|
||||||
|
for d in range(bands_n, 0, -1):
|
||||||
|
bp = self.mp.param["band"][d]
|
||||||
|
if d == bands_n: # high-end band
|
||||||
|
(
|
||||||
|
X_wave[d],
|
||||||
|
_,
|
||||||
|
) = librosa.core.load( # 理论上librosa读取可能对某些音频有bug,应该上ffmpeg读取,但是太麻烦了弃坑
|
||||||
|
music_file,
|
||||||
|
bp["sr"],
|
||||||
|
False,
|
||||||
|
dtype=np.float32,
|
||||||
|
res_type=bp["res_type"],
|
||||||
|
)
|
||||||
|
if X_wave[d].ndim == 1:
|
||||||
|
X_wave[d] = np.asfortranarray([X_wave[d], X_wave[d]])
|
||||||
|
else: # lower bands
|
||||||
|
X_wave[d] = librosa.core.resample(
|
||||||
|
X_wave[d + 1],
|
||||||
|
self.mp.param["band"][d + 1]["sr"],
|
||||||
|
bp["sr"],
|
||||||
|
res_type=bp["res_type"],
|
||||||
|
)
|
||||||
|
# Stft of wave source
|
||||||
|
X_spec_s[d] = spec_utils.wave_to_spectrogram_mt(
|
||||||
|
X_wave[d],
|
||||||
|
bp["hl"],
|
||||||
|
bp["n_fft"],
|
||||||
|
self.mp.param["mid_side"],
|
||||||
|
self.mp.param["mid_side_b2"],
|
||||||
|
self.mp.param["reverse"],
|
||||||
|
)
|
||||||
|
# pdb.set_trace()
|
||||||
|
if d == bands_n and self.data["high_end_process"] != "none":
|
||||||
|
input_high_end_h = (bp["n_fft"] // 2 - bp["crop_stop"]) + (
|
||||||
|
self.mp.param["pre_filter_stop"] - self.mp.param["pre_filter_start"]
|
||||||
|
)
|
||||||
|
input_high_end = X_spec_s[d][
|
||||||
|
:, bp["n_fft"] // 2 - input_high_end_h : bp["n_fft"] // 2, :
|
||||||
|
]
|
||||||
|
|
||||||
|
X_spec_m = spec_utils.combine_spectrograms(X_spec_s, self.mp)
|
||||||
|
aggresive_set = float(self.data["agg"] / 100)
|
||||||
|
aggressiveness = {
|
||||||
|
"value": aggresive_set,
|
||||||
|
"split_bin": self.mp.param["band"][1]["crop_stop"],
|
||||||
|
}
|
||||||
|
with torch.no_grad():
|
||||||
|
pred, X_mag, X_phase = inference(
|
||||||
|
X_spec_m, self.device, self.model, aggressiveness, self.data
|
||||||
|
)
|
||||||
|
# Postprocess
|
||||||
|
if self.data["postprocess"]:
|
||||||
|
pred_inv = np.clip(X_mag - pred, 0, np.inf)
|
||||||
|
pred = spec_utils.mask_silence(pred, pred_inv)
|
||||||
|
y_spec_m = pred * X_phase
|
||||||
|
v_spec_m = X_spec_m - y_spec_m
|
||||||
|
|
||||||
|
if ins_root is not None:
|
||||||
|
if self.data["high_end_process"].startswith("mirroring"):
|
||||||
|
input_high_end_ = spec_utils.mirroring(
|
||||||
|
self.data["high_end_process"], y_spec_m, input_high_end, self.mp
|
||||||
|
)
|
||||||
|
wav_instrument = spec_utils.cmb_spectrogram_to_wave(
|
||||||
|
y_spec_m, self.mp, input_high_end_h, input_high_end_
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
wav_instrument = spec_utils.cmb_spectrogram_to_wave(y_spec_m, self.mp)
|
||||||
|
print("%s instruments done" % name)
|
||||||
|
sf.write(
|
||||||
|
os.path.join(
|
||||||
|
ins_root,
|
||||||
|
"main_vocal_{}_{}.{}".format(name, self.data["agg"], format),
|
||||||
|
),
|
||||||
|
(np.array(wav_instrument) * 32768).astype("int16"),
|
||||||
|
self.mp.param["sr"],
|
||||||
|
) #
|
||||||
|
if vocal_root is not None:
|
||||||
|
if self.data["high_end_process"].startswith("mirroring"):
|
||||||
|
input_high_end_ = spec_utils.mirroring(
|
||||||
|
self.data["high_end_process"], v_spec_m, input_high_end, self.mp
|
||||||
|
)
|
||||||
|
wav_vocals = spec_utils.cmb_spectrogram_to_wave(
|
||||||
|
v_spec_m, self.mp, input_high_end_h, input_high_end_
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
wav_vocals = spec_utils.cmb_spectrogram_to_wave(v_spec_m, self.mp)
|
||||||
|
print("%s vocals done" % name)
|
||||||
|
sf.write(
|
||||||
|
os.path.join(
|
||||||
|
vocal_root, "others_{}_{}.{}".format(name, self.data["agg"], format)
|
||||||
|
),
|
||||||
|
(np.array(wav_vocals) * 32768).astype("int16"),
|
||||||
|
self.mp.param["sr"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
device = "cuda"
|
device = "cuda"
|
||||||
is_half = True
|
is_half = True
|
||||||
model_path = "uvr5_weights/2_HP-UVR.pth"
|
# model_path = "uvr5_weights/2_HP-UVR.pth"
|
||||||
pre_fun = _audio_pre_(model_path=model_path, device=device, is_half=True)
|
# model_path = "uvr5_weights/VR-DeEchoDeReverb.pth"
|
||||||
audio_path = "神女劈观.aac"
|
# model_path = "uvr5_weights/VR-DeEchoNormal.pth"
|
||||||
|
model_path = "uvr5_weights/DeEchoNormal.pth"
|
||||||
|
# pre_fun = _audio_pre_(model_path=model_path, device=device, is_half=True,agg=10)
|
||||||
|
pre_fun = _audio_pre_new(model_path=model_path, device=device, is_half=True, agg=10)
|
||||||
|
audio_path = "雪雪伴奏对消HP5.wav"
|
||||||
save_path = "opt"
|
save_path = "opt"
|
||||||
pre_fun._path_audio_(audio_path, save_path, save_path)
|
pre_fun._path_audio_(audio_path, save_path, save_path)
|
||||||
|
|||||||
BIN
logs/mute/3_feature768/mute.npy
Normal file
BIN
logs/mute/3_feature768/mute.npy
Normal file
Binary file not shown.
4121
poetry.lock
generated
4121
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
2
pretrained_v2/.gitignore
vendored
Normal file
2
pretrained_v2/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*
|
||||||
|
!.gitignore
|
||||||
@@ -6,7 +6,7 @@ authors = ["lj1995"]
|
|||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.8"
|
python = "^3.8,<3.11"
|
||||||
torch = "^2.0.0"
|
torch = "^2.0.0"
|
||||||
torchaudio = "^2.0.1"
|
torchaudio = "^2.0.1"
|
||||||
Cython = "^0.29.34"
|
Cython = "^0.29.34"
|
||||||
@@ -30,7 +30,7 @@ numba = "0.56.4"
|
|||||||
numpy = "1.23.5"
|
numpy = "1.23.5"
|
||||||
scipy = "1.9.3"
|
scipy = "1.9.3"
|
||||||
praat-parselmouth = "^0.4.3"
|
praat-parselmouth = "^0.4.3"
|
||||||
Pillow = "9.1.1"
|
Pillow = "9.3.0"
|
||||||
pyworld = "^0.3.2"
|
pyworld = "^0.3.2"
|
||||||
resampy = "^0.4.2"
|
resampy = "^0.4.2"
|
||||||
scikit-learn = "^1.2.2"
|
scikit-learn = "^1.2.2"
|
||||||
@@ -40,7 +40,7 @@ tensorboard-data-server = "^0.7.0"
|
|||||||
tensorboard-plugin-wit = "^1.8.1"
|
tensorboard-plugin-wit = "^1.8.1"
|
||||||
torchgen = "^0.0.1"
|
torchgen = "^0.0.1"
|
||||||
tqdm = "^4.65.0"
|
tqdm = "^4.65.0"
|
||||||
tornado = "^6.2"
|
tornado = "^6.3"
|
||||||
Werkzeug = "^2.2.3"
|
Werkzeug = "^2.2.3"
|
||||||
uc-micro-py = "^1.0.1"
|
uc-micro-py = "^1.0.1"
|
||||||
sympy = "^1.11.1"
|
sympy = "^1.11.1"
|
||||||
|
|||||||
@@ -38,3 +38,6 @@ audioread
|
|||||||
uvicorn>=0.21.1
|
uvicorn>=0.21.1
|
||||||
colorama>=0.4.5
|
colorama>=0.4.5
|
||||||
pyworld>=0.3.2
|
pyworld>=0.3.2
|
||||||
|
httpx==0.23.0
|
||||||
|
onnxruntime-gpu
|
||||||
|
torchcrepe
|
||||||
@@ -51,9 +51,9 @@ def spectrogram_torch(y, n_fft, sampling_rate, hop_size, win_size, center=False)
|
|||||||
:: (B, Freq, Frame) - Linear-frequency Linear-amplitude spectrogram
|
:: (B, Freq, Frame) - Linear-frequency Linear-amplitude spectrogram
|
||||||
"""
|
"""
|
||||||
# Validation
|
# Validation
|
||||||
if torch.min(y) < -1.0:
|
if torch.min(y) < -1.07:
|
||||||
print("min value is ", torch.min(y))
|
print("min value is ", torch.min(y))
|
||||||
if torch.max(y) > 1.0:
|
if torch.max(y) > 1.07:
|
||||||
print("max value is ", torch.max(y))
|
print("max value is ", torch.max(y))
|
||||||
|
|
||||||
# Window - Cache if needed
|
# Window - Cache if needed
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
import torch, traceback, os, pdb
|
import torch, traceback, os, pdb, sys
|
||||||
|
|
||||||
|
now_dir = os.getcwd()
|
||||||
|
sys.path.append(now_dir)
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
from i18n import I18nAuto
|
||||||
|
|
||||||
|
i18n = I18nAuto()
|
||||||
|
|
||||||
|
|
||||||
def savee(ckpt, sr, if_f0, name, epoch):
|
def savee(ckpt, sr, if_f0, name, epoch, version):
|
||||||
try:
|
try:
|
||||||
opt = OrderedDict()
|
opt = OrderedDict()
|
||||||
opt["weight"] = {}
|
opt["weight"] = {}
|
||||||
@@ -76,6 +82,7 @@ def savee(ckpt, sr, if_f0, name, epoch):
|
|||||||
opt["info"] = "%sepoch" % epoch
|
opt["info"] = "%sepoch" % epoch
|
||||||
opt["sr"] = sr
|
opt["sr"] = sr
|
||||||
opt["f0"] = if_f0
|
opt["f0"] = if_f0
|
||||||
|
opt["version"] = version
|
||||||
torch.save(opt, "weights/%s.pth" % name)
|
torch.save(opt, "weights/%s.pth" % name)
|
||||||
return "Success."
|
return "Success."
|
||||||
except:
|
except:
|
||||||
@@ -85,16 +92,17 @@ def savee(ckpt, sr, if_f0, name, epoch):
|
|||||||
def show_info(path):
|
def show_info(path):
|
||||||
try:
|
try:
|
||||||
a = torch.load(path, map_location="cpu")
|
a = torch.load(path, map_location="cpu")
|
||||||
return "模型信息:%s\n采样率:%s\n模型是否输入音高引导:%s" % (
|
return "模型信息:%s\n采样率:%s\n模型是否输入音高引导:%s\n版本:%s" % (
|
||||||
a.get("info", "None"),
|
a.get("info", "None"),
|
||||||
a.get("sr", "None"),
|
a.get("sr", "None"),
|
||||||
a.get("f0", "None"),
|
a.get("f0", "None"),
|
||||||
|
a.get("version", "None"),
|
||||||
)
|
)
|
||||||
except:
|
except:
|
||||||
return traceback.format_exc()
|
return traceback.format_exc()
|
||||||
|
|
||||||
|
|
||||||
def extract_small_model(path, name, sr, if_f0, info):
|
def extract_small_model(path, name, sr, if_f0, info, version):
|
||||||
try:
|
try:
|
||||||
ckpt = torch.load(path, map_location="cpu")
|
ckpt = torch.load(path, map_location="cpu")
|
||||||
if "model" in ckpt:
|
if "model" in ckpt:
|
||||||
@@ -171,6 +179,7 @@ def extract_small_model(path, name, sr, if_f0, info):
|
|||||||
if info == "":
|
if info == "":
|
||||||
info = "Extracted model."
|
info = "Extracted model."
|
||||||
opt["info"] = info
|
opt["info"] = info
|
||||||
|
opt["version"] = version
|
||||||
opt["sr"] = sr
|
opt["sr"] = sr
|
||||||
opt["f0"] = int(if_f0)
|
opt["f0"] = int(if_f0)
|
||||||
torch.save(opt, "weights/%s.pth" % name)
|
torch.save(opt, "weights/%s.pth" % name)
|
||||||
@@ -191,7 +200,7 @@ def change_info(path, info, name):
|
|||||||
return traceback.format_exc()
|
return traceback.format_exc()
|
||||||
|
|
||||||
|
|
||||||
def merge(path1, path2, alpha1, sr, f0, info, name):
|
def merge(path1, path2, alpha1, sr, f0, info, name, version):
|
||||||
try:
|
try:
|
||||||
|
|
||||||
def extract(ckpt):
|
def extract(ckpt):
|
||||||
@@ -240,7 +249,8 @@ def merge(path1, path2, alpha1, sr, f0, info, name):
|
|||||||
elif(sr=="32k"):opt["config"] = [513, 32, 192, 192, 768, 2, 6, 3, 0, "1", [3, 7, 11], [[1, 3, 5], [1, 3, 5], [1, 3, 5]], [10, 4, 2, 2, 2], 512, [16, 16, 4, 4,4], 109, 256, 32000]
|
elif(sr=="32k"):opt["config"] = [513, 32, 192, 192, 768, 2, 6, 3, 0, "1", [3, 7, 11], [[1, 3, 5], [1, 3, 5], [1, 3, 5]], [10, 4, 2, 2, 2], 512, [16, 16, 4, 4,4], 109, 256, 32000]
|
||||||
"""
|
"""
|
||||||
opt["sr"] = sr
|
opt["sr"] = sr
|
||||||
opt["f0"] = 1 if f0 == "是" else 0
|
opt["f0"] = 1 if f0 == i18n("是") else 0
|
||||||
|
opt["version"] = version
|
||||||
opt["info"] = info
|
opt["info"] = info
|
||||||
torch.save(opt, "weights/%s.pth" % name)
|
torch.save(opt, "weights/%s.pth" % name)
|
||||||
return "Success."
|
return "Success."
|
||||||
|
|||||||
@@ -284,8 +284,8 @@ def get_hparams(init=True):
|
|||||||
bs done
|
bs done
|
||||||
pretrainG、pretrainD done
|
pretrainG、pretrainD done
|
||||||
卡号:os.en["CUDA_VISIBLE_DEVICES"] done
|
卡号:os.en["CUDA_VISIBLE_DEVICES"] done
|
||||||
if_latest todo
|
if_latest done
|
||||||
模型:if_f0 todo
|
模型:if_f0 done
|
||||||
采样率:自动选择config done
|
采样率:自动选择config done
|
||||||
是否缓存数据集进GPU:if_cache_data_in_gpu done
|
是否缓存数据集进GPU:if_cache_data_in_gpu done
|
||||||
|
|
||||||
@@ -321,6 +321,16 @@ def get_hparams(init=True):
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-sr", "--sample_rate", type=str, required=True, help="sample rate, 32k/40k/48k"
|
"-sr", "--sample_rate", type=str, required=True, help="sample rate, 32k/40k/48k"
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-sw",
|
||||||
|
"--save_every_weights",
|
||||||
|
type=str,
|
||||||
|
default="0",
|
||||||
|
help="save the extracted model in weights directory when saving checkpoints",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-v", "--version", type=str, required=True, help="model version"
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-f0",
|
"-f0",
|
||||||
"--if_f0",
|
"--if_f0",
|
||||||
@@ -369,11 +379,13 @@ def get_hparams(init=True):
|
|||||||
hparams.total_epoch = args.total_epoch
|
hparams.total_epoch = args.total_epoch
|
||||||
hparams.pretrainG = args.pretrainG
|
hparams.pretrainG = args.pretrainG
|
||||||
hparams.pretrainD = args.pretrainD
|
hparams.pretrainD = args.pretrainD
|
||||||
|
hparams.version = args.version
|
||||||
hparams.gpus = args.gpus
|
hparams.gpus = args.gpus
|
||||||
hparams.train.batch_size = args.batch_size
|
hparams.train.batch_size = args.batch_size
|
||||||
hparams.sample_rate = args.sample_rate
|
hparams.sample_rate = args.sample_rate
|
||||||
hparams.if_f0 = args.if_f0
|
hparams.if_f0 = args.if_f0
|
||||||
hparams.if_latest = args.if_latest
|
hparams.if_latest = args.if_latest
|
||||||
|
hparams.save_every_weights = args.save_every_weights
|
||||||
hparams.if_cache_data_in_gpu = args.if_cache_data_in_gpu
|
hparams.if_cache_data_in_gpu = args.if_cache_data_in_gpu
|
||||||
hparams.data.training_files = "%s/filelist.txt" % experiment_dir
|
hparams.data.training_files = "%s/filelist.txt" % experiment_dir
|
||||||
return hparams
|
return hparams
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ now_dir = os.getcwd()
|
|||||||
sys.path.append(os.path.join(now_dir))
|
sys.path.append(os.path.join(now_dir))
|
||||||
sys.path.append(os.path.join(now_dir, "train"))
|
sys.path.append(os.path.join(now_dir, "train"))
|
||||||
import utils
|
import utils
|
||||||
|
import datetime
|
||||||
|
|
||||||
hps = utils.get_hparams()
|
hps = utils.get_hparams()
|
||||||
os.environ["CUDA_VISIBLE_DEVICES"] = hps.gpus.replace("-", ",")
|
os.environ["CUDA_VISIBLE_DEVICES"] = hps.gpus.replace("-", ",")
|
||||||
@@ -31,31 +32,59 @@ from data_utils import (
|
|||||||
TextAudioCollate,
|
TextAudioCollate,
|
||||||
DistributedBucketSampler,
|
DistributedBucketSampler,
|
||||||
)
|
)
|
||||||
from infer_pack.models import (
|
|
||||||
SynthesizerTrnMs256NSFsid,
|
if hps.version == "v1":
|
||||||
SynthesizerTrnMs256NSFsid_nono,
|
from infer_pack.models import (
|
||||||
MultiPeriodDiscriminator,
|
SynthesizerTrnMs256NSFsid as RVC_Model_f0,
|
||||||
)
|
SynthesizerTrnMs256NSFsid_nono as RVC_Model_nof0,
|
||||||
|
MultiPeriodDiscriminator,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
from infer_pack.models import (
|
||||||
|
SynthesizerTrnMs768NSFsid as RVC_Model_f0,
|
||||||
|
SynthesizerTrnMs768NSFsid_nono as RVC_Model_nof0,
|
||||||
|
MultiPeriodDiscriminatorV2 as MultiPeriodDiscriminator,
|
||||||
|
)
|
||||||
from losses import generator_loss, discriminator_loss, feature_loss, kl_loss
|
from losses import generator_loss, discriminator_loss, feature_loss, kl_loss
|
||||||
from mel_processing import mel_spectrogram_torch, spec_to_mel_torch
|
from mel_processing import mel_spectrogram_torch, spec_to_mel_torch
|
||||||
|
from process_ckpt import savee
|
||||||
|
|
||||||
global_step = 0
|
global_step = 0
|
||||||
|
|
||||||
|
|
||||||
|
class EpochRecorder:
|
||||||
|
def __init__(self):
|
||||||
|
self.last_time = ttime()
|
||||||
|
|
||||||
|
def record(self):
|
||||||
|
now_time = ttime()
|
||||||
|
elapsed_time = now_time - self.last_time
|
||||||
|
self.last_time = now_time
|
||||||
|
elapsed_time_str = str(datetime.timedelta(seconds=elapsed_time))
|
||||||
|
current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
return f"[{current_time}] | ({elapsed_time_str})"
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
# n_gpus = torch.cuda.device_count()
|
n_gpus = torch.cuda.device_count()
|
||||||
os.environ["MASTER_ADDR"] = "localhost"
|
os.environ["MASTER_ADDR"] = "localhost"
|
||||||
os.environ["MASTER_PORT"] = "51545"
|
os.environ["MASTER_PORT"] = "51545"
|
||||||
|
|
||||||
mp.spawn(
|
children = []
|
||||||
run,
|
for i in range(n_gpus):
|
||||||
nprocs=n_gpus,
|
subproc = mp.Process(
|
||||||
args=(
|
target=run,
|
||||||
n_gpus,
|
args=(
|
||||||
hps,
|
i,
|
||||||
),
|
n_gpus,
|
||||||
)
|
hps,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
children.append(subproc)
|
||||||
|
subproc.start()
|
||||||
|
|
||||||
|
for i in range(n_gpus):
|
||||||
|
children[i].join()
|
||||||
|
|
||||||
|
|
||||||
def run(rank, n_gpus, hps):
|
def run(rank, n_gpus, hps):
|
||||||
@@ -63,7 +92,7 @@ def run(rank, n_gpus, hps):
|
|||||||
if rank == 0:
|
if rank == 0:
|
||||||
logger = utils.get_logger(hps.model_dir)
|
logger = utils.get_logger(hps.model_dir)
|
||||||
logger.info(hps)
|
logger.info(hps)
|
||||||
utils.check_git_hash(hps.model_dir)
|
# utils.check_git_hash(hps.model_dir)
|
||||||
writer = SummaryWriter(log_dir=hps.model_dir)
|
writer = SummaryWriter(log_dir=hps.model_dir)
|
||||||
writer_eval = SummaryWriter(log_dir=os.path.join(hps.model_dir, "eval"))
|
writer_eval = SummaryWriter(log_dir=os.path.join(hps.model_dir, "eval"))
|
||||||
|
|
||||||
@@ -104,7 +133,7 @@ def run(rank, n_gpus, hps):
|
|||||||
prefetch_factor=8,
|
prefetch_factor=8,
|
||||||
)
|
)
|
||||||
if hps.if_f0 == 1:
|
if hps.if_f0 == 1:
|
||||||
net_g = SynthesizerTrnMs256NSFsid(
|
net_g = RVC_Model_f0(
|
||||||
hps.data.filter_length // 2 + 1,
|
hps.data.filter_length // 2 + 1,
|
||||||
hps.train.segment_size // hps.data.hop_length,
|
hps.train.segment_size // hps.data.hop_length,
|
||||||
**hps.model,
|
**hps.model,
|
||||||
@@ -112,7 +141,7 @@ def run(rank, n_gpus, hps):
|
|||||||
sr=hps.sample_rate,
|
sr=hps.sample_rate,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
net_g = SynthesizerTrnMs256NSFsid_nono(
|
net_g = RVC_Model_nof0(
|
||||||
hps.data.filter_length // 2 + 1,
|
hps.data.filter_length // 2 + 1,
|
||||||
hps.train.segment_size // hps.data.hop_length,
|
hps.train.segment_size // hps.data.hop_length,
|
||||||
**hps.model,
|
**hps.model,
|
||||||
@@ -315,6 +344,7 @@ def train_and_evaluate(
|
|||||||
data_iterator = enumerate(train_loader)
|
data_iterator = enumerate(train_loader)
|
||||||
|
|
||||||
# Run steps
|
# Run steps
|
||||||
|
epoch_recorder = EpochRecorder()
|
||||||
for batch_idx, info in data_iterator:
|
for batch_idx, info in data_iterator:
|
||||||
# Data
|
# Data
|
||||||
## Unpack
|
## Unpack
|
||||||
@@ -343,7 +373,7 @@ def train_and_evaluate(
|
|||||||
spec = spec.cuda(rank, non_blocking=True)
|
spec = spec.cuda(rank, non_blocking=True)
|
||||||
spec_lengths = spec_lengths.cuda(rank, non_blocking=True)
|
spec_lengths = spec_lengths.cuda(rank, non_blocking=True)
|
||||||
wave = wave.cuda(rank, non_blocking=True)
|
wave = wave.cuda(rank, non_blocking=True)
|
||||||
wave_lengths = wave_lengths.cuda(rank, non_blocking=True)
|
# wave_lengths = wave_lengths.cuda(rank, non_blocking=True)
|
||||||
|
|
||||||
# Calculate
|
# Calculate
|
||||||
with autocast(enabled=hps.train.fp16_run):
|
with autocast(enabled=hps.train.fp16_run):
|
||||||
@@ -428,10 +458,10 @@ def train_and_evaluate(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
# Amor For Tensorboard display
|
# Amor For Tensorboard display
|
||||||
if loss_mel > 50:
|
if loss_mel > 75:
|
||||||
loss_mel = 50
|
loss_mel = 75
|
||||||
if loss_kl > 5:
|
if loss_kl > 9:
|
||||||
loss_kl = 5
|
loss_kl = 9
|
||||||
|
|
||||||
logger.info([global_step, lr])
|
logger.info([global_step, lr])
|
||||||
logger.info(
|
logger.info(
|
||||||
@@ -512,12 +542,31 @@ def train_and_evaluate(
|
|||||||
epoch,
|
epoch,
|
||||||
os.path.join(hps.model_dir, "D_{}.pth".format(2333333)),
|
os.path.join(hps.model_dir, "D_{}.pth".format(2333333)),
|
||||||
)
|
)
|
||||||
|
if rank == 0 and hps.save_every_weights == "1":
|
||||||
|
if hasattr(net_g, "module"):
|
||||||
|
ckpt = net_g.module.state_dict()
|
||||||
|
else:
|
||||||
|
ckpt = net_g.state_dict()
|
||||||
|
logger.info(
|
||||||
|
"saving ckpt %s_e%s:%s"
|
||||||
|
% (
|
||||||
|
hps.name,
|
||||||
|
epoch,
|
||||||
|
savee(
|
||||||
|
ckpt,
|
||||||
|
hps.sample_rate,
|
||||||
|
hps.if_f0,
|
||||||
|
hps.name + "_e%s" % epoch,
|
||||||
|
epoch,
|
||||||
|
hps.version,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if rank == 0:
|
if rank == 0:
|
||||||
logger.info("====> Epoch: {}".format(epoch))
|
logger.info("====> Epoch: {} {}".format(epoch, epoch_recorder.record()))
|
||||||
if epoch >= hps.total_epoch and rank == 0:
|
if epoch >= hps.total_epoch and rank == 0:
|
||||||
logger.info("Training is done. The program is closed.")
|
logger.info("Training is done. The program is closed.")
|
||||||
from process_ckpt import savee # def savee(ckpt,sr,if_f0,name,epoch):
|
|
||||||
|
|
||||||
if hasattr(net_g, "module"):
|
if hasattr(net_g, "module"):
|
||||||
ckpt = net_g.module.state_dict()
|
ckpt = net_g.module.state_dict()
|
||||||
@@ -525,11 +574,12 @@ def train_and_evaluate(
|
|||||||
ckpt = net_g.state_dict()
|
ckpt = net_g.state_dict()
|
||||||
logger.info(
|
logger.info(
|
||||||
"saving final ckpt:%s"
|
"saving final ckpt:%s"
|
||||||
% (savee(ckpt, hps.sample_rate, hps.if_f0, hps.name, epoch))
|
% (savee(ckpt, hps.sample_rate, hps.if_f0, hps.name, epoch, hps.version))
|
||||||
)
|
)
|
||||||
sleep(1)
|
sleep(1)
|
||||||
os._exit(2333333)
|
os._exit(2333333)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
torch.multiprocessing.set_start_method("spawn")
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -32,19 +32,19 @@ class PreProcess:
|
|||||||
def __init__(self, sr, exp_dir):
|
def __init__(self, sr, exp_dir):
|
||||||
self.slicer = Slicer(
|
self.slicer = Slicer(
|
||||||
sr=sr,
|
sr=sr,
|
||||||
threshold=-40,
|
threshold=-42,
|
||||||
min_length=800,
|
min_length=1500,
|
||||||
min_interval=400,
|
min_interval=400,
|
||||||
hop_size=15,
|
hop_size=15,
|
||||||
max_sil_kept=150,
|
max_sil_kept=500,
|
||||||
)
|
)
|
||||||
self.sr = sr
|
self.sr = sr
|
||||||
self.bh, self.ah = signal.butter(N=5, Wn=48, btype="high", fs=self.sr)
|
self.bh, self.ah = signal.butter(N=5, Wn=48, btype="high", fs=self.sr)
|
||||||
self.per = 3.7
|
self.per = 3.7
|
||||||
self.overlap = 0.3
|
self.overlap = 0.3
|
||||||
self.tail = self.per + self.overlap
|
self.tail = self.per + self.overlap
|
||||||
self.max = 0.95
|
self.max = 0.9
|
||||||
self.alpha = 0.8
|
self.alpha = 0.75
|
||||||
self.exp_dir = exp_dir
|
self.exp_dir = exp_dir
|
||||||
self.gt_wavs_dir = "%s/0_gt_wavs" % exp_dir
|
self.gt_wavs_dir = "%s/0_gt_wavs" % exp_dir
|
||||||
self.wavs16k_dir = "%s/1_16k_wavs" % exp_dir
|
self.wavs16k_dir = "%s/1_16k_wavs" % exp_dir
|
||||||
@@ -115,10 +115,10 @@ class PreProcess:
|
|||||||
p = multiprocessing.Process(
|
p = multiprocessing.Process(
|
||||||
target=self.pipeline_mp, args=(infos[i::n_p],)
|
target=self.pipeline_mp, args=(infos[i::n_p],)
|
||||||
)
|
)
|
||||||
p.start()
|
|
||||||
ps.append(p)
|
ps.append(p)
|
||||||
for p in ps:
|
p.start()
|
||||||
p.join()
|
for i in range(n_p):
|
||||||
|
ps[i].join()
|
||||||
except:
|
except:
|
||||||
println("Fail. %s" % traceback.format_exc())
|
println("Fail. %s" % traceback.format_exc())
|
||||||
|
|
||||||
|
|||||||
125
uvr5_pack/lib_v5/layers_new.py
Normal file
125
uvr5_pack/lib_v5/layers_new.py
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
import torch
|
||||||
|
from torch import nn
|
||||||
|
import torch.nn.functional as F
|
||||||
|
|
||||||
|
from uvr5_pack.lib_v5 import spec_utils
|
||||||
|
|
||||||
|
|
||||||
|
class Conv2DBNActiv(nn.Module):
|
||||||
|
def __init__(self, nin, nout, ksize=3, stride=1, pad=1, dilation=1, activ=nn.ReLU):
|
||||||
|
super(Conv2DBNActiv, self).__init__()
|
||||||
|
self.conv = nn.Sequential(
|
||||||
|
nn.Conv2d(
|
||||||
|
nin,
|
||||||
|
nout,
|
||||||
|
kernel_size=ksize,
|
||||||
|
stride=stride,
|
||||||
|
padding=pad,
|
||||||
|
dilation=dilation,
|
||||||
|
bias=False,
|
||||||
|
),
|
||||||
|
nn.BatchNorm2d(nout),
|
||||||
|
activ(),
|
||||||
|
)
|
||||||
|
|
||||||
|
def __call__(self, x):
|
||||||
|
return self.conv(x)
|
||||||
|
|
||||||
|
|
||||||
|
class Encoder(nn.Module):
|
||||||
|
def __init__(self, nin, nout, ksize=3, stride=1, pad=1, activ=nn.LeakyReLU):
|
||||||
|
super(Encoder, self).__init__()
|
||||||
|
self.conv1 = Conv2DBNActiv(nin, nout, ksize, stride, pad, activ=activ)
|
||||||
|
self.conv2 = Conv2DBNActiv(nout, nout, ksize, 1, pad, activ=activ)
|
||||||
|
|
||||||
|
def __call__(self, x):
|
||||||
|
h = self.conv1(x)
|
||||||
|
h = self.conv2(h)
|
||||||
|
|
||||||
|
return h
|
||||||
|
|
||||||
|
|
||||||
|
class Decoder(nn.Module):
|
||||||
|
def __init__(
|
||||||
|
self, nin, nout, ksize=3, stride=1, pad=1, activ=nn.ReLU, dropout=False
|
||||||
|
):
|
||||||
|
super(Decoder, self).__init__()
|
||||||
|
self.conv1 = Conv2DBNActiv(nin, nout, ksize, 1, pad, activ=activ)
|
||||||
|
# self.conv2 = Conv2DBNActiv(nout, nout, ksize, 1, pad, activ=activ)
|
||||||
|
self.dropout = nn.Dropout2d(0.1) if dropout else None
|
||||||
|
|
||||||
|
def __call__(self, x, skip=None):
|
||||||
|
x = F.interpolate(x, scale_factor=2, mode="bilinear", align_corners=True)
|
||||||
|
|
||||||
|
if skip is not None:
|
||||||
|
skip = spec_utils.crop_center(skip, x)
|
||||||
|
x = torch.cat([x, skip], dim=1)
|
||||||
|
|
||||||
|
h = self.conv1(x)
|
||||||
|
# h = self.conv2(h)
|
||||||
|
|
||||||
|
if self.dropout is not None:
|
||||||
|
h = self.dropout(h)
|
||||||
|
|
||||||
|
return h
|
||||||
|
|
||||||
|
|
||||||
|
class ASPPModule(nn.Module):
|
||||||
|
def __init__(self, nin, nout, dilations=(4, 8, 12), activ=nn.ReLU, dropout=False):
|
||||||
|
super(ASPPModule, self).__init__()
|
||||||
|
self.conv1 = nn.Sequential(
|
||||||
|
nn.AdaptiveAvgPool2d((1, None)),
|
||||||
|
Conv2DBNActiv(nin, nout, 1, 1, 0, activ=activ),
|
||||||
|
)
|
||||||
|
self.conv2 = Conv2DBNActiv(nin, nout, 1, 1, 0, activ=activ)
|
||||||
|
self.conv3 = Conv2DBNActiv(
|
||||||
|
nin, nout, 3, 1, dilations[0], dilations[0], activ=activ
|
||||||
|
)
|
||||||
|
self.conv4 = Conv2DBNActiv(
|
||||||
|
nin, nout, 3, 1, dilations[1], dilations[1], activ=activ
|
||||||
|
)
|
||||||
|
self.conv5 = Conv2DBNActiv(
|
||||||
|
nin, nout, 3, 1, dilations[2], dilations[2], activ=activ
|
||||||
|
)
|
||||||
|
self.bottleneck = Conv2DBNActiv(nout * 5, nout, 1, 1, 0, activ=activ)
|
||||||
|
self.dropout = nn.Dropout2d(0.1) if dropout else None
|
||||||
|
|
||||||
|
def forward(self, x):
|
||||||
|
_, _, h, w = x.size()
|
||||||
|
feat1 = F.interpolate(
|
||||||
|
self.conv1(x), size=(h, w), mode="bilinear", align_corners=True
|
||||||
|
)
|
||||||
|
feat2 = self.conv2(x)
|
||||||
|
feat3 = self.conv3(x)
|
||||||
|
feat4 = self.conv4(x)
|
||||||
|
feat5 = self.conv5(x)
|
||||||
|
out = torch.cat((feat1, feat2, feat3, feat4, feat5), dim=1)
|
||||||
|
out = self.bottleneck(out)
|
||||||
|
|
||||||
|
if self.dropout is not None:
|
||||||
|
out = self.dropout(out)
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
class LSTMModule(nn.Module):
|
||||||
|
def __init__(self, nin_conv, nin_lstm, nout_lstm):
|
||||||
|
super(LSTMModule, self).__init__()
|
||||||
|
self.conv = Conv2DBNActiv(nin_conv, 1, 1, 1, 0)
|
||||||
|
self.lstm = nn.LSTM(
|
||||||
|
input_size=nin_lstm, hidden_size=nout_lstm // 2, bidirectional=True
|
||||||
|
)
|
||||||
|
self.dense = nn.Sequential(
|
||||||
|
nn.Linear(nout_lstm, nin_lstm), nn.BatchNorm1d(nin_lstm), nn.ReLU()
|
||||||
|
)
|
||||||
|
|
||||||
|
def forward(self, x):
|
||||||
|
N, _, nbins, nframes = x.size()
|
||||||
|
h = self.conv(x)[:, 0] # N, nbins, nframes
|
||||||
|
h = h.permute(2, 0, 1) # nframes, N, nbins
|
||||||
|
h, _ = self.lstm(h)
|
||||||
|
h = self.dense(h.reshape(-1, h.size()[-1])) # nframes * N, nbins
|
||||||
|
h = h.reshape(nframes, N, 1, nbins)
|
||||||
|
h = h.permute(1, 2, 3, 0)
|
||||||
|
|
||||||
|
return h
|
||||||
54
uvr5_pack/lib_v5/modelparams/4band_v3.json
Normal file
54
uvr5_pack/lib_v5/modelparams/4band_v3.json
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
{
|
||||||
|
"bins": 672,
|
||||||
|
"unstable_bins": 8,
|
||||||
|
"reduction_bins": 530,
|
||||||
|
"band": {
|
||||||
|
"1": {
|
||||||
|
"sr": 7350,
|
||||||
|
"hl": 80,
|
||||||
|
"n_fft": 640,
|
||||||
|
"crop_start": 0,
|
||||||
|
"crop_stop": 85,
|
||||||
|
"lpf_start": 25,
|
||||||
|
"lpf_stop": 53,
|
||||||
|
"res_type": "polyphase"
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"sr": 7350,
|
||||||
|
"hl": 80,
|
||||||
|
"n_fft": 320,
|
||||||
|
"crop_start": 4,
|
||||||
|
"crop_stop": 87,
|
||||||
|
"hpf_start": 25,
|
||||||
|
"hpf_stop": 12,
|
||||||
|
"lpf_start": 31,
|
||||||
|
"lpf_stop": 62,
|
||||||
|
"res_type": "polyphase"
|
||||||
|
},
|
||||||
|
"3": {
|
||||||
|
"sr": 14700,
|
||||||
|
"hl": 160,
|
||||||
|
"n_fft": 512,
|
||||||
|
"crop_start": 17,
|
||||||
|
"crop_stop": 216,
|
||||||
|
"hpf_start": 48,
|
||||||
|
"hpf_stop": 24,
|
||||||
|
"lpf_start": 139,
|
||||||
|
"lpf_stop": 210,
|
||||||
|
"res_type": "polyphase"
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"sr": 44100,
|
||||||
|
"hl": 480,
|
||||||
|
"n_fft": 960,
|
||||||
|
"crop_start": 78,
|
||||||
|
"crop_stop": 383,
|
||||||
|
"hpf_start": 130,
|
||||||
|
"hpf_stop": 86,
|
||||||
|
"res_type": "kaiser_fast"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sr": 44100,
|
||||||
|
"pre_filter_start": 668,
|
||||||
|
"pre_filter_stop": 672
|
||||||
|
}
|
||||||
132
uvr5_pack/lib_v5/nets_new.py
Normal file
132
uvr5_pack/lib_v5/nets_new.py
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
import torch
|
||||||
|
from torch import nn
|
||||||
|
import torch.nn.functional as F
|
||||||
|
from uvr5_pack.lib_v5 import layers_new as layers
|
||||||
|
|
||||||
|
|
||||||
|
class BaseNet(nn.Module):
|
||||||
|
def __init__(
|
||||||
|
self, nin, nout, nin_lstm, nout_lstm, dilations=((4, 2), (8, 4), (12, 6))
|
||||||
|
):
|
||||||
|
super(BaseNet, self).__init__()
|
||||||
|
self.enc1 = layers.Conv2DBNActiv(nin, nout, 3, 1, 1)
|
||||||
|
self.enc2 = layers.Encoder(nout, nout * 2, 3, 2, 1)
|
||||||
|
self.enc3 = layers.Encoder(nout * 2, nout * 4, 3, 2, 1)
|
||||||
|
self.enc4 = layers.Encoder(nout * 4, nout * 6, 3, 2, 1)
|
||||||
|
self.enc5 = layers.Encoder(nout * 6, nout * 8, 3, 2, 1)
|
||||||
|
|
||||||
|
self.aspp = layers.ASPPModule(nout * 8, nout * 8, dilations, dropout=True)
|
||||||
|
|
||||||
|
self.dec4 = layers.Decoder(nout * (6 + 8), nout * 6, 3, 1, 1)
|
||||||
|
self.dec3 = layers.Decoder(nout * (4 + 6), nout * 4, 3, 1, 1)
|
||||||
|
self.dec2 = layers.Decoder(nout * (2 + 4), nout * 2, 3, 1, 1)
|
||||||
|
self.lstm_dec2 = layers.LSTMModule(nout * 2, nin_lstm, nout_lstm)
|
||||||
|
self.dec1 = layers.Decoder(nout * (1 + 2) + 1, nout * 1, 3, 1, 1)
|
||||||
|
|
||||||
|
def __call__(self, x):
|
||||||
|
e1 = self.enc1(x)
|
||||||
|
e2 = self.enc2(e1)
|
||||||
|
e3 = self.enc3(e2)
|
||||||
|
e4 = self.enc4(e3)
|
||||||
|
e5 = self.enc5(e4)
|
||||||
|
|
||||||
|
h = self.aspp(e5)
|
||||||
|
|
||||||
|
h = self.dec4(h, e4)
|
||||||
|
h = self.dec3(h, e3)
|
||||||
|
h = self.dec2(h, e2)
|
||||||
|
h = torch.cat([h, self.lstm_dec2(h)], dim=1)
|
||||||
|
h = self.dec1(h, e1)
|
||||||
|
|
||||||
|
return h
|
||||||
|
|
||||||
|
|
||||||
|
class CascadedNet(nn.Module):
|
||||||
|
def __init__(self, n_fft, nout=32, nout_lstm=128):
|
||||||
|
super(CascadedNet, self).__init__()
|
||||||
|
|
||||||
|
self.max_bin = n_fft // 2
|
||||||
|
self.output_bin = n_fft // 2 + 1
|
||||||
|
self.nin_lstm = self.max_bin // 2
|
||||||
|
self.offset = 64
|
||||||
|
|
||||||
|
self.stg1_low_band_net = nn.Sequential(
|
||||||
|
BaseNet(2, nout // 2, self.nin_lstm // 2, nout_lstm),
|
||||||
|
layers.Conv2DBNActiv(nout // 2, nout // 4, 1, 1, 0),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.stg1_high_band_net = BaseNet(
|
||||||
|
2, nout // 4, self.nin_lstm // 2, nout_lstm // 2
|
||||||
|
)
|
||||||
|
|
||||||
|
self.stg2_low_band_net = nn.Sequential(
|
||||||
|
BaseNet(nout // 4 + 2, nout, self.nin_lstm // 2, nout_lstm),
|
||||||
|
layers.Conv2DBNActiv(nout, nout // 2, 1, 1, 0),
|
||||||
|
)
|
||||||
|
self.stg2_high_band_net = BaseNet(
|
||||||
|
nout // 4 + 2, nout // 2, self.nin_lstm // 2, nout_lstm // 2
|
||||||
|
)
|
||||||
|
|
||||||
|
self.stg3_full_band_net = BaseNet(
|
||||||
|
3 * nout // 4 + 2, nout, self.nin_lstm, nout_lstm
|
||||||
|
)
|
||||||
|
|
||||||
|
self.out = nn.Conv2d(nout, 2, 1, bias=False)
|
||||||
|
self.aux_out = nn.Conv2d(3 * nout // 4, 2, 1, bias=False)
|
||||||
|
|
||||||
|
def forward(self, x):
|
||||||
|
x = x[:, :, : self.max_bin]
|
||||||
|
|
||||||
|
bandw = x.size()[2] // 2
|
||||||
|
l1_in = x[:, :, :bandw]
|
||||||
|
h1_in = x[:, :, bandw:]
|
||||||
|
l1 = self.stg1_low_band_net(l1_in)
|
||||||
|
h1 = self.stg1_high_band_net(h1_in)
|
||||||
|
aux1 = torch.cat([l1, h1], dim=2)
|
||||||
|
|
||||||
|
l2_in = torch.cat([l1_in, l1], dim=1)
|
||||||
|
h2_in = torch.cat([h1_in, h1], dim=1)
|
||||||
|
l2 = self.stg2_low_band_net(l2_in)
|
||||||
|
h2 = self.stg2_high_band_net(h2_in)
|
||||||
|
aux2 = torch.cat([l2, h2], dim=2)
|
||||||
|
|
||||||
|
f3_in = torch.cat([x, aux1, aux2], dim=1)
|
||||||
|
f3 = self.stg3_full_band_net(f3_in)
|
||||||
|
|
||||||
|
mask = torch.sigmoid(self.out(f3))
|
||||||
|
mask = F.pad(
|
||||||
|
input=mask,
|
||||||
|
pad=(0, 0, 0, self.output_bin - mask.size()[2]),
|
||||||
|
mode="replicate",
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.training:
|
||||||
|
aux = torch.cat([aux1, aux2], dim=1)
|
||||||
|
aux = torch.sigmoid(self.aux_out(aux))
|
||||||
|
aux = F.pad(
|
||||||
|
input=aux,
|
||||||
|
pad=(0, 0, 0, self.output_bin - aux.size()[2]),
|
||||||
|
mode="replicate",
|
||||||
|
)
|
||||||
|
return mask, aux
|
||||||
|
else:
|
||||||
|
return mask
|
||||||
|
|
||||||
|
def predict_mask(self, x):
|
||||||
|
mask = self.forward(x)
|
||||||
|
|
||||||
|
if self.offset > 0:
|
||||||
|
mask = mask[:, :, :, self.offset : -self.offset]
|
||||||
|
assert mask.size()[3] > 0
|
||||||
|
|
||||||
|
return mask
|
||||||
|
|
||||||
|
def predict(self, x, aggressiveness=None):
|
||||||
|
mask = self.forward(x)
|
||||||
|
pred_mag = x * mask
|
||||||
|
|
||||||
|
if self.offset > 0:
|
||||||
|
pred_mag = pred_mag[:, :, :, self.offset : -self.offset]
|
||||||
|
assert pred_mag.size()[3] > 0
|
||||||
|
|
||||||
|
return pred_mag
|
||||||
@@ -2,7 +2,7 @@ import numpy as np, parselmouth, torch, pdb
|
|||||||
from time import time as ttime
|
from time import time as ttime
|
||||||
import torch.nn.functional as F
|
import torch.nn.functional as F
|
||||||
import scipy.signal as signal
|
import scipy.signal as signal
|
||||||
import pyworld, os, traceback, faiss, librosa
|
import pyworld, os, traceback, faiss, librosa, torchcrepe
|
||||||
from scipy import signal
|
from scipy import signal
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
|
|
||||||
@@ -25,6 +25,28 @@ def cache_harvest_f0(input_audio_path, fs, f0max, f0min, frame_period):
|
|||||||
return f0
|
return f0
|
||||||
|
|
||||||
|
|
||||||
|
def change_rms(data1, sr1, data2, sr2, rate): # 1是输入音频,2是输出音频,rate是2的占比
|
||||||
|
# print(data1.max(),data2.max())
|
||||||
|
rms1 = librosa.feature.rms(
|
||||||
|
y=data1, frame_length=sr1 // 2 * 2, hop_length=sr1 // 2
|
||||||
|
) # 每半秒一个点
|
||||||
|
rms2 = librosa.feature.rms(y=data2, frame_length=sr2 // 2 * 2, hop_length=sr2 // 2)
|
||||||
|
rms1 = torch.from_numpy(rms1)
|
||||||
|
rms1 = F.interpolate(
|
||||||
|
rms1.unsqueeze(0), size=data2.shape[0], mode="linear"
|
||||||
|
).squeeze()
|
||||||
|
rms2 = torch.from_numpy(rms2)
|
||||||
|
rms2 = F.interpolate(
|
||||||
|
rms2.unsqueeze(0), size=data2.shape[0], mode="linear"
|
||||||
|
).squeeze()
|
||||||
|
rms2 = torch.max(rms2, torch.zeros_like(rms2) + 1e-6)
|
||||||
|
data2 *= (
|
||||||
|
torch.pow(rms1, torch.tensor(1 - rate))
|
||||||
|
* torch.pow(rms2, torch.tensor(rate - 1))
|
||||||
|
).numpy()
|
||||||
|
return data2
|
||||||
|
|
||||||
|
|
||||||
class VC(object):
|
class VC(object):
|
||||||
def __init__(self, tgt_sr, config):
|
def __init__(self, tgt_sr, config):
|
||||||
self.x_pad, self.x_query, self.x_center, self.x_max, self.is_half = (
|
self.x_pad, self.x_query, self.x_center, self.x_max, self.is_half = (
|
||||||
@@ -81,6 +103,27 @@ class VC(object):
|
|||||||
f0 = cache_harvest_f0(input_audio_path, self.sr, f0_max, f0_min, 10)
|
f0 = cache_harvest_f0(input_audio_path, self.sr, f0_max, f0_min, 10)
|
||||||
if filter_radius > 2:
|
if filter_radius > 2:
|
||||||
f0 = signal.medfilt(f0, 3)
|
f0 = signal.medfilt(f0, 3)
|
||||||
|
elif f0_method == "crepe":
|
||||||
|
model = "full"
|
||||||
|
# Pick a batch size that doesn't cause memory errors on your gpu
|
||||||
|
batch_size = 512
|
||||||
|
# Compute pitch using first gpu
|
||||||
|
audio = torch.tensor(np.copy(x))[None].float()
|
||||||
|
f0, pd = torchcrepe.predict(
|
||||||
|
audio,
|
||||||
|
self.sr,
|
||||||
|
self.window,
|
||||||
|
f0_min,
|
||||||
|
f0_max,
|
||||||
|
model,
|
||||||
|
batch_size=batch_size,
|
||||||
|
device=self.device,
|
||||||
|
return_periodicity=True,
|
||||||
|
)
|
||||||
|
pd = torchcrepe.filter.median(pd, 3)
|
||||||
|
f0 = torchcrepe.filter.mean(f0, 3)
|
||||||
|
f0[pd < 0.1] = 0
|
||||||
|
f0 = f0[0].cpu().numpy()
|
||||||
f0 *= pow(2, f0_up_key / 12)
|
f0 *= pow(2, f0_up_key / 12)
|
||||||
# with open("test.txt","w")as f:f.write("\n".join([str(i)for i in f0.tolist()]))
|
# with open("test.txt","w")as f:f.write("\n".join([str(i)for i in f0.tolist()]))
|
||||||
tf0 = self.sr // self.window # 每秒f0点数
|
tf0 = self.sr // self.window # 每秒f0点数
|
||||||
@@ -118,6 +161,8 @@ class VC(object):
|
|||||||
index,
|
index,
|
||||||
big_npy,
|
big_npy,
|
||||||
index_rate,
|
index_rate,
|
||||||
|
version,
|
||||||
|
protect,
|
||||||
): # ,file_index,file_big_npy
|
): # ,file_index,file_big_npy
|
||||||
feats = torch.from_numpy(audio0)
|
feats = torch.from_numpy(audio0)
|
||||||
if self.is_half:
|
if self.is_half:
|
||||||
@@ -133,13 +178,14 @@ class VC(object):
|
|||||||
inputs = {
|
inputs = {
|
||||||
"source": feats.to(self.device),
|
"source": feats.to(self.device),
|
||||||
"padding_mask": padding_mask,
|
"padding_mask": padding_mask,
|
||||||
"output_layer": 9, # layer 9
|
"output_layer": 9 if version == "v1" else 12,
|
||||||
}
|
}
|
||||||
t0 = ttime()
|
t0 = ttime()
|
||||||
with torch.no_grad():
|
with torch.no_grad():
|
||||||
logits = model.extract_features(**inputs)
|
logits = model.extract_features(**inputs)
|
||||||
feats = model.final_proj(logits[0])
|
feats = model.final_proj(logits[0]) if version == "v1" else logits[0]
|
||||||
|
if protect < 0.5:
|
||||||
|
feats0 = feats.clone()
|
||||||
if (
|
if (
|
||||||
isinstance(index, type(None)) == False
|
isinstance(index, type(None)) == False
|
||||||
and isinstance(big_npy, type(None)) == False
|
and isinstance(big_npy, type(None)) == False
|
||||||
@@ -165,6 +211,10 @@ class VC(object):
|
|||||||
)
|
)
|
||||||
|
|
||||||
feats = F.interpolate(feats.permute(0, 2, 1), scale_factor=2).permute(0, 2, 1)
|
feats = F.interpolate(feats.permute(0, 2, 1), scale_factor=2).permute(0, 2, 1)
|
||||||
|
if protect < 0.5:
|
||||||
|
feats0 = F.interpolate(feats0.permute(0, 2, 1), scale_factor=2).permute(
|
||||||
|
0, 2, 1
|
||||||
|
)
|
||||||
t1 = ttime()
|
t1 = ttime()
|
||||||
p_len = audio0.shape[0] // self.window
|
p_len = audio0.shape[0] // self.window
|
||||||
if feats.shape[1] < p_len:
|
if feats.shape[1] < p_len:
|
||||||
@@ -172,21 +222,26 @@ class VC(object):
|
|||||||
if pitch != None and pitchf != None:
|
if pitch != None and pitchf != None:
|
||||||
pitch = pitch[:, :p_len]
|
pitch = pitch[:, :p_len]
|
||||||
pitchf = pitchf[:, :p_len]
|
pitchf = pitchf[:, :p_len]
|
||||||
|
|
||||||
|
if protect < 0.5:
|
||||||
|
pitchff = pitchf.clone()
|
||||||
|
pitchff[pitchf > 0] = 1
|
||||||
|
pitchff[pitchf < 1] = protect
|
||||||
|
pitchff = pitchff.unsqueeze(-1)
|
||||||
|
feats = feats * pitchff + feats0 * (1 - pitchff)
|
||||||
|
feats = feats.to(feats0.dtype)
|
||||||
p_len = torch.tensor([p_len], device=self.device).long()
|
p_len = torch.tensor([p_len], device=self.device).long()
|
||||||
with torch.no_grad():
|
with torch.no_grad():
|
||||||
if pitch != None and pitchf != None:
|
if pitch != None and pitchf != None:
|
||||||
audio1 = (
|
audio1 = (
|
||||||
(net_g.infer(feats, p_len, pitch, pitchf, sid)[0][0, 0] * 32768)
|
(net_g.infer(feats, p_len, pitch, pitchf, sid)[0][0, 0])
|
||||||
.data.cpu()
|
.data.cpu()
|
||||||
.float()
|
.float()
|
||||||
.numpy()
|
.numpy()
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
audio1 = (
|
audio1 = (
|
||||||
(net_g.infer(feats, p_len, sid)[0][0, 0] * 32768)
|
(net_g.infer(feats, p_len, sid)[0][0, 0]).data.cpu().float().numpy()
|
||||||
.data.cpu()
|
|
||||||
.float()
|
|
||||||
.numpy()
|
|
||||||
)
|
)
|
||||||
del feats, p_len, padding_mask
|
del feats, p_len, padding_mask
|
||||||
if torch.cuda.is_available():
|
if torch.cuda.is_available():
|
||||||
@@ -213,6 +268,9 @@ class VC(object):
|
|||||||
filter_radius,
|
filter_radius,
|
||||||
tgt_sr,
|
tgt_sr,
|
||||||
resample_sr,
|
resample_sr,
|
||||||
|
rms_mix_rate,
|
||||||
|
version,
|
||||||
|
protect,
|
||||||
f0_file=None,
|
f0_file=None,
|
||||||
):
|
):
|
||||||
if (
|
if (
|
||||||
@@ -299,6 +357,8 @@ class VC(object):
|
|||||||
index,
|
index,
|
||||||
big_npy,
|
big_npy,
|
||||||
index_rate,
|
index_rate,
|
||||||
|
version,
|
||||||
|
protect,
|
||||||
)[self.t_pad_tgt : -self.t_pad_tgt]
|
)[self.t_pad_tgt : -self.t_pad_tgt]
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@@ -314,6 +374,8 @@ class VC(object):
|
|||||||
index,
|
index,
|
||||||
big_npy,
|
big_npy,
|
||||||
index_rate,
|
index_rate,
|
||||||
|
version,
|
||||||
|
protect,
|
||||||
)[self.t_pad_tgt : -self.t_pad_tgt]
|
)[self.t_pad_tgt : -self.t_pad_tgt]
|
||||||
)
|
)
|
||||||
s = t
|
s = t
|
||||||
@@ -330,6 +392,8 @@ class VC(object):
|
|||||||
index,
|
index,
|
||||||
big_npy,
|
big_npy,
|
||||||
index_rate,
|
index_rate,
|
||||||
|
version,
|
||||||
|
protect,
|
||||||
)[self.t_pad_tgt : -self.t_pad_tgt]
|
)[self.t_pad_tgt : -self.t_pad_tgt]
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@@ -345,14 +409,22 @@ class VC(object):
|
|||||||
index,
|
index,
|
||||||
big_npy,
|
big_npy,
|
||||||
index_rate,
|
index_rate,
|
||||||
|
version,
|
||||||
|
protect,
|
||||||
)[self.t_pad_tgt : -self.t_pad_tgt]
|
)[self.t_pad_tgt : -self.t_pad_tgt]
|
||||||
)
|
)
|
||||||
audio_opt = np.concatenate(audio_opt)
|
audio_opt = np.concatenate(audio_opt)
|
||||||
|
if rms_mix_rate != 1:
|
||||||
|
audio_opt = change_rms(audio, 16000, audio_opt, tgt_sr, rms_mix_rate)
|
||||||
if resample_sr >= 16000 and tgt_sr != resample_sr:
|
if resample_sr >= 16000 and tgt_sr != resample_sr:
|
||||||
audio_opt = librosa.resample(
|
audio_opt = librosa.resample(
|
||||||
audio_opt, orig_sr=tgt_sr, target_sr=resample_sr
|
audio_opt, orig_sr=tgt_sr, target_sr=resample_sr
|
||||||
)
|
)
|
||||||
audio_opt = audio_opt.astype(np.int16)
|
audio_max = np.abs(audio_opt).max() / 0.99
|
||||||
|
max_int16 = 32768
|
||||||
|
if audio_max > 1:
|
||||||
|
max_int16 /= audio_max
|
||||||
|
audio_opt = (audio_opt * max_int16).astype(np.int16)
|
||||||
del pitch, pitchf, sid
|
del pitch, pitchf, sid
|
||||||
if torch.cuda.is_available():
|
if torch.cuda.is_available():
|
||||||
torch.cuda.empty_cache()
|
torch.cuda.empty_cache()
|
||||||
|
|||||||
Reference in New Issue
Block a user