├── readme ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png ├── 6.png ├── 7.png ├── 8.png ├── 9.png ├── 10.png ├── 11.png ├── 12.png ├── 13.png ├── token.png └── cyberchat.png ├── ChatWithGPT └── game │ ├── gui │ ├── nvl.png │ ├── skip.png │ ├── bar │ │ ├── top.png │ │ ├── left.png │ │ ├── right.png │ │ └── bottom.png │ ├── frame.png │ ├── namebox.png │ ├── notify.png │ ├── textbox.png │ ├── game_menu.png │ ├── main_menu.png │ ├── phone │ │ ├── nvl.png │ │ ├── bar │ │ │ ├── left.png │ │ │ ├── top.png │ │ │ ├── bottom.png │ │ │ └── right.png │ │ ├── textbox.png │ │ ├── overlay │ │ │ ├── game_menu.png │ │ │ └── main_menu.png │ │ ├── button │ │ │ ├── check_foreground.png │ │ │ ├── hover_background.png │ │ │ ├── idle_background.png │ │ │ ├── radio_foreground.png │ │ │ ├── slot_hover_background.png │ │ │ ├── slot_idle_background.png │ │ │ ├── choice_hover_background.png │ │ │ ├── choice_idle_background.png │ │ │ ├── check_selected_foreground.png │ │ │ └── radio_selected_foreground.png │ │ ├── slider │ │ │ ├── horizontal_idle_bar.png │ │ │ ├── vertical_hover_bar.png │ │ │ ├── vertical_idle_bar.png │ │ │ ├── vertical_idle_thumb.png │ │ │ ├── horizontal_hover_bar.png │ │ │ ├── horizontal_idle_thumb.png │ │ │ ├── vertical_hover_thumb.png │ │ │ └── horizontal_hover_thumb.png │ │ └── scrollbar │ │ │ ├── vertical_hover_bar.png │ │ │ ├── vertical_idle_bar.png │ │ │ ├── horizontal_hover_bar.png │ │ │ ├── horizontal_idle_bar.png │ │ │ ├── horizontal_idle_thumb.png │ │ │ ├── vertical_hover_thumb.png │ │ │ ├── vertical_idle_thumb.png │ │ │ └── horizontal_hover_thumb.png │ ├── window_icon.png │ ├── overlay │ │ ├── confirm.png │ │ ├── game_menu.png │ │ └── main_menu.png │ ├── button │ │ ├── idle_background.png │ │ ├── check_foreground.png │ │ ├── hover_background.png │ │ ├── radio_foreground.png │ │ ├── slot_idle_background.png │ │ ├── choice_idle_background.png │ │ ├── quick_hover_background.png │ │ ├── quick_idle_background.png │ │ ├── slot_hover_background.png │ │ ├── check_selected_foreground.png │ │ ├── choice_hover_background.png │ │ └── radio_selected_foreground.png │ ├── slider │ │ ├── vertical_idle_bar.png │ │ ├── horizontal_hover_bar.png │ │ ├── horizontal_idle_bar.png │ │ ├── vertical_hover_bar.png │ │ ├── vertical_hover_thumb.png │ │ ├── vertical_idle_thumb.png │ │ ├── horizontal_hover_thumb.png │ │ └── horizontal_idle_thumb.png │ └── scrollbar │ │ ├── vertical_idle_bar.png │ │ ├── horizontal_idle_bar.png │ │ ├── vertical_hover_bar.png │ │ ├── vertical_idle_thumb.png │ │ ├── horizontal_hover_bar.png │ │ ├── horizontal_hover_thumb.png │ │ ├── horizontal_idle_thumb.png │ │ └── vertical_hover_thumb.png │ ├── tl │ └── None │ │ └── common.rpymc │ ├── SourceHanSansLite.ttf │ ├── Resources │ └── Hiyori │ │ ├── Hiyori.moc3 │ │ ├── Hiyori.2048 │ │ ├── texture_00.png │ │ └── texture_01.png │ │ ├── Hiyori.pose3.json │ │ ├── Hiyori.userdata3.json │ │ ├── hiyori.model3.json │ │ ├── Hiyori.cdi3.json │ │ └── motions │ │ ├── Hiyori_m04.motion3.json │ │ ├── Hiyori_talking.motion3.json │ │ ├── Hiyori_m10.motion3.json │ │ └── Hiyori_m07.motion3.json │ ├── script.rpy │ └── options.rpy ├── .vscode └── settings.json ├── requirements.txt ├── text ├── __init__.py ├── LICENSE ├── thai.py ├── ngu_dialect.py ├── sanskrit.py ├── cantonese.py ├── shanghainese.py ├── japanese.py ├── english.py ├── cleaners.py ├── korean.py └── mandarin.py ├── LICENSE ├── README-original.md ├── README.md ├── utils.py ├── commons.py ├── mel_processing.py ├── .gitignore ├── hubert_model.py ├── transforms.py ├── server.py └── attentions.py /readme/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/readme/1.png -------------------------------------------------------------------------------- /readme/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/readme/2.png -------------------------------------------------------------------------------- /readme/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/readme/3.png -------------------------------------------------------------------------------- /readme/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/readme/4.png -------------------------------------------------------------------------------- /readme/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/readme/5.png -------------------------------------------------------------------------------- /readme/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/readme/6.png -------------------------------------------------------------------------------- /readme/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/readme/7.png -------------------------------------------------------------------------------- /readme/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/readme/8.png -------------------------------------------------------------------------------- /readme/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/readme/9.png -------------------------------------------------------------------------------- /readme/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/readme/10.png -------------------------------------------------------------------------------- /readme/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/readme/11.png -------------------------------------------------------------------------------- /readme/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/readme/12.png -------------------------------------------------------------------------------- /readme/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/readme/13.png -------------------------------------------------------------------------------- /readme/token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/readme/token.png -------------------------------------------------------------------------------- /readme/cyberchat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/readme/cyberchat.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/nvl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/nvl.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/skip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/skip.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/bar/top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/bar/top.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/frame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/frame.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/namebox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/namebox.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/notify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/notify.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/textbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/textbox.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/bar/left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/bar/left.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/bar/right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/bar/right.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/game_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/game_menu.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/main_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/main_menu.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/nvl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/nvl.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/bar/bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/bar/bottom.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/window_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/window_icon.png -------------------------------------------------------------------------------- /ChatWithGPT/game/tl/None/common.rpymc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/tl/None/common.rpymc -------------------------------------------------------------------------------- /ChatWithGPT/game/SourceHanSansLite.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/SourceHanSansLite.ttf -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/bar/left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/bar/left.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/bar/top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/bar/top.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/textbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/textbox.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/overlay/confirm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/overlay/confirm.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/overlay/game_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/overlay/game_menu.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/overlay/main_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/overlay/main_menu.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/bar/bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/bar/bottom.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/bar/right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/bar/right.png -------------------------------------------------------------------------------- /ChatWithGPT/game/Resources/Hiyori/Hiyori.moc3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/Resources/Hiyori/Hiyori.moc3 -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/button/idle_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/button/idle_background.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/button/check_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/button/check_foreground.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/button/hover_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/button/hover_background.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/button/radio_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/button/radio_foreground.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/overlay/game_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/overlay/game_menu.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/overlay/main_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/overlay/main_menu.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/slider/vertical_idle_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/slider/vertical_idle_bar.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/button/slot_idle_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/button/slot_idle_background.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/scrollbar/vertical_idle_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/scrollbar/vertical_idle_bar.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/slider/horizontal_hover_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/slider/horizontal_hover_bar.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/slider/horizontal_idle_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/slider/horizontal_idle_bar.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/slider/vertical_hover_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/slider/vertical_hover_bar.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/slider/vertical_hover_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/slider/vertical_hover_thumb.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/slider/vertical_idle_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/slider/vertical_idle_thumb.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/button/choice_idle_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/button/choice_idle_background.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/button/quick_hover_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/button/quick_hover_background.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/button/quick_idle_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/button/quick_idle_background.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/button/slot_hover_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/button/slot_hover_background.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/button/check_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/button/check_foreground.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/button/hover_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/button/hover_background.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/button/idle_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/button/idle_background.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/button/radio_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/button/radio_foreground.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/scrollbar/horizontal_idle_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/scrollbar/horizontal_idle_bar.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/scrollbar/vertical_hover_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/scrollbar/vertical_hover_bar.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/scrollbar/vertical_idle_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/scrollbar/vertical_idle_thumb.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/slider/horizontal_hover_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/slider/horizontal_hover_thumb.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/slider/horizontal_idle_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/slider/horizontal_idle_thumb.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/button/check_selected_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/button/check_selected_foreground.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/button/choice_hover_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/button/choice_hover_background.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/button/radio_selected_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/button/radio_selected_foreground.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/slider/horizontal_idle_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/slider/horizontal_idle_bar.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/slider/vertical_hover_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/slider/vertical_hover_bar.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/slider/vertical_idle_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/slider/vertical_idle_bar.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/slider/vertical_idle_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/slider/vertical_idle_thumb.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/scrollbar/horizontal_hover_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/scrollbar/horizontal_hover_bar.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/scrollbar/horizontal_hover_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/scrollbar/horizontal_hover_thumb.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/scrollbar/horizontal_idle_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/scrollbar/horizontal_idle_thumb.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/scrollbar/vertical_hover_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/scrollbar/vertical_hover_thumb.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/button/slot_hover_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/button/slot_hover_background.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/button/slot_idle_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/button/slot_idle_background.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/scrollbar/vertical_hover_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/scrollbar/vertical_hover_bar.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/scrollbar/vertical_idle_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/scrollbar/vertical_idle_bar.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/slider/horizontal_hover_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/slider/horizontal_hover_bar.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/slider/horizontal_idle_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/slider/horizontal_idle_thumb.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/slider/vertical_hover_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/slider/vertical_hover_thumb.png -------------------------------------------------------------------------------- /ChatWithGPT/game/Resources/Hiyori/Hiyori.2048/texture_00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/Resources/Hiyori/Hiyori.2048/texture_00.png -------------------------------------------------------------------------------- /ChatWithGPT/game/Resources/Hiyori/Hiyori.2048/texture_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/Resources/Hiyori/Hiyori.2048/texture_01.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/button/choice_hover_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/button/choice_hover_background.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/button/choice_idle_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/button/choice_idle_background.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/scrollbar/horizontal_hover_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/scrollbar/horizontal_hover_bar.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/scrollbar/horizontal_idle_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/scrollbar/horizontal_idle_bar.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/scrollbar/horizontal_idle_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/scrollbar/horizontal_idle_thumb.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/scrollbar/vertical_hover_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/scrollbar/vertical_hover_thumb.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/scrollbar/vertical_idle_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/scrollbar/vertical_idle_thumb.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/slider/horizontal_hover_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/slider/horizontal_hover_thumb.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/button/check_selected_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/button/check_selected_foreground.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/button/radio_selected_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/button/radio_selected_foreground.png -------------------------------------------------------------------------------- /ChatWithGPT/game/gui/phone/scrollbar/horizontal_hover_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouor/ChatWaifu-API/HEAD/ChatWithGPT/game/gui/phone/scrollbar/horizontal_hover_thumb.png -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "**/*.rpyc": true, 4 | "**/*.rpa": true, 5 | "**/*.rpymc": true, 6 | "**/cache/": true 7 | } 8 | } -------------------------------------------------------------------------------- /ChatWithGPT/game/Resources/Hiyori/Hiyori.pose3.json: -------------------------------------------------------------------------------- 1 | { 2 | "Type": "Live2D Pose", 3 | "FadeInTime": 0.5, 4 | "Groups": [ 5 | [ 6 | { 7 | "Id": "PartArmA", 8 | "Link": [] 9 | }, 10 | { 11 | "Id": "PartArmB", 12 | "Link": [] 13 | } 14 | ] 15 | ] 16 | } -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | numba 2 | librosa 3 | numpy 4 | scipy 5 | torch 6 | unidecode 7 | openjtalk>=0.3.0.dev2 8 | jamo 9 | pypinyin 10 | jieba 11 | protobuf 12 | cn2an 13 | inflect 14 | eng_to_ipa 15 | ko_pron 16 | indic_transliteration 17 | num_thai 18 | opencc 19 | vosk 20 | sounddevice 21 | pydub 22 | openai 23 | navertts -------------------------------------------------------------------------------- /ChatWithGPT/game/Resources/Hiyori/Hiyori.userdata3.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 3, 3 | "Meta": { 4 | "UserDataCount": 7, 5 | "TotalUserDataSize": 35 6 | }, 7 | "UserData": [ 8 | { 9 | "Target": "ArtMesh", 10 | "Id": "ArtMesh93", 11 | "Value": "ribon" 12 | }, 13 | { 14 | "Target": "ArtMesh", 15 | "Id": "ArtMesh94", 16 | "Value": "ribon" 17 | }, 18 | { 19 | "Target": "ArtMesh", 20 | "Id": "ArtMesh95", 21 | "Value": "ribon" 22 | }, 23 | { 24 | "Target": "ArtMesh", 25 | "Id": "ArtMesh57", 26 | "Value": "ribon" 27 | }, 28 | { 29 | "Target": "ArtMesh", 30 | "Id": "ArtMesh58", 31 | "Value": "ribon" 32 | }, 33 | { 34 | "Target": "ArtMesh", 35 | "Id": "ArtMesh59", 36 | "Value": "ribon" 37 | }, 38 | { 39 | "Target": "ArtMesh", 40 | "Id": "ArtMesh60", 41 | "Value": "ribon" 42 | } 43 | ] 44 | } -------------------------------------------------------------------------------- /text/__init__.py: -------------------------------------------------------------------------------- 1 | """ from https://github.com/keithito/tacotron """ 2 | from text import cleaners 3 | 4 | 5 | def text_to_sequence(text, symbols, cleaner_names): 6 | '''Converts a string of text to a sequence of IDs corresponding to the symbols in the text. 7 | Args: 8 | text: string to convert to a sequence 9 | cleaner_names: names of the cleaner functions to run the text through 10 | Returns: 11 | List of integers corresponding to the symbols in the text 12 | ''' 13 | _symbol_to_id = {s: i for i, s in enumerate(symbols)} 14 | 15 | sequence = [] 16 | 17 | clean_text = _clean_text(text, cleaner_names) 18 | for symbol in clean_text: 19 | if symbol not in _symbol_to_id.keys(): 20 | continue 21 | symbol_id = _symbol_to_id[symbol] 22 | sequence += [symbol_id] 23 | return sequence 24 | 25 | 26 | def _clean_text(text, cleaner_names): 27 | for name in cleaner_names: 28 | cleaner = getattr(cleaners, name) 29 | if not cleaner: 30 | raise Exception('Unknown cleaner: %s' % name) 31 | text = cleaner(text) 32 | return text 33 | -------------------------------------------------------------------------------- /text/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Keith Ito 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /text/thai.py: -------------------------------------------------------------------------------- 1 | import re 2 | from num_thai.thainumbers import NumThai 3 | 4 | 5 | num = NumThai() 6 | 7 | # List of (Latin alphabet, Thai) pairs: 8 | _latin_to_thai = [(re.compile('%s' % x[0], re.IGNORECASE), x[1]) for x in [ 9 | ('a', 'เอ'), 10 | ('b','บี'), 11 | ('c','ซี'), 12 | ('d','ดี'), 13 | ('e','อี'), 14 | ('f','เอฟ'), 15 | ('g','จี'), 16 | ('h','เอช'), 17 | ('i','ไอ'), 18 | ('j','เจ'), 19 | ('k','เค'), 20 | ('l','แอล'), 21 | ('m','เอ็ม'), 22 | ('n','เอ็น'), 23 | ('o','โอ'), 24 | ('p','พี'), 25 | ('q','คิว'), 26 | ('r','แอร์'), 27 | ('s','เอส'), 28 | ('t','ที'), 29 | ('u','ยู'), 30 | ('v','วี'), 31 | ('w','ดับเบิลยู'), 32 | ('x','เอ็กซ์'), 33 | ('y','วาย'), 34 | ('z','ซี') 35 | ]] 36 | 37 | 38 | def num_to_thai(text): 39 | return re.sub(r'(?:\d+(?:,?\d+)?)+(?:\.\d+(?:,?\d+)?)?', lambda x: ''.join(num.NumberToTextThai(float(x.group(0).replace(',', '')))), text) 40 | 41 | def latin_to_thai(text): 42 | for regex, replacement in _latin_to_thai: 43 | text = re.sub(regex, replacement, text) 44 | return text 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 CjangCjengh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /text/ngu_dialect.py: -------------------------------------------------------------------------------- 1 | import re 2 | import opencc 3 | 4 | 5 | dialects = {'SZ': 'suzhou', 'WX': 'wuxi', 'CZ': 'changzhou', 'HZ': 'hangzhou', 6 | 'SX': 'shaoxing', 'NB': 'ningbo', 'JJ': 'jingjiang', 'YX': 'yixing', 7 | 'JD': 'jiading', 'ZR': 'zhenru', 'PH': 'pinghu', 'TX': 'tongxiang', 8 | 'JS': 'jiashan', 'HN': 'xiashi', 'LP': 'linping', 'XS': 'xiaoshan', 9 | 'FY': 'fuyang', 'RA': 'ruao', 'CX': 'cixi', 'SM': 'sanmen', 10 | 'TT': 'tiantai', 'WZ': 'wenzhou', 'SC': 'suichang', 'YB': 'youbu'} 11 | 12 | converters = {} 13 | 14 | for dialect in dialects.values(): 15 | try: 16 | converters[dialect] = opencc.OpenCC(dialect) 17 | except: 18 | pass 19 | 20 | 21 | def ngu_dialect_to_ipa(text, dialect): 22 | dialect = dialects[dialect] 23 | text = converters[dialect].convert(text).replace('-','').replace('$',' ') 24 | text = re.sub(r'[、;:]', ',', text) 25 | text = re.sub(r'\s*,\s*', ', ', text) 26 | text = re.sub(r'\s*。\s*', '. ', text) 27 | text = re.sub(r'\s*?\s*', '? ', text) 28 | text = re.sub(r'\s*!\s*', '! ', text) 29 | text = re.sub(r'\s*$', '', text) 30 | return text 31 | -------------------------------------------------------------------------------- /README-original.md: -------------------------------------------------------------------------------- 1 | ![cover](readme/cyberchat.png) 2 | 3 |

4 | GitHub 5 | PYTHON 6 | 7 |

8 | 9 | [Korean](README.md) 10 | 11 | > ### 这是一个基于TTS+VITS的ChatGPT语音对话程序! 12 | 13 | 效果演示BiliBIli:[《青春猪头少年不会梦见赛博女友》](https://www.bilibili.com/video/BV1rv4y1Q7eT "BiliBili") 14 | 15 | **当前支持功能:** 16 | * [x] ChatGPT的对话聊天 17 | * [x] 回答转语音 18 | * [x] 多角色语音 19 | * [x] 语音识别对话 (研发了一款真正人性化的智能语音Q宝 20 | * [x] 对接Live2D的Web版本 21 | * [x] [对接Marai机器人](https://github.com/MuBai-He/ChatWaifu-marai) 22 | 23 | # 运行方法 24 | #### 如果您在国内,可能需要使用vpn 25 | 26 | # 如何获取Token 27 | #### 在浏览器登入https://api.openai.com 28 | #### 在个人账号界面添加新的api token并复制保存 29 | #### 将值复制进入游戏并回车 30 | 31 | ## 6.鸣谢: 32 | - [MoeGoe_GUI]https://github.com/CjangCjengh/MoeGoe_GUI 33 | - [Pretrained models]https://github.com/CjangCjengh/TTSModels 34 | -------------------------------------------------------------------------------- /text/sanskrit.py: -------------------------------------------------------------------------------- 1 | import re 2 | from indic_transliteration import sanscript 3 | 4 | 5 | # List of (iast, ipa) pairs: 6 | _iast_to_ipa = [(re.compile('%s' % x[0]), x[1]) for x in [ 7 | ('a', 'ə'), 8 | ('ā', 'aː'), 9 | ('ī', 'iː'), 10 | ('ū', 'uː'), 11 | ('ṛ', 'ɹ`'), 12 | ('ṝ', 'ɹ`ː'), 13 | ('ḷ', 'l`'), 14 | ('ḹ', 'l`ː'), 15 | ('e', 'eː'), 16 | ('o', 'oː'), 17 | ('k', 'k⁼'), 18 | ('k⁼h', 'kʰ'), 19 | ('g', 'g⁼'), 20 | ('g⁼h', 'gʰ'), 21 | ('ṅ', 'ŋ'), 22 | ('c', 'ʧ⁼'), 23 | ('ʧ⁼h', 'ʧʰ'), 24 | ('j', 'ʥ⁼'), 25 | ('ʥ⁼h', 'ʥʰ'), 26 | ('ñ', 'n^'), 27 | ('ṭ', 't`⁼'), 28 | ('t`⁼h', 't`ʰ'), 29 | ('ḍ', 'd`⁼'), 30 | ('d`⁼h', 'd`ʰ'), 31 | ('ṇ', 'n`'), 32 | ('t', 't⁼'), 33 | ('t⁼h', 'tʰ'), 34 | ('d', 'd⁼'), 35 | ('d⁼h', 'dʰ'), 36 | ('p', 'p⁼'), 37 | ('p⁼h', 'pʰ'), 38 | ('b', 'b⁼'), 39 | ('b⁼h', 'bʰ'), 40 | ('y', 'j'), 41 | ('ś', 'ʃ'), 42 | ('ṣ', 's`'), 43 | ('r', 'ɾ'), 44 | ('l̤', 'l`'), 45 | ('h', 'ɦ'), 46 | ("'", ''), 47 | ('~', '^'), 48 | ('ṃ', '^') 49 | ]] 50 | 51 | 52 | def devanagari_to_ipa(text): 53 | text = text.replace('ॐ', 'ओम्') 54 | text = re.sub(r'\s*।\s*$', '.', text) 55 | text = re.sub(r'\s*।\s*', ', ', text) 56 | text = re.sub(r'\s*॥', '.', text) 57 | text = sanscript.transliterate(text, sanscript.DEVANAGARI, sanscript.IAST) 58 | for regex, replacement in _iast_to_ipa: 59 | text = re.sub(regex, replacement, text) 60 | text = re.sub('(.)[`ː]*ḥ', lambda x: x.group(0) 61 | [:-1]+'h'+x.group(1)+'*', text) 62 | return text 63 | -------------------------------------------------------------------------------- /text/cantonese.py: -------------------------------------------------------------------------------- 1 | import re 2 | import cn2an 3 | import opencc 4 | 5 | 6 | converter = opencc.OpenCC('jyutjyu') 7 | 8 | # List of (Latin alphabet, ipa) pairs: 9 | _latin_to_ipa = [(re.compile('%s' % x[0]), x[1]) for x in [ 10 | ('A', 'ei˥'), 11 | ('B', 'biː˥'), 12 | ('C', 'siː˥'), 13 | ('D', 'tiː˥'), 14 | ('E', 'iː˥'), 15 | ('F', 'e˥fuː˨˩'), 16 | ('G', 'tsiː˥'), 17 | ('H', 'ɪk̚˥tsʰyː˨˩'), 18 | ('I', 'ɐi˥'), 19 | ('J', 'tsei˥'), 20 | ('K', 'kʰei˥'), 21 | ('L', 'e˥llou˨˩'), 22 | ('M', 'ɛːm˥'), 23 | ('N', 'ɛːn˥'), 24 | ('O', 'ou˥'), 25 | ('P', 'pʰiː˥'), 26 | ('Q', 'kʰiːu˥'), 27 | ('R', 'aː˥lou˨˩'), 28 | ('S', 'ɛː˥siː˨˩'), 29 | ('T', 'tʰiː˥'), 30 | ('U', 'juː˥'), 31 | ('V', 'wiː˥'), 32 | ('W', 'tʊk̚˥piː˥juː˥'), 33 | ('X', 'ɪk̚˥siː˨˩'), 34 | ('Y', 'waːi˥'), 35 | ('Z', 'iː˨sɛːt̚˥') 36 | ]] 37 | 38 | 39 | def number_to_cantonese(text): 40 | return re.sub(r'\d+(?:\.?\d+)?', lambda x: cn2an.an2cn(x.group()), text) 41 | 42 | 43 | def latin_to_ipa(text): 44 | for regex, replacement in _latin_to_ipa: 45 | text = re.sub(regex, replacement, text) 46 | return text 47 | 48 | 49 | def cantonese_to_ipa(text): 50 | text = number_to_cantonese(text.upper()) 51 | text = converter.convert(text).replace('-','').replace('$',' ') 52 | text = re.sub(r'[A-Z]', lambda x: latin_to_ipa(x.group())+' ', text) 53 | text = re.sub(r'[、;:]', ',', text) 54 | text = re.sub(r'\s*,\s*', ', ', text) 55 | text = re.sub(r'\s*。\s*', '. ', text) 56 | text = re.sub(r'\s*?\s*', '? ', text) 57 | text = re.sub(r'\s*!\s*', '! ', text) 58 | text = re.sub(r'\s*$', '', text) 59 | return text 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![cover](readme/cyberchat.png) 2 | 3 |

4 | GitHub 5 | PYTHON 6 | 7 |

