use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VoiceProfile {
pub npc_name: String,
pub base_voice: BaseVoice,
pub emotional_range: EmotionalVoiceRange,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BaseVoice {
pub voice_id: String,
pub base_pitch: f32,
pub base_rate: f32,
pub base_volume: f32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Gender {
Male,
Female,
NonBinary,
Androgynous,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EmotionalVoiceRange {
pub happiness_range: (f32, f32),
pub anger_range: (f32, f32),
pub fear_range: (f32, f32),
pub trust_range: (f32, f32),
pub energy_range: (f32, f32),
pub curiosity_range: (f32, f32),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VoiceSettings {
pub voice_id: String,
pub stability: f32,
pub similarity_boost: f32,
pub style_exaggeration: f32,
}
impl VoiceProfile {
pub fn default_for_npc(npc_name: &str) -> Self {
Self {
npc_name: npc_name.to_string(),
base_voice: BaseVoice {
voice_id: "JBFqnCBsd6RMkjVDRZzb".to_string(),
base_pitch: 0.5,
base_rate: 0.5,
base_volume: 0.7,
},
emotional_range: EmotionalVoiceRange {
happiness_range: (0.0, 0.3),
anger_range: (0.0, 0.4),
fear_range: (0.0, 0.3),
trust_range: (0.0, 0.2),
energy_range: (0.0, 0.3),
curiosity_range: (0.0, 0.3),
},
}
}
pub fn merchant() -> Self {
Self {
npc_name: "merchant".to_string(),
base_voice: BaseVoice {
voice_id: "friendly_male".to_string(),
base_pitch: 0.4,
base_rate: 0.6,
base_volume: 0.8,
},
emotional_range: EmotionalVoiceRange {
happiness_range: (0.1, 0.4),
anger_range: (0.0, 0.2),
fear_range: (0.0, 0.1),
trust_range: (0.0, 0.1),
energy_range: (0.2, 0.5),
curiosity_range: (0.0, 0.5),
},
}
}
pub fn guard() -> Self {
Self {
npc_name: "guard".to_string(),
base_voice: BaseVoice {
voice_id: "authoritative_male".to_string(),
base_pitch: 0.3,
base_rate: 0.4,
base_volume: 0.9,
},
emotional_range: EmotionalVoiceRange {
happiness_range: (0.0, 0.2),
anger_range: (0.2, 0.6),
fear_range: (0.0, 0.1),
trust_range: (0.0, 0.1),
energy_range: (0.0, 0.3),
curiosity_range: (0.0, 0.6),
},
}
}
pub fn wizard() -> Self {
Self {
npc_name: "wizard".to_string(),
base_voice: BaseVoice {
voice_id: "wise_elder".to_string(),
base_pitch: 0.2,
base_rate: 0.3,
base_volume: 0.6,
},
emotional_range: EmotionalVoiceRange {
happiness_range: (0.0, 0.3),
anger_range: (0.1, 0.4),
fear_range: (0.0, 0.2),
trust_range: (0.1, 0.3),
energy_range: (0.0, 0.4),
curiosity_range: (0.0, 0.2), },
}
}
}
impl VoiceSettings {
pub fn from_profile(profile: &VoiceProfile) -> Self {
Self {
voice_id: profile.base_voice.voice_id.clone(),
stability: 0.75,
similarity_boost: 0.75,
style_exaggeration: 0.3, }
}
}
impl EmotionalVoiceRange {
pub fn from_personality(personality: &str) -> Self {
let personality_lower = personality.to_lowercase();
let mut range = Self {
happiness_range: (0.0, 0.3),
anger_range: (0.0, 0.3),
fear_range: (0.0, 0.2),
trust_range: (0.0, 0.2),
energy_range: (0.0, 0.3),
curiosity_range: (0.0, 0.4),
};
if personality_lower.contains("cheerful") || personality_lower.contains("optimistic") {
range.happiness_range = (0.3, 0.5);
}
if personality_lower.contains("grumpy") || personality_lower.contains("irritable") {
range.anger_range = (0.3, 0.5);
}
if personality_lower.contains("nervous") || personality_lower.contains("anxious") {
range.fear_range = (0.2, 0.6);
}
if personality_lower.contains("energetic") || personality_lower.contains("enthusiastic") {
range.happiness_range = (0.2, 0.6);
range.energy_range = (0.3, 0.7);
}
range
}
}