This commit is contained in:
nadare 2023-07-07 08:57:23 +09:00
commit d4f80eeaa8
61 changed files with 2570 additions and 571 deletions

View File

@ -4,6 +4,11 @@
## What's New!
- v.1.5.3.8a
- Bugfix(test): force client device samplerate
- Bugfix: server device filter
- v.1.5.3.8
- RVC: performance improvement ([PR](https://github.com/w-okada/voice-changer/pull/371) from [nadare881](https://github.com/nadare881))
@ -15,33 +20,6 @@
- Bugfix:
- device output recorder button is showed in server device mode.
- v.1.5.3.6a
- some bugfix
- onnx export
- server device mode sampling rate
- server device io record
- improve gui
- dml gpu switch
- v.1.5.3.6
- Integrate Voice Changer model into new GUI
- mac: onnx framework version changed. 1.15.1 -> 1.13.1
- some bugfix
- v.1.5.3.5a
- some bugfix
- onnxcuda: onnx framework version changed. 1.15.1 -> 1.13.1
- rvc quality processing failed.
- model upload issue.
- and others.
- v.1.5.3.5
- RVC: new GUI released. Other VCs will be migrated to the new GUI in stages.
# VC Client とは
1. 各種音声変換 AI(VC, Voice Conversion)を用いてリアルタイム音声変換を行うためのクライアントソフトウェアです。サポートしている音声変換 AI は次のものになります。
@ -94,26 +72,17 @@
- ダウンロードはこちらから。
| Version | OS | フレームワーク | link | サポート VC | サイズ |
| ---------- | --- | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | ------ |
| v.1.5.3.8 | mac | ONNX(cpu), PyTorch(cpu,mps) | [normal](https://drive.google.com/uc?id=1ptmjFCRDW7M0l80072JVRII5tJpF13__&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC | 794MB |
| | win | ONNX(cpu,DirectML), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=19DfeACmpnzqCVH5bIoFunS2pGPABRuso&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3122MB |
| | win | ONNX(cpu,cuda), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1AYP_hMdoeacX0KiF31Vd3oEjxwdreSbM&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3237MB |
| v.1.5.3.7 | mac | ONNX(cpu), PyTorch(cpu,mps) | [normal](https://drive.google.com/uc?id=1HdJwgo0__vR6pAkOkekejUZJ0lu2NfDs&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC | 794MB |
| | win | ONNX(cpu,cuda), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1JIF4PvKg-8HNUv_fMaXSM3AeYa-F_c4z&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3237MB |
| | win | ONNX(cpu,DirectML), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1cJzRHmD3vk6av0Dvwj3v9Ef5KUsQYhKv&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3122MB |
| v.1.5.3.6a | mac | ONNX(cpu), PyTorch(cpu,mps) | [normal](https://drive.google.com/uc?id=14Q2_CPE3mZFU5PIq8RzYwuIX3XSQRTPD&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC | 794MB |
| | win | ONNX(cpu,cuda), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=18iO2JFyytBMFtcBZV5LENEzMGwEmL9H4&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3237MB |
| | win | ONNX(cpu,DirectML), PyTorch(cpu,cuda) \*2 | [normal](https://drive.google.com/uc?id=1PBrIuKQmhM3n1yOBJGgfojCDUt9P9MGa&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3122MB |
| v.1.5.3.6 | mac | ONNX(cpu), PyTorch(cpu,mps) | [google](https://drive.google.com/uc?id=1TNCFxx3FKluz-EYV8kutISnp_gbkE43U&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC | 794MB |
| | win | ONNX(cpu,cuda), PyTorch(cpu,cuda) | [google](https://drive.google.com/uc?id=1Q36yYVTi1hVUvim2WZFZAEuY4ItR9L9i&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3235MB |
| | win | ONNX(cpu,DirectML), PyTorch(cpu,cuda)\*2 | [google](https://drive.google.com/uc?id=1tJA7GQA07weSAQofbNax-Y0Wak_zEFlP&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3120MB |
| v.1.5.3.5a | mac | ONNX(cpu), PyTorch(cpu,mps) | [normal](https://drive.google.com/uc?id=1CDngewM_1xo8HgJ5oT6qqhhmgUUhiSdz&export=download), [hugging_face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC | 785MB |
| | win | ONNX(cpu,cuda), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1Tc1qvJIGF79cXCKDnZP4bGYXVg7OgJHp&export=download), [hugging_face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3236MB |
| | win | ONNX(cpu,DirectML), PyTorch(cpu,cuda)\*2 | [normal](https://drive.google.com/uc?id=1dibo9F09V1n6DyBBw0qmBm5hCRoXoo12&export=download), [hugging_face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3121MB |
| v.1.5.3.5 | mac | ONNX(cpu), PyTorch(cpu,mps) | [normal](https://drive.google.com/uc?id=1X4_zYe72yo3RnVHC1G5SZs8CRzlBiMPf&export=download), [hugging_face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC | 785MB |
| | win | ONNX(cpu,cuda), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1SeMiX3ZSyewsLKDptpRDlVD6j0htpKaJ&export=download), [hugging_face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3243MB |
| | win | ONNX(cpu,DirectML), PyTorch(cpu,cuda) \*2 | [normal](https://drive.google.com/uc?id=1FTWrKybOnOKp3yA8PGfQNV-OdyEAqpvx&export=download), [hugging_face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3121MB |
| Version | OS | フレームワーク | link | サポート VC | サイズ |
| ---------- | --- | ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | ------ |
| v.1.5.3.8a | mac | ONNX(cpu), PyTorch(cpu,mps) | [normal](https://drive.google.com/uc?id=1hg6lynE3wWJTNTParTa2qB2L06OL9KJ9&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC | 794MB |
| | win | ONNX(cpu,DirectML), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1C9PCu8pdafO6jJ2yCaB7x54Ls7LcM0Xc&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3122MB |
| | win | ONNX(cpu,cuda), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1bzrGhHPc9GdaRAMxkksTGtbuRLEeBx9i&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3237MB |
| v.1.5.3.8 | mac | ONNX(cpu), PyTorch(cpu,mps) | [normal](https://drive.google.com/uc?id=1ptmjFCRDW7M0l80072JVRII5tJpF13__&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC | 794MB |
| | win | ONNX(cpu,DirectML), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=19DfeACmpnzqCVH5bIoFunS2pGPABRuso&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3122MB |
| | win | ONNX(cpu,cuda), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1AYP_hMdoeacX0KiF31Vd3oEjxwdreSbM&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3237MB |
| v.1.5.3.7 | mac | ONNX(cpu), PyTorch(cpu,mps) | [normal](https://drive.google.com/uc?id=1HdJwgo0__vR6pAkOkekejUZJ0lu2NfDs&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC | 794MB |
| | win | ONNX(cpu,cuda), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1JIF4PvKg-8HNUv_fMaXSM3AeYa-F_c4z&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3237MB |
| | win | ONNX(cpu,DirectML), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1cJzRHmD3vk6av0Dvwj3v9Ef5KUsQYhKv&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3122MB |
(\*1) Google Drive からダウンロードできない方は[hugging_face](https://huggingface.co/wok000/vcclient000/tree/main)からダウンロードしてみてください
(\*2) 開発者が AMD のグラフィックボードを持っていないので動作確認していません。onnxruntime-directml を同梱しただけのものです。

View File

@ -4,6 +4,11 @@
## What's New!
- v.1.5.3.8a
- Bugfix(test): force client device samplerate
- Bugfix: server device filter
- v.1.5.3.8
- RVC: performance improvement ([PR](https://github.com/w-okada/voice-changer/pull/371) from [nadare881](https://github.com/nadare881))
@ -15,33 +20,6 @@
- Bugfix:
- device output recorder button is showed in server device mode.
- v.1.5.3.6a
- some bugfix
- onnx export
- server device mode sampling rate
- server device io record
- improve gui
- dml gpu switch
- v.1.5.3.6
- Integrate Voice Changer model into new GUI
- mac: onnx framework version changed. 1.15.1 -> 1.13.1
- some bugfix
- v.1.5.3.5a
- some bugfix
- onnxcuda: onnx framework version changed. 1.15.1 -> 1.13.1
- rvc quality processing failed.
- model upload issue.
- and others.
- v.1.5.3.5
- RVC: new GUI released. Other VCs will be migrated to the new GUI in stages.
# What is VC Client
1. This is a client software for performing real-time voice conversion using various Voice Conversion (VC) AI. The supported AI for voice conversion are as follows.
@ -91,26 +69,17 @@ It can be used in two main ways, in order of difficulty:
- Download (When you cannot download from google drive, try [hugging_face](https://huggingface.co/wok000/vcclient000/tree/main))
| Version | OS | Framework | link | support VC | size |
| ---------- | --- | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | ------ |
| v.1.5.3.8 | mac | ONNX(cpu), PyTorch(cpu,mps) | [normal](https://drive.google.com/uc?id=1ptmjFCRDW7M0l80072JVRII5tJpF13__&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC | 794MB |
| | win | ONNX(cpu,DirectML), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=19DfeACmpnzqCVH5bIoFunS2pGPABRuso&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3122MB |
| | win | ONNX(cpu,cuda), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1AYP_hMdoeacX0KiF31Vd3oEjxwdreSbM&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3237MB |
| v.1.5.3.7 | mac | ONNX(cpu), PyTorch(cpu,mps) | [normal](https://drive.google.com/uc?id=1HdJwgo0__vR6pAkOkekejUZJ0lu2NfDs&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC | 794MB |
| | win | ONNX(cpu,cuda), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1JIF4PvKg-8HNUv_fMaXSM3AeYa-F_c4z&export=download) , [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3237MB |
| | win | ONNX(cpu,DirectML), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1cJzRHmD3vk6av0Dvwj3v9Ef5KUsQYhKv&export=download) , [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3122MB |
| v.1.5.3.6a | mac | ONNX(cpu), PyTorch(cpu,mps) | [normal](https://drive.google.com/uc?id=14Q2_CPE3mZFU5PIq8RzYwuIX3XSQRTPD&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC | 794MB |
| | win | ONNX(cpu,cuda), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=18iO2JFyytBMFtcBZV5LENEzMGwEmL9H4&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3237MB |
| | win | ONNX(cpu,DirectML), PyTorch(cpu,cuda) \*2 | [normal](https://drive.google.com/uc?id=1PBrIuKQmhM3n1yOBJGgfojCDUt9P9MGa&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3122MB |
| v.1.5.3.6 | mac | ONNX(cpu), PyTorch(cpu,mps) | [google](https://drive.google.com/uc?id=1TNCFxx3FKluz-EYV8kutISnp_gbkE43U&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC | 794MB |
| | win | ONNX(cpu,cuda), PyTorch(cpu,cuda) | [google](https://drive.google.com/uc?id=1Q36yYVTi1hVUvim2WZFZAEuY4ItR9L9i&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3235MB |
| | win | ONNX(cpu,DirectML), PyTorch(cpu,cuda) \*2 | [google](https://drive.google.com/uc?id=1tJA7GQA07weSAQofbNax-Y0Wak_zEFlP&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3120MB |
| v.1.5.3.5a | mac | ONNX(cpu), PyTorch(cpu,mps) | [normal](https://drive.google.com/uc?id=1CDngewM_1xo8HgJ5oT6qqhhmgUUhiSdz&export=download), [hugging_face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC | 785MB |
| | win | ONNX(cpu,cuda), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1Tc1qvJIGF79cXCKDnZP4bGYXVg7OgJHp&export=download), [hugging_face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3236MB |
| | win | ONNX(cpu,DirectML), PyTorch(cpu,cuda)\*2 | [normal](https://drive.google.com/uc?id=1dibo9F09V1n6DyBBw0qmBm5hCRoXoo12&export=download), [hugging_face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3121MB |
| v.1.5.3.5 | mac | ONNX(cpu), PyTorch(cpu,mps) | [normal](https://drive.google.com/uc?id=1X4_zYe72yo3RnVHC1G5SZs8CRzlBiMPf&export=download), [hugging_face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC | 785MB |
| | win | ONNX(cpu,cuda), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1SeMiX3ZSyewsLKDptpRDlVD6j0htpKaJ&export=download), [hugging_face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3243MB |
| | win | ONNX(cpu,DirectML), PyTorch(cpu,cuda) \*2 | [normal](https://drive.google.com/uc?id=1FTWrKybOnOKp3yA8PGfQNV-OdyEAqpvx&export=download), [hugging_face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3121MB |
| Version | OS | Framework | link | support VC | size |
| ---------- | --- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | ------ |
| v.1.5.3.8a | mac | ONNX(cpu), PyTorch(cpu,mps) | [normal](https://drive.google.com/uc?id=1hg6lynE3wWJTNTParTa2qB2L06OL9KJ9&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC | 794MB |
| | win | ONNX(cpu,DirectML), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1C9PCu8pdafO6jJ2yCaB7x54Ls7LcM0Xc&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3122MB |
| | win | ONNX(cpu,cuda), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1bzrGhHPc9GdaRAMxkksTGtbuRLEeBx9i&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3237MB |
| v.1.5.3.8 | mac | ONNX(cpu), PyTorch(cpu,mps) | [normal](https://drive.google.com/uc?id=1ptmjFCRDW7M0l80072JVRII5tJpF13__&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC | 794MB |
| | win | ONNX(cpu,DirectML), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=19DfeACmpnzqCVH5bIoFunS2pGPABRuso&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3122MB |
| | win | ONNX(cpu,cuda), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1AYP_hMdoeacX0KiF31Vd3oEjxwdreSbM&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3237MB |
| v.1.5.3.7 | mac | ONNX(cpu), PyTorch(cpu,mps) | [normal](https://drive.google.com/uc?id=1HdJwgo0__vR6pAkOkekejUZJ0lu2NfDs&export=download), [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC | 794MB |
| | win | ONNX(cpu,cuda), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1JIF4PvKg-8HNUv_fMaXSM3AeYa-F_c4z&export=download) , [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3237MB |
| | win | ONNX(cpu,DirectML), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1cJzRHmD3vk6av0Dvwj3v9Ef5KUsQYhKv&export=download) , [hugging face](https://huggingface.co/wok000/vcclient000/tree/main) | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC, DDSP-SVC | 3122MB |
(\*1) You can also download from [hugging_face](https://huggingface.co/wok000/vcclient000/tree/main)
(\*2) The developer does not have an AMD graphics card, so it has not been tested. This package only includes onnxruntime-directml.

View File

@ -21,7 +21,7 @@
{
"name": "configArea",
"options": {
"detectors": ["dio", "harvest", "crepe"],
"detectors": ["dio", "harvest", "crepe", "crepe_full", "crepe_tiny"],
"inputChunkNums": [8, 16, 24, 32, 40, 48, 64, 80, 96, 112, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024, 2048]
}
}

View File

@ -1 +1,10 @@
<!doctype html><html style="width:100%;height:100%;overflow:hidden"><head><meta charset="utf-8"/><title>Voice Changer Client Demo</title><script defer="defer" src="index.js"></script></head><body style="width:100%;height:100%;margin:0"><div id="app" style="width:100%;height:100%"></div></body></html>
<!DOCTYPE html>
<html style="width: 100%; height: 100%; overflow: hidden">
<head>
<meta charset="utf-8" />
<title>Voice Changer Client Demo</title>
<script defer src="index.js"></script></head>
<body style="width: 100%; height: 100%; margin: 0px">
<div id="app" style="width: 100%; height: 100%"></div>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@ -1,31 +0,0 @@
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

View File

@ -9,7 +9,7 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"@dannadori/voice-changer-client-js": "^1.0.157",
"@dannadori/voice-changer-client-js": "^1.0.159",
"@fortawesome/fontawesome-svg-core": "^6.4.0",
"@fortawesome/free-brands-svg-icons": "^6.4.0",
"@fortawesome/free-regular-svg-icons": "^6.4.0",
@ -19,9 +19,9 @@
"react-dom": "^18.2.0"
},
"devDependencies": {
"@babel/core": "^7.22.5",
"@babel/plugin-transform-runtime": "^7.22.5",
"@babel/preset-env": "^7.22.5",
"@babel/core": "^7.22.6",
"@babel/plugin-transform-runtime": "^7.22.6",
"@babel/preset-env": "^7.22.6",
"@babel/preset-react": "^7.22.5",
"@babel/preset-typescript": "^7.22.5",
"@types/node": "^20.3.3",
@ -888,35 +888,35 @@
}
},
"node_modules/@babel/compat-data": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.5.tgz",
"integrity": "sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.6.tgz",
"integrity": "sha512-29tfsWTq2Ftu7MXmimyC0C5FDZv5DYxOZkh3XD3+QW4V/BYuv/LyEsjj3c0hqedEaDt6DBfDvexMKU8YevdqFg==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/core": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.5.tgz",
"integrity": "sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.6.tgz",
"integrity": "sha512-HPIyDa6n+HKw5dEuway3vVAhBboYCtREBMp+IWeseZy6TFtzn6MHkCH2KKYUOC/vKKwgSMHQW4htBOrmuRPXfw==",
"dev": true,
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.22.5",
"@babel/generator": "^7.22.5",
"@babel/helper-compilation-targets": "^7.22.5",
"@babel/helper-compilation-targets": "^7.22.6",
"@babel/helper-module-transforms": "^7.22.5",
"@babel/helpers": "^7.22.5",
"@babel/parser": "^7.22.5",
"@babel/helpers": "^7.22.6",
"@babel/parser": "^7.22.6",
"@babel/template": "^7.22.5",
"@babel/traverse": "^7.22.5",
"@babel/traverse": "^7.22.6",
"@babel/types": "^7.22.5",
"@nicolo-ribaudo/semver-v6": "^6.3.3",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
"json5": "^2.2.2",
"semver": "^6.3.0"
"json5": "^2.2.2"
},
"engines": {
"node": ">=6.9.0"
@ -966,16 +966,16 @@
}
},
"node_modules/@babel/helper-compilation-targets": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.5.tgz",
"integrity": "sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.6.tgz",
"integrity": "sha512-534sYEqWD9VfUm3IPn2SLcH4Q3P86XL+QvqdC7ZsFrzyyPF3T4XGiVghF6PTYNdWg6pXuoqXxNQAhbYeEInTzA==",
"dev": true,
"dependencies": {
"@babel/compat-data": "^7.22.5",
"@babel/compat-data": "^7.22.6",
"@babel/helper-validator-option": "^7.22.5",
"browserslist": "^4.21.3",
"lru-cache": "^5.1.1",
"semver": "^6.3.0"
"@nicolo-ribaudo/semver-v6": "^6.3.3",
"browserslist": "^4.21.9",
"lru-cache": "^5.1.1"
},
"engines": {
"node": ">=6.9.0"
@ -985,9 +985,9 @@
}
},
"node_modules/@babel/helper-create-class-features-plugin": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.5.tgz",
"integrity": "sha512-xkb58MyOYIslxu3gKmVXmjTtUPvBU4odYzbiIQbWwLKIHCsx6UGZGX6F1IznMFVnDdirseUZopzN+ZRt8Xb33Q==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.6.tgz",
"integrity": "sha512-iwdzgtSiBxF6ni6mzVnZCF3xt5qE6cEA0J7nFt8QOAWZ0zjCFceEgpn3vtb2V7WFR6QzP2jmIFOHMTRo7eNJjQ==",
"dev": true,
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.22.5",
@ -997,8 +997,8 @@
"@babel/helper-optimise-call-expression": "^7.22.5",
"@babel/helper-replace-supers": "^7.22.5",
"@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.5",
"semver": "^6.3.0"
"@babel/helper-split-export-declaration": "^7.22.6",
"@nicolo-ribaudo/semver-v6": "^6.3.3"
},
"engines": {
"node": ">=6.9.0"
@ -1008,14 +1008,14 @@
}
},
"node_modules/@babel/helper-create-regexp-features-plugin": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.5.tgz",
"integrity": "sha512-1VpEFOIbMRaXyDeUwUfmTIxExLwQ+zkW+Bh5zXpApA3oQedBx9v/updixWxnx/bZpKw7u8VxWjb/qWpIcmPq8A==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.6.tgz",
"integrity": "sha512-nBookhLKxAWo/TUCmhnaEJyLz2dekjQvv5SRpE9epWQBcpedWLKt8aZdsuT9XV5ovzR3fENLjRXVT0GsSlGGhA==",
"dev": true,
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.22.5",
"regexpu-core": "^5.3.1",
"semver": "^6.3.0"
"@nicolo-ribaudo/semver-v6": "^6.3.3",
"regexpu-core": "^5.3.1"
},
"engines": {
"node": ">=6.9.0"
@ -1199,9 +1199,9 @@
}
},
"node_modules/@babel/helper-split-export-declaration": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.5.tgz",
"integrity": "sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
"integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
"dev": true,
"dependencies": {
"@babel/types": "^7.22.5"
@ -1253,13 +1253,13 @@
}
},
"node_modules/@babel/helpers": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.5.tgz",
"integrity": "sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz",
"integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==",
"dev": true,
"dependencies": {
"@babel/template": "^7.22.5",
"@babel/traverse": "^7.22.5",
"@babel/traverse": "^7.22.6",
"@babel/types": "^7.22.5"
},
"engines": {
@ -1281,9 +1281,9 @@
}
},
"node_modules/@babel/parser": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.5.tgz",
"integrity": "sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.6.tgz",
"integrity": "sha512-EIQu22vNkceq3LbjAq7knDf/UmtI2qbcNI8GRBlijez6TpQLvSodJPYfydQmNA5buwkxxxa/PVI44jjYZ+/cLw==",
"dev": true,
"bin": {
"parser": "bin/babel-parser.js"
@ -1731,19 +1731,19 @@
}
},
"node_modules/@babel/plugin-transform-classes": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.5.tgz",
"integrity": "sha512-2edQhLfibpWpsVBx2n/GKOz6JdGQvLruZQfGr9l1qes2KQaWswjBzhQF7UDUZMNaMMQeYnQzxwOMPsbYF7wqPQ==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.6.tgz",
"integrity": "sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ==",
"dev": true,
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.22.5",
"@babel/helper-compilation-targets": "^7.22.5",
"@babel/helper-compilation-targets": "^7.22.6",
"@babel/helper-environment-visitor": "^7.22.5",
"@babel/helper-function-name": "^7.22.5",
"@babel/helper-optimise-call-expression": "^7.22.5",
"@babel/helper-plugin-utils": "^7.22.5",
"@babel/helper-replace-supers": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6",
"globals": "^11.1.0"
},
"engines": {
@ -2139,9 +2139,9 @@
}
},
"node_modules/@babel/plugin-transform-optional-chaining": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.5.tgz",
"integrity": "sha512-AconbMKOMkyG+xCng2JogMCDcqW8wedQAqpVIL4cOSescZ7+iW8utC6YDZLMCSUIReEA733gzRSaOSXMAt/4WQ==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.6.tgz",
"integrity": "sha512-Vd5HiWml0mDVtcLHIoEU5sw6HOUW/Zk0acLs/SAeuLzkGNOPc9DB4nkUajemhCmTIz3eiaKREZn2hQQqF79YTg==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5",
@ -2316,17 +2316,17 @@
}
},
"node_modules/@babel/plugin-transform-runtime": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.5.tgz",
"integrity": "sha512-bg4Wxd1FWeFx3daHFTWk1pkSWK/AyQuiyAoeZAOkAOUBjnZPH6KT7eMxouV47tQ6hl6ax2zyAWBdWZXbrvXlaw==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.6.tgz",
"integrity": "sha512-+AGkst7Kqq3QUflKGkhWWMRb9vaKamoreNmYc+sjsIpOp+TsyU0exhp3RlwjQa/HdlKkPt3AMDwfg8Hpt9Vwqg==",
"dev": true,
"dependencies": {
"@babel/helper-module-imports": "^7.22.5",
"@babel/helper-plugin-utils": "^7.22.5",
"@nicolo-ribaudo/semver-v6": "^6.3.3",
"babel-plugin-polyfill-corejs2": "^0.4.3",
"babel-plugin-polyfill-corejs3": "^0.8.1",
"babel-plugin-polyfill-regenerator": "^0.5.0",
"semver": "^6.3.0"
"babel-plugin-polyfill-regenerator": "^0.5.0"
},
"engines": {
"node": ">=6.9.0"
@ -2493,13 +2493,13 @@
}
},
"node_modules/@babel/preset-env": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.5.tgz",
"integrity": "sha512-fj06hw89dpiZzGZtxn+QybifF07nNiZjZ7sazs2aVDcysAZVGjW7+7iFYxg6GLNM47R/thYfLdrXc+2f11Vi9A==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.6.tgz",
"integrity": "sha512-IHr0AXHGk8oh8HYSs45Mxuv6iySUBwDTIzJSnXN7PURqHdxJVQlCoXmKJgyvSS9bcNf9NVRVE35z+LkCvGmi6w==",
"dev": true,
"dependencies": {
"@babel/compat-data": "^7.22.5",
"@babel/helper-compilation-targets": "^7.22.5",
"@babel/compat-data": "^7.22.6",
"@babel/helper-compilation-targets": "^7.22.6",
"@babel/helper-plugin-utils": "^7.22.5",
"@babel/helper-validator-option": "^7.22.5",
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.5",
@ -2530,7 +2530,7 @@
"@babel/plugin-transform-block-scoping": "^7.22.5",
"@babel/plugin-transform-class-properties": "^7.22.5",
"@babel/plugin-transform-class-static-block": "^7.22.5",
"@babel/plugin-transform-classes": "^7.22.5",
"@babel/plugin-transform-classes": "^7.22.6",
"@babel/plugin-transform-computed-properties": "^7.22.5",
"@babel/plugin-transform-destructuring": "^7.22.5",
"@babel/plugin-transform-dotall-regex": "^7.22.5",
@ -2555,7 +2555,7 @@
"@babel/plugin-transform-object-rest-spread": "^7.22.5",
"@babel/plugin-transform-object-super": "^7.22.5",
"@babel/plugin-transform-optional-catch-binding": "^7.22.5",
"@babel/plugin-transform-optional-chaining": "^7.22.5",
"@babel/plugin-transform-optional-chaining": "^7.22.6",
"@babel/plugin-transform-parameters": "^7.22.5",
"@babel/plugin-transform-private-methods": "^7.22.5",
"@babel/plugin-transform-private-property-in-object": "^7.22.5",
@ -2573,11 +2573,11 @@
"@babel/plugin-transform-unicode-sets-regex": "^7.22.5",
"@babel/preset-modules": "^0.1.5",
"@babel/types": "^7.22.5",
"@nicolo-ribaudo/semver-v6": "^6.3.3",
"babel-plugin-polyfill-corejs2": "^0.4.3",
"babel-plugin-polyfill-corejs3": "^0.8.1",
"babel-plugin-polyfill-regenerator": "^0.5.0",
"core-js-compat": "^3.30.2",
"semver": "^6.3.0"
"core-js-compat": "^3.31.0"
},
"engines": {
"node": ">=6.9.0"
@ -2648,9 +2648,9 @@
"dev": true
},
"node_modules/@babel/runtime": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz",
"integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
"integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
"dev": true,
"dependencies": {
"regenerator-runtime": "^0.13.11"
@ -2674,9 +2674,9 @@
}
},
"node_modules/@babel/traverse": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.5.tgz",
"integrity": "sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.6.tgz",
"integrity": "sha512-53CijMvKlLIDlOTrdWiHileRddlIiwUIyCKqYa7lYnnPldXCG5dUSN38uT0cA6i7rHWNKJLH0VU/Kxdr1GzB3w==",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.22.5",
@ -2684,8 +2684,8 @@
"@babel/helper-environment-visitor": "^7.22.5",
"@babel/helper-function-name": "^7.22.5",
"@babel/helper-hoist-variables": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.5",
"@babel/parser": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6",
"@babel/parser": "^7.22.6",
"@babel/types": "^7.22.5",
"debug": "^4.1.0",
"globals": "^11.1.0"
@ -2709,9 +2709,9 @@
}
},
"node_modules/@dannadori/voice-changer-client-js": {
"version": "1.0.157",
"resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.157.tgz",
"integrity": "sha512-KIqgMM3cvB3ZCTLFJyfqWypMJZqFNTExTxoKO/BxqnG02EPG+AsHIHZE0bdTZEg1ss1tba/QMnWsoZ5FQW5YQQ==",
"version": "1.0.159",
"resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.159.tgz",
"integrity": "sha512-QQLh/djAm1FPcIUacxBhXGRlbCn6POpxTd8Wmc195I9MbtEqy+9mXmGBG5+du1ohGL7HmoHkvLmgB0nlKGLoZw==",
"dependencies": {
"@types/readable-stream": "^2.3.15",
"amazon-chime-sdk-js": "^3.15.0",
@ -2949,24 +2949,24 @@
}
},
"node_modules/@jest/schemas": {
"version": "29.4.3",
"resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz",
"integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==",
"version": "29.6.0",
"resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz",
"integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==",
"dev": true,
"dependencies": {
"@sinclair/typebox": "^0.25.16"
"@sinclair/typebox": "^0.27.8"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/types": {
"version": "29.5.0",
"resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz",
"integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==",
"version": "29.6.0",
"resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.0.tgz",
"integrity": "sha512-8XCgL9JhqbJTFnMRjEAO+TuW251+MoMd5BSzLiE3vvzpQ8RlBxy8NoyNkDhs3K3OL3HeVinlOl9or5p7GTeOLg==",
"dev": true,
"dependencies": {
"@jest/schemas": "^29.4.3",
"@jest/schemas": "^29.6.0",
"@types/istanbul-lib-coverage": "^2.0.0",
"@types/istanbul-reports": "^3.0.0",
"@types/node": "*",
@ -3080,10 +3080,14 @@
}
},
"node_modules/@jridgewell/source-map": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.4.tgz",
"integrity": "sha512-KE/SxsDqNs3rrWwFHcRh15ZLVFrI0YoZtgAdIyIq9k5hUNmiWRXXThPomIxHuL20sLdgzbDFyvkUMna14bvtrw==",
"dev": true
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz",
"integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==",
"dev": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.0",
"@jridgewell/trace-mapping": "^0.3.9"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.15",
@ -3113,6 +3117,15 @@
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
"dev": true
},
"node_modules/@nicolo-ribaudo/semver-v6": {
"version": "6.3.3",
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz",
"integrity": "sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@ -3213,9 +3226,9 @@
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
},
"node_modules/@sinclair/typebox": {
"version": "0.25.24",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz",
"integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==",
"version": "0.27.8",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
"integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
"dev": true
},
"node_modules/@smithy/abort-controller": {
@ -4977,9 +4990,9 @@
"dev": true
},
"node_modules/caniuse-lite": {
"version": "1.0.30001509",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001509.tgz",
"integrity": "sha512-2uDDk+TRiTX5hMcUYT/7CSyzMZxjfGu0vAUjS2g0LSD8UoXOv0LtpH4LxGMemsiPq6LCVIUjNwVM0erkOkGCDA==",
"version": "1.0.30001512",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001512.tgz",
"integrity": "sha512-2S9nK0G/mE+jasCUsMPlARhRCts1ebcp2Ji8Y8PWi4NDE1iRdLCnEPHkEfeBrGC45L4isBx5ur3IQ6yTE2mRZw==",
"dev": true,
"funding": [
{
@ -5670,9 +5683,9 @@
"dev": true
},
"node_modules/electron-to-chromium": {
"version": "1.4.447",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.447.tgz",
"integrity": "sha512-sxX0LXh+uL41hSJsujAN86PjhrV/6c79XmpY0TvjZStV6VxIgarf8SRkUoUTuYmFcZQTemsoqo8qXOGw5npWfw==",
"version": "1.4.450",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.450.tgz",
"integrity": "sha512-BLG5HxSELlrMx7dJ2s+8SFlsCtJp37Zpk2VAxyC6CZtbc+9AJeZHfYHbrlSgdXp6saQ8StMqOTEDaBKgA7u1sw==",
"dev": true
},
"node_modules/emoji-regex": {
@ -6888,9 +6901,9 @@
}
},
"node_modules/globby": {
"version": "13.2.0",
"resolved": "https://registry.npmjs.org/globby/-/globby-13.2.0.tgz",
"integrity": "sha512-jWsQfayf13NvqKUIL3Ta+CIqMnvlaIDFveWE/dpOZ9+3AMEJozsxDvKA02zync9UuvOM8rOXzsD5GqKP4OnWPQ==",
"version": "13.2.1",
"resolved": "https://registry.npmjs.org/globby/-/globby-13.2.1.tgz",
"integrity": "sha512-DPCBxctI7dN4EeIqjW2KGqgdcUMbrhJ9AzON+PlxCtvppWhubTLD4+a0GFxiym14ZvacUydTPjLPc2DlKz7EIg==",
"dev": true,
"dependencies": {
"dir-glob": "^3.0.1",
@ -7796,12 +7809,12 @@
}
},
"node_modules/jest-util": {
"version": "29.5.0",
"resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz",
"integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==",
"version": "29.6.0",
"resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.0.tgz",
"integrity": "sha512-S0USx9YwcvEm4pQ5suisVm/RVxBmi0GFR7ocJhIeaCuW5AXnAnffXbaVKvIFodyZNOc9ygzVtTxmBf40HsHXaA==",
"dev": true,
"dependencies": {
"@jest/types": "^29.5.0",
"@jest/types": "^29.6.0",
"@types/node": "*",
"chalk": "^4.0.0",
"ci-info": "^3.2.0",
@ -7883,13 +7896,13 @@
}
},
"node_modules/jest-worker": {
"version": "29.5.0",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz",
"integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==",
"version": "29.6.0",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.0.tgz",
"integrity": "sha512-oiQHH1SnKmZIwwPnpOrXTq4kHBk3lKGY/07DpnH0sAu+x7J8rXlbLDROZsU6vy9GwB0hPiZeZpu6YlJ48QoKcA==",
"dev": true,
"dependencies": {
"@types/node": "*",
"jest-util": "^29.5.0",
"jest-util": "^29.6.0",
"merge-stream": "^2.0.0",
"supports-color": "^8.0.0"
},
@ -7922,9 +7935,9 @@
}
},
"node_modules/jiti": {
"version": "1.18.2",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.18.2.tgz",
"integrity": "sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==",
"version": "1.19.1",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz",
"integrity": "sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==",
"dev": true,
"bin": {
"jiti": "bin/jiti.js"

View File

@ -21,9 +21,9 @@
"author": "wataru.okada@flect.co.jp",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.22.5",
"@babel/plugin-transform-runtime": "^7.22.5",
"@babel/preset-env": "^7.22.5",
"@babel/core": "^7.22.6",
"@babel/plugin-transform-runtime": "^7.22.6",
"@babel/preset-env": "^7.22.6",
"@babel/preset-react": "^7.22.5",
"@babel/preset-typescript": "^7.22.5",
"@types/node": "^20.3.3",
@ -54,7 +54,7 @@
"webpack-dev-server": "^4.15.1"
},
"dependencies": {
"@dannadori/voice-changer-client-js": "^1.0.157",
"@dannadori/voice-changer-client-js": "^1.0.159",
"@fortawesome/fontawesome-svg-core": "^6.4.0",
"@fortawesome/free-brands-svg-icons": "^6.4.0",
"@fortawesome/free-regular-svg-icons": "^6.4.0",

View File

@ -21,7 +21,7 @@
{
"name": "configArea",
"options": {
"detectors": ["dio", "harvest", "crepe"],
"detectors": ["dio", "harvest", "crepe", "crepe_full", "crepe_tiny"],
"inputChunkNums": [8, 16, 24, 32, 40, 48, 64, 80, 96, 112, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024, 2048]
}
}

View File

@ -3,15 +3,34 @@ import { useEffect, useState } from "react"
export type AudioConfigState = {
audioContext: AudioContext | null
}
export const useAudioConfig = (): AudioConfigState => {
const [audioContext, setAudioContext] = useState<AudioContext | null>(null)
useEffect(() => {
const createAudioContext = () => {
const ctx = new AudioContext()
const url = new URL(window.location.href);
const params = url.searchParams;
const sampleRate = params.get('sample_rate') || null
let ctx: AudioContext
if(sampleRate){
if(sampleRate == "default"){
console.log(`Sample rate: default`)
ctx = new AudioContext()
}else{
console.log(`Sample rate: ${sampleRate}`)
ctx = new AudioContext({ sampleRate: Number(sampleRate)})
}
}else{
console.log(`Sample rate: default(48000)`)
ctx = new AudioContext({ sampleRate: 48000})
}
console.log(ctx)
setAudioContext(ctx)
document.removeEventListener('touchstart', createAudioContext);
document.removeEventListener('mousedown', createAudioContext);
setAudioContext(ctx)
}
document.addEventListener('touchstart', createAudioContext, false);
document.addEventListener('mousedown', createAudioContext, false);

View File

@ -12,7 +12,6 @@ export const useVCClient = (props: UseVCClientProps): VCClientState => {
const clientState = useClient({
audioContext: props.audioContext
})
console.log("useVCClient", props.audioContext)
const ret: VCClientState = {
clientState

View File

@ -3,76 +3,78 @@ import { ReactNode } from "react";
import { useAppRoot } from "../../001_provider/001_AppRootProvider";
import { StateControlCheckbox, useStateControlCheckbox } from "../../hooks/useStateControlCheckbox";
export const OpenServerControlCheckbox = "open-server-control-checkbox"
export const OpenModelSettingCheckbox = "open-model-setting-checkbox"
export const OpenDeviceSettingCheckbox = "open-device-setting-checkbox"
export const OpenQualityControlCheckbox = "open-quality-control-checkbox"
export const OpenSpeakerSettingCheckbox = "open-speaker-setting-checkbox"
export const OpenConverterSettingCheckbox = "open-converter-setting-checkbox"
export const OpenAdvancedSettingCheckbox = "open-advanced-setting-checkbox"
export const OpenLabCheckbox = "open-lab-checkbox"
export const OpenServerControlCheckbox = "open-server-control-checkbox";
export const OpenModelSettingCheckbox = "open-model-setting-checkbox";
export const OpenDeviceSettingCheckbox = "open-device-setting-checkbox";
export const OpenQualityControlCheckbox = "open-quality-control-checkbox";
export const OpenSpeakerSettingCheckbox = "open-speaker-setting-checkbox";
export const OpenConverterSettingCheckbox = "open-converter-setting-checkbox";
export const OpenAdvancedSettingCheckbox = "open-advanced-setting-checkbox";
export const OpenLabCheckbox = "open-lab-checkbox";
export const OpenLicenseDialogCheckbox = "open-license-dialog-checkbox"
export const OpenWaitingDialogCheckbox = "open-waiting-dialog-checkbox"
export const OpenStartingNoticeDialogCheckbox = "open-starting-notice-dialog-checkbox"
export const OpenModelSlotManagerDialogCheckbox = "open-model-slot-manager-dialog-checkbox"
export const OpenMergeLabDialogCheckbox = "open-merge-lab-dialog-checkbox"
export const OpenAdvancedSettingDialogCheckbox = "open-advanced-setting-dialog-checkbox"
export const OpenGetServerInformationDialogCheckbox = "open-get-server-information-dialog-checkbox"
export const OpenLicenseDialogCheckbox = "open-license-dialog-checkbox";
export const OpenWaitingDialogCheckbox = "open-waiting-dialog-checkbox";
export const OpenStartingNoticeDialogCheckbox = "open-starting-notice-dialog-checkbox";
export const OpenModelSlotManagerDialogCheckbox = "open-model-slot-manager-dialog-checkbox";
export const OpenMergeLabDialogCheckbox = "open-merge-lab-dialog-checkbox";
export const OpenAdvancedSettingDialogCheckbox = "open-advanced-setting-dialog-checkbox";
export const OpenGetServerInformationDialogCheckbox = "open-get-server-information-dialog-checkbox";
export const OpenGetClientInformationDialogCheckbox = "open-get-client-information-dialog-checkbox";
export const OpenTextInputDialogCheckbox = "open-text-input-dialog-checkbox"
export const OpenTextInputDialogCheckbox = "open-text-input-dialog-checkbox";
type Props = {
children: ReactNode;
};
export type StateControls = {
openServerControlCheckbox: StateControlCheckbox
openModelSettingCheckbox: StateControlCheckbox
openDeviceSettingCheckbox: StateControlCheckbox
openQualityControlCheckbox: StateControlCheckbox
openSpeakerSettingCheckbox: StateControlCheckbox
openConverterSettingCheckbox: StateControlCheckbox
openAdvancedSettingCheckbox: StateControlCheckbox
openLabCheckbox: StateControlCheckbox
openServerControlCheckbox: StateControlCheckbox;
openModelSettingCheckbox: StateControlCheckbox;
openDeviceSettingCheckbox: StateControlCheckbox;
openQualityControlCheckbox: StateControlCheckbox;
openSpeakerSettingCheckbox: StateControlCheckbox;
openConverterSettingCheckbox: StateControlCheckbox;
openAdvancedSettingCheckbox: StateControlCheckbox;
openLabCheckbox: StateControlCheckbox;
showWaitingCheckbox: StateControlCheckbox
showStartingNoticeCheckbox: StateControlCheckbox
showModelSlotManagerCheckbox: StateControlCheckbox
showWaitingCheckbox: StateControlCheckbox;
showStartingNoticeCheckbox: StateControlCheckbox;
showModelSlotManagerCheckbox: StateControlCheckbox;
showMergeLabCheckbox: StateControlCheckbox
showAdvancedSettingCheckbox: StateControlCheckbox
showGetServerInformationCheckbox: StateControlCheckbox
showTextInputCheckbox: StateControlCheckbox
}
showMergeLabCheckbox: StateControlCheckbox;
showAdvancedSettingCheckbox: StateControlCheckbox;
showGetServerInformationCheckbox: StateControlCheckbox;
showGetClientInformationCheckbox: StateControlCheckbox;
showTextInputCheckbox: StateControlCheckbox;
};
type GuiStateAndMethod = {
stateControls: StateControls
isConverting: boolean,
isAnalyzing: boolean,
showPyTorchModelUpload: boolean
setIsConverting: (val: boolean) => void
setIsAnalyzing: (val: boolean) => void
setShowPyTorchModelUpload: (val: boolean) => void
stateControls: StateControls;
isConverting: boolean;
isAnalyzing: boolean;
showPyTorchModelUpload: boolean;
setIsConverting: (val: boolean) => void;
setIsAnalyzing: (val: boolean) => void;
setShowPyTorchModelUpload: (val: boolean) => void;
inputAudioDeviceInfo: MediaDeviceInfo[]
outputAudioDeviceInfo: MediaDeviceInfo[]
audioInputForGUI: string
audioOutputForGUI: string
fileInputEchoback: boolean | undefined
audioOutputForAnalyzer: string
setInputAudioDeviceInfo: (val: MediaDeviceInfo[]) => void
setOutputAudioDeviceInfo: (val: MediaDeviceInfo[]) => void
setAudioInputForGUI: (val: string) => void
setAudioOutputForGUI: (val: string) => void
setFileInputEchoback: (val: boolean) => void
setAudioOutputForAnalyzer: (val: string) => void
inputAudioDeviceInfo: MediaDeviceInfo[];
outputAudioDeviceInfo: MediaDeviceInfo[];
audioInputForGUI: string;
audioOutputForGUI: string;
fileInputEchoback: boolean | undefined;
audioOutputForAnalyzer: string;
setInputAudioDeviceInfo: (val: MediaDeviceInfo[]) => void;
setOutputAudioDeviceInfo: (val: MediaDeviceInfo[]) => void;
setAudioInputForGUI: (val: string) => void;
setAudioOutputForGUI: (val: string) => void;
setFileInputEchoback: (val: boolean) => void;
setAudioOutputForAnalyzer: (val: string) => void;
modelSlotNum: number
setModelSlotNum: (val: number) => void
modelSlotNum: number;
setModelSlotNum: (val: number) => void;
textInputResolve: TextInputResolveType | null
setTextInputResolve: (val: TextInputResolveType | null) => void
}
textInputResolve: TextInputResolveType | null;
setTextInputResolve: (val: TextInputResolveType | null) => void;
};
const GuiStateContext = React.createContext<GuiStateAndMethod | null>(null);
export const useGuiState = (): GuiStateAndMethod => {
@ -84,59 +86,64 @@ export const useGuiState = (): GuiStateAndMethod => {
};
type TextInputResolveType = {
resolve: ((value: string | PromiseLike<string>) => void) | null
}
resolve: ((value: string | PromiseLike<string>) => void) | null;
};
export const GuiStateProvider = ({ children }: Props) => {
const { appGuiSettingState } = useAppRoot()
const [isConverting, setIsConverting] = useState<boolean>(false)
const [isAnalyzing, setIsAnalyzing] = useState<boolean>(false)
const [modelSlotNum, setModelSlotNum] = useState<number>(0)
const { appGuiSettingState } = useAppRoot();
const [isConverting, setIsConverting] = useState<boolean>(false);
const [isAnalyzing, setIsAnalyzing] = useState<boolean>(false);
const [modelSlotNum, setModelSlotNum] = useState<number>(0);
const [showPyTorchModelUpload, setShowPyTorchModelUpload] = useState<boolean>(false)
const [showPyTorchModelUpload, setShowPyTorchModelUpload] = useState<boolean>(false);
const [inputAudioDeviceInfo, setInputAudioDeviceInfo] = useState<MediaDeviceInfo[]>([]);
const [outputAudioDeviceInfo, setOutputAudioDeviceInfo] = useState<MediaDeviceInfo[]>([]);
const [audioInputForGUI, setAudioInputForGUI] = useState<string>("none");
const [audioOutputForGUI, setAudioOutputForGUI] = useState<string>("none");
const [fileInputEchoback, setFileInputEchoback] = useState<boolean>(false); //最初のmuteが有効になるように。undefined <-- ??? falseしておけばよさそう。undefinedだとwarningがでる。
const [audioOutputForAnalyzer, setAudioOutputForAnalyzer] = useState<string>("default");
const [inputAudioDeviceInfo, setInputAudioDeviceInfo] = useState<MediaDeviceInfo[]>([])
const [outputAudioDeviceInfo, setOutputAudioDeviceInfo] = useState<MediaDeviceInfo[]>([])
const [audioInputForGUI, setAudioInputForGUI] = useState<string>("none")
const [audioOutputForGUI, setAudioOutputForGUI] = useState<string>("none")
const [fileInputEchoback, setFileInputEchoback] = useState<boolean>(false)//最初のmuteが有効になるように。undefined <-- ??? falseしておけばよさそう。undefinedだとwarningがでる。
const [audioOutputForAnalyzer, setAudioOutputForAnalyzer] = useState<string>("default")
const [textInputResolve, setTextInputResolve] = useState<TextInputResolveType | null>(null)
const [textInputResolve, setTextInputResolve] = useState<TextInputResolveType | null>(null);
const reloadDeviceInfo = async () => {
try {
const ms = await navigator.mediaDevices.getUserMedia({ video: false, audio: true });
ms.getTracks().forEach(x => { x.stop() })
ms.getTracks().forEach((x) => {
x.stop();
});
} catch (e) {
console.warn("Enumerate device error::", e)
console.warn("Enumerate device error::", e);
}
const mediaDeviceInfos = await navigator.mediaDevices.enumerateDevices();
const audioInputs = mediaDeviceInfos.filter(x => { return x.kind == "audioinput" })
const audioInputs = mediaDeviceInfos.filter((x) => {
return x.kind == "audioinput";
});
audioInputs.push({
deviceId: "none",
groupId: "none",
kind: "audioinput",
label: "none",
toJSON: () => { }
})
toJSON: () => {},
});
audioInputs.push({
deviceId: "file",
groupId: "file",
kind: "audioinput",
label: "file",
toJSON: () => { }
})
const audioOutputs = mediaDeviceInfos.filter(x => { return x.kind == "audiooutput" })
toJSON: () => {},
});
const audioOutputs = mediaDeviceInfos.filter((x) => {
return x.kind == "audiooutput";
});
audioOutputs.push({
deviceId: "none",
groupId: "none",
kind: "audiooutput",
label: "none",
toJSON: () => { }
})
toJSON: () => {},
});
// audioOutputs.push({
// deviceId: "record",
// groupId: "record",
@ -144,16 +151,16 @@ export const GuiStateProvider = ({ children }: Props) => {
// label: "record",
// toJSON: () => { }
// })
return [audioInputs, audioOutputs]
}
return [audioInputs, audioOutputs];
};
useEffect(() => {
const audioInitialize = async () => {
const audioInfo = await reloadDeviceInfo()
setInputAudioDeviceInfo(audioInfo[0])
setOutputAudioDeviceInfo(audioInfo[1])
}
audioInitialize()
}, [])
const audioInfo = await reloadDeviceInfo();
setInputAudioDeviceInfo(audioInfo[0]);
setOutputAudioDeviceInfo(audioInfo[1]);
};
audioInitialize();
}, []);
// (1) Controller Switch
const openServerControlCheckbox = useStateControlCheckbox(OpenServerControlCheckbox);
@ -171,35 +178,31 @@ export const GuiStateProvider = ({ children }: Props) => {
const showMergeLabCheckbox = useStateControlCheckbox(OpenMergeLabDialogCheckbox);
const showAdvancedSettingCheckbox = useStateControlCheckbox(OpenAdvancedSettingDialogCheckbox);
const showGetServerInformationCheckbox = useStateControlCheckbox(OpenGetServerInformationDialogCheckbox);
const showGetClientInformationCheckbox = useStateControlCheckbox(OpenGetClientInformationDialogCheckbox);
const showTextInputCheckbox = useStateControlCheckbox(OpenTextInputDialogCheckbox);
useEffect(() => {
openServerControlCheckbox.updateState(true)
openModelSettingCheckbox.updateState(false)
openDeviceSettingCheckbox.updateState(true)
openSpeakerSettingCheckbox.updateState(true)
openConverterSettingCheckbox.updateState(true)
openQualityControlCheckbox.updateState(false)
openLabCheckbox.updateState(false)
openAdvancedSettingCheckbox.updateState(false)
openServerControlCheckbox.updateState(true);
openModelSettingCheckbox.updateState(false);
openDeviceSettingCheckbox.updateState(true);
openSpeakerSettingCheckbox.updateState(true);
openConverterSettingCheckbox.updateState(true);
openQualityControlCheckbox.updateState(false);
openLabCheckbox.updateState(false);
openAdvancedSettingCheckbox.updateState(false);
showWaitingCheckbox.updateState(false);
showWaitingCheckbox.updateState(false)
showStartingNoticeCheckbox.updateState(false);
showModelSlotManagerCheckbox.updateState(false);
showMergeLabCheckbox.updateState(false);
showAdvancedSettingCheckbox.updateState(false);
showGetServerInformationCheckbox.updateState(false);
showGetClientInformationCheckbox.updateState(false);
showStartingNoticeCheckbox.updateState(false)
showModelSlotManagerCheckbox.updateState(false)
showMergeLabCheckbox.updateState(false)
showAdvancedSettingCheckbox.updateState(false)
showGetServerInformationCheckbox.updateState(false)
showTextInputCheckbox.updateState(false)
}, [])
showTextInputCheckbox.updateState(false);
}, []);
useEffect(() => {
const show = () => {
@ -210,14 +213,12 @@ export const GuiStateProvider = ({ children }: Props) => {
// return
// }
document.getElementById("dialog")?.classList.add("dialog-container-show")
showStartingNoticeCheckbox.updateState(true)
document.getElementById("dialog2")?.classList.add("dialog-container-show")
}
setTimeout(show)
}, [appGuiSettingState.edition])
document.getElementById("dialog")?.classList.add("dialog-container-show");
showStartingNoticeCheckbox.updateState(true);
document.getElementById("dialog2")?.classList.add("dialog-container-show");
};
setTimeout(show);
}, [appGuiSettingState.edition]);
const providerValue = {
stateControls: {
@ -237,9 +238,9 @@ export const GuiStateProvider = ({ children }: Props) => {
showMergeLabCheckbox,
showAdvancedSettingCheckbox,
showGetServerInformationCheckbox,
showGetClientInformationCheckbox,
showTextInputCheckbox
showTextInputCheckbox,
},
isConverting,
setIsConverting,
@ -248,7 +249,6 @@ export const GuiStateProvider = ({ children }: Props) => {
showPyTorchModelUpload,
setShowPyTorchModelUpload,
reloadDeviceInfo,
inputAudioDeviceInfo,
outputAudioDeviceInfo,
@ -266,13 +266,8 @@ export const GuiStateProvider = ({ children }: Props) => {
modelSlotNum,
setModelSlotNum,
textInputResolve,
setTextInputResolve
setTextInputResolve,
};
return <GuiStateContext.Provider value={providerValue}>{children}</GuiStateContext.Provider>;
};

View File

@ -6,9 +6,10 @@ import { ModelSlotManagerDialog } from "./904_ModelSlotManagerDialog";
import { MergeLabDialog } from "./905_MergeLabDialog";
import { AdvancedSettingDialog } from "./906_AdvancedSettingDialog";
import { GetServerInfomationDialog } from "./907_GetServerInfomationDialog";
import { GetClientInfomationDialog } from "./908_GetClientInfomationDialog";
export const Dialogs = () => {
const guiState = useGuiState()
const guiState = useGuiState();
const dialogs = (
<div>
{guiState.stateControls.showWaitingCheckbox.trigger}
@ -17,6 +18,7 @@ export const Dialogs = () => {
{guiState.stateControls.showMergeLabCheckbox.trigger}
{guiState.stateControls.showAdvancedSettingCheckbox.trigger}
{guiState.stateControls.showGetServerInformationCheckbox.trigger}
{guiState.stateControls.showGetClientInformationCheckbox.trigger}
<div className="dialog-container" id="dialog">
{guiState.stateControls.showWaitingCheckbox.trigger}
<WaitingDialog></WaitingDialog>
@ -30,10 +32,11 @@ export const Dialogs = () => {
<AdvancedSettingDialog></AdvancedSettingDialog>
{guiState.stateControls.showGetServerInformationCheckbox.trigger}
<GetServerInfomationDialog></GetServerInfomationDialog>
{guiState.stateControls.showGetClientInformationCheckbox.trigger}
<GetClientInfomationDialog></GetClientInfomationDialog>
</div>
</div>
);
return dialogs
}
return dialogs;
};

View File

@ -0,0 +1,61 @@
import React, { useMemo } from "react";
import { useGuiState } from "./001_GuiStateProvider";
import { useAppState } from "../../001_provider/001_AppStateProvider";
import { useAppRoot } from "../../001_provider/001_AppRootProvider";
export const GetClientInfomationDialog = () => {
const guiState = useGuiState();
const { audioContextState } = useAppRoot();
const { setting } = useAppState();
const dialog = useMemo(() => {
const closeButtonRow = (
<div className="body-row split-3-4-3 left-padding-1">
<div className="body-item-text"></div>
<div className="body-button-container body-button-container-space-around">
<div
className="body-button"
onClick={() => {
guiState.stateControls.showGetClientInformationCheckbox.updateState(false);
}}
>
close
</div>
</div>
<div className="body-item-text"></div>
</div>
);
const settingJson = JSON.stringify(setting, null, 4);
const rootAudioContextJson = JSON.stringify(
{
sampleRate: audioContextState.audioContext?.sampleRate,
baseLatency: audioContextState.audioContext?.baseLatency,
currentTime: audioContextState.audioContext?.currentTime,
outputLatency: audioContextState.audioContext?.outputLatency,
// @ts-ignore
sinkId: audioContextState.audioContext?.sinkId,
state: audioContextState.audioContext?.state,
},
null,
4
);
const concatJson = settingJson + "\n" + rootAudioContextJson;
console.log("AUDIO_CONTEXT", audioContextState.audioContext);
const content = (
<div className="get-server-information-container">
<textarea className="get-server-information-text-area" id="get-server-information-text-area" value={concatJson} onChange={() => {}} />
</div>
);
return (
<div className="dialog-frame">
<div className="dialog-title">Client Information</div>
<div className="dialog-content">
{content}
{closeButtonRow}
</div>
</div>
);
}, [setting, audioContextState]);
return dialog;
};

View File

@ -154,6 +154,11 @@ export const DeviceArea = (_props: DeviceAreaProps) => {
);
})
.filter((x) => x != null);
const currentValue = devices.find((x) => {
return (x.hostAPI == inputHostApi || inputHostApi == "ALL") && x.index == serverSetting.serverSetting.serverInputDeviceId;
})
? serverSetting.serverSetting.serverInputDeviceId
: -1;
return (
<div className="config-sub-area-control">
@ -176,12 +181,15 @@ export const DeviceArea = (_props: DeviceAreaProps) => {
</select>
<select
className="config-sub-area-control-field-auido-io-select"
value={serverSetting.serverSetting.serverInputDeviceId}
value={currentValue}
onChange={(e) => {
serverSetting.updateServerSettings({ ...serverSetting.serverSetting, serverInputDeviceId: Number(e.target.value) });
}}
>
{filteredDevice}
<option value="-1" key="none">
none
</option>
</select>
</div>
</div>
@ -390,6 +398,12 @@ export const DeviceArea = (_props: DeviceAreaProps) => {
})
.filter((x) => x != null);
const currentValue = devices.find((x) => {
return (x.hostAPI == outputHostApi || outputHostApi == "ALL") && x.index == serverSetting.serverSetting.serverOutputDeviceId;
})
? serverSetting.serverSetting.serverOutputDeviceId
: -1;
return (
<div className="config-sub-area-control">
<div className="config-sub-area-control-title left-padding-1">output</div>
@ -411,12 +425,15 @@ export const DeviceArea = (_props: DeviceAreaProps) => {
</select>
<select
className="config-sub-area-control-field-auido-io-select"
value={serverSetting.serverSetting.serverOutputDeviceId}
value={currentValue}
onChange={(e) => {
serverSetting.updateServerSettings({ ...serverSetting.serverSetting, serverOutputDeviceId: Number(e.target.value) });
}}
>
{filteredDevice}
<option value="-1" key="none">
none
</option>
</select>
</div>
</div>
@ -523,10 +540,16 @@ export const DeviceArea = (_props: DeviceAreaProps) => {
.filter((x) => x != null);
filteredDevice.unshift(
<option value={-1} key={-1}>
None
none
</option>
);
const currentValue = devices.find((x) => {
return (x.hostAPI == monitorHostApi || monitorHostApi == "ALL") && x.index == serverSetting.serverSetting.serverMonitorDeviceId;
})
? serverSetting.serverSetting.serverMonitorDeviceId
: -1;
return (
<div className="config-sub-area-control">
<div className="config-sub-area-control-title left-padding-1">monitor</div>
@ -548,7 +571,7 @@ export const DeviceArea = (_props: DeviceAreaProps) => {
</select>
<select
className="config-sub-area-control-field-auido-io-select"
value={serverSetting.serverSetting.serverMonitorDeviceId}
value={currentValue}
onChange={(e) => {
serverSetting.updateServerSettings({ ...serverSetting.serverSetting, serverMonitorDeviceId: Number(e.target.value) });
}}

View File

@ -1,44 +1,48 @@
import React, { useMemo, } from "react"
import { useGuiState } from "../001_GuiStateProvider"
import React, { useMemo } from "react";
import { useGuiState } from "../001_GuiStateProvider";
export type MoreActionAreaProps = {
}
export type MoreActionAreaProps = {};
export const MoreActionArea = (_props: MoreActionAreaProps) => {
const { stateControls } = useGuiState()
const { stateControls } = useGuiState();
const serverIORecorderRow = useMemo(() => {
const onOpenMergeLabClicked = () => {
stateControls.showMergeLabCheckbox.updateState(true)
}
stateControls.showMergeLabCheckbox.updateState(true);
};
const onOpenAdvancedSettingClicked = () => {
stateControls.showAdvancedSettingCheckbox.updateState(true)
}
stateControls.showAdvancedSettingCheckbox.updateState(true);
};
const onOpenGetServerInformationClicked = () => {
stateControls.showGetServerInformationCheckbox.updateState(true)
}
stateControls.showGetServerInformationCheckbox.updateState(true);
};
const onOpenGetClientInformationClicked = () => {
stateControls.showGetClientInformationCheckbox.updateState(true);
};
return (
<>
<div className="config-sub-area-control left-padding-1">
<div className="config-sub-area-control-title">more...</div>
<div className="config-sub-area-control-field config-sub-area-control-field-long">
<div className="config-sub-area-buttons">
<div onClick={onOpenMergeLabClicked} className="config-sub-area-button">Merge Lab</div>
<div onClick={onOpenAdvancedSettingClicked} className="config-sub-area-button">Advanced Setting</div>
<div onClick={onOpenGetServerInformationClicked} className="config-sub-area-button">Server Info</div>
<div onClick={onOpenMergeLabClicked} className="config-sub-area-button">
Merge Lab
</div>
<div onClick={onOpenAdvancedSettingClicked} className="config-sub-area-button">
Advanced Setting
</div>
<div onClick={onOpenGetServerInformationClicked} className="config-sub-area-button">
Server Info
</div>
<div onClick={onOpenGetClientInformationClicked} className="config-sub-area-button">
Client Info
</div>
</div>
</div>
</div>
</>
)
}, [stateControls])
return (
<div className="config-sub-area">
{serverIORecorderRow}
</div>
)
}
);
}, [stateControls]);
return <div className="config-sub-area">{serverIORecorderRow}</div>;
};

View File

@ -1,12 +1,12 @@
{
"name": "@dannadori/voice-changer-client-js",
"version": "1.0.157",
"version": "1.0.159",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@dannadori/voice-changer-client-js",
"version": "1.0.157",
"version": "1.0.159",
"license": "ISC",
"dependencies": {
"@types/readable-stream": "^2.3.15",

View File

@ -1,6 +1,6 @@
{
"name": "@dannadori/voice-changer-client-js",
"version": "1.0.157",
"version": "1.0.159",
"description": "",
"main": "dist/index.js",
"directories": {

View File

@ -42,8 +42,9 @@ export type CrossFadeOverlapSize = typeof CrossFadeOverlapSize[keyof typeof Cros
export const F0Detector = {
"dio": "dio",
"harvest": "harvest",
// "parselmouth": "parselmouth",
"crepe": "crepe",
"crepe_full": "crepe_full",
"crepe_tiny": "crepe_tiny",
} as const
export type F0Detector = typeof F0Detector[keyof typeof F0Detector]

View File

@ -81,7 +81,7 @@ export const useClient = (props: UseClientProps): ClientState => {
}, [])
// (1-2) 各種設定I/F
const voiceChangerClientSetting = useClientSetting({ voiceChangerClient, audioContext: props.audioContext, voiceChangerClientSetting: setting.voiceChangerClientSetting })
const voiceChangerClientSetting = useClientSetting({ voiceChangerClient, voiceChangerClientSetting: setting.voiceChangerClientSetting })
const workletNodeSetting = useWorkletNodeSetting({ voiceChangerClient: voiceChangerClient, workletNodeSetting: setting.workletNodeSetting })
useWorkletSetting({ voiceChangerClient, workletSetting: setting.workletSetting })
const serverSetting = useServerSetting({ voiceChangerClient })

View File

@ -5,7 +5,6 @@ import { VoiceChangerClient } from "../VoiceChangerClient"
export type UseClientSettingProps = {
voiceChangerClient: VoiceChangerClient | null
audioContext: AudioContext | null
voiceChangerClientSetting: VoiceChangerClientSetting
}

View File

@ -113,8 +113,6 @@ export const useServerSetting = (props: UseServerSettingProps): ServerSettingSta
const _uploadFile2 = useMemo(() => {
return async (file: File, onprogress: (progress: number, end: boolean) => void, dir: string = "") => {
if (!props.voiceChangerClient) return
console.log("uploading..1.", file)
console.log("uploading..2.", file.name)
const num = await props.voiceChangerClient.uploadFile2(dir, file, onprogress)
const res = await props.voiceChangerClient.concatUploadedFile(dir + file.name, num)
console.log("uploaded", num, res)

View File

@ -34,6 +34,7 @@ def setupArgParser():
parser.add_argument("--logLevel", type=str, default="error", help="Log level info|critical|error. (default: error)")
parser.add_argument("-p", type=int, default=18888, help="port")
parser.add_argument("--https", type=strtobool, default=False, help="use https")
parser.add_argument("--test_connect", type=str, default="8.8.8.8", help="test connect to detect ip in https mode. default 8.8.8.8")
parser.add_argument("--httpsKey", type=str, default="ssl.key", help="path for the key of https")
parser.add_argument("--httpsCert", type=str, default="ssl.cert", help="path for the cert of https")
parser.add_argument("--httpsSelfSigned", type=strtobool, default=True, help="generate self-signed certificate")
@ -48,6 +49,8 @@ def setupArgParser():
parser.add_argument("--hubert_base_jp", type=str, help="path to hubert_base_jp model(pytorch)")
parser.add_argument("--hubert_soft", type=str, help="path to hubert_soft model(pytorch)")
parser.add_argument("--nsf_hifigan", type=str, help="path to nsf_hifigan model(pytorch)")
parser.add_argument("--crepe_onnx_full", type=str, help="path to crepe_onnx_full")
parser.add_argument("--crepe_onnx_tiny", type=str, help="path to crepe_onnx_tiny")
return parser
@ -85,6 +88,8 @@ voiceChangerParams = VoiceChangerParams(
hubert_base_jp=args.hubert_base_jp,
hubert_soft=args.hubert_soft,
nsf_hifigan=args.nsf_hifigan,
crepe_onnx_full=args.crepe_onnx_full,
crepe_onnx_tiny=args.crepe_onnx_tiny,
sample_mode=args.sample_mode,
)
@ -120,6 +125,7 @@ if __name__ == "__mp_main__":
if __name__ == "__main__":
mp.freeze_support()
printMessage(f"PYTHON:{sys.version}", level=2)
printMessage("Voice Changerを起動しています。", level=2)
# ダウンロード(Weight)
try:
@ -195,10 +201,10 @@ if __name__ == "__main__":
else:
printMessage(f"http://localhost:{EX_PORT}/", level=1)
else: # 直接python起動
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
hostname = s.getsockname()[0]
if args.https == 1:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect((args.test_connect, 80))
hostname = s.getsockname()[0]
printMessage(f"https://localhost:{PORT}/", level=1)
printMessage(f"https://{hostname}:{PORT}/", level=1)
else:

View File

@ -54,11 +54,11 @@ def getFrontendPath():
return frontend_path
# "hubert_base", "contentvec", "distilhubert"
class EnumEmbedderTypes(Enum):
hubert = "hubert_base"
contentvec = "contentvec"
hubert_jp = "hubert-base-japanese"
EmbedderType: TypeAlias = Literal[
"hubert_base",
"contentvec",
"hubert-base-japanese"
]
class EnumInferenceTypes(Enum):
@ -73,21 +73,18 @@ class EnumInferenceTypes(Enum):
onnxRVCNono = "onnxRVCNono"
class EnumPitchExtractorTypes(Enum):
harvest = "harvest"
dio = "dio"
crepe = "crepe"
class EnumFrameworkTypes(Enum):
pyTorch = "pyTorch"
onnx = "onnx"
class ServerAudioDeviceTypes(Enum):
audioinput = "audioinput"
audiooutput = "audiooutput"
PitchExtractorType: TypeAlias = Literal[
"harvest",
"dio",
"crepe",
"crepe_full",
"crepe_tiny",
]
ServerAudioDeviceType: TypeAlias = Literal[
"audioinput",
"audiooutput"
]
RVCSampleMode: TypeAlias = Literal[
"production",

View File

@ -1,5 +1,5 @@
from typing import TypeAlias, Union
from const import MAX_SLOT_NUM, EnumInferenceTypes, EnumEmbedderTypes, VoiceChangerType
from const import MAX_SLOT_NUM, EnumInferenceTypes, EmbedderType, VoiceChangerType
from dataclasses import dataclass, asdict, field
@ -34,7 +34,7 @@ class RVCModelSlot(ModelSlot):
embOutputLayer: int = 9
useFinalProj: bool = True
deprecated: bool = False
embedder: str = EnumEmbedderTypes.hubert.value
embedder: EmbedderType = "hubert_base"
sampleId: str = ""
speakers: dict = field(default_factory=lambda: {0: "target"})

View File

@ -166,7 +166,8 @@ def _downloadSamples(samples: list[ModelSamples], sampleModelIds: list[Tuple[str
slotInfo = modelSlotManager.get_slot_info(targetSlotIndex)
if slotInfo.voiceChangerType == "RVC":
if slotInfo.isONNX:
RVCModelSlotGenerator._setInfoByONNX(slotInfo)
slotInfo = RVCModelSlotGenerator._setInfoByONNX(slotInfo)
else:
RVCModelSlotGenerator._setInfoByPytorch(slotInfo)
slotInfo = RVCModelSlotGenerator._setInfoByPytorch(slotInfo)
modelSlotManager.save_model_slot(targetSlotIndex, slotInfo)

View File

@ -11,6 +11,8 @@ def downloadWeight(voiceChangerParams: VoiceChangerParams):
hubert_base_jp = voiceChangerParams.hubert_base_jp
hubert_soft = voiceChangerParams.hubert_soft
nsf_hifigan = voiceChangerParams.nsf_hifigan
crepe_onnx_full = voiceChangerParams.crepe_onnx_full
crepe_onnx_tiny = voiceChangerParams.crepe_onnx_tiny
# file exists check (currently only for rvc)
downloadParams = []
@ -57,6 +59,24 @@ def downloadWeight(voiceChangerParams: VoiceChangerParams):
}
)
if os.path.exists(crepe_onnx_full) is False:
downloadParams.append(
{
"url": "https://huggingface.co/wok000/weights/resolve/main/crepe/onnx/full.onnx",
"saveTo": crepe_onnx_full,
"position": 5,
}
)
if os.path.exists(crepe_onnx_tiny) is False:
downloadParams.append(
{
"url": "https://huggingface.co/wok000/weights/resolve/main/crepe/onnx/tiny.onnx",
"saveTo": crepe_onnx_tiny,
"position": 6,
}
)
with ThreadPoolExecutor() as pool:
pool.map(download, downloadParams)

View File

@ -1,14 +1,15 @@
import sounddevice as sd
from dataclasses import dataclass, field
from const import ServerAudioDeviceTypes
import numpy as np
from const import ServerAudioDeviceType
# from const import SERVER_DEVICE_SAMPLE_RATES
@dataclass
class ServerAudioDevice:
kind: ServerAudioDeviceTypes = ServerAudioDeviceTypes.audioinput
kind: ServerAudioDeviceType = "audioinput"
index: int = 0
name: str = ""
hostAPI: str = ""
@ -22,7 +23,7 @@ def dummy_callback(data: np.ndarray, frames, times, status):
pass
def checkSamplingRate(deviceId: int, desiredSamplingRate: int, type: ServerAudioDeviceTypes):
def checkSamplingRate(deviceId: int, desiredSamplingRate: int, type: ServerAudioDeviceType):
if type == "input":
try:
with sd.InputStream(
@ -71,7 +72,7 @@ def list_audio_device():
serverAudioOutputDevices: list[ServerAudioDevice] = []
for d in inputAudioDeviceList:
serverInputAudioDevice: ServerAudioDevice = ServerAudioDevice(
kind=ServerAudioDeviceTypes.audioinput,
kind="audioinput",
index=d["index"],
name=d["name"],
hostAPI=hostapis[d["hostapi"]]["name"],
@ -82,7 +83,7 @@ def list_audio_device():
serverAudioInputDevices.append(serverInputAudioDevice)
for d in outputAudioDeviceList:
serverOutputAudioDevice: ServerAudioDevice = ServerAudioDevice(
kind=ServerAudioDeviceTypes.audiooutput,
kind="audiooutput",
index=d["index"],
name=d["name"],
hostAPI=hostapis[d["hostapi"]]["name"],

View File

@ -300,5 +300,5 @@ class MMVCv15:
if file_path.find(remove_path + os.path.sep) >= 0:
# print("remove", key, file_path)
sys.modules.pop(key)
except: # type:ignore
except: # NOQA
pass

View File

@ -1,5 +1,5 @@
import sys
import os
# import sys
# import os
from dataclasses import asdict
import numpy as np
import torch
@ -7,18 +7,18 @@ import torchaudio
from data.ModelSlot import RVCModelSlot
# avoiding parse arg error in RVC
sys.argv = ["MMVCServerSIO.py"]
# # avoiding parse arg error in RVC
# sys.argv = ["MMVCServerSIO.py"]
if sys.platform.startswith("darwin"):
baseDir = [x for x in sys.path if x.endswith("Contents/MacOS")]
if len(baseDir) != 1:
print("baseDir should be only one ", baseDir)
sys.exit()
modulePath = os.path.join(baseDir[0], "RVC")
sys.path.append(modulePath)
else:
sys.path.append("RVC")
# if sys.platform.startswith("darwin"):
# baseDir = [x for x in sys.path if x.endswith("Contents/MacOS")]
# if len(baseDir) != 1:
# print("baseDir should be only one ", baseDir)
# sys.exit()
# modulePath = os.path.join(baseDir[0], "RVC")
# sys.path.append(modulePath)
# else:
# sys.path.append("RVC")
from voice_changer.RVC.RVCSettings import RVCSettings
@ -39,9 +39,10 @@ class RVC(VoiceChangerModel):
print("[Voice Changer] [RVC] Creating instance ")
self.deviceManager = DeviceManager.get_instance()
EmbedderManager.initialize(params)
PitchExtractorManager.initialize(params)
self.settings = RVCSettings()
self.params = params
self.pitchExtractor = PitchExtractorManager.getPitchExtractor(self.settings.f0Detector)
self.pitchExtractor = PitchExtractorManager.getPitchExtractor(self.settings.f0Detector, self.settings.gpu)
self.pipeline: Pipeline | None = None
@ -76,7 +77,7 @@ class RVC(VoiceChangerModel):
elif key in self.settings.strData:
setattr(self.settings, key, str(val))
if key == "f0Detector" and self.pipeline is not None:
pitchExtractor = PitchExtractorManager.getPitchExtractor(self.settings.f0Detector)
pitchExtractor = PitchExtractorManager.getPitchExtractor(self.settings.f0Detector, self.settings.gpu)
self.pipeline.setPitchExtractor(pitchExtractor)
else:
return False
@ -112,7 +113,7 @@ class RVC(VoiceChangerModel):
self.audio_buffer = newData
if self.slotInfo.f0:
self.pitchf_buffer = np.zeros(new_feature_length)
self.feature_buffer = np.zeros([new_feature_length, self.slotInfo.embChannels])
self.feature_buffer = np.zeros([new_feature_length, self.slotInfo.embChannels])
convertSize = inputSize + crossfadeSize + solaSearchFrame + self.settings.extraConvertSize
@ -201,21 +202,21 @@ class RVC(VoiceChangerModel):
def __del__(self):
del self.pipeline
print("---------- REMOVING ---------------")
# print("---------- REMOVING ---------------")
remove_path = os.path.join("RVC")
sys.path = [x for x in sys.path if x.endswith(remove_path) is False]
# remove_path = os.path.join("RVC")
# sys.path = [x for x in sys.path if x.endswith(remove_path) is False]
for key in list(sys.modules):
val = sys.modules.get(key)
try:
file_path = val.__file__
if file_path.find("RVC" + os.path.sep) >= 0:
# print("remove", key, file_path)
sys.modules.pop(key)
except Exception: # type:ignore
# print(e)
pass
# for key in list(sys.modules):
# val = sys.modules.get(key)
# try:
# file_path = val.__file__
# if file_path.find("RVC" + os.path.sep) >= 0:
# # print("remove", key, file_path)
# sys.modules.pop(key)
# except Exception: # type:ignore
# # print(e)
# pass
def export2onnx(self):
modelSlot = self.slotInfo

View File

@ -1,6 +1,6 @@
import os
from const import EnumEmbedderTypes, EnumInferenceTypes
from const import EnumInferenceTypes
from dataclasses import asdict
import torch
import onnxruntime
import json
@ -38,6 +38,8 @@ class RVCModelSlotGenerator(ModelSlotGenerator):
config_len = len(cpt["config"])
version = cpt.get("version", "v1")
slot = RVCModelSlot(**asdict(slot))
if version == "voras_beta":
slot.f0 = True if cpt["f0"] == 1 else False
slot.modelType = EnumInferenceTypes.pyTorchVoRASbeta.value
@ -49,12 +51,12 @@ class RVCModelSlotGenerator(ModelSlotGenerator):
if slot.embedder.endswith("768"):
slot.embedder = slot.embedder[:-3]
if slot.embedder == EnumEmbedderTypes.hubert.value:
slot.embedder = EnumEmbedderTypes.hubert.value
elif slot.embedder == EnumEmbedderTypes.contentvec.value:
slot.embedder = EnumEmbedderTypes.contentvec.value
elif slot.embedder == EnumEmbedderTypes.hubert_jp.value:
slot.embedder = EnumEmbedderTypes.hubert_jp.value
# if slot.embedder == "hubert":
# slot.embedder = "hubert"
# elif slot.embedder == "contentvec":
# slot.embedder = "contentvec"
# elif slot.embedder == "hubert_jp":
# slot.embedder = "hubert_jp"
else:
raise RuntimeError("[Voice Changer][setInfoByONNX] unknown embedder")
@ -67,14 +69,14 @@ class RVCModelSlotGenerator(ModelSlotGenerator):
slot.embChannels = 256
slot.embOutputLayer = 9
slot.useFinalProj = True
slot.embedder = EnumEmbedderTypes.hubert.value
slot.embedder = "hubert_base"
print("[Voice Changer] Official Model(pyTorch) : v1")
else:
slot.modelType = EnumInferenceTypes.pyTorchRVCv2.value if slot.f0 else EnumInferenceTypes.pyTorchRVCv2Nono.value
slot.embChannels = 768
slot.embOutputLayer = 12
slot.useFinalProj = False
slot.embedder = EnumEmbedderTypes.hubert.value
slot.embedder = "hubert_base"
print("[Voice Changer] Official Model(pyTorch) : v2")
else:
@ -104,24 +106,18 @@ class RVCModelSlotGenerator(ModelSlotGenerator):
for k, v in cpt["speaker_info"].items():
slot.speakers[int(k)] = str(v)
# if slot.embedder == EnumEmbedderTypes.hubert.value:
# slot.embedder = EnumEmbedderTypes.hubert
# elif slot.embedder == EnumEmbedderTypes.contentvec.value:
# slot.embedder = EnumEmbedderTypes.contentvec
# elif slot.embedder == EnumEmbedderTypes.hubert_jp.value:
# slot.embedder = EnumEmbedderTypes.hubert_jp
# else:
# raise RuntimeError("[Voice Changer][setInfoByONNX] unknown embedder")
slot.samplingRate = cpt["config"][-1]
del cpt
return slot
@classmethod
def _setInfoByONNX(cls, slot: ModelSlot):
tmp_onnx_session = onnxruntime.InferenceSession(slot.modelFile, providers=["CPUExecutionProvider"])
modelmeta = tmp_onnx_session.get_modelmeta()
try:
slot = RVCModelSlot(**asdict(slot))
metadata = json.loads(modelmeta.custom_metadata_map["metadata"])
# slot.modelType = metadata["modelType"]
@ -144,17 +140,9 @@ class RVCModelSlotGenerator(ModelSlotGenerator):
print(f"[Voice Changer] ONNX Model: ch:{slot.embChannels}, L:{slot.embOutputLayer}, FP:{slot.useFinalProj}")
if "embedder" not in metadata:
slot.embedder = EnumEmbedderTypes.hubert.value
slot.embedder = "hubert_base"
else:
slot.embedder = metadata["embedder"]
# elif metadata["embedder"] == EnumEmbedderTypes.hubert.value:
# slot.embedder = EnumEmbedderTypes.hubert
# elif metadata["embedder"] == EnumEmbedderTypes.contentvec.value:
# slot.embedder = EnumEmbedderTypes.contentvec
# elif metadata["embedder"] == EnumEmbedderTypes.hubert_jp.value:
# slot.embedder = EnumEmbedderTypes.hubert_jp
# else:
# raise RuntimeError("[Voice Changer][setInfoByONNX] unknown embedder")
slot.f0 = metadata["f0"]
slot.modelType = EnumInferenceTypes.onnxRVC.value if slot.f0 else EnumInferenceTypes.onnxRVCNono.value
@ -164,7 +152,7 @@ class RVCModelSlotGenerator(ModelSlotGenerator):
except Exception as e:
slot.modelType = EnumInferenceTypes.onnxRVC.value
slot.embChannels = 256
slot.embedder = EnumEmbedderTypes.hubert.value
slot.embedder = "hubert_base"
slot.f0 = True
slot.samplingRate = 48000
slot.deprecated = True
@ -175,3 +163,4 @@ class RVCModelSlotGenerator(ModelSlotGenerator):
print("[Voice Changer] ############## !!!! CAUTION !!!! ####################")
del tmp_onnx_session
return slot

View File

@ -3,11 +3,11 @@ from typing import Any, Protocol
import torch
from torch import device
from const import EnumEmbedderTypes
from const import EmbedderType
class Embedder(Protocol):
embedderType: EnumEmbedderTypes = EnumEmbedderTypes.hubert
embedderType: EmbedderType = "hubert_base"
file: str
isHalf: bool = True
dev: device
@ -24,7 +24,7 @@ class Embedder(Protocol):
def getEmbedderInfo(self):
return {
"embedderType": self.embedderType.value,
"embedderType": self.embedderType,
"file": self.file,
"isHalf": self.isHalf,
"devType": self.dev.type,
@ -33,7 +33,7 @@ class Embedder(Protocol):
def setProps(
self,
embedderType: EnumEmbedderTypes,
embedderType: EmbedderType,
file: str,
dev: device,
isHalf: bool = True,
@ -56,7 +56,7 @@ class Embedder(Protocol):
self.model = self.model.to(self.dev)
return self
def matchCondition(self, embedderType: EnumEmbedderTypes) -> bool:
def matchCondition(self, embedderType: EmbedderType) -> bool:
# Check Type
if self.embedderType != embedderType:
print(

View File

@ -1,6 +1,6 @@
from torch import device
from const import EnumEmbedderTypes
from const import EmbedderType
from voice_changer.RVC.embedder.Embedder import Embedder
from voice_changer.RVC.embedder.FairseqContentvec import FairseqContentvec
from voice_changer.RVC.embedder.FairseqHubert import FairseqHubert
@ -18,7 +18,7 @@ class EmbedderManager:
@classmethod
def getEmbedder(
cls, embederType: EnumEmbedderTypes, isHalf: bool, dev: device
cls, embederType: EmbedderType, isHalf: bool, dev: device
) -> Embedder:
if cls.currentEmbedder is None:
print("[Voice Changer] generate new embedder. (no embedder)")
@ -35,24 +35,15 @@ class EmbedderManager:
@classmethod
def loadEmbedder(
cls, embederType: EnumEmbedderTypes, isHalf: bool, dev: device
cls, embederType: EmbedderType, isHalf: bool, dev: device
) -> Embedder:
if (
embederType == EnumEmbedderTypes.hubert
or embederType == EnumEmbedderTypes.hubert.value
):
if embederType == "hubert_base":
file = cls.params.hubert_base
return FairseqHubert().loadModel(file, dev, isHalf)
elif (
embederType == EnumEmbedderTypes.hubert_jp
or embederType == EnumEmbedderTypes.hubert_jp.value
):
elif embederType == "hubert-base-japanese":
file = cls.params.hubert_base_jp
return FairseqHubertJp().loadModel(file, dev, isHalf)
elif (
embederType == EnumEmbedderTypes.contentvec
or embederType == EnumEmbedderTypes.contentvec.value
):
elif embederType == "contentvec":
file = cls.params.hubert_base
return FairseqContentvec().loadModel(file, dev, isHalf)
else:

View File

@ -1,5 +1,4 @@
from torch import device
from const import EnumEmbedderTypes
from voice_changer.RVC.embedder.Embedder import Embedder
from voice_changer.RVC.embedder.FairseqHubert import FairseqHubert
@ -7,5 +6,5 @@ from voice_changer.RVC.embedder.FairseqHubert import FairseqHubert
class FairseqContentvec(FairseqHubert):
def loadModel(self, file: str, dev: device, isHalf: bool = True) -> Embedder:
super().loadModel(file, dev, isHalf)
super().setProps(EnumEmbedderTypes.contentvec, file, dev, isHalf)
super().setProps("contentvec", file, dev, isHalf)
return self

View File

@ -1,13 +1,12 @@
import torch
from torch import device
from const import EnumEmbedderTypes
from voice_changer.RVC.embedder.Embedder import Embedder
from fairseq import checkpoint_utils
class FairseqHubert(Embedder):
def loadModel(self, file: str, dev: device, isHalf: bool = True) -> Embedder:
super().setProps(EnumEmbedderTypes.hubert, file, dev, isHalf)
super().setProps("hubert_base", file, dev, isHalf)
models, saved_cfg, task = checkpoint_utils.load_model_ensemble_and_task(
[file],

View File

@ -1,5 +1,4 @@
from torch import device
from const import EnumEmbedderTypes
from voice_changer.RVC.embedder.Embedder import Embedder
from voice_changer.RVC.embedder.FairseqHubert import FairseqHubert
@ -7,5 +6,5 @@ from voice_changer.RVC.embedder.FairseqHubert import FairseqHubert
class FairseqHubertJp(FairseqHubert):
def loadModel(self, file: str, dev: device, isHalf: bool = True) -> Embedder:
super().loadModel(file, dev, isHalf)
super().setProps(EnumEmbedderTypes.hubert_jp, file, dev, isHalf)
super().setProps("hubert-base-japanese", file, dev, isHalf)
return self

View File

@ -31,7 +31,6 @@ class InferencerManager:
file: str,
gpu: int,
) -> Inferencer:
print("inferencerTypeinferencerTypeinferencerTypeinferencerType", inferencerType)
if inferencerType == EnumInferenceTypes.pyTorchRVC or inferencerType == EnumInferenceTypes.pyTorchRVC.value:
return RVCInferencer().loadModel(file, gpu)
elif inferencerType == EnumInferenceTypes.pyTorchRVCNono or inferencerType == EnumInferenceTypes.pyTorchRVCNono.value:

View File

@ -51,7 +51,7 @@ class OnnxRVCInferencer(Inferencer):
"p_len": pitch_length.cpu().numpy().astype(np.int64),
"pitch": pitch.cpu().numpy().astype(np.int64),
"pitchf": pitchf.cpu().numpy().astype(np.float32),
"sid": sid.cpu().numpy().astype(np.int64)
"sid": sid.cpu().numpy().astype(np.int64)
},
)
else:
@ -62,7 +62,7 @@ class OnnxRVCInferencer(Inferencer):
"p_len": pitch_length.cpu().numpy().astype(np.int64),
"pitch": pitch.cpu().numpy().astype(np.int64),
"pitchf": pitchf.cpu().numpy().astype(np.float32),
"sid": sid.cpu().numpy().astype(np.int64)
"sid": sid.cpu().numpy().astype(np.int64)
},
)

View File

@ -4,6 +4,7 @@ from const import EnumInferenceTypes
from voice_changer.RVC.inferencer.OnnxRVCInferencer import OnnxRVCInferencer
class OnnxRVCInferencerNono(OnnxRVCInferencer):
def loadModel(self, file: str, gpu: int):
super().loadModel(file, gpu)

View File

@ -73,9 +73,9 @@ class Pipeline(object):
def exec(
self,
sid,
audio, # torch.tensor [n]
pitchf, # np.array [m]
feature, # np.array [m, feat]
audio, # torch.tensor [n]
pitchf, # np.array [m]
feature, # np.array [m, feat]
f0_up_key,
index_rate,
if_f0,

View File

@ -34,7 +34,7 @@ def createPipeline(modelSlot: RVCModelSlot, gpu: int, f0Detector: str):
traceback.print_exc()
# pitchExtractor
pitchExtractor = PitchExtractorManager.getPitchExtractor(f0Detector)
pitchExtractor = PitchExtractorManager.getPitchExtractor(f0Detector, gpu)
# index, feature
index = _loadIndex(modelSlot)
@ -67,7 +67,7 @@ def _loadIndex(modelSlot: RVCModelSlot):
try:
print("Try loading...", modelSlot.indexFile)
index = faiss.read_index(modelSlot.indexFile)
except:
except: # NOQA
print("[Voice Changer] load index failed. Use no index.")
traceback.print_exc()
return None

View File

@ -0,0 +1,68 @@
import numpy as np
from const import PitchExtractorType
from voice_changer.RVC.deviceManager.DeviceManager import DeviceManager
from voice_changer.RVC.pitchExtractor.PitchExtractor import PitchExtractor
import onnxruntime
from voice_changer.RVC.pitchExtractor import onnxcrepe
class CrepeOnnxPitchExtractor(PitchExtractor):
def __init__(self, pitchExtractorType: PitchExtractorType, file: str, gpu: int):
self.pitchExtractorType = pitchExtractorType
super().__init__()
(
onnxProviders,
onnxProviderOptions,
) = DeviceManager.get_instance().getOnnxExecutionProvider(gpu)
self.onnx_session = onnxruntime.InferenceSession(
file, providers=onnxProviders, provider_options=onnxProviderOptions
)
def extract(self, audio, pitchf, f0_up_key, sr, window, silence_front=0):
n_frames = int(len(audio) // window) + 1
start_frame = int(silence_front * sr / window)
real_silence_front = start_frame * window / sr
silence_front_offset = int(np.round(real_silence_front * sr))
audio = audio[silence_front_offset:]
f0_min = 50
f0_max = 1100
f0_mel_min = 1127 * np.log(1 + f0_min / 700)
f0_mel_max = 1127 * np.log(1 + f0_max / 700)
precision = 10.0
audio_num = audio.cpu()
onnx_f0, onnx_pd = onnxcrepe.predict(
self.onnx_session,
audio_num,
sr,
precision=precision,
fmin=f0_min,
fmax=f0_max,
batch_size=256,
return_periodicity=True,
decoder=onnxcrepe.decode.weighted_argmax,
)
f0 = onnxcrepe.filter.median(onnx_f0, 3)
pd = onnxcrepe.filter.median(onnx_pd, 3)
f0[pd < 0.1] = 0
f0 = f0.squeeze()
f0 = np.pad(f0, (start_frame, n_frames - f0.shape[0] - start_frame), 'constant', constant_values=(0, 0))
f0 *= pow(2, f0_up_key / 12)
pitchf[-f0.shape[0]:] = f0[:pitchf.shape[0]]
f0bak = pitchf.copy()
f0_mel = 1127.0 * np.log(1.0 + f0bak / 700.0)
f0_mel = np.clip(
(f0_mel - f0_mel_min) * 254.0 / (f0_mel_max - f0_mel_min) + 1.0, 1.0, 255.0
)
pitch_coarse = f0_mel.astype(int)
return pitch_coarse, pitchf

View File

@ -1,16 +1,16 @@
import torchcrepe
import torch
import numpy as np
from const import EnumPitchExtractorTypes
from const import PitchExtractorType
from voice_changer.RVC.pitchExtractor.PitchExtractor import PitchExtractor
class CrepePitchExtractor(PitchExtractor):
pitchExtractorType: EnumPitchExtractorTypes = EnumPitchExtractorTypes.crepe
def __init__(self):
super().__init__()
self.pitchExtractorType: PitchExtractorType = "crepe"
if torch.cuda.is_available():
self.device = torch.device("cuda:" + str(torch.cuda.current_device()))
else:

View File

@ -1,16 +1,19 @@
import pyworld
import numpy as np
from const import EnumPitchExtractorTypes
from const import PitchExtractorType
from voice_changer.RVC.pitchExtractor.PitchExtractor import PitchExtractor
class DioPitchExtractor(PitchExtractor):
pitchExtractorType: EnumPitchExtractorTypes = EnumPitchExtractorTypes.dio
def __init__(self):
super().__init__()
self.pitchExtractorType: PitchExtractorType = "dio"
def extract(self, audio, pitchf, f0_up_key, sr, window, silence_front=0):
audio = audio.detach().cpu().numpy()
n_frames = int(len(audio) // window) + 1
n_frames = int(len(audio) // window) + 1 # NOQA
start_frame = int(silence_front * sr / window)
real_silence_front = start_frame * window / sr
@ -31,7 +34,7 @@ class DioPitchExtractor(PitchExtractor):
frame_period=10,
)
f0 = pyworld.stonemask(audio.astype(np.double), _f0, t, sr)
# f0 = np.pad(f0.astype("float"), (start_frame, n_frames - len(f0) - start_frame))
# f0 = np.pad(f0.astype("float"), (start_frame, n_frames - len(f0) - start_frame))
f0 *= pow(2, f0_up_key / 12)
pitchf[-f0.shape[0]:] = f0[:pitchf.shape[0]]
@ -45,4 +48,3 @@ class DioPitchExtractor(PitchExtractor):
pitch_coarse = np.rint(f0_mel).astype(int)
return pitch_coarse, pitchf

View File

@ -1,17 +1,20 @@
import pyworld
import numpy as np
import scipy.signal as signal
from const import EnumPitchExtractorTypes
from const import PitchExtractorType
from voice_changer.RVC.pitchExtractor.PitchExtractor import PitchExtractor
class HarvestPitchExtractor(PitchExtractor):
pitchExtractorType: EnumPitchExtractorTypes = EnumPitchExtractorTypes.harvest
def __init__(self):
super().__init__()
self.pitchExtractorType: PitchExtractorType = "harvest"
def extract(self, audio, pitchf, f0_up_key, sr, window, silence_front=0):
audio = audio.detach().cpu().numpy()
n_frames = int(len(audio) // window) + 1
n_frames = int(len(audio) // window) + 1 # NOQA
start_frame = int(silence_front * sr / window)
real_silence_front = start_frame * window / sr

View File

@ -1,14 +1,12 @@
from typing import Protocol
from const import EnumPitchExtractorTypes
class PitchExtractor(Protocol):
pitchExtractorType: EnumPitchExtractorTypes = EnumPitchExtractorTypes.harvest
def extract(self, audio, f0_up_key, sr, window, silence_front=0):
...
def getPitchExtractorInfo(self):
return {
"pitchExtractorType": self.pitchExtractorType.value,
"pitchExtractorType": self.pitchExtractorType,
}

View File

@ -1,40 +1,42 @@
from typing import Protocol
from const import EnumPitchExtractorTypes
from const import PitchExtractorType
from voice_changer.RVC.pitchExtractor.CrepeOnnxPitchExtractor import CrepeOnnxPitchExtractor
from voice_changer.RVC.pitchExtractor.DioPitchExtractor import DioPitchExtractor
from voice_changer.RVC.pitchExtractor.HarvestPitchExtractor import HarvestPitchExtractor
from voice_changer.RVC.pitchExtractor.CrepePitchExtractor import CrepePitchExtractor
from voice_changer.RVC.pitchExtractor.PitchExtractor import PitchExtractor
from voice_changer.utils.VoiceChangerParams import VoiceChangerParams
class PitchExtractorManager(Protocol):
currentPitchExtractor: PitchExtractor | None = None
params: VoiceChangerParams
@classmethod
def initialize(cls, params: VoiceChangerParams):
cls.params = params
@classmethod
def getPitchExtractor(
cls, pitchExtractorType: EnumPitchExtractorTypes
cls, pitchExtractorType: PitchExtractorType, gpu: int
) -> PitchExtractor:
cls.currentPitchExtractor = cls.loadPitchExtractor(pitchExtractorType)
cls.currentPitchExtractor = cls.loadPitchExtractor(pitchExtractorType, gpu)
return cls.currentPitchExtractor
@classmethod
def loadPitchExtractor(
cls, pitchExtractorType: EnumPitchExtractorTypes
cls, pitchExtractorType: PitchExtractorType, gpu: int
) -> PitchExtractor:
if (
pitchExtractorType == EnumPitchExtractorTypes.harvest
or pitchExtractorType == EnumPitchExtractorTypes.harvest.value
):
if pitchExtractorType == "harvest":
return HarvestPitchExtractor()
elif (
pitchExtractorType == EnumPitchExtractorTypes.dio
or pitchExtractorType == EnumPitchExtractorTypes.dio.value
):
elif pitchExtractorType == "dio":
return DioPitchExtractor()
elif (
pitchExtractorType == EnumPitchExtractorTypes.crepe
or pitchExtractorType == EnumPitchExtractorTypes.crepe.value
):
elif pitchExtractorType == "crepe":
return CrepePitchExtractor()
elif pitchExtractorType == "crepe_tiny":
return CrepeOnnxPitchExtractor(pitchExtractorType, cls.params.crepe_onnx_tiny, gpu)
elif pitchExtractorType == "crepe_full":
return CrepeOnnxPitchExtractor(pitchExtractorType, cls.params.crepe_onnx_full, gpu)
else:
# return hubert as default
raise RuntimeError(

View File

@ -0,0 +1,8 @@
from . import decode # NOQA
from .core import * # NOQA
from . import convert # NOQA
from . import filter # NOQA
from . import load # NOQA
from . import loudness # NOQA
from .session import CrepeInferenceSession # NOQA
from . import threshold # NOQA

View File

@ -0,0 +1,57 @@
import numpy as np
import scipy
from voice_changer.RVC.pitchExtractor import onnxcrepe
###############################################################################
# Pitch unit conversions
###############################################################################
def bins_to_cents(bins, apply_dither=False):
"""Converts pitch bins to cents"""
cents = onnxcrepe.CENTS_PER_BIN * bins + 1997.3794084376191
# Trade quantization error for noise (disabled by default)
return dither(cents) if apply_dither else cents
def bins_to_frequency(bins, apply_dither=False):
"""Converts pitch bins to frequency in Hz"""
return cents_to_frequency(bins_to_cents(bins, apply_dither=apply_dither))
def cents_to_bins(cents, quantize_fn=np.floor):
"""Converts cents to pitch bins"""
bins = (cents - 1997.3794084376191) / onnxcrepe.CENTS_PER_BIN
return quantize_fn(bins).astype(np.int64)
def cents_to_frequency(cents):
"""Converts cents to frequency in Hz"""
return 10 * 2 ** (cents / 1200)
def frequency_to_bins(frequency, quantize_fn=np.floor):
"""Convert frequency in Hz to pitch bins"""
return cents_to_bins(frequency_to_cents(frequency), quantize_fn)
def frequency_to_cents(frequency):
"""Convert frequency in Hz to cents"""
return 1200 * np.log2(frequency / 10.)
###############################################################################
# Utilities
###############################################################################
def dither(cents):
"""Dither the predicted pitch in cents to remove quantization error"""
noise = scipy.stats.triang.rvs(c=0.5,
loc=-onnxcrepe.CENTS_PER_BIN,
scale=2 * onnxcrepe.CENTS_PER_BIN,
size=cents.shape)
return cents + noise.astype(cents.dtype)

View File

@ -0,0 +1,256 @@
import librosa
import numpy as np
from voice_changer.RVC.pitchExtractor import onnxcrepe
__all__ = ['CENTS_PER_BIN',
'MAX_FMAX',
'PITCH_BINS',
'SAMPLE_RATE',
'WINDOW_SIZE',
'UNVOICED',
'predict',
'preprocess',
'infer',
'postprocess',
'resample']
###############################################################################
# Constants
###############################################################################
CENTS_PER_BIN = 20 # cents
MAX_FMAX = 2006. # hz
PITCH_BINS = 360
SAMPLE_RATE = 16000 # hz
WINDOW_SIZE = 1024 # samples
UNVOICED = np.nan
###############################################################################
# Crepe pitch prediction
###############################################################################
def predict(session,
audio,
sample_rate,
precision=None,
fmin=50.,
fmax=MAX_FMAX,
decoder=onnxcrepe.decode.weighted_viterbi,
return_periodicity=False,
batch_size=None,
pad=True):
"""Performs pitch estimation
Arguments
session (onnxcrepe.CrepeInferenceSession)
An onnxruntime.InferenceSession holding the CREPE model
audio (numpy.ndarray [shape=(n_samples,)])
The audio signal
sample_rate (int)
The sampling rate in Hz
precision (float)
The precision in milliseconds, i.e. the length of each frame
fmin (float)
The minimum allowable frequency in Hz
fmax (float)
The maximum allowable frequency in Hz
decoder (function)
The decoder to use. See decode.py for decoders.
return_periodicity (bool)
Whether to also return the network confidence
batch_size (int)
The number of frames per batch
pad (bool)
Whether to zero-pad the audio
Returns
pitch (numpy.ndarray [shape=(1, 1 + int(time // precision))])
(Optional) periodicity (numpy.ndarray
[shape=(1, 1 + int(time // precision))])
"""
results = []
# Preprocess audio
generator = preprocess(audio,
sample_rate,
precision,
batch_size,
pad)
for frames in generator:
# Infer independent probabilities for each pitch bin
probabilities = infer(session, frames) # shape=(batch, 360)
probabilities = probabilities.transpose(1, 0)[None] # shape=(1, 360, batch)
# Convert probabilities to F0 and periodicity
result = postprocess(probabilities,
fmin,
fmax,
decoder,
return_periodicity)
# Place on same device as audio to allow very long inputs
if isinstance(result, tuple):
result = (result[0], result[1])
results.append(result)
# Split pitch and periodicity
if return_periodicity:
pitch, periodicity = zip(*results)
return np.concatenate(pitch, axis=1), np.concatenate(periodicity, axis=1)
# Concatenate
return np.concatenate(results, axis=1)
def preprocess(audio,
sample_rate,
precision=None,
batch_size=None,
pad=True):
"""Convert audio to model input
Arguments
audio (numpy.ndarray [shape=(time,)])
The audio signals
sample_rate (int)
The sampling rate in Hz
precision (float)
The precision in milliseconds, i.e. the length of each frame
batch_size (int)
The number of frames per batch
pad (bool)
Whether to zero-pad the audio
Returns
frames (numpy.ndarray [shape=(1 + int(time // precision), 1024)])
"""
# Resample
if sample_rate != SAMPLE_RATE:
audio = librosa.resample(audio, orig_sr=sample_rate, target_sr=SAMPLE_RATE)
# Default hop length of 10 ms
hop_length = SAMPLE_RATE / 100 if precision is None else SAMPLE_RATE * precision / 1000
# Get total number of frames
# Maybe pad
if pad:
total_frames = 1 + int(audio.shape[0] / hop_length)
audio = np.pad(
audio,
(WINDOW_SIZE // 2, WINDOW_SIZE // 2))
else:
total_frames = 1 + int((audio.shape[0] - WINDOW_SIZE) / hop_length)
# Default to running all frames in a single batch
batch_size = total_frames if batch_size is None else batch_size
# Generate batches
for i in range(0, total_frames, batch_size):
# Batch indices
start = max(0, int(i * hop_length))
end = min(audio.shape[0],
int((i + batch_size - 1) * hop_length) + WINDOW_SIZE)
# Chunk
n_bytes = audio.strides[-1]
frames = np.lib.stride_tricks.as_strided(
audio[start:end],
shape=((end - start - WINDOW_SIZE) // int(hop_length) + 1, WINDOW_SIZE),
strides=(int(hop_length) * n_bytes, n_bytes)) # shape=(batch, 1024)
# Note:
# Z-score standardization operations originally located here
# (https://github.com/maxrmorrison/torchcrepe/blob/master/torchcrepe/core.py#L692)
# are wrapped into the ONNX models for hardware acceleration.
yield frames
def infer(session, frames):
"""Forward pass through the model
Arguments
session (onnxcrepe.CrepeInferenceSession)
An onnxruntime.InferenceSession holding the CREPE model
frames (numpy.ndarray [shape=(time / precision, 1024)])
The network input
Returns
logits (numpy.ndarray [shape=(1 + int(time // precision), 360)])
"""
# Apply model
return session.run(None, {'frames': frames})[0]
def postprocess(probabilities,
fmin=0.,
fmax=MAX_FMAX,
decoder=onnxcrepe.decode.weighted_viterbi,
return_periodicity=False):
"""Convert model output to F0 and periodicity
Arguments
probabilities (numpy.ndarray [shape=(1, 360, time / precision)])
The probabilities for each pitch bin inferred by the network
fmin (float)
The minimum allowable frequency in Hz
fmax (float)
The maximum allowable frequency in Hz
decoder (function)
The decoder to use. See decode.py for decoders.
return_periodicity (bool)
Whether to also return the network confidence
Returns
pitch (numpy.ndarray [shape=(1, 1 + int(time // precision))])
periodicity (numpy.ndarray [shape=(1, 1 + int(time // precision))])
"""
# Convert frequency range to pitch bin range
minidx = onnxcrepe.convert.frequency_to_bins(fmin)
maxidx = onnxcrepe.convert.frequency_to_bins(fmax, np.ceil)
# Remove frequencies outside allowable range
probabilities[:, :minidx] = float('-inf')
probabilities[:, maxidx:] = float('-inf')
# Perform argmax or viterbi sampling
bins, pitch = decoder(probabilities)
if not return_periodicity:
return pitch
# Compute periodicity from probabilities and decoded pitch bins
return pitch, periodicity(probabilities, bins)
###############################################################################
# Utilities
###############################################################################
def periodicity(probabilities, bins):
"""Computes the periodicity from the network output and pitch bins"""
# shape=(time / precision, 360)
probs_stacked = probabilities.transpose(0, 2, 1).reshape(-1, PITCH_BINS)
# shape=(time / precision, 1)
bins_stacked = bins.reshape(-1, 1).astype(np.int64)
# Use maximum logit over pitch bins as periodicity
periodicity = np.take_along_axis(probs_stacked, bins_stacked, axis=1)
# shape=(batch, time / precision)
return periodicity.reshape(probabilities.shape[0], probabilities.shape[2])
def resample(audio, sample_rate):
"""Resample audio"""
return librosa.resample(audio, orig_sr=sample_rate, target_sr=onnxcrepe.SAMPLE_RATE)

View File

@ -0,0 +1,80 @@
import librosa
import numpy as np
from voice_changer.RVC.pitchExtractor import onnxcrepe
###############################################################################
# Probability sequence decoding methods
###############################################################################
def argmax(logits):
"""Sample observations by taking the argmax"""
bins = logits.argmax(axis=1)
# Convert to frequency in Hz
return bins, onnxcrepe.convert.bins_to_frequency(bins)
def weighted_argmax(logits: np.ndarray):
"""Sample observations using weighted sum near the argmax"""
# Find center of analysis window
bins = logits.argmax(axis=1)
return bins, _apply_weights(logits, bins)
def viterbi(logits):
"""Sample observations using viterbi decoding"""
# Create viterbi transition matrix
if not hasattr(viterbi, 'transition'):
xx, yy = np.meshgrid(range(360), range(360))
transition = np.maximum(12 - abs(xx - yy), 0)
transition = transition / transition.sum(axis=1, keepdims=True)
viterbi.transition = transition
# Normalize logits (softmax)
logits -= logits.max(axis=1)
exp = np.exp(logits)
probs = exp / np.sum(exp, axis=1)
# Perform viterbi decoding
bins = np.array([
librosa.sequence.viterbi(sequence, viterbi.transition).astype(np.int64)
for sequence in probs])
# Convert to frequency in Hz
return bins, onnxcrepe.convert.bins_to_frequency(bins)
def weighted_viterbi(logits):
"""Sample observations combining viterbi decoding and weighted argmax"""
bins, _ = viterbi(logits)
return bins, _apply_weights(logits, bins)
def _apply_weights(logits, bins):
# Find bounds of analysis window
start = np.maximum(0, bins - 4)
end = np.minimum(logits.shape[1], bins + 5)
# Mask out everything outside of window
for batch in range(logits.shape[0]):
for time in range(logits.shape[2]):
logits[batch, :start[batch, time], time] = float('-inf')
logits[batch, end[batch, time]:, time] = float('-inf')
# Construct weights
if not hasattr(_apply_weights, 'weights'):
weights = onnxcrepe.convert.bins_to_cents(np.arange(360))
_apply_weights.weights = weights[None, :, None]
# Convert to probabilities (ReLU)
probs = np.maximum(0, logits)
# Apply weights
cents = (_apply_weights.weights * probs).sum(axis=1) / probs.sum(axis=1)
# Convert to frequency in Hz
return onnxcrepe.convert.cents_to_frequency(cents)

View File

@ -0,0 +1,125 @@
import numpy as np
###############################################################################
# Sequence filters
###############################################################################
def mean(signals, win_length=9):
"""Averave filtering for signals containing nan values
Arguments
signals (numpy.ndarray (shape=(batch, time)))
The signals to filter
win_length
The size of the analysis window
Returns
filtered (numpy.ndarray (shape=(batch, time)))
"""
return nanfilter(signals, win_length, nanmean)
def median(signals, win_length):
"""Median filtering for signals containing nan values
Arguments
signals (numpy.ndarray (shape=(batch, time)))
The signals to filter
win_length
The size of the analysis window
Returns
filtered (numpy.ndarray (shape=(batch, time)))
"""
return nanfilter(signals, win_length, nanmedian)
###############################################################################
# Utilities
###############################################################################
def nanfilter(signals, win_length, filter_fn):
"""Filters a sequence, ignoring nan values
Arguments
signals (numpy.ndarray (shape=(batch, time)))
The signals to filter
win_length
The size of the analysis window
filter_fn (function)
The function to use for filtering
Returns
filtered (numpy.ndarray (shape=(batch, time)))
"""
# Output buffer
filtered = np.empty_like(signals)
# Loop over frames
for i in range(signals.shape[1]):
# Get analysis window bounds
start = max(0, i - win_length // 2)
end = min(signals.shape[1], i + win_length // 2 + 1)
# Apply filter to window
filtered[:, i] = filter_fn(signals[:, start:end])
return filtered
def nanmean(signals):
"""Computes the mean, ignoring nans
Arguments
signals (numpy.ndarray [shape=(batch, time)])
The signals to filter
Returns
filtered (numpy.ndarray [shape=(batch, time)])
"""
signals = signals.clone()
# Find nans
nans = np.isnan(signals)
# Set nans to 0.
signals[nans] = 0.
# Compute average
return signals.sum(axis=1) / (~nans).astype(np.float32).sum(axis=1)
def nanmedian(signals):
"""Computes the median, ignoring nans
Arguments
signals (numpy.ndarray [shape=(batch, time)])
The signals to filter
Returns
filtered (numpy.ndarray [shape=(batch, time)])
"""
# Find nans
nans = np.isnan(signals)
# Compute median for each slice
medians = [nanmedian1d(signal[~nan]) for signal, nan in zip(signals, nans)]
# Stack results
return np.array(medians, dtype=signals.dtype)
def nanmedian1d(signal):
"""Computes the median. If signal is empty, returns torch.nan
Arguments
signal (numpy.ndarray [shape=(time,)])
Returns
median (numpy.ndarray [shape=(1,)])
"""
return np.median(signal) if signal.size else np.nan

View File

@ -0,0 +1,12 @@
import librosa
import numpy as np
def audio(filename):
"""Load audio from disk"""
samples, sr = librosa.load(filename, sr=None)
if len(samples.shape) > 1:
# To mono
samples = np.mean(samples, axis=1)
return samples, sr

View File

@ -0,0 +1,73 @@
import warnings
import librosa
import numpy as np
from voice_changer.RVC.pitchExtractor import onnxcrepe
###############################################################################
# Constants
###############################################################################
# Minimum decibel level
MIN_DB = -100.
# Reference decibel level
REF_DB = 20.
###############################################################################
# A-weighted loudness
###############################################################################
def a_weighted(audio, sample_rate, hop_length=None, pad=True):
"""Retrieve the per-frame loudness"""
# Default hop length of 10 ms
hop_length = sample_rate // 100 if hop_length is None else hop_length
# Convert to numpy
audio = audio.squeeze(0)
# Resample
if sample_rate != onnxcrepe.SAMPLE_RATE:
audio = librosa.resample(audio, orig_sr=sample_rate, target_sr=onnxcrepe.SAMPLE_RATE)
hop_length = int(hop_length * onnxcrepe.SAMPLE_RATE / sample_rate)
# Cache weights
if not hasattr(a_weighted, 'weights'):
a_weighted.weights = perceptual_weights()
# Take stft
stft = librosa.stft(audio,
n_fft=onnxcrepe.WINDOW_SIZE,
hop_length=hop_length,
win_length=onnxcrepe.WINDOW_SIZE,
center=pad,
pad_mode='constant')
# Compute magnitude on db scale
db = librosa.amplitude_to_db(np.abs(stft))
# Apply A-weighting
weighted = db + a_weighted.weights
# Threshold
weighted[weighted < MIN_DB] = MIN_DB
# Average over weighted frequencies
return weighted.mean(axis=0).astype(np.float32)[None]
def perceptual_weights():
"""A-weighted frequency-dependent perceptual loudness weights"""
frequencies = librosa.fft_frequencies(sr=onnxcrepe.SAMPLE_RATE,
n_fft=onnxcrepe.WINDOW_SIZE)
# A warning is raised for nearly inaudible frequencies, but it ends up
# defaulting to -100 db. That default is fine for our purposes.
with warnings.catch_warnings():
warnings.simplefilter('ignore', RuntimeWarning)
return librosa.A_weighting(frequencies)[:, None] - REF_DB

View File

@ -0,0 +1 @@
modules in this folder from https://github.com/yqzhishen/onnxcrepe at ca7e5d7f2dfca5cc4d99e8d546b00793ca4e7157

View File

@ -0,0 +1,9 @@
import os
import onnxruntime as ort
class CrepeInferenceSession(ort.InferenceSession):
def __init__(self, model='full', sess_options=None, providers=None, provider_options=None, **kwargs):
model_path = os.path.join(os.path.dirname(__file__), 'assets', f'{model}.onnx')
super().__init__(model_path, sess_options, providers, provider_options, **kwargs)

View File

@ -0,0 +1,129 @@
import numpy as np
from voice_changer.RVC.pitchExtractor import onnxcrepe
###############################################################################
# Pitch thresholding methods
###############################################################################
class At:
"""Simple thresholding at a specified probability value"""
def __init__(self, value):
self.value = value
def __call__(self, pitch, periodicity):
# Make a copy to prevent in-place modification
pitch = pitch.copy()
# Threshold
pitch[periodicity < self.value] = onnxcrepe.UNVOICED
return pitch
class Hysteresis:
"""Hysteresis thresholding"""
def __init__(self,
lower_bound=.19,
upper_bound=.31,
width=.2,
stds=1.7,
return_threshold=False):
self.lower_bound = lower_bound
self.upper_bound = upper_bound
self.width = width
self.stds = stds
self.return_threshold = return_threshold
def __call__(self, pitch, periodicity):
# Perform hysteresis in log-2 space
pitch = np.log2(pitch).flatten()
# Flatten periodicity
periodicity = periodicity.flatten()
# Ignore confidently unvoiced pitch
pitch[periodicity < self.lower_bound] = onnxcrepe.UNVOICED
# Whiten pitch
mean, std = np.nanmean(pitch), np.nanstd(pitch)
pitch = (pitch - mean) / std
# Require high confidence to make predictions far from the mean
parabola = self.width * pitch ** 2 - self.width * self.stds ** 2
threshold = self.lower_bound + np.clip(parabola, 0, 1 - self.lower_bound)
threshold[np.isnan(threshold)] = self.lower_bound
# Apply hysteresis to prevent short, unconfident voiced regions
i = 0
while i < len(periodicity) - 1:
# Detect unvoiced to voiced transition
if periodicity[i] < threshold[i] and periodicity[i + 1] > threshold[i + 1]:
# Grow region until next unvoiced or end of array
start, end, keep = i + 1, i + 1, False
while end < len(periodicity) and periodicity[end] > threshold[end]:
if periodicity[end] > self.upper_bound:
keep = True
end += 1
# Force unvoiced if we didn't pass the confidence required by
# the hysteresis
if not keep:
threshold[start:end] = 1
i = end
else:
i += 1
# Remove pitch with low periodicity
pitch[periodicity < threshold] = onnxcrepe.UNVOICED
# Unwhiten
pitch = pitch * std + mean
# Convert to Hz
pitch = np.array(2 ** pitch)[None, :]
# Optionally return threshold
if self.return_threshold:
return pitch, np.array(threshold)
return pitch
###############################################################################
# Periodicity thresholding methods
###############################################################################
class Silence:
"""Set periodicity to zero in silent regions"""
def __init__(self, value=-60):
self.value = value
def __call__(self,
periodicity,
audio,
sample_rate=onnxcrepe.SAMPLE_RATE,
precision=None,
pad=True):
# Don't modify in-place
periodicity = periodicity.copy()
# Compute loudness
hop_length = sample_rate * precision // 1000
loudness = onnxcrepe.loudness.a_weighted(
audio, sample_rate, hop_length, pad)
# Threshold silence
periodicity[loudness < self.value] = 0.
return periodicity

View File

@ -1,5 +1,6 @@
import json
import os
import sys
import shutil
import threading
import numpy as np
@ -169,6 +170,7 @@ class VoiceChangerManager(ServerDeviceCallbacks):
data["gpus"] = self.gpus
data["modelSlots"] = self.modelSlotManager.getAllSlotInfo(reload=True)
data["sampleModels"] = getSampleInfos(self.params.sample_mode)
data["python"] = sys.version
data["status"] = "OK"

View File

@ -12,3 +12,5 @@ class VoiceChangerParams:
hubert_soft: str
nsf_hifigan: str
sample_mode: str
crepe_onnx_full: str
crepe_onnx_tiny: str

View File

@ -80,6 +80,14 @@ Q3. The pitch is off.
A3. Although it wasn't explained in the Quick Start, if the model is pitch-changeable, you can change it with TUNE. Please refer to the more detailed explanation below.
Q4. The window doesn't show up or the window shows up but the contents are not displayed. A console error such as `electron: Failed to load URL: http://localhost:18888/ with error: ERR_CONNECTION_REFUSED` is displayed.
A4. There is a possibility that the virus checker is running. Please wait or designate the folder to be excluded at your own risk.
Q5. `[4716:0429/213736.103:ERROR:gpu_init.cc(523)] Passthrough is not supported, GL is disabled, ANGLE is` is displayed
A5. This is an error produced by the library used by this application, but it does not have any effect, so please ignore it.
## Configurable items
## Title

View File

@ -36,6 +36,7 @@
`.bat`ファイル(win)や`.command`ファイル(mac)を実行すると、次のような画面が表示され、初回起動時には各種データをインターネットからダウンロードします。
お使いの環境によりますが、多くの場合1~2分かかります。
![image](https://github.com/w-okada/voice-changer/assets/48346627/88a30097-2fb3-4c50-8bf1-19c41f27c481)
### GUI 表示
@ -80,6 +81,14 @@ Q3. 音程がおかしい
A3. クイックスタートでは説明しませんでしたが、Pitch 変更可能なモデルであれば TUNE で変更できます。後述の詳細説明をご確認ください。
Q4. ウィンドウが表示されない。あるいはウィンドウは表示されるが中身が表示されない。コンソールに`electron: Failed to load URL: http://localhost:18888/ with error: ERR_CONNECTION_REFUSED`のようなエラーが表示される。
A4. ウィルスチェッカーが走っている可能性があります。しばらく待つか、自己責任でフォルダを除外指定してください。
Q5. `[4716:0429/213736.103:ERROR:gpu_init.cc(523)] Passthrough is not supported, GL is disabled, ANGLE is`という表示が出る
A5. 使用しているライブラリが出しているエラーです。影響はありませんので無視してください。
# GUI の詳細
## タイトルエリア