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}