use {
std::{cmp::min, f32::consts::PI},
voxudio::*,
};
fn calculate_snr(original: &[i16], decoded: &[i16]) -> f32 {
let len = min(original.len(), decoded.len());
let mut signal_power = 0.0;
let mut noise_power = 0.0;
for i in 0..len {
let signal = original[i] as f32;
let noise = signal - decoded[i] as f32;
signal_power += signal * signal;
noise_power += noise * noise;
}
if noise_power > 0.0 && signal_power > 0.0 {
10.0 * (signal_power / noise_power).log10()
} else {
f32::INFINITY }
}
fn generate_complex_audio(duration_ms: usize, sample_rate: usize) -> Vec<i16> {
let num_samples = sample_rate * duration_ms / 1000;
let mut samples = Vec::with_capacity(num_samples * 2);
let max_freq = (sample_rate as f32 / 2.0) * 0.8;
let frequencies = [261.63, 329.63, 392.00, 523.25, 659.25];
for i in 0..num_samples {
let t = i as f32 / sample_rate as f32;
let mut value = 0.0;
for (j, &freq) in frequencies.iter().enumerate() {
if freq < max_freq {
let amplitude = 0.1 / (j + 1) as f32; value += amplitude * f32::sin(2.0 * PI * freq * t);
}
}
let noise_freq = max_freq * 0.5; let noise = f32::sin(t * noise_freq) * f32::cos(t * (noise_freq * 0.7) * 0.005);
value += noise;
value = value.max(-0.8).min(0.8);
let sample = (value * 30000.0) as i16;
samples.push(sample); samples.push((sample as f32 * 0.95) as i16); }
samples
}
fn test_basic_encoding_decoding(
sample_rate: usize,
channels: usize,
bitrate: usize,
) -> Result<(), OperationError> {
println!("\n--- Testing basic encode/decode ({} Hz) ---", sample_rate);
let frame_size = sample_rate * 20 / 1000;
let input_audio = generate_complex_audio(500, sample_rate);
let mut encoder = OpusCodec::new_encoder(sample_rate, channels, OpusApplication::Audio)?;
encoder.set_bitrate(bitrate)?;
encoder.set_complexity(10)?;
encoder.set_bandwidth(OpusCodec::get_max_bandwidth_for_sample_rate(sample_rate))?;
let decoder = OpusCodec::new_decoder(sample_rate, channels)?;
println!("Encoding and decoding multiple frames...");
let frame_count = 5;
let mut all_input = Vec::new();
let mut all_decoded = Vec::new();
for i in 0..frame_count {
let start = i * frame_size * channels;
let end = start + frame_size * channels;
let end = end.min(input_audio.len());
if start >= input_audio.len() {
break;
}
let frame_input = &input_audio[start..end];
all_input.extend_from_slice(frame_input);
let encoded = encoder.encode(frame_input, frame_size, OpusCodec::MAX_PACKET_SIZE)?;
println!(" Frame {}: encoded {} bytes", i + 1, encoded.len());
let decoded = decoder.decode::<i16>(Some(&encoded), frame_size)?;
println!(" Frame {}: decoded {} samples", i + 1, decoded.len());
all_decoded.extend(decoded);
}
println!("Frame size: {} samples (20 ms)", frame_size);
println!("Total input samples: {}", all_input.len());
println!("Total decoded samples: {}", all_decoded.len());
if !all_decoded.is_empty() {
let min_len = min(all_input.len(), all_decoded.len());
let snr = calculate_snr(&all_input[0..min_len], &all_decoded[0..min_len]);
println!("Signal-to-noise ratio (SNR): {:.2} dB", snr);
}
Ok(())
}
#[test]
fn test_opus() -> anyhow::Result<()> {
println!("Opus version: {}", OpusCodec::version());
println!("\n=== Opus codec test - Basic encoding/decoding functionality ===");
let sample_rates = [8000, 16000, 24000, 48000];
let channels = 2;
let bitrate = 256000;
for &rate in &sample_rates {
test_basic_encoding_decoding(rate, channels, bitrate)?;
}
Ok(())
}