use super::math::*;
use super::wave::*;
use std::fs::File;
use std::io::prelude::*;
use std::io::BufWriter;
use std::path::Path;
#[inline]
fn write32<W: Write>(writer: &mut W, x: u32) -> std::io::Result<()> {
writer.write_all(&[x as u8, (x >> 8) as u8, (x >> 16) as u8, (x >> 24) as u8])?;
std::io::Result::Ok(())
}
#[inline]
fn write16<W: Write>(writer: &mut W, x: u16) -> std::io::Result<()> {
writer.write_all(&[x as u8, (x >> 8) as u8])?;
std::io::Result::Ok(())
}
fn write_wav_header<W: Write>(
writer: &mut W,
data_length: usize,
format: u16,
channels: usize,
sample_rate: usize,
) -> std::io::Result<()> {
writer.write_all(b"RIFF")?;
write32(writer, data_length as u32 + 36)?;
writer.write_all(b"WAVE")?;
writer.write_all(b"fmt ")?;
write32(writer, 16)?;
write16(writer, format)?;
write16(writer, channels as u16)?;
write32(writer, sample_rate as u32)?;
let sample_bytes = if format == 1 { 2 } else { 4 };
write32(writer, (sample_rate * channels) as u32 * sample_bytes)?;
write16(writer, channels as u16 * sample_bytes as u16)?;
write16(writer, sample_bytes as u16 * 8)?;
writer.write_all(b"data")?;
write32(writer, data_length as u32)?;
std::io::Result::Ok(())
}
impl Wave {
pub fn write_wav16<W: Write>(&self, writer: &mut W) -> std::io::Result<()> {
assert!(self.channels() > 0);
let mut writer = BufWriter::new(writer);
write_wav_header(
&mut writer,
2 * self.channels() * self.length(),
1,
self.channels(),
round(self.sample_rate()) as usize,
)?;
for i in 0..self.length() {
for channel in 0..self.channels() {
let sample = round(clamp11(self.at(channel, i)) * 32767.49);
write16(&mut writer, (sample as i16) as u16)?;
}
}
std::io::Result::Ok(())
}
pub fn write_wav32<W: Write>(&self, writer: &mut W) -> std::io::Result<()> {
assert!(self.channels() > 0);
let mut writer = BufWriter::new(writer);
write_wav_header(
&mut writer,
4 * self.channels() * self.length(),
3,
self.channels(),
round(self.sample_rate()) as usize,
)?;
for i in 0..self.length() {
for channel in 0..self.channels() {
let sample = self.at(channel, i);
writer.write_all(&sample.to_le_bytes())?;
}
}
std::io::Result::Ok(())
}
pub fn save_wav16<P: AsRef<Path>>(&self, path: P) -> std::io::Result<()> {
assert!(self.channels() > 0);
let mut file = File::create(path.as_ref())?;
self.write_wav16(&mut file)
}
pub fn save_wav32<P: AsRef<Path>>(&self, path: P) -> std::io::Result<()> {
assert!(self.channels() > 0);
let mut file = File::create(path.as_ref())?;
self.write_wav32(&mut file)
}
}