wav.rs

2.5 kB · rust · 65 lines

1/// Encodes mono 16-bit pcm samples at a sample rate as a riff wave file.2///3/// ```4/// let bytes = mrlymusic::wav(&[0i16; 4], 44100);5/// assert_eq!(bytes.len(), 52);6/// assert_eq!(&bytes[0..4], b"RIFF");7/// ```8pub fn wav(samples: &[i16], rate: usize) -> Vec<u8> {9    let data = samples.len() * 2;10    let mut out = Vec::with_capacity(44 + data);11    out.extend_from_slice(b"RIFF");12    out.extend_from_slice(&(36 + data as u32).to_le_bytes());13    out.extend_from_slice(b"WAVE");14    out.extend_from_slice(b"fmt ");15    out.extend_from_slice(&16u32.to_le_bytes());16    out.extend_from_slice(&1u16.to_le_bytes());17    out.extend_from_slice(&1u16.to_le_bytes());18    out.extend_from_slice(&(rate as u32).to_le_bytes());19    out.extend_from_slice(&(rate as u32 * 2).to_le_bytes());20    out.extend_from_slice(&2u16.to_le_bytes());21    out.extend_from_slice(&16u16.to_le_bytes());22    out.extend_from_slice(b"data");23    out.extend_from_slice(&(data as u32).to_le_bytes());24    for &sample in samples {25        out.extend_from_slice(&sample.to_le_bytes());26    }27    out28}2930#[cfg(test)]31mod tests {32    use super::*;33    #[test]34    fn wav_lays_out_the_header() {35        let bytes = wav(&[0, 1, -1], 44100);36        assert_eq!(bytes.len(), 50);37        assert_eq!(&bytes[0..4], b"RIFF");38        assert_eq!(&bytes[4..8], &42u32.to_le_bytes());39        assert_eq!(&bytes[8..12], b"WAVE");40        assert_eq!(&bytes[12..16], b"fmt ");41        assert_eq!(&bytes[16..20], &16u32.to_le_bytes());42        assert_eq!(&bytes[20..22], &1u16.to_le_bytes());43        assert_eq!(&bytes[22..24], &1u16.to_le_bytes());44        assert_eq!(&bytes[24..28], &44100u32.to_le_bytes());45        assert_eq!(&bytes[28..32], &88200u32.to_le_bytes());46        assert_eq!(&bytes[32..34], &2u16.to_le_bytes());47        assert_eq!(&bytes[34..36], &16u16.to_le_bytes());48        assert_eq!(&bytes[36..40], b"data");49        assert_eq!(&bytes[40..44], &6u32.to_le_bytes());50        assert_eq!(&bytes[44..], &[0, 0, 1, 0, 255, 255]);51    }52    #[test]53    fn wav_sizes_track_the_sample_count() {54        let empty = wav(&[], 8000);55        assert_eq!(empty.len(), 44);56        assert_eq!(&empty[4..8], &36u32.to_le_bytes());57        assert_eq!(&empty[40..44], &0u32.to_le_bytes());58        let hundred = wav(&[7; 100], 8000);59        assert_eq!(hundred.len(), 244);60        assert_eq!(&hundred[4..8], &236u32.to_le_bytes());61        assert_eq!(&hundred[24..28], &8000u32.to_le_bytes());62        assert_eq!(&hundred[28..32], &16000u32.to_le_bytes());63        assert_eq!(&hundred[40..44], &200u32.to_le_bytes());64    }65}