← back to jeffrydegrande__voicevo

Function bodies 463 total

All specs Real LLM only Function bodies
compute_rms_known_value function · rust · L269-L272 (4 LOC)
src/audio/capture.rs
    fn compute_rms_known_value() {
        let rms = compute_rms(&[1.0, -1.0]);
        assert!((rms - 1.0).abs() < 0.001);
    }
audio_state_rms_db_silence function · rust · L275-L285 (11 LOC)
src/audio/capture.rs
    fn audio_state_rms_db_silence() {
        let state = AudioState {
            live_rms: Arc::new(AtomicU32::new(0_f32.to_bits())),
            stop: Arc::new(AtomicBool::new(false)),
            waveform_buffer: Arc::new(Mutex::new(VecDeque::new())),
            live_pitch: Arc::new(AtomicU32::new(0)),
            sample_rate: 44100,
        };
        assert!(state.rms_db().is_infinite());
        assert!(state.is_silent());
    }
audio_state_rms_db_signal function · rust · L288-L300 (13 LOC)
src/audio/capture.rs
    fn audio_state_rms_db_signal() {
        let rms: f32 = 0.1; // -20 dB
        let state = AudioState {
            live_rms: Arc::new(AtomicU32::new(rms.to_bits())),
            stop: Arc::new(AtomicBool::new(false)),
            waveform_buffer: Arc::new(Mutex::new(VecDeque::new())),
            live_pitch: Arc::new(AtomicU32::new(0)),
            sample_rate: 44100,
        };
        let db = state.rms_db();
        assert!((db - (-20.0)).abs() < 0.1);
        assert!(!state.is_silent());
    }
audio_state_pitch_none_when_zero function · rust · L303-L312 (10 LOC)
src/audio/capture.rs
    fn audio_state_pitch_none_when_zero() {
        let state = AudioState {
            live_rms: Arc::new(AtomicU32::new(0_f32.to_bits())),
            stop: Arc::new(AtomicBool::new(false)),
            waveform_buffer: Arc::new(Mutex::new(VecDeque::new())),
            live_pitch: Arc::new(AtomicU32::new(0)),
            sample_rate: 44100,
        };
        assert!(state.pitch_hz().is_none());
    }
audio_state_pitch_some_when_set function · rust · L315-L325 (11 LOC)
src/audio/capture.rs
    fn audio_state_pitch_some_when_set() {
        let hz: f32 = 440.0;
        let state = AudioState {
            live_rms: Arc::new(AtomicU32::new(0_f32.to_bits())),
            stop: Arc::new(AtomicBool::new(false)),
            waveform_buffer: Arc::new(Mutex::new(VecDeque::new())),
            live_pitch: Arc::new(AtomicU32::new(hz.to_bits())),
            sample_rate: 44100,
        };
        assert_eq!(state.pitch_hz(), Some(440.0));
    }
waveform_snapshot_empty function · rust · L328-L337 (10 LOC)
src/audio/capture.rs
    fn waveform_snapshot_empty() {
        let state = AudioState {
            live_rms: Arc::new(AtomicU32::new(0_f32.to_bits())),
            stop: Arc::new(AtomicBool::new(false)),
            waveform_buffer: Arc::new(Mutex::new(VecDeque::new())),
            live_pitch: Arc::new(AtomicU32::new(0)),
            sample_rate: 44100,
        };
        assert!(state.waveform_snapshot().is_empty());
    }
waveform_snapshot_returns_data function · rust · L340-L354 (15 LOC)
src/audio/capture.rs
    fn waveform_snapshot_returns_data() {
        let mut buf = VecDeque::new();
        buf.push_back(0.1);
        buf.push_back(0.2);
        let state = AudioState {
            live_rms: Arc::new(AtomicU32::new(0_f32.to_bits())),
            stop: Arc::new(AtomicBool::new(false)),
            waveform_buffer: Arc::new(Mutex::new(buf)),
            live_pitch: Arc::new(AtomicU32::new(0)),
            sample_rate: 44100,
        };
        let snap = state.waveform_snapshot();
        assert_eq!(snap.len(), 2);
        assert!((snap[0] - 0.1).abs() < 0.001);
    }
