Piper Plus โ€” ๋œ์†Œ๋ฆฌ ๊ณผ์ž‰ ์ผ๋ฐ˜ํ™”๋ฅผ ์–ต์ œํ•˜๊ณ  ์‹ ๊ฒฝ๊ณต๋ช…์œผ๋กœ ๊ฐ์ •์„ ํ‘œํ˜„ํ•˜๋Š” ํ•œ๊ธ€ ์ž๋ชจ ์ŒํŒŒ ๋ฐœ์„ฑ ๋ชจ๋ธ

Piper Plus: Korean Neural-Resonance TTS with Fortis-Overgeneralization Suppression, Emotion-Expressive Neural Resonance & Acoustic Jamo Vocalization

๐Ÿ“ข [2026-10-24 ๋ชจ๋ธ ๊ฐ€์ค‘์น˜ ์ „๋ฉด ๊ต์ฒด ์•ˆ๋‚ด] ์–ด์ ˆ ๊ฒฝ๊ณ„๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ๋œ์†Œ๋ฆฌ ๊ณผ์ž‰ ์ผ๋ฐ˜ํ™”๋ฅผ ์–ต์ œํ•œ ์ตœ์‹  Epoch 880 EMA (piper-plus.onnx) ๋ชจ๋ธ๋กœ ๊ต์ฒด๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด์ „์— ๋‹ค์šด๋กœ๋“œํ•˜์‹  ๋ถ„๋“ค์€ ์ตœ์‹  ๋ชจ๋ธ๋กœ ๋‹ค์‹œ ๋ฐ›์•„์ฃผ์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๐Ÿ“ข [2026-10-24 Model Weights Updated] Replaced with the latest Epoch 880 EMA (piper-plus.onnx) model (word-boundary eojeol_boundary CumSum completely removed & excessive fortis/tensification generalization structurally suppressed). If you downloaded an earlier version, please re-download piper-plus.onnx.

