1use std::io::prelude::*;
2
3pub trait Sample {
4 fn to_i16(&self) -> i16;
5}
6
7impl Sample for f32 {
8 fn to_i16(&self) -> i16 {
9 (self.clamp(-1.0, 1.0) * 32767.0) as i16
10 }
11}
12
13impl Sample for f64 {
14 fn to_i16(&self) -> i16 {
15 (self.clamp(-1.0, 1.0) * 32767.0) as i16
16 }
17}
18
19impl Sample for i16 {
20 fn to_i16(&self) -> i16 {
21 *self
22 }
23}
24
25pub fn write_pcm_as_wav<W: Write, S: Sample>(
26 w: &mut W,
27 samples: &[S],
28 sample_rate: u32,
29) -> std::io::Result<()> {
30 let len = 12u32; let len = len + 24u32; let len = len + samples.len() as u32 * 2 + 8; let n_channels = 1u16;
34 let bytes_per_second = sample_rate * 2 * n_channels as u32;
35 w.write_all(b"RIFF")?;
36 w.write_all(&(len - 8).to_le_bytes())?; w.write_all(b"WAVE")?;
38
39 w.write_all(b"fmt ")?;
41 w.write_all(&16u32.to_le_bytes())?; w.write_all(&1u16.to_le_bytes())?; w.write_all(&n_channels.to_le_bytes())?; w.write_all(&sample_rate.to_le_bytes())?;
45 w.write_all(&bytes_per_second.to_le_bytes())?;
46 w.write_all(&2u16.to_le_bytes())?; w.write_all(&16u16.to_le_bytes())?; w.write_all(b"data")?;
51 w.write_all(&(samples.len() as u32 * 2).to_le_bytes())?;
52 for sample in samples.iter() {
53 w.write_all(&sample.to_i16().to_le_bytes())?
54 }
55 Ok(())
56}