Methodology: Repobility · https://repobility.com/research/state-of-ai-code-2026/
list_devices function · rust · L6-L71 (66 LOC)
src/audio/devices.rs
pub fn list_devices() -> Result<()> {
    let host = cpal::default_host();

    let default_device = host.default_input_device();
    let default_name = default_device
        .as_ref()
        .and_then(|d| d.name().ok())
        .unwrap_or_default();

    let devices: Vec<_> = host.input_devices()?.collect();

    if devices.is_empty() {
        eprintln!("No audio input devices found.");
        return Ok(());
    }

    println!("{}", style("Audio Input Devices").bold());
    println!();

    for device in &devices {
        let name = device.name().unwrap_or_else(|_| "<unknown>".into());
        let is_default = name == default_name;

        if is_default {
            print!("  {} ", style("*").green().bold());
            print!("{}", style(&name).green().bold());
        } else {
            print!("    {}", style(&name).bold());
        }
        println!();

        match device.supported_input_configs() {
            Ok(configs) => {
                for cfg in configs {
   
run_sustain_exercise function · rust · L22-L147 (126 LOC)
src/audio/exercise.rs
pub fn run_sustain_exercise(config: &AppConfig) -> Result<()> {
    // --- Phase 1: Setup ---
    let reference_mpt = load_reference_mpt();

    println!();
    println!(
        "{}",
        style("=== Sustained Phonation Exercise ===").bold()
    );
    println!();
    println!("  Take a deep breath, then hold {} as long and steady as you can.", style("\"AAAH\"").cyan());
    println!("  The exercise auto-stops when you go silent.");
    println!();

    if let Some(mpt) = reference_mpt {
        println!("  Your last MPT: {:.1}s — try to match or beat it.", mpt);
    } else {
        println!("  No previous sessions found — just hold as long as you can.");
    }

    println!();
    println!(
        "  Press {} when ready.",
        style("Enter").green().bold()
    );

    crate::audio::recorder::wait_for_enter()?;

    // --- Phase 2: TUI recording ---
    let mut terminal = crate::tui::init()?;
    let (audio_state, stream, collector) = capture::start_capture(false)?;
    let s
load_reference_mpt function · rust · L150-L160 (11 LOC)
src/audio/exercise.rs
fn load_reference_mpt() -> Option<f32> {
    let dates = storage::store::list_sessions().ok()?;
    for date in dates.iter().rev() {
        if let Ok(session) = storage::store::load_session(date) {
            if let Some(ref s) = session.analysis.sustained {
                return Some(s.mpt_seconds);
            }
        }
    }
    None
}
format_comparison function · rust · L163-L176 (14 LOC)
src/audio/exercise.rs
fn format_comparison(current: f32, reference: f32, unit: &str, higher_is_better: bool) -> String {
    let diff = current - reference;
    let sign = if diff >= 0.0 { "+" } else { "" };
    let color_good = diff > 0.0 && higher_is_better || diff < 0.0 && !higher_is_better;

    let text = format!("{sign}{diff:.1}{unit}");
    if color_good {
        style(text).green().to_string()
    } else if diff.abs() < 0.1 {
        style(text).dim().to_string()
    } else {
        style(text).red().to_string()
    }
}
print_metric function · rust · L179-L184 (6 LOC)
src/audio/exercise.rs
fn print_metric(label: &str, value: &str, annotation: Option<String>) {
    match annotation {
        Some(ann) => println!("  {:12} {:>12}  {}", style(label).bold(), value, ann),
        None => println!("  {:12} {:>12}", style(label).bold(), value),
    }
}
rate_jitter function · rust · L187-L193 (7 LOC)
src/audio/exercise.rs
fn rate_jitter(jitter: f32, thresholds: &crate::config::ThresholdConfig) -> String {
    if jitter < thresholds.jitter_pathological {
        style("normal").green().to_string()
    } else {
        style("elevated").yellow().to_string()
    }
}
rate_shimmer function · rust · L196-L202 (7 LOC)
src/audio/exercise.rs
fn rate_shimmer(shimmer: f32, thresholds: &crate::config::ThresholdConfig) -> String {
    if shimmer < thresholds.shimmer_pathological {
        style("normal").green().to_string()
    } else {
        style("elevated").yellow().to_string()
    }
}
rate_cpps function · rust · L205-L213 (9 LOC)
src/audio/exercise.rs
fn rate_cpps(cpps: f32) -> String {
    if cpps >= 5.0 {
        style("normal").green().to_string()
    } else if cpps >= 3.0 {
        style("mild dysphonia").yellow().to_string()
    } else {
        style("significant dysphonia").red().to_string()
    }
}
Same scanner, your repo: https://repobility.com — Repobility
rate_hnr function · rust · L216-L224 (9 LOC)
src/audio/exercise.rs
fn rate_hnr(hnr: f32, thresholds: &crate::config::ThresholdConfig) -> String {
    if hnr >= thresholds.hnr_normal {
        style("healthy").green().to_string()
    } else if hnr >= thresholds.hnr_low {
        style("fair").yellow().to_string()
    } else {
        style("low").red().to_string()
    }
}
format_comparison_positive function · rust · L231-L234 (4 LOC)
src/audio/exercise.rs
    fn format_comparison_positive() {
        let result = format_comparison(10.0, 8.0, "s", true);
        assert!(result.contains("2.0s"));
    }
format_comparison_negative function · rust · L237-L240 (4 LOC)
src/audio/exercise.rs
    fn format_comparison_negative() {
        let result = format_comparison(6.0, 8.0, "s", true);
        assert!(result.contains("2.0s"));
    }
format_comparison_equal function · rust · L243-L246 (4 LOC)
src/audio/exercise.rs
    fn format_comparison_equal() {
        let result = format_comparison(8.0, 8.0, "s", true);
        assert!(result.contains("0.0s"));
    }
rate_jitter_normal function · rust · L249-L253 (5 LOC)
src/audio/exercise.rs
    fn rate_jitter_normal() {
        let thresholds = crate::config::ThresholdConfig::default();
        let result = rate_jitter(0.5, &thresholds);
        assert!(result.contains("normal"));
    }
rate_jitter_elevated function · rust · L256-L260 (5 LOC)
src/audio/exercise.rs
    fn rate_jitter_elevated() {
        let thresholds = crate::config::ThresholdConfig::default();
        let result = rate_jitter(2.0, &thresholds);
        assert!(result.contains("elevated"));
    }
rate_shimmer_normal function · rust · L263-L267 (5 LOC)
src/audio/exercise.rs
    fn rate_shimmer_normal() {
        let thresholds = crate::config::ThresholdConfig::default();
        let result = rate_shimmer(2.0, &thresholds);
        assert!(result.contains("normal"));
    }
rate_shimmer_elevated function · rust · L270-L274 (5 LOC)
src/audio/exercise.rs
    fn rate_shimmer_elevated() {
        let thresholds = crate::config::ThresholdConfig::default();
        let result = rate_shimmer(5.0, &thresholds);
        assert!(result.contains("elevated"));
    }
Repobility (the analyzer behind this table) · https://repobility.com
rate_hnr_healthy function · rust · L277-L281 (5 LOC)
src/audio/exercise.rs
    fn rate_hnr_healthy() {
        let thresholds = crate::config::ThresholdConfig::default();
        let result = rate_hnr(25.0, &thresholds);
        assert!(result.contains("healthy"));
    }
rate_hnr_fair function · rust · L284-L288 (5 LOC)
src/audio/exercise.rs
    fn rate_hnr_fair() {
        let thresholds = crate::config::ThresholdConfig::default();
        let result = rate_hnr(12.0, &thresholds);
        assert!(result.contains("fair"));
    }
rate_hnr_low function · rust · L291-L295 (5 LOC)
src/audio/exercise.rs
    fn rate_hnr_low() {
        let thresholds = crate::config::ThresholdConfig::default();
        let result = rate_hnr(3.0, &thresholds);
        assert!(result.contains("low"));
    }
load_reference_mpt_no_sessions function · rust · L298-L300 (3 LOC)
src/audio/exercise.rs
    fn load_reference_mpt_no_sessions() {
        let _ = load_reference_mpt();
    }
run_fatigue_exercise function · rust · L17-L154 (138 LOC)
src/audio/fatigue_exercise.rs
pub fn run_fatigue_exercise(_config: &AppConfig) -> Result<()> {
    println!();
    println!("{}", style("=== Vocal Fatigue Test ===").bold());
    println!();
    println!("  You'll hold \"AAAH\" 5 times with 45s rest between trials.");
    println!("  This measures if your voice tires with repeated use.");
    println!();
    println!("  Press {} when ready.", style("Enter").green().bold());

    crate::audio::recorder::wait_for_enter()?;

    // TUI phase
    let mut terminal = crate::tui::init()?;
    let (audio_state, stream, collector) = capture::start_capture(false)?;
    let sample_rate = audio_state.sample_rate;

    let outcome = crate::tui::screens::fatigue::run(
        &mut terminal,
        &audio_state,
    )?;

    crate::tui::restore()?;

    // Stop audio, collect samples
    audio_state.stop.store(true, Ordering::Relaxed);
    drop(stream);

    let outcome = match outcome {
        Some(o) => o,
        None => {
            drop(collector);
            println!();
run function · rust · L21-L161 (141 LOC)
src/audio/mic_check.rs
pub fn run() -> Result<()> {
    let host = cpal::default_host();
    let device = host
        .default_input_device()
        .context("No default input device found")?;

    let device_name = device.name().unwrap_or_else(|_| "<unknown>".into());
    let config = device
        .default_input_config()
        .context("Failed to get default input config")?;

    let sample_rate = config.sample_rate().0;
    let channels = config.channels() as usize;
    let format = config.sample_format();

    println!(
        "  Device:  {}",
        style(&device_name).cyan().bold()
    );
    println!("  Config:  {channels}ch, {sample_rate} Hz, {format:?}");
    println!();
    println!(
        "  Press {} to capture a 2-second sample.",
        style("Enter").green().bold()
    );

    recorder::wait_for_enter()?;

    println!();

    // Channel to send captured samples from audio thread to main thread
    let (tx, rx) = mpsc::channel::<Vec<f32>>();

    // Build input stream based on sample 
play function · rust · L14-L51 (38 LOC)
src/audio/playback.rs
pub fn play(target: &str, exercise: Option<&str>) -> Result<()> {
    let path = resolve_play_path(target, exercise)?;

    println!(
        "Playing {}",
        style(path.display()).green()
    );

    // OutputStream::try_default() opens the default output device.
    // We must keep `_stream` alive — it's an RAII guard. If we used `_` instead
    // of `_stream`, Rust would drop it immediately (underscore = "I don't need this").
    // `_stream` (with a name) keeps it alive until the end of this function scope.
    let (_stream, stream_handle) =
        OutputStream::try_default().context("Failed to open audio output device")?;

    // Sink gives us playback control (pause, stop, wait).
    // It runs on a background thread managed by rodio.
    let sink = Sink::try_new(&stream_handle).context("Failed to create audio sink")?;

    let file = File::open(&path)
        .with_context(|| format!("Failed to open: {}", path.display()))?;
    let reader = BufReader::new(file);

    // D
resolve_play_path function · rust · L54-L69 (16 LOC)
src/audio/playback.rs
fn resolve_play_path(target: &str, exercise: Option<&str>) -> Result<PathBuf> {
    // If target looks like a file path (contains a dot or slash), use it directly
    if target.contains('/') || target.contains('.') {
        return Ok(PathBuf::from(target));
    }

    // Otherwise treat it as a date — exercise name is required
    let exercise = exercise.context(
        "When playing by date, you must specify an exercise name.\n\
         Usage: voicevo play 2026-02-08 sustained",
    )?;

    let date = util::resolve_date(Some(target))?;
    paths::latest_attempt_path(&date, exercise)
        .context(format!("No recordings found for {exercise} on {date}"))
}
Repobility · open methodology · https://repobility.com/research/
resolve_direct_path function · rust · L76-L79 (4 LOC)
src/audio/playback.rs
    fn resolve_direct_path() {
        let path = resolve_play_path("./test.wav", None).unwrap();
        assert_eq!(path, PathBuf::from("./test.wav"));
    }
resolve_absolute_path function · rust · L82-L85 (4 LOC)
src/audio/playback.rs
    fn resolve_absolute_path() {
        let path = resolve_play_path("/tmp/test.wav", None).unwrap();
        assert_eq!(path, PathBuf::from("/tmp/test.wav"));
    }
resolve_date_with_exercise_no_recordings function · rust · L88-L92 (5 LOC)
src/audio/playback.rs
    fn resolve_date_with_exercise_no_recordings() {
        // With no recordings on disk, latest_attempt_path returns None → error
        let result = resolve_play_path("2099-01-01", Some("sustained"));
        assert!(result.is_err());
    }
resolve_date_without_exercise_fails function · rust · L95-L98 (4 LOC)
src/audio/playback.rs
    fn resolve_date_without_exercise_fails() {
        let result = resolve_play_path("2026-02-08", None);
        assert!(result.is_err());
    }
record_exercise function · rust · L26-L113 (88 LOC)
src/audio/recorder.rs
pub fn record_exercise(exercise: &str, date: &NaiveDate, config: &crate::config::AppConfig) -> Result<()> {
    let path = paths::next_attempt_path(date, exercise);
    if let Some(parent) = path.parent() {
        std::fs::create_dir_all(parent)?;
    }

    println!(
        "{} {}",
        style("Exercise:").bold(),
        style(exercise).cyan()
    );
    println!(
        "{} {}",
        style("Date:").bold(),
        date
    );
    println!(
        "{} {}",
        style("Output:").bold(),
        path.display()
    );
    println!();

    // Show exercise-specific instructions
    match exercise {
        "sustained" => {
            println!(
                "  Take a deep breath, then hold {} as long as comfortable.",
                style("\"AAAH\"").cyan()
            );
            println!();
        }
        "scale" => {
            println!(
                "  Sing from your {} comfortable note up to your {},",
                style("lowest").cyan(),
              
record_to_file function · rust · L122-L236 (115 LOC)
src/audio/recorder.rs
pub fn record_to_file(path: &std::path::Path) -> Result<RecordingStats> {
    let host = cpal::default_host();
    let device = host
        .default_input_device()
        .context("No default input device found")?;

    let config = device
        .default_input_config()
        .context("Failed to get default input config")?;

    let sample_rate = config.sample_rate().0;
    let channels = config.channels() as usize;
    let format = config.sample_format();

    // Channel for sending audio data from cpal callback to writer thread
    let (tx, rx) = mpsc::channel::<Vec<f32>>();

    // Stop signal: set to true when user presses Enter
    let stop = Arc::new(AtomicBool::new(false));
    let stop_for_stream = Arc::clone(&stop);

    // Build the input stream. The closure captures tx by move.
    let stream = match format {
        SampleFormat::F32 => device.build_input_stream(
            &config.into(),
            move |data: &[f32], _: &cpal::InputCallbackInfo| {
                
wait_for_enter function · rust · L239-L254 (16 LOC)
src/audio/recorder.rs
pub fn wait_for_enter() -> Result<()> {
    crossterm::terminal::enable_raw_mode()?;

    loop {
        if event::poll(std::time::Duration::from_millis(100))? {
            if let Event::Key(key) = event::read()? {
                if key.kind == KeyEventKind::Press && key.code == KeyCode::Enter {
                    break;
                }
            }
        }
    }

    crossterm::terminal::disable_raw_mode()?;
    Ok(())
}
wait_for_keep_or_rerecord function · rust · L265-L286 (22 LOC)
src/audio/recorder.rs
pub fn wait_for_keep_or_rerecord() -> Result<PostRecordChoice> {
    crossterm::terminal::enable_raw_mode()?;

    let choice = loop {
        if event::poll(std::time::Duration::from_millis(100))? {
            if let Event::Key(key) = event::read()? {
                if key.kind == KeyEventKind::Press {
                    match key.code {
                        KeyCode::Enter => break PostRecordChoice::Keep,
                        KeyCode::Char('r') | KeyCode::Char('R') => {
                            break PostRecordChoice::Rerecord
                        }
                        _ => {}
                    }
                }
            }
        }
    };

    crossterm::terminal::disable_raw_mode()?;
    Ok(choice)
}
Methodology: Repobility · https://repobility.com/research/state-of-ai-code-2026/
run_scale_exercise function · rust · L16-L125 (110 LOC)
src/audio/scale_exercise.rs
pub fn run_scale_exercise(config: &AppConfig) -> Result<()> {
    println!();
    println!("{}", style("=== Chromatic Scale Exercise ===").bold());
    println!();
    println!("  Sing from your lowest note to your highest, then back down.");
    println!("  The display shows your current pitch in real time.");
    println!();
    println!("  Press {} when ready.", style("Enter").green().bold());

    crate::audio::recorder::wait_for_enter()?;

    // TUI phase: recording with live pitch feedback
    let mut terminal = crate::tui::init()?;
    let (audio_state, stream, collector) = capture::start_capture(true)?;
    let sample_rate = audio_state.sample_rate;

    let outcome = crate::tui::screens::scale::run(&mut terminal, &audio_state)?;

    crate::tui::restore()?;

    // Stop audio, collect samples
    audio_state.stop.store(true, Ordering::Relaxed);
    drop(stream);

    let outcome = match outcome {
        Some(o) => o,
        None => {
            collector.join().map_err(|_|
run_guided_session function · rust · L22-L149 (128 LOC)
src/audio/session.rs
pub fn run_guided_session(date: &NaiveDate, config: &AppConfig) -> Result<()> {
    let date_str = date.to_string();

    println!();
    println!(
        "{}",
        style("=== Voice Recovery Tracker — Recording Session ===").bold()
    );
    println!("  Date: {}", style(date).cyan());
    println!();

    // --- Step 1: Mic check ---
    println!(
        "{} {}",
        style("Step 1/4:").bold(),
        "Mic check"
    );
    println!();

    mic_check::run()?;
    println!();

    println!(
        "  Press {} to continue to the exercises.",
        style("Enter").green().bold()
    );
    recorder::wait_for_enter()?;
    println!();

    // --- Step 2: Sustained vowel ---
    println!(
        "{} {}",
        style("Step 2/4:").bold(),
        "Sustained vowel"
    );
    println!();
    println!(
        "  Take a deep breath, then hold {} as long as comfortable.",
        style("\"AAAH\"").cyan()
    );
    println!();

    let sustained_stats = record_with_retry(date, "s
record_with_retry function · rust · L155-L189 (35 LOC)
src/audio/session.rs
fn record_with_retry(
    date: &NaiveDate,
    exercise: &str,
) -> Result<recorder::RecordingStats> {
    loop {
        let path = paths::next_attempt_path(date, exercise);
        if let Some(parent) = path.parent() {
            std::fs::create_dir_all(parent)?;
        }

        let stats = record_exercise_with_path(&path)?;

        println!(
            "  Press {} to keep, {} to re-record.",
            style("Enter").green().bold(),
            style("r").yellow().bold(),
        );

        match recorder::wait_for_keep_or_rerecord()? {
            PostRecordChoice::Keep => {
                println!();
                return Ok(stats);
            }
            PostRecordChoice::Rerecord => {
                std::fs::remove_file(&path)?;
                println!(
                    "  {} Re-recording {}...",
                    style("DISCARDED").yellow(),
                    exercise
                );
                println!();
            }
        }
    }
}
record_exercise_with_path function · rust · L192-L229 (38 LOC)
src/audio/session.rs
fn record_exercise_with_path(
    path: &std::path::Path,
) -> Result<recorder::RecordingStats> {
    println!(
        "  Press {} when ready to record.",
        style("Enter").green().bold()
    );
    recorder::wait_for_enter()?;

    println!();
    println!(
        "  {} Press {} to stop.",
        style("*** RECORDING ***").red().bold(),
        style("Enter").bold()
    );

    let stats = recorder::record_to_file(path)?;

    println!(
        "  {}",
        style("*** STOPPED ***").dim()
    );
    println!();
    println!(
        "  Duration: {:.1}s  |  Peak: {:.1} dB  |  RMS: {:.1} dB",
        stats.duration_secs, stats.peak_db, stats.rms_db
    );

    if stats.peak_db < -60.0 {
        eprintln!(
            "  {} Recording appears silent!",
            style("WARNING").red().bold()
        );
    }

    println!();
    Ok(stats)
}
print_summary_row function · rust · L230-L236 (7 LOC)
src/audio/session.rs
fn print_summary_row(name: &str, stats: &recorder::RecordingStats) {
    println!(
        "  {:12} {:>9.1}s {:>9.1} {:>9.1}",
        name, stats.duration_secs, stats.peak_db, stats.rms_db
    );
}
run_sz_exercise function · rust · L15-L102 (88 LOC)
src/audio/sz_exercise.rs
pub fn run_sz_exercise(_config: &AppConfig) -> Result<()> {
    println!();
    println!("{}", style("=== S/Z Ratio Test ===").bold());
    println!();
    println!("  This test compares how long you can hold /s/ vs /z/.");
    println!("  A ratio close to 1.0 means healthy vocal cord function.");
    println!("  A ratio above 1.4 may indicate air leak through the vocal cords.");
    println!();
    println!("  Press {} when ready.", style("Enter").green().bold());

    crate::audio::recorder::wait_for_enter()?;

    // TUI phase
    let mut terminal = crate::tui::init()?;
    let (audio_state, stream, collector) = capture::start_capture(false)?;

    let outcome = crate::tui::screens::sz::run(&mut terminal, &audio_state)?;

    crate::tui::restore()?;

    // Stop audio
    audio_state.stop.store(true, Ordering::Relaxed);
    drop(stream);
    drop(collector);

    let outcome = match outcome {
        Some(o) => o,
        None => {
            println!();
            println!("  Can
recording_spec function · rust · L7-L14 (8 LOC)
src/audio/wav.rs
pub fn recording_spec(sample_rate: u32) -> WavSpec {
    WavSpec {
        channels: 1,
        sample_rate,
        bits_per_sample: 16,
        sample_format: SampleFormat::Int,
    }
}
create_writer function · rust · L17-L25 (9 LOC)
src/audio/wav.rs
pub fn create_writer(path: &Path, spec: WavSpec) -> Result<WavWriter<std::io::BufWriter<std::fs::File>>> {
    if let Some(parent) = path.parent() {
        std::fs::create_dir_all(parent)
            .with_context(|| format!("Failed to create directory: {}", parent.display()))?;
    }

    WavWriter::create(path, spec)
        .with_context(|| format!("Failed to create WAV file: {}", path.display()))
}
Same scanner, your repo: https://repobility.com — Repobility
load_samples function · rust · L29-L51 (23 LOC)
src/audio/wav.rs
pub fn load_samples(path: &Path) -> Result<(Vec<f32>, WavSpec)> {
    let mut reader = WavReader::open(path)
        .with_context(|| format!("Failed to open WAV file: {}", path.display()))?;

    let spec = reader.spec();

    let samples: Vec<f32> = match spec.sample_format {
        SampleFormat::Int => {
            let max_val = (1 << (spec.bits_per_sample - 1)) as f32;
            reader
                .samples::<i32>()
                .map(|s| s.map(|v| v as f32 / max_val))
                .collect::<hound::Result<Vec<_>>>()
                .context("Failed to read WAV samples")?
        }
        SampleFormat::Float => reader
            .samples::<f32>()
            .collect::<hound::Result<Vec<_>>>()
            .context("Failed to read WAV samples")?,
    };

    Ok((samples, spec))
}
test_wav_path function · rust · L57-L63 (7 LOC)
src/audio/wav.rs
    fn test_wav_path() -> PathBuf {
        // Use a temp dir so tests don't pollute the working directory
        let dir = std::env::temp_dir().join("voicevo-tests");
        std::fs::create_dir_all(&dir).unwrap();
        dir.join("roundtrip.wav")
    }
wav_roundtrip function · rust · L66-L99 (34 LOC)
src/audio/wav.rs
    fn wav_roundtrip() {
        let path = test_wav_path();
        let spec = recording_spec(44100);

        // Write a known signal: a short ramp
        let original: Vec<f32> = (0..1000).map(|i| (i as f32 / 1000.0) * 2.0 - 1.0).collect();

        {
            let mut writer = create_writer(&path, spec).unwrap();
            for &sample in &original {
                // Convert f32 to i16 for writing
                let s16 = (sample * i16::MAX as f32) as i16;
                writer.write_sample(s16).unwrap();
            }
            writer.finalize().unwrap();
        }

        // Read back and verify
        let (loaded, loaded_spec) = load_samples(&path).unwrap();
        assert_eq!(loaded_spec.sample_rate, 44100);
        assert_eq!(loaded_spec.channels, 1);
        assert_eq!(loaded.len(), original.len());

        // Verify samples match within quantization error (16-bit → ~0.00003 tolerance)
        for (orig, loaded) in original.iter().zip(loaded.iter()) {
           
‹ prevpage 6 / 10next ›