| 37 | /// Prefer [`Self::try_new`] for data that is not already trusted. |
| 38 | pub fn new(samples: Vec<i16>, sample_rate: u32, channels: u16) -> Self { |
| 39 | Self::try_new(samples, sample_rate, channels).expect("invalid mic clip format") |
| 40 | } |
| 41 | |
| 42 | /// Creates a clip after validating channel frames and encoder size limits. |
| 43 | pub fn try_new(samples: Vec<i16>, sample_rate: u32, channels: u16) -> Result<Self, String> { |
| 44 | if sample_rate == 0 { |
| 45 | return Err("mic clip sample rate must be non-zero".to_string()); |
| 46 | } |
| 47 | if channels == 0 { |
| 48 | return Err("mic clip channel count must be non-zero".to_string()); |
| 49 | } |
| 50 | let channel_count = channels as usize; |
| 51 | if !samples.len().is_multiple_of(channel_count) { |
| 52 | return Err(format!( |
| 53 | "mic clip sample count {} is not divisible by {channels} channels", |
| 54 | samples.len() |
| 55 | )); |
| 56 | } |
| 57 | let frames = samples.len() / channel_count; |
| 58 | u32::try_from(frames).map_err(|_| "mic clip frame count exceeds u32".to_string())?; |
| 59 | let data_len = samples |
| 60 | .len() |
| 61 | .checked_mul(std::mem::size_of::<i16>()) |
| 62 | .ok_or_else(|| "mic clip byte length overflow".to_string())?; |
| 63 | let data_len = |
| 64 | u32::try_from(data_len).map_err(|_| "mic clip WAV data exceeds u32".to_string())?; |
| 65 | data_len |
| 66 | .checked_add(36) |
| 67 | .ok_or_else(|| "mic clip WAV RIFF length exceeds u32".to_string())?; |
| 68 | channels |
| 69 | .checked_mul(std::mem::size_of::<i16>() as u16) |
| 70 | .ok_or_else(|| "mic clip WAV block alignment exceeds u16".to_string())?; |
| 71 | sample_rate |
| 72 | .checked_mul(channels as u32) |
| 73 | .and_then(|rate| rate.checked_mul(std::mem::size_of::<i16>() as u32)) |
| 74 | .ok_or_else(|| "mic clip WAV byte rate exceeds u32".to_string())?; |
| 75 | |
| 76 | Ok(Self { |
| 77 | samples: Arc::from(samples), |
| 78 | sample_rate, |
| 79 | channels, |
| 80 | }) |
| 81 | } |
| 82 | |
| 83 | pub fn samples(&self) -> &[i16] { |
| 84 | &self.samples |
| 85 | } |
| 86 | |
| 87 | pub const fn sample_rate(&self) -> u32 { |
| 88 | self.sample_rate |
| 89 | } |
| 90 | |