mirror of
https://github.com/w-okada/voice-changer.git
synced 2025-02-03 00:33:57 +03:00
This commit is contained in:
commit
d4f80eeaa8
63
README.md
63
README.md
@ -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 を同梱しただけのものです。
|
||||
|
63
README_en.md
63
README_en.md
@ -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.
|
||||
|
@ -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]
|
||||
}
|
||||
}
|
||||
|
11
client/demo/dist/index.html
vendored
11
client/demo/dist/index.html
vendored
@ -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>
|
||||
|
1125
client/demo/dist/index.js
vendored
1125
client/demo/dist/index.js
vendored
File diff suppressed because one or more lines are too long
31
client/demo/dist/index.js.LICENSE.txt
vendored
31
client/demo/dist/index.js.LICENSE.txt
vendored
@ -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.
|
||||
*/
|
235
client/demo/package-lock.json
generated
235
client/demo/package-lock.json
generated
@ -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"
|
||||
|
@ -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",
|
||||
|
@ -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]
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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>;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
};
|
@ -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) });
|
||||
}}
|
||||
|
@ -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>;
|
||||
};
|
||||
|
4
client/lib/package-lock.json
generated
4
client/lib/package-lock.json
generated
@ -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",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@dannadori/voice-changer-client-js",
|
||||
"version": "1.0.157",
|
||||
"version": "1.0.159",
|
||||
"description": "",
|
||||
"main": "dist/index.js",
|
||||
"directories": {
|
||||
|
@ -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]
|
||||
|
||||
|
@ -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 })
|
||||
|
@ -5,7 +5,6 @@ import { VoiceChangerClient } from "../VoiceChangerClient"
|
||||
|
||||
export type UseClientSettingProps = {
|
||||
voiceChangerClient: VoiceChangerClient | null
|
||||
audioContext: AudioContext | null
|
||||
voiceChangerClientSetting: VoiceChangerClientSetting
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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",
|
||||
|
@ -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"})
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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"],
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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],
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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:
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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
|
57
server/voice_changer/RVC/pitchExtractor/onnxcrepe/convert.py
Normal file
57
server/voice_changer/RVC/pitchExtractor/onnxcrepe/convert.py
Normal 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)
|
256
server/voice_changer/RVC/pitchExtractor/onnxcrepe/core.py
Normal file
256
server/voice_changer/RVC/pitchExtractor/onnxcrepe/core.py
Normal 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)
|
80
server/voice_changer/RVC/pitchExtractor/onnxcrepe/decode.py
Normal file
80
server/voice_changer/RVC/pitchExtractor/onnxcrepe/decode.py
Normal 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)
|
125
server/voice_changer/RVC/pitchExtractor/onnxcrepe/filter.py
Normal file
125
server/voice_changer/RVC/pitchExtractor/onnxcrepe/filter.py
Normal 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
|
12
server/voice_changer/RVC/pitchExtractor/onnxcrepe/load.py
Normal file
12
server/voice_changer/RVC/pitchExtractor/onnxcrepe/load.py
Normal 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
|
@ -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
|
@ -0,0 +1 @@
|
||||
modules in this folder from https://github.com/yqzhishen/onnxcrepe at ca7e5d7f2dfca5cc4d99e8d546b00793ca4e7157
|
@ -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)
|
129
server/voice_changer/RVC/pitchExtractor/onnxcrepe/threshold.py
Normal file
129
server/voice_changer/RVC/pitchExtractor/onnxcrepe/threshold.py
Normal 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
|
@ -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"
|
||||
|
||||
|
@ -12,3 +12,5 @@ class VoiceChangerParams:
|
||||
hubert_soft: str
|
||||
nsf_hifigan: str
|
||||
sample_mode: str
|
||||
crepe_onnx_full: str
|
||||
crepe_onnx_tiny: str
|
||||
|
@ -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
|
||||
|
@ -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 の詳細
|
||||
|
||||
## タイトルエリア
|
||||
|
Loading…
Reference in New Issue
Block a user