pub fn int16_to_float32(bytes: &[u8]) -> Vec<f32> {
let len = bytes.len() & !1; let mut out = Vec::with_capacity(len / 2);
for chunk in bytes[..len].chunks_exact(2) {
let sample = i16::from_le_bytes([chunk[0], chunk[1]]);
out.push(sample as f32 / 32768.0);
}
out
}
pub fn float32_to_int16(samples: &[f32]) -> Vec<u8> {
let mut out = Vec::with_capacity(samples.len() * 2);
for &s in samples {
let clamped = s.clamp(-1.0, 1.0);
let i = (clamped * 32767.0) as i16;
out.extend_from_slice(&i.to_le_bytes());
}
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_int16_to_float32_silence() {
let bytes = vec![0u8; 10]; let floats = int16_to_float32(&bytes);
assert_eq!(floats.len(), 5);
assert!(floats.iter().all(|&f| f == 0.0));
}
#[test]
fn test_int16_to_float32_max() {
let bytes = 32767i16.to_le_bytes().to_vec();
let floats = int16_to_float32(&bytes);
assert_eq!(floats.len(), 1);
assert!(
(floats[0] - 0.99997).abs() < 0.001,
"Expected ~0.99997, got {}",
floats[0]
);
}
#[test]
fn test_int16_to_float32_min() {
let bytes = (-32768i16).to_le_bytes().to_vec();
let floats = int16_to_float32(&bytes);
assert_eq!(floats.len(), 1);
assert!(
(floats[0] - (-1.0)).abs() < 1e-6,
"Expected -1.0, got {}",
floats[0]
);
}
#[test]
fn test_roundtrip_pcm() {
let original = vec![0.5f32, -0.5, 0.0, 1.0, -1.0];
let bytes = float32_to_int16(&original);
let recovered = int16_to_float32(&bytes);
for (o, r) in original.iter().zip(recovered.iter()) {
assert!((o - r).abs() < 0.001, "Roundtrip failed: {} vs {}", o, r);
}
}
#[test]
fn test_odd_byte_length() {
let bytes = vec![0u8; 5];
let floats = int16_to_float32(&bytes);
assert_eq!(floats.len(), 2);
}
#[test]
fn test_float32_to_int16_clamping() {
let samples = vec![2.0f32, -2.0, 0.5];
let bytes = float32_to_int16(&samples);
let recovered = int16_to_float32(&bytes);
assert!(recovered[0] > 0.99);
assert!(recovered[1] < -0.99);
assert!((recovered[2] - 0.5).abs() < 0.001);
}
#[test]
fn test_empty_bytes() {
assert_eq!(int16_to_float32(&[]).len(), 0);
assert_eq!(float32_to_int16(&[]).len(), 0);
}
#[test]
fn test_single_byte_truncated() {
let bytes = vec![0xFFu8];
let floats = int16_to_float32(&bytes);
assert_eq!(floats.len(), 0);
}
}