From 06a4169d7bd188039f22bdb20172b6c0829aac6c Mon Sep 17 00:00:00 2001 From: Yuval Adam <_@yuv.al> Date: Tue, 24 Jun 2025 13:05:11 +0200 Subject: Cleanup lib and CLI usage --- src/lib.rs | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 2 deletions(-) (limited to 'src/lib.rs') diff --git a/src/lib.rs b/src/lib.rs index 599694c..32eb119 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,87 @@ // src/lib.rs // Library interface for ditdah -pub mod decoder; +mod decoder; pub mod generator; -pub use decoder::MorseDecoder; pub use generator::MorseGenerator; +use decoder::MorseDecoder; + +use anyhow::Result; + +/// High-level convenience function to decode a WAV file directly +/// +/// # Example +/// ```no_run +/// use ditdah::decode_wav_file; +/// +/// let decoded_text = decode_wav_file("morse.wav").unwrap(); +/// println!("Decoded: {}", decoded_text); +/// ``` +pub fn decode_wav_file>(path: P) -> Result { + use hound::{SampleFormat, WavReader}; + + let mut reader = WavReader::open(path)?; + let spec = reader.spec(); + + // Check supported formats + if spec.sample_format != SampleFormat::Int && spec.sample_format != SampleFormat::Float { + anyhow::bail!( + "Unsupported sample format: {:?}. Only 16-bit Int and 32-bit Float are supported.", + spec.sample_format + ); + } + + // Create decoder with automatic sample rate conversion + let mut decoder = MorseDecoder::new(spec.sample_rate, 12000)?; + + // Read all samples + let samples_f32: Vec = if spec.sample_format == SampleFormat::Int { + reader + .samples::() + .map(|s| s.unwrap() as f32 / 32768.0) + .collect() + } else { + reader.samples::().map(|s| s.unwrap()).collect() + }; + + // Convert to mono if necessary + let mono_samples: Vec = if spec.channels > 1 { + samples_f32 + .chunks_exact(spec.channels as usize) + .map(|chunk| chunk.iter().sum::() / spec.channels as f32) + .collect() + } else { + samples_f32 + }; + + // Process in chunks for better memory efficiency + const CHUNK_SIZE: usize = 4096; + for chunk in mono_samples.chunks(CHUNK_SIZE) { + decoder.process(chunk)?; + } + + decoder.finalize() +} + +/// High-level convenience function to decode audio samples directly +/// +/// # Example +/// ```no_run +/// use ditdah::decode_samples; +/// +/// // For real audio data with sufficient length for processing +/// let samples = vec![0.0; 48000]; // 4 seconds of audio at 12kHz +/// let decoded_text = decode_samples(&samples, 12000).unwrap(); +/// println!("Decoded: {}", decoded_text); +/// ``` +pub fn decode_samples(samples: &[f32], sample_rate: u32) -> Result { + let mut decoder = MorseDecoder::new(sample_rate, 12000)?; + + const CHUNK_SIZE: usize = 4096; + for chunk in samples.chunks(CHUNK_SIZE) { + decoder.process(chunk)?; + } + + decoder.finalize() +} -- cgit v1.3.1