use crate::buffer::AudioBuffer;
pub use prani::species::{Species, SpeciesParams, VocalApparatus};
pub use prani::voice::CreatureVoice;
pub use prani::tract::CreatureTract;
pub use prani::vocalization::Vocalization;
pub use prani::vocalization::{CallIntent, IntentModifiers};
pub use prani::error::PraniError;
pub fn render_vocalization(
voice: &CreatureVoice,
vocalization: &Vocalization,
sample_rate: u32,
duration: f32,
) -> crate::Result<AudioBuffer> {
let samples = voice
.vocalize(vocalization, sample_rate as f32, duration)
.map_err(|e| crate::NadaError::Dsp(format!("creature vocalization failed: {e}")))?;
AudioBuffer::from_interleaved(samples, 1, sample_rate)
.map_err(|e| crate::NadaError::Dsp(format!("buffer from creature output: {e}")))
}
pub fn render_vocalization_with_intent(
voice: &CreatureVoice,
vocalization: &Vocalization,
intent: CallIntent,
sample_rate: u32,
duration: f32,
) -> crate::Result<AudioBuffer> {
let samples = voice
.vocalize_with_intent(vocalization, intent, sample_rate as f32, duration)
.map_err(|e| crate::NadaError::Dsp(format!("creature vocalization failed: {e}")))?;
AudioBuffer::from_interleaved(samples, 1, sample_rate)
.map_err(|e| crate::NadaError::Dsp(format!("buffer from creature output: {e}")))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn wolf_howl() {
let voice = CreatureVoice::new(Species::Wolf);
let buf = render_vocalization(&voice, &Vocalization::Howl, 44100, 0.5).unwrap();
assert!(buf.frames() > 0);
assert!(buf.rms() > 0.0);
assert!(buf.samples().iter().all(|s| s.is_finite()));
}
#[test]
fn cat_purr() {
let voice = CreatureVoice::new(Species::Cat);
let buf = render_vocalization(&voice, &Vocalization::Purr, 44100, 0.5).unwrap();
assert!(buf.frames() > 0);
assert!(buf.samples().iter().all(|s| s.is_finite()));
}
#[test]
fn dragon_roar_with_intent() {
let voice = CreatureVoice::new(Species::Dragon);
let buf = render_vocalization_with_intent(
&voice,
&Vocalization::Roar,
CallIntent::Threat,
44100,
0.5,
)
.unwrap();
assert!(buf.frames() > 0);
assert!(buf.rms() > 0.0);
}
#[test]
fn songbird_chirp() {
let voice = CreatureVoice::new(Species::Songbird);
let buf = render_vocalization(&voice, &Vocalization::Chirp, 44100, 0.3).unwrap();
assert!(buf.frames() > 0);
}
#[test]
fn species_supports_vocalization() {
assert!(Species::Wolf.supports_vocalization(&Vocalization::Howl));
assert!(Species::Snake.supports_vocalization(&Vocalization::Hiss));
assert!(Species::Cricket.supports_vocalization(&Vocalization::Stridulate));
}
#[test]
fn voice_builder() {
let voice = CreatureVoice::new(Species::Lion)
.with_size(1.3)
.with_breathiness(0.2);
let buf = render_vocalization(&voice, &Vocalization::Roar, 44100, 0.5).unwrap();
assert!(buf.rms() > 0.0);
}
}