8 | 9 | [original readme](README-original.md) 10 | 11 | > ## How to run 12 | ### Create virtual environment (optional) 13 | ``` 14 | python -m venv venv 15 | venv\Scripts\activate 16 | ``` 17 | ### Install pytorch 18 | ``` 19 | pip3 install torch==1.13.1 torchvision==0.14.1 torchaudio==0.13.1 --index-url https://download.pytorch.org/whl/cu117 20 | ``` 21 | ### Install requirements 22 | ``` 23 | pip3 install -r requirements.txt 24 | ``` 25 | if error occurs, install visual studio and build tools and try again. 26 | 27 | ### Install Ren'py 28 | - Download [Ren'py sdk](https://www.renpy.org/latest.html) and add path to environment variable 29 | - Install Live2D library 30 | ``` 31 | Setting - Install library - Install Live2D Cubism 32 | ``` 33 | 34 | ### Place your vits model ./userfile/tts/ 35 | such this structure: 36 | ``` 37 | ──┬─userfile/tts/ 38 | ├── config.json 39 | └── G_128000.pth 40 | ``` 41 | 42 | ### Run server 43 | ``` 44 | python server.py 45 | ``` 46 | 47 | ### Run game 48 | ``` 49 | renpy ./ChatWithGPT/ 50 | ``` 51 | You can get api key [here](https://platform.openai.com/account/api-keys) 52 | 53 | ## VITS credit 54 | - [MoeGoe_GUI]https://github.com/CjangCjengh/MoeGoe_GUI 55 | - [Pretrained models]https://github.com/CjangCjengh/TTSModels 56 | -------------------------------------------------------------------------------- /text/shanghainese.py: -------------------------------------------------------------------------------- 1 | import re 2 | import cn2an 3 | import opencc 4 | 5 | 6 | converter = opencc.OpenCC('zaonhe') 7 | 8 | # List of (Latin alphabet, ipa) pairs: 9 | _latin_to_ipa = [(re.compile('%s' % x[0]), x[1]) for x in [ 10 | ('A', 'ᴇ'), 11 | ('B', 'bi'), 12 | ('C', 'si'), 13 | ('D', 'di'), 14 | ('E', 'i'), 15 | ('F', 'ᴇf'), 16 | ('G', 'dʑi'), 17 | ('H', 'ᴇtɕʰ'), 18 | ('I', 'ᴀi'), 19 | ('J', 'dʑᴇ'), 20 | ('K', 'kʰᴇ'), 21 | ('L', 'ᴇl'), 22 | ('M', 'ᴇm'), 23 | ('N', 'ᴇn'), 24 | ('O', 'o'), 25 | ('P', 'pʰi'), 26 | ('Q', 'kʰiu'), 27 | ('R', 'ᴀl'), 28 | ('S', 'ᴇs'), 29 | ('T', 'tʰi'), 30 | ('U', 'ɦiu'), 31 | ('V', 'vi'), 32 | ('W', 'dᴀbɤliu'), 33 | ('X', 'ᴇks'), 34 | ('Y', 'uᴀi'), 35 | ('Z', 'zᴇ') 36 | ]] 37 | 38 | 39 | def _number_to_shanghainese(num): 40 | num = cn2an.an2cn(num).replace('一十','十').replace('二十', '廿').replace('二', '两') 41 | return re.sub(r'((?:^|[^三四五六七八九])十|廿)两', r'\1二', num) 42 | 43 | 44 | def number_to_shanghainese(text): 45 | return re.sub(r'\d+(?:\.?\d+)?', lambda x: _number_to_shanghainese(x.group()), text) 46 | 47 | 48 | def latin_to_ipa(text): 49 | for regex, replacement in _latin_to_ipa: 50 | text = re.sub(regex, replacement, text) 51 | return text 52 | 53 | 54 | def shanghainese_to_ipa(text): 55 | text = number_to_shanghainese(text.upper()) 56 | text = converter.convert(text).replace('-','').replace('$',' ') 57 | text = re.sub(r'[A-Z]', lambda x: latin_to_ipa(x.group())+' ', text) 58 | text = re.sub(r'[、;:]', ',', text) 59 | text = re.sub(r'\s*,\s*', ', ', text) 60 | text = re.sub(r'\s*。\s*', '. ', text) 61 | text = re.sub(r'\s*?\s*', '? ', text) 62 | text = re.sub(r'\s*!\s*', '! ', text) 63 | text = re.sub(r'\s*$', '', text) 64 | return text 65 | -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from json import loads 3 | import torch 4 | from torch import load, FloatTensor 5 | from numpy import float32 6 | import librosa 7 | 8 | 9 | class HParams(): 10 | def __init__(self, **kwargs): 11 | for k, v in kwargs.items(): 12 | if type(v) == dict: 13 | v = HParams(**v) 14 | self[k] = v 15 | 16 | def keys(self): 17 | return self.__dict__.keys() 18 | 19 | def items(self): 20 | return self.__dict__.items() 21 | 22 | def values(self): 23 | return self.__dict__.values() 24 | 25 | def __len__(self): 26 | return len(self.__dict__) 27 | 28 | def __getitem__(self, key): 29 | return getattr(self, key) 30 | 31 | def __setitem__(self, key, value): 32 | return setattr(self, key, value) 33 | 34 | def __contains__(self, key): 35 | return key in self.__dict__ 36 | 37 | def __repr__(self): 38 | return self.__dict__.__repr__() 39 | 40 | 41 | def load_checkpoint(checkpoint_path, model): 42 | device = torch.device("cuda" if torch.cuda.is_available() else "cpu") 43 | checkpoint_dict = load(checkpoint_path, map_location=device) 44 | iteration = checkpoint_dict['iteration'] 45 | saved_state_dict = checkpoint_dict['model'] 46 | if hasattr(model, 'module'): 47 | state_dict = model.module.state_dict() 48 | else: 49 | state_dict = model.state_dict() 50 | new_state_dict= {} 51 | for k, v in state_dict.items(): 52 | try: 53 | new_state_dict[k] = saved_state_dict[k] 54 | except: 55 | logging.info("%s is not in the checkpoint" % k) 56 | new_state_dict[k] = v 57 | if hasattr(model, 'module'): 58 | model.module.load_state_dict(new_state_dict) 59 | else: 60 | model.load_state_dict(new_state_dict) 61 | logging.info("Loaded checkpoint '{}' (iteration {})" .format( 62 | checkpoint_path, iteration)) 63 | return 64 | 65 | 66 | def get_hparams_from_file(config_path): 67 | with open(config_path, "r", encoding='utf-8') as f: 68 | data = f.read() 69 | config = loads(data) 70 | 71 | hparams = HParams(**config) 72 | return hparams 73 | 74 | 75 | def load_audio_to_torch(full_path, target_sampling_rate): 76 | audio, sampling_rate = librosa.load(full_path, sr=target_sampling_rate, mono=True) 77 | return FloatTensor(audio.astype(float32)) 78 | -------------------------------------------------------------------------------- /commons.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch.nn import functional as F 3 | import torch.jit 4 | 5 | 6 | def script_method(fn, _rcb=None): 7 | return fn 8 | 9 | 10 | def script(obj, optimize=True, _frames_up=0, _rcb=None): 11 | return obj 12 | 13 | 14 | torch.jit.script_method = script_method 15 | torch.jit.script = script 16 | 17 | 18 | def init_weights(m, mean=0.0, std=0.01): 19 | classname = m.__class__.__name__ 20 | if classname.find("Conv") != -1: 21 | m.weight.data.normal_(mean, std) 22 | 23 | 24 | def get_padding(kernel_size, dilation=1): 25 | return int((kernel_size*dilation - dilation)/2) 26 | 27 | 28 | def intersperse(lst, item): 29 | result = [item] * (len(lst) * 2 + 1) 30 | result[1::2] = lst 31 | return result 32 | 33 | 34 | def slice_segments(x, ids_str, segment_size=4): 35 | ret = torch.zeros_like(x[:, :, :segment_size]) 36 | for i in range(x.size(0)): 37 | idx_str = ids_str[i] 38 | idx_end = idx_str + segment_size 39 | ret[i] = x[i, :, idx_str:idx_end] 40 | return ret 41 | 42 | 43 | def rand_slice_segments(x, x_lengths=None, segment_size=4): 44 | b, d, t = x.size() 45 | if x_lengths is None: 46 | x_lengths = t 47 | ids_str_max = x_lengths - segment_size + 1 48 | ids_str = (torch.rand([b]).to(device=x.device) * ids_str_max).to(dtype=torch.long) 49 | ret = slice_segments(x, ids_str, segment_size) 50 | return ret, ids_str 51 | 52 | 53 | def subsequent_mask(length): 54 | mask = torch.tril(torch.ones(length, length)).unsqueeze(0).unsqueeze(0) 55 | return mask 56 | 57 | 58 | @torch.jit.script 59 | def fused_add_tanh_sigmoid_multiply(input_a, input_b, n_channels): 60 | n_channels_int = n_channels[0] 61 | in_act = input_a + input_b 62 | t_act = torch.tanh(in_act[:, :n_channels_int, :]) 63 | s_act = torch.sigmoid(in_act[:, n_channels_int:, :]) 64 | acts = t_act * s_act 65 | return acts 66 | 67 | 68 | def convert_pad_shape(pad_shape): 69 | l = pad_shape[::-1] 70 | pad_shape = [item for sublist in l for item in sublist] 71 | return pad_shape 72 | 73 | 74 | def sequence_mask(length, max_length=None): 75 | if max_length is None: 76 | max_length = length.max() 77 | x = torch.arange(max_length, dtype=length.dtype, device=length.device) 78 | return x.unsqueeze(0) < length.unsqueeze(1) 79 | 80 | 81 | def generate_path(duration, mask): 82 | """ 83 | duration: [b, 1, t_x] 84 | mask: [b, 1, t_y, t_x] 85 | """ 86 | device = duration.device 87 | 88 | b, _, t_y, t_x = mask.shape 89 | cum_duration = torch.cumsum(duration, -1) 90 | 91 | cum_duration_flat = cum_duration.view(b * t_x) 92 | path = sequence_mask(cum_duration_flat, t_y).to(mask.dtype) 93 | path = path.view(b, t_x, t_y) 94 | path = path - F.pad(path, convert_pad_shape([[0, 0], [1, 0], [0, 0]]))[:, :-1] 95 | path = path.unsqueeze(1).transpose(2,3) * mask 96 | return path 97 | -------------------------------------------------------------------------------- /ChatWithGPT/game/Resources/Hiyori/hiyori.model3.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 3, 3 | "FileReferences": { 4 | "Moc": "Hiyori.moc3", 5 | "Textures": [ 6 | "Hiyori.2048/texture_00.png", 7 | "Hiyori.2048/texture_01.png" 8 | ], 9 | "Physics": "Hiyori.physics3.json", 10 | "UserData": "Hiyori.userdata3.json", 11 | "Pose": "Hiyori.pose3.json", 12 | "DisplayInfo": "Hiyori.cdi3.json", 13 | "Motions": { 14 | "Idle": [ 15 | { 16 | "File": "motions/Hiyori_m01.motion3.json", 17 | "FadeInTime": 0.5, 18 | "FadeOutTime": 0.5 19 | }, 20 | { 21 | "File": "motions/Hiyori_m02.motion3.json", 22 | "FadeInTime": 0.5, 23 | "FadeOutTime": 0.5 24 | }, 25 | { 26 | "File": "motions/Hiyori_m03.motion3.json", 27 | "FadeInTime": 0.5, 28 | "FadeOutTime": 0.5 29 | }, 30 | { 31 | "File": "motions/Hiyori_m05.motion3.json", 32 | "FadeInTime": 0.5, 33 | "FadeOutTime": 0.5 34 | }, 35 | { 36 | "File": "motions/Hiyori_m06.motion3.json", 37 | "FadeInTime": 0.5, 38 | "FadeOutTime": 0.5 39 | }, 40 | { 41 | "File": "motions/Hiyori_m07.motion3.json", 42 | "FadeInTime": 0.5, 43 | "FadeOutTime": 0.5 44 | }, 45 | { 46 | "File": "motions/Hiyori_m08.motion3.json", 47 | "FadeInTime": 0.5, 48 | "FadeOutTime": 0.5 49 | }, 50 | { 51 | "File": "motions/Hiyori_m09.motion3.json", 52 | "FadeInTime": 0.5, 53 | "FadeOutTime": 0.5 54 | }, 55 | { 56 | "File": "motions/Hiyori_m10.motion3.json", 57 | "FadeInTime": 0.5, 58 | "FadeOutTime": 0.5 59 | } 60 | ], 61 | "TapBody": [ 62 | { 63 | "File": "motions/Hiyori_m04.motion3.json", 64 | "FadeInTime": 0.5, 65 | "FadeOutTime": 0.5 66 | } 67 | ], 68 | "": [ 69 | { 70 | "File": "motions/Hiyori_m01.motion3.json" 71 | }, 72 | { 73 | "File": "motions/Hiyori_m02.motion3.json" 74 | }, 75 | { 76 | "File": "motions/Hiyori_m03.motion3.json" 77 | }, 78 | { 79 | "File": "motions/Hiyori_m04.motion3.json" 80 | }, 81 | { 82 | "File": "motions/Hiyori_m05.motion3.json" 83 | }, 84 | { 85 | "File": "motions/Hiyori_m06.motion3.json" 86 | }, 87 | { 88 | "File": "motions/Hiyori_m07.motion3.json" 89 | }, 90 | { 91 | "File": "motions/Hiyori_m08.motion3.json" 92 | }, 93 | { 94 | "File": "motions/Hiyori_m09.motion3.json" 95 | }, 96 | { 97 | "File": "motions/Hiyori_m10.motion3.json" 98 | }, 99 | { 100 | "File": "motions/Hiyori_talking.motion3.json" 101 | }, 102 | { 103 | "File": "motions/Hiyori_talking.motion3.json" 104 | } 105 | ] 106 | } 107 | }, 108 | "Groups": [ 109 | { 110 | "Target": "Parameter", 111 | "Name": "LipSync", 112 | "Ids": [ 113 | "ParamMouthOpenY" 114 | ] 115 | }, 116 | { 117 | "Target": "Parameter", 118 | "Name": "EyeBlink", 119 | "Ids": [ 120 | "ParamEyeLOpen", 121 | "ParamEyeROpen" 122 | ] 123 | } 124 | ], 125 | "HitAreas": [ 126 | { 127 | "Id": "HitArea", 128 | "Name": "Body" 129 | } 130 | ] 131 | } -------------------------------------------------------------------------------- /ChatWithGPT/game/script.rpy: -------------------------------------------------------------------------------- 1 | # Game scripts can be placed in this file. 2 | 3 | # Declare the characters used by this game. The color parameter colors the character name. 4 | 5 | define e = Character("챗봇") 6 | define y = Character("사용자") 7 | define config.gl2 = True 8 | 9 | image hiyori = Live2D("Resources/Hiyori", base=.6, loop = True, fade=True) 10 | 11 | init python: 12 | import socket 13 | import time 14 | thinking = 0 15 | total_data = bytes() 16 | renpy.block_rollback() 17 | ip_port = ('127.0.0.1', 9000) 18 | client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 19 | client.connect(ip_port) 20 | 21 | 22 | # The game starts here. 23 | 24 | label start: 25 | $ renpy.block_rollback() 26 | show hiyori m01 27 | 28 | jump chooseTts 29 | 30 | label chooseTts: 31 | $ renpy.block_rollback() 32 | menu TTSChoice: 33 | e"TTS 서비스를 선택해주세요" 34 | "로컬 VITS": 35 | python: 36 | client.send(("0").encode()) 37 | jump modelChoice 38 | "네이버 TTS": 39 | python: 40 | client.send(("1").encode()) 41 | jump getApiKey 42 | 43 | label modelChoice: 44 | $ renpy.block_rollback() 45 | menu KRmodelChoice: 46 | e "음성 출력할 캐릭터를 선택해주세요" 47 | "index 0": 48 | python: 49 | client.send(("0").encode()) 50 | "index 1": 51 | python: 52 | client.send(("1").encode()) 53 | "index 2": 54 | python: 55 | client.send(("2").encode()) 56 | "index 3": 57 | python: 58 | client.send(("3").encode()) 59 | "index 4": 60 | python: 61 | client.send(("4").encode()) 62 | "index 5": 63 | python: 64 | client.send(("5").encode()) 65 | 66 | jump getApiKey 67 | 68 | 69 | label getApiKey: 70 | $ renpy.block_rollback() 71 | 72 | python: 73 | token = renpy.input("open AI API KEY를 입력해주세요") 74 | client.send(token.encode()) 75 | 76 | jump uploadSetting 77 | return 78 | 79 | 80 | label uploadSetting: 81 | $ renpy.block_rollback() 82 | python: 83 | token = renpy.input("원하는 배경 설정을 입력해주세요") 84 | client.send(token.encode()) 85 | jump uploadInit 86 | 87 | label uploadInit: 88 | $ renpy.block_rollback() 89 | python: 90 | token = renpy.input("해당 캐릭터의 첫 대사를 입력해주세요") 91 | client.send(token.encode()) 92 | jump talk_keyboard 93 | 94 | 95 | label talk_keyboard: 96 | $ renpy.block_rollback() 97 | show hiyori m02 98 | python: 99 | message = renpy.input("나:") 100 | client.send(message.encode()) 101 | data = bytes() 102 | jump checkRes 103 | 104 | label checkRes: 105 | $ renpy.block_rollback() 106 | if(thinking == 0): 107 | show hiyori m03 108 | e "..." 109 | 110 | python: 111 | client.setblocking(0) 112 | try: 113 | data = client.recv(1024) 114 | total_data += data 115 | except: 116 | data = bytes() 117 | client.setblocking(1) 118 | 119 | if(len(data) > 0 and len(data) < 1024): 120 | python: 121 | response = total_data.decode() 122 | total_data = bytes() 123 | thinking = 0 124 | jump answer 125 | else: 126 | $ renpy.block_rollback() 127 | e "......" 128 | $ thinking = 1 129 | jump checkRes 130 | 131 | 132 | 133 | 134 | label answer: 135 | show hiyori talking 136 | voice "/audio/test.ogg" 137 | $ renpy.block_rollback() 138 | e "[response]" 139 | voice sustain 140 | 141 | $ client.send("음성 재생 완료".encode()) 142 | jump talk_keyboard -------------------------------------------------------------------------------- /mel_processing.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.utils.data 3 | from librosa.filters import mel as librosa_mel_fn 4 | 5 | MAX_WAV_VALUE = 32768.0 6 | 7 | 8 | def dynamic_range_compression_torch(x, C=1, clip_val=1e-5): 9 | """ 10 | PARAMS 11 | ------ 12 | C: compression factor 13 | """ 14 | return torch.log(torch.clamp(x, min=clip_val) * C) 15 | 16 | 17 | def dynamic_range_decompression_torch(x, C=1): 18 | """ 19 | PARAMS 20 | ------ 21 | C: compression factor used to compress 22 | """ 23 | return torch.exp(x) / C 24 | 25 | 26 | def spectral_normalize_torch(magnitudes): 27 | output = dynamic_range_compression_torch(magnitudes) 28 | return output 29 | 30 | 31 | def spectral_de_normalize_torch(magnitudes): 32 | output = dynamic_range_decompression_torch(magnitudes) 33 | return output 34 | 35 | 36 | mel_basis = {} 37 | hann_window = {} 38 | 39 | 40 | def spectrogram_torch(y, n_fft, sampling_rate, hop_size, win_size, center=False): 41 | if torch.min(y) < -1.: 42 | print('min value is ', torch.min(y)) 43 | if torch.max(y) > 1.: 44 | print('max value is ', torch.max(y)) 45 | 46 | global hann_window 47 | dtype_device = str(y.dtype) + '_' + str(y.device) 48 | wnsize_dtype_device = str(win_size) + '_' + dtype_device 49 | if wnsize_dtype_device not in hann_window: 50 | hann_window[wnsize_dtype_device] = torch.hann_window(win_size).to(dtype=y.dtype, device=y.device) 51 | 52 | y = torch.nn.functional.pad(y.unsqueeze(1), (int((n_fft-hop_size)/2), int((n_fft-hop_size)/2)), mode='reflect') 53 | y = y.squeeze(1) 54 | 55 | spec = torch.stft(y, n_fft, hop_length=hop_size, win_length=win_size, window=hann_window[wnsize_dtype_device], 56 | center=center, pad_mode='reflect', normalized=False, onesided=True, return_complex=False) 57 | 58 | spec = torch.sqrt(spec.pow(2).sum(-1) + 1e-6) 59 | return spec 60 | 61 | 62 | def spec_to_mel_torch(spec, n_fft, num_mels, sampling_rate, fmin, fmax): 63 | global mel_basis 64 | dtype_device = str(spec.dtype) + '_' + str(spec.device) 65 | fmax_dtype_device = str(fmax) + '_' + dtype_device 66 | if fmax_dtype_device not in mel_basis: 67 | mel = librosa_mel_fn(sampling_rate, n_fft, num_mels, fmin, fmax) 68 | mel_basis[fmax_dtype_device] = torch.from_numpy(mel).to(dtype=spec.dtype, device=spec.device) 69 | spec = torch.matmul(mel_basis[fmax_dtype_device], spec) 70 | spec = spectral_normalize_torch(spec) 71 | return spec 72 | 73 | 74 | def mel_spectrogram_torch(y, n_fft, num_mels, sampling_rate, hop_size, win_size, fmin, fmax, center=False): 75 | if torch.min(y) < -1.: 76 | print('min value is ', torch.min(y)) 77 | if torch.max(y) > 1.: 78 | print('max value is ', torch.max(y)) 79 | 80 | global mel_basis, hann_window 81 | dtype_device = str(y.dtype) + '_' + str(y.device) 82 | fmax_dtype_device = str(fmax) + '_' + dtype_device 83 | wnsize_dtype_device = str(win_size) + '_' + dtype_device 84 | if fmax_dtype_device not in mel_basis: 85 | mel = librosa_mel_fn(sampling_rate, n_fft, num_mels, fmin, fmax) 86 | mel_basis[fmax_dtype_device] = torch.from_numpy(mel).to(dtype=y.dtype, device=y.device) 87 | if wnsize_dtype_device not in hann_window: 88 | hann_window[wnsize_dtype_device] = torch.hann_window(win_size).to(dtype=y.dtype, device=y.device) 89 | 90 | y = torch.nn.functional.pad(y.unsqueeze(1), (int((n_fft-hop_size)/2), int((n_fft-hop_size)/2)), mode='reflect') 91 | y = y.squeeze(1) 92 | 93 | spec = torch.stft(y, n_fft, hop_length=hop_size, win_length=win_size, window=hann_window[wnsize_dtype_device], 94 | center=center, pad_mode='reflect', normalized=False, onesided=True) 95 | 96 | spec = torch.sqrt(spec.pow(2).sum(-1) + 1e-6) 97 | 98 | spec = torch.matmul(mel_basis[fmax_dtype_device], spec) 99 | spec = spectral_normalize_torch(spec) 100 | 101 | return spec 102 | -------------------------------------------------------------------------------- /text/japanese.py: -------------------------------------------------------------------------------- 1 | import re 2 | from unidecode import unidecode 3 | import pyopenjtalk 4 | 5 | 6 | # Regular expression matching Japanese without punctuation marks: 7 | _japanese_characters = re.compile( 8 | r'[A-Za-z\d\u3005\u3040-\u30ff\u4e00-\u9fff\uff11-\uff19\uff21-\uff3a\uff41-\uff5a\uff66-\uff9d]') 9 | 10 | # Regular expression matching non-Japanese characters or punctuation marks: 11 | _japanese_marks = re.compile( 12 | r'[^A-Za-z\d\u3005\u3040-\u30ff\u4e00-\u9fff\uff11-\uff19\uff21-\uff3a\uff41-\uff5a\uff66-\uff9d]') 13 | 14 | # List of (symbol, Japanese) pairs for marks: 15 | _symbols_to_japanese = [(re.compile('%s' % x[0]), x[1]) for x in [ 16 | ('%', 'パーセント') 17 | ]] 18 | 19 | # List of (romaji, ipa) pairs for marks: 20 | _romaji_to_ipa = [(re.compile('%s' % x[0]), x[1]) for x in [ 21 | ('ts', 'ʦ'), 22 | ('u', 'ɯ'), 23 | ('j', 'ʥ'), 24 | ('y', 'j'), 25 | ('ni', 'n^i'), 26 | ('nj', 'n^'), 27 | ('hi', 'çi'), 28 | ('hj', 'ç'), 29 | ('f', 'ɸ'), 30 | ('I', 'i*'), 31 | ('U', 'ɯ*'), 32 | ('r', 'ɾ') 33 | ]] 34 | 35 | # List of (romaji, ipa2) pairs for marks: 36 | _romaji_to_ipa2 = [(re.compile('%s' % x[0]), x[1]) for x in [ 37 | ('u', 'ɯ'), 38 | ('ʧ', 'tʃ'), 39 | ('j', 'dʑ'), 40 | ('y', 'j'), 41 | ('ni', 'n^i'), 42 | ('nj', 'n^'), 43 | ('hi', 'çi'), 44 | ('hj', 'ç'), 45 | ('f', 'ɸ'), 46 | ('I', 'i*'), 47 | ('U', 'ɯ*'), 48 | ('r', 'ɾ') 49 | ]] 50 | 51 | # List of (consonant, sokuon) pairs: 52 | _real_sokuon = [(re.compile('%s' % x[0]), x[1]) for x in [ 53 | (r'Q([↑↓]*[kg])', r'k#\1'), 54 | (r'Q([↑↓]*[tdjʧ])', r't#\1'), 55 | (r'Q([↑↓]*[sʃ])', r's\1'), 56 | (r'Q([↑↓]*[pb])', r'p#\1') 57 | ]] 58 | 59 | # List of (consonant, hatsuon) pairs: 60 | _real_hatsuon = [(re.compile('%s' % x[0]), x[1]) for x in [ 61 | (r'N([↑↓]*[pbm])', r'm\1'), 62 | (r'N([↑↓]*[ʧʥj])', r'n^\1'), 63 | (r'N([↑↓]*[tdn])', r'n\1'), 64 | (r'N([↑↓]*[kg])', r'ŋ\1') 65 | ]] 66 | 67 | 68 | def symbols_to_japanese(text): 69 | for regex, replacement in _symbols_to_japanese: 70 | text = re.sub(regex, replacement, text) 71 | return text 72 | 73 | 74 | def japanese_to_romaji_with_accent(text): 75 | '''Reference https://r9y9.github.io/ttslearn/latest/notebooks/ch10_Recipe-Tacotron.html''' 76 | text = symbols_to_japanese(text) 77 | sentences = re.split(_japanese_marks, text) 78 | marks = re.findall(_japanese_marks, text) 79 | text = '' 80 | for i, sentence in enumerate(sentences): 81 | if re.match(_japanese_characters, sentence): 82 | if text != '': 83 | text += ' ' 84 | labels = pyopenjtalk.extract_fullcontext(sentence) 85 | for n, label in enumerate(labels): 86 | phoneme = re.search(r'\-([^\+]*)\+', label).group(1) 87 | if phoneme not in ['sil', 'pau']: 88 | text += phoneme.replace('ch', 'ʧ').replace('sh', 89 | 'ʃ').replace('cl', 'Q') 90 | else: 91 | continue 92 | # n_moras = int(re.search(r'/F:(\d+)_', label).group(1)) 93 | a1 = int(re.search(r"/A:(\-?[0-9]+)\+", label).group(1)) 94 | a2 = int(re.search(r"\+(\d+)\+", label).group(1)) 95 | a3 = int(re.search(r"\+(\d+)/", label).group(1)) 96 | if re.search(r'\-([^\+]*)\+', labels[n + 1]).group(1) in ['sil', 'pau']: 97 | a2_next = -1 98 | else: 99 | a2_next = int( 100 | re.search(r"\+(\d+)\+", labels[n + 1]).group(1)) 101 | # Accent phrase boundary 102 | if a3 == 1 and a2_next == 1: 103 | text += ' ' 104 | # Falling 105 | elif a1 == 0 and a2_next == a2 + 1: 106 | text += '↓' 107 | # Rising 108 | elif a2 == 1 and a2_next == 2: 109 | text += '↑' 110 | if i < len(marks): 111 | text += unidecode(marks[i]).replace(' ', '') 112 | return text 113 | 114 | 115 | def get_real_sokuon(text): 116 | for regex, replacement in _real_sokuon: 117 | text = re.sub(regex, replacement, text) 118 | return text 119 | 120 | 121 | def get_real_hatsuon(text): 122 | for regex, replacement in _real_hatsuon: 123 | text = re.sub(regex, replacement, text) 124 | return text 125 | 126 | 127 | def japanese_to_ipa(text): 128 | text = japanese_to_romaji_with_accent(text).replace('...', '…') 129 | text = re.sub( 130 | r'([aiueo])\1+', lambda x: x.group(0)[0]+'ː'*(len(x.group(0))-1), text) 131 | text = get_real_sokuon(text) 132 | text = get_real_hatsuon(text) 133 | for regex, replacement in _romaji_to_ipa: 134 | text = re.sub(regex, replacement, text) 135 | return text 136 | 137 | 138 | def japanese_to_ipa2(text): 139 | text = japanese_to_romaji_with_accent(text).replace('...', '…') 140 | text = get_real_sokuon(text) 141 | text = get_real_hatsuon(text) 142 | for regex, replacement in _romaji_to_ipa2: 143 | text = re.sub(regex, replacement, text) 144 | return text 145 | 146 | 147 | def japanese_to_ipa3(text): 148 | text = japanese_to_ipa2(text).replace('n^', 'ȵ').replace( 149 | 'ʃ', 'ɕ').replace('*', '\u0325').replace('#', '\u031a') 150 | text = re.sub( 151 | r'([aiɯeo])\1+', lambda x: x.group(0)[0]+'ː'*(len(x.group(0))-1), text) 152 | text = re.sub(r'((?:^|\s)(?:ts|tɕ|[kpt]))', r'\1ʰ', text) 153 | return text 154 | -------------------------------------------------------------------------------- /ChatWithGPT/game/options.rpy: -------------------------------------------------------------------------------- 1 | ## 이 파일은 귀하의 게임 커스텀으로 변경될 수 있는 옵션을 포함합니다. 2 | ## 3 | ## 두 개의 '#' 표시로 시작되는 줄은 주석이며, 그것을 없애지 말아야 합니다. 한 개 4 | ## 의 '#' 표시로 시작되는 줄은 주석 처리된 코드로 필요한 경우 제거해도 됩니다. 5 | 6 | 7 | ## 기본 ########################################################################## 8 | 9 | ## 인간이 읽을 수 있는 게임의 이름. 기본 윈도우의 제목으로 사용되며, 인터페이스 10 | ## 와 오류 보고에서 보여집니다. 11 | ## 12 | ## 문자열을 _()로 둘러 쌓으면 씌우면 번역의 대상으로 표시됩니다. 13 | 14 | define config.name = _("ChatWithGPT") 15 | 16 | 17 | ## 위에 주어진 제목이 주 메뉴 화면에 표시되는지 결정합니다. 제목을 숨기려면 이것 18 | ## 을 False로 설정하십시오. 19 | 20 | define gui.show_name = True 21 | 22 | 23 | ## 게임의 버전입니다. 24 | 25 | define config.version = "1.0" 26 | 27 | 28 | ## 게임의 about 스크린에 배치되는 텍스트입니다. 텍스트를 삼중 따옴표 사이에 배치 29 | ## 하고 단락 사이에 빈 줄을 남겨 둡니다. 30 | 31 | define gui.about = _p(""" 32 | """) 33 | 34 | 35 | ## 배포판의 실행 파일과 디렉토리에 사용되는 게임의 약식 이름. 이것은 ASCII 전용 36 | ## 이어야 하며 공백, 콜론 또는 세미콜론을 포함해서는 안 됩니다. 37 | 38 | define build.name = "ChatWithGPT" 39 | 40 | 41 | ## 음악과 음향 ###################################################################### 42 | 43 | ## These three variables control, among other things, which mixers are shown 44 | ## to the player by default. Setting one of these to False will hide the 45 | ## appropriate mixer. 46 | 47 | define config.has_sound = True 48 | define config.has_music = True 49 | define config.has_voice = True 50 | 51 | 52 | ## 사용자가 음향 또는 음성 채널에서 테스트 사운드를 재생할 수 있게 하려면 아래 53 | ## 줄의 주석을 제거하고 이를 사용하여 재생할 샘플 사운드를 설정하십시오. 54 | 55 | # define config.sample_sound = "sample-sound.ogg" 56 | # define config.sample_voice = "sample-voice.ogg" 57 | 58 | 59 | ## 플레이어가 주 메뉴에 있을 때 재생할 오디오 파일을 설정하려면 다음 줄의 주석 60 | ## 처리를 제거하십시오. 이 파일은 중지되거나 다른 파일이 재생 될 때까지 계속 재 61 | ## 생합니다. 62 | 63 | # define config.main_menu_music = "main-menu-theme.ogg" 64 | 65 | 66 | ## 번역 ########################################################################## 67 | ## 68 | ## 이러한 변수는 특정 이벤트가 발생할 때 사용되는 전환을 설정합니다. 각 변수는 69 | ## 전환으로 설정해야 하며, 전환을 사용하지 말아야 한다는 것을 나타내려면 None으 70 | ## 로 설정해야 합니다. 71 | 72 | ## 게임 메뉴에 진입하거나 나갑니다. 73 | 74 | define config.enter_transition = dissolve 75 | define config.exit_transition = dissolve 76 | 77 | 78 | ## 게임 메뉴 화면 사이입니다. 79 | 80 | define config.intra_transition = dissolve 81 | 82 | 83 | ## 게임이 로드된 후 사용되는 전환입니다. 84 | 85 | define config.after_load_transition = None 86 | 87 | 88 | ## 게임 종료 후 주 메뉴에 진입할 때 사용됩니다. 89 | 90 | define config.end_game_transition = None 91 | 92 | 93 | ## 게임을 시작할 때 사용되는 전환을 설정하는 변수가 없습니다. 대신, 초기 장면을 94 | ## 표시한 후 with 문을 사용하십시오. 95 | 96 | 97 | ## 창 관리 ######################################################################## 98 | ## 99 | ## 이것은 대사 창이 표시됐을 때 제어합니다. 만약 "show"면, 그것은 상항 표시됩니 100 | ## 다. 만약 "hide"면, 그것은 대사가 주어질 때만 표시됩니다. 만약 "auto"면, 창은 101 | ## 장면(scene) 문 앞에 숨겨져 대화 상자가 표시되면 다시 표시됩니다. 102 | ## 103 | ## 게임이 시작된 후에는 "window show", "window hide", 그리고 "window auto" 문을 104 | ## 사용하여 변경할 수 있습니다. 105 | 106 | define config.window = "auto" 107 | 108 | 109 | ## 대화 창을 표시하고 숨기는 데 사용되는 전환 110 | 111 | define config.window_show_transition = Dissolve(.2) 112 | define config.window_hide_transition = Dissolve(.2) 113 | 114 | 115 | ## 환경설정 기본값 #################################################################### 116 | 117 | ## 기본 글자 속도를 제어합니다. 기본적으로, 0은 즉시이며 다른 숫자는 초당 입력 118 | ## 할 문자 수입니다. 119 | 120 | default preferences.text_cps = 0 121 | 122 | 123 | ## 기본 auto-forward 지연 시간입니다. 숫자가 클수록 대기 시간이 길어지며, 0 ~ 30 124 | ## 이 유효한 범위가 됩니다. 125 | 126 | default preferences.afm_time = 15 127 | 128 | 129 | ## 세이브 디렉토리 #################################################################### 130 | ## 131 | ## 렌파이는 이 게임에 대한 저장 파일을 플랫폼 별로 배치합니다. 세이브 파일들은 132 | ## 여기에 있습니다: 133 | ## 134 | ## 윈도우즈: %APPDATA\RenPy\ 135 | ## 136 | ## 매킨토시: $HOME/Library/RenPy/ 137 | ## 138 | ## 리눅스: $HOME/.renpy/ 139 | ## 140 | ## 이것은 일반적으로 변경해서는 안 되며, 항상 표현형식이 아닌 정확한 문자열이어 141 | ## 야 합니다. 142 | 143 | define config.save_directory = "ChatWithGPT-1680367288" 144 | 145 | 146 | ## Icon ######################################################################## 147 | ## 148 | ## 작업 표시 줄 또는 독에 표시되는 아이콘. 149 | 150 | define config.window_icon = "gui/window_icon.png" 151 | 152 | 153 | ## 빌드 구성 ####################################################################### 154 | ## 155 | ## 이 섹션은 렌파이가 프로젝트를 배포 파일로 만드는 방법을 제어합니다. 156 | 157 | init python: 158 | 159 | ## 다음 함수는 파일 패턴을 사용합니다. 파일 패턴은 대/소문자를 구분하지 않으 160 | ## 며, /의 유무와 관계없이 기본 디렉터리의 상대 경로와 일치합니다. 여러 패턴 161 | ## 이 일치하면 첫 번째 패턴이 사용됩니다. 162 | ## 163 | ## 패턴 있음: 164 | ## 165 | ## / 는 디렉토리 구분 기호입니다. 166 | ## 167 | ## * 는 디렉토리 구분자를 제외한 모든 문자와 일치합니다. 168 | ## 169 | ## ** 는 디렉토리 구분자를 포함해 모든 문자와 일치합니다. 170 | ## 171 | ## 예를 들어, "*.txt" 는 기본 디렉토리의 txt 파일들과 일치하고, "game/ 172 | ## **.ogg" 는 게임 디렉토리 또는 그 서브 디렉토리의 ogg 파일들과 일치하며, 173 | ## "**.psd" 는 프로젝트에서 모든 곳의 psd 파일들과 일치합니다. 174 | 175 | ## 파일을 None으로 분류하여 배포판으로부터 제외하십시오. 176 | 177 | build.classify('**~', None) 178 | build.classify('**.bak', None) 179 | build.classify('**/.**', None) 180 | build.classify('**/#**', None) 181 | build.classify('**/thumbs.db', None) 182 | 183 | ## 파일을 아카이브하려면 'archive'로 분류하십시오. 184 | 185 | # build.classify('game/**.png', 'archive') 186 | # build.classify('game/**.jpg', 'archive') 187 | 188 | ## 파일들의 매칭 문서 패턴은 맥앱(Mac App) 빌드에서 중복되므로 app 및 zip 파 189 | ## 일에 모두 나타납니다. 190 | 191 | build.documentation('*.html') 192 | build.documentation('*.txt') 193 | 194 | 195 | ## 확장 파일을 다운로드하고 인앱 구매를 수행하려면 Google Play 라이센스 키가 필 196 | ## 요합니다. Google Play 개발자 콘솔의 "서비스 및 API"페이지에서 확인할 수 있습 197 | ## 니다. 198 | 199 | # define build.google_play_key = "..." 200 | 201 | 202 | ## itch.io 프로젝트와 연관된 사용자 이름과 프로젝트 이름이며 슬래시로 구분됩니 203 | ## 다. 204 | 205 | # define build.itch_project = "renpytom/test-project" 206 | -------------------------------------------------------------------------------- /text/english.py: -------------------------------------------------------------------------------- 1 | """ from https://github.com/keithito/tacotron """ 2 | 3 | ''' 4 | Cleaners are transformations that run over the input text at both training and eval time. 5 | 6 | Cleaners can be selected by passing a comma-delimited list of cleaner names as the "cleaners" 7 | hyperparameter. Some cleaners are English-specific. You'll typically want to use: 8 | 1. "english_cleaners" for English text 9 | 2. "transliteration_cleaners" for non-English text that can be transliterated to ASCII using 10 | the Unidecode library (https://pypi.python.org/pypi/Unidecode) 11 | 3. "basic_cleaners" if you do not want to transliterate (in this case, you should also update 12 | the symbols in symbols.py to match your data). 13 | ''' 14 | 15 | 16 | # Regular expression matching whitespace: 17 | 18 | 19 | import re 20 | import inflect 21 | from unidecode import unidecode 22 | import eng_to_ipa as ipa 23 | _inflect = inflect.engine() 24 | _comma_number_re = re.compile(r'([0-9][0-9\,]+[0-9])') 25 | _decimal_number_re = re.compile(r'([0-9]+\.[0-9]+)') 26 | _pounds_re = re.compile(r'£([0-9\,]*[0-9]+)') 27 | _dollars_re = re.compile(r'\$([0-9\.\,]*[0-9]+)') 28 | _ordinal_re = re.compile(r'[0-9]+(st|nd|rd|th)') 29 | _number_re = re.compile(r'[0-9]+') 30 | 31 | # List of (regular expression, replacement) pairs for abbreviations: 32 | _abbreviations = [(re.compile('\\b%s\\.' % x[0], re.IGNORECASE), x[1]) for x in [ 33 | ('mrs', 'misess'), 34 | ('mr', 'mister'), 35 | ('dr', 'doctor'), 36 | ('st', 'saint'), 37 | ('co', 'company'), 38 | ('jr', 'junior'), 39 | ('maj', 'major'), 40 | ('gen', 'general'), 41 | ('drs', 'doctors'), 42 | ('rev', 'reverend'), 43 | ('lt', 'lieutenant'), 44 | ('hon', 'honorable'), 45 | ('sgt', 'sergeant'), 46 | ('capt', 'captain'), 47 | ('esq', 'esquire'), 48 | ('ltd', 'limited'), 49 | ('col', 'colonel'), 50 | ('ft', 'fort'), 51 | ]] 52 | 53 | 54 | # List of (ipa, lazy ipa) pairs: 55 | _lazy_ipa = [(re.compile('%s' % x[0]), x[1]) for x in [ 56 | ('r', 'ɹ'), 57 | ('æ', 'e'), 58 | ('ɑ', 'a'), 59 | ('ɔ', 'o'), 60 | ('ð', 'z'), 61 | ('θ', 's'), 62 | ('ɛ', 'e'), 63 | ('ɪ', 'i'), 64 | ('ʊ', 'u'), 65 | ('ʒ', 'ʥ'), 66 | ('ʤ', 'ʥ'), 67 | ('ˈ', '↓'), 68 | ]] 69 | 70 | # List of (ipa, lazy ipa2) pairs: 71 | _lazy_ipa2 = [(re.compile('%s' % x[0]), x[1]) for x in [ 72 | ('r', 'ɹ'), 73 | ('ð', 'z'), 74 | ('θ', 's'), 75 | ('ʒ', 'ʑ'), 76 | ('ʤ', 'dʑ'), 77 | ('ˈ', '↓'), 78 | ]] 79 | 80 | # List of (ipa, ipa2) pairs 81 | _ipa_to_ipa2 = [(re.compile('%s' % x[0]), x[1]) for x in [ 82 | ('r', 'ɹ'), 83 | ('ʤ', 'dʒ'), 84 | ('ʧ', 'tʃ') 85 | ]] 86 | 87 | 88 | def expand_abbreviations(text): 89 | for regex, replacement in _abbreviations: 90 | text = re.sub(regex, replacement, text) 91 | return text 92 | 93 | 94 | def collapse_whitespace(text): 95 | return re.sub(r'\s+', ' ', text) 96 | 97 | 98 | def _remove_commas(m): 99 | return m.group(1).replace(',', '') 100 | 101 | 102 | def _expand_decimal_point(m): 103 | return m.group(1).replace('.', ' point ') 104 | 105 | 106 | def _expand_dollars(m): 107 | match = m.group(1) 108 | parts = match.split('.') 109 | if len(parts) > 2: 110 | return match + ' dollars' # Unexpected format 111 | dollars = int(parts[0]) if parts[0] else 0 112 | cents = int(parts[1]) if len(parts) > 1 and parts[1] else 0 113 | if dollars and cents: 114 | dollar_unit = 'dollar' if dollars == 1 else 'dollars' 115 | cent_unit = 'cent' if cents == 1 else 'cents' 116 | return '%s %s, %s %s' % (dollars, dollar_unit, cents, cent_unit) 117 | elif dollars: 118 | dollar_unit = 'dollar' if dollars == 1 else 'dollars' 119 | return '%s %s' % (dollars, dollar_unit) 120 | elif cents: 121 | cent_unit = 'cent' if cents == 1 else 'cents' 122 | return '%s %s' % (cents, cent_unit) 123 | else: 124 | return 'zero dollars' 125 | 126 | 127 | def _expand_ordinal(m): 128 | return _inflect.number_to_words(m.group(0)) 129 | 130 | 131 | def _expand_number(m): 132 | num = int(m.group(0)) 133 | if num > 1000 and num < 3000: 134 | if num == 2000: 135 | return 'two thousand' 136 | elif num > 2000 and num < 2010: 137 | return 'two thousand ' + _inflect.number_to_words(num % 100) 138 | elif num % 100 == 0: 139 | return _inflect.number_to_words(num // 100) + ' hundred' 140 | else: 141 | return _inflect.number_to_words(num, andword='', zero='oh', group=2).replace(', ', ' ') 142 | else: 143 | return _inflect.number_to_words(num, andword='') 144 | 145 | 146 | def normalize_numbers(text): 147 | text = re.sub(_comma_number_re, _remove_commas, text) 148 | text = re.sub(_pounds_re, r'\1 pounds', text) 149 | text = re.sub(_dollars_re, _expand_dollars, text) 150 | text = re.sub(_decimal_number_re, _expand_decimal_point, text) 151 | text = re.sub(_ordinal_re, _expand_ordinal, text) 152 | text = re.sub(_number_re, _expand_number, text) 153 | return text 154 | 155 | 156 | def mark_dark_l(text): 157 | return re.sub(r'l([^aeiouæɑɔəɛɪʊ ]*(?: |$))', lambda x: 'ɫ'+x.group(1), text) 158 | 159 | 160 | def english_to_ipa(text): 161 | text = unidecode(text).lower() 162 | text = expand_abbreviations(text) 163 | text = normalize_numbers(text) 164 | phonemes = ipa.convert(text) 165 | phonemes = collapse_whitespace(phonemes) 166 | return phonemes 167 | 168 | 169 | def english_to_lazy_ipa(text): 170 | text = english_to_ipa(text) 171 | for regex, replacement in _lazy_ipa: 172 | text = re.sub(regex, replacement, text) 173 | return text 174 | 175 | 176 | def english_to_ipa2(text): 177 | text = english_to_ipa(text) 178 | text = mark_dark_l(text) 179 | for regex, replacement in _ipa_to_ipa2: 180 | text = re.sub(regex, replacement, text) 181 | return text.replace('...', '…') 182 | 183 | 184 | def english_to_lazy_ipa2(text): 185 | text = english_to_ipa(text) 186 | for regex, replacement in _lazy_ipa2: 187 | text = re.sub(regex, replacement, text) 188 | return text 189 | -------------------------------------------------------------------------------- /text/cleaners.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | 4 | def japanese_cleaners(text): 5 | from text.japanese import japanese_to_romaji_with_accent 6 | text = japanese_to_romaji_with_accent(text) 7 | text = re.sub(r'([A-Za-z])$', r'\1.', text) 8 | return text 9 | 10 | 11 | def japanese_cleaners2(text): 12 | return japanese_cleaners(text).replace('ts', 'ʦ').replace('...', '…') 13 | 14 | 15 | def korean_cleaners(text): 16 | '''Pipeline for Korean text''' 17 | from text.korean import latin_to_hangul, number_to_hangul, divide_hangul 18 | text = latin_to_hangul(text) 19 | text = number_to_hangul(text) 20 | text = divide_hangul(text) 21 | text = re.sub(r'([\u3131-\u3163])$', r'\1.', text) 22 | return text 23 | 24 | 25 | def chinese_cleaners(text): 26 | '''Pipeline for Chinese text''' 27 | from text.mandarin import number_to_chinese, chinese_to_bopomofo, latin_to_bopomofo 28 | text = number_to_chinese(text) 29 | text = chinese_to_bopomofo(text) 30 | text = latin_to_bopomofo(text) 31 | text = re.sub(r'([ˉˊˇˋ˙])$', r'\1。', text) 32 | return text 33 | 34 | 35 | def zh_ja_mixture_cleaners(text): 36 | from text.mandarin import chinese_to_romaji 37 | from text.japanese import japanese_to_romaji_with_accent 38 | text = re.sub(r'\[ZH\](.*?)\[ZH\]', 39 | lambda x: chinese_to_romaji(x.group(1))+' ', text) 40 | text = re.sub(r'\[JA\](.*?)\[JA\]', lambda x: japanese_to_romaji_with_accent( 41 | x.group(1)).replace('ts', 'ʦ').replace('u', 'ɯ').replace('...', '…')+' ', text) 42 | text = re.sub(r'\s+$', '', text) 43 | text = re.sub(r'([^\.,!\?\-…~])$', r'\1.', text) 44 | return text 45 | 46 | 47 | def sanskrit_cleaners(text): 48 | text = text.replace('॥', '।').replace('ॐ', 'ओम्') 49 | text = re.sub(r'([^।])$', r'\1।', text) 50 | return text 51 | 52 | 53 | def cjks_cleaners(text): 54 | from text.mandarin import chinese_to_lazy_ipa 55 | from text.japanese import japanese_to_ipa 56 | from text.korean import korean_to_lazy_ipa 57 | from text.sanskrit import devanagari_to_ipa 58 | from text.english import english_to_lazy_ipa 59 | text = re.sub(r'\[ZH\](.*?)\[ZH\]', 60 | lambda x: chinese_to_lazy_ipa(x.group(1))+' ', text) 61 | text = re.sub(r'\[JA\](.*?)\[JA\]', 62 | lambda x: japanese_to_ipa(x.group(1))+' ', text) 63 | text = re.sub(r'\[KO\](.*?)\[KO\]', 64 | lambda x: korean_to_lazy_ipa(x.group(1))+' ', text) 65 | text = re.sub(r'\[SA\](.*?)\[SA\]', 66 | lambda x: devanagari_to_ipa(x.group(1))+' ', text) 67 | text = re.sub(r'\[EN\](.*?)\[EN\]', 68 | lambda x: english_to_lazy_ipa(x.group(1))+' ', text) 69 | text = re.sub(r'\s+$', '', text) 70 | text = re.sub(r'([^\.,!\?\-…~])$', r'\1.', text) 71 | return text 72 | 73 | 74 | def cjke_cleaners(text): 75 | from text.mandarin import chinese_to_lazy_ipa 76 | from text.japanese import japanese_to_ipa 77 | from text.korean import korean_to_ipa 78 | from text.english import english_to_ipa2 79 | text = re.sub(r'\[ZH\](.*?)\[ZH\]', lambda x: chinese_to_lazy_ipa(x.group(1)).replace( 80 | 'ʧ', 'tʃ').replace('ʦ', 'ts').replace('ɥan', 'ɥæn')+' ', text) 81 | text = re.sub(r'\[JA\](.*?)\[JA\]', lambda x: japanese_to_ipa(x.group(1)).replace('ʧ', 'tʃ').replace( 82 | 'ʦ', 'ts').replace('ɥan', 'ɥæn').replace('ʥ', 'dz')+' ', text) 83 | text = re.sub(r'\[KO\](.*?)\[KO\]', 84 | lambda x: korean_to_ipa(x.group(1))+' ', text) 85 | text = re.sub(r'\[EN\](.*?)\[EN\]', lambda x: english_to_ipa2(x.group(1)).replace('ɑ', 'a').replace( 86 | 'ɔ', 'o').replace('ɛ', 'e').replace('ɪ', 'i').replace('ʊ', 'u')+' ', text) 87 | text = re.sub(r'\s+$', '', text) 88 | text = re.sub(r'([^\.,!\?\-…~])$', r'\1.', text) 89 | return text 90 | 91 | 92 | def cjke_cleaners2(text): 93 | from text.mandarin import chinese_to_ipa 94 | from text.japanese import japanese_to_ipa2 95 | from text.korean import korean_to_ipa 96 | from text.english import english_to_ipa2 97 | text = re.sub(r'\[ZH\](.*?)\[ZH\]', 98 | lambda x: chinese_to_ipa(x.group(1))+' ', text) 99 | text = re.sub(r'\[JA\](.*?)\[JA\]', 100 | lambda x: japanese_to_ipa2(x.group(1))+' ', text) 101 | text = re.sub(r'\[KO\](.*?)\[KO\]', 102 | lambda x: korean_to_ipa(x.group(1))+' ', text) 103 | text = re.sub(r'\[EN\](.*?)\[EN\]', 104 | lambda x: english_to_ipa2(x.group(1))+' ', text) 105 | text = re.sub(r'\s+$', '', text) 106 | text = re.sub(r'([^\.,!\?\-…~])$', r'\1.', text) 107 | return text 108 | 109 | 110 | def thai_cleaners(text): 111 | from text.thai import num_to_thai, latin_to_thai 112 | text = num_to_thai(text) 113 | text = latin_to_thai(text) 114 | return text 115 | 116 | 117 | def shanghainese_cleaners(text): 118 | from text.shanghainese import shanghainese_to_ipa 119 | text = shanghainese_to_ipa(text) 120 | text = re.sub(r'([^\.,!\?\-…~])$', r'\1.', text) 121 | return text 122 | 123 | 124 | def chinese_dialect_cleaners(text): 125 | from text.mandarin import chinese_to_ipa2 126 | from text.japanese import japanese_to_ipa3 127 | from text.shanghainese import shanghainese_to_ipa 128 | from text.cantonese import cantonese_to_ipa 129 | from text.english import english_to_lazy_ipa2 130 | from text.ngu_dialect import ngu_dialect_to_ipa 131 | text = re.sub(r'\[ZH\](.*?)\[ZH\]', 132 | lambda x: chinese_to_ipa2(x.group(1))+' ', text) 133 | text = re.sub(r'\[JA\](.*?)\[JA\]', 134 | lambda x: japanese_to_ipa3(x.group(1)).replace('Q', 'ʔ')+' ', text) 135 | text = re.sub(r'\[SH\](.*?)\[SH\]', lambda x: shanghainese_to_ipa(x.group(1)).replace('1', '˥˧').replace('5', 136 | '˧˧˦').replace('6', '˩˩˧').replace('7', '˥').replace('8', '˩˨').replace('ᴀ', 'ɐ').replace('ᴇ', 'e')+' ', text) 137 | text = re.sub(r'\[GD\](.*?)\[GD\]', 138 | lambda x: cantonese_to_ipa(x.group(1))+' ', text) 139 | text = re.sub(r'\[EN\](.*?)\[EN\]', 140 | lambda x: english_to_lazy_ipa2(x.group(1))+' ', text) 141 | text = re.sub(r'\[([A-Z]{2})\](.*?)\[\1\]', lambda x: ngu_dialect_to_ipa(x.group(2), x.group( 142 | 1)).replace('ʣ', 'dz').replace('ʥ', 'dʑ').replace('ʦ', 'ts').replace('ʨ', 'tɕ')+' ', text) 143 | text = re.sub(r'\s+$', '', text) 144 | text = re.sub(r'([^\.,!\?\-…~])$', r'\1.', text) 145 | return text 146 | -------------------------------------------------------------------------------- /text/korean.py: -------------------------------------------------------------------------------- 1 | import re 2 | from jamo import h2j, j2hcj 3 | import ko_pron 4 | 5 | 6 | # This is a list of Korean classifiers preceded by pure Korean numerals. 7 | _korean_classifiers = '군데 권 개 그루 닢 대 두 마리 모 모금 뭇 발 발짝 방 번 벌 보루 살 수 술 시 쌈 움큼 정 짝 채 척 첩 축 켤레 톨 통' 8 | 9 | # List of (hangul, hangul divided) pairs: 10 | _hangul_divided = [(re.compile('%s' % x[0]), x[1]) for x in [ 11 | ('ㄳ', 'ㄱㅅ'), 12 | ('ㄵ', 'ㄴㅈ'), 13 | ('ㄶ', 'ㄴㅎ'), 14 | ('ㄺ', 'ㄹㄱ'), 15 | ('ㄻ', 'ㄹㅁ'), 16 | ('ㄼ', 'ㄹㅂ'), 17 | ('ㄽ', 'ㄹㅅ'), 18 | ('ㄾ', 'ㄹㅌ'), 19 | ('ㄿ', 'ㄹㅍ'), 20 | ('ㅀ', 'ㄹㅎ'), 21 | ('ㅄ', 'ㅂㅅ'), 22 | ('ㅘ', 'ㅗㅏ'), 23 | ('ㅙ', 'ㅗㅐ'), 24 | ('ㅚ', 'ㅗㅣ'), 25 | ('ㅝ', 'ㅜㅓ'), 26 | ('ㅞ', 'ㅜㅔ'), 27 | ('ㅟ', 'ㅜㅣ'), 28 | ('ㅢ', 'ㅡㅣ'), 29 | ('ㅑ', 'ㅣㅏ'), 30 | ('ㅒ', 'ㅣㅐ'), 31 | ('ㅕ', 'ㅣㅓ'), 32 | ('ㅖ', 'ㅣㅔ'), 33 | ('ㅛ', 'ㅣㅗ'), 34 | ('ㅠ', 'ㅣㅜ') 35 | ]] 36 | 37 | # List of (Latin alphabet, hangul) pairs: 38 | _latin_to_hangul = [(re.compile('%s' % x[0], re.IGNORECASE), x[1]) for x in [ 39 | ('a', '에이'), 40 | ('b', '비'), 41 | ('c', '시'), 42 | ('d', '디'), 43 | ('e', '이'), 44 | ('f', '에프'), 45 | ('g', '지'), 46 | ('h', '에이치'), 47 | ('i', '아이'), 48 | ('j', '제이'), 49 | ('k', '케이'), 50 | ('l', '엘'), 51 | ('m', '엠'), 52 | ('n', '엔'), 53 | ('o', '오'), 54 | ('p', '피'), 55 | ('q', '큐'), 56 | ('r', '아르'), 57 | ('s', '에스'), 58 | ('t', '티'), 59 | ('u', '유'), 60 | ('v', '브이'), 61 | ('w', '더블유'), 62 | ('x', '엑스'), 63 | ('y', '와이'), 64 | ('z', '제트') 65 | ]] 66 | 67 | # List of (ipa, lazy ipa) pairs: 68 | _ipa_to_lazy_ipa = [(re.compile('%s' % x[0], re.IGNORECASE), x[1]) for x in [ 69 | ('t͡ɕ','ʧ'), 70 | ('d͡ʑ','ʥ'), 71 | ('ɲ','n^'), 72 | ('ɕ','ʃ'), 73 | ('ʷ','w'), 74 | ('ɭ','l`'), 75 | ('ʎ','ɾ'), 76 | ('ɣ','ŋ'), 77 | ('ɰ','ɯ'), 78 | ('ʝ','j'), 79 | ('ʌ','ə'), 80 | ('ɡ','g'), 81 | ('\u031a','#'), 82 | ('\u0348','='), 83 | ('\u031e',''), 84 | ('\u0320',''), 85 | ('\u0339','') 86 | ]] 87 | 88 | 89 | def latin_to_hangul(text): 90 | for regex, replacement in _latin_to_hangul: 91 | text = re.sub(regex, replacement, text) 92 | return text 93 | 94 | 95 | def divide_hangul(text): 96 | text = j2hcj(h2j(text)) 97 | for regex, replacement in _hangul_divided: 98 | text = re.sub(regex, replacement, text) 99 | return text 100 | 101 | 102 | def hangul_number(num, sino=True): 103 | '''Reference https://github.com/Kyubyong/g2pK''' 104 | num = re.sub(',', '', num) 105 | 106 | if num == '0': 107 | return '영' 108 | if not sino and num == '20': 109 | return '스무' 110 | 111 | digits = '123456789' 112 | names = '일이삼사오육칠팔구' 113 | digit2name = {d: n for d, n in zip(digits, names)} 114 | 115 | modifiers = '한 두 세 네 다섯 여섯 일곱 여덟 아홉' 116 | decimals = '열 스물 서른 마흔 쉰 예순 일흔 여든 아흔' 117 | digit2mod = {d: mod for d, mod in zip(digits, modifiers.split())} 118 | digit2dec = {d: dec for d, dec in zip(digits, decimals.split())} 119 | 120 | spelledout = [] 121 | for i, digit in enumerate(num): 122 | i = len(num) - i - 1 123 | if sino: 124 | if i == 0: 125 | name = digit2name.get(digit, '') 126 | elif i == 1: 127 | name = digit2name.get(digit, '') + '십' 128 | name = name.replace('일십', '십') 129 | else: 130 | if i == 0: 131 | name = digit2mod.get(digit, '') 132 | elif i == 1: 133 | name = digit2dec.get(digit, '') 134 | if digit == '0': 135 | if i % 4 == 0: 136 | last_three = spelledout[-min(3, len(spelledout)):] 137 | if ''.join(last_three) == '': 138 | spelledout.append('') 139 | continue 140 | else: 141 | spelledout.append('') 142 | continue 143 | if i == 2: 144 | name = digit2name.get(digit, '') + '백' 145 | name = name.replace('일백', '백') 146 | elif i == 3: 147 | name = digit2name.get(digit, '') + '천' 148 | name = name.replace('일천', '천') 149 | elif i == 4: 150 | name = digit2name.get(digit, '') + '만' 151 | name = name.replace('일만', '만') 152 | elif i == 5: 153 | name = digit2name.get(digit, '') + '십' 154 | name = name.replace('일십', '십') 155 | elif i == 6: 156 | name = digit2name.get(digit, '') + '백' 157 | name = name.replace('일백', '백') 158 | elif i == 7: 159 | name = digit2name.get(digit, '') + '천' 160 | name = name.replace('일천', '천') 161 | elif i == 8: 162 | name = digit2name.get(digit, '') + '억' 163 | elif i == 9: 164 | name = digit2name.get(digit, '') + '십' 165 | elif i == 10: 166 | name = digit2name.get(digit, '') + '백' 167 | elif i == 11: 168 | name = digit2name.get(digit, '') + '천' 169 | elif i == 12: 170 | name = digit2name.get(digit, '') + '조' 171 | elif i == 13: 172 | name = digit2name.get(digit, '') + '십' 173 | elif i == 14: 174 | name = digit2name.get(digit, '') + '백' 175 | elif i == 15: 176 | name = digit2name.get(digit, '') + '천' 177 | spelledout.append(name) 178 | return ''.join(elem for elem in spelledout) 179 | 180 | 181 | def number_to_hangul(text): 182 | '''Reference https://github.com/Kyubyong/g2pK''' 183 | tokens = set(re.findall(r'(\d[\d,]*)([\uac00-\ud71f]+)', text)) 184 | for token in tokens: 185 | num, classifier = token 186 | if classifier[:2] in _korean_classifiers or classifier[0] in _korean_classifiers: 187 | spelledout = hangul_number(num, sino=False) 188 | else: 189 | spelledout = hangul_number(num, sino=True) 190 | text = text.replace(f'{num}{classifier}', f'{spelledout}{classifier}') 191 | # digit by digit for remaining digits 192 | digits = '0123456789' 193 | names = '영일이삼사오육칠팔구' 194 | for d, n in zip(digits, names): 195 | text = text.replace(d, n) 196 | return text 197 | 198 | 199 | def korean_to_lazy_ipa(text): 200 | text = latin_to_hangul(text) 201 | text = number_to_hangul(text) 202 | text=re.sub('[\uac00-\ud7af]+',lambda x:ko_pron.romanise(x.group(0),'ipa').split('] ~ [')[0],text) 203 | for regex, replacement in _ipa_to_lazy_ipa: 204 | text = re.sub(regex, replacement, text) 205 | return text 206 | 207 | 208 | def korean_to_ipa(text): 209 | text = korean_to_lazy_ipa(text) 210 | return text.replace('ʧ','tʃ').replace('ʥ','dʑ') 211 | -------------------------------------------------------------------------------- /text/mandarin.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import re 4 | from pypinyin import lazy_pinyin, BOPOMOFO 5 | import jieba 6 | import cn2an 7 | import logging 8 | 9 | logging.getLogger('jieba').setLevel(logging.WARNING) 10 | jieba.set_dictionary(r'./jieba/dict.txt') 11 | jieba.initialize() 12 | 13 | 14 | # List of (Latin alphabet, bopomofo) pairs: 15 | _latin_to_bopomofo = [(re.compile('%s' % x[0], re.IGNORECASE), x[1]) for x in [ 16 | ('a', 'ㄟˉ'), 17 | ('b', 'ㄅㄧˋ'), 18 | ('c', 'ㄙㄧˉ'), 19 | ('d', 'ㄉㄧˋ'), 20 | ('e', 'ㄧˋ'), 21 | ('f', 'ㄝˊㄈㄨˋ'), 22 | ('g', 'ㄐㄧˋ'), 23 | ('h', 'ㄝˇㄑㄩˋ'), 24 | ('i', 'ㄞˋ'), 25 | ('j', 'ㄐㄟˋ'), 26 | ('k', 'ㄎㄟˋ'), 27 | ('l', 'ㄝˊㄛˋ'), 28 | ('m', 'ㄝˊㄇㄨˋ'), 29 | ('n', 'ㄣˉ'), 30 | ('o', 'ㄡˉ'), 31 | ('p', 'ㄆㄧˉ'), 32 | ('q', 'ㄎㄧㄡˉ'), 33 | ('r', 'ㄚˋ'), 34 | ('s', 'ㄝˊㄙˋ'), 35 | ('t', 'ㄊㄧˋ'), 36 | ('u', 'ㄧㄡˉ'), 37 | ('v', 'ㄨㄧˉ'), 38 | ('w', 'ㄉㄚˋㄅㄨˋㄌㄧㄡˋ'), 39 | ('x', 'ㄝˉㄎㄨˋㄙˋ'), 40 | ('y', 'ㄨㄞˋ'), 41 | ('z', 'ㄗㄟˋ') 42 | ]] 43 | 44 | # List of (bopomofo, romaji) pairs: 45 | _bopomofo_to_romaji = [(re.compile('%s' % x[0]), x[1]) for x in [ 46 | ('ㄅㄛ', 'p⁼wo'), 47 | ('ㄆㄛ', 'pʰwo'), 48 | ('ㄇㄛ', 'mwo'), 49 | ('ㄈㄛ', 'fwo'), 50 | ('ㄅ', 'p⁼'), 51 | ('ㄆ', 'pʰ'), 52 | ('ㄇ', 'm'), 53 | ('ㄈ', 'f'), 54 | ('ㄉ', 't⁼'), 55 | ('ㄊ', 'tʰ'), 56 | ('ㄋ', 'n'), 57 | ('ㄌ', 'l'), 58 | ('ㄍ', 'k⁼'), 59 | ('ㄎ', 'kʰ'), 60 | ('ㄏ', 'h'), 61 | ('ㄐ', 'ʧ⁼'), 62 | ('ㄑ', 'ʧʰ'), 63 | ('ㄒ', 'ʃ'), 64 | ('ㄓ', 'ʦ`⁼'), 65 | ('ㄔ', 'ʦ`ʰ'), 66 | ('ㄕ', 's`'), 67 | ('ㄖ', 'ɹ`'), 68 | ('ㄗ', 'ʦ⁼'), 69 | ('ㄘ', 'ʦʰ'), 70 | ('ㄙ', 's'), 71 | ('ㄚ', 'a'), 72 | ('ㄛ', 'o'), 73 | ('ㄜ', 'ə'), 74 | ('ㄝ', 'e'), 75 | ('ㄞ', 'ai'), 76 | ('ㄟ', 'ei'), 77 | ('ㄠ', 'au'), 78 | ('ㄡ', 'ou'), 79 | ('ㄧㄢ', 'yeNN'), 80 | ('ㄢ', 'aNN'), 81 | ('ㄧㄣ', 'iNN'), 82 | ('ㄣ', 'əNN'), 83 | ('ㄤ', 'aNg'), 84 | ('ㄧㄥ', 'iNg'), 85 | ('ㄨㄥ', 'uNg'), 86 | ('ㄩㄥ', 'yuNg'), 87 | ('ㄥ', 'əNg'), 88 | ('ㄦ', 'əɻ'), 89 | ('ㄧ', 'i'), 90 | ('ㄨ', 'u'), 91 | ('ㄩ', 'ɥ'), 92 | ('ˉ', '→'), 93 | ('ˊ', '↑'), 94 | ('ˇ', '↓↑'), 95 | ('ˋ', '↓'), 96 | ('˙', ''), 97 | (',', ','), 98 | ('。', '.'), 99 | ('!', '!'), 100 | ('?', '?'), 101 | ('—', '-') 102 | ]] 103 | 104 | # List of (romaji, ipa) pairs: 105 | _romaji_to_ipa = [(re.compile('%s' % x[0], re.IGNORECASE), x[1]) for x in [ 106 | ('ʃy', 'ʃ'), 107 | ('ʧʰy', 'ʧʰ'), 108 | ('ʧ⁼y', 'ʧ⁼'), 109 | ('NN', 'n'), 110 | ('Ng', 'ŋ'), 111 | ('y', 'j'), 112 | ('h', 'x') 113 | ]] 114 | 115 | # List of (bopomofo, ipa) pairs: 116 | _bopomofo_to_ipa = [(re.compile('%s' % x[0]), x[1]) for x in [ 117 | ('ㄅㄛ', 'p⁼wo'), 118 | ('ㄆㄛ', 'pʰwo'), 119 | ('ㄇㄛ', 'mwo'), 120 | ('ㄈㄛ', 'fwo'), 121 | ('ㄅ', 'p⁼'), 122 | ('ㄆ', 'pʰ'), 123 | ('ㄇ', 'm'), 124 | ('ㄈ', 'f'), 125 | ('ㄉ', 't⁼'), 126 | ('ㄊ', 'tʰ'), 127 | ('ㄋ', 'n'), 128 | ('ㄌ', 'l'), 129 | ('ㄍ', 'k⁼'), 130 | ('ㄎ', 'kʰ'), 131 | ('ㄏ', 'x'), 132 | ('ㄐ', 'tʃ⁼'), 133 | ('ㄑ', 'tʃʰ'), 134 | ('ㄒ', 'ʃ'), 135 | ('ㄓ', 'ts`⁼'), 136 | ('ㄔ', 'ts`ʰ'), 137 | ('ㄕ', 's`'), 138 | ('ㄖ', 'ɹ`'), 139 | ('ㄗ', 'ts⁼'), 140 | ('ㄘ', 'tsʰ'), 141 | ('ㄙ', 's'), 142 | ('ㄚ', 'a'), 143 | ('ㄛ', 'o'), 144 | ('ㄜ', 'ə'), 145 | ('ㄝ', 'ɛ'), 146 | ('ㄞ', 'aɪ'), 147 | ('ㄟ', 'eɪ'), 148 | ('ㄠ', 'ɑʊ'), 149 | ('ㄡ', 'oʊ'), 150 | ('ㄧㄢ', 'jɛn'), 151 | ('ㄩㄢ', 'ɥæn'), 152 | ('ㄢ', 'an'), 153 | ('ㄧㄣ', 'in'), 154 | ('ㄩㄣ', 'ɥn'), 155 | ('ㄣ', 'ən'), 156 | ('ㄤ', 'ɑŋ'), 157 | ('ㄧㄥ', 'iŋ'), 158 | ('ㄨㄥ', 'ʊŋ'), 159 | ('ㄩㄥ', 'jʊŋ'), 160 | ('ㄥ', 'əŋ'), 161 | ('ㄦ', 'əɻ'), 162 | ('ㄧ', 'i'), 163 | ('ㄨ', 'u'), 164 | ('ㄩ', 'ɥ'), 165 | ('ˉ', '→'), 166 | ('ˊ', '↑'), 167 | ('ˇ', '↓↑'), 168 | ('ˋ', '↓'), 169 | ('˙', ''), 170 | (',', ','), 171 | ('。', '.'), 172 | ('!', '!'), 173 | ('?', '?'), 174 | ('—', '-') 175 | ]] 176 | 177 | # List of (bopomofo, ipa2) pairs: 178 | _bopomofo_to_ipa2 = [(re.compile('%s' % x[0]), x[1]) for x in [ 179 | ('ㄅㄛ', 'pwo'), 180 | ('ㄆㄛ', 'pʰwo'), 181 | ('ㄇㄛ', 'mwo'), 182 | ('ㄈㄛ', 'fwo'), 183 | ('ㄅ', 'p'), 184 | ('ㄆ', 'pʰ'), 185 | ('ㄇ', 'm'), 186 | ('ㄈ', 'f'), 187 | ('ㄉ', 't'), 188 | ('ㄊ', 'tʰ'), 189 | ('ㄋ', 'n'), 190 | ('ㄌ', 'l'), 191 | ('ㄍ', 'k'), 192 | ('ㄎ', 'kʰ'), 193 | ('ㄏ', 'h'), 194 | ('ㄐ', 'tɕ'), 195 | ('ㄑ', 'tɕʰ'), 196 | ('ㄒ', 'ɕ'), 197 | ('ㄓ', 'tʂ'), 198 | ('ㄔ', 'tʂʰ'), 199 | ('ㄕ', 'ʂ'), 200 | ('ㄖ', 'ɻ'), 201 | ('ㄗ', 'ts'), 202 | ('ㄘ', 'tsʰ'), 203 | ('ㄙ', 's'), 204 | ('ㄚ', 'a'), 205 | ('ㄛ', 'o'), 206 | ('ㄜ', 'ɤ'), 207 | ('ㄝ', 'ɛ'), 208 | ('ㄞ', 'aɪ'), 209 | ('ㄟ', 'eɪ'), 210 | ('ㄠ', 'ɑʊ'), 211 | ('ㄡ', 'oʊ'), 212 | ('ㄧㄢ', 'jɛn'), 213 | ('ㄩㄢ', 'yæn'), 214 | ('ㄢ', 'an'), 215 | ('ㄧㄣ', 'in'), 216 | ('ㄩㄣ', 'yn'), 217 | ('ㄣ', 'ən'), 218 | ('ㄤ', 'ɑŋ'), 219 | ('ㄧㄥ', 'iŋ'), 220 | ('ㄨㄥ', 'ʊŋ'), 221 | ('ㄩㄥ', 'jʊŋ'), 222 | ('ㄥ', 'ɤŋ'), 223 | ('ㄦ', 'əɻ'), 224 | ('ㄧ', 'i'), 225 | ('ㄨ', 'u'), 226 | ('ㄩ', 'y'), 227 | ('ˉ', '˥'), 228 | ('ˊ', '˧˥'), 229 | ('ˇ', '˨˩˦'), 230 | ('ˋ', '˥˩'), 231 | ('˙', ''), 232 | (',', ','), 233 | ('。', '.'), 234 | ('!', '!'), 235 | ('?', '?'), 236 | ('—', '-') 237 | ]] 238 | 239 | 240 | def number_to_chinese(text): 241 | numbers = re.findall(r'\d+(?:\.?\d+)?', text) 242 | for number in numbers: 243 | text = text.replace(number, cn2an.an2cn(number), 1) 244 | return text 245 | 246 | 247 | def chinese_to_bopomofo(text): 248 | text = text.replace('、', ',').replace(';', ',').replace(':', ',') 249 | words = jieba.lcut(text, cut_all=False) 250 | text = '' 251 | for word in words: 252 | bopomofos = lazy_pinyin(word, BOPOMOFO) 253 | if not re.search('[\u4e00-\u9fff]', word): 254 | text += word 255 | continue 256 | for i in range(len(bopomofos)): 257 | bopomofos[i] = re.sub(r'([\u3105-\u3129])$', r'\1ˉ', bopomofos[i]) 258 | if text != '': 259 | text += ' ' 260 | text += ''.join(bopomofos) 261 | return text 262 | 263 | 264 | def latin_to_bopomofo(text): 265 | for regex, replacement in _latin_to_bopomofo: 266 | text = re.sub(regex, replacement, text) 267 | return text 268 | 269 | 270 | def bopomofo_to_romaji(text): 271 | for regex, replacement in _bopomofo_to_romaji: 272 | text = re.sub(regex, replacement, text) 273 | return text 274 | 275 | 276 | def bopomofo_to_ipa(text): 277 | for regex, replacement in _bopomofo_to_ipa: 278 | text = re.sub(regex, replacement, text) 279 | return text 280 | 281 | 282 | def bopomofo_to_ipa2(text): 283 | for regex, replacement in _bopomofo_to_ipa2: 284 | text = re.sub(regex, replacement, text) 285 | return text 286 | 287 | 288 | def chinese_to_romaji(text): 289 | text = number_to_chinese(text) 290 | text = chinese_to_bopomofo(text) 291 | text = latin_to_bopomofo(text) 292 | text = bopomofo_to_romaji(text) 293 | text = re.sub('i([aoe])', r'y\1', text) 294 | text = re.sub('u([aoəe])', r'w\1', text) 295 | text = re.sub('([ʦsɹ]`[⁼ʰ]?)([→↓↑ ]+|$)', 296 | r'\1ɹ`\2', text).replace('ɻ', 'ɹ`') 297 | text = re.sub('([ʦs][⁼ʰ]?)([→↓↑ ]+|$)', r'\1ɹ\2', text) 298 | return text 299 | 300 | 301 | def chinese_to_lazy_ipa(text): 302 | text = chinese_to_romaji(text) 303 | for regex, replacement in _romaji_to_ipa: 304 | text = re.sub(regex, replacement, text) 305 | return text 306 | 307 | 308 | def chinese_to_ipa(text): 309 | text = number_to_chinese(text) 310 | text = chinese_to_bopomofo(text) 311 | text = latin_to_bopomofo(text) 312 | text = bopomofo_to_ipa(text) 313 | text = re.sub('i([aoe])', r'j\1', text) 314 | text = re.sub('u([aoəe])', r'w\1', text) 315 | text = re.sub('([sɹ]`[⁼ʰ]?)([→↓↑ ]+|$)', 316 | r'\1ɹ`\2', text).replace('ɻ', 'ɹ`') 317 | text = re.sub('([s][⁼ʰ]?)([→↓↑ ]+|$)', r'\1ɹ\2', text) 318 | return text 319 | 320 | 321 | def chinese_to_ipa2(text): 322 | text = number_to_chinese(text) 323 | text = chinese_to_bopomofo(text) 324 | text = latin_to_bopomofo(text) 325 | text = bopomofo_to_ipa2(text) 326 | text = re.sub(r'i([aoe])', r'j\1', text) 327 | text = re.sub(r'u([aoəe])', r'w\1', text) 328 | text = re.sub(r'([ʂɹ]ʰ?)([˩˨˧˦˥ ]+|$)', r'\1ʅ\2', text) 329 | text = re.sub(r'(sʰ?)([˩˨˧˦˥ ]+|$)', r'\1ɿ\2', text) 330 | return text 331 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Oo]ut/ 33 | [Ll]og/ 34 | [Ll]ogs/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUnit 49 | *.VisualState.xml 50 | TestResult.xml 51 | nunit-*.xml 52 | 53 | # Build Results of an ATL Project 54 | [Dd]ebugPS/ 55 | [Rr]eleasePS/ 56 | dlldata.c 57 | 58 | # Benchmark Results 59 | BenchmarkDotNet.Artifacts/ 60 | 61 | # .NET Core 62 | project.lock.json 63 | project.fragment.lock.json 64 | artifacts/ 65 | 66 | # ASP.NET Scaffolding 67 | ScaffoldingReadMe.txt 68 | 69 | # StyleCop 70 | StyleCopReport.xml 71 | 72 | # Files built by Visual Studio 73 | *_i.c 74 | *_p.c 75 | *_h.h 76 | *.ilk 77 | *.meta 78 | *.obj 79 | *.iobj 80 | *.pch 81 | *.pdb 82 | *.ipdb 83 | *.pgc 84 | *.pgd 85 | *.rsp 86 | *.sbr 87 | *.tlb 88 | *.tli 89 | *.tlh 90 | *.tmp 91 | *.tmp_proj 92 | *_wpftmp.csproj 93 | *.log 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio LightSwitch build output 298 | **/*.HTMLClient/GeneratedArtifacts 299 | **/*.DesktopClient/GeneratedArtifacts 300 | **/*.DesktopClient/ModelManifest.xml 301 | **/*.Server/GeneratedArtifacts 302 | **/*.Server/ModelManifest.xml 303 | _Pvt_Extensions 304 | 305 | # Paket dependency manager 306 | .paket/paket.exe 307 | paket-files/ 308 | 309 | # FAKE - F# Make 310 | .fake/ 311 | 312 | # CodeRush personal settings 313 | .cr/personal 314 | 315 | # Python Tools for Visual Studio (PTVS) 316 | __pycache__/ 317 | *.pyc 318 | 319 | # Cake - Uncomment if you are using it 320 | # tools/** 321 | # !tools/packages.config 322 | 323 | # Tabs Studio 324 | *.tss 325 | 326 | # Telerik's JustMock configuration file 327 | *.jmconfig 328 | 329 | # BizTalk build output 330 | *.btp.cs 331 | *.btm.cs 332 | *.odx.cs 333 | *.xsd.cs 334 | 335 | # OpenCover UI analysis results 336 | OpenCover/ 337 | 338 | # Azure Stream Analytics local run output 339 | ASALocalRun/ 340 | 341 | # MSBuild Binary and Structured Log 342 | *.binlog 343 | 344 | # NVidia Nsight GPU debugger configuration file 345 | *.nvuser 346 | 347 | # MFractors (Xamarin productivity tool) working folder 348 | .mfractor/ 349 | 350 | # Local History for Visual Studio 351 | .localhistory/ 352 | 353 | # BeatPulse healthcheck temp database 354 | healthchecksdb 355 | 356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 357 | MigrationBackup/ 358 | 359 | # Ionide (cross platform F# VS Code tools) working folder 360 | .ionide/ 361 | 362 | # Fody - auto-generated XML schema 363 | FodyWeavers.xsd 364 | 365 | # build 366 | build 367 | monotonic_align/core.c 368 | *.o 369 | *.so 370 | *.dll 371 | 372 | # data 373 | /config.json 374 | /*.pth 375 | *.wav 376 | /monotonic_align/monotonic_align 377 | /resources 378 | /MoeGoe.spec 379 | /dist/MoeGoe 380 | /dist 381 | 382 | # MacOS 383 | .DS_Store 384 | 385 | # 가상환경 386 | .venv/ 387 | 388 | # 개인 기록 389 | userfile/log/* 390 | userfile/tts/* 391 | output.wav 392 | test.ogg 393 | log.txt 394 | 395 | # 테스트용 396 | *.ipynb 397 | 398 | # 렌파이 생성 파일 399 | *.rpyc 400 | ChatWithGPT/game/saves/ 401 | ChatWithGPT/game/cache/ 402 | ChatWithGPT/game/Resources/* 403 | !ChatWithGPT/game/Resources/Hiyori/ 404 | -------------------------------------------------------------------------------- /hubert_model.py: -------------------------------------------------------------------------------- 1 | import copy 2 | from typing import Optional, Tuple 3 | import random 4 | 5 | import torch 6 | import torch.nn as nn 7 | import torch.nn.functional as F 8 | from torch.nn.modules.utils import consume_prefix_in_state_dict_if_present 9 | 10 | device = torch.device("cuda" if torch.cuda.is_available() else "cpu") 11 | 12 | class Hubert(nn.Module): 13 | def __init__(self, num_label_embeddings: int = 100, mask: bool = True): 14 | super().__init__() 15 | self._mask = mask 16 | self.feature_extractor = FeatureExtractor().to(device) 17 | self.feature_projection = FeatureProjection().to(device) 18 | self.positional_embedding = PositionalConvEmbedding().to(device) 19 | self.norm = nn.LayerNorm(768).to(device) 20 | self.dropout = nn.Dropout(0.1).to(device) 21 | self.encoder = TransformerEncoder( 22 | nn.TransformerEncoderLayer( 23 | 768, 12, 3072, activation="gelu", batch_first=True 24 | ), 25 | 12, 26 | ).to(device) 27 | self.proj = nn.Linear(768, 256).to(device) 28 | 29 | self.masked_spec_embed = nn.Parameter(torch.cuda.FloatTensor(768).uniform_()) 30 | self.label_embedding = nn.Embedding(num_label_embeddings, 256).to(device) 31 | 32 | def mask(self, x: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]: 33 | mask = None 34 | if self.training and self._mask: 35 | mask = _compute_mask((x.size(0), x.size(1)), 0.8, 10, x.device, 2) 36 | x[mask] = self.masked_spec_embed.to(x.dtype) 37 | return x, mask 38 | 39 | def encode( 40 | self, x: torch.Tensor, layer: Optional[int] = None 41 | ) -> Tuple[torch.Tensor, torch.Tensor]: 42 | x = self.feature_extractor(x.to(device)) 43 | x = self.feature_projection(x.transpose(1, 2)) 44 | x, mask = self.mask(x) 45 | x = x + self.positional_embedding(x) 46 | x = self.dropout(self.norm(x)) 47 | x = self.encoder(x, output_layer=layer) 48 | return x, mask 49 | 50 | def logits(self, x: torch.Tensor) -> torch.Tensor: 51 | logits = torch.cosine_similarity( 52 | x.unsqueeze(2), 53 | self.label_embedding.weight.unsqueeze(0).unsqueeze(0), 54 | dim=-1, 55 | ) 56 | return logits / 0.1 57 | 58 | def forward(self, x: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]: 59 | x, mask = self.encode(x.to(device)) 60 | x = self.proj(x) 61 | logits = self.logits(x) 62 | return logits, mask 63 | 64 | 65 | class HubertSoft(Hubert): 66 | def __init__(self): 67 | super().__init__() 68 | 69 | @torch.jit.script 70 | @torch.jit.unused 71 | def units(self, wav: torch.Tensor) -> torch.Tensor: 72 | wav = F.pad(wav, ((400 - 320) // 2, (400 - 320) // 2)) 73 | x, _ = self.encode(wav.to(device)) 74 | return self.proj(x) 75 | 76 | 77 | class FeatureExtractor(nn.Module): 78 | def __init__(self): 79 | super().__init__() 80 | self.conv0 = nn.Conv1d(1, 512, 10, 5, bias=False) 81 | self.norm0 = nn.GroupNorm(512, 512) 82 | self.conv1 = nn.Conv1d(512, 512, 3, 2, bias=False) 83 | self.conv2 = nn.Conv1d(512, 512, 3, 2, bias=False) 84 | self.conv3 = nn.Conv1d(512, 512, 3, 2, bias=False) 85 | self.conv4 = nn.Conv1d(512, 512, 3, 2, bias=False) 86 | self.conv5 = nn.Conv1d(512, 512, 2, 2, bias=False) 87 | self.conv6 = nn.Conv1d(512, 512, 2, 2, bias=False) 88 | 89 | def forward(self, x: torch.Tensor) -> torch.Tensor: 90 | x = F.gelu(self.norm0(self.conv0(x.to(device)))) 91 | x = F.gelu(self.conv1(x)) 92 | x = F.gelu(self.conv2(x)) 93 | x = F.gelu(self.conv3(x)) 94 | x = F.gelu(self.conv4(x)) 95 | x = F.gelu(self.conv5(x)) 96 | x = F.gelu(self.conv6(x)) 97 | return x 98 | 99 | 100 | class FeatureProjection(nn.Module): 101 | def __init__(self): 102 | super().__init__() 103 | self.norm = nn.LayerNorm(512) 104 | self.projection = nn.Linear(512, 768) 105 | self.dropout = nn.Dropout(0.1) 106 | 107 | def forward(self, x: torch.Tensor) -> torch.Tensor: 108 | x = self.norm(x.to(device)) 109 | x = self.projection(x) 110 | x = self.dropout(x) 111 | return x 112 | 113 | 114 | class PositionalConvEmbedding(nn.Module): 115 | def __init__(self): 116 | super().__init__() 117 | self.conv = nn.Conv1d( 118 | 768, 119 | 768, 120 | kernel_size=128, 121 | padding=128 // 2, 122 | groups=16, 123 | ) 124 | self.conv = nn.utils.weight_norm(self.conv.to(device), name="weight", dim=2) 125 | 126 | def forward(self, x: torch.Tensor) -> torch.Tensor: 127 | x = self.conv(x.transpose(1, 2)) 128 | x = F.gelu(x[:, :, :-1]) 129 | return x.transpose(1, 2) 130 | 131 | 132 | class TransformerEncoder(nn.Module): 133 | def __init__( 134 | self, encoder_layer: nn.TransformerEncoderLayer, num_layers: int 135 | ) -> None: 136 | super(TransformerEncoder, self).__init__() 137 | self.layers = nn.ModuleList( 138 | [copy.deepcopy(encoder_layer) for _ in range(num_layers)] 139 | ) 140 | self.num_layers = num_layers 141 | 142 | def forward( 143 | self, 144 | src: torch.Tensor, 145 | mask: torch.Tensor = None, 146 | src_key_padding_mask: torch.Tensor = None, 147 | output_layer: Optional[int] = None, 148 | ) -> torch.Tensor: 149 | output = src.to(device) 150 | if mask is not None: 151 | mask = mask.to(device) 152 | if src_key_padding_mask is not None: 153 | src_key_padding_mask = src_key_padding_mask.to(device) 154 | for layer in self.layers[:output_layer]: 155 | output = layer( 156 | output.to(device), src_mask=mask, src_key_padding_mask=src_key_padding_mask 157 | ) 158 | return output 159 | 160 | 161 | def _compute_mask( 162 | shape: Tuple[int, int], 163 | mask_prob: float, 164 | mask_length: int, 165 | device: torch.device, 166 | min_masks: int = 0, 167 | ) -> torch.Tensor: 168 | batch_size, sequence_length = shape 169 | 170 | if mask_length < 1: 171 | raise ValueError("`mask_length` has to be bigger than 0.") 172 | 173 | if mask_length > sequence_length: 174 | raise ValueError( 175 | f"`mask_length` has to be smaller than `sequence_length`, but got `mask_length`: {mask_length} and `sequence_length`: {sequence_length}`" 176 | ) 177 | 178 | # compute number of masked spans in batch 179 | num_masked_spans = int(mask_prob * sequence_length / mask_length + random.random()) 180 | num_masked_spans = max(num_masked_spans, min_masks) 181 | 182 | # make sure num masked indices <= sequence_length 183 | if num_masked_spans * mask_length > sequence_length: 184 | num_masked_spans = sequence_length // mask_length 185 | 186 | # SpecAugment mask to fill 187 | mask = torch.zeros((batch_size, sequence_length), device=device, dtype=torch.bool) 188 | 189 | # uniform distribution to sample from, make sure that offset samples are < sequence_length 190 | uniform_dist = torch.ones( 191 | (batch_size, sequence_length - (mask_length - 1)), device=device 192 | ) 193 | 194 | # get random indices to mask 195 | mask_indices = torch.multinomial(uniform_dist, num_masked_spans) 196 | 197 | # expand masked indices to masked spans 198 | mask_indices = ( 199 | mask_indices.unsqueeze(dim=-1) 200 | .expand((batch_size, num_masked_spans, mask_length)) 201 | .reshape(batch_size, num_masked_spans * mask_length) 202 | ) 203 | offsets = ( 204 | torch.arange(mask_length, device=device)[None, None, :] 205 | .expand((batch_size, num_masked_spans, mask_length)) 206 | .reshape(batch_size, num_masked_spans * mask_length) 207 | ) 208 | mask_idxs = mask_indices + offsets 209 | 210 | # scatter indices to mask 211 | mask = mask.scatter(1, mask_idxs, True) 212 | 213 | return mask.to(torch.bool) 214 | 215 | 216 | def hubert_soft(path: str) -> HubertSoft: 217 | r"""HuBERT-Soft from `"A Comparison of Discrete and Soft Speech Units for Improved Voice Conversion"`. 218 | Args: 219 | path (str): path of a pretrained model 220 | """ 221 | hubert = HubertSoft() 222 | checkpoint = torch.load(path, map_location=device) 223 | consume_prefix_in_state_dict_if_present(checkpoint, "module.") 224 | hubert.load_state_dict(checkpoint) 225 | hubert.to(device) 226 | hubert.eval() 227 | return hubert -------------------------------------------------------------------------------- /transforms.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch.nn import functional as F 3 | 4 | import numpy as np 5 | 6 | 7 | DEFAULT_MIN_BIN_WIDTH = 1e-3 8 | DEFAULT_MIN_BIN_HEIGHT = 1e-3 9 | DEFAULT_MIN_DERIVATIVE = 1e-3 10 | 11 | 12 | def piecewise_rational_quadratic_transform(inputs, 13 | unnormalized_widths, 14 | unnormalized_heights, 15 | unnormalized_derivatives, 16 | inverse=False, 17 | tails=None, 18 | tail_bound=1., 19 | min_bin_width=DEFAULT_MIN_BIN_WIDTH, 20 | min_bin_height=DEFAULT_MIN_BIN_HEIGHT, 21 | min_derivative=DEFAULT_MIN_DERIVATIVE): 22 | 23 | if tails is None: 24 | spline_fn = rational_quadratic_spline 25 | spline_kwargs = {} 26 | else: 27 | spline_fn = unconstrained_rational_quadratic_spline 28 | spline_kwargs = { 29 | 'tails': tails, 30 | 'tail_bound': tail_bound 31 | } 32 | 33 | outputs, logabsdet = spline_fn( 34 | inputs=inputs, 35 | unnormalized_widths=unnormalized_widths, 36 | unnormalized_heights=unnormalized_heights, 37 | unnormalized_derivatives=unnormalized_derivatives, 38 | inverse=inverse, 39 | min_bin_width=min_bin_width, 40 | min_bin_height=min_bin_height, 41 | min_derivative=min_derivative, 42 | **spline_kwargs 43 | ) 44 | return outputs, logabsdet 45 | 46 | 47 | def searchsorted(bin_locations, inputs, eps=1e-6): 48 | bin_locations[..., -1] += eps 49 | return torch.sum( 50 | inputs[..., None] >= bin_locations, 51 | dim=-1 52 | ) - 1 53 | 54 | 55 | def unconstrained_rational_quadratic_spline(inputs, 56 | unnormalized_widths, 57 | unnormalized_heights, 58 | unnormalized_derivatives, 59 | inverse=False, 60 | tails='linear', 61 | tail_bound=1., 62 | min_bin_width=DEFAULT_MIN_BIN_WIDTH, 63 | min_bin_height=DEFAULT_MIN_BIN_HEIGHT, 64 | min_derivative=DEFAULT_MIN_DERIVATIVE): 65 | inside_interval_mask = (inputs >= -tail_bound) & (inputs <= tail_bound) 66 | outside_interval_mask = ~inside_interval_mask 67 | 68 | outputs = torch.zeros_like(inputs) 69 | logabsdet = torch.zeros_like(inputs) 70 | 71 | if tails == 'linear': 72 | unnormalized_derivatives = F.pad(unnormalized_derivatives, pad=(1, 1)) 73 | constant = np.log(np.exp(1 - min_derivative) - 1) 74 | unnormalized_derivatives[..., 0] = constant 75 | unnormalized_derivatives[..., -1] = constant 76 | 77 | outputs[outside_interval_mask] = inputs[outside_interval_mask] 78 | logabsdet[outside_interval_mask] = 0 79 | else: 80 | raise RuntimeError('{} tails are not implemented.'.format(tails)) 81 | 82 | outputs[inside_interval_mask], logabsdet[inside_interval_mask] = rational_quadratic_spline( 83 | inputs=inputs[inside_interval_mask], 84 | unnormalized_widths=unnormalized_widths[inside_interval_mask, :], 85 | unnormalized_heights=unnormalized_heights[inside_interval_mask, :], 86 | unnormalized_derivatives=unnormalized_derivatives[inside_interval_mask, :], 87 | inverse=inverse, 88 | left=-tail_bound, right=tail_bound, bottom=-tail_bound, top=tail_bound, 89 | min_bin_width=min_bin_width, 90 | min_bin_height=min_bin_height, 91 | min_derivative=min_derivative 92 | ) 93 | 94 | return outputs, logabsdet 95 | 96 | def rational_quadratic_spline(inputs, 97 | unnormalized_widths, 98 | unnormalized_heights, 99 | unnormalized_derivatives, 100 | inverse=False, 101 | left=0., right=1., bottom=0., top=1., 102 | min_bin_width=DEFAULT_MIN_BIN_WIDTH, 103 | min_bin_height=DEFAULT_MIN_BIN_HEIGHT, 104 | min_derivative=DEFAULT_MIN_DERIVATIVE): 105 | if torch.min(inputs) < left or torch.max(inputs) > right: 106 | raise ValueError('Input to a transform is not within its domain') 107 | 108 | num_bins = unnormalized_widths.shape[-1] 109 | 110 | if min_bin_width * num_bins > 1.0: 111 | raise ValueError('Minimal bin width too large for the number of bins') 112 | if min_bin_height * num_bins > 1.0: 113 | raise ValueError('Minimal bin height too large for the number of bins') 114 | 115 | widths = F.softmax(unnormalized_widths, dim=-1) 116 | widths = min_bin_width + (1 - min_bin_width * num_bins) * widths 117 | cumwidths = torch.cumsum(widths, dim=-1) 118 | cumwidths = F.pad(cumwidths, pad=(1, 0), mode='constant', value=0.0) 119 | cumwidths = (right - left) * cumwidths + left 120 | cumwidths[..., 0] = left 121 | cumwidths[..., -1] = right 122 | widths = cumwidths[..., 1:] - cumwidths[..., :-1] 123 | 124 | derivatives = min_derivative + F.softplus(unnormalized_derivatives) 125 | 126 | heights = F.softmax(unnormalized_heights, dim=-1) 127 | heights = min_bin_height + (1 - min_bin_height * num_bins) * heights 128 | cumheights = torch.cumsum(heights, dim=-1) 129 | cumheights = F.pad(cumheights, pad=(1, 0), mode='constant', value=0.0) 130 | cumheights = (top - bottom) * cumheights + bottom 131 | cumheights[..., 0] = bottom 132 | cumheights[..., -1] = top 133 | heights = cumheights[..., 1:] - cumheights[..., :-1] 134 | 135 | if inverse: 136 | bin_idx = searchsorted(cumheights, inputs)[..., None] 137 | else: 138 | bin_idx = searchsorted(cumwidths, inputs)[..., None] 139 | 140 | input_cumwidths = cumwidths.gather(-1, bin_idx)[..., 0] 141 | input_bin_widths = widths.gather(-1, bin_idx)[..., 0] 142 | 143 | input_cumheights = cumheights.gather(-1, bin_idx)[..., 0] 144 | delta = heights / widths 145 | input_delta = delta.gather(-1, bin_idx)[..., 0] 146 | 147 | input_derivatives = derivatives.gather(-1, bin_idx)[..., 0] 148 | input_derivatives_plus_one = derivatives[..., 1:].gather(-1, bin_idx)[..., 0] 149 | 150 | input_heights = heights.gather(-1, bin_idx)[..., 0] 151 | 152 | if inverse: 153 | a = (((inputs - input_cumheights) * (input_derivatives 154 | + input_derivatives_plus_one 155 | - 2 * input_delta) 156 | + input_heights * (input_delta - input_derivatives))) 157 | b = (input_heights * input_derivatives 158 | - (inputs - input_cumheights) * (input_derivatives 159 | + input_derivatives_plus_one 160 | - 2 * input_delta)) 161 | c = - input_delta * (inputs - input_cumheights) 162 | 163 | discriminant = b.pow(2) - 4 * a * c 164 | assert (discriminant >= 0).all() 165 | 166 | root = (2 * c) / (-b - torch.sqrt(discriminant)) 167 | outputs = root * input_bin_widths + input_cumwidths 168 | 169 | theta_one_minus_theta = root * (1 - root) 170 | denominator = input_delta + ((input_derivatives + input_derivatives_plus_one - 2 * input_delta) 171 | * theta_one_minus_theta) 172 | derivative_numerator = input_delta.pow(2) * (input_derivatives_plus_one * root.pow(2) 173 | + 2 * input_delta * theta_one_minus_theta 174 | + input_derivatives * (1 - root).pow(2)) 175 | logabsdet = torch.log(derivative_numerator) - 2 * torch.log(denominator) 176 | 177 | return outputs, -logabsdet 178 | else: 179 | theta = (inputs - input_cumwidths) / input_bin_widths 180 | theta_one_minus_theta = theta * (1 - theta) 181 | 182 | numerator = input_heights * (input_delta * theta.pow(2) 183 | + input_derivatives * theta_one_minus_theta) 184 | denominator = input_delta + ((input_derivatives + input_derivatives_plus_one - 2 * input_delta) 185 | * theta_one_minus_theta) 186 | outputs = input_cumheights + numerator / denominator 187 | 188 | derivative_numerator = input_delta.pow(2) * (input_derivatives_plus_one * theta.pow(2) 189 | + 2 * input_delta * theta_one_minus_theta 190 | + input_derivatives * (1 - theta).pow(2)) 191 | logabsdet = torch.log(derivative_numerator) - 2 * torch.log(denominator) 192 | 193 | return outputs, logabsdet 194 | -------------------------------------------------------------------------------- /server.py: -------------------------------------------------------------------------------- 1 | from scipy.io.wavfile import write 2 | from text import text_to_sequence 3 | from models import SynthesizerTrn 4 | import utils 5 | import commons 6 | import sys 7 | import re 8 | from pydub import AudioSegment 9 | import torch 10 | from torch import no_grad, LongTensor 11 | import logging 12 | import argparse 13 | import requests 14 | import json 15 | import os 16 | import openai 17 | import socket 18 | from navertts import NaverTTS 19 | import datetime 20 | import glob 21 | 22 | class SocketServer: 23 | def __init__(self, host, port): 24 | self.host = host 25 | self.port = port 26 | self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 27 | 28 | def start(self): 29 | self.socket.bind((self.host, self.port)) 30 | self.socket.listen(5) 31 | self.client, self.addr = self.socket.accept() 32 | 33 | def receive(self): 34 | total_data = b"" 35 | while True: 36 | data = self.client.recv(1024) 37 | total_data += data 38 | if len(data) < 1024: 39 | break 40 | return total_data.decode() 41 | 42 | def send(self, data): 43 | self.client.send(data.encode()) 44 | 45 | def stop(self): 46 | self.socket.close() 47 | 48 | class vits(): 49 | def __init__(self, model, config): 50 | logging.getLogger('numba').setLevel(logging.WARNING) 51 | self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu") 52 | 53 | hps_ms = utils.get_hparams_from_file(config) 54 | n_speakers = hps_ms.data.n_speakers if 'n_speakers' in hps_ms.data.keys() else 0 55 | self.n_symbols = len(hps_ms.symbols) if 'symbols' in hps_ms.keys() else 0 56 | 57 | self.net_g_ms = SynthesizerTrn( 58 | self.n_symbols, 59 | hps_ms.data.filter_length // 2 + 1, 60 | hps_ms.train.segment_size // hps_ms.data.hop_length, 61 | n_speakers=n_speakers, 62 | **hps_ms.model).to(self.device) 63 | _ = self.net_g_ms.eval() 64 | self.hps_ms = hps_ms 65 | utils.load_checkpoint(model, self.net_g_ms) 66 | 67 | def get_text(self, text, hps, cleaned=False): 68 | if cleaned: 69 | text_norm = text_to_sequence(text, hps.symbols, []) 70 | else: 71 | text_norm = text_to_sequence(text, hps.symbols, hps.data.text_cleaners) 72 | if hps.data.add_blank: 73 | text_norm = commons.intersperse(text_norm, 0) 74 | text_norm = LongTensor(text_norm) 75 | return text_norm 76 | 77 | def get_label_value(self, text, label, default, warning_name='value'): 78 | value = re.search(rf'\[{label}=(.+?)\]', text) 79 | if value: 80 | try: 81 | text = re.sub(rf'\[{label}=(.+?)\]', '', text, 1) 82 | value = float(value.group(1)) 83 | except: 84 | print(f'Invalid {warning_name}!') 85 | sys.exit(1) 86 | else: 87 | value = default 88 | return value, text 89 | 90 | 91 | def get_label(self, text, label): 92 | if f'[{label}]' in text: 93 | return True, text.replace(f'[{label}]', '') 94 | else: 95 | return False, text 96 | 97 | def generateSound(self, inputString, id): 98 | if self.n_symbols != 0: 99 | text = inputString 100 | 101 | length_scale, text = self.get_label_value( 102 | text, 'LENGTH', 1, 'length scale') 103 | noise_scale, text = self.get_label_value( 104 | text, 'NOISE', 0.667, 'noise scale') 105 | noise_scale_w, text = self.get_label_value( 106 | text, 'NOISEW', 0.8, 'deviation of noise') 107 | cleaned, text = self.get_label(text, 'CLEANED') 108 | 109 | stn_tst = self.get_text(text, self.hps_ms, cleaned=cleaned) 110 | 111 | speaker_id = id 112 | out_path = "./output.wav" 113 | with no_grad(): 114 | x_tst = stn_tst.unsqueeze(0).to(self.device) 115 | x_tst_lengths = LongTensor([stn_tst.size(0)]).to(self.device) 116 | sid = LongTensor([speaker_id]).to(self.device) 117 | audio = self.net_g_ms.infer(x_tst, x_tst_lengths, sid=sid, noise_scale=noise_scale, 118 | noise_scale_w=noise_scale_w, length_scale=length_scale)[0][0, 0].data.to(self.device).cpu().float().numpy() 119 | 120 | write(out_path, self.hps_ms.data.sampling_rate, audio) 121 | print('Successfully saved!') 122 | # torch.cuda.empty_cache() 123 | return out_path 124 | 125 | get_dir = lambda x: os.path.split(os.path.realpath(x))[0] 126 | 127 | def download_file(url, save_dir): 128 | local_filename = url.split('/')[-1] 129 | r = requests.get(url, stream=True) 130 | with open(os.path.join(save_dir, local_filename), 'wb') as f: 131 | for chunk in r.iter_content(chunk_size=1024): 132 | if chunk: # filter out keep-alive new chunks 133 | f.write(chunk) 134 | return local_filename 135 | 136 | class openai_session(): 137 | def __init__(self, api_key): 138 | self.api_key = api_key 139 | openai.api_key = api_key 140 | self.messages = [] 141 | self.model = "gpt-3.5-turbo" 142 | self.currunt_log = f"userfile/log/{datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.json" 143 | if not os.path.exists("userfile/log"): 144 | os.makedirs("userfile/log") 145 | 146 | def save(self): 147 | with open(self.currunt_log, 'w', encoding='utf-8') as f: 148 | data = json.dumps(self.messages, ensure_ascii=False, indent=4) 149 | f.write(data) 150 | 151 | def set_role(self, role): 152 | prefix = "이제부터 당신은 다음과 같은 역할을 맡아 대화를 진행합니다: \n" 153 | self.messages.append({"role": "system", "content": prefix + role}) 154 | 155 | def set_greeting(self, greeting): 156 | self.messages.append({"role": "assistant", "content": greeting}) 157 | 158 | def send_message(self, message): 159 | try: 160 | self.messages.append({"role": "user", "content": message}) 161 | res = openai.ChatCompletion.create( 162 | model=self.model, 163 | messages=self.messages if len(self.messages) <= 30 else [self.messages[0]] + self.messages[-9:], 164 | ) 165 | answer = res['choices'][0]['message']['content'] 166 | self.messages.append({"role": "assistant", "content": answer}) 167 | self.save() 168 | except Exception as e: 169 | answer = "앗.. 뭐라고 하셨었죠? 다시 한번 말씀해 주실 수 있나요?" 170 | print("에러 발생: " + str(e)) 171 | 172 | return answer 173 | 174 | class navertts(): 175 | def generateSound(self, inputString, id): 176 | output_path = "./output.mp3" 177 | tts = NaverTTS(inputString, lang='ko') 178 | tts.save(output_path) 179 | print('Successfully saved!') 180 | return output_path 181 | 182 | def main(): 183 | server = SocketServer("127.0.0.1", 9000) 184 | print("렌파이 클라이언트와 연결 대기중...") 185 | server.start() 186 | 187 | print("렌파이 클라이언트와 연결되었습니다.") 188 | 189 | tts_service = int(server.receive()) # 0: 로컬 vits, 1: 네이버 190 | 191 | if tts_service == 0: 192 | korean_model_path = r"userfile\tts\model.pth" 193 | korean_config_path = r"userfile\tts\config.json" 194 | 195 | if not os.path.isfile(korean_model_path): 196 | os.makedirs(get_dir(korean_model_path), exist_ok=True) 197 | print("TTS 모델 체크포인트 파일이 없습니다.해당 파일을 다운로드 받습니다.") 198 | url = 'https://huggingface.co/spaces/skytnt/moe-tts/resolve/main/saved_model/6/model.pth' 199 | download_file(url, get_dir(korean_model_path)) 200 | print("TTS 모델 체크포인트 파일 다운로드 완료") 201 | 202 | if not os.path.isfile(korean_config_path): 203 | os.makedirs(get_dir(korean_config_path), exist_ok=True) 204 | print("TTS 모델 설정 파일이 없습니다.해당 파일을 다운로드 받습니다.") 205 | url = 'https://huggingface.co/spaces/skytnt/moe-tts/resolve/main/saved_model/6/config.json' 206 | download_file(url, get_dir(korean_config_path)) 207 | print("TTS 모델 설정 파일 다운로드 완료") 208 | 209 | tts = vits(korean_model_path, korean_config_path) 210 | config = json.load(open(korean_config_path, 'r')) 211 | spk_list = config['speakers'] 212 | speaker = int(server.receive()) 213 | print("선택된 음성: " + spk_list[speaker]) 214 | 215 | elif tts_service == 1: 216 | tts = navertts() 217 | speaker = 0 218 | 219 | print("렌파이에서 API KEY를 입력해주세요.") 220 | print("API KEY는 https://platform.openai.com/account/api-keys 에서 발급할 수 있습니다.") 221 | 222 | session_token = server.receive() 223 | 224 | if(session_token): 225 | print(f"API KEY: ...{session_token[-8:]}") 226 | oai = openai_session(session_token) 227 | 228 | setting = server.receive() 229 | oai.set_role(setting) 230 | print("배경 설정: "+ setting) 231 | 232 | greeting = server.receive() 233 | oai.set_greeting(greeting) 234 | print("인사말: "+ greeting) 235 | 236 | while True: 237 | question = server.receive() 238 | print("Question Received: " + question) 239 | 240 | answer = oai.send_message(question) 241 | print("ChatGPT:", answer) 242 | 243 | tts_audio_path = tts.generateSound(answer, speaker) 244 | 245 | # convert wav to ogg 246 | src = tts_audio_path 247 | dst = "./ChatWithGPT/game/audio/test.ogg" 248 | sound = getattr(AudioSegment, f'from_{src.split(".")[-1]}')(src) 249 | sound.export(dst, format="ogg") 250 | 251 | # send response to UI 252 | server.send(answer) 253 | 254 | # finish playing audio 255 | print(server.receive()) 256 | 257 | if __name__ == "__main__": 258 | try: 259 | main() 260 | except KeyboardInterrupt: 261 | print("종료합니다.") 262 | sys.exit(0) 263 | except ConnectionResetError: 264 | print("클라이언트와의 연결이 끊겼습니다.") 265 | sys.exit(0) -------------------------------------------------------------------------------- /ChatWithGPT/game/Resources/Hiyori/Hiyori.cdi3.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 3, 3 | "Parameters": [ 4 | { 5 | "Id": "ParamAngleX", 6 | "GroupId": "ParamGroupFace", 7 | "Name": "角度 X" 8 | }, 9 | { 10 | "Id": "ParamAngleY", 11 | "GroupId": "ParamGroupFace", 12 | "Name": "角度 Y" 13 | }, 14 | { 15 | "Id": "ParamAngleZ", 16 | "GroupId": "ParamGroupFace", 17 | "Name": "角度 Z" 18 | }, 19 | { 20 | "Id": "ParamCheek", 21 | "GroupId": "ParamGroupFace", 22 | "Name": "照れ" 23 | }, 24 | { 25 | "Id": "ParamEyeLOpen", 26 | "GroupId": "ParamGroupEyes", 27 | "Name": "左目 開閉" 28 | }, 29 | { 30 | "Id": "ParamEyeLSmile", 31 | "GroupId": "ParamGroupEyes", 32 | "Name": "左目 笑顔" 33 | }, 34 | { 35 | "Id": "ParamEyeROpen", 36 | "GroupId": "ParamGroupEyes", 37 | "Name": "右目 開閉" 38 | }, 39 | { 40 | "Id": "ParamEyeRSmile", 41 | "GroupId": "ParamGroupEyes", 42 | "Name": "右目 笑顔" 43 | }, 44 | { 45 | "Id": "ParamEyeBallX", 46 | "GroupId": "ParamGroupEyeballs", 47 | "Name": "目玉 X" 48 | }, 49 | { 50 | "Id": "ParamEyeBallY", 51 | "GroupId": "ParamGroupEyeballs", 52 | "Name": "目玉 Y" 53 | }, 54 | { 55 | "Id": "ParamBrowLY", 56 | "GroupId": "ParamGroupBrows", 57 | "Name": "左眉 上下" 58 | }, 59 | { 60 | "Id": "ParamBrowRY", 61 | "GroupId": "ParamGroupBrows", 62 | "Name": "右眉 上下" 63 | }, 64 | { 65 | "Id": "ParamBrowLX", 66 | "GroupId": "ParamGroupBrows", 67 | "Name": "左眉 左右" 68 | }, 69 | { 70 | "Id": "ParamBrowRX", 71 | "GroupId": "ParamGroupBrows", 72 | "Name": "右眉 左右" 73 | }, 74 | { 75 | "Id": "ParamBrowLAngle", 76 | "GroupId": "ParamGroupBrows", 77 | "Name": "左眉 角度" 78 | }, 79 | { 80 | "Id": "ParamBrowRAngle", 81 | "GroupId": "ParamGroupBrows", 82 | "Name": "右眉 角度" 83 | }, 84 | { 85 | "Id": "ParamBrowLForm", 86 | "GroupId": "ParamGroupBrows", 87 | "Name": "左眉 変形" 88 | }, 89 | { 90 | "Id": "ParamBrowRForm", 91 | "GroupId": "ParamGroupBrows", 92 | "Name": "右眉 変形" 93 | }, 94 | { 95 | "Id": "ParamMouthForm", 96 | "GroupId": "ParamGroupMouth", 97 | "Name": "口 変形" 98 | }, 99 | { 100 | "Id": "ParamMouthOpenY", 101 | "GroupId": "ParamGroupMouth", 102 | "Name": "口 開閉" 103 | }, 104 | { 105 | "Id": "ParamBodyAngleX", 106 | "GroupId": "ParamGroupBody", 107 | "Name": "体の回転 X" 108 | }, 109 | { 110 | "Id": "ParamBodyAngleY", 111 | "GroupId": "ParamGroupBody", 112 | "Name": "体の回転 Y" 113 | }, 114 | { 115 | "Id": "ParamBodyAngleZ", 116 | "GroupId": "ParamGroupBody", 117 | "Name": "体の回転 Z" 118 | }, 119 | { 120 | "Id": "ParamBreath", 121 | "GroupId": "ParamGroupBody", 122 | "Name": "呼吸" 123 | }, 124 | { 125 | "Id": "ParamShoulder", 126 | "GroupId": "ParamGroupBody", 127 | "Name": "肩 すくみ" 128 | }, 129 | { 130 | "Id": "ParamLeg", 131 | "GroupId": "ParamGroupBody", 132 | "Name": "あし" 133 | }, 134 | { 135 | "Id": "ParamArmLA", 136 | "GroupId": "ParamGroupArms", 137 | "Name": "左腕 A" 138 | }, 139 | { 140 | "Id": "ParamArmRA", 141 | "GroupId": "ParamGroupArms", 142 | "Name": "右腕 A" 143 | }, 144 | { 145 | "Id": "ParamArmLB", 146 | "GroupId": "ParamGroupArms", 147 | "Name": "左腕 B" 148 | }, 149 | { 150 | "Id": "ParamArmRB", 151 | "GroupId": "ParamGroupArms", 152 | "Name": "右腕 B" 153 | }, 154 | { 155 | "Id": "ParamHandLB", 156 | "GroupId": "ParamGroupArms", 157 | "Name": "左手B 回転" 158 | }, 159 | { 160 | "Id": "ParamHandRB", 161 | "GroupId": "ParamGroupArms", 162 | "Name": "右手B 回転" 163 | }, 164 | { 165 | "Id": "ParamHandL", 166 | "GroupId": "ParamGroupArms", 167 | "Name": "左手" 168 | }, 169 | { 170 | "Id": "ParamHandR", 171 | "GroupId": "ParamGroupArms", 172 | "Name": "右手" 173 | }, 174 | { 175 | "Id": "ParamBustY", 176 | "GroupId": "ParamGroupSway", 177 | "Name": "胸 揺れ" 178 | }, 179 | { 180 | "Id": "ParamHairAhoge", 181 | "GroupId": "ParamGroupSway", 182 | "Name": "髪揺れ アホ毛" 183 | }, 184 | { 185 | "Id": "ParamHairFront", 186 | "GroupId": "ParamGroupSway", 187 | "Name": "髪揺れ 前" 188 | }, 189 | { 190 | "Id": "ParamHairBack", 191 | "GroupId": "ParamGroupSway", 192 | "Name": "髪揺れ 後" 193 | }, 194 | { 195 | "Id": "ParamSideupRibbon", 196 | "GroupId": "ParamGroupSway", 197 | "Name": "髪飾りの揺れ" 198 | }, 199 | { 200 | "Id": "ParamRibbon", 201 | "GroupId": "ParamGroupSway", 202 | "Name": "胸リボンの揺れ" 203 | }, 204 | { 205 | "Id": "ParamSkirt", 206 | "GroupId": "ParamGroupSway", 207 | "Name": "スカートの揺れ" 208 | }, 209 | { 210 | "Id": "ParamSkirt2", 211 | "GroupId": "ParamGroupSway", 212 | "Name": "スカートめくれ" 213 | }, 214 | { 215 | "Id": "Param_Angle_Rotation_1_ArtMesh62", 216 | "GroupId": "ParamGroup2", 217 | "Name": "[0]サイドアップ左" 218 | }, 219 | { 220 | "Id": "Param_Angle_Rotation_2_ArtMesh62", 221 | "GroupId": "ParamGroup2", 222 | "Name": "[1]サイドアップ左" 223 | }, 224 | { 225 | "Id": "Param_Angle_Rotation_3_ArtMesh62", 226 | "GroupId": "ParamGroup2", 227 | "Name": "[2]サイドアップ左" 228 | }, 229 | { 230 | "Id": "Param_Angle_Rotation_4_ArtMesh62", 231 | "GroupId": "ParamGroup2", 232 | "Name": "[3]サイドアップ左" 233 | }, 234 | { 235 | "Id": "Param_Angle_Rotation_5_ArtMesh62", 236 | "GroupId": "ParamGroup2", 237 | "Name": "[4]サイドアップ左" 238 | }, 239 | { 240 | "Id": "Param_Angle_Rotation_6_ArtMesh62", 241 | "GroupId": "ParamGroup2", 242 | "Name": "[5]サイドアップ左" 243 | }, 244 | { 245 | "Id": "Param_Angle_Rotation_7_ArtMesh62", 246 | "GroupId": "ParamGroup2", 247 | "Name": "[6]サイドアップ左" 248 | }, 249 | { 250 | "Id": "Param_Angle_Rotation_1_ArtMesh61", 251 | "GroupId": "ParamGroup", 252 | "Name": "[0]サイドアップ右" 253 | }, 254 | { 255 | "Id": "Param_Angle_Rotation_2_ArtMesh61", 256 | "GroupId": "ParamGroup", 257 | "Name": "[1]サイドアップ右" 258 | }, 259 | { 260 | "Id": "Param_Angle_Rotation_3_ArtMesh61", 261 | "GroupId": "ParamGroup", 262 | "Name": "[2]サイドアップ右" 263 | }, 264 | { 265 | "Id": "Param_Angle_Rotation_4_ArtMesh61", 266 | "GroupId": "ParamGroup", 267 | "Name": "[3]サイドアップ右" 268 | }, 269 | { 270 | "Id": "Param_Angle_Rotation_5_ArtMesh61", 271 | "GroupId": "ParamGroup", 272 | "Name": "[4]サイドアップ右" 273 | }, 274 | { 275 | "Id": "Param_Angle_Rotation_6_ArtMesh61", 276 | "GroupId": "ParamGroup", 277 | "Name": "[5]サイドアップ右" 278 | }, 279 | { 280 | "Id": "Param_Angle_Rotation_7_ArtMesh61", 281 | "GroupId": "ParamGroup", 282 | "Name": "[6]サイドアップ右" 283 | }, 284 | { 285 | "Id": "Param_Angle_Rotation_1_ArtMesh55", 286 | "GroupId": "ParamGroup4", 287 | "Name": "[0]前髪左" 288 | }, 289 | { 290 | "Id": "Param_Angle_Rotation_2_ArtMesh55", 291 | "GroupId": "ParamGroup4", 292 | "Name": "[1]前髪左" 293 | }, 294 | { 295 | "Id": "Param_Angle_Rotation_3_ArtMesh55", 296 | "GroupId": "ParamGroup4", 297 | "Name": "[2]前髪左" 298 | }, 299 | { 300 | "Id": "Param_Angle_Rotation_4_ArtMesh55", 301 | "GroupId": "ParamGroup4", 302 | "Name": "[3]前髪左" 303 | }, 304 | { 305 | "Id": "Param_Angle_Rotation_5_ArtMesh55", 306 | "GroupId": "ParamGroup4", 307 | "Name": "[4]前髪左" 308 | }, 309 | { 310 | "Id": "Param_Angle_Rotation_6_ArtMesh55", 311 | "GroupId": "ParamGroup4", 312 | "Name": "[5]前髪左" 313 | }, 314 | { 315 | "Id": "Param_Angle_Rotation_7_ArtMesh55", 316 | "GroupId": "ParamGroup4", 317 | "Name": "[6]前髪左" 318 | }, 319 | { 320 | "Id": "Param_Angle_Rotation_1_ArtMesh54", 321 | "GroupId": "ParamGroup3", 322 | "Name": "[0]前髪右" 323 | }, 324 | { 325 | "Id": "Param_Angle_Rotation_2_ArtMesh54", 326 | "GroupId": "ParamGroup3", 327 | "Name": "[1]前髪右" 328 | }, 329 | { 330 | "Id": "Param_Angle_Rotation_3_ArtMesh54", 331 | "GroupId": "ParamGroup3", 332 | "Name": "[2]前髪右" 333 | }, 334 | { 335 | "Id": "Param_Angle_Rotation_4_ArtMesh54", 336 | "GroupId": "ParamGroup3", 337 | "Name": "[3]前髪右" 338 | }, 339 | { 340 | "Id": "Param_Angle_Rotation_5_ArtMesh54", 341 | "GroupId": "ParamGroup3", 342 | "Name": "[4]前髪右" 343 | }, 344 | { 345 | "Id": "Param_Angle_Rotation_6_ArtMesh54", 346 | "GroupId": "ParamGroup3", 347 | "Name": "[5]前髪右" 348 | }, 349 | { 350 | "Id": "Param_Angle_Rotation_7_ArtMesh54", 351 | "GroupId": "ParamGroup3", 352 | "Name": "[6]前髪右" 353 | } 354 | ], 355 | "ParameterGroups": [ 356 | { 357 | "Id": "ParamGroupFace", 358 | "GroupId": "", 359 | "Name": "顔" 360 | }, 361 | { 362 | "Id": "ParamGroupEyes", 363 | "GroupId": "", 364 | "Name": "目" 365 | }, 366 | { 367 | "Id": "ParamGroupEyeballs", 368 | "GroupId": "", 369 | "Name": "目玉" 370 | }, 371 | { 372 | "Id": "ParamGroupBrows", 373 | "GroupId": "", 374 | "Name": "眉" 375 | }, 376 | { 377 | "Id": "ParamGroupMouth", 378 | "GroupId": "", 379 | "Name": "口" 380 | }, 381 | { 382 | "Id": "ParamGroupBody", 383 | "GroupId": "", 384 | "Name": "体" 385 | }, 386 | { 387 | "Id": "ParamGroupArms", 388 | "GroupId": "", 389 | "Name": "腕" 390 | }, 391 | { 392 | "Id": "ParamGroupSway", 393 | "GroupId": "", 394 | "Name": "揺れ" 395 | }, 396 | { 397 | "Id": "ParamGroup2", 398 | "GroupId": "", 399 | "Name": "揺れ サイドアップ左" 400 | }, 401 | { 402 | "Id": "ParamGroup", 403 | "GroupId": "", 404 | "Name": "揺れ サイドアップ右" 405 | }, 406 | { 407 | "Id": "ParamGroup4", 408 | "GroupId": "", 409 | "Name": "揺れ 前髪左" 410 | }, 411 | { 412 | "Id": "ParamGroup3", 413 | "GroupId": "", 414 | "Name": "揺れ 前髪右" 415 | } 416 | ], 417 | "Parts": [ 418 | { 419 | "Id": "PartCore", 420 | "Name": "コア" 421 | }, 422 | { 423 | "Id": "PartCheek", 424 | "Name": "頬" 425 | }, 426 | { 427 | "Id": "PartBrow", 428 | "Name": "まゆ毛" 429 | }, 430 | { 431 | "Id": "PartEye", 432 | "Name": "目" 433 | }, 434 | { 435 | "Id": "PartNose", 436 | "Name": "鼻" 437 | }, 438 | { 439 | "Id": "PartMouth", 440 | "Name": "口" 441 | }, 442 | { 443 | "Id": "PartFace", 444 | "Name": "顔" 445 | }, 446 | { 447 | "Id": "PartEar", 448 | "Name": "耳" 449 | }, 450 | { 451 | "Id": "PartHairSide", 452 | "Name": "横髪" 453 | }, 454 | { 455 | "Id": "PartHairFront", 456 | "Name": "前髪" 457 | }, 458 | { 459 | "Id": "PartHairBack", 460 | "Name": "後ろ髪" 461 | }, 462 | { 463 | "Id": "PartNeck", 464 | "Name": "首" 465 | }, 466 | { 467 | "Id": "PartArmA", 468 | "Name": "腕 A" 469 | }, 470 | { 471 | "Id": "PartArmB", 472 | "Name": "腕 B" 473 | }, 474 | { 475 | "Id": "PartBody", 476 | "Name": "体" 477 | }, 478 | { 479 | "Id": "PartBackground", 480 | "Name": "背景" 481 | }, 482 | { 483 | "Id": "PartSketch", 484 | "Name": "[ 下絵 ]" 485 | }, 486 | { 487 | "Id": "PartEyeBall", 488 | "Name": "目玉" 489 | }, 490 | { 491 | "Id": "ArtMesh55_Skinning", 492 | "Name": "前髪左(スキニング)" 493 | }, 494 | { 495 | "Id": "Part4", 496 | "Name": "前髪左(回転)" 497 | }, 498 | { 499 | "Id": "ArtMesh54_Skinning", 500 | "Name": "前髪右(スキニング)" 501 | }, 502 | { 503 | "Id": "Part3", 504 | "Name": "前髪右(回転)" 505 | }, 506 | { 507 | "Id": "ArtMesh61_Skinning", 508 | "Name": "サイドアップ右(スキニング)" 509 | }, 510 | { 511 | "Id": "Part", 512 | "Name": "サイドアップ右(回転)" 513 | }, 514 | { 515 | "Id": "ArtMesh62_Skinning", 516 | "Name": "サイドアップ左(スキニング)" 517 | }, 518 | { 519 | "Id": "Part2", 520 | "Name": "サイドアップ左(回転)" 521 | } 522 | ] 523 | } -------------------------------------------------------------------------------- /attentions.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | from torch import nn 4 | from torch.nn import functional as F 5 | 6 | import commons 7 | from modules import LayerNorm 8 | 9 | 10 | class Encoder(nn.Module): 11 | def __init__(self, hidden_channels, filter_channels, n_heads, n_layers, kernel_size=1, p_dropout=0., window_size=4, **kwargs): 12 | super().__init__() 13 | self.hidden_channels = hidden_channels 14 | self.filter_channels = filter_channels 15 | self.n_heads = n_heads 16 | self.n_layers = n_layers 17 | self.kernel_size = kernel_size 18 | self.p_dropout = p_dropout 19 | self.window_size = window_size 20 | 21 | self.drop = nn.Dropout(p_dropout) 22 | self.attn_layers = nn.ModuleList() 23 | self.norm_layers_1 = nn.ModuleList() 24 | self.ffn_layers = nn.ModuleList() 25 | self.norm_layers_2 = nn.ModuleList() 26 | for i in range(self.n_layers): 27 | self.attn_layers.append(MultiHeadAttention(hidden_channels, hidden_channels, n_heads, p_dropout=p_dropout, window_size=window_size)) 28 | self.norm_layers_1.append(LayerNorm(hidden_channels)) 29 | self.ffn_layers.append(FFN(hidden_channels, hidden_channels, filter_channels, kernel_size, p_dropout=p_dropout)) 30 | self.norm_layers_2.append(LayerNorm(hidden_channels)) 31 | 32 | def forward(self, x, x_mask): 33 | attn_mask = x_mask.unsqueeze(2) * x_mask.unsqueeze(-1) 34 | x = x * x_mask 35 | for i in range(self.n_layers): 36 | y = self.attn_layers[i](x, x, attn_mask) 37 | y = self.drop(y) 38 | x = self.norm_layers_1[i](x + y) 39 | 40 | y = self.ffn_layers[i](x, x_mask) 41 | y = self.drop(y) 42 | x = self.norm_layers_2[i](x + y) 43 | x = x * x_mask 44 | return x 45 | 46 | 47 | class Decoder(nn.Module): 48 | def __init__(self, hidden_channels, filter_channels, n_heads, n_layers, kernel_size=1, p_dropout=0., proximal_bias=False, proximal_init=True, **kwargs): 49 | super().__init__() 50 | self.hidden_channels = hidden_channels 51 | self.filter_channels = filter_channels 52 | self.n_heads = n_heads 53 | self.n_layers = n_layers 54 | self.kernel_size = kernel_size 55 | self.p_dropout = p_dropout 56 | self.proximal_bias = proximal_bias 57 | self.proximal_init = proximal_init 58 | 59 | self.drop = nn.Dropout(p_dropout) 60 | self.self_attn_layers = nn.ModuleList() 61 | self.norm_layers_0 = nn.ModuleList() 62 | self.encdec_attn_layers = nn.ModuleList() 63 | self.norm_layers_1 = nn.ModuleList() 64 | self.ffn_layers = nn.ModuleList() 65 | self.norm_layers_2 = nn.ModuleList() 66 | for i in range(self.n_layers): 67 | self.self_attn_layers.append(MultiHeadAttention(hidden_channels, hidden_channels, n_heads, p_dropout=p_dropout, proximal_bias=proximal_bias, proximal_init=proximal_init)) 68 | self.norm_layers_0.append(LayerNorm(hidden_channels)) 69 | self.encdec_attn_layers.append(MultiHeadAttention(hidden_channels, hidden_channels, n_heads, p_dropout=p_dropout)) 70 | self.norm_layers_1.append(LayerNorm(hidden_channels)) 71 | self.ffn_layers.append(FFN(hidden_channels, hidden_channels, filter_channels, kernel_size, p_dropout=p_dropout, causal=True)) 72 | self.norm_layers_2.append(LayerNorm(hidden_channels)) 73 | 74 | def forward(self, x, x_mask, h, h_mask): 75 | """ 76 | x: decoder input 77 | h: encoder output 78 | """ 79 | self_attn_mask = commons.subsequent_mask(x_mask.size(2)).to(device=x.device, dtype=x.dtype) 80 | encdec_attn_mask = h_mask.unsqueeze(2) * x_mask.unsqueeze(-1) 81 | x = x * x_mask 82 | for i in range(self.n_layers): 83 | y = self.self_attn_layers[i](x, x, self_attn_mask) 84 | y = self.drop(y) 85 | x = self.norm_layers_0[i](x + y) 86 | 87 | y = self.encdec_attn_layers[i](x, h, encdec_attn_mask) 88 | y = self.drop(y) 89 | x = self.norm_layers_1[i](x + y) 90 | 91 | y = self.ffn_layers[i](x, x_mask) 92 | y = self.drop(y) 93 | x = self.norm_layers_2[i](x + y) 94 | x = x * x_mask 95 | return x 96 | 97 | 98 | class MultiHeadAttention(nn.Module): 99 | def __init__(self, channels, out_channels, n_heads, p_dropout=0., window_size=None, heads_share=True, block_length=None, proximal_bias=False, proximal_init=False): 100 | super().__init__() 101 | assert channels % n_heads == 0 102 | 103 | self.channels = channels 104 | self.out_channels = out_channels 105 | self.n_heads = n_heads 106 | self.p_dropout = p_dropout 107 | self.window_size = window_size 108 | self.heads_share = heads_share 109 | self.block_length = block_length 110 | self.proximal_bias = proximal_bias 111 | self.proximal_init = proximal_init 112 | self.attn = None 113 | 114 | self.k_channels = channels // n_heads 115 | self.conv_q = nn.Conv1d(channels, channels, 1) 116 | self.conv_k = nn.Conv1d(channels, channels, 1) 117 | self.conv_v = nn.Conv1d(channels, channels, 1) 118 | self.conv_o = nn.Conv1d(channels, out_channels, 1) 119 | self.drop = nn.Dropout(p_dropout) 120 | 121 | if window_size is not None: 122 | n_heads_rel = 1 if heads_share else n_heads 123 | rel_stddev = self.k_channels**-0.5 124 | self.emb_rel_k = nn.Parameter(torch.randn(n_heads_rel, window_size * 2 + 1, self.k_channels) * rel_stddev) 125 | self.emb_rel_v = nn.Parameter(torch.randn(n_heads_rel, window_size * 2 + 1, self.k_channels) * rel_stddev) 126 | 127 | nn.init.xavier_uniform_(self.conv_q.weight) 128 | nn.init.xavier_uniform_(self.conv_k.weight) 129 | nn.init.xavier_uniform_(self.conv_v.weight) 130 | if proximal_init: 131 | with torch.no_grad(): 132 | self.conv_k.weight.copy_(self.conv_q.weight) 133 | self.conv_k.bias.copy_(self.conv_q.bias) 134 | 135 | def forward(self, x, c, attn_mask=None): 136 | q = self.conv_q(x) 137 | k = self.conv_k(c) 138 | v = self.conv_v(c) 139 | 140 | x, self.attn = self.attention(q, k, v, mask=attn_mask) 141 | 142 | x = self.conv_o(x) 143 | return x 144 | 145 | def attention(self, query, key, value, mask=None): 146 | # reshape [b, d, t] -> [b, n_h, t, d_k] 147 | b, d, t_s, t_t = (*key.size(), query.size(2)) 148 | query = query.view(b, self.n_heads, self.k_channels, t_t).transpose(2, 3) 149 | key = key.view(b, self.n_heads, self.k_channels, t_s).transpose(2, 3) 150 | value = value.view(b, self.n_heads, self.k_channels, t_s).transpose(2, 3) 151 | 152 | scores = torch.matmul(query / math.sqrt(self.k_channels), key.transpose(-2, -1)) 153 | if self.window_size is not None: 154 | assert t_s == t_t, "Relative attention is only available for self-attention." 155 | key_relative_embeddings = self._get_relative_embeddings(self.emb_rel_k, t_s) 156 | rel_logits = self._matmul_with_relative_keys(query /math.sqrt(self.k_channels), key_relative_embeddings) 157 | scores_local = self._relative_position_to_absolute_position(rel_logits) 158 | scores = scores + scores_local 159 | if self.proximal_bias: 160 | assert t_s == t_t, "Proximal bias is only available for self-attention." 161 | scores = scores + self._attention_bias_proximal(t_s).to(device=scores.device, dtype=scores.dtype) 162 | if mask is not None: 163 | scores = scores.masked_fill(mask == 0, -1e4) 164 | if self.block_length is not None: 165 | assert t_s == t_t, "Local attention is only available for self-attention." 166 | block_mask = torch.ones_like(scores).triu(-self.block_length).tril(self.block_length) 167 | scores = scores.masked_fill(block_mask == 0, -1e4) 168 | p_attn = F.softmax(scores, dim=-1) # [b, n_h, t_t, t_s] 169 | p_attn = self.drop(p_attn) 170 | output = torch.matmul(p_attn, value) 171 | if self.window_size is not None: 172 | relative_weights = self._absolute_position_to_relative_position(p_attn) 173 | value_relative_embeddings = self._get_relative_embeddings(self.emb_rel_v, t_s) 174 | output = output + self._matmul_with_relative_values(relative_weights, value_relative_embeddings) 175 | output = output.transpose(2, 3).contiguous().view(b, d, t_t) # [b, n_h, t_t, d_k] -> [b, d, t_t] 176 | return output, p_attn 177 | 178 | def _matmul_with_relative_values(self, x, y): 179 | """ 180 | x: [b, h, l, m] 181 | y: [h or 1, m, d] 182 | ret: [b, h, l, d] 183 | """ 184 | ret = torch.matmul(x, y.unsqueeze(0)) 185 | return ret 186 | 187 | def _matmul_with_relative_keys(self, x, y): 188 | """ 189 | x: [b, h, l, d] 190 | y: [h or 1, m, d] 191 | ret: [b, h, l, m] 192 | """ 193 | ret = torch.matmul(x, y.unsqueeze(0).transpose(-2, -1)) 194 | return ret 195 | 196 | def _get_relative_embeddings(self, relative_embeddings, length): 197 | max_relative_position = 2 * self.window_size + 1 198 | # Pad first before slice to avoid using cond ops. 199 | pad_length = max(length - (self.window_size + 1), 0) 200 | slice_start_position = max((self.window_size + 1) - length, 0) 201 | slice_end_position = slice_start_position + 2 * length - 1 202 | if pad_length > 0: 203 | padded_relative_embeddings = F.pad( 204 | relative_embeddings, 205 | commons.convert_pad_shape([[0, 0], [pad_length, pad_length], [0, 0]])) 206 | else: 207 | padded_relative_embeddings = relative_embeddings 208 | used_relative_embeddings = padded_relative_embeddings[:,slice_start_position:slice_end_position] 209 | return used_relative_embeddings 210 | 211 | def _relative_position_to_absolute_position(self, x): 212 | """ 213 | x: [b, h, l, 2*l-1] 214 | ret: [b, h, l, l] 215 | """ 216 | batch, heads, length, _ = x.size() 217 | # Concat columns of pad to shift from relative to absolute indexing. 218 | x = F.pad(x, commons.convert_pad_shape([[0,0],[0,0],[0,0],[0,1]])) 219 | 220 | # Concat extra elements so to add up to shape (len+1, 2*len-1). 221 | x_flat = x.view([batch, heads, length * 2 * length]) 222 | x_flat = F.pad(x_flat, commons.convert_pad_shape([[0,0],[0,0],[0,length-1]])) 223 | 224 | # Reshape and slice out the padded elements. 225 | x_final = x_flat.view([batch, heads, length+1, 2*length-1])[:, :, :length, length-1:] 226 | return x_final 227 | 228 | def _absolute_position_to_relative_position(self, x): 229 | """ 230 | x: [b, h, l, l] 231 | ret: [b, h, l, 2*l-1] 232 | """ 233 | batch, heads, length, _ = x.size() 234 | # padd along column 235 | x = F.pad(x, commons.convert_pad_shape([[0, 0], [0, 0], [0, 0], [0, length-1]])) 236 | x_flat = x.view([batch, heads, length**2 + length*(length -1)]) 237 | # add 0's in the beginning that will skew the elements after reshape 238 | x_flat = F.pad(x_flat, commons.convert_pad_shape([[0, 0], [0, 0], [length, 0]])) 239 | x_final = x_flat.view([batch, heads, length, 2*length])[:,:,:,1:] 240 | return x_final 241 | 242 | def _attention_bias_proximal(self, length): 243 | """Bias for self-attention to encourage attention to close positions. 244 | Args: 245 | length: an integer scalar. 246 | Returns: 247 | a Tensor with shape [1, 1, length, length] 248 | """ 249 | r = torch.arange(length, dtype=torch.float32) 250 | diff = torch.unsqueeze(r, 0) - torch.unsqueeze(r, 1) 251 | return torch.unsqueeze(torch.unsqueeze(-torch.log1p(torch.abs(diff)), 0), 0) 252 | 253 | 254 | class FFN(nn.Module): 255 | def __init__(self, in_channels, out_channels, filter_channels, kernel_size, p_dropout=0., activation=None, causal=False): 256 | super().__init__() 257 | self.in_channels = in_channels 258 | self.out_channels = out_channels 259 | self.filter_channels = filter_channels 260 | self.kernel_size = kernel_size 261 | self.p_dropout = p_dropout 262 | self.activation = activation 263 | self.causal = causal 264 | 265 | if causal: 266 | self.padding = self._causal_padding 267 | else: 268 | self.padding = self._same_padding 269 | 270 | self.conv_1 = nn.Conv1d(in_channels, filter_channels, kernel_size) 271 | self.conv_2 = nn.Conv1d(filter_channels, out_channels, kernel_size) 272 | self.drop = nn.Dropout(p_dropout) 273 | 274 | def forward(self, x, x_mask): 275 | x = self.conv_1(self.padding(x * x_mask)) 276 | if self.activation == "gelu": 277 | x = x * torch.sigmoid(1.702 * x) 278 | else: 279 | x = torch.relu(x) 280 | x = self.drop(x) 281 | x = self.conv_2(self.padding(x * x_mask)) 282 | return x * x_mask 283 | 284 | def _causal_padding(self, x): 285 | if self.kernel_size == 1: 286 | return x 287 | pad_l = self.kernel_size - 1 288 | pad_r = 0 289 | padding = [[0, 0], [0, 0], [pad_l, pad_r]] 290 | x = F.pad(x, commons.convert_pad_shape(padding)) 291 | return x 292 | 293 | def _same_padding(self, x): 294 | if self.kernel_size == 1: 295 | return x 296 | pad_l = (self.kernel_size - 1) // 2 297 | pad_r = self.kernel_size // 2 298 | padding = [[0, 0], [0, 0], [pad_l, pad_r]] 299 | x = F.pad(x, commons.convert_pad_shape(padding)) 300 | return x 301 | -------------------------------------------------------------------------------- /ChatWithGPT/game/Resources/Hiyori/motions/Hiyori_m04.motion3.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 3, 3 | "Meta": { 4 | "Duration": 4.43, 5 | "Fps": 30.0, 6 | "Loop": true, 7 | "AreBeziersRestricted": false, 8 | "CurveCount": 31, 9 | "TotalSegmentCount": 106, 10 | "TotalPointCount": 287, 11 | "UserDataCount": 0, 12 | "TotalUserDataSize": 0 13 | }, 14 | "Curves": [ 15 | { 16 | "Target": "Parameter", 17 | "Id": "ParamAngleX", 18 | "Segments": [ 19 | 0, 20 | 1, 21 | 1, 22 | 0.211, 23 | 1, 24 | 0.422, 25 | 0, 26 | 0.633, 27 | 0, 28 | 1, 29 | 0.911, 30 | 0, 31 | 1.189, 32 | 5, 33 | 1.467, 34 | 5, 35 | 1, 36 | 1.689, 37 | 5, 38 | 1.911, 39 | -16, 40 | 2.133, 41 | -16, 42 | 1, 43 | 2.356, 44 | -16, 45 | 2.578, 46 | 13.871, 47 | 2.8, 48 | 13.871, 49 | 1, 50 | 2.956, 51 | 13.871, 52 | 3.111, 53 | 0, 54 | 3.267, 55 | 0, 56 | 0, 57 | 4.433, 58 | 0 59 | ] 60 | }, 61 | { 62 | "Target": "Parameter", 63 | "Id": "ParamAngleY", 64 | "Segments": [ 65 | 0, 66 | 0, 67 | 1, 68 | 0.211, 69 | 0, 70 | 0.422, 71 | 0, 72 | 0.633, 73 | 0, 74 | 1, 75 | 0.911, 76 | 0, 77 | 1.189, 78 | -25, 79 | 1.467, 80 | -25, 81 | 1, 82 | 1.689, 83 | -25, 84 | 1.911, 85 | -15.225, 86 | 2.133, 87 | -11, 88 | 1, 89 | 2.356, 90 | -6.775, 91 | 2.578, 92 | -5.127, 93 | 2.8, 94 | -2.5, 95 | 1, 96 | 2.956, 97 | -0.661, 98 | 3.111, 99 | 0, 100 | 3.267, 101 | 0, 102 | 0, 103 | 4.433, 104 | 0 105 | ] 106 | }, 107 | { 108 | "Target": "Parameter", 109 | "Id": "ParamAngleZ", 110 | "Segments": [ 111 | 0, 112 | 0, 113 | 1, 114 | 0.222, 115 | 0, 116 | 0.444, 117 | 0, 118 | 0.667, 119 | 0, 120 | 1, 121 | 0.756, 122 | 0, 123 | 0.844, 124 | -4, 125 | 0.933, 126 | -4, 127 | 1, 128 | 1.122, 129 | -4, 130 | 1.311, 131 | 18, 132 | 1.5, 133 | 18, 134 | 1, 135 | 1.722, 136 | 18, 137 | 1.944, 138 | -14, 139 | 2.167, 140 | -14, 141 | 1, 142 | 2.567, 143 | -14, 144 | 2.967, 145 | -14, 146 | 3.367, 147 | -14, 148 | 1, 149 | 3.511, 150 | -14, 151 | 3.656, 152 | -12, 153 | 3.8, 154 | -12, 155 | 0, 156 | 4.433, 157 | -12 158 | ] 159 | }, 160 | { 161 | "Target": "Parameter", 162 | "Id": "ParamCheek", 163 | "Segments": [ 164 | 0, 165 | 1, 166 | 0, 167 | 4.433, 168 | 1 169 | ] 170 | }, 171 | { 172 | "Target": "Parameter", 173 | "Id": "ParamEyeLOpen", 174 | "Segments": [ 175 | 0, 176 | 1.2, 177 | 1, 178 | 0.389, 179 | 1.2, 180 | 0.778, 181 | 1.148, 182 | 1.167, 183 | 1, 184 | 1, 185 | 1.211, 186 | 0.983, 187 | 1.256, 188 | 0, 189 | 1.3, 190 | 0, 191 | 1, 192 | 1.322, 193 | 0, 194 | 1.344, 195 | 0, 196 | 1.367, 197 | 0, 198 | 1, 199 | 1.422, 200 | 0, 201 | 1.478, 202 | 1, 203 | 1.533, 204 | 1, 205 | 1, 206 | 1.944, 207 | 1, 208 | 2.356, 209 | 1, 210 | 2.767, 211 | 1, 212 | 1, 213 | 2.811, 214 | 1, 215 | 2.856, 216 | 0, 217 | 2.9, 218 | 0, 219 | 1, 220 | 2.922, 221 | 0, 222 | 2.944, 223 | 0, 224 | 2.967, 225 | 0, 226 | 1, 227 | 3.022, 228 | 0, 229 | 3.078, 230 | 1, 231 | 3.133, 232 | 1, 233 | 0, 234 | 4.433, 235 | 1 236 | ] 237 | }, 238 | { 239 | "Target": "Parameter", 240 | "Id": "ParamEyeLSmile", 241 | "Segments": [ 242 | 0, 243 | 0, 244 | 0, 245 | 4.433, 246 | 0 247 | ] 248 | }, 249 | { 250 | "Target": "Parameter", 251 | "Id": "ParamEyeROpen", 252 | "Segments": [ 253 | 0, 254 | 1.2, 255 | 1, 256 | 0.389, 257 | 1.2, 258 | 0.778, 259 | 1.148, 260 | 1.167, 261 | 1, 262 | 1, 263 | 1.211, 264 | 0.983, 265 | 1.256, 266 | 0, 267 | 1.3, 268 | 0, 269 | 1, 270 | 1.322, 271 | 0, 272 | 1.344, 273 | 0, 274 | 1.367, 275 | 0, 276 | 1, 277 | 1.422, 278 | 0, 279 | 1.478, 280 | 1, 281 | 1.533, 282 | 1, 283 | 1, 284 | 1.944, 285 | 1, 286 | 2.356, 287 | 1, 288 | 2.767, 289 | 1, 290 | 1, 291 | 2.811, 292 | 1, 293 | 2.856, 294 | 0, 295 | 2.9, 296 | 0, 297 | 1, 298 | 2.922, 299 | 0, 300 | 2.944, 301 | 0, 302 | 2.967, 303 | 0, 304 | 1, 305 | 3.022, 306 | 0, 307 | 3.078, 308 | 1, 309 | 3.133, 310 | 1, 311 | 0, 312 | 4.433, 313 | 1 314 | ] 315 | }, 316 | { 317 | "Target": "Parameter", 318 | "Id": "ParamEyeRSmile", 319 | "Segments": [ 320 | 0, 321 | 0, 322 | 0, 323 | 4.433, 324 | 0 325 | ] 326 | }, 327 | { 328 | "Target": "Parameter", 329 | "Id": "ParamEyeBallX", 330 | "Segments": [ 331 | 0, 332 | 0, 333 | 1, 334 | 0.211, 335 | 0, 336 | 0.422, 337 | 0, 338 | 0.633, 339 | 0, 340 | 1, 341 | 0.911, 342 | 0, 343 | 1.189, 344 | -0.44, 345 | 1.467, 346 | -0.44, 347 | 1, 348 | 1.689, 349 | -0.44, 350 | 1.911, 351 | 0.79, 352 | 2.133, 353 | 0.79, 354 | 1, 355 | 2.511, 356 | 0.79, 357 | 2.889, 358 | 0, 359 | 3.267, 360 | 0, 361 | 0, 362 | 4.433, 363 | 0 364 | ] 365 | }, 366 | { 367 | "Target": "Parameter", 368 | "Id": "ParamEyeBallY", 369 | "Segments": [ 370 | 0, 371 | 0, 372 | 1, 373 | 0.211, 374 | 0, 375 | 0.422, 376 | 0, 377 | 0.633, 378 | 0, 379 | 1, 380 | 0.911, 381 | 0, 382 | 1.189, 383 | -1, 384 | 1.467, 385 | -1, 386 | 1, 387 | 1.689, 388 | -1, 389 | 1.911, 390 | -1, 391 | 2.133, 392 | -1, 393 | 1, 394 | 2.511, 395 | -1, 396 | 2.889, 397 | 0, 398 | 3.267, 399 | 0, 400 | 0, 401 | 4.433, 402 | 0 403 | ] 404 | }, 405 | { 406 | "Target": "Parameter", 407 | "Id": "ParamBrowLY", 408 | "Segments": [ 409 | 0, 410 | 1, 411 | 1, 412 | 0.544, 413 | 1, 414 | 1.089, 415 | 1, 416 | 1.633, 417 | 1, 418 | 1, 419 | 1.856, 420 | 1, 421 | 2.078, 422 | 0, 423 | 2.3, 424 | 0, 425 | 1, 426 | 2.5, 427 | 0, 428 | 2.7, 429 | 1, 430 | 2.9, 431 | 1, 432 | 0, 433 | 4.433, 434 | 1 435 | ] 436 | }, 437 | { 438 | "Target": "Parameter", 439 | "Id": "ParamBrowRY", 440 | "Segments": [ 441 | 0, 442 | 1, 443 | 1, 444 | 0.544, 445 | 1, 446 | 1.089, 447 | 1, 448 | 1.633, 449 | 1, 450 | 1, 451 | 1.856, 452 | 1, 453 | 2.078, 454 | 0, 455 | 2.3, 456 | 0, 457 | 1, 458 | 2.5, 459 | 0, 460 | 2.7, 461 | 1, 462 | 2.9, 463 | 1, 464 | 0, 465 | 4.433, 466 | 1 467 | ] 468 | }, 469 | { 470 | "Target": "Parameter", 471 | "Id": "ParamBrowLX", 472 | "Segments": [ 473 | 0, 474 | 0, 475 | 0, 476 | 4.433, 477 | 0 478 | ] 479 | }, 480 | { 481 | "Target": "Parameter", 482 | "Id": "ParamBrowRX", 483 | "Segments": [ 484 | 0, 485 | 0, 486 | 0, 487 | 4.433, 488 | 0 489 | ] 490 | }, 491 | { 492 | "Target": "Parameter", 493 | "Id": "ParamBrowLAngle", 494 | "Segments": [ 495 | 0, 496 | 0, 497 | 0, 498 | 4.433, 499 | 0 500 | ] 501 | }, 502 | { 503 | "Target": "Parameter", 504 | "Id": "ParamBrowRAngle", 505 | "Segments": [ 506 | 0, 507 | 0, 508 | 0, 509 | 4.433, 510 | 0 511 | ] 512 | }, 513 | { 514 | "Target": "Parameter", 515 | "Id": "ParamBrowLForm", 516 | "Segments": [ 517 | 0, 518 | -1, 519 | 0, 520 | 4.433, 521 | -1 522 | ] 523 | }, 524 | { 525 | "Target": "Parameter", 526 | "Id": "ParamBrowRForm", 527 | "Segments": [ 528 | 0, 529 | -1, 530 | 0, 531 | 4.433, 532 | -1 533 | ] 534 | }, 535 | { 536 | "Target": "Parameter", 537 | "Id": "ParamMouthForm", 538 | "Segments": [ 539 | 0, 540 | -2, 541 | 0, 542 | 4.433, 543 | -2 544 | ] 545 | }, 546 | { 547 | "Target": "Parameter", 548 | "Id": "ParamMouthOpenY", 549 | "Segments": [ 550 | 0, 551 | 0, 552 | 0, 553 | 4.433, 554 | 0 555 | ] 556 | }, 557 | { 558 | "Target": "Parameter", 559 | "Id": "ParamBodyAngleX", 560 | "Segments": [ 561 | 0, 562 | 0, 563 | 1, 564 | 0.244, 565 | 0, 566 | 0.489, 567 | 0, 568 | 0.733, 569 | 0, 570 | 1, 571 | 0.933, 572 | 0, 573 | 1.133, 574 | -7, 575 | 1.333, 576 | -7, 577 | 1, 578 | 1.644, 579 | -7, 580 | 1.956, 581 | 0, 582 | 2.267, 583 | 0, 584 | 0, 585 | 4.433, 586 | 0 587 | ] 588 | }, 589 | { 590 | "Target": "Parameter", 591 | "Id": "ParamBodyAngleY", 592 | "Segments": [ 593 | 0, 594 | 0, 595 | 1, 596 | 0.244, 597 | 0, 598 | 0.489, 599 | 0, 600 | 0.733, 601 | 0, 602 | 0, 603 | 4.433, 604 | 0 605 | ] 606 | }, 607 | { 608 | "Target": "Parameter", 609 | "Id": "ParamBodyAngleZ", 610 | "Segments": [ 611 | 0, 612 | 2, 613 | 1, 614 | 0.233, 615 | 2, 616 | 0.467, 617 | 0, 618 | 0.7, 619 | 0, 620 | 1, 621 | 0.733, 622 | 0, 623 | 0.767, 624 | 0, 625 | 0.8, 626 | 0, 627 | 1, 628 | 1, 629 | 0, 630 | 1.2, 631 | -4, 632 | 1.4, 633 | -4, 634 | 1, 635 | 1.711, 636 | -4, 637 | 2.022, 638 | 5, 639 | 2.333, 640 | 5, 641 | 1, 642 | 2.567, 643 | 5, 644 | 2.8, 645 | 3.64, 646 | 3.033, 647 | 0, 648 | 1, 649 | 3.133, 650 | -1.56, 651 | 3.233, 652 | -3, 653 | 3.333, 654 | -3, 655 | 1, 656 | 3.467, 657 | -3, 658 | 3.6, 659 | -2, 660 | 3.733, 661 | -2, 662 | 0, 663 | 4.433, 664 | -2 665 | ] 666 | }, 667 | { 668 | "Target": "Parameter", 669 | "Id": "ParamBreath", 670 | "Segments": [ 671 | 0, 672 | 0, 673 | 1, 674 | 0.189, 675 | 0, 676 | 0.378, 677 | 1, 678 | 0.567, 679 | 1, 680 | 1, 681 | 0.711, 682 | 1, 683 | 0.856, 684 | 0, 685 | 1, 686 | 0, 687 | 1, 688 | 1.222, 689 | 0, 690 | 1.444, 691 | 1, 692 | 1.667, 693 | 1, 694 | 1, 695 | 1.889, 696 | 1, 697 | 2.111, 698 | 0, 699 | 2.333, 700 | 0, 701 | 1, 702 | 2.544, 703 | 0, 704 | 2.756, 705 | 1, 706 | 2.967, 707 | 1, 708 | 1, 709 | 3.167, 710 | 1, 711 | 3.367, 712 | 0, 713 | 3.567, 714 | 0, 715 | 0, 716 | 4.433, 717 | 0 718 | ] 719 | }, 720 | { 721 | "Target": "Parameter", 722 | "Id": "ParamShoulder", 723 | "Segments": [ 724 | 0, 725 | 0.1, 726 | 1, 727 | 0.467, 728 | 0.1, 729 | 0.933, 730 | 1, 731 | 1.4, 732 | 1, 733 | 1, 734 | 1.844, 735 | 1, 736 | 2.289, 737 | 1, 738 | 2.733, 739 | 1, 740 | 1, 741 | 2.967, 742 | 1, 743 | 3.2, 744 | -1, 745 | 3.433, 746 | -1, 747 | 0, 748 | 4.433, 749 | -1 750 | ] 751 | }, 752 | { 753 | "Target": "Parameter", 754 | "Id": "ParamLeg", 755 | "Segments": [ 756 | 0, 757 | 1, 758 | 0, 759 | 4.433, 760 | 1 761 | ] 762 | }, 763 | { 764 | "Target": "Parameter", 765 | "Id": "ParamArmLA", 766 | "Segments": [ 767 | 0, 768 | -10, 769 | 0, 770 | 4.433, 771 | -10 772 | ] 773 | }, 774 | { 775 | "Target": "Parameter", 776 | "Id": "ParamArmRA", 777 | "Segments": [ 778 | 0, 779 | -10, 780 | 0, 781 | 4.433, 782 | -10 783 | ] 784 | }, 785 | { 786 | "Target": "Parameter", 787 | "Id": "ParamHairAhoge", 788 | "Segments": [ 789 | 0, 790 | 0, 791 | 1, 792 | 0.3, 793 | 0, 794 | 0.6, 795 | 0, 796 | 0.9, 797 | -0.012, 798 | 1, 799 | 1.067, 800 | -0.019, 801 | 1.233, 802 | -6.827, 803 | 1.4, 804 | -6.827, 805 | 1, 806 | 1.511, 807 | -6.827, 808 | 1.622, 809 | 7.958, 810 | 1.733, 811 | 7.958, 812 | 1, 813 | 1.944, 814 | 7.958, 815 | 2.156, 816 | -7.565, 817 | 2.367, 818 | -7.565, 819 | 1, 820 | 2.5, 821 | -7.565, 822 | 2.633, 823 | 9.434, 824 | 2.767, 825 | 9.434, 826 | 1, 827 | 2.978, 828 | 9.434, 829 | 3.189, 830 | -8.871, 831 | 3.4, 832 | -8.871, 833 | 1, 834 | 3.5, 835 | -8.871, 836 | 3.6, 837 | 7.588, 838 | 3.7, 839 | 7.588, 840 | 1, 841 | 3.789, 842 | 7.588, 843 | 3.878, 844 | -3.904, 845 | 3.967, 846 | -3.904, 847 | 1, 848 | 4.011, 849 | -3.904, 850 | 4.056, 851 | -0.032, 852 | 4.1, 853 | -0.032, 854 | 0, 855 | 4.433, 856 | -0.032 857 | ] 858 | }, 859 | { 860 | "Target": "PartOpacity", 861 | "Id": "PartArmA", 862 | "Segments": [ 863 | 0, 864 | 1, 865 | 0, 866 | 4.43, 867 | 1 868 | ] 869 | }, 870 | { 871 | "Target": "PartOpacity", 872 | "Id": "PartArmB", 873 | "Segments": [ 874 | 0, 875 | 0, 876 | 0, 877 | 4.43, 878 | 0 879 | ] 880 | } 881 | ] 882 | } -------------------------------------------------------------------------------- /ChatWithGPT/game/Resources/Hiyori/motions/Hiyori_talking.motion3.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 3, 3 | "Meta": { 4 | "Duration": 3.167, 5 | "Fps": 30.0, 6 | "Loop": true, 7 | "AreBeziersRestricted": false, 8 | "CurveCount": 30, 9 | "TotalSegmentCount": 107, 10 | "TotalPointCount": 317, 11 | "UserDataCount": 0, 12 | "TotalUserDataSize": 0 13 | }, 14 | "Curves": [ 15 | { 16 | "Target": "Model", 17 | "Id": "EyeBlink", 18 | "Segments": [ 19 | 0, 20 | 1, 21 | 0, 22 | 1.167, 23 | 1, 24 | 1, 25 | 1.267, 26 | 1, 27 | 1.367, 28 | 0, 29 | 1.467, 30 | 0, 31 | 1, 32 | 1.533, 33 | 0, 34 | 1.6, 35 | 0, 36 | 1.667, 37 | 0, 38 | 1, 39 | 1.767, 40 | 0, 41 | 1.867, 42 | 1, 43 | 1.967, 44 | 1, 45 | 0, 46 | 3.167, 47 | 1 48 | ] 49 | }, 50 | { 51 | "Target": "Parameter", 52 | "Id": "ParamAngleX", 53 | "Segments": [ 54 | 0, 55 | 0, 56 | 0, 57 | 3.167, 58 | 0 59 | ] 60 | }, 61 | { 62 | "Target": "Parameter", 63 | "Id": "ParamAngleY", 64 | "Segments": [ 65 | 0, 66 | 0, 67 | 0, 68 | 3.167, 69 | 0 70 | ] 71 | }, 72 | { 73 | "Target": "Parameter", 74 | "Id": "ParamAngleZ", 75 | "Segments": [ 76 | 0, 77 | 0, 78 | 0, 79 | 3.167, 80 | 0 81 | ] 82 | }, 83 | { 84 | "Target": "Parameter", 85 | "Id": "ParamCheek", 86 | "Segments": [ 87 | 0, 88 | 0, 89 | 0, 90 | 3.167, 91 | 0 92 | ] 93 | }, 94 | { 95 | "Target": "Parameter", 96 | "Id": "ParamEyeLOpen", 97 | "Segments": [ 98 | 0, 99 | 1, 100 | 0, 101 | 3.167, 102 | 1 103 | ] 104 | }, 105 | { 106 | "Target": "Parameter", 107 | "Id": "ParamEyeLSmile", 108 | "Segments": [ 109 | 0, 110 | 0, 111 | 0, 112 | 3.167, 113 | 0 114 | ] 115 | }, 116 | { 117 | "Target": "Parameter", 118 | "Id": "ParamEyeROpen", 119 | "Segments": [ 120 | 0, 121 | 1, 122 | 0, 123 | 3.167, 124 | 1 125 | ] 126 | }, 127 | { 128 | "Target": "Parameter", 129 | "Id": "ParamEyeRSmile", 130 | "Segments": [ 131 | 0, 132 | 0, 133 | 0, 134 | 3.167, 135 | 0 136 | ] 137 | }, 138 | { 139 | "Target": "Parameter", 140 | "Id": "ParamEyeBallX", 141 | "Segments": [ 142 | 0, 143 | 0, 144 | 0, 145 | 3.167, 146 | 0 147 | ] 148 | }, 149 | { 150 | "Target": "Parameter", 151 | "Id": "ParamEyeBallY", 152 | "Segments": [ 153 | 0, 154 | 0, 155 | 0, 156 | 3.167, 157 | 0 158 | ] 159 | }, 160 | { 161 | "Target": "Parameter", 162 | "Id": "ParamBrowLForm", 163 | "Segments": [ 164 | 0, 165 | 0, 166 | 0, 167 | 3.167, 168 | 0 169 | ] 170 | }, 171 | { 172 | "Target": "Parameter", 173 | "Id": "ParamBrowRForm", 174 | "Segments": [ 175 | 0, 176 | 0, 177 | 0, 178 | 3.167, 179 | 0 180 | ] 181 | }, 182 | { 183 | "Target": "Parameter", 184 | "Id": "ParamMouthForm", 185 | "Segments": [ 186 | 0, 187 | 0.5, 188 | 1, 189 | 0.056, 190 | 0.5, 191 | 0.111, 192 | 1, 193 | 0.167, 194 | 1, 195 | 1, 196 | 0.222, 197 | 1, 198 | 0.278, 199 | 0.5, 200 | 0.333, 201 | 0.5, 202 | 1, 203 | 0.389, 204 | 0.5, 205 | 0.444, 206 | 1, 207 | 0.5, 208 | 1, 209 | 1, 210 | 0.556, 211 | 1, 212 | 0.611, 213 | 0.5, 214 | 0.667, 215 | 0.5, 216 | 1, 217 | 0.722, 218 | 0.5, 219 | 0.778, 220 | 1, 221 | 0.833, 222 | 1, 223 | 1, 224 | 0.889, 225 | 1, 226 | 0.944, 227 | 0.5, 228 | 1, 229 | 0.5, 230 | 1, 231 | 1.056, 232 | 0.5, 233 | 1.111, 234 | 1, 235 | 1.167, 236 | 1, 237 | 1, 238 | 1.222, 239 | 1, 240 | 1.278, 241 | 0.5, 242 | 1.333, 243 | 0.5, 244 | 1, 245 | 1.389, 246 | 0.5, 247 | 1.444, 248 | 1, 249 | 1.5, 250 | 1, 251 | 1, 252 | 1.556, 253 | 1, 254 | 1.611, 255 | 0.5, 256 | 1.667, 257 | 0.5, 258 | 1, 259 | 1.722, 260 | 0.5, 261 | 1.778, 262 | 1, 263 | 1.833, 264 | 1, 265 | 1, 266 | 1.889, 267 | 1, 268 | 1.944, 269 | 0.5, 270 | 2, 271 | 0.5, 272 | 1, 273 | 2.056, 274 | 0.5, 275 | 2.111, 276 | 1, 277 | 2.167, 278 | 1, 279 | 1, 280 | 2.222, 281 | 1, 282 | 2.278, 283 | 0.5, 284 | 2.333, 285 | 0.5, 286 | 1, 287 | 2.389, 288 | 0.5, 289 | 2.444, 290 | 1, 291 | 2.5, 292 | 1, 293 | 1, 294 | 2.556, 295 | 1, 296 | 2.611, 297 | 0.5, 298 | 2.667, 299 | 0.5, 300 | 1, 301 | 2.722, 302 | 0.5, 303 | 2.778, 304 | 1, 305 | 2.833, 306 | 1, 307 | 1, 308 | 2.889, 309 | 1, 310 | 2.944, 311 | 0.5, 312 | 3, 313 | 0.5, 314 | 1, 315 | 3.056, 316 | 0.5, 317 | 3.111, 318 | 1, 319 | 3.167, 320 | 1 321 | ] 322 | }, 323 | { 324 | "Target": "Parameter", 325 | "Id": "ParamMouthOpenY", 326 | "Segments": [ 327 | 0, 328 | 0, 329 | 1, 330 | 0.056, 331 | 0, 332 | 0.111, 333 | 1, 334 | 0.167, 335 | 1, 336 | 1, 337 | 0.222, 338 | 1, 339 | 0.278, 340 | 0.6, 341 | 0.333, 342 | 0.6, 343 | 1, 344 | 0.389, 345 | 0.6, 346 | 0.444, 347 | 1, 348 | 0.5, 349 | 1, 350 | 1, 351 | 0.556, 352 | 1, 353 | 0.611, 354 | 0, 355 | 0.667, 356 | 0, 357 | 1, 358 | 0.722, 359 | 0, 360 | 0.778, 361 | 1, 362 | 0.833, 363 | 1, 364 | 1, 365 | 0.889, 366 | 1, 367 | 0.944, 368 | 0.6, 369 | 1, 370 | 0.6, 371 | 1, 372 | 1.056, 373 | 0.6, 374 | 1.111, 375 | 1, 376 | 1.167, 377 | 1, 378 | 1, 379 | 1.222, 380 | 1, 381 | 1.278, 382 | 0, 383 | 1.333, 384 | 0, 385 | 1, 386 | 1.389, 387 | 0, 388 | 1.444, 389 | 1, 390 | 1.5, 391 | 1, 392 | 1, 393 | 1.556, 394 | 1, 395 | 1.611, 396 | 0.6, 397 | 1.667, 398 | 0.6, 399 | 1, 400 | 1.722, 401 | 0.6, 402 | 1.778, 403 | 1, 404 | 1.833, 405 | 1, 406 | 1, 407 | 1.889, 408 | 1, 409 | 1.944, 410 | 0, 411 | 2, 412 | 0, 413 | 1, 414 | 2.056, 415 | 0, 416 | 2.111, 417 | 1, 418 | 2.167, 419 | 1, 420 | 1, 421 | 2.222, 422 | 1, 423 | 2.278, 424 | 0.6, 425 | 2.333, 426 | 0.6, 427 | 1, 428 | 2.389, 429 | 0.6, 430 | 2.444, 431 | 1, 432 | 2.5, 433 | 1, 434 | 1, 435 | 2.556, 436 | 1, 437 | 2.611, 438 | 0, 439 | 2.667, 440 | 0, 441 | 1, 442 | 2.722, 443 | 0, 444 | 2.778, 445 | 1, 446 | 2.833, 447 | 1, 448 | 1, 449 | 2.889, 450 | 1, 451 | 2.944, 452 | 0.6, 453 | 3, 454 | 0.6, 455 | 1, 456 | 3.056, 457 | 0.6, 458 | 3.111, 459 | 1, 460 | 3.167, 461 | 1 462 | ] 463 | }, 464 | { 465 | "Target": "Parameter", 466 | "Id": "ParamBodyAngleX", 467 | "Segments": [ 468 | 0, 469 | 0, 470 | 1, 471 | 0.333, 472 | 0, 473 | 0.667, 474 | 2, 475 | 1, 476 | 2, 477 | 1, 478 | 1.356, 479 | 2, 480 | 1.711, 481 | -2, 482 | 2.067, 483 | -2, 484 | 1, 485 | 2.433, 486 | -2, 487 | 2.8, 488 | 0, 489 | 3.167, 490 | 0 491 | ] 492 | }, 493 | { 494 | "Target": "Parameter", 495 | "Id": "ParamBodyAngleY", 496 | "Segments": [ 497 | 0, 498 | 0, 499 | 1, 500 | 0.056, 501 | 0, 502 | 0.111, 503 | 0, 504 | 0.167, 505 | 0, 506 | 1, 507 | 0.556, 508 | 0, 509 | 0.944, 510 | 5, 511 | 1.333, 512 | 5, 513 | 1, 514 | 1.778, 515 | 5, 516 | 2.222, 517 | 0, 518 | 2.667, 519 | 0, 520 | 0, 521 | 3.167, 522 | 0 523 | ] 524 | }, 525 | { 526 | "Target": "Parameter", 527 | "Id": "ParamBodyAngleZ", 528 | "Segments": [ 529 | 0, 530 | 0, 531 | 1, 532 | 0.333, 533 | 0, 534 | 0.667, 535 | 2, 536 | 1, 537 | 2, 538 | 1, 539 | 1.356, 540 | 2, 541 | 1.711, 542 | -2, 543 | 2.067, 544 | -2, 545 | 1, 546 | 2.433, 547 | -2, 548 | 2.8, 549 | 0, 550 | 3.167, 551 | 0 552 | ] 553 | }, 554 | { 555 | "Target": "Parameter", 556 | "Id": "ParamBreath", 557 | "Segments": [ 558 | 0, 559 | 0, 560 | 1, 561 | 0.222, 562 | 0, 563 | 0.444, 564 | 0.167, 565 | 0.667, 566 | 0.5, 567 | 1, 568 | 0.889, 569 | 0.833, 570 | 1.111, 571 | 1, 572 | 1.333, 573 | 1, 574 | 1, 575 | 1.556, 576 | 1, 577 | 1.778, 578 | 0.833, 579 | 2, 580 | 0.5, 581 | 1, 582 | 2.222, 583 | 0.167, 584 | 2.444, 585 | 0, 586 | 2.667, 587 | 0, 588 | 0, 589 | 3.167, 590 | 0 591 | ] 592 | }, 593 | { 594 | "Target": "Parameter", 595 | "Id": "ParamArmLA", 596 | "Segments": [ 597 | 0, 598 | 0, 599 | 1, 600 | 0.511, 601 | 0, 602 | 1.022, 603 | -3, 604 | 1.533, 605 | -3, 606 | 1, 607 | 2.078, 608 | -3, 609 | 2.622, 610 | 0, 611 | 3.167, 612 | 0 613 | ] 614 | }, 615 | { 616 | "Target": "Parameter", 617 | "Id": "ParamArmRA", 618 | "Segments": [ 619 | 0, 620 | 0, 621 | 1, 622 | 0.511, 623 | 0, 624 | 1.022, 625 | -3, 626 | 1.533, 627 | -3, 628 | 1, 629 | 2.078, 630 | -3, 631 | 2.622, 632 | 0, 633 | 3.167, 634 | 0 635 | ] 636 | }, 637 | { 638 | "Target": "Parameter", 639 | "Id": "ParamBustY", 640 | "Segments": [ 641 | 0, 642 | 0, 643 | 0, 644 | 3.167, 645 | 0 646 | ] 647 | }, 648 | { 649 | "Target": "Parameter", 650 | "Id": "ParamHairAhoge", 651 | "Segments": [ 652 | 0, 653 | 0, 654 | 1, 655 | 0.244, 656 | 0, 657 | 0.489, 658 | 10, 659 | 0.733, 660 | 10, 661 | 1, 662 | 1, 663 | 10, 664 | 1.267, 665 | 6.528, 666 | 1.533, 667 | 0, 668 | 1, 669 | 1.811, 670 | -6.8, 671 | 2.089, 672 | -10, 673 | 2.367, 674 | -10, 675 | 1, 676 | 2.633, 677 | -10, 678 | 2.9, 679 | 0, 680 | 3.167, 681 | 0 682 | ] 683 | }, 684 | { 685 | "Target": "Parameter", 686 | "Id": "ParamHairFront", 687 | "Segments": [ 688 | 0, 689 | 0, 690 | 1, 691 | 0.244, 692 | 0, 693 | 0.489, 694 | 0.2, 695 | 0.733, 696 | 0.2, 697 | 1, 698 | 1, 699 | 0.2, 700 | 1.267, 701 | 0.131, 702 | 1.533, 703 | 0, 704 | 1, 705 | 1.811, 706 | -0.136, 707 | 2.089, 708 | -0.2, 709 | 2.367, 710 | -0.2, 711 | 1, 712 | 2.633, 713 | -0.2, 714 | 2.9, 715 | 0, 716 | 3.167, 717 | 0 718 | ] 719 | }, 720 | { 721 | "Target": "Parameter", 722 | "Id": "ParamHairSide", 723 | "Segments": [ 724 | 0, 725 | 0, 726 | 1, 727 | 0.244, 728 | 0, 729 | 0.489, 730 | 0.2, 731 | 0.733, 732 | 0.2, 733 | 1, 734 | 1, 735 | 0.2, 736 | 1.267, 737 | 0.131, 738 | 1.533, 739 | 0, 740 | 1, 741 | 1.811, 742 | -0.136, 743 | 2.089, 744 | -0.2, 745 | 2.367, 746 | -0.2, 747 | 1, 748 | 2.633, 749 | -0.2, 750 | 2.9, 751 | 0, 752 | 3.167, 753 | 0 754 | ] 755 | }, 756 | { 757 | "Target": "Parameter", 758 | "Id": "ParamHairBack", 759 | "Segments": [ 760 | 0, 761 | 0, 762 | 1, 763 | 0.244, 764 | 0, 765 | 0.489, 766 | 0.2, 767 | 0.733, 768 | 0.2, 769 | 1, 770 | 1, 771 | 0.2, 772 | 1.267, 773 | 0.131, 774 | 1.533, 775 | 0, 776 | 1, 777 | 1.811, 778 | -0.136, 779 | 2.089, 780 | -0.2, 781 | 2.367, 782 | -0.2, 783 | 1, 784 | 2.633, 785 | -0.2, 786 | 2.9, 787 | 0, 788 | 3.167, 789 | 0 790 | ] 791 | }, 792 | { 793 | "Target": "Parameter", 794 | "Id": "ParamHairSideUp", 795 | "Segments": [ 796 | 0, 797 | 0, 798 | 1, 799 | 0.244, 800 | 0, 801 | 0.489, 802 | 0.2, 803 | 0.733, 804 | 0.2, 805 | 1, 806 | 1, 807 | 0.2, 808 | 1.267, 809 | 0.131, 810 | 1.533, 811 | 0, 812 | 1, 813 | 1.811, 814 | -0.136, 815 | 2.089, 816 | -0.2, 817 | 2.367, 818 | -0.2, 819 | 1, 820 | 2.633, 821 | -0.2, 822 | 2.9, 823 | 0, 824 | 3.167, 825 | 0 826 | ] 827 | }, 828 | { 829 | "Target": "Parameter", 830 | "Id": "ParamRibbon", 831 | "Segments": [ 832 | 0, 833 | 0, 834 | 1, 835 | 0.244, 836 | 0, 837 | 0.489, 838 | 0.2, 839 | 0.733, 840 | 0.2, 841 | 1, 842 | 1, 843 | 0.2, 844 | 1.267, 845 | 0.131, 846 | 1.533, 847 | 0, 848 | 1, 849 | 1.811, 850 | -0.136, 851 | 2.089, 852 | -0.2, 853 | 2.367, 854 | -0.2, 855 | 1, 856 | 2.633, 857 | -0.2, 858 | 2.9, 859 | 0, 860 | 3.167, 861 | 0 862 | ] 863 | }, 864 | { 865 | "Target": "Parameter", 866 | "Id": "ParamSkirt", 867 | "Segments": [ 868 | 0, 869 | 0, 870 | 1, 871 | 0.244, 872 | 0, 873 | 0.489, 874 | 0.2, 875 | 0.733, 876 | 0.2, 877 | 1, 878 | 1, 879 | 0.2, 880 | 1.267, 881 | 0.131, 882 | 1.533, 883 | 0, 884 | 1, 885 | 1.811, 886 | -0.136, 887 | 2.089, 888 | -0.2, 889 | 2.367, 890 | -0.2, 891 | 1, 892 | 2.633, 893 | -0.2, 894 | 2.9, 895 | 0, 896 | 3.167, 897 | 0 898 | ] 899 | }, 900 | { 901 | "Target": "Parameter", 902 | "Id": "ParamSideUpRibbon", 903 | "Segments": [ 904 | 0, 905 | 0, 906 | 1, 907 | 0.244, 908 | 0, 909 | 0.489, 910 | 0.2, 911 | 0.733, 912 | 0.2, 913 | 1, 914 | 1, 915 | 0.2, 916 | 1.267, 917 | 0.131, 918 | 1.533, 919 | 0, 920 | 1, 921 | 1.811, 922 | -0.136, 923 | 2.089, 924 | -0.2, 925 | 2.367, 926 | -0.2, 927 | 1, 928 | 2.633, 929 | -0.2, 930 | 2.9, 931 | 0, 932 | 3.167, 933 | 0 934 | ] 935 | } 936 | ] 937 | } -------------------------------------------------------------------------------- /ChatWithGPT/game/Resources/Hiyori/motions/Hiyori_m10.motion3.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 3, 3 | "Meta": { 4 | "Duration": 4.17, 5 | "Fps": 30.0, 6 | "Loop": true, 7 | "AreBeziersRestricted": false, 8 | "CurveCount": 33, 9 | "TotalSegmentCount": 118, 10 | "TotalPointCount": 321, 11 | "UserDataCount": 0, 12 | "TotalUserDataSize": 0 13 | }, 14 | "Curves": [ 15 | { 16 | "Target": "Parameter", 17 | "Id": "ParamAngleX", 18 | "Segments": [ 19 | 0, 20 | 0, 21 | 1, 22 | 0.067, 23 | 0, 24 | 0.133, 25 | 0, 26 | 0.2, 27 | 0, 28 | 1, 29 | 0.4, 30 | 0, 31 | 0.6, 32 | 0, 33 | 0.8, 34 | 0, 35 | 1, 36 | 1.067, 37 | 0, 38 | 1.333, 39 | 1.041, 40 | 1.6, 41 | 1.041, 42 | 1, 43 | 1.844, 44 | 1.041, 45 | 2.089, 46 | -8, 47 | 2.333, 48 | -8, 49 | 1, 50 | 2.656, 51 | -8, 52 | 2.978, 53 | 6, 54 | 3.3, 55 | 6, 56 | 0, 57 | 4.167, 58 | 6 59 | ] 60 | }, 61 | { 62 | "Target": "Parameter", 63 | "Id": "ParamAngleY", 64 | "Segments": [ 65 | 0, 66 | 0, 67 | 1, 68 | 0.067, 69 | 0, 70 | 0.133, 71 | 0, 72 | 0.2, 73 | 0, 74 | 1, 75 | 0.344, 76 | 0, 77 | 0.489, 78 | -30, 79 | 0.633, 80 | -30, 81 | 0, 82 | 4.167, 83 | -30 84 | ] 85 | }, 86 | { 87 | "Target": "Parameter", 88 | "Id": "ParamAngleZ", 89 | "Segments": [ 90 | 0, 91 | 0, 92 | 1, 93 | 0.067, 94 | 0, 95 | 0.133, 96 | 0, 97 | 0.2, 98 | 0, 99 | 0, 100 | 4.167, 101 | 0 102 | ] 103 | }, 104 | { 105 | "Target": "Parameter", 106 | "Id": "ParamCheek", 107 | "Segments": [ 108 | 0, 109 | 0, 110 | 1, 111 | 0.067, 112 | 0, 113 | 0.133, 114 | 0, 115 | 0.2, 116 | 0, 117 | 0, 118 | 4.167, 119 | 0 120 | ] 121 | }, 122 | { 123 | "Target": "Parameter", 124 | "Id": "ParamEyeLOpen", 125 | "Segments": [ 126 | 0, 127 | 1, 128 | 1, 129 | 0.067, 130 | 1, 131 | 0.133, 132 | 1, 133 | 0.2, 134 | 1, 135 | 1, 136 | 0.311, 137 | 1, 138 | 0.422, 139 | 0.988, 140 | 0.533, 141 | 0.8, 142 | 1, 143 | 0.589, 144 | 0.706, 145 | 0.644, 146 | 0, 147 | 0.7, 148 | 0, 149 | 1, 150 | 0.722, 151 | 0, 152 | 0.744, 153 | 0, 154 | 0.767, 155 | 0, 156 | 1, 157 | 0.822, 158 | 0, 159 | 0.878, 160 | 0.8, 161 | 0.933, 162 | 0.8, 163 | 1, 164 | 1.422, 165 | 0.8, 166 | 1.911, 167 | 0.8, 168 | 2.4, 169 | 0.8, 170 | 1, 171 | 2.456, 172 | 0.8, 173 | 2.511, 174 | 0, 175 | 2.567, 176 | 0, 177 | 1, 178 | 2.589, 179 | 0, 180 | 2.611, 181 | 0, 182 | 2.633, 183 | 0, 184 | 1, 185 | 2.689, 186 | 0, 187 | 2.744, 188 | 0.8, 189 | 2.8, 190 | 0.8, 191 | 0, 192 | 4.167, 193 | 0.8 194 | ] 195 | }, 196 | { 197 | "Target": "Parameter", 198 | "Id": "ParamEyeLSmile", 199 | "Segments": [ 200 | 0, 201 | 0, 202 | 1, 203 | 0.067, 204 | 0, 205 | 0.133, 206 | 0, 207 | 0.2, 208 | 0, 209 | 0, 210 | 4.167, 211 | 0 212 | ] 213 | }, 214 | { 215 | "Target": "Parameter", 216 | "Id": "ParamEyeROpen", 217 | "Segments": [ 218 | 0, 219 | 1, 220 | 1, 221 | 0.067, 222 | 1, 223 | 0.133, 224 | 1, 225 | 0.2, 226 | 1, 227 | 1, 228 | 0.311, 229 | 1, 230 | 0.422, 231 | 0.988, 232 | 0.533, 233 | 0.8, 234 | 1, 235 | 0.589, 236 | 0.706, 237 | 0.644, 238 | 0, 239 | 0.7, 240 | 0, 241 | 1, 242 | 0.722, 243 | 0, 244 | 0.744, 245 | 0, 246 | 0.767, 247 | 0, 248 | 1, 249 | 0.822, 250 | 0, 251 | 0.878, 252 | 0.8, 253 | 0.933, 254 | 0.8, 255 | 1, 256 | 1.422, 257 | 0.8, 258 | 1.911, 259 | 0.8, 260 | 2.4, 261 | 0.8, 262 | 1, 263 | 2.456, 264 | 0.8, 265 | 2.511, 266 | 0, 267 | 2.567, 268 | 0, 269 | 1, 270 | 2.589, 271 | 0, 272 | 2.611, 273 | 0, 274 | 2.633, 275 | 0, 276 | 1, 277 | 2.689, 278 | 0, 279 | 2.744, 280 | 0.8, 281 | 2.8, 282 | 0.8, 283 | 0, 284 | 4.167, 285 | 0.8 286 | ] 287 | }, 288 | { 289 | "Target": "Parameter", 290 | "Id": "ParamEyeRSmile", 291 | "Segments": [ 292 | 0, 293 | 0, 294 | 1, 295 | 0.067, 296 | 0, 297 | 0.133, 298 | 0, 299 | 0.2, 300 | 0, 301 | 1, 302 | 0.278, 303 | 0, 304 | 0.356, 305 | 0, 306 | 0.433, 307 | 0, 308 | 0, 309 | 4.167, 310 | 0 311 | ] 312 | }, 313 | { 314 | "Target": "Parameter", 315 | "Id": "ParamEyeBallX", 316 | "Segments": [ 317 | 0, 318 | 0, 319 | 1, 320 | 0.067, 321 | 0, 322 | 0.133, 323 | 0, 324 | 0.2, 325 | 0, 326 | 1, 327 | 0.278, 328 | 0, 329 | 0.356, 330 | 0, 331 | 0.433, 332 | 0, 333 | 1, 334 | 0.667, 335 | 0, 336 | 0.9, 337 | 0.004, 338 | 1.133, 339 | -0.01, 340 | 1, 341 | 1.4, 342 | -0.025, 343 | 1.667, 344 | -0.43, 345 | 1.933, 346 | -0.43, 347 | 1, 348 | 2.211, 349 | -0.43, 350 | 2.489, 351 | 0.283, 352 | 2.767, 353 | 0.283, 354 | 0, 355 | 4.167, 356 | 0.283 357 | ] 358 | }, 359 | { 360 | "Target": "Parameter", 361 | "Id": "ParamEyeBallY", 362 | "Segments": [ 363 | 0, 364 | 0, 365 | 1, 366 | 0.067, 367 | 0, 368 | 0.133, 369 | 0, 370 | 0.2, 371 | 0, 372 | 1, 373 | 0.278, 374 | 0, 375 | 0.356, 376 | -1, 377 | 0.433, 378 | -1, 379 | 0, 380 | 4.167, 381 | -1 382 | ] 383 | }, 384 | { 385 | "Target": "Parameter", 386 | "Id": "ParamBrowLY", 387 | "Segments": [ 388 | 0, 389 | 0, 390 | 1, 391 | 0.067, 392 | 0, 393 | 0.133, 394 | 0, 395 | 0.2, 396 | 0, 397 | 1, 398 | 0.278, 399 | 0, 400 | 0.356, 401 | 0.19, 402 | 0.433, 403 | 0.19, 404 | 0, 405 | 4.167, 406 | 0.19 407 | ] 408 | }, 409 | { 410 | "Target": "Parameter", 411 | "Id": "ParamBrowRY", 412 | "Segments": [ 413 | 0, 414 | 0, 415 | 1, 416 | 0.067, 417 | 0, 418 | 0.133, 419 | 0, 420 | 0.2, 421 | 0, 422 | 1, 423 | 0.278, 424 | 0, 425 | 0.356, 426 | 0.11, 427 | 0.433, 428 | 0.11, 429 | 0, 430 | 4.167, 431 | 0.11 432 | ] 433 | }, 434 | { 435 | "Target": "Parameter", 436 | "Id": "ParamBrowLX", 437 | "Segments": [ 438 | 0, 439 | 0, 440 | 1, 441 | 0.067, 442 | 0, 443 | 0.133, 444 | 0, 445 | 0.2, 446 | 0, 447 | 1, 448 | 0.278, 449 | 0, 450 | 0.356, 451 | -0.48, 452 | 0.433, 453 | -0.48, 454 | 0, 455 | 4.167, 456 | -0.48 457 | ] 458 | }, 459 | { 460 | "Target": "Parameter", 461 | "Id": "ParamBrowRX", 462 | "Segments": [ 463 | 0, 464 | 0, 465 | 1, 466 | 0.067, 467 | 0, 468 | 0.133, 469 | 0, 470 | 0.2, 471 | 0, 472 | 1, 473 | 0.278, 474 | 0, 475 | 0.356, 476 | 0.29, 477 | 0.433, 478 | 0.29, 479 | 0, 480 | 4.167, 481 | 0.29 482 | ] 483 | }, 484 | { 485 | "Target": "Parameter", 486 | "Id": "ParamBrowLAngle", 487 | "Segments": [ 488 | 0, 489 | 0, 490 | 1, 491 | 0.067, 492 | 0, 493 | 0.133, 494 | 0, 495 | 0.2, 496 | 0, 497 | 1, 498 | 0.278, 499 | 0, 500 | 0.356, 501 | 1, 502 | 0.433, 503 | 1, 504 | 0, 505 | 4.167, 506 | 1 507 | ] 508 | }, 509 | { 510 | "Target": "Parameter", 511 | "Id": "ParamBrowRAngle", 512 | "Segments": [ 513 | 0, 514 | 0, 515 | 1, 516 | 0.067, 517 | 0, 518 | 0.133, 519 | 0, 520 | 0.2, 521 | 0, 522 | 1, 523 | 0.278, 524 | 0, 525 | 0.356, 526 | 0.85, 527 | 0.433, 528 | 0.85, 529 | 0, 530 | 4.167, 531 | 0.85 532 | ] 533 | }, 534 | { 535 | "Target": "Parameter", 536 | "Id": "ParamBrowLForm", 537 | "Segments": [ 538 | 0, 539 | 0, 540 | 1, 541 | 0.067, 542 | 0, 543 | 0.133, 544 | 0, 545 | 0.2, 546 | 0, 547 | 1, 548 | 0.278, 549 | 0, 550 | 0.356, 551 | -0.75, 552 | 0.433, 553 | -0.75, 554 | 0, 555 | 4.167, 556 | -0.75 557 | ] 558 | }, 559 | { 560 | "Target": "Parameter", 561 | "Id": "ParamBrowRForm", 562 | "Segments": [ 563 | 0, 564 | 0, 565 | 1, 566 | 0.067, 567 | 0, 568 | 0.133, 569 | 0, 570 | 0.2, 571 | 0, 572 | 1, 573 | 0.278, 574 | 0, 575 | 0.356, 576 | -0.87, 577 | 0.433, 578 | -0.87, 579 | 0, 580 | 4.167, 581 | -0.87 582 | ] 583 | }, 584 | { 585 | "Target": "Parameter", 586 | "Id": "ParamMouthForm", 587 | "Segments": [ 588 | 0, 589 | 1, 590 | 1, 591 | 0.067, 592 | 1, 593 | 0.133, 594 | 1, 595 | 0.2, 596 | 1, 597 | 1, 598 | 0.278, 599 | 1, 600 | 0.356, 601 | -1, 602 | 0.433, 603 | -1, 604 | 0, 605 | 4.167, 606 | -1 607 | ] 608 | }, 609 | { 610 | "Target": "Parameter", 611 | "Id": "ParamMouthOpenY", 612 | "Segments": [ 613 | 0, 614 | 0, 615 | 1, 616 | 0.067, 617 | 0, 618 | 0.133, 619 | 0, 620 | 0.2, 621 | 0, 622 | 1, 623 | 0.278, 624 | 0, 625 | 0.356, 626 | 1, 627 | 0.433, 628 | 1, 629 | 0, 630 | 4.167, 631 | 1 632 | ] 633 | }, 634 | { 635 | "Target": "Parameter", 636 | "Id": "ParamBodyAngleX", 637 | "Segments": [ 638 | 0, 639 | 0, 640 | 1, 641 | 0.067, 642 | 0, 643 | 0.133, 644 | 0, 645 | 0.2, 646 | 0, 647 | 1, 648 | 0.444, 649 | 0, 650 | 0.689, 651 | 0, 652 | 0.933, 653 | 0, 654 | 1, 655 | 1.211, 656 | 0, 657 | 1.489, 658 | 0, 659 | 1.767, 660 | 0, 661 | 1, 662 | 2.056, 663 | 0, 664 | 2.344, 665 | -6, 666 | 2.633, 667 | -6, 668 | 1, 669 | 3.033, 670 | -6, 671 | 3.433, 672 | 10, 673 | 3.833, 674 | 10, 675 | 0, 676 | 4.167, 677 | 10 678 | ] 679 | }, 680 | { 681 | "Target": "Parameter", 682 | "Id": "ParamBodyAngleY", 683 | "Segments": [ 684 | 0, 685 | 0, 686 | 1, 687 | 0.067, 688 | 0, 689 | 0.133, 690 | 0, 691 | 0.2, 692 | 0, 693 | 0, 694 | 4.167, 695 | 0 696 | ] 697 | }, 698 | { 699 | "Target": "Parameter", 700 | "Id": "ParamBodyAngleZ", 701 | "Segments": [ 702 | 0, 703 | 0, 704 | 1, 705 | 0.067, 706 | 0, 707 | 0.133, 708 | 0, 709 | 0.2, 710 | 0, 711 | 1, 712 | 0.8, 713 | 0, 714 | 1.4, 715 | -2, 716 | 2, 717 | -2, 718 | 1, 719 | 2.456, 720 | -2, 721 | 2.911, 722 | 8.125, 723 | 3.367, 724 | 8.125, 725 | 0, 726 | 4.167, 727 | 8.125 728 | ] 729 | }, 730 | { 731 | "Target": "Parameter", 732 | "Id": "ParamBreath", 733 | "Segments": [ 734 | 0, 735 | 0, 736 | 1, 737 | 0.067, 738 | 0, 739 | 0.133, 740 | 0, 741 | 0.2, 742 | 0, 743 | 0, 744 | 4.167, 745 | 0 746 | ] 747 | }, 748 | { 749 | "Target": "Parameter", 750 | "Id": "ParamShoulder", 751 | "Segments": [ 752 | 0, 753 | 0, 754 | 0, 755 | 4.167, 756 | 0 757 | ] 758 | }, 759 | { 760 | "Target": "Parameter", 761 | "Id": "ParamLeg", 762 | "Segments": [ 763 | 0, 764 | 1, 765 | 1, 766 | 0.667, 767 | 1, 768 | 1.333, 769 | 1, 770 | 2, 771 | 1, 772 | 1, 773 | 2.267, 774 | 1, 775 | 2.533, 776 | 0.948, 777 | 2.8, 778 | 0.948, 779 | 0, 780 | 4.167, 781 | 0.948 782 | ] 783 | }, 784 | { 785 | "Target": "Parameter", 786 | "Id": "ParamArmLA", 787 | "Segments": [ 788 | 0, 789 | 0, 790 | 1, 791 | 0.067, 792 | 0, 793 | 0.133, 794 | 0, 795 | 0.2, 796 | 0, 797 | 1, 798 | 0.233, 799 | 0, 800 | 0.267, 801 | 0, 802 | 0.3, 803 | 0, 804 | 1, 805 | 0.478, 806 | 0, 807 | 0.656, 808 | -10, 809 | 0.833, 810 | -10, 811 | 1, 812 | 0.922, 813 | -10, 814 | 1.011, 815 | -8.846, 816 | 1.1, 817 | -8.846, 818 | 1, 819 | 1.467, 820 | -8.846, 821 | 1.833, 822 | -8.835, 823 | 2.2, 824 | -9.1, 825 | 1, 826 | 2.622, 827 | -9.405, 828 | 3.044, 829 | -10, 830 | 3.467, 831 | -10, 832 | 0, 833 | 4.167, 834 | -10 835 | ] 836 | }, 837 | { 838 | "Target": "Parameter", 839 | "Id": "ParamArmRA", 840 | "Segments": [ 841 | 0, 842 | 0, 843 | 1, 844 | 0.067, 845 | 0, 846 | 0.133, 847 | 0, 848 | 0.2, 849 | 0, 850 | 1, 851 | 0.233, 852 | 0, 853 | 0.267, 854 | 0, 855 | 0.3, 856 | 0, 857 | 1, 858 | 0.478, 859 | 0, 860 | 0.656, 861 | -10, 862 | 0.833, 863 | -10, 864 | 1, 865 | 0.922, 866 | -10, 867 | 1.011, 868 | -8.972, 869 | 1.1, 870 | -8.846, 871 | 1, 872 | 1.467, 873 | -8.328, 874 | 1.833, 875 | -8.2, 876 | 2.2, 877 | -8.2, 878 | 1, 879 | 2.622, 880 | -8.2, 881 | 3.044, 882 | -10, 883 | 3.467, 884 | -10, 885 | 0, 886 | 4.167, 887 | -10 888 | ] 889 | }, 890 | { 891 | "Target": "Parameter", 892 | "Id": "ParamArmLB", 893 | "Segments": [ 894 | 0, 895 | 0, 896 | 0, 897 | 4.167, 898 | 0 899 | ] 900 | }, 901 | { 902 | "Target": "Parameter", 903 | "Id": "ParamArmRB", 904 | "Segments": [ 905 | 0, 906 | 0, 907 | 0, 908 | 4.167, 909 | 0 910 | ] 911 | }, 912 | { 913 | "Target": "Parameter", 914 | "Id": "ParamHairAhoge", 915 | "Segments": [ 916 | 0, 917 | 0, 918 | 1, 919 | 0.067, 920 | 0, 921 | 0.133, 922 | 0, 923 | 0.2, 924 | 0, 925 | 1, 926 | 0.233, 927 | 0, 928 | 0.267, 929 | -5, 930 | 0.3, 931 | -5, 932 | 1, 933 | 0.378, 934 | -5, 935 | 0.456, 936 | 10, 937 | 0.533, 938 | 10, 939 | 1, 940 | 0.633, 941 | 10, 942 | 0.733, 943 | 4, 944 | 0.833, 945 | 4, 946 | 0, 947 | 4.167, 948 | 4 949 | ] 950 | }, 951 | { 952 | "Target": "PartOpacity", 953 | "Id": "PartArmA", 954 | "Segments": [ 955 | 0, 956 | 1, 957 | 0, 958 | 4.17, 959 | 1 960 | ] 961 | }, 962 | { 963 | "Target": "PartOpacity", 964 | "Id": "PartArmB", 965 | "Segments": [ 966 | 0, 967 | 0, 968 | 0, 969 | 4.17, 970 | 0 971 | ] 972 | } 973 | ] 974 | } -------------------------------------------------------------------------------- /ChatWithGPT/game/Resources/Hiyori/motions/Hiyori_m07.motion3.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 3, 3 | "Meta": { 4 | "Duration": 1.9, 5 | "Fps": 30.0, 6 | "Loop": true, 7 | "AreBeziersRestricted": false, 8 | "CurveCount": 32, 9 | "TotalSegmentCount": 121, 10 | "TotalPointCount": 331, 11 | "UserDataCount": 0, 12 | "TotalUserDataSize": 0 13 | }, 14 | "Curves": [ 15 | { 16 | "Target": "Parameter", 17 | "Id": "ParamAngleX", 18 | "Segments": [ 19 | 0, 20 | 0, 21 | 1, 22 | 0.111, 23 | 0, 24 | 0.222, 25 | 0, 26 | 0.333, 27 | 0, 28 | 0, 29 | 1.9, 30 | 0 31 | ] 32 | }, 33 | { 34 | "Target": "Parameter", 35 | "Id": "ParamAngleY", 36 | "Segments": [ 37 | 0, 38 | 0, 39 | 1, 40 | 0.111, 41 | 0, 42 | 0.222, 43 | 0, 44 | 0.333, 45 | 0, 46 | 0, 47 | 1.9, 48 | 0 49 | ] 50 | }, 51 | { 52 | "Target": "Parameter", 53 | "Id": "ParamAngleZ", 54 | "Segments": [ 55 | 0, 56 | 0, 57 | 1, 58 | 0.111, 59 | 0, 60 | 0.222, 61 | 0, 62 | 0.333, 63 | 0, 64 | 1, 65 | 0.444, 66 | 0, 67 | 0.556, 68 | 8, 69 | 0.667, 70 | 8, 71 | 0, 72 | 1.9, 73 | 8 74 | ] 75 | }, 76 | { 77 | "Target": "Parameter", 78 | "Id": "ParamCheek", 79 | "Segments": [ 80 | 0, 81 | 0, 82 | 1, 83 | 0.111, 84 | 0, 85 | 0.222, 86 | 0, 87 | 0.333, 88 | 0, 89 | 0, 90 | 1.9, 91 | 0 92 | ] 93 | }, 94 | { 95 | "Target": "Parameter", 96 | "Id": "ParamEyeLOpen", 97 | "Segments": [ 98 | 0, 99 | 1, 100 | 1, 101 | 0.111, 102 | 1, 103 | 0.222, 104 | 1, 105 | 0.333, 106 | 1, 107 | 1, 108 | 0.378, 109 | 1, 110 | 0.422, 111 | 0, 112 | 0.467, 113 | 0, 114 | 1, 115 | 0.522, 116 | 0, 117 | 0.578, 118 | 1.2, 119 | 0.633, 120 | 1.2, 121 | 1, 122 | 0.744, 123 | 1.2, 124 | 0.856, 125 | 1.2, 126 | 0.967, 127 | 1.2, 128 | 1, 129 | 0.989, 130 | 1.2, 131 | 1.011, 132 | 0, 133 | 1.033, 134 | 0, 135 | 1, 136 | 1.067, 137 | 0, 138 | 1.1, 139 | 1.2, 140 | 1.133, 141 | 1.2, 142 | 1, 143 | 1.167, 144 | 1.2, 145 | 1.2, 146 | 1.2, 147 | 1.233, 148 | 1.2, 149 | 1, 150 | 1.267, 151 | 1.2, 152 | 1.3, 153 | 0, 154 | 1.333, 155 | 0, 156 | 1, 157 | 1.356, 158 | 0, 159 | 1.378, 160 | 1.2, 161 | 1.4, 162 | 1.2, 163 | 0, 164 | 1.9, 165 | 1.2 166 | ] 167 | }, 168 | { 169 | "Target": "Parameter", 170 | "Id": "ParamEyeLSmile", 171 | "Segments": [ 172 | 0, 173 | 0, 174 | 1, 175 | 0.111, 176 | 0, 177 | 0.222, 178 | 0, 179 | 0.333, 180 | 0, 181 | 0, 182 | 1.9, 183 | 0 184 | ] 185 | }, 186 | { 187 | "Target": "Parameter", 188 | "Id": "ParamEyeROpen", 189 | "Segments": [ 190 | 0, 191 | 1, 192 | 1, 193 | 0.111, 194 | 1, 195 | 0.222, 196 | 1, 197 | 0.333, 198 | 1, 199 | 1, 200 | 0.378, 201 | 1, 202 | 0.422, 203 | 0, 204 | 0.467, 205 | 0, 206 | 1, 207 | 0.522, 208 | 0, 209 | 0.578, 210 | 1.2, 211 | 0.633, 212 | 1.2, 213 | 1, 214 | 0.744, 215 | 1.2, 216 | 0.856, 217 | 1.2, 218 | 0.967, 219 | 1.2, 220 | 1, 221 | 0.989, 222 | 1.2, 223 | 1.011, 224 | 0, 225 | 1.033, 226 | 0, 227 | 1, 228 | 1.067, 229 | 0, 230 | 1.1, 231 | 1.2, 232 | 1.133, 233 | 1.2, 234 | 1, 235 | 1.167, 236 | 1.2, 237 | 1.2, 238 | 1.2, 239 | 1.233, 240 | 1.2, 241 | 1, 242 | 1.267, 243 | 1.2, 244 | 1.3, 245 | 0, 246 | 1.333, 247 | 0, 248 | 1, 249 | 1.356, 250 | 0, 251 | 1.378, 252 | 1.2, 253 | 1.4, 254 | 1.2, 255 | 0, 256 | 1.9, 257 | 1.2 258 | ] 259 | }, 260 | { 261 | "Target": "Parameter", 262 | "Id": "ParamEyeRSmile", 263 | "Segments": [ 264 | 0, 265 | 0, 266 | 1, 267 | 0.111, 268 | 0, 269 | 0.222, 270 | 0, 271 | 0.333, 272 | 0, 273 | 1, 274 | 0.356, 275 | 0, 276 | 0.378, 277 | 0, 278 | 0.4, 279 | 0, 280 | 1, 281 | 0.489, 282 | 0, 283 | 0.578, 284 | 0, 285 | 0.667, 286 | 0, 287 | 0, 288 | 1.9, 289 | 0 290 | ] 291 | }, 292 | { 293 | "Target": "Parameter", 294 | "Id": "ParamEyeBallX", 295 | "Segments": [ 296 | 0, 297 | 0, 298 | 1, 299 | 0.111, 300 | 0, 301 | 0.222, 302 | 0, 303 | 0.333, 304 | 0, 305 | 1, 306 | 0.356, 307 | 0, 308 | 0.378, 309 | 0, 310 | 0.4, 311 | 0, 312 | 1, 313 | 0.489, 314 | 0, 315 | 0.578, 316 | 0, 317 | 0.667, 318 | 0, 319 | 0, 320 | 1.9, 321 | 0 322 | ] 323 | }, 324 | { 325 | "Target": "Parameter", 326 | "Id": "ParamEyeBallY", 327 | "Segments": [ 328 | 0, 329 | 0, 330 | 1, 331 | 0.111, 332 | 0, 333 | 0.222, 334 | 0, 335 | 0.333, 336 | 0, 337 | 1, 338 | 0.356, 339 | 0, 340 | 0.378, 341 | 0, 342 | 0.4, 343 | 0, 344 | 1, 345 | 0.489, 346 | 0, 347 | 0.578, 348 | 0, 349 | 0.667, 350 | 0, 351 | 0, 352 | 1.9, 353 | 0 354 | ] 355 | }, 356 | { 357 | "Target": "Parameter", 358 | "Id": "ParamBrowLY", 359 | "Segments": [ 360 | 0, 361 | 0, 362 | 1, 363 | 0.111, 364 | 0, 365 | 0.222, 366 | 0, 367 | 0.333, 368 | 0, 369 | 1, 370 | 0.356, 371 | 0, 372 | 0.378, 373 | 0, 374 | 0.4, 375 | 0, 376 | 1, 377 | 0.489, 378 | 0, 379 | 0.578, 380 | 0.26, 381 | 0.667, 382 | 0.26, 383 | 0, 384 | 1.9, 385 | 0.26 386 | ] 387 | }, 388 | { 389 | "Target": "Parameter", 390 | "Id": "ParamBrowRY", 391 | "Segments": [ 392 | 0, 393 | 0, 394 | 1, 395 | 0.111, 396 | 0, 397 | 0.222, 398 | 0, 399 | 0.333, 400 | 0, 401 | 1, 402 | 0.356, 403 | 0, 404 | 0.378, 405 | 0, 406 | 0.4, 407 | 0, 408 | 1, 409 | 0.489, 410 | 0, 411 | 0.578, 412 | 0.36, 413 | 0.667, 414 | 0.36, 415 | 0, 416 | 1.9, 417 | 0.36 418 | ] 419 | }, 420 | { 421 | "Target": "Parameter", 422 | "Id": "ParamBrowLX", 423 | "Segments": [ 424 | 0, 425 | 0, 426 | 1, 427 | 0.111, 428 | 0, 429 | 0.222, 430 | 0, 431 | 0.333, 432 | 0, 433 | 1, 434 | 0.356, 435 | 0, 436 | 0.378, 437 | 0, 438 | 0.4, 439 | 0, 440 | 1, 441 | 0.489, 442 | 0, 443 | 0.578, 444 | 0, 445 | 0.667, 446 | 0, 447 | 0, 448 | 1.9, 449 | 0 450 | ] 451 | }, 452 | { 453 | "Target": "Parameter", 454 | "Id": "ParamBrowRX", 455 | "Segments": [ 456 | 0, 457 | 0, 458 | 1, 459 | 0.111, 460 | 0, 461 | 0.222, 462 | 0, 463 | 0.333, 464 | 0, 465 | 1, 466 | 0.356, 467 | 0, 468 | 0.378, 469 | 0, 470 | 0.4, 471 | 0, 472 | 1, 473 | 0.489, 474 | 0, 475 | 0.578, 476 | 0.27, 477 | 0.667, 478 | 0.27, 479 | 0, 480 | 1.9, 481 | 0.27 482 | ] 483 | }, 484 | { 485 | "Target": "Parameter", 486 | "Id": "ParamBrowLAngle", 487 | "Segments": [ 488 | 0, 489 | 0, 490 | 1, 491 | 0.111, 492 | 0, 493 | 0.222, 494 | 0, 495 | 0.333, 496 | 0, 497 | 1, 498 | 0.356, 499 | 0, 500 | 0.378, 501 | 0, 502 | 0.4, 503 | 0, 504 | 1, 505 | 0.489, 506 | 0, 507 | 0.578, 508 | 0.26, 509 | 0.667, 510 | 0.26, 511 | 0, 512 | 1.9, 513 | 0.26 514 | ] 515 | }, 516 | { 517 | "Target": "Parameter", 518 | "Id": "ParamBrowRAngle", 519 | "Segments": [ 520 | 0, 521 | 0, 522 | 1, 523 | 0.111, 524 | 0, 525 | 0.222, 526 | 0, 527 | 0.333, 528 | 0, 529 | 1, 530 | 0.356, 531 | 0, 532 | 0.378, 533 | 0, 534 | 0.4, 535 | 0, 536 | 1, 537 | 0.489, 538 | 0, 539 | 0.578, 540 | -0.03, 541 | 0.667, 542 | -0.03, 543 | 0, 544 | 1.9, 545 | -0.03 546 | ] 547 | }, 548 | { 549 | "Target": "Parameter", 550 | "Id": "ParamBrowLForm", 551 | "Segments": [ 552 | 0, 553 | 0, 554 | 1, 555 | 0.111, 556 | 0, 557 | 0.222, 558 | 0, 559 | 0.333, 560 | 0, 561 | 1, 562 | 0.356, 563 | 0, 564 | 0.378, 565 | 0, 566 | 0.4, 567 | 0, 568 | 1, 569 | 0.489, 570 | 0, 571 | 0.578, 572 | 0.33, 573 | 0.667, 574 | 0.33, 575 | 0, 576 | 1.9, 577 | 0.33 578 | ] 579 | }, 580 | { 581 | "Target": "Parameter", 582 | "Id": "ParamBrowRForm", 583 | "Segments": [ 584 | 0, 585 | 0, 586 | 1, 587 | 0.111, 588 | 0, 589 | 0.222, 590 | 0, 591 | 0.333, 592 | 0, 593 | 1, 594 | 0.356, 595 | 0, 596 | 0.378, 597 | 0, 598 | 0.4, 599 | 0, 600 | 1, 601 | 0.489, 602 | 0, 603 | 0.578, 604 | 0.21, 605 | 0.667, 606 | 0.21, 607 | 0, 608 | 1.9, 609 | 0.21 610 | ] 611 | }, 612 | { 613 | "Target": "Parameter", 614 | "Id": "ParamMouthForm", 615 | "Segments": [ 616 | 0, 617 | 1, 618 | 1, 619 | 0.111, 620 | 1, 621 | 0.222, 622 | 1, 623 | 0.333, 624 | 1, 625 | 1, 626 | 0.356, 627 | 1, 628 | 0.378, 629 | 1, 630 | 0.4, 631 | 1, 632 | 1, 633 | 0.489, 634 | 1, 635 | 0.578, 636 | -2, 637 | 0.667, 638 | -2, 639 | 0, 640 | 1.9, 641 | -2 642 | ] 643 | }, 644 | { 645 | "Target": "Parameter", 646 | "Id": "ParamMouthOpenY", 647 | "Segments": [ 648 | 0, 649 | 0, 650 | 1, 651 | 0.111, 652 | 0, 653 | 0.222, 654 | 0, 655 | 0.333, 656 | 0, 657 | 1, 658 | 0.356, 659 | 0, 660 | 0.378, 661 | 0, 662 | 0.4, 663 | 0, 664 | 1, 665 | 0.489, 666 | 0, 667 | 0.578, 668 | 0.75, 669 | 0.667, 670 | 0.75, 671 | 0, 672 | 1.9, 673 | 0.75 674 | ] 675 | }, 676 | { 677 | "Target": "Parameter", 678 | "Id": "ParamBodyAngleX", 679 | "Segments": [ 680 | 0, 681 | 0, 682 | 1, 683 | 0.111, 684 | 0, 685 | 0.222, 686 | 0, 687 | 0.333, 688 | 0, 689 | 1, 690 | 0.444, 691 | 0, 692 | 0.556, 693 | -6, 694 | 0.667, 695 | -6, 696 | 0, 697 | 1.9, 698 | -6 699 | ] 700 | }, 701 | { 702 | "Target": "Parameter", 703 | "Id": "ParamBodyAngleY", 704 | "Segments": [ 705 | 0, 706 | 0, 707 | 1, 708 | 0.111, 709 | 0, 710 | 0.222, 711 | 0, 712 | 0.333, 713 | 0, 714 | 1, 715 | 0.422, 716 | 0, 717 | 0.511, 718 | 10, 719 | 0.6, 720 | 10, 721 | 1, 722 | 0.667, 723 | 10, 724 | 0.733, 725 | -6, 726 | 0.8, 727 | -6, 728 | 1, 729 | 0.833, 730 | -6, 731 | 0.867, 732 | 5, 733 | 0.9, 734 | 5, 735 | 1, 736 | 1.011, 737 | 5, 738 | 1.122, 739 | 0, 740 | 1.233, 741 | 0, 742 | 0, 743 | 1.9, 744 | 0 745 | ] 746 | }, 747 | { 748 | "Target": "Parameter", 749 | "Id": "ParamBodyAngleZ", 750 | "Segments": [ 751 | 0, 752 | 0, 753 | 1, 754 | 0.111, 755 | 0, 756 | 0.222, 757 | 0, 758 | 0.333, 759 | 0, 760 | 1, 761 | 0.444, 762 | 0, 763 | 0.556, 764 | -3, 765 | 0.667, 766 | -3, 767 | 0, 768 | 1.9, 769 | -3 770 | ] 771 | }, 772 | { 773 | "Target": "Parameter", 774 | "Id": "ParamBreath", 775 | "Segments": [ 776 | 0, 777 | 0, 778 | 1, 779 | 0.111, 780 | 0, 781 | 0.222, 782 | 0, 783 | 0.333, 784 | 0, 785 | 0, 786 | 1.9, 787 | 0 788 | ] 789 | }, 790 | { 791 | "Target": "Parameter", 792 | "Id": "ParamShoulder", 793 | "Segments": [ 794 | 0, 795 | -0.062, 796 | 1, 797 | 0.111, 798 | -0.062, 799 | 0.222, 800 | -0.103, 801 | 0.333, 802 | 0, 803 | 1, 804 | 0.589, 805 | 0.238, 806 | 0.844, 807 | 1, 808 | 1.1, 809 | 1, 810 | 0, 811 | 1.9, 812 | 1 813 | ] 814 | }, 815 | { 816 | "Target": "Parameter", 817 | "Id": "ParamArmLA", 818 | "Segments": [ 819 | 0, 820 | 0, 821 | 1, 822 | 0.111, 823 | 0, 824 | 0.222, 825 | 0, 826 | 0.333, 827 | 0, 828 | 1, 829 | 0.478, 830 | 0, 831 | 0.622, 832 | -10, 833 | 0.767, 834 | -10, 835 | 1, 836 | 0.811, 837 | -10, 838 | 0.856, 839 | -8.2, 840 | 0.9, 841 | -8.2, 842 | 0, 843 | 1.9, 844 | -8.2 845 | ] 846 | }, 847 | { 848 | "Target": "Parameter", 849 | "Id": "ParamArmRA", 850 | "Segments": [ 851 | 0, 852 | 0, 853 | 1, 854 | 0.111, 855 | 0, 856 | 0.222, 857 | 0, 858 | 0.333, 859 | 0, 860 | 1, 861 | 0.478, 862 | 0, 863 | 0.622, 864 | -10, 865 | 0.767, 866 | -10, 867 | 1, 868 | 0.811, 869 | -10, 870 | 0.856, 871 | -7.2, 872 | 0.9, 873 | -7.2, 874 | 0, 875 | 1.9, 876 | -7.2 877 | ] 878 | }, 879 | { 880 | "Target": "Parameter", 881 | "Id": "ParamArmLB", 882 | "Segments": [ 883 | 0, 884 | 0, 885 | 1, 886 | 0.111, 887 | 0, 888 | 0.222, 889 | 0, 890 | 0.333, 891 | 0, 892 | 0, 893 | 1.9, 894 | 0 895 | ] 896 | }, 897 | { 898 | "Target": "Parameter", 899 | "Id": "ParamArmRB", 900 | "Segments": [ 901 | 0, 902 | 0, 903 | 1, 904 | 0.111, 905 | 0, 906 | 0.222, 907 | 0, 908 | 0.333, 909 | 0, 910 | 0, 911 | 1.9, 912 | 0 913 | ] 914 | }, 915 | { 916 | "Target": "Parameter", 917 | "Id": "ParamHairAhoge", 918 | "Segments": [ 919 | 0, 920 | 0, 921 | 1, 922 | 0.111, 923 | 0, 924 | 0.222, 925 | 1.9, 926 | 0.333, 927 | 5.2, 928 | 1, 929 | 0.444, 930 | 8.5, 931 | 0.556, 932 | 9.926, 933 | 0.667, 934 | 9.926, 935 | 1, 936 | 0.744, 937 | 9.926, 938 | 0.822, 939 | -10, 940 | 0.9, 941 | -10, 942 | 1, 943 | 0.956, 944 | -10, 945 | 1.011, 946 | 6, 947 | 1.067, 948 | 6, 949 | 1, 950 | 1.144, 951 | 6, 952 | 1.222, 953 | -4, 954 | 1.3, 955 | -4, 956 | 1, 957 | 1.367, 958 | -4, 959 | 1.433, 960 | 0, 961 | 1.5, 962 | 0, 963 | 0, 964 | 1.9, 965 | 0 966 | ] 967 | }, 968 | { 969 | "Target": "PartOpacity", 970 | "Id": "PartArmA", 971 | "Segments": [ 972 | 0, 973 | 1, 974 | 0, 975 | 1.9, 976 | 1 977 | ] 978 | }, 979 | { 980 | "Target": "PartOpacity", 981 | "Id": "PartArmB", 982 | "Segments": [ 983 | 0, 984 | 0, 985 | 0, 986 | 1.9, 987 | 0 988 | ] 989 | } 990 | ] 991 | } --------------------------------------------------------------------------------