import type { EmotionTag } from "@kokorone/shared"; import type { Archetype } from "../personality/archetype-params.js"; export type SentenceEndContour = "RISING" | "FALLING" | "FLAT"; export interface ProsodyTemplate { rateDeltaPercent: number; // 語速變化百分比,正值變快 pitchDeltaSemitones: number; // 音高變化(半音),正值變高 volumeDeltaPercent: number; // 音量變化百分比,正值變大 contour: SentenceEndContour; characteristic: string; // 描述性文字,供除錯/前端顯示 } // P-3 情緒 → 韻律對照:情緒狀態機的輸出直接驅動韻律參數。 export const EMOTION_PROSODY_TABLE: Record = { CALM: { rateDeltaPercent: 0, pitchDeltaSemitones: 0, volumeDeltaPercent: 0, contour: "FLAT", characteristic: "角色預設值" }, JOY: { rateDeltaPercent: 15, pitchDeltaSemitones: 1.5, volumeDeltaPercent: 10, contour: "RISING", characteristic: "句尾上揚、偶爾帶笑聲" }, SAD: { rateDeltaPercent: -20, pitchDeltaSemitones: -1.5, volumeDeltaPercent: -15, contour: "FALLING", characteristic: "句間停頓變長、句尾下沉" }, ALERT: { rateDeltaPercent: 5, pitchDeltaSemitones: 0, volumeDeltaPercent: 0, contour: "FLAT", characteristic: "語調變平、字句變短" }, SHY: { rateDeltaPercent: -5, pitchDeltaSemitones: 2, volumeDeltaPercent: -10, contour: "FLAT", characteristic: "結巴、語尾變小聲,忽快忽慢" }, GRUMPY: { rateDeltaPercent: 10, pitchDeltaSemitones: 1, volumeDeltaPercent: -5, contour: "FALLING", characteristic: "「哼」開頭,先大後小" }, }; // P-1 Voice Sheet 預設值:依性格原型推導基準語速與音域幅度(同 G-5「原型 → 種子預設」的作法)。 export const DEFAULT_VOICE_SHEET_BY_ARCHETYPE: Record = { 傲嬌: { baseTimbre: "清亮少女音", baseRate: 1.05, pitchRangeSemitones: 5 }, 冷淡: { baseTimbre: "低沉平穩音", baseRate: 0.85, pitchRangeSemitones: 1.5 }, 天然呆: { baseTimbre: "軟糯蘿莉音", baseRate: 0.95, pitchRangeSemitones: 4 }, 元氣: { baseTimbre: "清亮少女音", baseRate: 1.2, pitchRangeSemitones: 6 }, 大小姐: { baseTimbre: "低沉御姐音", baseRate: 0.95, pitchRangeSemitones: 3.5 }, 三無: { baseTimbre: "軟糯蘿莉音", baseRate: 0.8, pitchRangeSemitones: 0.5 }, }; const DEFAULT_VOICE_SHEET_FALLBACK = { baseTimbre: "清亮少女音", baseRate: 1.0, pitchRangeSemitones: 3 }; export function defaultVoiceSheetFor(archetype: string) { return DEFAULT_VOICE_SHEET_BY_ARCHETYPE[archetype as Archetype] ?? DEFAULT_VOICE_SHEET_FALLBACK; } // P-2 非語言發聲庫:依情緒狀態的預設候選詞,角色的 Voice Sheet 口頭聲響庫可補充、禁則可過濾排除。 export const DEFAULT_INTERJECTIONS_BY_EMOTION: Record = { CALM: ["嗯"], JOY: ["欸嘿嘿", "呵呵"], SAD: ["唔……", "……"], ALERT: ["嗯?", "欸?!"], SHY: ["那個……就是……", "唔……"], GRUMPY: ["哼!", "哼……"], }; // P-2 停頓:情緒強度達門檻(沿用 C-4 高情緒事件的判斷門檻)且屬於重大話題時,回答前故意停頓 1~2 秒。 export const SIGNIFICANT_PAUSE_THRESHOLD = 0.6; export const SIGNIFICANT_PAUSE_SECONDS = [1, 2]; export const DEFAULT_PAUSE_SECONDS = 0.2; // P-2 打斷與搶話:需要「talkative」特徵(見 archetype-params.ts)且親密度達朋友分層以上才可能插話。 export const INTERRUPT_MIN_INTIMACY = 40; // P-2 親密度影響音量與氣音比例:對陌生人聲音端正清晰,對摯友放鬆、氣音比例上升。 export function intimacyVoiceModifiers(intimacy: number): { volumeMultiplier: number; breathinessRatio: number } { const clamped = Math.max(0, Math.min(100, intimacy)); return { volumeMultiplier: 1 - (clamped / 100) * 0.15, // 端正清晰(1.0) → 放鬆慵懶(0.85) breathinessRatio: clamped / 100, }; }