pub mod buffer;
pub mod dsp;
pub mod effects;
pub mod enhancement;
pub mod io;
pub mod processing;
pub mod simd_ops;
mod utilities;
pub mod workflows;
pub use buffer::{AudioBuffer, AudioMetadata, BufferFormat};
pub use effects::{
ChorusEffect, CompressorEffect, DelayEffect, EffectsChain, EqualizerEffect, ReverbEffect,
};
pub use enhancement::{AdaptiveEnhancer, EnhancementConfig, PerformanceMetrics};
pub use io::{AudioInfo, RawFormat};
pub use simd_ops::{SimdAudioProcessor, SimdCapabilities};
pub use workflows::{AudioQualityMetrics, VoiceFeatures};
#[cfg(test)]
mod tests {
use super::*;
use crate::types::AudioFormat;
use tempfile::NamedTempFile;
#[test]
fn test_full_audio_pipeline() {
let mut buffer = AudioBuffer::sine_wave(440.0, 1.0, 44100, 0.5);
buffer.apply_gain(3.0).unwrap();
buffer.normalize(0.8).unwrap();
buffer.fade_in(0.1).unwrap();
buffer.fade_out(0.1).unwrap();
let other = AudioBuffer::sine_wave(880.0, 1.0, 44100, 0.3);
buffer.mix(&other, 0.5).unwrap();
let (first, second) = buffer.split(0.5).unwrap();
let mut combined = first;
combined.append(&second).unwrap();
let temp_file = NamedTempFile::with_suffix(".wav").unwrap();
combined.save(temp_file.path(), AudioFormat::Wav).unwrap();
let loaded = AudioBuffer::load(temp_file.path()).unwrap();
assert_eq!(loaded.sample_rate(), combined.sample_rate());
assert_eq!(loaded.channels(), combined.channels());
assert!((loaded.duration() - combined.duration()).abs() < 0.01);
}
#[test]
fn test_buffer_format_compatibility() {
let format1 = BufferFormat::mono(44100);
let format2 = BufferFormat::stereo(44100);
let format3 = BufferFormat::mono(22050);
assert!(!format1.is_compatible(&format2)); assert!(!format1.is_compatible(&format3)); assert!(format1.is_compatible(&format1)); }
#[test]
fn test_metadata_accuracy() {
let samples = vec![0.5, -0.3, 0.8, -0.1, 0.0];
let buffer = AudioBuffer::mono(samples.clone(), 44100);
let metadata = buffer.metadata();
let expected_peak = samples.iter().map(|&s| s.abs()).fold(0.0, f32::max);
assert_eq!(metadata.peak_amplitude, expected_peak);
let expected_duration = samples.len() as f32 / 44100.0;
assert!((metadata.duration - expected_duration).abs() < 0.001);
let sum_squares: f32 = samples.iter().map(|&s| s * s).sum();
let expected_rms = (sum_squares / samples.len() as f32).sqrt();
assert!((metadata.rms_amplitude - expected_rms).abs() < 0.001);
}
#[test]
fn test_advanced_processing() {
let mut buffer = AudioBuffer::sine_wave(440.0, 2.0, 44100, 0.7);
buffer.lowpass_filter(2000.0).unwrap();
buffer.compress(0.5, 4.0, 10.0, 100.0).unwrap();
buffer.reverb(0.3, 0.2, 0.1).unwrap();
let stretched = buffer.time_stretch(1.5).unwrap();
assert!((stretched.duration() - buffer.duration() / 1.5).abs() < 0.1);
let shifted = buffer.pitch_shift(12.0).unwrap();
assert!((shifted.duration() - buffer.duration()).abs() < 0.1);
}
#[test]
fn test_io_operations() {
let buffer = AudioBuffer::sine_wave(440.0, 0.5, 44100, 0.5);
let wav_bytes = buffer.to_wav_bytes().unwrap();
assert!(!wav_bytes.is_empty());
let mut chunk_count = 0;
buffer
.stream_to_callback(1024, |_chunk| {
chunk_count += 1;
Ok(())
})
.unwrap();
let expected_chunks = buffer.len().div_ceil(1024); assert_eq!(chunk_count, expected_chunks);
let metadata_json = buffer.export_metadata().unwrap();
assert!(metadata_json.contains("duration"));
assert!(metadata_json.contains("peak_amplitude"));
}
#[test]
fn test_error_handling() {
let buffer1 = AudioBuffer::mono(vec![0.1, 0.2], 44100);
let buffer2 = AudioBuffer::mono(vec![0.3, 0.4], 22050);
let mut buffer1_copy = buffer1.clone();
assert!(buffer1_copy.mix(&buffer2, 0.5).is_err());
assert!(buffer1_copy.append(&buffer2).is_err());
assert!(buffer1.split(10.0).is_err());
assert!(buffer1.extract(10.0, 1.0).is_err());
}
}