//! Sound representation. use crate::durandal::err::*; use std::io; pub fn write_wav(out: &mut impl io::Write, snd: &impl Sound) -> ResultS<()> { let rate = u32::from(snd.rate()); let bps = rate * 2; let ssize = bps * snd.len() as u32; let fsize = 36 + ssize; out.write_all(b"RIFF")?; out.write_all(&fsize.to_le_bytes())?; out.write_all(b"WAVE")?; out.write_all(b"fmt ")?; out.write_all(&16u32.to_le_bytes())?; out.write_all(&1u16.to_le_bytes())?; // PCM out.write_all(&1u16.to_le_bytes())?; // mono out.write_all(&rate.to_le_bytes())?; // rate out.write_all(&bps.to_le_bytes())?; // bytes per second out.write_all(&2u16.to_le_bytes())?; // block alignment out.write_all(&16u16.to_le_bytes())?; // bits per sample out.write_all(b"data")?; out.write_all(&ssize.to_le_bytes())?; for p in 0..snd.len() { let sample = snd.index(p); out.write_all(&sample.to_le_bytes())?; } if ssize & 1 == 1 { out.write_all(&[0])?; } Ok(()) } pub trait Sound { fn rate(&self) -> u16; fn len(&self) -> usize; fn index(&self, p: usize) -> i16; fn is_empty(&self) -> bool { self.len() == 0 } fn get(&self, p: usize) -> Option { if p < self.len() { Some(self.index(p)) } else { None } } } impl Sound8 { /// Creates a new Sound8. pub fn new(rate: u16, len: usize) -> Self { Self{rate, data: Vec::with_capacity(len)} } } impl Sound16 { /// Creates a new Sound16. pub fn new(rate: u16, len: usize) -> Self { Self{rate, data: Vec::with_capacity(len)} } /// Creates a new Sound16 from an unsigned 8-bit stream. pub fn new_from_8(rate: u16, b: &[u8]) -> Self { let mut snd = Sound16::new(rate, b.len()); for &sample in b { snd.data.push(Sound16::sample_from_8(sample)); } snd } /// Creates a new Sound16 from a signed 16-bit stream. pub fn new_from_16(rate: u16, b: &[u8]) -> Self { let mut snd = Sound16::new(rate, b.len() / 2); for (&x, &y) in b.iter().step_by(2).zip(b.iter().step_by(2).next()) { snd.data.push(i16::from_be_bytes([x, y])); } snd } /// Creates a signed 16-bit sample from an unsigned 8-bit sample. pub fn sample_from_8(sample: u8) -> i16 { i16::from(sample) - 0x80 << 8 } } impl Sound for Sound8 { fn rate(&self) -> u16 {self.rate} fn len(&self) -> usize {self.data.len()} fn index(&self, p: usize) -> i16 { Sound16::sample_from_8(self.data[p]) } } impl Sound for Sound16 { fn rate(&self) -> u16 {self.rate} fn len(&self) -> usize {self.data.len()} fn index(&self, p: usize) -> i16 {self.data[p]} } pub struct Sound8 { rate: u16, pub data: Vec, } pub struct Sound16 { rate: u16, pub data: Vec, } // EOF