Skip to main content

audioadapter_buffers/
lib.rs

1#![doc = include_str!("../README.md")]
2#![cfg_attr(not(feature = "std"), no_std)]
3
4#[cfg(feature = "alloc")]
5extern crate alloc;
6
7/// Wrappers providing direct access to samples in buffers.
8pub mod direct;
9/// Wrappers providing float conversion of numeric values
10/// stored both directly and as raw bytes.
11pub mod number_to_float;
12/// Wrappers that store their data in an owned vector.
13#[cfg(feature = "alloc")]
14pub mod owned;
15
16/// Dummy Adapter
17pub mod dummy;
18
19mod slicetools;
20
21use core::error::Error;
22use core::fmt;
23
24pub mod adapter_to_float;
25
26/// Error returned when the wrapped data structure has the wrong dimensions,
27/// typically that it is too short.
28#[derive(Debug)]
29pub enum SizeError {
30    /// The outer container in a sequential nested layout has too few channel buffers.
31    ///
32    /// This applies to structures like `&[Vec<T>]` or `&[&[T]]` used as
33    /// channel-major data, where each outer element represents one channel.
34    ChannelsContainer { actual: usize, required: usize },
35    /// The outer container in an interleaved nested layout has too few frame buffers.
36    ///
37    /// This applies to structures like `&[Vec<T>]` or `&[&[T]]` used as
38    /// frame-major data, where each outer element represents one frame.
39    FramesContainer { actual: usize, required: usize },
40    /// An inner channel buffer is too short for the requested frame count.
41    ///
42    /// `index` identifies which channel buffer failed the length check.
43    ChannelBuffer {
44        index: usize,
45        actual: usize,
46        required: usize,
47    },
48    /// An inner frame buffer is too short for the requested channel count.
49    ///
50    /// `index` identifies which frame buffer failed the length check.
51    FrameBuffer {
52        index: usize,
53        actual: usize,
54        required: usize,
55    },
56    /// A flat (non-nested) sample buffer is too short for the requested dimensions.
57    ///
58    /// This is used for adapters backed by a single contiguous slice/vector where
59    /// the required length is computed from `channels * frames` (and possibly an
60    /// additional per-sample element factor for raw byte/sample representations).
61    ///
62    /// `actual` is the provided flat buffer length and `required` is the minimum
63    /// length needed for the requested adapter shape.
64    Total { actual: usize, required: usize },
65    /// A channel-activity mask has an invalid length.
66    ///
67    /// This applies to sparse sequential adapters where the mask must contain one
68    /// boolean entry per channel.
69    ///
70    /// `actual` is the provided mask length and `required` is the channel count.
71    Mask { actual: usize, required: usize },
72}
73
74impl Error for SizeError {}
75
76impl fmt::Display for SizeError {
77    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78        match self {
79            SizeError::ChannelsContainer { actual, required } => write!(
80                f,
81                "Channels container is too short, got: {}, required: {}",
82                actual, required
83            ),
84            SizeError::FramesContainer { actual, required } => write!(
85                f,
86                "Frames container is too short, got: {}, required: {}",
87                actual, required
88            ),
89            SizeError::ChannelBuffer {
90                index,
91                actual,
92                required,
93            } => write!(
94                f,
95                "Channel buffer {} is too short for requested frame count, got: {}, required: {}",
96                index, actual, required
97            ),
98            SizeError::FrameBuffer {
99                index,
100                actual,
101                required,
102            } => write!(
103                f,
104                "Frame buffer {} is too short for requested channel count, got: {}, required: {}",
105                index, actual, required
106            ),
107            SizeError::Total { actual, required } => write!(
108                f,
109                "Flat buffer is too short for requested dimensions, got: {}, required: {}",
110                actual, required
111            ),
112            SizeError::Mask { actual, required } => write!(
113                f,
114                "Mask length is invalid for channel count, got: {}, required: {}",
115                actual, required
116            ),
117        }
118    }
119}
120
121macro_rules! implement_size_getters {
122    () => {
123        fn channels(&self) -> usize {
124            self.channels
125        }
126
127        fn frames(&self) -> usize {
128            self.frames
129        }
130    };
131}
132pub(crate) use implement_size_getters;
133
134macro_rules! check_slice_length {
135    ($channels:expr , $frames:expr, $length:expr ) => {
136        if $length < $frames * $channels {
137            return Err(SizeError::Total {
138                actual: $length,
139                required: $frames * $channels,
140            });
141        }
142    };
143    ($channels:expr , $frames:expr, $length:expr, $elements_per_sample:expr) => {
144        if $length < $frames * $channels * $elements_per_sample {
145            return Err(SizeError::Total {
146                actual: $length,
147                required: $frames * $channels * $elements_per_sample,
148            });
149        }
150    };
151}
152pub(crate) use check_slice_length;
153
154#[cfg(test)]
155mod tests {
156    use audioadapter::AdapterMut;
157
158    fn prepare_test_data(buffer: &mut dyn AdapterMut<u32>) {
159        for channel in 0..buffer.channels() {
160            for frame in 0..buffer.frames() {
161                let value = (100 * channel + frame) as u32;
162                buffer.write_sample(channel, frame, &value);
163            }
164        }
165    }
166
167    pub(crate) fn check_copy_within(buffer: &mut dyn AdapterMut<u32>) {
168        assert!(buffer.channels() > 1, "Too few channels to run tests");
169        assert!(buffer.frames() > 8, "Too few frames to run test");
170        // copy forward, no overlap
171        prepare_test_data(buffer);
172        assert_eq!(buffer.copy_frames_within(1, 5, 3), Some(3));
173        check_copy_result(buffer, 1, 5, 3);
174
175        // copy backwards, no overlap
176        prepare_test_data(buffer);
177        assert_eq!(buffer.copy_frames_within(5, 1, 3), Some(3));
178        check_copy_result(buffer, 5, 1, 3);
179
180        // copy forward, with overlap
181        prepare_test_data(buffer);
182        assert_eq!(buffer.copy_frames_within(1, 3, 5), Some(5));
183        check_copy_result(buffer, 1, 3, 5);
184
185        // copy backwards, with overlap
186        prepare_test_data(buffer);
187        assert_eq!(buffer.copy_frames_within(3, 1, 5), Some(5));
188        check_copy_result(buffer, 3, 1, 5);
189    }
190
191    fn check_copy_result(buffer: &dyn AdapterMut<u32>, src: usize, dest: usize, count: usize) {
192        for channel in 0..buffer.channels() {
193            for frame in 0..buffer.frames() {
194                let copied_frame = if frame >= dest && frame < dest + count {
195                    frame + src - dest
196                } else {
197                    frame
198                };
199                let expected_value = (100 * channel + copied_frame) as u32;
200                assert_eq!(
201                    buffer.read_sample(channel, frame),
202                    Some(expected_value),
203                    "Wrong value at ch {}, frame {}",
204                    channel,
205                    frame
206                );
207            }
208        }
209    }
210}