pub mod result_handler;
use crate::config;
use anyhow::{Context, Result};
use std::io::Cursor;
use std::time::Duration;
use tokio::sync::Mutex;
use tracing::{error, info, instrument, trace, warn};
use crate::audio::buffer::{CHANNELS, SAMPLE_RATE};
use crate::providers::TranscriptionProvider;
#[instrument(skip(samples))]
pub fn convert_samples_to_wav(samples: &[f32]) -> Result<Vec<u8>> {
if samples.is_empty() {
return Ok(Vec::new());
}
trace!("Converting {} samples to WAV format", samples.len());
let mut cursor = Cursor::new(Vec::new());
{
let spec = hound::WavSpec {
channels: CHANNELS,
sample_rate: SAMPLE_RATE,
bits_per_sample: 32,
sample_format: hound::SampleFormat::Float,
};
cursor.get_mut().reserve(samples.len() * 4 + 44);
let mut writer =
hound::WavWriter::new(&mut cursor, spec).context("Failed to create WAV writer")?;
for &sample in samples {
writer
.write_sample(sample)
.context("Failed to write sample")?;
}
writer.finalize().context("Failed to finalize WAV")?;
}
let wav_data = cursor.into_inner();
trace!("WAV conversion complete: {} bytes", wav_data.len());
Ok(wav_data)
}
#[cfg(test)]
mod tests {
use super::*;
use hound::WavReader;
use std::time::Duration;
#[test]
fn test_convert_samples_to_wav_basic() {
let sample_rate = 16000;
let duration_secs = 1.0;
let frequency = 440.0;
let num_samples = (sample_rate as f32 * duration_secs) as usize;
let mut samples = Vec::with_capacity(num_samples);
for i in 0..num_samples {
let t = i as f32 / sample_rate as f32;
let sample = (t * frequency * 2.0 * std::f32::consts::PI).sin();
samples.push(sample);
}
let wav_data = convert_samples_to_wav(&samples).unwrap();
assert!(!wav_data.is_empty());
assert!(wav_data.len() > 44);
let expected_size = samples.len() * 4 + 44;
assert_eq!(wav_data.len(), expected_size);
let cursor = std::io::Cursor::new(&wav_data);
let reader = WavReader::new(cursor).unwrap();
let spec = reader.spec();
assert_eq!(spec.channels, CHANNELS);
assert_eq!(spec.sample_rate, SAMPLE_RATE);
assert_eq!(spec.bits_per_sample, 32);
assert_eq!(spec.sample_format, hound::SampleFormat::Float);
}
#[test]
fn test_convert_samples_to_wav_empty() {
let empty: Vec<f32> = vec![];
let wav_data = convert_samples_to_wav(&empty).unwrap();
assert!(wav_data.is_empty());
}
#[test]
fn test_convert_samples_to_wav_large() {
let sample_rate = 16000;
let duration_secs = 5.0;
let num_samples = (sample_rate as f32 * duration_secs) as usize;
let samples = vec![0.5; num_samples];
let wav_data = convert_samples_to_wav(&samples).unwrap();
let expected_size = samples.len() * 4 + 44;
assert_eq!(wav_data.len(), expected_size);
assert!(wav_data.len() > 16000 * 2 * 5);
}
#[test]
fn test_audio_processing_pipeline() {
let sample_rate = 16000;
let duration_secs = 3.0;
let num_samples = (sample_rate as f32 * duration_secs) as usize;
let samples = vec![0.5; num_samples];
let wav_data = convert_samples_to_wav(&samples).unwrap();
}
}