web_audio_api/
buffer.rs

1//! General purpose audio signal data structures
2use std::sync::Arc;
3
4use crate::{
5    assert_valid_buffer_length, assert_valid_channel_number, assert_valid_number_of_channels,
6    assert_valid_sample_rate,
7};
8
9/// Options for constructing an [`AudioBuffer`]
10// dictionary AudioBufferOptions {
11//   unsigned long numberOfChannels = 1;
12//   required unsigned long length;
13//   required float sampleRate;
14// };
15#[derive(Clone, Debug)]
16pub struct AudioBufferOptions {
17    /// The number of channels for the buffer
18    pub number_of_channels: usize,
19    /// The length in sample frames of the buffer
20    pub length: usize,
21    /// The sample rate in Hz for the buffer
22    pub sample_rate: f32,
23}
24
25/// Memory-resident audio asset, basically a matrix of channels * samples
26///
27/// An AudioBuffer has copy-on-write semantics, so it is cheap to clone.
28///
29/// - MDN documentation: <https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer>
30/// - specification: <https://webaudio.github.io/web-audio-api/#AudioBuffer>
31/// - see also: [`BaseAudioContext::create_buffer`](crate::context::BaseAudioContext::create_buffer)
32///
33/// # Usage
34///
35/// ```no_run
36/// use std::f32::consts::PI;
37/// use web_audio_api::context::{AudioContext, BaseAudioContext};
38/// use web_audio_api::node::{AudioNode, AudioScheduledSourceNode};
39///
40/// let context = AudioContext::default();
41///
42/// let length = context.sample_rate() as usize;
43/// let sample_rate = context.sample_rate();
44/// let mut buffer = context.create_buffer(1, length, sample_rate);
45///
46/// // fill buffer with a sine wave
47/// let mut sine = vec![];
48///
49/// for i in 0..length {
50///     let phase = i as f32 / length as f32 * 2. * PI * 200.;
51///     sine.push(phase.sin());
52/// }
53///
54/// buffer.copy_to_channel(&sine, 0);
55///
56/// // play the buffer in a loop
57/// let mut src = context.create_buffer_source();
58/// src.set_buffer(buffer.clone());
59/// src.set_loop(true);
60/// src.connect(&context.destination());
61/// src.start();
62/// ```
63///
64/// # Example
65///
66/// - `cargo run --release --example audio_buffer`
67///
68#[derive(Clone, Debug)]
69pub struct AudioBuffer {
70    pub(crate) channels: Vec<ChannelData>,
71    pub(crate) sample_rate: f32,
72}
73
74impl AudioBuffer {
75    /// Allocate a silent audiobuffer with [`AudioBufferOptions`]
76    ///
77    /// # Panics
78    ///
79    /// This function will panic if:
80    /// - the given sample rate is zero
81    /// - the given number of channels is outside the [1, 32] range,
82    ///   32 being defined by the MAX_CHANNELS constant.
83    pub fn new(options: AudioBufferOptions) -> Self {
84        assert_valid_sample_rate(options.sample_rate);
85        assert_valid_buffer_length(options.length);
86        assert_valid_number_of_channels(options.number_of_channels);
87
88        let silence = ChannelData::new(options.length);
89
90        Self {
91            channels: vec![silence; options.number_of_channels],
92            sample_rate: options.sample_rate,
93        }
94    }
95
96    /// Convert raw samples to an AudioBuffer
97    ///
98    /// The outer Vec determine the channels. The inner Vecs should have the same length.
99    ///
100    /// # Panics
101    ///
102    /// This function will panic if:
103    /// - the given sample rate is zero
104    /// - the given number of channels defined by `samples.len()`is outside the
105    ///   [1, 32] range, 32 being defined by the MAX_CHANNELS constant.
106    /// - any of its items have different lengths
107    pub fn from(samples: Vec<Vec<f32>>, sample_rate: f32) -> Self {
108        assert_valid_sample_rate(sample_rate);
109        assert_valid_number_of_channels(samples.len());
110
111        let channels: Vec<_> = samples.into_iter().map(ChannelData::from).collect();
112        if !channels.iter().all(|c| c.len() == channels[0].len()) {
113            panic!("Trying to create AudioBuffer from channel data with unequal length");
114        }
115
116        Self {
117            channels,
118            sample_rate,
119        }
120    }
121
122    /// Number of channels in this `AudioBuffer`
123    pub fn number_of_channels(&self) -> usize {
124        self.channels.len()
125    }
126
127    /// Number of samples per channel in this `AudioBuffer`
128    pub fn length(&self) -> usize {
129        self.channels.first().map(ChannelData::len).unwrap_or(0)
130    }
131
132    /// Sample rate of this `AudioBuffer` in Hertz
133    pub fn sample_rate(&self) -> f32 {
134        self.sample_rate
135    }
136
137    /// Duration in seconds of the `AudioBuffer`
138    pub fn duration(&self) -> f64 {
139        self.length() as f64 / self.sample_rate as f64
140    }
141
142    /// Copy data from a given channel to the given `Vec`
143    ///
144    /// # Panics
145    ///
146    /// This function will panic if `channel_number` is greater or equal than
147    /// `AudioBuffer::number_of_channels()`
148    pub fn copy_from_channel(&self, destination: &mut [f32], channel_number: usize) {
149        assert_valid_channel_number(channel_number, self.number_of_channels());
150
151        self.copy_from_channel_with_offset(destination, channel_number, 0);
152    }
153
154    /// Copy data from a given channel to the given `Vec` starting at `offset`
155    ///
156    /// # Panics
157    ///
158    /// This function will panic if:
159    /// - the given channel number is greater than or equal to the given number of channels.
160    pub fn copy_from_channel_with_offset(
161        &self,
162        destination: &mut [f32],
163        channel_number: usize,
164        offset: usize,
165    ) {
166        assert_valid_channel_number(channel_number, self.number_of_channels());
167        let offset = offset.min(self.length());
168        // [spec] Let buffer be the AudioBuffer with 𝑁𝑏 frames, let 𝑁𝑓 be the number
169        // of elements in the destination array, and 𝑘 be the value of bufferOffset.
170        // Then the number of frames copied from buffer to destination is max(0,min(𝑁𝑏−𝑘,𝑁𝑓)).
171        // If this is less than 𝑁𝑓, then the remaining elements of destination are not modified.
172        let dest_length = destination.len();
173        let max_frame = (self.length() - offset).clamp(0, dest_length);
174        let channel = self.channel_data(channel_number).as_slice();
175
176        destination[..max_frame].copy_from_slice(&channel[offset..(max_frame + offset)]);
177    }
178
179    /// Copy data from a given source to the given channel.
180    ///
181    /// # Panics
182    ///
183    /// This function will panic if:
184    /// - the given channel number is greater than or equal to the given number of channels.
185    pub fn copy_to_channel(&mut self, source: &[f32], channel_number: usize) {
186        assert_valid_channel_number(channel_number, self.number_of_channels());
187
188        self.copy_to_channel_with_offset(source, channel_number, 0);
189    }
190
191    /// Copy data from a given source to the given channel starting at `offset`.
192    ///
193    /// # Panics
194    ///
195    /// This function will panic if:
196    /// - the given channel number is greater than or equal to the given number of channels.
197    pub fn copy_to_channel_with_offset(
198        &mut self,
199        source: &[f32],
200        channel_number: usize,
201        offset: usize,
202    ) {
203        assert_valid_channel_number(channel_number, self.number_of_channels());
204        let offset = offset.min(self.length());
205        // [spec] Let buffer be the AudioBuffer with 𝑁𝑏 frames, let 𝑁𝑓 be the number
206        // of elements in the source array, and 𝑘 be the value of bufferOffset. Then
207        // the number of frames copied from source to the buffer is max(0,min(𝑁𝑏−𝑘,𝑁𝑓)).
208        // If this is less than 𝑁𝑓, then the remaining elements of buffer are not modified.
209        let src_len = source.len();
210        let max_frame = (self.length() - offset).clamp(0, src_len);
211        let channel = self.channel_data_mut(channel_number).as_mut_slice();
212
213        channel[offset..(max_frame + offset)].copy_from_slice(&source[..max_frame]);
214    }
215
216    /// Return a read-only copy of the underlying data of the channel
217    ///
218    /// # Panics
219    ///
220    /// This function will panic if:
221    /// - the given channel number is greater than or equal to the given number of channels.
222    pub fn get_channel_data(&self, channel_number: usize) -> &[f32] {
223        assert_valid_channel_number(channel_number, self.number_of_channels());
224        // [spec] According to the rules described in acquire the content either allow writing
225        // into or getting a copy of the bytes stored in [[internal data]] in a new Float32Array
226        self.channel_data(channel_number).as_slice()
227    }
228
229    /// Return a mutable slice of the underlying data of the channel
230    ///
231    /// # Panics
232    ///
233    /// This function will panic if:
234    /// - the given channel number is greater than or equal to the given number of channels.
235    pub fn get_channel_data_mut(&mut self, channel_number: usize) -> &mut [f32] {
236        assert_valid_channel_number(channel_number, self.number_of_channels());
237        self.channel_data_mut(channel_number).as_mut_slice()
238    }
239
240    /// Create a multi-channel audiobuffer directly from `ChannelData`s.
241    // @todo - remove in favor of `AudioBuffer::from`
242    pub(crate) fn from_channels(channels: Vec<ChannelData>, sample_rate: f32) -> Self {
243        Self {
244            channels,
245            sample_rate,
246        }
247    }
248
249    /// Channel data as slice
250    pub(crate) fn channels(&self) -> &[ChannelData] {
251        &self.channels
252    }
253
254    /// Channel data as slice (mutable)
255    pub(crate) fn channels_mut(&mut self) -> &mut [ChannelData] {
256        &mut self.channels
257    }
258
259    /// Get the samples from this specific channel.
260    ///
261    /// Panics if the index is greater than the available number of channels
262    // @note - this one is used in
263    pub(crate) fn channel_data(&self, index: usize) -> &ChannelData {
264        &self.channels[index]
265    }
266
267    /// Get the samples (mutable) from this specific channel.
268    ///
269    /// Panics if the index is greater than the available number of channels
270    pub(crate) fn channel_data_mut(&mut self, index: usize) -> &mut ChannelData {
271        &mut self.channels[index]
272    }
273
274    /// Extends an AudioBuffer with the contents of another.
275    ///
276    /// This function will panic if the sample_rate and channel_count are not equal
277    pub(crate) fn extend(&mut self, other: &Self) {
278        assert_eq!(self.sample_rate, other.sample_rate);
279        assert_eq!(self.number_of_channels(), other.number_of_channels());
280
281        let data = self.channels_mut();
282        data.iter_mut()
283            .zip(other.channels.iter())
284            .for_each(|(channel, other_channel)| {
285                let cur_channel_data = Arc::make_mut(&mut channel.data);
286                cur_channel_data.extend(other_channel.as_slice());
287            })
288    }
289
290    /// Split an AudioBuffer in two at the given index.
291    pub(crate) fn split_off(&mut self, index: usize) -> Self {
292        let channels: Vec<_> = self
293            .channels_mut()
294            .iter_mut()
295            .map(|channel_data| Arc::make_mut(&mut channel_data.data).split_off(index))
296            .map(ChannelData::from)
297            .collect();
298
299        AudioBuffer::from_channels(channels, self.sample_rate)
300    }
301
302    /// Resample to the desired sample rate. The method performs a simple linear
303    /// interpolation an keep the first and last sample intact. The new number
304    /// of samples is always ceiled according the ratio defined by old and new
305    /// sample rates.
306    ///
307    /// # Panics
308    ///
309    /// This function will panic if:
310    /// - the given sample rate is zero
311    pub(crate) fn resample(&mut self, sample_rate: f32) {
312        assert_valid_sample_rate(sample_rate);
313
314        // if requested sample rate is very similar, do not resample
315        if float_eq::float_eq!(self.sample_rate, sample_rate, abs <= 0.1) {
316            self.sample_rate = sample_rate;
317            return;
318        }
319
320        // handle zero length case
321        if self.length() == 0 {
322            self.sample_rate = sample_rate;
323            return;
324        }
325
326        let source_sr = self.sample_rate as f64;
327        let target_sr = sample_rate as f64;
328        let ratio = target_sr / source_sr;
329        let source_length = self.length();
330        let target_length = (self.length() as f64 * ratio).ceil() as usize;
331
332        let num_channels = self.number_of_channels();
333        let mut resampled = Vec::<Vec<f32>>::with_capacity(num_channels);
334        resampled.resize_with(num_channels, || Vec::<f32>::with_capacity(target_length));
335
336        for i in 0..target_length {
337            let position = i as f64 / (target_length - 1) as f64; // [0., 1.]
338            let playhead = position * (source_length - 1) as f64;
339            let playhead_floored = playhead.floor();
340            let prev_index = playhead_floored as usize;
341            let next_index = (prev_index + 1).min(source_length - 1);
342
343            let k = (playhead - playhead_floored) as f32;
344            let k_inv = 1. - k;
345
346            for (channel, resampled_data) in resampled.iter_mut().enumerate() {
347                let prev_sample = self.channels[channel].data[prev_index];
348                let next_sample = self.channels[channel].data[next_index];
349
350                let value = k_inv * prev_sample + k * next_sample;
351                resampled_data.push(value);
352            }
353        }
354
355        self.channels
356            .iter_mut()
357            .zip(resampled)
358            .for_each(|(channel_data, resampled_data)| {
359                channel_data.data = Arc::new(resampled_data);
360            });
361
362        self.sample_rate = sample_rate;
363    }
364}
365
366/// Single channel audio samples, basically wraps a `Arc<Vec<f32>>`
367///
368/// ChannelData has copy-on-write semantics, so it is cheap to clone.
369#[derive(Clone, PartialEq)]
370pub(crate) struct ChannelData {
371    data: Arc<Vec<f32>>,
372}
373
374impl std::fmt::Debug for ChannelData {
375    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
376        f.debug_struct("ChannelData")
377            .field("len", &self.len())
378            .finish_non_exhaustive()
379    }
380}
381
382impl ChannelData {
383    pub fn new(length: usize) -> Self {
384        let buffer = vec![0.; length];
385        let data = Arc::new(buffer);
386
387        Self { data }
388    }
389
390    pub fn from(data: Vec<f32>) -> Self {
391        Self {
392            data: Arc::new(data),
393        }
394    }
395
396    pub fn len(&self) -> usize {
397        self.data.len()
398    }
399
400    // clippy wants to keep it, so keep it :)
401    #[allow(dead_code)]
402    pub fn is_empty(&self) -> bool {
403        self.data.is_empty()
404    }
405
406    pub fn as_slice(&self) -> &[f32] {
407        &self.data[..]
408    }
409
410    pub fn as_mut_slice(&mut self) -> &mut [f32] {
411        &mut Arc::make_mut(&mut self.data)[..]
412    }
413}
414
415#[cfg(test)]
416mod tests {
417    use float_eq::assert_float_eq;
418    use std::f32::consts::PI;
419
420    use super::*;
421
422    #[test]
423    fn test_constructor() {
424        let options = AudioBufferOptions {
425            number_of_channels: 1,
426            length: 96000,
427            sample_rate: 48000.,
428        };
429
430        let audio_buffer = AudioBuffer::new(options);
431
432        assert_eq!(audio_buffer.number_of_channels(), 1);
433        assert_eq!(audio_buffer.length(), 96000);
434        assert_float_eq!(audio_buffer.sample_rate(), 48000., abs <= 0.);
435        assert_float_eq!(audio_buffer.duration(), 2., abs <= 0.);
436    }
437
438    #[test]
439    #[should_panic]
440    fn test_zero_channels() {
441        let options = AudioBufferOptions {
442            number_of_channels: 0,
443            length: 10,
444            sample_rate: 48000.,
445        };
446
447        AudioBuffer::new(options); // should panic
448    }
449
450    #[test]
451    #[should_panic]
452    fn test_zero_channels_from() {
453        let samples = vec![];
454        let sample_rate = 48000.;
455
456        AudioBuffer::from(samples, sample_rate); // should panic
457    }
458
459    #[test]
460    #[should_panic]
461    fn test_invalid_sample_rate() {
462        let options = AudioBufferOptions {
463            number_of_channels: 1,
464            length: 10,
465            sample_rate: 0.,
466        };
467
468        AudioBuffer::new(options); // should panic
469    }
470
471    #[test]
472    #[should_panic]
473    fn test_invalid_sample_rate_from() {
474        let samples = vec![vec![0.]];
475        let sample_rate = 0.;
476
477        AudioBuffer::from(samples, sample_rate); // should panic
478    }
479
480    #[test]
481    #[should_panic]
482    fn test_invalid_length() {
483        let options = AudioBufferOptions {
484            number_of_channels: 1,
485            length: 0,
486            sample_rate: 48000.,
487        };
488
489        AudioBuffer::new(options); // should panic
490    }
491
492    #[test]
493    fn test_channel_data_get_set() {
494        let options = AudioBufferOptions {
495            number_of_channels: 1,
496            length: 10,
497            sample_rate: 48000.,
498        };
499
500        let mut audio_buffer = AudioBuffer::new(options);
501        audio_buffer.channel_data_mut(0).as_mut_slice().fill(1.);
502        assert_float_eq!(
503            audio_buffer.channel_data(0).as_slice()[..],
504            [1.; 10][..],
505            abs_all <= 0.
506        );
507    }
508
509    #[test]
510    #[should_panic]
511    fn test_invalid_copy_from_channel() {
512        let options = AudioBufferOptions {
513            number_of_channels: 1,
514            length: 10,
515            sample_rate: 48000.,
516        };
517
518        let audio_buffer = AudioBuffer::new(options);
519
520        // same size
521        let mut dest = vec![1.; 10];
522        audio_buffer.copy_from_channel(&mut dest, 1);
523    }
524
525    #[test]
526    fn test_copy_from_channel() {
527        let options = AudioBufferOptions {
528            number_of_channels: 1,
529            length: 10,
530            sample_rate: 48000.,
531        };
532
533        let audio_buffer = AudioBuffer::new(options);
534
535        // same size
536        let mut dest = vec![1.; 10];
537        audio_buffer.copy_from_channel(&mut dest, 0);
538        assert_float_eq!(dest[..], vec![0.; 10][..], abs_all <= 0.);
539
540        // smaller destination
541        let mut dest = vec![1.; 5];
542        audio_buffer.copy_from_channel(&mut dest, 0);
543        assert_float_eq!(dest[..], [0., 0., 0., 0., 0.][..], abs_all <= 0.);
544
545        // larger destination
546        let mut dest = vec![1.; 11];
547        audio_buffer.copy_from_channel(&mut dest, 0);
548        assert_float_eq!(
549            dest[..],
550            [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.][..],
551            abs_all <= 0.
552        );
553
554        // with offset
555        let mut dest = vec![1.; 10];
556        audio_buffer.copy_from_channel_with_offset(&mut dest, 0, 5);
557        assert_float_eq!(
558            dest[..],
559            [0., 0., 0., 0., 0., 1., 1., 1., 1., 1.][..],
560            abs_all <= 0.
561        );
562
563        // w/ offset outside range
564        let mut dest = vec![1.; 10];
565        audio_buffer.copy_from_channel_with_offset(&mut dest, 0, usize::MAX);
566
567        assert_float_eq!(dest[..], vec![1.; 10][..], abs_all <= 0.);
568    }
569
570    #[test]
571    #[should_panic]
572    fn test_invalid_copy_to_channel() {
573        let options = AudioBufferOptions {
574            number_of_channels: 1,
575            length: 10,
576            sample_rate: 48000.,
577        };
578
579        let mut audio_buffer = AudioBuffer::new(options);
580
581        // same size
582        let src = vec![1.; 10];
583        audio_buffer.copy_to_channel(&src, 1);
584    }
585
586    #[test]
587    fn test_copy_to_channel() {
588        let options = AudioBufferOptions {
589            number_of_channels: 1,
590            length: 10,
591            sample_rate: 48000.,
592        };
593
594        {
595            // same size
596            let mut audio_buffer = AudioBuffer::new(options.clone());
597            let src = vec![1.; 10];
598            audio_buffer.copy_to_channel(&src, 0);
599            assert_float_eq!(
600                audio_buffer.channel_data(0).as_slice()[..],
601                [1.; 10][..],
602                abs_all <= 0.
603            );
604        }
605
606        {
607            // smaller source
608            let mut audio_buffer = AudioBuffer::new(options.clone());
609            let src = vec![1.; 5];
610            audio_buffer.copy_to_channel(&src, 0);
611            assert_float_eq!(
612                audio_buffer.channel_data(0).as_slice()[..],
613                [1., 1., 1., 1., 1., 0., 0., 0., 0., 0.][..],
614                abs_all <= 0.
615            );
616        }
617
618        {
619            // larger source
620            let mut audio_buffer = AudioBuffer::new(options.clone());
621            let src = vec![1.; 12];
622            audio_buffer.copy_to_channel(&src, 0);
623            assert_float_eq!(
624                audio_buffer.channel_data(0).as_slice()[..],
625                [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.][..],
626                abs_all <= 0.
627            );
628        }
629
630        {
631            // w/ offset
632            let mut audio_buffer = AudioBuffer::new(options.clone());
633            let src = vec![1.; 10];
634            audio_buffer.copy_to_channel_with_offset(&src, 0, 5);
635            assert_float_eq!(
636                audio_buffer.channel_data(0).as_slice()[..],
637                [0., 0., 0., 0., 0., 1., 1., 1., 1., 1.][..],
638                abs_all <= 0.
639            );
640        }
641
642        {
643            // w/ offset outside range
644            let mut audio_buffer = AudioBuffer::new(options);
645            let src = vec![1.; 10];
646            audio_buffer.copy_to_channel_with_offset(&src, 0, usize::MAX);
647            assert_float_eq!(
648                audio_buffer.channel_data(0).as_slice()[..],
649                [0.; 10][..],
650                abs_all <= 0.
651            );
652        }
653    }
654
655    #[test]
656    #[should_panic]
657    fn test_invalid_get_channel_data() {
658        let options = AudioBufferOptions {
659            number_of_channels: 1,
660            length: 10,
661            sample_rate: 48000.,
662        };
663
664        let audio_buffer = AudioBuffer::new(options);
665
666        audio_buffer.get_channel_data(1);
667    }
668
669    // internal API
670    #[test]
671    fn test_silent() {
672        let options = AudioBufferOptions {
673            number_of_channels: 2,
674            length: 10,
675            sample_rate: 44100.,
676        };
677        let b = AudioBuffer::new(options);
678
679        assert_eq!(b.length(), 10);
680        assert_eq!(b.number_of_channels(), 2);
681        assert_float_eq!(b.sample_rate(), 44100., abs_all <= 0.);
682        assert_float_eq!(b.channel_data(0).as_slice(), &[0.; 10][..], abs_all <= 0.);
683        assert_float_eq!(b.channel_data(1).as_slice(), &[0.; 10][..], abs_all <= 0.);
684        assert_eq!(b.channels().get(2), None);
685    }
686
687    #[test]
688    fn test_concat() {
689        let options = AudioBufferOptions {
690            number_of_channels: 2,
691            length: 5,
692            sample_rate: 44100.,
693        };
694        let mut b1 = AudioBuffer::new(options.clone());
695        let b2 = AudioBuffer::new(options);
696        b1.extend(&b2);
697
698        assert_eq!(b1.length(), 10);
699        assert_eq!(b1.number_of_channels(), 2);
700        assert_float_eq!(b1.sample_rate(), 44100., abs_all <= 0.);
701
702        let channel_data = ChannelData::from(vec![1.; 5]);
703        let b3 = AudioBuffer::from_channels(vec![channel_data; 2], 44100.);
704
705        b1.extend(&b3);
706
707        assert_eq!(b1.length(), 15);
708        assert_eq!(b1.number_of_channels(), 2);
709        assert_float_eq!(b1.sample_rate(), 44100., abs_all <= 0.);
710        assert_float_eq!(
711            b1.channel_data(0).as_slice(),
712            &[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1., 1., 1.][..],
713            abs_all <= 0.
714        );
715    }
716
717    #[test]
718    #[should_panic]
719    fn test_resample_to_zero_hertz() {
720        let channel = ChannelData::from(vec![1., 2., 3., 4., 5.]);
721        let mut buffer = AudioBuffer::from_channels(vec![channel], 48000.);
722        buffer.resample(0.);
723    }
724
725    #[test]
726    fn test_resample_from_empty() {
727        let channel = ChannelData::from(vec![]);
728        let mut buffer = AudioBuffer::from_channels(vec![channel], 48000.);
729        buffer.resample(48000.);
730
731        assert_eq!(buffer.length(), 0);
732        assert_float_eq!(buffer.sample_rate, 48000., abs_all <= 0.);
733    }
734
735    #[test]
736    fn test_upsample() {
737        let channel = ChannelData::from(vec![1., 2., 3., 4., 5.]);
738        let mut buffer = AudioBuffer::from_channels(vec![channel], 48000.);
739        buffer.resample(96000.); // double
740
741        let mut expected = [0.; 10];
742        let incr = 4. / 9.; // (5 - 1) / (10 - 1)
743
744        for (i, value) in expected.iter_mut().enumerate() {
745            *value = 1. + incr * i as f32;
746        }
747
748        assert_float_eq!(
749            buffer.channel_data(0).as_slice(),
750            &expected[..],
751            abs_all <= 1e-6
752        );
753
754        assert_float_eq!(buffer.sample_rate, 96000., abs_all <= 0.);
755    }
756
757    #[test]
758    fn test_downsample() {
759        let channel = ChannelData::from(vec![1., 2., 3., 4., 5.]);
760        let mut buffer = AudioBuffer::from_channels(vec![channel], 96000.);
761        buffer.resample(48000.); // half
762
763        assert_float_eq!(
764            buffer.channel_data(0).as_slice(),
765            &[1., 3., 5.][..],
766            abs_all <= 0.
767        );
768
769        assert_float_eq!(buffer.sample_rate, 48000., abs_all <= 0.);
770    }
771
772    #[test]
773    fn test_resample_stereo() {
774        [22500, 38000, 48000, 96000].iter().for_each(|sr| {
775            let source_sr = *sr;
776            let target_sr = 44_100;
777
778            let mut left = Vec::<f32>::with_capacity(source_sr);
779            let mut right = Vec::<f32>::with_capacity(source_sr);
780
781            for i in 0..source_sr {
782                let phase = i as f32 / source_sr as f32 * 2. * PI;
783                left.push(phase.sin());
784                right.push(phase.cos());
785            }
786
787            let left_chan = ChannelData::from(left);
788            let right_chan = ChannelData::from(right);
789            let mut buffer =
790                AudioBuffer::from_channels(vec![left_chan, right_chan], source_sr as f32);
791            buffer.resample(target_sr as f32);
792
793            let mut expected_left = vec![];
794            let mut expected_right = vec![];
795
796            for i in 0..target_sr {
797                let phase = i as f32 / target_sr as f32 * 2. * PI;
798                expected_left.push(phase.sin());
799                expected_right.push(phase.cos());
800            }
801
802            assert_float_eq!(
803                buffer.get_channel_data(0)[..],
804                &expected_left[..],
805                abs_all <= 1e-3
806            );
807
808            assert_float_eq!(
809                buffer.get_channel_data(1)[..],
810                &expected_right[..],
811                abs_all <= 1e-3
812            );
813
814            assert_float_eq!(buffer.sample_rate, target_sr as f32, abs_all <= 0.);
815        });
816    }
817}