← back to jeffrydegrande__voicevo

Function bodies 463 total

All specs Real LLM only Function bodies
compute_fatigue function · rust · L13-L49 (37 LOC)
core/src/analysis/fatigue.rs
pub fn compute_fatigue(
    mpt_per_trial: Vec<f32>,
    cpps_per_trial: Vec<Option<f32>>,
    effort_per_trial: Vec<u8>,
) -> Option<FatigueAnalysis> {
    if mpt_per_trial.len() < 2 {
        return None;
    }

    // Compute MPT slope: trial index (0, 1, 2, ...) vs MPT
    let mpt_points: Vec<(f32, f32)> = mpt_per_trial
        .iter()
        .enumerate()
        .map(|(i, &mpt)| (i as f32, mpt))
        .collect();
    let (mpt_slope, _) = util::linear_regression(&mpt_points);

    // Compute CPPS slope from trials that have CPPS values
    let cpps_points: Vec<(f32, f32)> = cpps_per_trial
        .iter()
        .enumerate()
        .filter_map(|(i, cpps)| cpps.map(|c| (i as f32, c)))
        .collect();
    let cpps_slope = if cpps_points.len() >= 2 {
        util::linear_regression(&cpps_points).0
    } else {
        0.0
    };

    Some(FatigueAnalysis {
        mpt_per_trial,
        cpps_per_trial,
        effort_per_trial,
        mpt_slope,
        cpps_slope,
    })
}
compute_from_raw function · rust · L53-L60 (8 LOC)
core/src/analysis/fatigue.rs
pub fn compute_from_raw(raw: &FatigueRawData) -> Option<FatigueAnalysis> {
    let cpps_per_trial = vec![None; raw.mpt_per_trial.len()];
    compute_fatigue(
        raw.mpt_per_trial.clone(),
        cpps_per_trial,
        raw.effort_per_trial.clone(),
    )
}
declining_mpt_negative_slope function · rust · L67-L79 (13 LOC)
core/src/analysis/fatigue.rs
    fn declining_mpt_negative_slope() {
        let result = compute_fatigue(
            vec![10.0, 9.0, 8.0, 7.0, 6.0],
            vec![None; 5],
            vec![3, 4, 5, 6, 7],
        )
        .unwrap();
        assert!(
            result.mpt_slope < -0.5,
            "Declining MPT should have negative slope, got {:.3}",
            result.mpt_slope
        );
    }
stable_mpt_flat_slope function · rust · L82-L94 (13 LOC)
core/src/analysis/fatigue.rs
    fn stable_mpt_flat_slope() {
        let result = compute_fatigue(
            vec![10.0, 10.0, 10.0, 10.0],
            vec![None; 4],
            vec![3, 3, 3, 3],
        )
        .unwrap();
        assert!(
            result.mpt_slope.abs() < 0.1,
            "Stable MPT should have ~0 slope, got {:.3}",
            result.mpt_slope
        );
    }
cpps_slope_computed function · rust · L97-L109 (13 LOC)
core/src/analysis/fatigue.rs
    fn cpps_slope_computed() {
        let result = compute_fatigue(
            vec![10.0, 9.0, 8.0],
            vec![Some(8.0), Some(7.0), Some(6.0)],
            vec![3, 4, 5],
        )
        .unwrap();
        assert!(
            result.cpps_slope < -0.5,
            "Declining CPPS should have negative slope, got {:.3}",
            result.cpps_slope
        );
    }
cpps_slope_zero_when_no_cpps function · rust · L112-L120 (9 LOC)
core/src/analysis/fatigue.rs
    fn cpps_slope_zero_when_no_cpps() {
        let result = compute_fatigue(
            vec![10.0, 9.0, 8.0],
            vec![None, None, None],
            vec![3, 4, 5],
        )
        .unwrap();
        assert_eq!(result.cpps_slope, 0.0);
    }
too_few_trials function · rust · L123-L125 (3 LOC)
core/src/analysis/fatigue.rs
    fn too_few_trials() {
        assert!(compute_fatigue(vec![10.0], vec![None], vec![3]).is_none());
    }
