rawdio/buffer/
owned_audio_buffer.rs

1use crate::prelude::*;
2use rand::Rng;
3use std::ops::Range;
4
5/// An audio buffer that owns its audio data
6///
7/// Create an `OwnedAudioBuffer` will allocate a vector with enough space to hold the audio data
8#[repr(align(64))]
9#[derive(Clone)]
10pub struct OwnedAudioBuffer {
11    data: Vec<f32>,
12    channel_count: usize,
13    frame_count: usize,
14    sample_rate: usize,
15}
16
17impl OwnedAudioBuffer {
18    /// Create an audio buffer with specified number of frames, channels, and at  the specified sample rate
19    pub fn new(frame_count: usize, channel_count: usize, sample_rate: usize) -> Self {
20        Self {
21            data: vec![0.0; frame_count * channel_count],
22            channel_count,
23            frame_count,
24            sample_rate,
25        }
26    }
27
28    /// Create an audio buffer with audio from the specified slice
29    ///
30    /// The audio from `data` represents a single channel and will be copied to all channels
31    pub fn from_slice(data: &[f32], channel_count: usize, sample_rate: usize) -> Self {
32        let mut buffer = Self::new(data.len(), 1, sample_rate);
33
34        for channel in 0..channel_count {
35            buffer.fill_from_slice(data, SampleLocation::channel(channel));
36        }
37
38        buffer
39    }
40
41    /// Create a buffer by copying the data from another buffer
42    pub fn from_buffer(buffer: &dyn AudioBuffer) -> Self {
43        let mut new_buffer = Self::new(
44            buffer.frame_count(),
45            buffer.channel_count(),
46            buffer.sample_rate(),
47        );
48
49        new_buffer.copy_from(
50            buffer,
51            SampleLocation::origin(),
52            SampleLocation::origin(),
53            buffer.channel_count(),
54            buffer.frame_count(),
55        );
56
57        new_buffer
58    }
59
60    /// Create a new buffer with the existing audio data, and copying in the data from `buffer`
61    ///
62    /// `buffer` should have the same number of channels and be at the same sample rate
63    pub fn extended_with_buffer(&self, buffer: &dyn AudioBuffer) -> Self {
64        assert_eq!(buffer.channel_count(), self.channel_count());
65        assert_eq!(buffer.sample_rate(), self.sample_rate());
66
67        let mut new_buffer = Self::new(
68            self.frame_count() + buffer.frame_count(),
69            self.channel_count(),
70            self.sample_rate(),
71        );
72
73        new_buffer.copy_from(
74            self,
75            SampleLocation::origin(),
76            SampleLocation::origin(),
77            self.channel_count(),
78            self.frame_count(),
79        );
80
81        new_buffer.copy_from(
82            buffer,
83            SampleLocation::origin(),
84            SampleLocation::frame(self.frame_count()),
85            buffer.channel_count(),
86            buffer.frame_count(),
87        );
88
89        new_buffer
90    }
91
92    /// Create a buffer with random audio samples
93    pub fn white_noise(frame_count: usize, channel_count: usize, sample_rate: usize) -> Self {
94        let mut buffer = Self::new(frame_count, channel_count, sample_rate);
95
96        let mut random_generator = rand::thread_rng();
97
98        for frame in buffer.frame_iter() {
99            let sample_value = random_generator.gen_range(-1.0..=1.0);
100            buffer.set_sample(frame, sample_value);
101        }
102
103        buffer
104    }
105
106    /// Create a new buffer that has been padded to the specified length
107    pub fn padded_to_length(&self, frame_count: usize) -> Self {
108        let mut buffer = Self::new(frame_count, self.channel_count(), self.sample_rate());
109
110        buffer.copy_from(
111            self,
112            SampleLocation::origin(),
113            SampleLocation::origin(),
114            self.channel_count(),
115            self.frame_count(),
116        );
117
118        buffer
119    }
120
121    /// Create an audio buffer filled with a sine wave at the specified frequency
122    pub fn sine(
123        frame_count: usize,
124        channel_count: usize,
125        sample_rate: usize,
126        frequency: f64,
127        amplitude: f64,
128    ) -> Self {
129        debug_assert!(channel_count > 0);
130
131        let mut buffer = Self::new(frame_count, channel_count, sample_rate);
132
133        let channel = buffer.get_channel_data_mut(SampleLocation::origin());
134
135        for (index, sample) in channel.iter_mut().enumerate() {
136            let time = index as f64 / sample_rate as f64;
137            *sample = (amplitude * (std::f64::consts::TAU * frequency * time).sin()) as f32;
138        }
139
140        for channel in 1..channel_count {
141            let source_location = SampleLocation::channel(0);
142            buffer.duplicate_channel(source_location, channel, frame_count);
143        }
144
145        buffer
146    }
147
148    /// Create an audio buffer that is value 0.0 until frame_count, then 1.0
149    pub fn step(
150        frame_count: usize,
151        channel_count: usize,
152        sample_rate: usize,
153        step_range: Range<usize>,
154    ) -> Self {
155        let mut buffer = Self::new(frame_count, channel_count, sample_rate);
156
157        let channel = buffer.get_channel_data_mut(SampleLocation::origin());
158
159        for (index, sample) in channel.iter_mut().enumerate() {
160            *sample = if step_range.contains(&index) {
161                1.0
162            } else {
163                0.0
164            };
165        }
166
167        for channel in 1..channel_count {
168            let source_location = SampleLocation::channel(0);
169            buffer.duplicate_channel(source_location, channel, frame_count);
170        }
171
172        buffer
173    }
174
175    fn get_sample_location_range(&self, sample_location: &SampleLocation) -> Range<usize> {
176        let start = sample_location.channel * self.frame_count + sample_location.frame;
177        let end = (sample_location.channel + 1) * self.frame_count;
178        start..end
179    }
180}
181
182impl AudioBuffer for OwnedAudioBuffer {
183    fn channel_count(&self) -> usize {
184        self.channel_count
185    }
186
187    fn frame_count(&self) -> usize {
188        self.frame_count
189    }
190
191    fn sample_rate(&self) -> usize {
192        self.sample_rate
193    }
194
195    fn get_channel_data(&self, sample_location: SampleLocation) -> &[f32] {
196        let range = self.get_sample_location_range(&sample_location);
197        &self.data[range]
198    }
199
200    fn get_channel_data_mut(&mut self, sample_location: SampleLocation) -> &mut [f32] {
201        let range = self.get_sample_location_range(&sample_location);
202        &mut self.data[range]
203    }
204
205    fn duplicate_channel(&mut self, source: SampleLocation, to_channel: usize, frame_count: usize) {
206        let source_range = self.get_sample_location_range(&source);
207        let destination_range = self.get_sample_location_range(&source.with_channel(to_channel));
208        self.data.copy_within(
209            source_range.start..source_range.start + frame_count,
210            destination_range.start,
211        );
212    }
213}
214
215#[cfg(test)]
216mod tests {
217
218    use super::*;
219    use rand::Rng;
220
221    fn random_sample() -> f32 {
222        let mut generator = rand::thread_rng();
223        generator.gen_range(-1.0_f32..=1.0_f32)
224    }
225
226    fn is_empty(buffer: &dyn AudioBuffer) -> bool {
227        for channel in 0..buffer.channel_count() {
228            let data = buffer.get_channel_data(SampleLocation::channel(channel));
229            if !data.iter().all(|value| relative_eq!(*value, 0.0)) {
230                return false;
231            }
232        }
233
234        true
235    }
236
237    #[test]
238    fn starts_empty() {
239        let frame_count = 1000;
240        let channel_count = 2;
241        let sample_rate = 44100;
242        let buffer = OwnedAudioBuffer::new(frame_count, channel_count, sample_rate);
243        assert!(is_empty(&buffer));
244    }
245
246    #[test]
247    fn clear_resets_all_samples() {
248        let frame_count = 1000;
249        let channel_count = 2;
250        let sample_rate = 44100;
251        let mut buffer = OwnedAudioBuffer::white_noise(frame_count, channel_count, sample_rate);
252
253        assert!(!is_empty(&buffer));
254        buffer.clear();
255        assert!(is_empty(&buffer));
256    }
257
258    #[test]
259    fn set_and_get_a_sample() {
260        let frame_count = 1000;
261        let channel_count = 2;
262        let sample_rate = 44100;
263        let mut buffer = OwnedAudioBuffer::new(frame_count, channel_count, sample_rate);
264
265        let frame_index = 53;
266        let channel_index = 1;
267        let location = SampleLocation::new(channel_index, frame_index);
268
269        let expected_sample = random_sample();
270        buffer.set_sample(location, expected_sample);
271
272        let actual_sample = buffer.get_sample(location);
273        assert_eq!(expected_sample, actual_sample);
274    }
275}