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