extern crate alloc;
use alloc::vec::Vec;
#[derive(Debug, Clone, PartialEq)]
pub struct Chunk {
data: Vec<f32>,
sample_rate: u32,
channels: u16,
}
impl Chunk {
#[must_use]
pub fn new(data: Vec<f32>, sample_rate: u32, channels: u16) -> Self {
assert!(channels > 0, "channels must be > 0");
assert!(sample_rate > 0, "sample_rate must be > 0");
Self {
data,
sample_rate,
channels,
}
}
#[must_use]
pub fn empty(sample_rate: u32, channels: u16) -> Self {
Self::new(Vec::new(), sample_rate, channels)
}
#[inline]
#[must_use]
pub fn data(&self) -> &[f32] {
&self.data
}
#[inline]
pub fn data_mut(&mut self) -> &mut [f32] {
&mut self.data
}
#[inline]
#[must_use]
pub fn into_data(self) -> Vec<f32> {
self.data
}
#[doc(hidden)]
#[inline]
pub fn set_data(&mut self, data: Vec<f32>) {
self.data = data;
}
#[inline]
#[must_use]
pub fn sample_rate(&self) -> u32 {
self.sample_rate
}
#[inline]
#[must_use]
pub fn channels(&self) -> u16 {
self.channels
}
#[inline]
#[must_use]
pub fn frames(&self) -> usize {
if self.channels == 0 {
return 0;
}
self.data.len() / self.channels as usize
}
#[inline]
#[must_use]
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
#[inline]
#[must_use]
pub fn len(&self) -> usize {
self.data.len()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_mono_chunk() {
let chunk = Chunk::new(vec![1.0, 2.0, 3.0, 4.0], 44100, 1);
assert_eq!(chunk.frames(), 4);
assert_eq!(chunk.len(), 4);
assert_eq!(chunk.channels(), 1);
assert_eq!(chunk.sample_rate(), 44100);
assert!(!chunk.is_empty());
}
#[test]
fn new_stereo_chunk() {
let chunk = Chunk::new(vec![1.0, 2.0, 3.0, 4.0], 48000, 2);
assert_eq!(chunk.frames(), 2);
assert_eq!(chunk.len(), 4);
assert_eq!(chunk.channels(), 2);
}
#[test]
fn empty_chunk() {
let chunk = Chunk::empty(44100, 1);
assert!(chunk.is_empty());
assert_eq!(chunk.frames(), 0);
assert_eq!(chunk.len(), 0);
}
#[test]
fn data_access() {
let chunk = Chunk::new(vec![0.5, -0.5], 44100, 1);
assert_eq!(chunk.data(), &[0.5, -0.5]);
}
#[test]
fn data_mut_allows_modification() {
let mut chunk = Chunk::new(vec![0.0; 4], 44100, 1);
chunk.data_mut()[0] = 1.0;
assert_eq!(chunk.data()[0], 1.0);
}
#[test]
fn into_data_returns_buffer() {
let chunk = Chunk::new(vec![1.0, 2.0], 44100, 1);
let data = chunk.into_data();
assert_eq!(data, vec![1.0, 2.0]);
}
#[test]
fn set_data_replaces_buffer() {
let mut chunk = Chunk::new(vec![1.0], 44100, 1);
chunk.set_data(vec![2.0, 3.0]);
assert_eq!(chunk.data(), &[2.0, 3.0]);
assert_eq!(chunk.frames(), 2);
}
#[test]
fn clone_and_eq() {
let a = Chunk::new(vec![1.0, 2.0], 44100, 2);
let b = a.clone();
assert_eq!(a, b);
}
#[test]
#[should_panic(expected = "channels must be > 0")]
fn zero_channels_panics() {
let _ = Chunk::new(vec![1.0], 44100, 0);
}
#[test]
#[should_panic(expected = "sample_rate must be > 0")]
fn zero_sample_rate_panics() {
let _ = Chunk::new(vec![1.0], 0, 1);
}
}