โš ๏ธ [๋น„์ƒ์—…์šฉ ์‚ฌ์šฉ ์ œํ•œ ๋ฐ ์ €์ž‘์ž ํ‘œ์‹œ ์˜๋ฌด (Non-Commercial Use Only & Mandatory Attribution)]

  • ๋น„์ƒ์—…์šฉ ์ „์šฉ (์ƒ์—…์  ์‚ฌ์šฉ ์‹œ ๋ณ„๋„ ํ—ˆ๊ฐ€ ํ•„์ˆ˜): ๋ณธ ๋ชจ๋ธ(piper-plus)๊ณผ ํฌํ•จ๋œ ๊ณต๋ช… ์ฃผํŒŒ์ˆ˜ ํ‘œยท์ฝ”๋“œยท๊ฐ€์ค‘์น˜๋Š” ๋น„์ƒ์—…์šฉ(๊ฐœ์ธ ํ•™์Šตยทํ•™์ˆ  ์—ฐ๊ตฌยท๋น„์˜๋ฆฌ ๋ชฉ์ )์œผ๋กœ๋งŒ ๋ฌด๋ฃŒ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ, ์ƒ์—…์  ์‚ฌ์šฉ(์œ ๋ฃŒ ์•ฑยท์›น ์„œ๋น„์Šค ํƒ‘์žฌ, ์˜๋ฆฌ ๋ชฉ์  ์ฝ˜ํ…์ธ  ์ œ์ž‘ยท๋ฐฐํฌ, ๊ธฐ์—…์šฉ ํ™œ์šฉ ๋“ฑ)์€ ๋ฐ˜๋“œ์‹œ ์›์ €์ž‘์ž(watchpen)์˜ ๋ณ„๋„ ์‚ฌ์ „ ํ—ˆ๊ฐ€๋ฅผ ๋ฐ›์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์ €์ž‘์ž ํ‘œ์‹œ ๋ฐ ๊นƒํ—ˆ๋ธŒ ์ฃผ์†Œ ์ฒจ๋ถ€ ์˜๋ฌด: ๋ณธ ๋ชจ๋ธ(piper-plus), ์‹ ๊ฒฝ๊ณต๋ช…(๋ฐœ์Œยท์„ฑ์šฐยท๊ฐ์ • ๊ณต๋ช… ์ฃผํŒŒ์ˆ˜ ํ‘œ), ์ž๋ชจ ์ŒํŒŒ ๋ฐœ์„ฑ ๊ตฌ์กฐ, ์ œ๋กœ๋“€๋ ˆ์ด์…˜ ํƒœ๊ทธ ์ฒด๊ณ„, ๋˜๋Š” ํฌํ•จ ์ฝ”๋“œ/๊ฐ€์ค‘์น˜๋ฅผ **์‘์šฉํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ยทํŒŒ์ƒยท์žฌ๊ฐœ๋ฐœํ•  ๊ฒฝ์šฐ, ๋ฐ˜๋“œ์‹œ ์›์ €์ž‘์ž ์ด๋‹ˆ์…œ(watchpen)๊ณผ ๊ณต์‹ ๊นƒํ—ˆ๋ธŒ ์ฃผ์†Œ(https://github.com/wacthpen/piper-plus)๋ฅผ ํ•จ๊ป˜ ์ฒจ๋ถ€(๋ช…์‹œ)**ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • Non-Commercial Use Only (Separate Permission Required for Commercial Use): This model (piper-plus), its neural resonance tables, weights, and codebase are provided strictly for non-commercial use (personal, academic, and non-profit research). Any commercial use requires prior separate permission from the original author (watchpen).
  • Mandatory Attribution: If you adapt, modify, fine-tune, or redevelop this model, its neural resonance tables, or its codebase, you MUST explicitly credit and include the original author's handle/initials (watchpen / GitHub: wacthpen, Hugging Face: watchpen) AND attach the official GitHub repository URL (https://github.com/wacthpen/piper-plus) in your documentation, model card, and derivative works.

๐ŸŒŸ Piper Plus ํ•ต์‹ฌ ์ •์ฒด์„ฑ (Core Identities)

  1. ๋œ์†Œ๋ฆฌ(๊ฒฝ์Œํ™”) ์ผ๋ฐ˜ํ™” ๊ณผ์ž‰ ์–ต์ œ (Suppression of Excessive Fortis / Tensification Generalization)
    • ๊ธฐ์กด ํ•œ๊ตญ์–ด TTS์™€ ๋ถˆ์™„์ „ํ•œ ์™ธ๋ถ€ G2P๊ฐ€ ๋งŒ์—ฐํ•˜๊ฒŒ ์ผ์œผํ‚ค๋˜ ๊ณ ์งˆ๋ณ‘์ธ **'์˜ˆ์‚ฌ์†Œ๋ฆฌ์˜ ๊ณผ๋„ํ•œ ๋œ์†Œ๋ฆฌ(๊ฒฝ์Œํ™”) ์ผ๋ฐ˜ํ™”'**๋ฅผ ์›์ฒœ ์–ต์ œํ•œ ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค.
    • ์‹ ๊ฒฝ๋ง์˜ ๋ฌธ๋งฅยท์ž„๋ฒ ๋”ฉ ๊ธฐ์–ต์ธต(Memory Layer)์„ ๊ทธ๋Œ€๋กœ ํ†ต๊ณผ์‹œํ‚ค๋ฉด ํ•™์Šต ๋ฐ์ดํ„ฐ ์† ๊ฒฝ์Œํ™” ํ˜„์ƒ์ด ๊ณผ์ž‰ ์ผ๋ฐ˜ํ™”๋˜์–ด ๋ฉ€์ฉกํ•œ ์˜ˆ์‚ฌ์†Œ๋ฆฌ(ํ‰์Œ ใ„ฑ, ใ„ท, ใ…‚, ใ……, ใ…ˆ)๊นŒ์ง€ ๋œ์†Œ๋ฆฌ(ใ„ฒ, ใ„ธ, ใ…ƒ, ใ…†, ใ…‰)๋กœ ์˜ค์—ผ๋ฉ๋‹ˆ๋‹ค. Piper Plus๋Š” ์ถœ๋ ฅยทํ…์ŠคํŠธ ์ธ์ฝ”๋”์—์„œ '๋œ์†Œ๋ฆฌํ™”๋œ ๊ธฐ์–ต์ธต(self.emb)'์„ ํ†ต๊ณผํ•˜์ง€ ์•Š๋„๋ก(100% ๊ณต๋ช… ์ฃผํŒŒ์ˆ˜ ๋Œ€์ฒด ๋ชจ๋“œ๋กœ ์šฐํšŒ) ์„ค๊ณ„ํ•˜๊ณ  ์˜ˆ์‚ฌ์†Œ๋ฆฌ 24๋ฐฐ ๋ณดํ˜ธ ์„ธ๊ธฐํŒ๋ณ„๊ธฐ๋ฅผ ๊ฒฐํ•ฉํ•ด ์‹ ๊ฒฝ๋ง์ด ์ž„์˜๋กœ ๋œ์†Œ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด๋‚ด๋Š” ํ˜„์ƒ์„ ๊ตฌ์กฐ์ ์œผ๋กœ ์™„์ „ํžˆ ํ”ผํ•ด๊ฐ”์œผ๋ฉฐ, ์‹ค์ œ๋กœ ์†Œ๋ฆฌ๊ฐ€ ๋ฐ”๋€Œ์–ด์•ผ ํ•˜๋Š” ๋ถˆ๊ทœ์น™ ๋ฐœ์Œ์€ ๋ฐœ์Œ์‚ฌ์ „(Dictionary)์œผ๋กœ 1:1 ์ •๋ฐ€ ๋Œ€์‘ํ•ฉ๋‹ˆ๋‹ค.
  2. ๊ฐ์ • ํ‘œํ˜„์ด ๊ฐ€๋Šฅํ•œ ์‹ ๊ฒฝ๊ณต๋ช… & ๋ฌธ๋งฅ ๊ฐ์ • ๋ชจ๋ธ ์ž๋™ ๋งคํ•‘ (Emotion-Expressive Neural Resonance & Context-Aware Auto Emotion Mapping)
    • ๋‹จ์ˆœํ•œ ํ‰๋ฉด์  ํ…์ŠคํŠธ ๋‚ญ๋…์„ ๋„˜์–ด, 32๋Œ€ ๊ฐ์ •ยท๋งํˆฌ ์ฒด๊ณ„์™€ **5๋Œ€ ๋ฐœ์„ฑ ๋ฌผ๋ฆฌ ์ถ•(๊ณต๋ช… ๊ท ํ˜•, ์„ฑ๋ฌธ ๊ธด์žฅ๋„, ํ˜ธํก๊ธฐ์‹, ํ”ผ์น˜ยทํฌ๋จผํŠธ ์ด๋™, ๋ฐœํ™” ์†๋„)**์ด ๊ฒฐํ•ฉ๋œ '์‹ ๊ฒฝ๊ณต๋ช…(Neural Resonance)' ์•„ํ‚คํ…์ฒ˜๋กœ ์‚ด์•„ ์ˆจ ์‰ฌ๋Š” ๊ฐ์ • ์—ฐ๊ธฐ๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
    • ํŠนํžˆ ์ž์—ฐ์Šค๋Ÿฌ์šด ๊ฐ์ • ํ‘œํ˜„์„ ์œ ๋„ํ•˜๊ธฐ ์œ„ํ•ด ์ „์šฉ ํ•œ๊ตญ์–ด ๋ฌธ๋งฅ ๊ฐ์ • ๋ถ„๋ฅ˜ ๋ชจ๋ธ(emotion/emotion_int8.onnx)์„ ์ง์ ‘ ํ•™์Šตํ•˜์—ฌ ํƒ‘์žฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ์ผ์ผ์ด ๊ฐ์ • ํƒœ๊ทธ๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ ์ง€ ์•Š์•„๋„, ๊ฐ์ • ๋ชจ๋ธ์ด ๋ฌธ์žฅ์˜ ์•ž๋’ค ๋ฌธ๋งฅ(Context)์„ ์ฝ๊ณ  ์ž๋™์œผ๋กœ ๊ฐ์ • ํƒœ๊ทธยท๋งํˆฌยท๊ฐ์ • ์„ธ๊ธฐยท๋ฐœํ™” ์†๋„ ๋ฐ ๊ฐ์ • ๊ณต๋ช… ์ฃผํŒŒ์ˆ˜(res)๋ฅผ ๋งคํ•‘ํ•ฉ๋‹ˆ๋‹ค.
    • ๋˜ํ•œ ๋Œ€๋ณธ์— ์‚ฝ์ž…๋œ ๊ฐ์ •ยท๋ฐœ์„ฑยท์†Œ๋ฆฌ ํƒœ๊ทธ๋Š” **_ํƒœ๊ทธ์นธ๋–ผ๊ธฐ (Zero-Duration Scatter Compaction)**๋ฅผ ํ†ตํ•ด **ํ”„๋ ˆ์ž„ ์ˆ˜ 0(์ œ๋กœ๋“€๋ ˆ์ด์…˜, Zero-Duration)**์œผ๋กœ ์ฒ˜๋ฆฌ๋˜์–ด, ํƒœ๊ทธ ์ž์ฒด๊ฐ€ ๊ธ€์ž๋‚˜ ๊ตฐ์†Œ๋ฆฌ๋กœ ๋ฐœ์Œ๋˜๋Š” ์ผ ์—†์ด ์˜ค์ง ์ˆœ์ˆ˜ํ•˜๊ฒŒ ๊ฐ์ •๊ณผ ๋ฐœ์„ฑ ํšจ๊ณผ๋งŒ ๋ณธ๋ฌธ ์Œ์„ฑ์— ์ž…ํ˜€์ง‘๋‹ˆ๋‹ค.
  3. ์ž๋ชจ ํ•™์Šต์„ ํ†ตํ•œ ์ŒํŒŒ ๊ธ€์ž ๋ฐœ์„ฑ (Acoustic Character Vocalization via Direct Jamo Learning)
    • "ใ€Žํ›ˆ๋ฏผ์ •์Œ ํ•ด๋ก€๋ณธใ€์— ๋”ฐ๋ผ ์ŒํŒŒ(๋ฐœ์„ฑ ์ฃผํŒŒ์ˆ˜)๋ฅผ ๋งŒ๋“ค์–ด์„œ ์ดˆยท์ค‘ยท์ข…์„ฑ์„ ๋ฐœ์„ฑํ•˜๋‹ˆ ํ•œ๊ตญ์–ด ๋ฐœ์Œ์ด ๊ทธ๋Œ€๋กœ ๋‚˜์˜จ๋‹ค."
    • ์˜์–ด์‹ IPA ์Œ์†Œ ๋ณ€ํ™˜(eSpeak ๋“ฑ)์ด๋‚˜ ์™œ๊ณก๋œ ์Œ์šด ๊ทœ์น™์„ ๊ฑฐ์น˜์ง€ ์•Š๊ณ , ใ€Žํ›ˆ๋ฏผ์ •์Œ ํ•ด๋ก€๋ณธใ€์˜ ์ œ์ž ์›๋ฆฌ์— ๋”ฐ๋ผ ํ•œ๊ธ€ ์ดˆยท์ค‘ยท์ข…์„ฑ ์ž๋ชจ(NFD) ์ž์ฒด๋ฅผ ์ŒํŒŒ(104์ฐจ์› ๊ณ ์œ  ๊ณต๋ช… ์ฃผํŒŒ์ˆ˜)์™€ 1:1๋กœ ์ง์ ‘ ํ•™์Šต์‹œ์ผœ ๊ธ€์ž ๊ทธ๋Œ€๋กœ์˜ ๋ง‘๊ณ  ์ˆœ์ˆ˜ํ•œ ์ŒํŒŒ ๋ฐœ์„ฑ์„ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.
    • (When we construct the acoustic soundwaves / vocal resonance frequencies according to the Hunminjeongeum Haeryebon and vocalize the initial, medial, and final Jamo, authentic Korean pronunciation emerges just as written.)
  4. ์ดˆ๊ฒฝ๋Ÿ‰ ๊ตฌ๋™ & ๋ฐœ์—ด์ด ๊ฑฐ์˜ ์—†์Œ (Ultra-Light & Near-Zero Heat on Mobile / CPU)
    • ๋ฌด๊ฑฐ์šด ๊ฑฐ๋Œ€ ์‹ ๊ฒฝ๋ง ๊ธฐ์–ต์ธต์ด๋‚˜ ํ’€๋ฐด๋“œ HiFi-GAN ๋ณด์ฝ”๋” ๋Œ€์‹ , ์ž๋ชจยท์„ฑ์šฐยท๊ฐ์ • ์ฃผํŒŒ์ˆ˜์˜ ๋‹จ์ผ ์„ ํ˜• ํˆฌ์˜(emb_f, emb_g_res, emb_res) + 4-๋ถ€๋Œ€์—ญ MB-iSTFT-VITS(PQMF) ํ•ฉ์„ฑ ๊ตฌ์กฐ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์—ฐ์‚ฐ๋Ÿ‰์ด ๊ทน๋„๋กœ ๊ฐ€๋ฒผ์›Œ ์Šค๋งˆํŠธํฐ(๋ชจ๋ฐ”์ผ)์ด๋‚˜ ์ผ๋ฐ˜ ๋…ธํŠธ๋ถ CPU์—์„œ๋„ ๋ฐœ์—ด์ด ๊ฑฐ์˜ ์—†์ด ๊ฐ€๋ณ๊ณ  ๋น ๋ฅด๊ฒŒ ์‹ค์‹œ๊ฐ„ ๊ตฌ๋™๋ฉ๋‹ˆ๋‹ค.

๊ธฐ์กด ํŒŒ์ดํผ(Piper)๋ณด๋‹ค ๋‚˜์•„๊ฐ„ ์ 

๊ตฌ๋ถ„ ๊ธฐ์กด Piper Piper Plus (Epoch 880 EMA)
๋œ์†Œ๋ฆฌ(๊ฒฝ์Œํ™”) ์ œ์–ด ๋ฌธ๋งฅ ๊ธฐ์–ต์ธต์ด ๊ฒฝ์Œํ™”๋ฅผ ๊ณผ์ž‰ ์ผ๋ฐ˜ํ™”ํ•˜์—ฌ ํ‰์Œ์ด ๋œ์†Œ๋ฆฌ๋กœ ๋ฌด๋„ˆ์ง **์ถœ๋ ฅ ์ธ์ฝ”๋” ๊ธฐ์–ต์ธต(self.emb) 100% ๋ฏธํ†ต๊ณผ(๋Œ€์ฒด) + ์„ธ๊ธฐํŒ๋ณ„๊ธฐ(์˜ˆ์‚ฌ์†Œ๋ฆฌ ๋ณดํ˜ธ 24๋ฐฐ) + ํ‰์„ฑ ๊ฐ€์ค‘์น˜ ์–ต์ œ(0,2,4)**๋กœ ์˜ˆ์‚ฌ์†Œ๋ฆฌ ๋ณด์กด, ๋ถˆ๊ทœ์น™ ๋ฐœ์Œ์€ ์‚ฌ์ „์œผ๋กœ 1:1 ๋Œ€์‘
ํ•œ๊ตญ์–ด ์ž…๋ ฅ ๋ฐ ๋ฐœ์„ฑ eSpeak IPA ์Œ์†Œ ๋ณ€ํ™˜ (ํ•œ๊ตญ์–ด ๋ฐœ์Œ ๊ทœ์น™ ๋ถ€์ •ํ™•ยท์Œ์†Œ ์™œ๊ณก) ํ•œ๊ธ€ NFD ์ž๋ชจ ์ง๊ฒฐ ์ŒํŒŒ ๋ฐœ์„ฑ โ€” ใ€Žํ›ˆ๋ฏผ์ •์Œ ํ•ด๋ก€๋ณธใ€ ์ œ์ž ์›๋ฆฌ๋ฅผ ๋”ฐ๋ฅธ 104์ฐจ์› ์„ฑ๋„ ๊ณต๋ช… ์ฃผํŒŒ์ˆ˜ ์ง์ ‘ ์ž…๋ ฅ (๊ธ€์ž ๊ธฐ์–ต ์นธ 0)
์™ธ๊ตญ์–ดยท์˜์–ด ํ™•์žฅ ๋ฏธ์ง€์› ๋˜๋Š” ์–ด์ƒ‰ํ•œ ์•ŒํŒŒ๋ฒณ ์ฒ ์ž ์ฝ๊ธฐ ์˜›๋ชจ์Œยท์˜›์ž์Œ(แ„ซ, แ…€, แ„ฝ, แ…—, แ„ผ, ใ†, ใ†Ž ๋“ฑ) ๊ณต๋ช… ์ฃผํŒŒ์ˆ˜๋ฅผ ํ†ตํ•œ ์›์–ด๊ธ‰ ๋งˆ์ฐฐ์Œ/๋ชจ์Œ ๋ฐœ์„ฑ + ๋ฏธํ•™์Šต ์˜๋‹จ์–ด ํ•œ๊ตญ์‹ ๋ฐœ์Œ(์ฝฉ๊ธ€๋ฆฌ์‰ฌ/์•ŒํŒŒ๋ฒณ ์Œ์ฐจ) ์ž๋™ ๋ณ€ํ™˜
์ถœ๋ ฅ ๋””์ฝ”๋” & ๋ฐœ์—ด ๋ฌด๊ฑฐ์šด HiFi-GAN ์ƒ์„ฑ๊ธฐ (๋ชจ๋ฐ”์ผ ๋ฐœ์—ดยท์ง€์—ฐ ๋ฐœ์ƒ) ๋‹จ์ผ ์„ ํ˜• ๊ณต๋ช… ํˆฌ์˜ + 4๋Œ€์—ญ MB-iSTFT ๋””์ฝ”๋”(PQMF 4๋ถ€๋Œ€์—ญ ยท n_fft 16 ยท hop 4) โ€” ์Šค๋งˆํŠธํฐยทCPU์—์„œ ๋ฐœ์—ด์ด ๊ฑฐ์˜ ์—†์ด ์ดˆ๊ฒฝ๋Ÿ‰ ์‹ค์‹œ๊ฐ„ ๊ตฌ๋™
์„ฑ์šฐ ํ‘œํ˜„ ํ™”์ž ID๋งˆ๋‹ค ์™ธ์šด ๊ณ ์ • ์ž„๋ฒ ๋”ฉ(emb_g) ์„ฑ์šฐ ๊ณต๋ช… ์ฃผํŒŒ์ˆ˜ 31๊ฐ€์ง€(spk_feat 28ร—31 โ†’ Linear 31โ†’512) โ€” ์Œ๋†’์ดยท์„ฑ๋„ยทํฌ๋งŒํŠธยท์Œ์ƒ‰ ๊ป์งˆ z ์ ์ˆ˜๋กœ ๋ชฉ์†Œ๋ฆฌ ์ƒ์„ฑ
๊ฐ์ • ํ‘œํ˜„ & ํƒœ๊ทธ ์—†์Œ (๋‹จ์กฐ๋กœ์šด ๋‚ญ๋…) ์ „์šฉ ๋ฌธ๋งฅ ๊ฐ์ • ๋ชจ๋ธ(emotion_int8.onnx) ์ž๋™ ๋งคํ•‘ + ์‹ ๊ฒฝ๊ณต๋ช… res(๋…ธ๋ธŒ 3 + ๊ผฌ๋ฆฌ 15) + ๊ฐ์ • ํƒœ๊ทธ ์ œ๋กœ๋“€๋ ˆ์ด์…˜(๊ธธ์ด 0, ์†Œ๋ฆฌ ์—†์ด ๊ฐ์ •๋งŒ ์ฃผ์ž…)
ํ˜ธํก ๋ฐ ๋Š์–ด ์ฝ๊ธฐ ์–ด์ ˆ๋งˆ๋‹ค ๊ธฐ๊ณ„์  ๋‹จ์ ˆ ๋˜๋Š” ๊ธด ๋ฌธ์žฅ ํ†ต์งธ ํ•ฉ์„ฑ ์‹œ ์–ต์–‘ ๋ถ•๊ดด ์–ด์ ˆ ๊ฒฝ๊ณ„(eojeol_boundary) ์™„์ „ ์ œ๊ฑฐ + ํ‘œ์ค€ ์ •์† 0.85 & ๊ฐ์ • ๋น ๋ฅด๊ธฐ(1.08/1.0/0.93) + ์ข…๊ฒฐํ˜•ยท์—ฐ๊ฒฐํ˜• ์–ด๋ฏธ ๊ฐˆ๋ผ์ฝ๊ธฐ(0.01์ดˆ ์ด์Œ)

๐Ÿ›๏ธ ํ•ต์‹ฌ ๊ธฐ์ˆ  ์•„ํ‚คํ…์ฒ˜ (Core Technical Architecture)

1. 3๋Œ€ ์™„์ „๊ณต๋ช… ์•„ํ‚คํ…์ฒ˜ (๋ฐœ์Œ๊ณต๋ช… ยท ์„ฑ์šฐ๊ณต๋ช… ยท ๊ฐ์ •๊ณต๋ช…) & ใ€Žํ›ˆ๋ฏผ์ •์Œ ํ•ด๋ก€๋ณธใ€ ์ฃผํŒŒ์ˆ˜ ๋งคํ•‘

"ใ€Žํ›ˆ๋ฏผ์ •์Œ ํ•ด๋ก€๋ณธใ€์— ๋”ฐ๋ผ ์ŒํŒŒ(๋ฐœ์„ฑ ์ฃผํŒŒ์ˆ˜)๋ฅผ ๋งŒ๋“ค์–ด์„œ ์ดˆยท์ค‘ยท์ข…์„ฑ์„ ๋ฐœ์„ฑํ•˜๋‹ˆ ํ•œ๊ตญ์–ด ๋ฐœ์Œ์ด ๊ทธ๋Œ€๋กœ ๋‚˜์˜จ๋‹ค." "ใ€Žํ›ˆ๋ฏผ์ •์Œ ํ•ด๋ก€๋ณธใ€์ด ๋ฐํžŒ ๋ฐœ์„ฑ๋ฒ•์„ ๊ทธ๋Œ€๋กœ ์ฃผํŒŒ์ˆ˜๋กœ ๋ณธ๋–  ๋งž์ถ˜ ์ŒํŒŒ ๋ฐœ์„ฑ ๋ชจ๋ธ" (When we construct the acoustic soundwaves / vocal resonance frequencies according to the Hunminjeongeum Haeryebon and vocalize the initial, medial, and final Jamo, authentic Korean pronunciation emerges just as written.)

๋ณดํ†ต์˜ ์Œ์„ฑ ํ•ฉ์„ฑ ๋ชจ๋ธ์€ ๊ธ€์ž ํ•˜๋‚˜, ํ™”์ž ํ•˜๋‚˜, ๊ฐ์ • ํ•˜๋‚˜๋งˆ๋‹ค ์ž„๋ฒ ๋”ฉ ์นธ์„ ๋‘๊ณ  ๊ทธ ๊ฐ’์„ ๋‹จ์ˆœ ์•”๊ธฐํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด **Piper Plus (์™„์ „๊ณต๋ช…ํŒ Epoch 880 EMA)**๋Š” ๊ธ€์žยท์„ฑ์šฐยท๊ฐ์ •์˜ ๊ฐœ๋ณ„ ๊ธฐ์–ต ์นธ์„ ๋ชจ๋‘ ๋น„์šฐ๊ณ , ใ€Žํ›ˆ๋ฏผ์ •์Œ ํ•ด๋ก€๋ณธ(่จ“ๆฐ‘ๆญฃ้Ÿณ ่งฃไพ‹ๆœฌ)ใ€์ด ๋ฐํžŒ ๋ฐœ์„ฑ ๊ธฐ๊ด€์˜ ๊ณผํ•™์  ์ œ์ž ์›๋ฆฌ๋ฅผ ํ˜„๋Œ€ ์Œํ–ฅ๋ฌผ๋ฆฌํ•™์˜ ์„ฑ๋„(Vocal Tract) ๊ณต๋ช… ์ฃผํŒŒ์ˆ˜๋กœ ๊ทธ๋Œ€๋กœ ์˜ฎ๊ธด 3๋Œ€ ์™„์ „๊ณต๋ช… ์•„ํ‚คํ…์ฒ˜๋กœ ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

  1. ๋ฐœ์Œ๊ณต๋ช… (jamo_feat 544ร—104 โ†’ emb_f Linear(104 โ†’ 192, bias=False)):
    • ๊ธ€์ž๋ณ„ ์ž„๋ฒ ๋”ฉ ๊ธฐ์–ต ์นธ(self.emb)์„ ์“ฐ์ง€ ์•Š๊ณ , ใ€Žํ›ˆ๋ฏผ์ •์Œ ํ•ด๋ก€๋ณธใ€์˜ ์ œ์ž ์›๋ฆฌ๋ฅผ ๋ณธ๋–  ๋…น์Œ์—์„œ ์‹ค์ธกํ•œ **104์ฐจ์› ์ž๋ชจ ์„ฑ์งˆ ํ–‰๋ ฌ(jamo_feat: ์•ž 80์นธ์€ ํ‘œ_๋ฐ”ํƒ•.json ์ž๋ชจ ๋ฐœ์Œ ๊ณต๋ช… ์ฃผํŒŒ์ˆ˜, ๋’ค 24์นธ์€ ํ‘œ_ํƒœ๊ทธ.json ์†Œ๋ฆฌยท๋ฐœ์„ฑยท์ˆ˜์‹ ํƒœ๊ทธ ์ฃผํŒŒ์ˆ˜)**์— ๋‹จ์ผ ๊ณต์œ  ์„ ํ˜• ๋ณ€ํ™˜(emb_f)๋งŒ ๊ฑฐ์ณ ํ…์ŠคํŠธ ์ธ์ฝ”๋”๋กœ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค(resonance/jamo_features.json).
  2. ์„ฑ์šฐ๊ณต๋ช… (spk_feat 28ร—31 โ†’ emb_g_res Linear(31 โ†’ 512)):
    • ์„ฑ์šฐ๋ณ„ ์ž„๋ฒ ๋”ฉ ๊ธฐ์–ต ์นธ(emb_g)์„ ์•„์˜ˆ ๋งŒ๋“ค์ง€ ์•Š๊ณ , ์„ฑ์šฐ๋งˆ๋‹ค ๋…น์Œ์—์„œ ์‹ค์ธกํ•œ **31๊ฐ€์ง€ ๋ฐœ์„ฑ ์ฃผํŒŒ์ˆ˜ ๋ฒกํ„ฐ(z: ์Œ๋†’์ด, F1F4, B1B3, ์„ฑ๋„ ๊ธธ์ด, ์ €์—ญ/ํ‰์„ฑ, ๋ฐฐ์šฐ ํฌ๋งŒํŠธ, ๋ฐ๊ธฐ ์ค‘์‹ฌ, ๊ธฐ์šธ๊ธฐ, H1-H2, CPP, HNR, MFCC ๊ป์งˆ 1~12)**์— ๋‹จ์ผ ๊ณต์œ  ์„ ํ˜• ์‹(Wยทz + b)๋งŒ ์ ์šฉํ•ด ์Œ์ƒ‰ ์กฐ๊ฑด g๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค(resonance/speaker_features.json).
  3. ๊ฐ์ •๊ณต๋ช… (tag_dummy=True ๋นˆ์นธ 250 + ์ฃผํŒŒ์ˆ˜ํƒœ๊ทธ์นธ + res 34์ฐจ์›):
    • ๊ฐ์ •ยท๋งํˆฌ ํƒœ๊ทธ ๋ฒˆํ˜ธ๋งˆ๋‹ค ๋”ฐ๋กœ ์™ธ์šฐ๋Š” ๊ธฐ์–ต ์นธ์„ ์—†์• ๊ณ  ๋ชจ๋‘ ๋นˆ ์นธ(tag_dummy_id = 250)์œผ๋กœ ๋ณด๋‚ธ ๋’ค, res 34์ฐจ์› ์‹ ๊ฒฝ๊ณต๋ช… ๋ฒกํ„ฐ โ€” res_g_dims = 3 ๊ณต๋ช… ๋…ธ๋ธŒ(์„ฑ๋„ ์ฒ™๋„ ยท ์ €์—ญ/ํ‰์„ฑ ยท ๋ฐฐ์šฐ ํฌ๋งŒํŠธ) + res_g_tail = 15 ๊ฐ์ • ๊ณต๋ช… ๊ผฌ๋ฆฌ(eGeMAPS 14๊ฐ€์ง€ ์Œ์งˆ ์ฃผํŒŒ์ˆ˜ ๋ณ€ํ™”๋Ÿ‰ + ์ฝง์†Œ๋ฆฌ ์„ž์ž„ A1-P0) โ€” ๋กœ๋งŒ ์ž‘๋™ํ•˜๊ฒŒ ํ•˜์—ฌ ๋ชจ๋“  ์„ฑ์šฐ์—๊ฒŒ ๊ฐ์ • ํ‘œํ˜„์ด ๊ณ ๋ฅด๊ฒŒ ์ „์ด๋˜๋„๋ก ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค(emotion/emotion_resonance.json).
๊ณต๋ช… ๊ฐˆ๋ž˜ ๋ชจ๋ธ ๋‚ด๋ถ€ ๋ณ€ํ™˜ ๊ตฌ์กฐ ์ฐจ์›(์นธ ์ˆ˜) ์„ค์ • ํ‘œ ํŒŒ์ผ
๋ฐœ์Œ๊ณต๋ช… (์ž๋ชจ) jamo_feat (544ร—104) โ†’ emb_f (Linear 104โ†’192, bias=False) โ€” self.emb 100% ๋Œ€์ฒด 104 (๋ฐœ์Œ 80 + ํƒœ๊ทธ 24) resonance/jamo_features.json
์„ฑ์šฐ๊ณต๋ช… (ํ™”์ž) spk_feat (28ร—31) โ†’ emb_g_res (Linear 31โ†’512) โ€” ํ™”์ž ์ž„๋ฒ ๋”ฉ emb_g ์—†์Œ 31 resonance/speaker_features.json
๊ฐ์ •๊ณต๋ช… (๊ฐ์ •) res ([b, 34]): ๊ณต๋ช… ๋…ธ๋ธŒ 3 ([0:3]) + ๊ฐ์ • ๊ผฌ๋ฆฌ 15 ([19:34], eGeMAPS 14 + ์ฝง์†Œ๋ฆฌ A1-P0) 3 + 15 (res 34) emotion/emotion_resonance.json

1-1. ใ€Žํ›ˆ๋ฏผ์ •์Œ ํ•ด๋ก€๋ณธใ€ ์ŒํŒŒ ๋ฐœ์„ฑ์˜ ์ฝ”๋“œ์ ยท์ˆ˜ํ•™์  ์‹ค์ฆ (ํ‘œ_๋ฐ”ํƒ•.json ยท ํ•™์Šต์ฃผํŒŒ์ˆ˜ํ‘œ๋งŒ๋“ค๊ธฐ.py ยท ํ•ด๋ก€๋ณธ๋ฐ›์นจ.py)

๋น„์œ ๊ฐ€ ์•„๋‹ˆ๋ผ ์‹ค์ œ ์‹ ๊ฒฝ๋ง์˜ ์ˆ˜ํ•™์  ์—ฐ์‚ฐ ์ž์ฒด๊ฐ€ ใ€Žํ›ˆ๋ฏผ์ •์Œ ํ•ด๋ก€๋ณธใ€์˜ ์›๋ฆฌ ๊ทธ๋Œ€๋กœ๋งŒ ๋Œ์•„๊ฐ€๋„๋ก ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

โ‘  ๊ธ€์ž ์ด๋ฆ„ํ‘œ(0/1 ๊ธฐํ˜ธ ์นธ) 49๊ฐœ ์ „๋Ÿ‰ 0 ์ œ๊ฑฐ โ€” ์˜ค์ง 31๊ฐœ ๋ฌผ๋ฆฌ์  ์ŒํŒŒ ์ฃผํŒŒ์ˆ˜๋งŒ ์ž‘๋™

  • resonance/jamo_features.json(ํ‘œ_๋ฐ”ํƒ•.json 80์—ด + ํƒœ๊ทธ ์ฃผํŒŒ์ˆ˜ 24์—ด = 104์—ด)์˜ ๊ธฐ๋ณธ 80๊ฐœ ์—ด์„ ๊ฒ€์‚ฌํ•˜๋ฉด, ์ดˆ๊ธฐ ์„ค๊ณ„์— ์žˆ๋˜ ๊ธ€์žใ„ฑ~ใ…Ž, ์ž๋ฆฌ:์–ด๊ธˆ๋‹ˆ/ํ˜€/์ž…์ˆ , ๋ฐฉ์‹:๋ง‰ํž˜/๊ฐˆ๋ฆผ, ์„ธ๊ธฐ:์˜ˆ์‚ฌ/๊ฑฐ์„ผ/๋œ ๋“ฑ **๊ธฐํ˜ธ ํ‘œ์‹œ(One-Hot) ์นธ 49๊ฐœ๋Š” ์ „๋Ÿ‰ 0.0**์œผ๋กœ ๋น„์›Œ์ ธ ์žˆ์Šต๋‹ˆ๋‹ค (assert all(v == 0 ... if ์ด๋ฆ„[i] not in ์žฐ)).
  • ๋™์‹œ์— models.py(jamo_feature_mode = "๋Œ€์ฒด")์—์„œ ๋ชจ๋“  ์ž๋ชจ ํ† ํฐ์€ ๊ฐœ๋ณ„ ๊ธ€์ž ์ž„๋ฒ ๋”ฉ ๊ธฐ์–ต ์นธ(self.emb(x))์„ 100% ๋ฒ„๋ฆฌ๊ณ , ์˜ค์ง self.emb_f(jamo_feat[x])๋งŒ ์ธ์ฝ”๋”๋กœ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค.
  • ์ฆ‰, ์‹ ๊ฒฝ๋ง์€ ์ง€๊ธˆ ๋“ค์–ด์˜จ ๊ธ€์ž๊ฐ€ 'ใ„ฑ'์ธ์ง€ 'ใ…'์ธ์ง€ ๋ฒˆํ˜ธ๋‚˜ ๊ธฐํ˜ธ๋กœ๋Š” ์ „ํ˜€ ์•Œ ์ˆ˜ ์—†๊ณ , ์˜ค์ง 31๊ฐœ์˜ ๋ฌผ๋ฆฌ์  ์ŒํŒŒ ์ฃผํŒŒ์ˆ˜ ์ˆ˜์น˜๋งŒ ๋ณด๊ณ  ์†Œ๋ฆฌ๋ฅผ ํ•ฉ์„ฑํ•ฉ๋‹ˆ๋‹ค.

โ‘ก ์ดˆ์„ฑยท์ค‘์„ฑยท์ข…์„ฑ 31๊ฐœ ์ฃผํŒŒ์ˆ˜ ์นธ๊ณผ ใ€Žํ›ˆ๋ฏผ์ •์Œ ํ•ด๋ก€๋ณธใ€ ๊ตฌ์ ˆ์˜ 1:1 ์ง๊ฒฐ

  1. ์ดˆ์„ฑ 16์นธ โ€” ํ•ด๋ก€๋ณธ ๅˆ่ฒๆœ‰็™ผๅ‹•ไน‹็พฉ (์ดˆ์„ฑ์€ ์†Œ๋ฆฌ๋ฅผ ์ผ์œผํ‚จ๋‹ค) & ์˜ค์Œ(์•„ยท์„คยท์ˆœยท์น˜ยทํ›„)ยท๊ฐ€ํš
    • ์กฐ์Œ ์œ„์น˜(์ž…์ˆ ์†Œ๋ฆฌ ใ…‚/ใ…์€ ์ €์—ญ์— ํผ์ง€๊ณ  ์–ด๊ธˆ๋‹ˆ์†Œ๋ฆฌ ใ„ฑ/ใ…‹์€ ์ค‘์—ญ์— ๋ชฐ๋ฆฌ๋Š” ์ดˆ์„ฑํ„ฐ์ง์ €์ค‘๋น„ยท์ค‘๊ณ ๋น„, ์ดˆ์„ฑํ„ฐ์งkHz, ์ดˆ์„ฑํ„ฐ์ง๋ด‰์šฐ๋ฆฌ/ํผ์งkHz, ์ดˆ์„ฑF2/F3ํœจ)์™€ ๊ฐ€ํš(์ „์ฒญยท์ฐจ์ฒญยท์ „ํƒ์— ๋”ฐ๋ฅธ ์ดˆ์„ฑ์ˆจ, ์ดˆ์„ฑ์ˆจ์†Œ๋ฆฌkHz/๋ด‰์šฐ๋ฆฌ/ํผ์ง/์ €์ค‘๋น„/์ค‘๊ณ ๋น„, ์ดˆ์„ฑ์„ธ๊ธฐ, ์ดˆ์„ฑ๋’ค์Œ๋†’์ด, ์ดˆ์„ฑ์šธ๋ฆผkHz) ์‹ค์ธก์น˜๋งŒ ์ž…๋ ฅ๋ฉ๋‹ˆ๋‹ค.
    • ํŠนํžˆ ์ดˆ์„ฑ ใ…‡์„ 0์œผ๋กœ ๋น„์› ์„ ๋•Œ ๊ธฐ์–ต ์นธ(self.emb)์œผ๋กœ ๋น ์ ธ ๋ชจ์Œ ์—ฐ์† ๋ฐœ์Œ(์•„์•„โ†’์•„, ์œผ์•—โ†’์™€)์ด ๋ญ‰๊ฐœ์ง€๋˜ ํ˜„์ƒ์„, ํ•ด๋ก€๋ณธ ์ œ์žํ•ด ์›๋ฌธ ใ€Œใ…‡ใ€‚ๅ–‰้Ÿณใ€‚ๅฆ‚ๆฌฒๅญ—ๅˆ็™ผ่ฒใ€(๋ชฉ์ฒญ์—์„œ ์†Œ๋ฆฌ๋ฅผ ์—ฌ๋Š” ํ›„์Œ) ๊ทธ๋Œ€๋กœ ์ฝ”๋“œ์— ์ ์šฉํ•ด ์‹ค์ œ ๋ชฉ์ฒญ ๋ฐœ์„ฑ ์ฃผํŒŒ์ˆ˜๋ฅผ ๋„ฃ์–ด ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.
  2. ์ค‘์„ฑ 7์นธ โ€” ์ฒœยท์ง€ยท์ธ ๋‹จ๋ชจ์Œ๊ณผ ํ•ฉ์šฉ(์ด์ค‘๋ชจ์Œ)์˜ ํฌ๋จผํŠธ ์ถœ๋ฐœยท๋„์ฐฉ ๊ถค์ 
    • ๋ชจ์Œ ์‹œ์ž‘ 10% ์ง€์ (๊ณต๋ช…F1ยทF2ยทF3์ถœ๋ฐœ)๊ณผ 75% ์ง€์ (๊ณต๋ช…F1ยทF2ยทF3๋„์ฐฉ), ๋ชจ์Œ๊ธธ์ด 7์นธ๋งŒ์œผ๋กœ ๋‹จ๋ชจ์Œ๊ณผ ํ•ฉ์šฉ ์ด์ค‘๋ชจ์Œ(ใ…˜, ใ…™, ใ…, ใ…ž, ใ…ข ๋“ฑ)์˜ ์„ฑ๋„ ๊ณต๋ช… ์ด๋™ ๊ถค์ ์„ ๊ทธ๋Œ€๋กœ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.
  3. ์ข…์„ฑ(๋ฐ›์นจ) 8์นธ + ์—ฐ์Œ ๋„˜์–ด๊ฐ 16์นธ โ€” ํ•ด๋ก€๋ณธ ์ข…์„ฑํ•ดยทํ•ฉ์žํ•ด ์›๋ฌธ ๊ตฌํ˜„์œผ๋กœ ๋ฐ›์นจ ๋ฏธ๋ถ„ํ™” ํ•ด๊ฒฐ (ํ•ด๋ก€๋ณธ๋ฐ›์นจ.py)
    • ์—ํญ 632 ๋‹น์‹œ ๋‹จ์ˆœ ๋ชจ์Œ ์ค‘์•™๊ฐ’ ๋น„์œจ์„ ๋„ฃ์—ˆ์„ ๋•Œ๋Š” ๊ฐ„ยท๊ฐยท๊ฐ•์ด ์†Œ๋ฆฌ๋กœ ๊ฐˆ๋ฆฌ์ง€ ์•Š๊ณ  ๋ชจ๋‘ ์นธ์œผ๋กœ ๋ฐœ์Œ๋˜์—ˆ์œผ๋‚˜(๋ 40% ์ฐจ์ด 3~8dB), ํ•ด๋ก€๋ณธ์˜ 5๊ฐ€์ง€ ์›๋ฆฌ๋ฅผ ์ฝ”๋“œ๋กœ ๊ตฌํ˜„ํ•ด ๋„ฃ์ž ๋ฐ›์นจ ๋ฐœ์„ฑ์ด ์ •ํ™•ํžˆ ๋ถ„๋ฆฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค(์ž…๋ ฅ ๊ฑฐ๋ฆฌ ใ„ดโ†”ใ…‡ 0.98โ†’1.95, ใ„ฑโ†”ใ…‚ 1.45โ†’3.72):
      • ็ต‚่ฒๅพฉ็”จๅˆ่ฒ & ใ†่ˆ‡ใ„ฑ็ˆฒๅฐ ยท ่ˆŒไน‹ใ„ดใ„ท ยท ่„ฃไน‹ใ…ใ…‚ (์ดˆ์„ฑ์„ ๋‹ค์‹œ ์“ฐ๋ฉฐ ์ฝง์†Œ๋ฆฌ์™€ ๋ง‰ํž˜์†Œ๋ฆฌ๋Š” ์กฐ์Œ ์ž๋ฆฌ๊ฐ€ ๊ฐ™๋‹ค): ์–ด๊ธˆ๋‹ˆ(ใ„ฑยทใ† 1,503Hz), ํ˜€(ใ„ดยทใ„ท 1,875Hz, ใ„น 1,813Hz), ์ž…์ˆ (ใ…ยทใ…‚ 559Hz) ์ง์„ ๋ฌถ์–ด ๊ตฌํ•œ ๋กœ์ปค์Šค ์ž๋ฆฌ ์ฃผํŒŒ์ˆ˜(z2์ง, z3์ง)๋ฅผ ๋ฐ›์นจF2ํœจยทF3ํœจ์— ์ž…๋ ฅ.
      • ๅ…ซๅญ—ๅฏ่ถณ็”จ (8์ข…์„ฑ ๊ฐ€์กฑ์šฉ): ใ„ฒยทใ…‹โ†’ใ„ฑ, ใ……ยทใ…†ยทใ…ˆยทใ…Šยทใ…Œโ†’ใ„ท, ใ…โ†’ใ…‚์œผ๋กœ 8์ข…์„ฑ ๋Œ€ํ‘œ ์ž๋ฆฌ ์ฃผํŒŒ์ˆ˜๋ฅผ ๋งคํ•‘(ใ…Ž์€ ํ›„์Œ์ด๋ผ ์ž…์•ˆ ์ž๋ฆฌ ํœจ 0).
      • ็ต‚่ฒๆœ‰ๆญขๅฎšไน‹็พฉ & ไธๆทธไธๆฟไน‹ๅญ— ๅ…ถ่ฒไธๅŽฒ(่ˆ’็ทฉ) / ๅ…จๆทธโ€ฆๅ…ถ่ฒ็ˆฒๅŽฒ(ไฟƒๆ€ฅ): ๋ฐ›์นจ ์นธ ์ž์ฒด์—๋Š” ํ„ฐ์งยท์ˆจ์„ ๋‘์ง€ ์•Š๊ณ , ๋ถˆ์ฒญ๋ถˆํƒ(ใ„ดยทใ„นยทใ…ยทใ…‡)์—๋งŒ ์šธ๋ฆผ(๋ฐ›์นจ์šธ๋ฆผkHz)๊ณผ ๋น„๊ฐ• ๋ฐ˜๊ณต๋ช…(๋ฐ›์นจ์ฝง์†Œ๋ฆฌ๊ณจkHz: ใ„ด 1.38 / ใ… 1.30 / ใ…‡ 1.73kHz)์„ ๋ถ€์—ฌํ•˜๋ฉฐ ๋ง‰ํž˜ ๋ฐ›์นจ(๋‹ซํž˜๋น„ > 0.5)์€ ์šธ๋ฆผ์„ 0์œผ๋กœ ์„ค์ •.
      • ็ต‚่ฒไบŒๅญ—ไธ‰ๅญ—ๅˆ็”จ ่‡ชๅทฆ่€Œๅณ (ํ•ฉ์žํ•ด): ๊ฒน๋ฐ›์นจ(ใ„ณ, ใ„ต, ใ„ถ, ใ„บ, ใ„ป, ใ„ผ, ใ„ฝ, ใ„พ, ใ„ฟ, ใ…€, ใ…„)์€ ์™ผ์ชฝ ์ฒซ ์ž์Œ ์ž๋ฆฌ(๋ฐ›์นจF2ํœจยทF3ํœจ)๋กœ ๋“ค์–ด๊ฐ€ ์˜ค๋ฅธ์ชฝ ๋‘˜์งธ ์ž์Œ ์ž๋ฆฌ(๋ฐ›์นจ๋‘˜์งธF2ํœจยทF3ํœจ)๋กœ ๋‹ซํžˆ๊ณ , ๊ธธ์ด๋Š” ๋‘ ์†Œ๋ฆฌ์˜ ํ•ฉ์œผ๋กœ ๊ณ„์‚ฐํ•˜๋ฉฐ, ๋ชจ์Œ ์•ž์—์„œ ๋‹ค์Œ ์Œ์ ˆ ์ฒซ์†Œ๋ฆฌ๋กœ ๋ฐœ๋™ํ•˜๋Š” ์—ฐ์Œ(๋„˜์–ด๊ฐ)์€ ๋ฐ›์นจ ์ค„์˜ ์ดˆ์„ฑ 16์นธ์— ํ•จ๊ป˜ ์‹ค์–ด ๋ชจ๋ธ์ด ๋ฌธ๋งฅ์— ๋”ฐ๋ผ ์„ ํƒํ•˜๊ฒŒ ํ•จ.

โ‘ข ์˜›๊ธ€์ž(์˜์–ด ๋งˆ์ฐฐ์Œ)๊นŒ์ง€ ๋™์ผํ•œ ์ฃผํŒŒ์ˆ˜ ์‹ ํ•˜๋‚˜๋กœ ๋ฐœ์„ฑ

  • ํ•œ๊ตญ์–ด ๋ณธ๋ฌธ ๋…น์Œ์— ์—†๋Š” ์˜›์ž์Œ แ…—[f], แ„ซ[v], แ…€[z], แ„ผ[ฮธ], แ„ฝ[รฐ](๋ฒˆํ˜ธ 384~388) ์—ญ์‹œ ๊ธ€์ž ๊ธฐ์–ต ์นธ ์—†์ด ์ดˆ์„ฑ 16์นธ์— ์˜์–ด ๋งˆ์ฐฐ์Œ ์‹ค์ธก ์ฃผํŒŒ์ˆ˜๋งŒ ์ฑ„์›Œ ๋„ฃ์—ˆ์„ ๋•Œ ๋™์ผํ•œ emb_f ์‹ ํ•˜๋‚˜๋กœ ๋ฐœ์„ฑ๋ฉ๋‹ˆ๋‹ค.

2. ์™œ ๋œ์†Œ๋ฆฌ๋ฅผ ํ”ผํ•ด๊ฐˆ ์ˆ˜ ์žˆ์—ˆ๋Š”๊ฐ€? โ€” ์ž๋ชจ ๊ธฐ์–ต์ธต(self.emb) 100% ์šฐํšŒ & ์„ธ๊ธฐํŒ๋ณ„๊ธฐ 24๋ฐฐ ๋ณดํ˜ธ & ๋ถˆ๊ทœ์น™ ๋ฐœ์Œ ์‚ฌ์ „ ๋Œ€์‘

๊ธฐ์กด ํ•œ๊ตญ์–ด ์‹ ๊ฒฝ๋ง TTS๋“ค์ด ์˜ˆ์‚ฌ์†Œ๋ฆฌ๋ฅผ ๊ณผ๋„ํ•˜๊ฒŒ ๋œ์†Œ๋ฆฌ๋กœ ๋ฐœ์Œํ•˜๋Š” ๊ทผ๋ณธ ์›์ธ์€ ๊ธ€์ž๋ณ„ ์ž„๋ฒ ๋”ฉ ๊ธฐ์–ต์ธต(self.emb)๊ณผ ๋ฌธ๋งฅ ๊ธฐ์–ต์˜ ๊ฒฝ์Œํ™” ๊ณผ์ž‰ ์ผ๋ฐ˜ํ™”์— ์žˆ์Šต๋‹ˆ๋‹ค. ํ•™์Šต ๋ฐ์ดํ„ฐ์— ์ธ๊ถŒ[์ธ๊ฟ˜], ์†๊ฐ€๋ฝ[์†๊นŒ๋ฝ]์ฒ˜๋Ÿผ ํ‘œ๊ธฐ๋Š” ์˜ˆ์‚ฌ์†Œ๋ฆฌ(ใ„ฑ)์ธ๋ฐ ๋…น์Œ์€ ๋œ์†Œ๋ฆฌ([ใ„ฒ])์ธ ๋‹จ์–ด๊ฐ€ ๋“ค์–ด ์žˆ์œผ๋ฉด, ๊ธฐ์–ต์ธต์„ ํ†ต๊ณผํ•˜๋Š” ์‹ ๊ฒฝ๋ง์€ *"์šธ๋ฆผ ๋ฐ›์นจ ๋’ค์˜ ํ‰์Œ์€ ๋œ์†Œ๋ฆฌ๋กœ ์ฝ๋Š”๋‹ค"*๋Š” ๋ฒ„๋ฆ‡์„ ์™ธ์›Œ ์†๊ถŒ๊นŒ์ง€ [์†๊ฟ˜]์œผ๋กœ ์ฝ๊ณ  ๋ฌธ์žฅ ๊ณณ๊ณณ์˜ ํ‰์Œ์„ ๊ฒฝ์Œ์œผ๋กœ ์˜ค์—ผ์‹œํ‚ต๋‹ˆ๋‹ค.

**Piper Plus (์™„์ „๊ณต๋ช…ํŒ Epoch 880 EMA)**๋Š” ์ด๋ฅผ ๋‹ค์Œ 4๋‹จ๊ณ„ ์•„ํ‚คํ…์ฒ˜์™€ ์—ญํ•  ๋ถ„๋‹ด์œผ๋กœ ์™„๋ฒฝํžˆ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค:

  1. ์ถœ๋ ฅยทํ…์ŠคํŠธ ์ธ์ฝ”๋”์—์„œ '๋œ์†Œ๋ฆฌํ™”๋œ ์ž๋ชจ ๊ธฐ์–ต์ธต(self.emb)' 100% ๋ฏธํ†ต๊ณผ(๋Œ€์ฒด) ์„ค๊ณ„ (jamo_feature_mode = "๋Œ€์ฒด"):
    • models.py (TextEncoder.forward 297302ํ–‰, _๋ฐœ์„ฑ์ž์งˆ 14531456ํ–‰):
      ๋ชซ = self.emb_f(F.embedding(x, self.jamo_feat))  # [544, 104] ์ฃผํŒŒ์ˆ˜ ์„ฑ์งˆ ํ–‰๋ ฌ -> Linear(104, 192, bias=False)
      x = torch.where(์ž๋ชจ์นธ.unsqueeze(-1), ๋ชซ, x)     # ์ž๋ชจ ์นธ์€ ๊ธ€์ž๋ณ„ ๊ธฐ์–ต ์นธ(self.emb)์„ 100% ๋ฒ„๋ฆฌ๊ณ  ์ฃผํŒŒ์ˆ˜ ์„ฑ์งˆ ๋ชซ์œผ๋กœ ๋Œ€์ฒด!
      
    • ๋ชจ๋“  ํ•œ๊ธ€ ์ž๋ชจ(ํ˜„๋Œ€ ์ž๋ชจ + ์˜›๋ชจ์Œยท์˜›์ž์Œ)๋Š” ๋œ์†Œ๋ฆฌ ๋ฒ„๋ฆ‡์ด ํ•™์Šต๋œ ๊ธ€์ž๋ณ„ ์ž„๋ฒ ๋”ฉ ๊ธฐ์–ต ์นธ(self.emb)์„ ์•„์˜ˆ ํ†ต๊ณผํ•˜์ง€ ์•Š๊ณ , ์˜ค์ง ใ€Žํ›ˆ๋ฏผ์ •์Œ ํ•ด๋ก€๋ณธใ€์„ ๋ณธ๋–  ์‹ค์ธกํ•œ **104์ฐจ์› ๋ฐœ์„ฑ ์ฃผํŒŒ์ˆ˜ ํ–‰๋ ฌ(jamo_feat)**์— ๋‹จ์ผ ๊ณต์œ  ์„ ํ˜• ๋ณ€ํ™˜(emb_f)๋งŒ ๊ฑฐ์ณ ์ธ์ฝ”๋”๋กœ ์ง๊ฒฐ๋ฉ๋‹ˆ๋‹ค.
    • ๋˜ํ•œ _๋ฌธ๋งฅ์„ฑ์งˆ(x)(1427~1435ํ–‰)์—์„œ ์ธ์ฝ”๋” ์•ž๋‹จ์˜ ์ธ์œ„์  ๋ฐœ์Œ ๊ทœ์น™์„ ์™„์ „ํžˆ ๋„๊ณ ("์ž…๋ ฅ ์ธ์ฝ”๋”๋Š” ์•ž๋’ค ๊ธ€์ž๋ฅผ ๋ณด๊ณ  ์„ฑ์งˆ์„ ๋ฐ”๊พธ์ง€ ์•Š๋Š”๋‹ค โ€” ๊ทธ๋ƒฅ ์ฃผํŒŒ์ˆ˜๋กœ ์ฝ๋Š”๋‹ค"), ์—ํญ 437์—์„œ ๋œ์†Œ๋ฆฌ๊ฐ€ ๊ตณ์–ด์ง„ ๊ธฐ์กด ํ…์ŠคํŠธ ์ธ์ฝ”๋”(enc_p.* 112๊ฐœ ํ‚ค)๋ฅผ ํ†ต์งธ๋กœ ๋น„์šด ๋’ค **๋ฐœ์Œ๊ณต๋ช…ยท์„ฑ์šฐ๊ณต๋ช…ยท๊ฐ์ •๊ณต๋ช… ์„ธ ๊ฐ€์ง€๋งŒ ๊ธฐ์–ตํ•˜๋Š” '์™„์ „๊ณต๋ช…ํŒ'**์œผ๋กœ ์—ํญ 880๊นŒ์ง€ ์žฌํ•™์Šตํ–ˆ์Šต๋‹ˆ๋‹ค. (์•„์šธ๋Ÿฌ TextEncoder ๋‚ด๋ถ€์—๋Š” ๋ฐœ์Œ ์‚ฌ์ „๋ถ„ํฌ m_p, logs_p๊ฐ€ ๋ฌธ๋งฅ ์ธ์ฝ”๋”๋ฅผ ์šฐํšŒํ•˜๋Š” pron_context_free / _๋ฐœ์Œ์ถœ๊ตฌ ๋ชจ๋“ˆ๋„ ํ•จ๊ป˜ ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.)
  2. ํ•œ๊ตญ์–ด ์„ธ๊ธฐํŒ๋ณ„๊ธฐ(tense_clf=True) & ์˜ˆ์‚ฌ์†Œ๋ฆฌ 24๋ฐฐ ๋ณดํ˜ธ ๊ฐ€์ค‘์น˜(tense_plain_weight=24.0):
    • ํ•™์Šต ์‹œ ์ƒ์„ฑ๋œ ์Œ์„ฑ ํŒŒํ˜•์—์„œ ์˜ˆ์‚ฌ์†Œ๋ฆฌยท๋œ์†Œ๋ฆฌยท๊ฑฐ์„ผ์†Œ๋ฆฌ๋ฅผ ํŒ๋ณ„ํ•˜๋Š” **์„ธ๊ธฐํŒ๋ณ„๊ธฐ(tense_clf=True, c_tense_gen=8.0)**๋ฅผ ๋‘๊ณ , ํŠนํžˆ **์˜ˆ์‚ฌ์†Œ๋ฆฌ ๋ณดํ˜ธ ๊ฐ€์ค‘์น˜(tense_plain_weight=24.0)**๋ฅผ ๋ถ€์—ฌํ•˜์—ฌ ๋ชจ๋ธ์ด ์˜ˆ์‚ฌ์†Œ๋ฆฌ ๊ธ€์ž๋ฅผ ์ž„์˜๋กœ ๋œ์†Œ๋ฆฌ๋กœ ๋ฐœ์„ฑํ•˜๋ฉด **24๋ฐฐ์˜ ๊ฐ•๋ ฅํ•œ ๋ฒŒ์ (Loss)**์„ ๋ฐ›๋„๋ก ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค.
  3. ๊ฐ€์Šด(ํ‰์„ฑ) ๊ณต๋ช… ๋Œ€์—ญ ๊ณผ์ž‰ ๊ฐ€์ค‘์น˜ ์–ต์ œ (res_band_weights = "0,2,4"):
    • ์ €์—ญ(ํ‰์„ฑ) ๋Œ€์—ญ ๊ฐ€์ค‘์น˜๋ฅผ 0์œผ๋กœ ์–ต์ œ(res_band_weights='0,2,4')ํ•˜์—ฌ, ์ €์—ญ ์—๋„ˆ์ง€๊ฐ€ ๊ณผ๋„ํ•˜๊ฒŒ ๋ถ€ํ’€์–ด ์˜ˆ์‚ฌ์†Œ๋ฆฌ๊ฐ€ ๋ฌด๊ฒ๊ณ  ๋”ฑ๋”ฑํ•œ ๋œ์†Œ๋ฆฌ์ฒ˜๋Ÿผ ๋“ค๋ฆฌ๋Š” ํ˜„์ƒ์„ ์›์ฒœ ์ฐจ๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค.
  4. ๋ถˆ๊ทœ์น™ ๋ฐœ์Œ์€ ๋ฐœ์Œ์‚ฌ์ „(Dictionary)์œผ๋กœ 1:1 ์ •๋ฐ€ ๋Œ€์‘:
    • ๊ธฐ์–ต์ธต์„ ์šฐํšŒํ•˜์—ฌ ๋ชจ๋ธ์ด ๊ธ€์ž ๊ทธ๋Œ€๋กœ์˜ ๋ง‘์€ ์˜ˆ์‚ฌ์†Œ๋ฆฌ๋ฅผ 100% ๋ฐœ์„ฑํ•˜๊ฒŒ ๋งŒ๋“  ๋Œ€์‹ , ์‹ค์ œ ํ•œ๊ตญ์–ด์—์„œ ์†Œ๋ฆฌ๊ฐ€ ๋ฐ”๋€Œ์–ด์•ผ ํ•˜๋Š” **๋ถˆ๊ทœ์น™ ๋ฐœ์Œ(์˜ˆ์™ธ์  ๊ฒฝ์Œํ™”, ํ•œ์ž์–ด ๋œ์†Œ๋ฆฌ ์ธ๊ถŒโ†’์ธ๊ฟ˜, ์‚ฌ์ด์‹œ์˜ท ์†๊ฐ€๋ฝโ†’์†๊นŒ๋ฝ, ์—ฐ์Œยทใ„ด/ใ„น ์ฒจ๊ฐ€ ๋“ฑ)**์€ ์‹ ๊ฒฝ๋ง์˜ ๋ถˆํ™•์‹คํ•œ ์ถ”์ธก์— ๋งก๊ธฐ์ง€ ์•Š๊ณ  ์ถ”๋ก  ์•ž๋‹จ์˜ **๋ฐœ์Œ์‚ฌ์ „(๋ถˆ๊ทœ์น™๋‹จ์–ด์‚ฌ์ „)**์œผ๋กœ 1:1 ์ •๋ฐ€ ๋Œ€์‘ํ•˜๋„๋ก ์—ญํ•  ๋ถ„๋‹ด์„ ์™„์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

3. ๋ฌธ๋งฅ(Context) ๊ธฐ๋ฐ˜ ์ „์šฉ ๊ฐ์ • ๋ชจ๋ธ ์ž๋™ ๋งคํ•‘ & ์ œ๋กœ๋“€๋ ˆ์ด์…˜(Zero-Duration) ๊ฐ์ • ํƒœ๊ทธ

  1. ๋ฌธ๋งฅ์„ ์ฝ์–ด ์ž๋™์œผ๋กœ ๊ฐ์ • ํƒœ๊ทธยท๊ณต๋ช… ์ฃผํŒŒ์ˆ˜๋ฅผ ๋งคํ•‘ํ•˜๋Š” ์ „์šฉ ๊ฐ์ • ๋ชจ๋ธ (emotion/emotion_int8.onnx):
    • ์ž์—ฐ์Šค๋Ÿฌ์šด ๊ฐ์ • ํ‘œํ˜„์„ ์œ ๋„ํ•˜๊ธฐ ์œ„ํ•ด, ๋ฌธ์žฅ์˜ ์•ž๋’ค ๋งฅ๋ฝ(Context)๊ณผ ํ™”ํ–‰์„ ๋ถ„์„ํ•˜๋Š” **์ „์šฉ ํ•œ๊ตญ์–ด ๊ฐ์ • ๋ชจ๋ธ(emotion/emotion_int8.onnx, KoELECTRA-small ๊ธฐ๋ฐ˜ ๋‹ค์ค‘ ๋จธ๋ฆฌ ๋ถ„๋ฅ˜๊ธฐ)**์„ ์ง์ ‘ ํ•™์Šตํ•˜์—ฌ ๊ฒฐํ•ฉํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ์‚ฌ์šฉ์ž๊ฐ€ ๋Œ€๋ณธ์— ์ผ์ผ์ด ๊ฐ์ • ํƒœ๊ทธ๋ฅผ ๋‹ฌ์ง€ ์•Š์•„๋„, ๊ฐ์ • ๋ชจ๋ธ์ด ์ž…๋ ฅ ๋ฌธ์žฅ์˜ ๋ฌธ๋งฅ์„ ๋ถ„์„ํ•˜์—ฌ ๊ฐ์ • ๊ฐˆ๋ž˜(32์ข… ๊ฐ์ •ยท๋งํˆฌ ํƒœ๊ทธ ์ฒด๊ณ„), ๊ฐ์ • ์„ธ๊ธฐ(ํฌ๊ธฐ), ๋งํ•˜๊ธฐ ๋น ๋ฅด๊ธฐ(๋А๋ฆฌ๊ฒŒ 1.08 / ๋ณดํ†ต 1.0 / ๋น ๋ฅด๊ฒŒ 0.93), ์ˆจ๊ฒฐยท์Œ๋†’์ดยท์—๋„ˆ์ง€๋ฅผ ์ž๋™์œผ๋กœ ํŒ๋ณ„ํ•˜๊ณ , ์ด๋ฅผ emotion/emotion_resonance.json์˜ **34์ฐจ์› ์‹ ๊ฒฝ๊ณต๋ช… ๋ฒกํ„ฐ(res)**๋กœ ์ฆ‰์‹œ ๋งคํ•‘ํ•˜์—ฌ ์ƒ์ƒํ•œ ๊ฐ์ • ์—ฐ๊ธฐ๋ฅผ ์ด๋Œ์–ด๋ƒ…๋‹ˆ๋‹ค.
  2. ๊ฐ์ • ํƒœ๊ทธ ์ œ๋กœ๋“€๋ ˆ์ด์…˜ (_ํƒœ๊ทธ์นธ๋–ผ๊ธฐ Zero-Duration Scatter Compaction) โ€” ์†Œ๋ฆฌ๋Š” ์•ˆ ๋‚ด๊ณ  ๊ฐ์ •๋งŒ ์ฃผ์ž…:
    • ๋ฌธ์žฅ ๋จธ๋ฆฌ๋‚˜ ์ค‘๊ฐ„์— ์‚ฝ์ž…๋œ ๊ฐ์ •ยท๋ฐœ์„ฑยท์†Œ๋ฆฌ ํƒœ๊ทธ๋Š” ํ…์ŠคํŠธ ์ธ์ฝ”๋” ๋‚ด๋ถ€์—์„œ ์ฃผ๋ณ€ ๋ณธ๋ฌธ ์ž๋ชจ์— ๊ฐ์ • ์ฃผํŒŒ์ˆ˜์™€ ์–ต์–‘ยท๋ฐœ์„ฑ ํšจ๊ณผ๋งŒ ์ž…ํž™๋‹ˆ๋‹ค.
    • ์ดํ›„ ๊ธธ์ด ์˜ˆ์ธก๊ธฐ(Duration Predictor)์™€ ๋””์ฝ”๋”๋กœ ๋„˜์–ด๊ฐ€๊ธฐ ์ง์ „, ๋ชจ๋ธ ๋‚ด๋ถ€์˜ **_ํƒœ๊ทธ์นธ๋–ผ๊ธฐ(Zero-Duration Scatter Compaction)**๊ฐ€ ํƒœ๊ทธ ์นธ์„ 100% ๋–ผ์–ด๋‚ด์–ด **ํ”„๋ ˆ์ž„ ์ˆ˜ 0(์ œ๋กœ๋“€๋ ˆ์ด์…˜, Zero-Duration)**์œผ๋กœ ์†Œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
    • ๋•๋ถ„์— ํƒœ๊ทธ ๊ธฐํ˜ธ ์ž์ฒด๊ฐ€ ๊ธ€์ž ์†Œ๋ฆฌ๋‚˜ ๊ธฐ๊ดดํ•œ ๊ตฐ์†Œ๋ฆฌ๋กœ ๋ฐœ์Œ๋˜๋Š” ์ผ์ด ์ ˆ๋Œ€ ์—†์œผ๋ฉฐ, ์˜ค์ง ์ˆœ์ˆ˜ํ•˜๊ฒŒ ๊ฐ์ •๊ณผ ๋ฐœ์„ฑ ๊ณต๋ช… ํšจ๊ณผ๋งŒ ์Œ์„ฑ์— ๋‚จ์Šต๋‹ˆ๋‹ค.

4. ์˜›๋ชจ์Œยท์˜›์ž์Œ(์˜›ํ•œ๊ธ€)์„ ํ™œ์šฉํ•œ ์™ธ๊ตญ์–ด ๋ฐœ์Œ ๊ตฌํ˜„ & ๋ฏธํ•™์Šต ์˜๋‹จ์–ด ํ•œ๊ตญ์‹ ๋ฐœ์Œ(์ฝฉ๊ธ€๋ฆฌ์‰ฌ) ์ฒ˜๋ฆฌ

  1. ํ›ˆ๋ฏผ์ •์Œ ์˜›์ž์Œยท์˜›๋ชจ์Œ ๊ณต๋ช… ์ฃผํŒŒ์ˆ˜๋ฅผ ํ†ตํ•œ ์˜์–ดยท์™ธ๊ตญ์–ด ์›์Œ ํ™•์žฅ:
    • ๊ฐœ๋ณ„ ๊ธ€์ž ๊ธฐ์–ต ์นธ(self.emb)์„ ์“ฐ์ง€ ์•Š๊ณ  jamo_feat(544ร—104) ๊ณต๋ช… ์ฃผํŒŒ์ˆ˜ ํ–‰๋ ฌ๊ณผ ๊ณต์œ  ์„ ํ˜• ๋ณ€ํ™˜(emb_f)๋งŒ์œผ๋กœ ์†Œ๋ฆฌ๋ฅผ ์ง“๊ธฐ ๋•Œ๋ฌธ์—, ํ•™์Šต ์ฝ”ํผ์Šค์— ๋“ฑ์žฅ ๋นˆ๋„๊ฐ€ ์ ๊ฑฐ๋‚˜ ๋ฏธํ•™์Šต๋œ **ํ›ˆ๋ฏผ์ •์Œ์˜ ์˜›์ž์Œ โ€” ์ˆœ๊ฒฝ์Œ ํ”ผ์– แ…—(U+1157, ID 384 [f]), ์ˆœ๊ฒฝ์Œ ๋น„์ แ„ซ/ใ…ธ(U+112B, ID 385 [v]), ๋ฐ˜์น˜์Œ แ…€/ใ…ฟ(U+1140, ID 386 [z]), ์น˜๋‘์Œ ์‹œ์˜ท แ„ผ(U+113C, ID 387 [ฮธ]), ์ •์น˜์Œ ์‹œ์˜ท แ„ฝ(U+113D, ID 388 [รฐ]), ์—ฌ๋ฆฐํžˆ์— ใ††, ์˜›์ด์‘ ใ† โ€” ๋ฐ ์˜›๋ชจ์Œ(์•„๋ž˜์•„ ใ†, ใ†Ž ๋“ฑ)**๋„ ์ฃผํŒŒ์ˆ˜ ๊ฐ’๋งŒ์œผ๋กœ ์ฆ‰์‹œ ์ •ํ™•ํ•œ ์ŒํŒŒ ๊ธ€์ž ๋ฐœ์„ฑ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
    • ์ด๋ฅผ ํ†ตํ•ด ํ˜„๋Œ€ ํ•œ๊ธ€ ํ‘œ๊ธฐ๋งŒ์œผ๋กœ๋Š” ๊ตฌ๋ณ„ํ•  ์ˆ˜ ์—†๋Š” ์˜์–ดยท์™ธ๊ตญ์–ด์˜ ์œ ์„ฑ ๋งˆ์ฐฐ์Œ([v] โ†’ แ„ซ, [z] โ†’ แ…€, [รฐ] โ†’ แ„ฝ)๊ณผ ๋ฏธ์„ธํ•œ ๋ชจ์Œ ์Œ๊ฐ€๋ฅผ ์˜›์ž์Œยท์˜›๋ชจ์Œ์˜ ๊ณต๋ช… ์ฃผํŒŒ์ˆ˜ ์กฐํ•ฉ์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ๋ฏธํ•™์Šต ์˜๋‹จ์–ด(OOV English) ๋ฐ ์•ฝ์–ด์˜ ์ž์—ฐ์Šค๋Ÿฌ์šด ํ•œ๊ตญ์‹ ๋ฐœ์Œ(์ฝฉ๊ธ€๋ฆฌ์‰ฌ / ์•ŒํŒŒ๋ฒณ-ํ•œ๊ธ€ ์Œ์ฐจ) ์ฒ˜๋ฆฌ:
    • ๋ณ„๋„์˜ ์˜์–ด ์›์–ด๋ฏผ ์Œ์„ฑ ๋ฐ์ดํ„ฐ์…‹์œผ๋กœ ์ง์ ‘ ํ•™์Šตํ•˜์ง€ ์•Š์€ ๋ฏธํ•™์Šต ์˜๋‹จ์–ด๋‚˜ ์˜๋ฌธ ์•ฝ์–ด๊ฐ€ ์ž…๋ ฅ๋˜๋”๋ผ๋„ ๊นจ์ง€๊ฑฐ๋‚˜ ์นจ๋ฌตํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
    • CMU ๋ฐœ์Œ๊ธฐํ˜ธ(ARPAbet)์™€ ๊ตญ๋ฆฝ๊ตญ์–ด์› ์™ธ๋ž˜์–ด ํ‘œ๊ธฐ๋ฒ• ๋ฐ ์˜›๊ธ€์ž ์šธ๋ฆผ ๊ณต๋ช…(แ„ซยทแ…€ยทแ„ฝ)์„ ๊ฒฐํ•ฉํ•œ ํ•œ๊ตญ์‹ ์˜์–ด ๋ฐœ์Œ(์ฝฉ๊ธ€๋ฆฌ์‰ฌ) ๋ณ€ํ™˜์„ ํ†ตํ•ด coffee โ†’ ์นดํ”ผ, thank โ†’ ์ƒํฌ, very โ†’ แ„ซแ…ฆ๋ฆฌ(๋ฒ ๋ฆฌ), music โ†’ ๋ฎคแ…€แ…ตแ†จ(๋ฎค์ง)์ฒ˜๋Ÿผ ํ•œ๊ตญ์–ด ํ™”์ž์—๊ฒŒ ๊ฐ€์žฅ ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ฐœ์Œ์œผ๋กœ ๋ฐ”๊พธ์–ด ์ฝ์œผ๋ฉฐ, ๋ฏธ๋“ฑ๋ก ์˜๋‹จ์–ด๋‚˜ ๋Œ€๋ฌธ์ž ์•ฝ์–ด(SNS โ†’ ์—์Šค์—”์—์Šค, TV โ†’ ํ‹ฐแ„ซใ…ฃ, OK โ†’ ์˜ค์ผ€์ด)๋Š” ์•ŒํŒŒ๋ฒณ ํ•œ๊ธ€ ์Œ์ฐจ ๊ทœ์น™์œผ๋กœ ๋งค๋„๋Ÿฝ๊ฒŒ ๋ฐœ์„ฑํ•ฉ๋‹ˆ๋‹ค.

5. ์ดˆ๊ฒฝ๋Ÿ‰ยท๋ฌด๋ฐœ์—ด ๊ตฌ๋™ & Epoch 880 EMA์˜ ํ˜ธํกยท์†๋„ยท๊ฐˆ๋ผ์ฝ๊ธฐ ํ˜์‹ 

  1. ์ดˆ๊ฒฝ๋Ÿ‰ ๊ตฌ๋™ & ์Šค๋งˆํŠธํฐยทCPU ๋ฌด๋ฐœ์—ด ์„ค๊ณ„ (Ultra-Light & Near-Zero Heat):
    • ๊ฑฐ๋Œ€ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ฐ€์ง„ ์ž„๋ฒ ๋”ฉ ๊ธฐ์–ต์ธต์ด๋‚˜ ์—ฐ์‚ฐ ์ง‘์•ฝ์ ์ธ ํ’€๋ฐด๋“œ HiFi-GAN ๋ณด์ฝ”๋”๋ฅผ ์ œ๊ฑฐํ•˜๊ณ , ์ž๋ชจยท์„ฑ์šฐยท๊ฐ์ • ์ฃผํŒŒ์ˆ˜์˜ ๊ฐ€๋ฒผ์šด ๋‹จ์ผ ์„ ํ˜• ํˆฌ์˜(emb_f, emb_g_res, emb_res) + 4-๋ถ€๋Œ€์—ญ MB-iSTFT-VITS(PQMF ์—ญํ‘ธ๋ฆฌ์— ๋ณ€ํ™˜) ๋””์ฝ”๋”๋กœ ํŒŒํ˜•์„ ์ง์ ‘ ํ•ฉ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋ฐ”์ผ ๊ธฐ๊ธฐ(์Šค๋งˆํŠธํฐ)๋‚˜ ์ €์ „๋ ฅ CPU์—์„œ๋„ ์žฅ์‹œ๊ฐ„ ์—ฐ์† ๋‚ญ๋… ์‹œ ๋ฐœ์—ด์ด ๊ฑฐ์˜ ์—†์ด ๋น ๋ฅด๊ณ  ์พŒ์ ํ•˜๊ฒŒ ๊ตฌ๋™๋ฉ๋‹ˆ๋‹ค.
  2. ์–ด์ ˆ ๊ฒฝ๊ณ„(eojeol_boundary) ์™„์ „ ์ œ๊ฑฐ:
    • ๋„์–ด์“ฐ๊ธฐ(์–ด์ ˆ)๋งˆ๋‹ค ๋ˆ„์ ํ•ฉ(CumSum)์œผ๋กœ ์–ด์ ˆ ๋ฒˆํ˜ธ๋ฅผ ์„ธ์–ด ์ธ์ฝ”๋” ์–ดํ…์…˜์„ ๊ฐ€๋‘๋˜ ์–ด์ ˆ ๊ฒฝ๊ณ„ ๊ธฐ๋Šฅ์„ ๋ชจ๋ธ์—์„œ ์™„์ „ํžˆ ์ œ๊ฑฐํ–ˆ์Šต๋‹ˆ๋‹ค. ์–ด์ ˆ๋งˆ๋‹ค ๊ธฐ๊ณ„์ ์œผ๋กœ ๋š๋š ๋Š์–ด ์ฝ๊ฑฐ๋‚˜ ์–ด์ ˆ ๊ฒฝ๊ณ„์—์„œ ๋ฐœ์Œ์ด ํ”๋“ค๋ฆฌ๋˜ ํ˜„์ƒ์ด ์‚ฌ๋ผ์ง€๊ณ , ๋ฌธ์žฅ ์ „์ฒด์˜ ํ˜ธํก๊ณผ ์—ฐ์Œ์ด ๋ฌผ ํ๋ฅด๋“ฏ ์ด์–ด์ง‘๋‹ˆ๋‹ค.
  3. ๋งํ•˜๊ธฐ ์†๋„ ํ‘œ์ค€ํ™” (๋ฐ”ํƒ• ๋ฐฐ์† 0.85 + ๊ฐ์ •๋ณ„ ๋น ๋ฅด๊ธฐ 1.08 / 1.0 / 0.93):
    • ์ด ๋ชจ๋ธ์˜ ๊ฐ€์žฅ ์ž์—ฐ์Šค๋Ÿฌ์šด ํ‘œ์ค€ ์ •์†(base length_scale)์€ 0.85 (scales = [0.667, 0.85, 0.8])์ž…๋‹ˆ๋‹ค.
    • ์—ฌ๊ธฐ์— KoELECTRA ๊ฐ์ • ๋ถ„๋ฅ˜๊ธฐ์˜ ๋น ๋ฅด๊ธฐ ๋จธ๋ฆฌ ์˜ˆ์ธก๊ฐ’(๋А๋ฆฌ๊ฒŒ: 1.08, ๋ณดํ†ต: 1.0, ๋น ๋ฅด๊ฒŒ: 0.93, ํ™•์‹ ๋„ โ‰ฅ 0.4์ผ ๋•Œ ์ ์šฉ)์„ ๊ณฑํ•˜์—ฌ ์Šฌํ””ยทํšŒ์ƒ ์žฅ๋ฉด์—์„œ๋Š” ์ฐจ๋ถ„ํ•˜๊ฒŒ(0.85 ร— 1.08 = 0.918), ๊ธด๋ฐ•ยท๋ถ„๋…ธ ์žฅ๋ฉด์—์„œ๋Š” ์†๋„๊ฐ ์žˆ๊ฒŒ(0.85 ร— 0.93 = 0.7905) ์™„๊ธ‰์„ ์กฐ์ ˆํ•ฉ๋‹ˆ๋‹ค.
  4. ์ข…๊ฒฐํ˜•ยท์—ฐ๊ฒฐํ˜• ์–ด๋ฏธ์™€ ๋ฌธ์žฅ๋ถ€ํ˜ธ์—์„œ ๋Š์–ด ์ฝ๊ธฐ (๊ฐˆ๋ผ์ฝ๊ธฐ):
    • ๊ธด ๋ฌธ์žฅ์„ ๊ธ€์ž ์ˆ˜๋‚˜ ์–ด์ ˆ ๋‹จ์œ„๋กœ ๋ฌด์ž‘์ • ์ž๋ฅด๋ฉด ์–ต์–‘์ด ํ† ๋ง‰ ๋‚˜๊ณ , ๋ฐ˜๋Œ€๋กœ ๊ธด ๋ฌธ๋‹จ์„ ํ†ต์งธ๋กœ ํ•œ ๋ฒˆ์— ํ•ฉ์„ฑํ•˜๋ฉด ๋’ค์ชฝ ํ˜ธํก์ด ๋ฌด๋„ˆ์ง€๊ฑฐ๋‚˜ ์ธ์ฝ”๋”๊ฐ€ ๊ฒฝ๊ณ„๋ฅผ ๋„˜์–ด ๋ฐœ์Œ์„ ํ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ๊ฐˆ๋ผ์ฝ๊ธฐ๋Š” ์˜ค์ง ๋ฌธ์žฅ๋ถ€ํ˜ธ(. ! ? , โ€ฆ ; โ€”) ๋ฐ **ํ•œ๊ตญ์–ด ์—ฐ๊ฒฐํ˜• ์–ด๋ฏธ(~๊ณ , ~๋ฉฐ, ~๋ฉด์„œ, ~๋Š”๋ฐ, ~์ง€๋งŒ, ~์„œ[์กฐ์‚ฌ ์—์„œยท๊ป˜์„œยท๋กœ์„œ ์ œ์™ธ], ~๋‹ˆ๊นŒ, ~๋‹ค๊ฐ€, ~๊ฑฐ๋‚˜, ~๋“ ์ง€, ~๋ ค๊ณ , ~์ž๋งˆ์ž ๋“ฑ โ€” ์ ‘์†๋ถ€์‚ฌ ๊ทธ๋ฆฌ๊ณ ยท๊ทธ๋ž˜์„œยทํ•˜์ง€๋งŒ ๋“ฑ์€ ์ œ์™ธ)**์™€ ์ข…๊ฒฐํ˜• ์–ด๋ฏธ(~๋‹ˆ๋‹ค, ~์–ด์š”, ~์•„์š”, ~ํ•ด์š”, ~๋Š”๋‹ค, ~์—ˆ๋‹ค, ~์•˜๋‹ค, ~๋‹ค, ~์š”, ~๊นŒ, ~๋„ค ๋“ฑ) ๋’ค์—์„œ๋งŒ ํ˜ธํก ๋‹จ์œ„๋กœ ๋‚˜๋ˆ„์–ด ๊ฐ๊ฐ ํ•ฉ์„ฑํ•ฉ๋‹ˆ๋‹ค.
    • ๊ฐ ์กฐ๊ฐ ์•ž๋’ค์— ๋ถ™์ธ ๊ฒฝ๊ณ„ ๊ธฐํ˜ธ(^ _, $)์˜ ์†Œ๋ฆฌ๋Š” ๋ชจ๋ธ์ด ๋ฐ˜ํ™˜ํ•œ durations ๊ธธ์ดํ‘œ๋กœ ์ •ํ™•ํžˆ ์ž˜๋ผ๋‚ด๊ณ , ์กฐ๊ฐ ์‚ฌ์ด์— **0.01์ดˆ(10ms)**์˜ ๋ฏธ์„ธํ•œ ์ˆจํ‹ˆ์„ ๋‘์–ด ์ด์–ด ๋ถ™์ž„์œผ๋กœ์จ ํ•œ ํ˜ธํก์ฒ˜๋Ÿผ ๋งค๋„๋Ÿฝ๊ณ  ์„ ๋ช…ํ•œ ๋‚ญ๋…์„ ์™„์„ฑํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ ํŒŒ์ผ ๊ตฌ์„ฑ

ํŒŒ์ผ ๋‚ด์šฉ
piper-plus.onnx ๋‚ญ๋… ๋ชจ๋ธ (Epoch 880 EMA, 85.6MB) โ€” ์–ด์ ˆ ๊ฒฝ๊ณ„ ์ œ๊ฑฐ ยท ๋œ์†Œ๋ฆฌ ๊ณผ์ž‰ ์ผ๋ฐ˜ํ™” ์–ต์ œ ยท ์™„์ „๊ณต๋ช…ํŒ
piper-plus.onnx.json ๋ชจ๋ธ ์„ค์ • โ€” ํ‘œ๋ณธ์œจ(22,050Hz), ๊ธ€์žยท์˜›๊ธ€์žยทํƒœ๊ทธ ๋ฒˆํ˜ธํ‘œ(phoneme_id_map), ํ™”์ž ๋ฒˆํ˜ธํ‘œ(speaker_id_map), ๊ธฐ๋ณธ ์ถ”๋ก  ๋ฐฐ์†(length_scale: 0.85)
resonance/jamo_features.json ์ž๋ชจ ์„ฑ์งˆํ‘œ (ํ›ˆ๋ฏผ์ •์Œ ํ•ด๋ก€๋ณธ ๊ธฐ๋ฐ˜ ๋ฐœ์Œ ๊ณต๋ช… ์ฃผํŒŒ์ˆ˜ 80์นธ + ํƒœ๊ทธ ์˜ˆ๋น„ 24์นธ = 104์นธ)
resonance/speaker_features.json ์„ฑ์šฐ ๋ฐœ์„ฑ ์ฃผํŒŒ์ˆ˜ 31๊ฐ€์ง€ (ํ‰๊ท ยทํ‘œ์ค€ํŽธ์ฐจ ๋ฐ ํ™”์ž๋ณ„ z ์ ์ˆ˜)
emotion/emotion_resonance.json ๊ฐ์ •ยท๋งํˆฌ ์ด๋ฆ„ โ†’ res ์‹ ๊ฒฝ๊ณต๋ช… ์ž…๋ ฅ ๊ฐ’ (๊ณต๋ช… ๋…ธ๋ธŒ 3์นธ + ๊ฐ์ • ๊ผฌ๋ฆฌ 15์นธ)
emotion/emotion_int8.onnx ๋ฌธ๋งฅ ๊ธฐ๋ฐ˜ ๋ฌธ์žฅ ๊ฐ์ •ยท๋น ๋ฅด๊ธฐยท๋งํˆฌ ์ž๋™ ๋ถ„๋ฅ˜ ๋ชจ๋ธ (KoELECTRA-small v3 ๊ธฐ๋ฐ˜, int8, 14.6MB)
emotion/vocab.txt ๊ฐ์ • ๋ชจ๋ธ ํ† ํฌ๋‚˜์ด์ € ์–ดํœ˜ (WordPiece)
emotion/emotion_labels.json ยท emotion_labels_full.json ๊ฐ์ • ๋ชจ๋ธ ์ถœ๋ ฅ ๋จธ๋ฆฌ ๋ผ๋ฒจ ์ด๋ฆ„๊ณผ ์ฐจ๋ก€
emotion/emotion_config.json ๊ฐ์ • ๋ชจ๋ธ ์„ค์ • (max_len 192 ๋“ฑ)
emotion/emotion_tokens.json ๊ฐ์ • ์ด๋ฆ„ยท๋งํˆฌ ๋‚ฑ๋ง โ†’ ๋ฒˆํ˜ธ ๋งคํ•‘ ํ‘œ

๐Ÿš€ ๋‚ญ๋… ๋ชจ๋ธ ์“ฐ๋Š” ๋ฒ•

์ž…๋ ฅ ํ…์„œ ๊ทœ๊ฒฉ

์ด๋ฆ„ ๋ชจ์–‘ ๋œป
input [1, n] int64 NFD ์ž๋ชจ ๋ฒˆํ˜ธ์—ด (^, _, ์ž๋ชจ๋“ค, $)
input_lengths [1] int64 n
scales [3] float32 [noise_scale, length_scale, noise_w] โ€” ํ‘œ์ค€ ์ •์†์€ [0.667, 0.85, 0.8] (length_scale = 0.85 ร— ๋น ๋ฅด๊ธฐ๋ฐฐ์ˆ˜)
sid [1] int64 ํ™”์ž ๋ฒˆํ˜ธ (speaker_id_map) โ€” ๋ชจ๋ธ ๋‚ด๋ถ€ ์„ฑ์šฐ ๊ณต๋ช… ์ฃผํŒŒ์ˆ˜ํ‘œ์˜ ํ–‰ ๋ฒˆํ˜ธ
res [1, 34] float32 ์‹ ๊ฒฝ๊ณต๋ช… ์ž…๋ ฅ. [0:3] ๊ณต๋ช… ๋…ธ๋ธŒ, [19:34] ๊ฐ์ • ๊ผฌ๋ฆฌ, [3:19] ๋ฏธ์‚ฌ์šฉ(0). ๋ชจ๋‘ 0์ด๋ฉด ๋ฌด๊ฐ์ • ๊ธฐ๋ณธ ๋ชฉ์†Œ๋ฆฌ

์ถœ๋ ฅ output์€ 22,050Hz ํŒŒํ˜•(-1.0 ~ 1.0), durations๋Š” ๊ฐ ์ž…๋ ฅ ํ† ํฐ์˜ ํ”„๋ ˆ์ž„ ๊ธธ์ด(hop_length = 256 ํ‘œ๋ณธ ๋‹จ์œ„, ํƒœ๊ทธ ์นธ์€ ์ œ๋กœ๋“€๋ ˆ์ด์…˜์œผ๋กœ ์ž๋™ ์ œ๊ฑฐ๋จ)์ž…๋‹ˆ๋‹ค.

ํŒŒ์ด์ฌ ์ „์ฒด ์˜ˆ์ œ (๋ถˆ๊ทœ์น™ ๋ฐœ์Œยท์˜์–ด ์Œ์ฐจ + ๊ฐˆ๋ผ์ฝ๊ธฐ + 0.85 ๋ฐฐ์† & ๊ฐ์ • ๋น ๋ฅด๊ธฐ + ์‹ ๊ฒฝ๊ณต๋ช…)

import json, re, unicodedata, wave
import numpy as np, onnxruntime as ort

cfg = json.load(open("piper-plus.onnx.json", encoding="utf-8"))
emo = json.load(open("emotion/emotion_resonance.json", encoding="utf-8"))
ids_of = cfg["phoneme_id_map"]
sr = cfg["audio"]["sample_rate"]          # 22050
hop = cfg.get("hop_length", 256)          # 256

# 1. ๋ถˆ๊ทœ์น™ ๋ฐœ์Œ ์‚ฌ์ „(๋œ์†Œ๋ฆฌ ๋“ฑ) ๋ฐ ์˜์–ด/์ฝฉ๊ธ€๋ฆฌ์‰ฌยท์˜›๊ธ€์ž(แ„ซยทแ…€ยทแ„ฝ) ์Œ์ฐจ ์˜ˆ์‹œ
IRREGULAR_DICT = {"์ธ๊ถŒ": "์ธ๊ฟ˜", "์ •๊ถŒ": "์ •๊ฟ˜", "์†๊ฐ€๋ฝ": "์†๊นŒ๋ฝ", "๋ฌผ๊ฐ€": "๋ฌผ๊นŒ", "์ธ๊ธฐ": "์ธ๋ผ"}
ENGLISH_DICT = {"coffee": "์นดํ”ผ", "thank": "์ƒํฌ", "very": "แ„ซแ…ฆ๋ฆฌ", "music": "๋ฎคแ…€แ…ตแ†จ", "SNS": "์—์Šค์—”์—์Šค", "TV": "ํ‹ฐแ„ซใ…ฃ"}
ALPHA_NAMES = {
    "A": "์—์ด", "B": "๋น„", "C": "์‹œ", "D": "๋””", "E": "์ด", "F": "์—ํ”„", "G": "์ง€",
    "H": "์—์ด์น˜", "I": "์•„์ด", "J": "์ œ์ด", "K": "์ผ€์ด", "L": "์—˜", "M": "์— ", "N": "์—”",
    "O": "์˜ค", "P": "ํ”ผ", "Q": "ํ", "R": "์•„๋ฅด", "S": "์—์Šค", "T": "ํ‹ฐ", "U": "์œ ",
    "V": "แ„ซแ…ด", "W": "๋”๋ธ”์œ ", "X": "์—‘์Šค", "Y": "์™€์ด", "Z": "แ…€แ…ต",
}

def normalize_text(text):
    for k, v in sorted(IRREGULAR_DICT.items(), key=lambda x: -len(x[0])):
        text = text.replace(k, v)
    def repl_en(m):
        w = m.group(0)
        if w in ENGLISH_DICT:
            return ENGLISH_DICT[w]
        if w.lower() in ENGLISH_DICT:
            return ENGLISH_DICT[w.lower()]
        return "".join(ALPHA_NAMES.get(c.upper(), c) for c in w)
    return re.sub(r"[A-Za-z]+", repl_en, text)

# 2. ๊ฐˆ๋ผ์ฝ๊ธฐ: ๋ฌธ์žฅ๋ถ€ํ˜ธ ๋ฐ ํ•œ๊ตญ์–ด ์—ฐ๊ฒฐํ˜•ยท์ข…๊ฒฐํ˜• ์–ด๋ฏธ ์ž๋ฆฌ์—์„œ๋งŒ ํ˜ธํก ๋ถ„ํ• 
CONN_EOMI = ("๋ฉด์„œ", "๋Š”๋ฐ", "์ง€๋งŒ", "๋‹ˆ๊นŒ", "๋‹ค๊ฐ€", "๊ฑฐ๋‚˜", "๋“ ์ง€", "๋ ค๊ณ ", "์ž๋งˆ์ž", "๊ณ ", "๋ฉฐ", "์„œ")
FINAL_EOMI = (
    "๋‹ˆ๋‹ค", "์–ด์š”", "์•„์š”", "์—์š”", "์˜ˆ์š”", "ํ•ด์š”", "์„ธ์š”", "๋„ค์š”", "๊ตฐ์š”", "์ง€์š”",
    "๋Š”๋‹ค", "์—ˆ๋‹ค", "์•˜๋‹ค", "์˜€๋‹ค", "๊ฒ ๋‹ค", "ํ•œ๋‹ค", "ํ–ˆ๋‹ค", "๋‹ค", "์š”", "๊นŒ", "๋„ค",
)
CONJ_ADV = {"๊ทธ๋ฆฌ๊ณ ", "๊ทธ๋Ÿฌ๊ณ ", "๊ทธ๋ž˜์„œ", "๊ทธ๋Ÿฌ๋‹ˆ๊นŒ", "ํ•˜์ง€๋งŒ", "๊ทธ๋ ‡์ง€๋งŒ", "๊ทธ๋Ÿฌ๋‹ค๊ฐ€", "๊ทธ๋Ÿฌ๋ฉด์„œ"}
PUNCT_CHARS = set(".!?,โ€ฆ;โ€”โ€•โ€“ใ€‚๏ผ๏ผŸ")

def should_split_eojeol(eojeol):
    if eojeol in CONJ_ADV:
        return False
    if any(ch in PUNCT_CHARS for ch in eojeol):
        return True
    hangul = re.sub(r"[^๊ฐ€-ํžฃ]+$", "", eojeol)
    if len(hangul) < 2:
        return False
    for e in CONN_EOMI:
        if hangul.endswith(e) and len(hangul) > len(e):
            if e == "์„œ" and hangul[-2] in ("์—", "๊ป˜", "๋กœ"):  # ์กฐ์‚ฌ(์—์„œยท๊ป˜์„œยท๋กœ์„œ) ์ œ์™ธ
                continue
            return True
    for e in FINAL_EOMI:
        if hangul.endswith(e) and len(hangul) > len(e):
            return True
    return False

def split_by_eomi(text):
    words = text.strip().split()
    if len(words) <= 1:
        return [text.strip()] if text.strip() else []
    chunks, cur = [], []
    for i, w in enumerate(words):
        cur.append(w)
        if i < len(words) - 1 and should_split_eojeol(w):
            chunks.append(" ".join(cur))
            cur = []
    if cur:
        chunks.append(" ".join(cur))
    return chunks

# 3. NFD ์ž๋ชจ ๋ฒˆํ˜ธ์—ด ๋ฐ ์‹ ๊ฒฝ๊ณต๋ช…(res) ์ƒ์„ฑ
def to_ids(text):
    ids = ids_of["^"] + ids_of["_"]
    for ch in unicodedata.normalize("NFD", text):
        if ch in ids_of:
            ids += ids_of[ch] + ids_of["_"]
    return ids + ids_of["$"]

def res_for(emotion=None, strength=1.0):
    r = np.zeros((1, emo["res"]["๊ธธ์ด"]), dtype=np.float32)
    if emotion:
        key = str(emo["๊ฐ์ •"][emotion])          # ๋ฌด๊ฐ์ •(250)์€ ํ‘œ์— ์—†์Œ โ†’ 0
        knob, tail = emo["res"]["๋…ธ๋ธŒ"], emo["res"]["๊ฐ์ •๊ผฌ๋ฆฌ"]
        r[0, knob["์ž๋ฆฌ"]:knob["์ž๋ฆฌ"] + knob["์นธ"]] = np.array(emo["๋…ธ๋ธŒํ‘œ"].get(key, [0.0] * knob["์นธ"])) * knob["๋ฐฐ์ˆ˜"] * strength
        r[0, tail["์ž๋ฆฌ"]:tail["์ž๋ฆฌ"] + tail["์นธ"]] = np.array(emo["๊ผฌ๋ฆฌํ‘œ"].get(key, [0.0] * tail["์นธ"])) * tail["๋ฐฐ์ˆ˜"] * strength
    return r

# 4. ํ‘œ์ค€ ์ •์†(0.85) + ๊ฐ์ •๋ณ„ ๋น ๋ฅด๊ธฐ(1.08 / 1.0 / 0.93, ํ™•์‹ ๋„ >= 0.4) + ๊ฐˆ๋ผ์ฝ๊ธฐ(0.01์ดˆ ์ด์Œ) ํ•ฉ์„ฑ
BASE_SPEED = 0.85
SPEED_MULT = {"๋А๋ฆฌ๊ฒŒ": 1.08, "๋ณดํ†ต": 1.0, "๋น ๋ฅด๊ฒŒ": 0.93}

sess = ort.InferenceSession("piper-plus.onnx", providers=["CPUExecutionProvider"])

def speak(text, speaker="nangdok", emotion=None, strength=1.0, speed_label="๋ณดํ†ต", speed_conf=1.0, gap_sec=0.01):
    text = normalize_text(text)
    chunks = split_by_eomi(text)
    length_scale = BASE_SPEED * (SPEED_MULT.get(speed_label, 1.0) if speed_conf >= 0.4 else 1.0)
    scales = np.array([0.667, length_scale, 0.8], dtype=np.float32)
    sid = np.array([cfg["speaker_id_map"][speaker]], dtype=np.int64)
    res = res_for(emotion, strength)
    gap = np.zeros(int(sr * gap_sec), dtype=np.float32)
    head_len = len(ids_of["^"] + ids_of["_"])
    tail_len = len(ids_of["$"])

    pieces = []
    for idx, chunk in enumerate(chunks):
        chunk_str = chunk + (" " if idx < len(chunks) - 1 else "")
        x = np.array([to_ids(chunk_str)], dtype=np.int64)
        out, durs = sess.run(None, {
            "input": x,
            "input_lengths": np.array([x.shape[1]], dtype=np.int64),
            "scales": scales,
            "sid": sid,
            "res": res,
        })
        wav = out.squeeze()
        d = durs.squeeze()
        # ์กฐ๊ฐ ๊ฒฝ๊ณ„์— ๋ง๋ถ™์ธ ๋จธ๋ฆฌ(^ _)ยท๊ผฌ๋ฆฌ($) ๊ตฌ๊ฐ„์„ durations๋กœ ์ •๋ฐ€ํ•˜๊ฒŒ ์ž˜๋ผ๋ƒ„
        trim_head = 0 if idx == 0 else int(round(float(d[:head_len].sum()) * hop))
        trim_tail = len(wav) if idx == len(chunks) - 1 else int(round(float(d[:-tail_len].sum()) * hop))
        trim_head = max(0, min(trim_head, len(wav)))
        trim_tail = max(trim_head, min(trim_tail, len(wav)))
        if idx > 0 and len(gap) > 0:
            pieces.append(gap)
        pieces.append(wav[trim_head:trim_tail])
    return np.concatenate(pieces) if pieces else np.zeros(0, dtype=np.float32)

# ๋ฌด๊ฐ์ • ๊ธฐ๋ณธ ๋‚ญ๋… (์–ด๋ฏธยท๋ฌธ์žฅ๋ถ€ํ˜ธ ๊ฐˆ๋ผ์ฝ๊ธฐ + 0.85 ์ •์†)
audio = speak("์•ˆ๋…•ํ•˜์„ธ์š”. ์˜ค๋Š˜์€ ๋‚ ์”จ๊ฐ€ ์ฐธ ์ข‹์•˜๊ณ , coffee ํ•œ ์ž” ๋งˆ์‹œ๋ฉฐ ์‚ฐ์ฑ…ํ•˜๊ธฐ์—๋„ ์•„์ฃผ ์ข‹๋„ค์š”.")
# ๊ฐ์ • ์‹ ๊ฒฝ๊ณต๋ช… + ๋น ๋ฅด๊ธฐ ๊ฒฐํ•ฉ ๋‚ญ๋…
angry = speak("๋‹น์žฅ ์—ฌ๊ธฐ์„œ ๋‚˜๊ฐ€!", speaker="seungwoo", emotion="๋ถ„๋…ธ", speed_label="๋น ๋ฅด๊ฒŒ")

with wave.open("out.wav", "wb") as w:
    w.setnchannels(1); w.setsampwidth(2); w.setframerate(sr)
    w.writeframes((np.clip(audio, -1, 1) * 32767).astype(np.int16).tobytes())

ํ™”์ž ์•ˆ๋‚ด (speaker_id_map)

speaker_id_map์— 26์นธ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ญ๋…(ํ•ด์„ค)์€ nangdok(1), ์ฃผ์š” ์„ฑ์šฐ ๋ชฉ์†Œ๋ฆฌ๋Š” seungwoo(0) ยท joyjjang(2) ยท seungchul(3) ยท ์†Œ๋ผ(6) ยท ์ง€์šฐ(23) ๋“ฑ์ž…๋‹ˆ๋‹ค. ๊ฐ ํ™”์ž๊ฐ€ ์–ด๋–ค 31์ฐจ์› ๋ฐœ์„ฑ ๊ณต๋ช… ์ฃผํŒŒ์ˆ˜๋กœ ๋“ค์–ด๊ฐ€๋Š”์ง€๋Š” resonance/speaker_features.json์— ์ˆ˜๋ก๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌธ๋งฅ ๊ธฐ๋ฐ˜ ์ „์šฉ ๊ฐ์ • ๋ชจ๋ธ ์“ฐ๋Š” ๋ฒ• (emotion/emotion_int8.onnx)

์‚ฌ์šฉ์ž๊ฐ€ ์ˆ˜๋™์œผ๋กœ ๊ฐ์ • ํƒœ๊ทธ๋ฅผ ์ž…๋ ฅํ•˜์ง€ ์•Š์•„๋„ ์ž์—ฐ์Šค๋Ÿฌ์šด ๊ฐ์ • ํ‘œํ˜„์ด ์œ ๋„๋˜๋„๋ก ์ง์ ‘ ํ•™์Šตํ•œ ๋ฌธ๋งฅ ๊ธฐ๋ฐ˜ ๊ฐ์ • ๋ถ„๋ฅ˜ ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค:

  • ํ† ํฌ๋‚˜์ด์ €: emotion/vocab.txt์˜ WordPiece (KoELECTRA-small v3 ๋™์ผ). [CLS] ๋ฌธ์žฅ [SEP], ์ตœ๋Œ€ 192 ํ† ํฐ. ์•ž๋’ค ๋ฌธ์žฅ ๋งฅ๋ฝ์„ ํ•จ๊ป˜ ์ค„ ๋•Œ๋Š” tokenizer(๋งฅ๋ฝ๊ธ€, ๋ฌธ์žฅ, truncation="only_first", max_length=192) ํ˜•์‹(์˜ˆ: "์•ž: ๋น„ํƒ„. ๋’ค: ๋ถ„๋…ธ.")์œผ๋กœ ๋„ฃ์Šต๋‹ˆ๋‹ค.
  • ์ž…๋ ฅ: input_ids, attention_mask, token_type_ids ([b, t] int64).
  • ์ถœ๋ ฅ ๋จธ๋ฆฌ (emotion/emotion_labels_full.json ์ฐธ์กฐ):
    • ๋ฌธ์žฅ ๋จธ๋ฆฌ [b, C]: ๊ฐ์ •(16) ยท ํฌ๊ธฐ(3) ยท ๋น ๋ฅด๊ธฐ(3: ๋А๋ฆฌ๊ฒŒ, ๋ณดํ†ต, ๋น ๋ฅด๊ฒŒ) ยท ์ˆจ๊ฒฐ(4) ยท ๋งํˆฌ(46)
    • ํ† ํฐ ๋จธ๋ฆฌ [b, t, C]: ๋ผ์šธํƒœ๊ทธ(27) ยท ๊ตฌ๊ฐ„(11)
  • ์ž๋™ ๋งคํ•‘ ํ๋ฆ„: ๊ฐ์ • ๋ฐ ๋งํˆฌ ๋จธ๋ฆฌ๊ฐ€ ๋ฌธ๋งฅ์—์„œ ์ถ”๋ก ํ•œ ๊ฐ์ •ยท๋งํˆฌ ๋ผ๋ฒจ์„ emotion_resonance.json์„ ํ†ตํ•ด 34์ฐจ์› res ๊ณต๋ช… ๋ฒกํ„ฐ๋กœ ์ž๋™ ๋ณ€ํ™˜ํ•˜๊ณ , ๋น ๋ฅด๊ธฐ ๋จธ๋ฆฌ์˜ ํ™•์‹ ๋„๊ฐ€ 0.4 ์ด์ƒ์ด๋ฉด SPEED_MULT ๋ฐฐ์ˆ˜(๋А๋ฆฌ๊ฒŒ: 1.08, ๋ณดํ†ต: 1.0, ๋น ๋ฅด๊ฒŒ: 0.93)๋ฅผ ๊ธฐ๋ณธ ๋ฐฐ์† 0.85์— ๊ณฑํ•ด scales์˜ length_scale๋กœ ์ž๋™ ์ฃผ์ž…ํ•ฉ๋‹ˆ๋‹ค.

โš ๏ธ ๋ผ์ด์„ ์Šค ๋ฐ ์ €์ž‘์ž ํ‘œ์‹œ ์˜๋ฌด (License, Attribution & Citation)

  • ์‘์šฉยทํŒŒ์ƒยท์žฌ๊ฐœ๋ฐœ ์‹œ ์›์ €์ž‘์ž ์ด๋‹ˆ์…œ(watchpen) ๋ฐ ๊ณต์‹ ๊นƒํ—ˆ๋ธŒ ์ฃผ์†Œ ์ฒจ๋ถ€ ์˜๋ฌด:
    • ๋ณธ ๋ชจ๋ธ(piper-plus), 3๋Œ€ ์‹ ๊ฒฝ๊ณต๋ช… ์ฃผํŒŒ์ˆ˜ ํ‘œ(jamo_features.json, speaker_features.json, emotion_resonance.json), ์ž๋ชจ ์ŒํŒŒ ๋ฐœ์„ฑ ๊ตฌ์กฐ, ์ œ๋กœ๋“€๋ ˆ์ด์…˜ ๊ฐ์ • ํƒœ๊ทธ ์ฒด๊ณ„, ๋˜๋Š” ํฌํ•จ๋œ ์ฝ”๋“œ/๊ฐ€์ค‘์น˜๋ฅผ **์‘์šฉํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ยทํŒŒ์ƒยท์žฌ๊ฐœ๋ฐœํ•˜์—ฌ ๋ฐฐํฌ/๊ณต๊ฐœํ•  ๊ฒฝ์šฐ, ๋ฐ˜๋“œ์‹œ ์›์ €์ž‘์ž ์ด๋‹ˆ์…œ(watchpen)๊ณผ ๊ณต์‹ ๊นƒํ—ˆ๋ธŒ ์ฃผ์†Œ(https://github.com/wacthpen/piper-plus)๋ฅผ ํ•จ๊ป˜ ์ฒจ๋ถ€(๋ช…์‹œ)**ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • Mandatory Attribution Requirement (English): If you adapt, modify, fine-tune, or redevelop this model (piper-plus), its neural resonance frequency tables, its Jamo acoustic vocalization architecture, or its codebase, you MUST explicitly credit the original author's handle/initials (**watchpen* / GitHub: wacthpen, Hugging Face: watchpen) AND attach the official GitHub repository URL (https://github.com/wacthpen/piper-plus) in your documentation, model card, and derivative works.*
  • ์‹ค์ œ ์‚ฌ๋žŒ ๋ชฉ์†Œ๋ฆฌ๋ฅผ ์‚ฌ์นญํ•˜๊ฑฐ๋‚˜ ์†์ด๋Š” ์šฉ๋„๋กœ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”.
  • ๊ฐ์ • ๋ถ„๋ฅ˜ ๋ชจ๋ธ์˜ ๊ธฐ๋ฐ˜ ๋ชจ๋ธ์€ monologg/koelectra-small-v3-discriminator์ž…๋‹ˆ๋‹ค.

์ธ์šฉ (Citation / BibTeX)

@misc{watchpen2026piperplus,
  author       = {watchpen},
  title        = {Piper Plus: Korean Neural-Resonance TTS with Fortis-Overgeneralization Suppression, Emotion-Expressive Neural Resonance & Acoustic Jamo Vocalization},
  year         = {2026},
  publisher    = {GitHub / Hugging Face},
  url          = {https://github.com/wacthpen/piper-plus},
  howpublished = {\url{https://github.com/wacthpen/piper-plus}, \url{https://huggingface.co/watchpen/piper-plus}}
}

English Summary

Piper Plus (Epoch 880 EMA) is a Korean multi-speaker neural text-to-speech model in the Piper (VITS) family exported to ONNX (22,050 Hz), engineered around four core innovations:

  1. Suppression of Excessive Fortis / Tensification Generalization:
    • Traditional Korean TTS models allow the text encoder's embedding/context memory layer (self.emb) to over-generalize tensification from training words (e.g., learning fortis [kk] from ์ธ๊ถŒ [inkkwon] and falsely tensifying lax consonants across ordinary words like ์†๊ถŒ).
    • Piper Plus structurally bypasses the fortis-contaminated embedding memory layer (jamo_feature_mode = "๋Œ€์ฒด", x = torch.where(jamo_mask, emb_f(jamo_feat[x]), x)), driving synthesis directly from 104-dimensional measured acoustic resonance vectors, paired with a Korean Tenseness Discriminator (tense_clf=True, tense_plain_weight=24.0 penalty for false tensification) and chest-resonance weight suppression (res_band_weights='0,2,4'). Lax consonants remain pure, while genuine irregular pronunciations are handled deterministically via a 1:1 Irregular Pronunciation Dictionary.
  2. Emotion-Expressive Neural Resonance, Context-Aware Auto Emotion Model & Zero-Duration Tags:
    • Emotions are injected via a 34-dimensional Neural Resonance vector (res) combining 3 vocal-tract resonance knobs (vocal-tract scale, chest resonance, actor's formant) and 15 measured voice-quality shifts (eGeMAPS 14 parameters + nasal coupling A1-P0).
    • A custom-trained Context-Aware Korean Emotion Classifier (emotion/emotion_int8.onnx, KoELECTRA-small int8) automatically analyzes sentence context to map emotion tags, speaking rate (base length_scale = 0.85 ร— 1.08 / 1.0 / 0.93), and resonance parameters without manual tagging.
    • Any inline emotion/phonation tags impart their acoustic resonance onto surrounding Jamo inside the encoder and are then stripped with Zero-Duration (_ํƒœ๊ทธ์นธ๋–ผ๊ธฐ scatter compaction, 0 frames) before the Duration Predictor โ€” producing pure emotional expression with zero spoken tag artifacts.
  3. Acoustic Character Vocalization via Direct Jamo Learning & Hunminjeongeum Haeryebon Mathematical Realization:
    • 49 Symbolic Columns Zeroed Out โ€” Only 31 Measured Acoustic Frequencies Active: In resonance/jamo_features.json (80 base columns + 24 tag columns = 104 columns), all 49 symbolic/one-hot indicator columns (letter ID, place, manner, tenseness) are strictly set to 0.0 (assert all(v == 0 ...)), and models.py replaces self.emb(x) 100% with self.emb_f(jamo_feat[x]). The neural network never sees symbolic letter identities โ€” it synthesizes speech solely from 31 physical acoustic frequency measurements:
      • Initial Consonants (16 cols โ€” ๅˆ่ฒๆœ‰็™ผๅ‹•ไน‹็พฉ & Five Sounds / Stroke Addition): Burst frequency/peak/spread, low-mid/mid-high energy ratios, aspiration duration/spectrum, intensity, F2/F3 locus shifts, voicing F1, and post-consonantal pitch. Initial ใ…‡ is explicitly populated with measured glottal initiation frequencies per Haeryebon's ใ€Œใ…‡ใ€‚ๅ–‰้Ÿณใ€‚ๅฆ‚ๆฌฒๅญ—ๅˆ็™ผ่ฒใ€ so consecutive vowels (์•„์•„, ์œผ์•—) never fall back to self.emb or collapse.
      • Medial Vowels (7 cols โ€” Heaven-Earth-Human ใ†, ใ…ก, ใ…ฃ & Diphthong Trajectories): Formant frequencies at 10% (F1ยทF2ยทF3 start) and 75% (F1ยทF2ยทF3 end) plus vowel duration capture both monophthongs and compound diphthong trajectories.
      • Final Codas (8 cols + 16 Liaison cols โ€” ็ต‚่ฒๅพฉ็”จๅˆ่ฒ, ๅ…ซๅญ—ๅฏ่ถณ็”จ, ไธๆทธไธๆฟ, ่‡ชๅทฆ่€Œๅณ in ํ•ด๋ก€๋ณธ๋ฐ›์นจ.py): At Epoch 632, naive median ratios caused ๊ฐ„ยท๊ฐยท๊ฐ• to collapse into [์นธ]. Implementing Haeryebon's five coda laws โ€” pairing homorganic stops & nasals (ใ„ฑยทใ† 1,503 Hz, ใ„ดยทใ„ท 1,875 Hz, ใ„น 1,813 Hz, ใ…ยทใ…‚ 559 Hz) for F2/F3 locus targets (z2์ง, z3์ง), mapping the 8-coda neutralization (ๅ…ซๅญ—ๅฏ่ถณ็”จ), assigning voicing & nasal anti-resonance zeros (๋ฐ›์นจ์ฝง์†Œ๋ฆฌ๊ณจkHz: ใ„ด 1.38 / ใ… 1.30 / ใ…‡ 1.73 kHz) exclusively to ไธๆทธไธๆฟ sonorants (ใ„ดยทใ„นยทใ…ยทใ…‡), and encoding double codas (ใ„ณ~ใ…„) left-to-right (่‡ชๅทฆ่€Œๅณ: 1st consonant closure locus โ†’ 2nd consonant locus + prevocalic liaison in the 16 initial columns) โ€” cleanly separated coda distances (ใ„ดโ†”ใ…‡ 0.98 โ†’ 1.95, ใ„ฑโ†”ใ…‚ 1.45 โ†’ 3.72).
    • Archaic Hangul Jamo for Foreign/English Sounds & Konglish OOV Handling: Archaic Hangul consonants (แ…— [f], แ„ซ/ใ…ธ [v], แ…€/ใ…ฟ [z], แ„ผ [ฮธ], แ„ฝ [รฐ], IDs 384~388) are populated with measured English fricative frequencies in the exact same 16 initial-consonant columns and vocalized through the single shared emb_f projection, while unseen English words and acronyms are seamlessly converted into natural Korean-style pronunciation (Konglish / ARPAbet-to-Hangul + alphabet vocalization).
  4. Ultra-Light, Near-Zero Heat on Mobile/CPU & Prosodic Ending Splitting (๊ฐˆ๋ผ์ฝ๊ธฐ):
    • Combining single linear resonance projections (emb_f, emb_g_res, emb_res) with a 4-subband MB-iSTFT-VITS (PQMF) decoder makes inference extremely lightweight, running in real time on mobile phones and standard CPUs with near-zero thermal output.
    • Removes mechanical word-boundary (eojeol_boundary) CumSum breaks and splits long sentences only at punctuation and Korean connective/sentence-final verb endings (split_by_eomi), trimming boundary tokens precisely via durations and joining chunks with a 10 ms (0.01 s) breath gap.

๐Ÿ“œ ํ—Œ์ • ๋ฐ ๊ธฐ๋… (Dedication)

"์˜ฌํ•ด๋Š” ํ›ˆ๋ฏผ์ •์Œ ๋ฐ˜ํฌ 580๋Œ์ž…๋‹ˆ๋‹ค. ์„ธ์ข…๋Œ€์™•์€ ์œ„๋Œ€ํ•ฉ๋‹ˆ๋‹ค. ใ€Žํ›ˆ๋ฏผ์ •์Œ ํ•ด๋ก€๋ณธใ€์„ ๋ณธ๋–  ๋ฐœ์„ฑ ์ฃผํŒŒ์ˆ˜๋ฅผ ๋งž์ถ”์–ด ์ด ํ”„๋กœ์ ํŠธ๋ฅผ ์™„์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค."

๋ฐœ์„ฑ ๊ธฐ๊ด€์˜ ๋ชจ์–‘๊ณผ ์†Œ๋ฆฌ ์ด์น˜๋ฅผ ๋ณธ๋œฌ ใ€Žํ›ˆ๋ฏผ์ •์Œ ํ•ด๋ก€๋ณธ(่จ“ๆฐ‘ๆญฃ้Ÿณ ่งฃไพ‹ๆœฌ)ใ€์˜ ์œ„๋Œ€ํ•œ ์ œ์ž ์›๋ฆฌ๋ฅผ ํ˜„๋Œ€ ์‹ ๊ฒฝ๋ง ์ŒํŒŒ ๋ฐœ์„ฑ ์ฃผํŒŒ์ˆ˜๋กœ ๊ณ ์Šค๋ž€ํžˆ ์˜ฎ๊ฒจ ๋งž์ถ”๋ฉฐ, ํ›ˆ๋ฏผ์ •์Œ ๋ฐ˜ํฌ 580๋Œ(1446~2026)์„ ๋งž์•„ ์„ธ์ข…๋Œ€์™•์˜ ์• ๋ฏผ ์ •์‹ ๊ณผ ๊ณผํ•™์  ์„ฑ์Œ(่ฒ้Ÿณ) ์ฒ ํ•™์— ๊นŠ์€ ๊ฒฝ์˜๋ฅผ ํ‘œํ•ฉ๋‹ˆ๋‹ค.

This year marks the 580th anniversary of the promulgation of Hunminjeongeum (1446โ€“2026). King Sejong the Great is truly great. We conducted this project by aligning vocal resonance frequencies modeled after the Hunminjeongeum Haeryebon (่จ“ๆฐ‘ๆญฃ้Ÿณ ่งฃไพ‹ๆœฌ).

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. ๐Ÿ™‹ Ask for provider support