Provenance: Repobility (https://repobility.com) — every score reproducible from /scan/
compute_from_raw_no_cpps function · rust · L128-L137 (10 LOC)
core/src/analysis/fatigue.rs
    fn compute_from_raw_no_cpps() {
        let raw = FatigueRawData {
            mpt_per_trial: vec![10.0, 9.0, 8.0, 7.0, 6.0],
            effort_per_trial: vec![3, 4, 5, 6, 7],
        };
        let result = compute_from_raw(&raw).unwrap();
        assert!(result.mpt_slope < -0.5);
        assert_eq!(result.cpps_slope, 0.0); // no audio = no CPPS
        assert!(result.cpps_per_trial.iter().all(|c| c.is_none()));
    }
analyze function · rust · L10-L78 (69 LOC)
core/src/analysis/reading.rs
pub fn analyze(
    samples: &[f32],
    sample_rate: u32,
    pitch_config: &pitch::PitchConfig,
) -> Result<ReadingAnalysis> {
    // Activity detection — ground truth for sound production
    let activity_result = activity::detect_activity(samples, sample_rate, &activity::ActivityConfig::default());

    let result = pitch::extract_contour_with_fallback(samples, sample_rate, pitch_config);
    let pitch_contour = &result.contour;

    let mut frequencies = pitch::voiced_frequencies(pitch_contour);
    let vf = pitch::voiced_fraction(pitch_contour);

    if frequencies.is_empty() {
        anyhow::bail!(
            "No voiced frames detected in reading passage. \
             Recording may be silent or too quiet."
        );
    }

    // F0 statistics
    let mean_f0: f32 = frequencies.iter().sum::<f32>() / frequencies.len() as f32;
    let variance: f32 = frequencies.iter().map(|&f| (f - mean_f0).powi(2)).sum::<f32>()
        / frequencies.len() as f32;
    let f0_std = variance.s
analyze function · rust · L16-L53 (38 LOC)
core/src/analysis/scale.rs
pub fn analyze(
    samples: &[f32],
    sample_rate: u32,
    pitch_config: &pitch::PitchConfig,
) -> Result<ScaleAnalysis> {
    let pitch_contour = pitch::extract_pitch_contour(samples, sample_rate, pitch_config);
    let mut frequencies = pitch::voiced_frequencies(&pitch_contour);

    if frequencies.is_empty() {
        anyhow::bail!(
            "No voiced frames detected in scale recording. \
             Recording may be silent or too quiet."
        );
    }

    // Sort for percentile computation
    frequencies.sort_by(|a, b| a.partial_cmp(b).unwrap());

    let floor = contour::percentile(&frequencies, 0.05);
    let ceiling = contour::percentile(&frequencies, 0.95);
    let range_hz = ceiling - floor;

    // Semitones: the musical unit of pitch interval.
    // 12 semitones = 1 octave = doubling of frequency.
    // semitones = 12 * log2(f2 / f1)
    let range_semitones = if floor > 0.0 {
        12.0 * (ceiling / floor).log2()
    } else {
        0.0
    };

    Ok(Scal
analyze function · rust · L11-L98 (88 LOC)
core/src/analysis/sustained.rs
pub fn analyze(
    samples: &[f32],
    sample_rate: u32,
    pitch_config: &pitch::PitchConfig,
) -> Result<SustainedAnalysis> {
    // Activity detection — ground truth for sound production
    let activity_result = activity::detect_activity(samples, sample_rate, &activity::ActivityConfig::default());

    let result = pitch::extract_contour_with_fallback(samples, sample_rate, pitch_config);
    let contour = &result.contour;

    let frequencies = pitch::voiced_frequencies(contour);

    if frequencies.is_empty() {
        anyhow::bail!(
            "No voiced frames detected in sustained vowel. \
             Recording may be silent or too quiet."
        );
    }

    // F0 statistics
    let mean_f0: f32 = frequencies.iter().sum::<f32>() / frequencies.len() as f32;
    let variance: f32 = frequencies.iter().map(|&f| (f - mean_f0).powi(2)).sum::<f32>()
        / frequencies.len() as f32;
    let f0_std = variance.sqrt();

    // Prefer gated jitter/shimmer (tier 1/2 frames only) 
compute_sz function · rust · L13-L34 (22 LOC)
core/src/analysis/sz.rs
pub fn compute_sz(s_durations: Vec<f32>, z_durations: Vec<f32>) -> Option<SzAnalysis> {
    if s_durations.is_empty() || z_durations.is_empty() {
        return None;
    }

    let mean_s = s_durations.iter().sum::<f32>() / s_durations.len() as f32;
    let mean_z = z_durations.iter().sum::<f32>() / z_durations.len() as f32;

    if mean_z == 0.0 {
        return None;
    }

    let sz_ratio = mean_s / mean_z;

    Some(SzAnalysis {
        s_durations,
        z_durations,
        mean_s,
        mean_z,
        sz_ratio,
    })
}
compute_from_raw function · rust · L37-L39 (3 LOC)
core/src/analysis/sz.rs
pub fn compute_from_raw(raw: &SzRawData) -> Option<SzAnalysis> {
    compute_sz(raw.s_durations.clone(), raw.z_durations.clone())
}
normal_ratio function · rust · L46-L50 (5 LOC)
core/src/analysis/sz.rs
    fn normal_ratio() {
        let result = compute_sz(vec![10.0, 11.0], vec![10.5, 10.0]).unwrap();
        assert!((result.sz_ratio - 1.0).abs() < 0.15);
        assert!((result.mean_s - 10.5).abs() < 0.01);
    }
concerning_ratio function · rust · L53-L57 (5 LOC)
core/src/analysis/sz.rs
    fn concerning_ratio() {
        // /s/ much longer than /z/ — cord dysfunction
        let result = compute_sz(vec![15.0, 14.0], vec![8.0, 7.0]).unwrap();
        assert!(result.sz_ratio > 1.4, "Expected ratio > 1.4, got {:.2}", result.sz_ratio);
    }
All rows scored by the Repobility analyzer (https://repobility.com)
single_trial_each function · rust · L60-L63 (4 LOC)
core/src/analysis/sz.rs
    fn single_trial_each() {
        let result = compute_sz(vec![12.0], vec![10.0]).unwrap();
        assert!((result.sz_ratio - 1.2).abs() < 0.01);
    }
empty_s_returns_none function · rust · L66-L68 (3 LOC)
core/src/analysis/sz.rs
    fn empty_s_returns_none() {
        assert!(compute_sz(vec![], vec![10.0]).is_none());
    }
empty_z_returns_none function · rust · L71-L73 (3 LOC)
core/src/analysis/sz.rs
    fn empty_z_returns_none() {
        assert!(compute_sz(vec![10.0], vec![]).is_none());
    }
compute_from_raw_roundtrip function · rust · L76-L84 (9 LOC)
core/src/analysis/sz.rs
    fn compute_from_raw_roundtrip() {
        let raw = SzRawData {
            s_durations: vec![15.0, 14.0],
            z_durations: vec![8.0, 7.0],
        };
        let result = compute_from_raw(&raw).unwrap();
        assert!(result.sz_ratio > 1.4);
        assert_eq!(result.s_durations, vec![15.0, 14.0]);
    }
default function · rust · L53-L63 (11 LOC)
core/src/config.rs
    fn default() -> Self {
        Self {
            pitch_floor_hz: 30.0,
            pitch_ceiling_hz: 1000.0,
            frame_size_ms: 30.0,
            hop_size_ms: 10.0,
            sustained_ceiling_hz: 500.0,
            reading_ceiling_hz: 600.0,
            thresholds: ThresholdConfig::default(),
        }
    }
pitch_config_for function · rust · L68-L82 (15 LOC)
core/src/config.rs
    pub fn pitch_config_for(&self, exercise: &str) -> PitchConfig {
        let ceiling = match exercise {
            "sustained" => self.sustained_ceiling_hz,
            "reading" => self.reading_ceiling_hz,
            _ => self.pitch_ceiling_hz, // scale uses global ceiling
        };

        PitchConfig {
            pitch_floor_hz: self.pitch_floor_hz,
            pitch_ceiling_hz: ceiling,
            frame_size_ms: self.frame_size_ms,
            hop_size_ms: self.hop_size_ms,
            ..PitchConfig::default()
        }
    }
default function · rust · L86-L93 (8 LOC)
core/src/config.rs
    fn default() -> Self {
        Self {
            jitter_pathological: 1.04,
            shimmer_pathological: 3.81,
            hnr_low: 7.0,
            hnr_normal: 20.0,
        }
    }
default function · rust · L97-L106 (10 LOC)
core/src/config.rs
    fn default() -> Self {
        Self {
            reading_passage: "\
When the sunlight strikes raindrops in the air, they act as a prism \
and form a rainbow. The rainbow is a division of white light into \
many beautiful colors. These take the shape of a long round arch, \
with its path high above, and its two ends apparently beyond the horizon."
                .into(),
        }
    }
Repobility · code-quality intelligence · https://repobility.com
default function · rust · L110-L116 (7 LOC)
core/src/config.rs
    fn default() -> Self {
        Self {
            sample_rate: 44100,
            channels: 1,
            device: "default".into(),
        }
    }
from function · rust · L121-L129 (9 LOC)
core/src/config.rs
    fn from(cfg: &AnalysisConfig) -> Self {
        PitchConfig {
            pitch_floor_hz: cfg.pitch_floor_hz,
            pitch_ceiling_hz: cfg.pitch_ceiling_hz,
            frame_size_ms: cfg.frame_size_ms,
            hop_size_ms: cfg.hop_size_ms,
            ..PitchConfig::default()
        }
    }
default_config_values function · rust · L137-L141 (5 LOC)
core/src/config.rs
    fn default_config_values() {
        let cfg = AnalysisConfig::default();
        assert_eq!(cfg.pitch_floor_hz, 30.0);
        assert_eq!(cfg.thresholds.jitter_pathological, 1.04);
    }
pitch_config_conversion function · rust · L144-L149 (6 LOC)
core/src/config.rs
    fn pitch_config_conversion() {
        let cfg = AnalysisConfig::default();
        let pitch_cfg: PitchConfig = (&cfg).into();
        assert_eq!(pitch_cfg.pitch_floor_hz, 30.0);
        assert_eq!(pitch_cfg.hop_size_ms, 10.0);
    }
pitch_config_for_sustained function · rust · L152-L156 (5 LOC)
core/src/config.rs
    fn pitch_config_for_sustained() {
        let cfg = AnalysisConfig::default();
        let pitch = cfg.pitch_config_for("sustained");
        assert_eq!(pitch.pitch_ceiling_hz, 500.0);
    }
pitch_config_for_reading function · rust · L159-L163 (5 LOC)
core/src/config.rs
    fn pitch_config_for_reading() {
        let cfg = AnalysisConfig::default();
        let pitch = cfg.pitch_config_for("reading");
        assert_eq!(pitch.pitch_ceiling_hz, 600.0);
    }
pitch_config_for_scale function · rust · L166-L170 (5 LOC)
core/src/config.rs
    fn pitch_config_for_scale() {
        let cfg = AnalysisConfig::default();
        let pitch = cfg.pitch_config_for("scale");
        assert_eq!(pitch.pitch_ceiling_hz, 1000.0);
    }
default function · rust · L19-L27 (9 LOC)
core/src/dsp/activity.rs
    fn default() -> Self {
        Self {
            threshold_on_db: -45.0,
            threshold_off_db: -50.0,
            min_active_ms: 80.0,
            min_silent_ms: 120.0,
            frame_size_ms: 10.0,
        }
    }
Want fix-PRs on findings? Install Repobility's GitHub App · github.com/apps/repobility-bot
detect_activity function · rust · L44-L111 (68 LOC)
core/src/dsp/activity.rs
pub fn detect_activity(
    samples: &[f32],
    sample_rate: u32,
    config: &ActivityConfig,
) -> ActivityResult {
    let sr = sample_rate as f32;
    let frame_size = (config.frame_size_ms / 1000.0 * sr) as usize;

    if frame_size == 0 || samples.len() < frame_size {
        return ActivityResult {
            active_frames: Vec::new(),
            active_fraction: 0.0,
        };
    }

    // Step 1: Compute RMS dB per frame
    let mut rms_db_values = Vec::new();
    let mut pos = 0;
    while pos + frame_size <= samples.len() {
        let frame = &samples[pos..pos + frame_size];
        let rms = frame_rms(frame);
        let db = if rms > 0.0 {
            20.0 * rms.log10()
        } else {
            f32::NEG_INFINITY
        };
        rms_db_values.push(db);
        pos += frame_size;
    }

    // Step 2: Apply hysteresis
    let mut active_frames: Vec<bool> = Vec::with_capacity(rms_db_values.len());
    let mut is_active = false;

    for &db in &rms_db_values {
   
remove_short_segments function · rust · L114-L136 (23 LOC)
core/src/dsp/activity.rs
fn remove_short_segments(frames: &mut [bool], target_value: bool, min_length: usize) {
    if frames.is_empty() || min_length == 0 {
        return;
    }

    let mut i = 0;
    while i < frames.len() {
        if frames[i] == target_value {
            let start = i;
            while i < frames.len() && frames[i] == target_value {
                i += 1;
            }
            let run_len = i - start;
            if run_len < min_length {
                for frame in &mut frames[start..i] {
                    *frame = !target_value;
                }
            }
        } else {
            i += 1;
        }
    }
}
voiced_quality function · rust · L140-L163 (24 LOC)
core/src/dsp/activity.rs
pub fn voiced_quality(contour: &[PitchFrame], active_frames: &[bool]) -> f32 {
    let len = contour.len().min(active_frames.len());
    if len == 0 {
        return 0.0;
    }

    let mut active_count = 0;
    let mut pitched_in_active = 0;

    for i in 0..len {
        if active_frames[i] {
            active_count += 1;
            if contour[i].frequency.is_some() {
                pitched_in_active += 1;
            }
        }
    }

    if active_count == 0 {
        return 0.0;
    }

    pitched_in_active as f32 / active_count as f32
}
frame_rms function · rust · L164-L171 (8 LOC)
core/src/dsp/activity.rs
fn frame_rms(samples: &[f32]) -> f32 {
    if samples.is_empty() {
        return 0.0;
    }
    let sum_sq: f32 = samples.iter().map(|&s| s * s).sum();
    (sum_sq / samples.len() as f32).sqrt()
}
sine_wave function · rust · L177-L186 (10 LOC)
core/src/dsp/activity.rs
    fn sine_wave(freq_hz: f32, sample_rate: u32, duration_secs: f32) -> Vec<f32> {
        let num_samples = (sample_rate as f32 * duration_secs) as usize;
        (0..num_samples)
            .map(|i| {
                let t = i as f32 / sample_rate as f32;
                0.5 * (2.0 * PI * freq_hz * t).sin()
            })
            .collect()
    }
default_config function · rust · L187-L190 (4 LOC)
core/src/dsp/activity.rs
    fn default_config() -> ActivityConfig {
        ActivityConfig::default()
    }
sine_wave_fully_active function · rust · L193-L201 (9 LOC)
core/src/dsp/activity.rs
    fn sine_wave_fully_active() {
        let samples = sine_wave(100.0, 44100, 1.0);
        let result = detect_activity(&samples, 44100, &default_config());
        assert!(
            result.active_fraction > 0.9,
            "Sine wave should be mostly active, got {:.2}",
            result.active_fraction
        );
    }
silence_fully_inactive function · rust · L204-L212 (9 LOC)
core/src/dsp/activity.rs
    fn silence_fully_inactive() {
        let samples = vec![0.0; 44100];
        let result = detect_activity(&samples, 44100, &default_config());
        assert!(
            result.active_fraction < 0.01,
            "Silence should be inactive, got {:.2}",
            result.active_fraction
        );
    }
Provenance: Repobility (https://repobility.com) — every score reproducible from /scan/
signal_with_gap function · rust · L215-L238 (24 LOC)
core/src/dsp/activity.rs
    fn signal_with_gap() {
        let sr = 44100u32;
        // 500ms tone + 200ms silence + 500ms tone
        let mut samples = sine_wave(100.0, sr, 0.5);
        samples.extend(vec![0.0; (sr as f32 * 0.2) as usize]);
        samples.extend(sine_wave(100.0, sr, 0.5));

        let result = detect_activity(&samples, sr, &default_config());

        // Should have two active segments with a gap
        let total_ms = result.active_frames.len() as f32 * 10.0;
        let active_ms = result.active_fraction * total_ms;

        // ~1000ms of signal, expect ~800-1000ms active (some ramp-up at edges)
        assert!(
            active_ms > 700.0,
            "Expected significant active time, got {active_ms:.0}ms"
        );
        assert!(
            result.active_fraction < 0.95,
            "Gap should cause some inactive frames, got {:.2}",
            result.active_fraction
        );
    }
hysteresis_prevents_toggling function · rust · L241-L272 (32 LOC)
core/src/dsp/activity.rs
    fn hysteresis_prevents_toggling() {
        let sr = 44100u32;
        // Signal hovering near threshold: alternate between -44 dB and -46 dB
        // This tests that hysteresis prevents rapid on/off toggling
        let config = ActivityConfig {
            threshold_on_db: -45.0,
            threshold_off_db: -50.0,
            ..default_config()
        };

        // Create a signal at ~-44 dB (just above on threshold)
        // amplitude for -44 dB: 10^(-44/20) ≈ 0.0063
        let amp = 0.0063;
        let samples: Vec<f32> = (0..sr)
            .map(|i| amp * (2.0 * PI * 100.0 * i as f32 / sr as f32).sin())
            .collect();

        let result = detect_activity(&samples, sr, &config);

        // Count transitions
        let transitions: usize = result
            .active_frames
            .windows(2)
            .filter(|w| w[0] != w[1])
            .count();

        // With hysteresis, there should be very few transitions (0 or 2 at most)
        assert!(
    
short_transient_filtered function · rust · L275-L289 (15 LOC)
core/src/dsp/activity.rs
    fn short_transient_filtered() {
        let sr = 44100u32;
        // Silence with a 50ms burst in the middle (should be filtered at min_active=80ms)
        let mut samples = vec![0.0; (sr as f32 * 0.5) as usize];
        let burst = sine_wave(100.0, sr, 0.05); // 50ms
        samples.extend(burst);
        samples.extend(vec![0.0; (sr as f32 * 0.5) as usize]);

        let result = detect_activity(&samples, sr, &default_config());
        assert!(
            result.active_fraction < 0.05,
            "50ms transient should be filtered by min_active_ms=80ms, got {:.2}",
            result.active_fraction
        );
    }
voiced_quality_all_pitched function · rust · L292-L301 (10 LOC)
core/src/dsp/activity.rs
    fn voiced_quality_all_pitched() {
        let contour: Vec<PitchFrame> = (0..10)
            .map(|i| PitchFrame {
                time: i as f32 * 0.01,
                frequency: Some(100.0),
            })
            .collect();
        let active = vec![true; 10];
        assert!((voiced_quality(&contour, &active) - 1.0).abs() < 0.01);
    }
voiced_quality_no_active function · rust · L304-L313 (10 LOC)
core/src/dsp/activity.rs
    fn voiced_quality_no_active() {
        let contour: Vec<PitchFrame> = (0..10)
            .map(|i| PitchFrame {
                time: i as f32 * 0.01,
                frequency: Some(100.0),
            })
            .collect();
        let active = vec![false; 10];
        assert!((voiced_quality(&contour, &active)).abs() < 0.01);
    }
voiced_quality_half_pitched function · rust · L316-L325 (10 LOC)
core/src/dsp/activity.rs
    fn voiced_quality_half_pitched() {
        let contour: Vec<PitchFrame> = (0..10)
            .map(|i| PitchFrame {
                time: i as f32 * 0.01,
                frequency: if i < 5 { Some(100.0) } else { None },
            })
            .collect();
        let active = vec![true; 10];
        assert!((voiced_quality(&contour, &active) - 0.5).abs() < 0.01);
    }
voiced_runs function · rust · L10-L36 (27 LOC)
core/src/dsp/contour.rs
pub fn voiced_runs(contour: &[PitchFrame]) -> Vec<(usize, usize)> {
    let mut runs = Vec::new();
    let mut start = None;

    for (i, frame) in contour.iter().enumerate() {
        match (frame.frequency.is_some(), start) {
            // Voiced frame, not currently in a run → start one
            (true, None) => start = Some(i),
            // Voiced frame, already in a run → continue
            (true, Some(_)) => {}
            // Unvoiced frame, was in a run → end it
            (false, Some(s)) => {
                runs.push((s, i - 1));
                start = None;
            }
            // Unvoiced frame, not in a run → nothing to do
            (false, None) => {}
        }
    }

    // Don't forget a run that extends to the end of the contour
    if let Some(s) = start {
        runs.push((s, contour.len() - 1));
    }

    runs
}
run_duration_secs function · rust · L68-L70 (3 LOC)
core/src/dsp/contour.rs
pub fn run_duration_secs(start: usize, end: usize, hop_size_ms: f32) -> f32 {
    (end - start + 1) as f32 * hop_size_ms / 1000.0
}
All rows scored by the Repobility analyzer (https://repobility.com)
percentile function · rust · L74-L78 (5 LOC)
core/src/dsp/contour.rs
pub fn percentile(sorted: &[f32], p: f32) -> f32 {
    assert!(!sorted.is_empty(), "Cannot compute percentile of empty slice");
    let idx = (p * (sorted.len() - 1) as f32).round() as usize;
    sorted[idx.min(sorted.len() - 1)]
}
frame function · rust · L83-L89 (7 LOC)
core/src/dsp/contour.rs
    fn frame(time: f32, freq: Option<f32>) -> PitchFrame {
        PitchFrame {
            time,
            frequency: freq,
        }
    }
single_voiced_run function · rust · L92-L100 (9 LOC)
core/src/dsp/contour.rs
    fn single_voiced_run() {
        let contour = vec![
            frame(0.0, Some(100.0)),
            frame(0.01, Some(101.0)),
            frame(0.02, Some(99.0)),
        ];
        let runs = voiced_runs(&contour);
        assert_eq!(runs, vec![(0, 2)]);
    }
page 1 / 10next ›