media_core/audio/
circular_buffer.rs

1use crate::{audio::SampleFormat, circular_buffer::CircularBuffer, frame::Frame, Error, FrameDescriptorSpec, Result};
2
3pub struct AudioCircularBuffer {
4    buffers: Vec<CircularBuffer>,
5    format: SampleFormat,
6    channels: u8,
7    len: u32,
8    capacity: u32,
9}
10
11impl AudioCircularBuffer {
12    pub fn new(format: SampleFormat, channels: u8, samples: u32) -> Self {
13        let num_buffers = if format.is_planar() {
14            channels as usize
15        } else {
16            1
17        };
18
19        let buffer_size = format.calc_plane_size(channels, samples);
20
21        let mut buffers = Vec::with_capacity(num_buffers);
22        for _ in 0..num_buffers {
23            buffers.push(CircularBuffer::new(buffer_size));
24        }
25
26        Self {
27            buffers,
28            format,
29            channels,
30            len: 0,
31            capacity: samples,
32        }
33    }
34
35    #[inline]
36    pub fn len(&self) -> u32 {
37        self.len
38    }
39
40    #[inline]
41    pub fn is_empty(&self) -> bool {
42        self.len == 0
43    }
44
45    #[inline]
46    pub fn capacity(&self) -> u32 {
47        self.capacity
48    }
49
50    #[inline]
51    pub fn available(&self) -> u32 {
52        self.capacity - self.len
53    }
54
55    pub fn grow(&mut self, samples: u32) -> crate::Result<()> {
56        if self.capacity >= samples {
57            return Ok(());
58        }
59        let buffer_size = self.format.calc_plane_size(self.channels, samples);
60
61        for buffer in &mut self.buffers {
62            buffer.grow(buffer_size)?;
63        }
64
65        self.capacity = samples;
66
67        Ok(())
68    }
69
70    fn validate_frame<D>(&self, frame: &Frame<D>) -> Result<u32>
71    where
72        D: FrameDescriptorSpec,
73    {
74        let desc = frame.descriptor().as_audio().ok_or_else(|| Error::Invalid("not audio frame".to_string()))?;
75
76        if desc.format != self.format {
77            return Err(Error::Invalid("sample format mismatch".to_string()));
78        }
79
80        if desc.channels().get() != self.channels {
81            return Err(Error::Invalid("channel count mismatch".to_string()));
82        }
83
84        Ok(desc.samples.get())
85    }
86
87    pub fn write<D>(&mut self, frame: &Frame<D>) -> Result<usize>
88    where
89        D: FrameDescriptorSpec,
90    {
91        let samples = self.validate_frame(frame)?;
92
93        if self.available() < samples {
94            self.grow(self.len + samples)?;
95        }
96
97        let guard = frame.map().map_err(|_| Error::Invalid("cannot read source frame".into()))?;
98        let planes = guard.planes().unwrap();
99
100        if planes.len() != self.buffers.len() {
101            return Err(Error::Invalid("plane count mismatch".to_string()));
102        }
103
104        planes.iter().enumerate().try_for_each(|(i, plane)| {
105            let buffer = &mut self.buffers[i];
106            buffer.write(plane.data().unwrap())?;
107            Ok(())
108        })?;
109
110        self.len += samples;
111
112        Ok(samples as usize)
113    }
114
115    pub fn read<D>(&mut self, frame: &mut Frame<D>) -> Result<usize>
116    where
117        D: FrameDescriptorSpec,
118    {
119        let samples = self.validate_frame(frame)?.min(self.len);
120
121        let mut guard = frame.map_mut().map_err(|_| Error::Invalid("cannot write destination frame".into()))?;
122        let mut planes = guard.planes_mut().unwrap();
123
124        if planes.len() != self.buffers.len() {
125            return Err(Error::Invalid("plane count mismatch".to_string()));
126        }
127
128        planes.iter_mut().enumerate().try_for_each(|(i, plane)| {
129            let buffer = &mut self.buffers[i];
130            buffer.read(plane.data_mut().unwrap())?;
131            Ok(())
132        })?;
133
134        self.len -= samples;
135
136        Ok(samples as usize)
137    }
138
139    pub fn clear(&mut self) {
140        self.buffers.iter_mut().for_each(|buffer| buffer.clear());
141        self.len = 0;
142    }
143}