Skip to main content

dspk_core/buffer/
chunk.rs

1use crate::error::{DspError, DspResult};
2use crate::time::{RationalTime, SampleRate};
3use super::layout::{BufferLayout, MemoryOrder};
4
5/// An authoritative multi-channel signal chunk in host memory.
6#[derive(Debug, Clone, PartialEq)]
7pub struct SignalChunk {
8    layout: BufferLayout,
9    sample_rate: SampleRate,
10    start_time: RationalTime,
11    data: Vec<f32>,
12}
13
14impl SignalChunk {
15    pub fn new(
16        channels: usize,
17        samples: usize,
18        sample_rate: SampleRate,
19        start_time: RationalTime,
20        order: MemoryOrder,
21        data: Vec<f32>,
22    ) -> DspResult<Self> {
23        let expected_len = channels * samples;
24        if data.len() != expected_len {
25            return Err(DspError::ShapeMismatch {
26                expected: vec![expected_len],
27                actual: vec![data.len()],
28            });
29        }
30
31        Ok(Self {
32            layout: BufferLayout::new(channels, samples, order),
33            sample_rate,
34            start_time,
35            data,
36        })
37    }
38
39    pub fn zeros(
40        channels: usize,
41        samples: usize,
42        sample_rate: SampleRate,
43        start_time: RationalTime,
44        order: MemoryOrder,
45    ) -> Self {
46        let data = vec![0.0f32; channels * samples];
47        Self {
48            layout: BufferLayout::new(channels, samples, order),
49            sample_rate,
50            start_time,
51            data,
52        }
53    }
54
55    pub fn layout(&self) -> &BufferLayout {
56        &self.layout
57    }
58
59    pub fn channels(&self) -> usize {
60        self.layout.channels
61    }
62
63    pub fn samples(&self) -> usize {
64        self.layout.samples
65    }
66
67    pub fn sample_rate(&self) -> SampleRate {
68        self.sample_rate
69    }
70
71    pub fn start_time(&self) -> RationalTime {
72        self.start_time
73    }
74
75    pub fn as_slice(&self) -> &[f32] {
76        &self.data
77    }
78
79    pub fn as_mut_slice(&mut self) -> &mut [f32] {
80        &mut self.data
81    }
82
83    fn check(&self, channel: usize, sample: usize) -> DspResult<()> {
84        if channel >= self.layout.channels {
85            return Err(DspError::InvalidChannel { channel, total: self.layout.channels });
86        }
87        if sample >= self.layout.samples {
88            return Err(DspError::SampleRange {
89                start: sample as u64,
90                end: sample as u64 + 1,
91                total: self.layout.samples as u64,
92            });
93        }
94        Ok(())
95    }
96
97    #[inline(always)]
98    pub fn get(&self, channel: usize, sample: usize) -> DspResult<f32> {
99        self.check(channel, sample)?;
100        let idx = self.layout.linear_index(channel, sample);
101        Ok(self.data[idx])
102    }
103
104    #[inline(always)]
105    pub fn set(&mut self, channel: usize, sample: usize, value: f32) -> DspResult<()> {
106        self.check(channel, sample)?;
107        let idx = self.layout.linear_index(channel, sample);
108        self.data[idx] = value;
109        Ok(())
110    }
111}