ThreadAbort's picture
Refactor: Remove internationalization (i18n) support and related files
e3e7558
//! Marine algorithm configuration
//!
//! Tunable parameters for jitter detection. These have been calibrated
//! for speech/audio processing but can be adjusted for specific use cases.
#![cfg_attr(not(feature = "std"), no_std)]
/// Configuration for Marine salience detection
///
/// These parameters control sensitivity and behavior of the jitter detector.
/// The defaults are tuned for speech processing at common sample rates.
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub struct MarineConfig {
/// Minimum amplitude to consider a sample (gating threshold)
/// Samples below this are ignored as noise
/// Default: 1e-3 (~-60dB)
pub clip_threshold: f32,
/// EMA smoothing factor for period tracking (0..1)
/// Lower = smoother, slower adaptation
/// Default: 0.01
pub ema_period_alpha: f32,
/// EMA smoothing factor for amplitude tracking (0..1)
/// Default: 0.01
pub ema_amp_alpha: f32,
/// Minimum inter-peak period in samples
/// Rejects peaks closer than this (filters high-frequency noise)
/// Default: sample_rate / 4000 (~4kHz upper F0)
pub min_period: u32,
/// Maximum inter-peak period in samples
/// Rejects peaks farther than this (filters very low frequencies)
/// Default: sample_rate / 60 (~60Hz lower F0)
pub max_period: u32,
/// Threshold below which jitter is considered "low" (stable)
/// Default: 0.02
pub jitter_low: f32,
/// Threshold above which jitter is considered "high" (unstable)
/// Default: 0.60
pub jitter_high: f32,
}
impl MarineConfig {
/// Create config optimized for speech at given sample rate
///
/// # Arguments
/// * `sample_rate` - Audio sample rate in Hz (e.g., 22050, 44100)
///
/// # Example
/// ```
/// use marine_salience::MarineConfig;
/// let config = MarineConfig::speech_default(22050);
/// assert!(config.min_period < config.max_period);
/// ```
pub const fn speech_default(sample_rate: u32) -> Self {
// F0 range: ~60Hz (low male) to ~4kHz (includes harmonics)
let min_period = sample_rate / 4000; // Upper bound
let max_period = sample_rate / 60; // Lower bound
Self {
clip_threshold: 1e-3,
ema_period_alpha: 0.01,
ema_amp_alpha: 0.01,
min_period,
max_period,
jitter_low: 0.02,
jitter_high: 0.60,
}
}
/// Create config for high-sensitivity detection
/// More peaks detected, faster adaptation
pub const fn high_sensitivity(sample_rate: u32) -> Self {
let min_period = sample_rate / 8000;
let max_period = sample_rate / 40;
Self {
clip_threshold: 5e-4,
ema_period_alpha: 0.05,
ema_amp_alpha: 0.05,
min_period,
max_period,
jitter_low: 0.01,
jitter_high: 0.50,
}
}
/// Create config for TTS output validation
/// Tuned to detect synthetic artifacts
pub const fn tts_validation(sample_rate: u32) -> Self {
let min_period = sample_rate / 4000;
let max_period = sample_rate / 80;
Self {
clip_threshold: 1e-3,
ema_period_alpha: 0.02,
ema_amp_alpha: 0.02,
min_period,
max_period,
jitter_low: 0.015, // Stricter for synthetic speech
jitter_high: 0.40, // More sensitive to artifacts
}
}
}
impl Default for MarineConfig {
fn default() -> Self {
// Default to 22050 Hz (common TTS sample rate)
Self::speech_default(22050)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_speech_default_periods() {
let config = MarineConfig::speech_default(22050);
assert!(config.min_period < config.max_period);
assert_eq!(config.min_period, 22050 / 4000); // 5 samples
assert_eq!(config.max_period, 22050 / 60); // 367 samples
}
#[test]
fn test_different_sample_rates() {
let config_22k = MarineConfig::speech_default(22050);
let config_44k = MarineConfig::speech_default(44100);
let config_48k = MarineConfig::speech_default(48000);
// Higher sample rates = more samples per period
assert!(config_44k.max_period > config_22k.max_period);
assert!(config_48k.max_period > config_44k.max_period);
}
}