Maraiah/src/durandal/sound.rs

115 lines
2.7 KiB
Rust
Raw Normal View History

2019-02-17 18:17:35 -08:00
//! 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())?;
2019-02-20 18:33:57 -08:00
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
2019-02-17 18:17:35 -08:00
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;
2019-02-17 19:25:20 -08:00
fn lp_beg(&self) -> usize;
fn lp_end(&self) -> usize;
2019-02-17 18:17:35 -08:00
2019-02-20 18:33:57 -08:00
fn is_empty(&self) -> bool {self.len() == 0}
2019-02-17 18:17:35 -08:00
fn get(&self, p: usize) -> Option<i16>
{
if p < self.len() {
Some(self.index(p))
} else {
None
}
}
}
impl Sound16
{
/// Creates a new Sound16.
2019-02-17 19:25:20 -08:00
pub fn new(rate: u16, lp_beg: usize, lp_end: usize, len: usize) -> Self
2019-02-17 18:17:35 -08:00
{
2019-02-17 19:25:20 -08:00
Self{rate, lp_beg, lp_end, data: Vec::with_capacity(len)}
2019-02-17 18:17:35 -08:00
}
/// Creates a new Sound16 from an unsigned 8-bit stream.
2019-02-20 18:33:57 -08:00
pub fn new_from_8(rate: u16, lp_beg: usize, lp_end: usize, b: &[u8])
-> Self
2019-02-17 18:17:35 -08:00
{
2019-02-17 19:25:20 -08:00
let mut snd = Sound16::new(rate, lp_beg, lp_end, b.len());
2019-02-17 18:17:35 -08:00
for &sample in b {
snd.data.push(Sound16::sample_from_8(sample));
}
snd
}
/// Creates a new Sound16 from a signed 16-bit stream.
2019-02-20 18:33:57 -08:00
pub fn new_from_16(rate: u16, lp_beg: usize, lp_end: usize, b: &[u8])
-> Self
2019-02-17 18:17:35 -08:00
{
2019-02-17 19:25:20 -08:00
let mut snd = Sound16::new(rate, lp_beg, lp_end, b.len() / 2);
2019-02-17 18:17:35 -08:00
2019-02-17 19:25:20 -08:00
for i in (0..b.len()).step_by(2) {
snd.data.push(i16::from_le_bytes([b[i], b[i + 1]]));
2019-02-17 18:17:35 -08:00
}
snd
}
/// Creates a signed 16-bit sample from an unsigned 8-bit sample.
2019-02-20 18:33:57 -08:00
pub fn sample_from_8(sample: u8) -> i16 {(i16::from(sample) - 0x80) << 8}
2019-02-17 18:17:35 -08:00
}
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]}
2019-02-17 19:25:20 -08:00
fn lp_beg(&self) -> usize {self.lp_beg}
fn lp_end(&self) -> usize {self.lp_end}
2019-02-17 18:17:35 -08:00
}
pub struct Sound16
{
rate: u16,
2019-02-17 19:25:20 -08:00
lp_beg: usize,
lp_end: usize,
2019-02-17 18:17:35 -08:00
pub data: Vec<i16>,
}
// EOF