Skip to main content

fixed_resample/
resampler.rs

1use audioadapter_buffers::direct;
2use audioadapter_buffers::owned::{InterleavedOwned, SequentialOwned};
3use rubato::{
4    audioadapter::{Adapter, AdapterMut},
5    ResampleResult, Resampler, Sample,
6};
7use std::ops::Range;
8
9/// The quality of the resampling algorithm used for a [`PacketResampler`] or a
10/// [`Resampler`] created with [`resampler_from_quality`].
11#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
12pub enum ResampleQuality {
13    /// Low quality, low CPU, low latency
14    ///
15    /// Internally this uses the [`Async`][rubato::Async] resampler from rubato
16    /// with linear polynomial interpolation.
17    VeryLow,
18    /// Slightly better quality than [`ResampleQuality::VeryLow`], slightly higher
19    /// CPU than [`ResampleQuality::VeryLow`], low latency
20    ///
21    /// Internally this uses the [`Async`][rubato::Async] resampler from rubato
22    /// with cubic polynomial interpolation.
23    Low,
24    #[default]
25    /// Great quality, medium CPU, high latency
26    ///
27    /// This is recommended for most non-realtime applications where higher
28    /// latency is not an issue.
29    ///
30    /// Note, this resampler type adds a significant amount of latency (in
31    /// the hundreds of frames), so prefer to use the "Low" option if low
32    /// latency is desired.
33    ///
34    /// If the `fft-resampler` feature is not enabled, then this will fall
35    /// back to [`ResampleQuality::Low`].
36    ///
37    /// Internally this uses the [`rubato::Fft`] resampler from rubato.
38    High,
39    /// Great quality, high CPU, low latency
40    ///
41    /// Internally this uses the [`Async`][rubato::Async] resampler from rubato
42    /// with [`Cubic`](rubato::SincInterpolationType::Cubic) sinc
43    /// interpolation, a [`BlackmanHarris2`](rubato::WindowFunction::BlackmanHarris2)
44    /// window function, a sinc length of `256`, and an oversampling factor
45    /// of `128`.
46    HighWithLowLatency,
47}
48
49impl From<usize> for ResampleQuality {
50    fn from(value: usize) -> Self {
51        match value {
52            0 => Self::VeryLow,
53            1 => Self::Low,
54            2 => Self::High,
55            _ => Self::HighWithLowLatency,
56        }
57    }
58}
59
60/// The configuration for a [`PacketResampler`] or a [`Resampler`] create with
61/// [`resampler_from_quality`].
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub struct ResamplerConfig {
64    /// The quality of the resampling algorithm.
65    ///
66    /// By default this is set to [`ResampleQuality::High`].
67    pub quality: ResampleQuality,
68
69    /// The chunk size of the resampler. Lower values may reduce latency, but may
70    /// use more CPU.
71    ///
72    /// By default this is set to `512`.
73    pub chunk_size: usize,
74}
75
76impl Default for ResamplerConfig {
77    fn default() -> Self {
78        Self {
79            quality: ResampleQuality::default(),
80            chunk_size: 512,
81        }
82    }
83}
84
85/// Create a new [`Resampler`] with the given settings.
86///
87/// * `num_channels` - The number of audio channels.
88/// * `in_sample_rate` - The sample rate of the input data.
89/// * `out_sample_rate` - The sample rate of the output data.
90/// * `config` - Extra configuration for the resampler.
91///
92/// # Panics
93/// Panics if:
94/// * `num_channels == 0`
95/// * `in_sample_rate == 0`
96/// * `out_sample_rate == 0`
97/// * `config.chunk_size == 0`
98/// * `config.sub_chunks == 0`
99pub fn resampler_from_quality<T: Sample>(
100    num_channels: usize,
101    in_sample_rate: u32,
102    out_sample_rate: u32,
103    config: ResamplerConfig,
104) -> Box<dyn Resampler<T>> {
105    assert_ne!(num_channels, 0);
106    assert_ne!(in_sample_rate, 0);
107    assert_ne!(out_sample_rate, 0);
108    assert_ne!(config.chunk_size, 0);
109
110    let low = || -> Box<dyn rubato::Resampler<T>> {
111        Box::new(
112            rubato::Async::new_poly(
113                out_sample_rate as f64 / in_sample_rate as f64,
114                1.0,
115                rubato::PolynomialDegree::Cubic,
116                config.chunk_size,
117                num_channels,
118                rubato::FixedAsync::Input,
119            )
120            .unwrap(),
121        )
122    };
123
124    match config.quality {
125        ResampleQuality::VeryLow => Box::new(
126            rubato::Async::new_poly(
127                out_sample_rate as f64 / in_sample_rate as f64,
128                1.0,
129                rubato::PolynomialDegree::Linear,
130                config.chunk_size,
131                num_channels,
132                rubato::FixedAsync::Input,
133            )
134            .unwrap(),
135        ),
136        ResampleQuality::Low => low(),
137        ResampleQuality::High => {
138            #[cfg(feature = "fft-resampler")]
139            return Box::new(
140                rubato::Fft::new(
141                    in_sample_rate as usize,
142                    out_sample_rate as usize,
143                    config.chunk_size,
144                    num_channels,
145                    rubato::FixedSync::Input,
146                )
147                .unwrap(),
148            );
149
150            #[cfg(not(feature = "fft-resampler"))]
151            return low();
152        }
153        ResampleQuality::HighWithLowLatency => Box::new(
154            rubato::Async::new_sinc(
155                out_sample_rate as f64 / in_sample_rate as f64,
156                1.0,
157                &rubato::SincInterpolationParameters::default(),
158                config.chunk_size,
159                num_channels,
160                rubato::FixedAsync::Input,
161            )
162            .unwrap(),
163        ),
164    }
165}
166
167/// The resampling ratio for [`PacketResampler::from_custom`].
168#[derive(Debug, Clone, Copy, PartialEq)]
169enum ResampleRatio {
170    IntegerSampleRate {
171        in_sample_rate: u32,
172        out_sample_rate: u32,
173    },
174    Float(f64),
175}
176
177/// A wrapper around rubato's [`Resampler`] that accepts inputs of any size and sends
178/// resampled output packets to a given closure.
179///
180/// When using the [`Sequential`] [`PacketResamplerBuffer`], the output packets will
181/// be in de-interleaved format (using &[`SequentialOwned`]). When using the
182/// [`Interleaved`] [`PacketResamplerBuffer`], the output packets be be in interleaved
183/// format (using `&[T]`).
184///
185/// This only supports synchronous resampling.
186pub struct PacketResampler<T: Sample, B: PacketResamplerBuffer<T>> {
187    resampler: Box<dyn Resampler<T>>,
188    ratio: ResampleRatio,
189    num_channels: usize,
190
191    buffer: B,
192    active_channels_mask: Option<Vec<bool>>,
193    in_buf_len: usize,
194    delay_frames_left: usize,
195}
196
197impl<T: Sample, B: PacketResamplerBuffer<T>> PacketResampler<T, B> {
198    /// Create a new [`PacketResampler`].
199    ///
200    /// * `num_channels` - The number of audio channels.
201    /// * `in_sample_rate` - The sample rate of the input data.
202    /// * `out_sample_rate` - The sample rate of the output data.
203    /// * `config` - Extra configuration for the resampler.
204    ///
205    /// # Panics
206    /// Panics if:
207    /// * `num_channels == 0`
208    /// * `in_sample_rate == 0`
209    /// * `out_sample_rate == 0`
210    /// * `config.chunk_size == 0`
211    /// * `config.sub_chunks == 0`
212    pub fn new(
213        num_channels: usize,
214        in_sample_rate: u32,
215        out_sample_rate: u32,
216        config: ResamplerConfig,
217    ) -> Self {
218        let resampler =
219            resampler_from_quality(num_channels, in_sample_rate, out_sample_rate, config);
220
221        Self::new_inner(resampler, Some((in_sample_rate, out_sample_rate)))
222    }
223
224    /// Create a new [`PacketResampler`] using a custom [`Resampler`].
225    ///
226    /// This can be used, for example, to create a PacketResampler with non-integer input
227    /// and/or output sample rates.
228    pub fn from_custom(resampler: Box<dyn Resampler<T>>) -> Self {
229        Self::new_inner(resampler, None)
230    }
231
232    fn new_inner(resampler: Box<dyn Resampler<T>>, sr: Option<(u32, u32)>) -> Self {
233        let ratio = if let Some((in_sample_rate, out_sample_rate)) = sr {
234            ResampleRatio::IntegerSampleRate {
235                in_sample_rate,
236                out_sample_rate,
237            }
238        } else {
239            ResampleRatio::Float(resampler.resample_ratio())
240        };
241
242        let num_channels = resampler.nbr_channels();
243        let input_frames_max = resampler.input_frames_max();
244        let output_frames_max = resampler.output_frames_max();
245        let delay_frames_left = resampler.output_delay();
246
247        Self {
248            resampler,
249            ratio,
250            num_channels,
251            buffer: B::new(num_channels, input_frames_max, output_frames_max),
252            active_channels_mask: Some(vec![false; num_channels]),
253            in_buf_len: 0,
254            delay_frames_left,
255        }
256    }
257
258    /// The number of channels configured for this resampler.
259    pub fn nbr_channels(&self) -> usize {
260        self.num_channels
261    }
262
263    /// The resampling ratio `output / input`.
264    pub fn ratio(&self) -> f64 {
265        self.resampler.resample_ratio()
266    }
267
268    /// The number of frames (samples in a single channel of audio) that appear in
269    /// a single packet of input data in the internal resampler.
270    pub fn max_input_block_frames(&self) -> usize {
271        self.resampler.input_frames_max()
272    }
273
274    /// The maximum number of frames (samples in a single channel of audio) that can
275    /// appear in a single call to the `on_output_packet` closure in
276    /// [`PacketResampler::process`].
277    pub fn max_output_block_frames(&self) -> usize {
278        self.resampler.output_frames_max()
279    }
280
281    /// The delay introduced by the internal resampler in number of output frames (
282    /// samples in a single channel of audio).
283    pub fn output_delay(&self) -> usize {
284        self.resampler.output_delay()
285    }
286
287    /// The number of frames (samples in a single channel of audio) that are needed
288    /// for an output buffer given the number of input frames.
289    pub fn out_alloc_frames(&self, input_frames: u64) -> u64 {
290        match self.ratio {
291            // Use integer math when possible for more accurate results.
292            ResampleRatio::IntegerSampleRate {
293                in_sample_rate,
294                out_sample_rate,
295            } => {
296                let out_frames = (input_frames * out_sample_rate as u64) / in_sample_rate as u64;
297                let leftover_frames =
298                    (input_frames * out_sample_rate as u64) % in_sample_rate as u64;
299
300                let extra_frame = (leftover_frames as f64 / in_sample_rate as f64).round() as u64;
301
302                out_frames + extra_frame
303            }
304            ResampleRatio::Float(ratio) => (input_frames as f64 * ratio).round() as u64,
305        }
306    }
307
308    #[allow(unused)]
309    pub(crate) fn tmp_input_frames(&self) -> usize {
310        self.in_buf_len
311    }
312
313    /// Process the given input data and return packets of resampled output data.
314    ///
315    /// * `buffer_in` - The input data. You can use one of the types in the [`direct`]
316    ///   module to wrap your input data into a type that implements [`Adapter`].
317    /// * `input_range` - The range in each input channel to read from. If this is
318    ///   `None`, then the entire input buffer will be read.
319    /// * `active_channels_mask` - An optional mask that selects which channels in
320    ///   `buffer_in` to use. Channels marked with `false` will be skipped and the
321    ///   output channel filled with zeros. If `None`, then all of the channels will
322    ///   be active.
323    /// * `on_output_packet` - Gets called whenever there is a new packet of resampled
324    ///   output data. `(buffer, output_frames)`
325    ///     * When using [`Sequential`] output buffers, the output will be of type
326    ///       &[`SequentialOwned`]. Note, the length of this buffer may be less than
327    ///       `output_frames`. Only read up to `output_frames` data from the buffer.
328    ///     * When using [`Interleaved`] output buffers, the output will be of type
329    ///       `&[T]`. The number of frames in this slice will always be equal to
330    ///       `output_frames`.
331    /// * `last_packet` - If this is `Some`, then any leftover input samples in the
332    ///   buffer will be flushed out and the resampler reset. Use this if this is the
333    ///   last/only packet of input data.
334    /// * `trim_delay` - If `true`, then the initial padded zeros introduced by the
335    ///   internal resampler will be trimmed off.
336    ///
337    /// This method is realtime-safe.
338    ///
339    /// # Panics
340    /// Panics if:
341    /// * The `input_range` is out of bounds for any of the input channels.
342    pub fn process(
343        &mut self,
344        buffer_in: &dyn Adapter<T>,
345        input_range: Option<Range<usize>>,
346        active_channels_mask: Option<&[bool]>,
347        mut on_output_packet: impl FnMut(&B::Output, usize),
348        last_packet: Option<LastPacketInfo>,
349        trim_delay: bool,
350    ) {
351        let (input_start, total_input_frames) = if let Some(range) = input_range {
352            (range.start, range.end - range.start)
353        } else {
354            (0, buffer_in.frames())
355        };
356
357        let use_indexing =
358            active_channels_mask.is_some() || buffer_in.channels() < self.num_channels;
359
360        let mut indexing = if use_indexing {
361            let mut m = self.active_channels_mask.take().unwrap();
362
363            if let Some(in_mask) = active_channels_mask {
364                for (in_mask, out_mask) in in_mask.iter().zip(m.iter_mut()) {
365                    *out_mask = *in_mask;
366                }
367            } else {
368                for mask in m.iter_mut().take(buffer_in.channels()) {
369                    *mask = true;
370                }
371            }
372            for mask in m.iter_mut().skip(buffer_in.channels()) {
373                *mask = false;
374            }
375
376            rubato::Indexing {
377                input_offset: 0,
378                output_offset: 0,
379                partial_len: None,
380                active_channels_mask: Some(m),
381            }
382        } else {
383            rubato::Indexing {
384                input_offset: 0,
385                output_offset: 0,
386                partial_len: None,
387                active_channels_mask: None,
388            }
389        };
390
391        let mut output_frames_processed: u64 = 0;
392
393        let mut input_frames_left = total_input_frames;
394        while input_frames_left > 0 {
395            let needed_input_frames = self.resampler.input_frames_next();
396
397            if self.in_buf_len < needed_input_frames {
398                let block_frames_to_copy =
399                    input_frames_left.min(needed_input_frames - self.in_buf_len);
400
401                for ch_i in 0..self.num_channels {
402                    let channel_active = ch_i < buffer_in.channels()
403                        && active_channels_mask
404                            .as_ref()
405                            .map(|m| m.get(ch_i).copied().unwrap_or(false))
406                            .unwrap_or(true);
407
408                    if channel_active {
409                        self.buffer.copy_from_other_to_input_channel(
410                            buffer_in,
411                            ch_i,
412                            ch_i,
413                            input_start + (total_input_frames - input_frames_left),
414                            self.in_buf_len,
415                            block_frames_to_copy,
416                        );
417                    }
418                }
419
420                self.in_buf_len += block_frames_to_copy;
421                input_frames_left -= block_frames_to_copy;
422            }
423
424            if self.in_buf_len >= needed_input_frames {
425                self.in_buf_len = 0;
426
427                let (_, mut output_frames) = self
428                    .buffer
429                    .resample(Some(&indexing), &mut self.resampler)
430                    .unwrap();
431
432                if self.delay_frames_left > 0 {
433                    if self.delay_frames_left >= output_frames {
434                        self.delay_frames_left -= output_frames;
435
436                        if trim_delay {
437                            continue;
438                        }
439                    } else if trim_delay {
440                        output_frames -= self.delay_frames_left;
441
442                        self.buffer.output_copy_frames_within(
443                            self.delay_frames_left,
444                            0,
445                            output_frames,
446                        );
447
448                        self.delay_frames_left = 0;
449                    } else {
450                        self.delay_frames_left = 0;
451                    }
452                }
453
454                output_frames_processed += output_frames as u64;
455
456                (on_output_packet)(self.buffer.output(output_frames), output_frames);
457            }
458        }
459
460        if let Some(info) = &last_packet {
461            let desired_output_frames = info
462                .desired_output_frames
463                .unwrap_or_else(|| output_frames_processed + self.resampler.output_delay() as u64);
464
465            while output_frames_processed < desired_output_frames {
466                indexing.partial_len = Some(self.in_buf_len);
467
468                let (_, mut output_frames) = self
469                    .buffer
470                    .resample(Some(&indexing), &mut self.resampler)
471                    .unwrap();
472
473                self.in_buf_len = 0;
474
475                if self.delay_frames_left > 0 {
476                    if self.delay_frames_left >= output_frames {
477                        self.delay_frames_left -= output_frames;
478
479                        if trim_delay {
480                            continue;
481                        }
482                    } else if trim_delay {
483                        output_frames -= self.delay_frames_left;
484
485                        self.buffer.output_copy_frames_within(
486                            self.delay_frames_left,
487                            0,
488                            output_frames,
489                        );
490
491                        self.delay_frames_left = 0;
492                    } else {
493                        self.delay_frames_left = 0;
494                    }
495                }
496
497                output_frames =
498                    output_frames.min((desired_output_frames - output_frames_processed) as usize);
499                output_frames_processed += output_frames as u64;
500
501                (on_output_packet)(self.buffer.output(output_frames), output_frames);
502            }
503
504            self.reset();
505        }
506
507        if let Some(m) = indexing.active_channels_mask.take() {
508            self.active_channels_mask = Some(m);
509        }
510    }
511
512    pub fn output_delay_frames_left(&self) -> usize {
513        self.delay_frames_left
514    }
515
516    pub fn reset(&mut self) {
517        self.resampler.reset();
518        self.in_buf_len = 0;
519        self.delay_frames_left = self.resampler.output_delay();
520    }
521
522    pub fn into_inner(self) -> Box<dyn Resampler<T>> {
523        self.resampler
524    }
525}
526
527/// Options for processes the last packet in a resampler.
528#[derive(Debug, Clone, Copy, PartialEq, Eq)]
529pub struct LastPacketInfo {
530    /// The desired number of output frames that should be sent via the
531    /// `on_output_packet` closure.
532    ///
533    /// If this is `None`, then the last packet sent may contain extra
534    /// padded zeros on the end.
535    pub desired_output_frames: Option<u64>,
536}
537
538/// The type of output buffer to use for a [`PacketResampler`].
539///
540/// The provided options are [`Sequential`] and [`Interleaved`].
541pub trait PacketResamplerBuffer<T: Sample> {
542    type Output: ?Sized;
543
544    fn new(channels: usize, input_frames: usize, output_frames: usize) -> Self;
545
546    fn output(&self, frames: usize) -> &Self::Output;
547
548    fn resample(
549        &mut self,
550        indexing: Option<&rubato::Indexing>,
551        resampler: &mut Box<dyn Resampler<T>>,
552    ) -> ResampleResult<(usize, usize)>;
553
554    /// Copy values from a channel of another Adapter.
555    /// The `self_skip` and `other_skip` arguments are the offsets
556    /// in frames for where copying starts in the two channels.
557    /// The method copies `take` values.
558    ///
559    /// Returns the the number of values that were clipped during conversion.
560    /// Implementations that do not perform any conversion
561    /// always return zero clipped samples.
562    ///
563    /// If an invalid channel number is given,
564    /// or if either of the channels is to short to copy `take` values,
565    /// no values will be copied and `None` is returned.
566    fn copy_from_other_to_input_channel(
567        &mut self,
568        other: &dyn Adapter<T>,
569        other_channel: usize,
570        self_channel: usize,
571        other_skip: usize,
572        self_skip: usize,
573        take: usize,
574    ) -> Option<usize>;
575
576    /// Write the provided value to every sample in a range of frames.
577    /// Can be used to clear a range of frames by writing zeroes,
578    /// or to initialize each sample to a certain value.
579    /// Returns `None` if called with a too large range.
580    fn input_fill_frames_with(&mut self, start: usize, count: usize, value: &T) -> Option<usize>;
581
582    /// Write the provided value to every sample in the entire buffer.
583    /// Can be used to clear a buffer by writing zeroes,
584    /// or to initialize each sample to a certain value.
585    fn input_fill_with(&mut self, value: &T);
586
587    /// Copy frames within the buffer.
588    /// Copying is performed for all channels.
589    /// Copies `count` frames, from the range `src..src+count`,
590    /// to the range `dest..dest+count`.
591    /// The two regions are allowed to overlap.
592    /// The default implementation copies by calling the read and write methods,
593    /// while type specific implementations can use more efficient methods.
594    fn output_copy_frames_within(&mut self, src: usize, dest: usize, count: usize);
595}
596
597/// Use de-interleaved output packets for a [`PacketResampler`].
598pub struct Sequential<T: Sample> {
599    in_buffer: SequentialOwned<T>,
600    out_buffer: SequentialOwned<T>,
601}
602
603impl<T: Sample> PacketResamplerBuffer<T> for Sequential<T> {
604    type Output = SequentialOwned<T>;
605
606    fn new(channels: usize, input_frames: usize, output_frames: usize) -> Self {
607        Self {
608            in_buffer: SequentialOwned::new(T::zero(), channels, input_frames),
609            out_buffer: SequentialOwned::new(T::zero(), channels, output_frames),
610        }
611    }
612
613    fn output(&self, _frames: usize) -> &Self::Output {
614        &self.out_buffer
615    }
616
617    fn resample(
618        &mut self,
619        indexing: Option<&rubato::Indexing>,
620        resampler: &mut Box<dyn Resampler<T>>,
621    ) -> ResampleResult<(usize, usize)> {
622        resampler.process_into_buffer(&self.in_buffer, &mut self.out_buffer, indexing)
623    }
624
625    fn copy_from_other_to_input_channel(
626        &mut self,
627        other: &dyn Adapter<T>,
628        other_channel: usize,
629        self_channel: usize,
630        other_skip: usize,
631        self_skip: usize,
632        take: usize,
633    ) -> Option<usize> {
634        self.in_buffer.copy_from_other_to_channel(
635            other,
636            other_channel,
637            self_channel,
638            other_skip,
639            self_skip,
640            take,
641        )
642    }
643
644    fn input_fill_frames_with(&mut self, start: usize, count: usize, value: &T) -> Option<usize> {
645        self.in_buffer.fill_frames_with(start, count, value)
646    }
647
648    fn input_fill_with(&mut self, value: &T) {
649        self.in_buffer.fill_with(value);
650    }
651
652    fn output_copy_frames_within(&mut self, src: usize, dest: usize, count: usize) {
653        self.out_buffer.copy_frames_within(src, dest, count);
654    }
655}
656
657/// Use interleaved output packets for a [`PacketResampler`].
658pub struct Interleaved<T: Sample> {
659    in_buffer: InterleavedOwned<T>,
660    out_buffer: Vec<T>,
661    channels: usize,
662    output_frames: usize,
663}
664
665impl<T: Sample> PacketResamplerBuffer<T> for Interleaved<T> {
666    type Output = [T];
667
668    fn new(channels: usize, input_frames: usize, output_frames: usize) -> Self {
669        let out_buffer_size = output_frames * channels;
670        let mut out_buffer = Vec::new();
671        out_buffer.reserve_exact(out_buffer_size);
672        out_buffer.resize(out_buffer_size, T::zero());
673
674        Self {
675            in_buffer: InterleavedOwned::new(T::zero(), channels, input_frames),
676            out_buffer,
677            channels,
678            output_frames,
679        }
680    }
681
682    fn output(&self, frames: usize) -> &Self::Output {
683        &self.out_buffer[0..frames * self.channels]
684    }
685
686    fn resample(
687        &mut self,
688        indexing: Option<&rubato::Indexing>,
689        resampler: &mut Box<dyn Resampler<T>>,
690    ) -> ResampleResult<(usize, usize)> {
691        let mut out_buffer_wrapper = direct::InterleavedSlice::new_mut(
692            &mut self.out_buffer,
693            self.channels,
694            self.output_frames,
695        )
696        .unwrap();
697
698        resampler.process_into_buffer(&self.in_buffer, &mut out_buffer_wrapper, indexing)
699    }
700
701    fn copy_from_other_to_input_channel(
702        &mut self,
703        other: &dyn Adapter<T>,
704        other_channel: usize,
705        self_channel: usize,
706        other_skip: usize,
707        self_skip: usize,
708        take: usize,
709    ) -> Option<usize> {
710        self.in_buffer.copy_from_other_to_channel(
711            other,
712            other_channel,
713            self_channel,
714            other_skip,
715            self_skip,
716            take,
717        )
718    }
719
720    fn input_fill_frames_with(&mut self, start: usize, count: usize, value: &T) -> Option<usize> {
721        self.in_buffer.fill_frames_with(start, count, value)
722    }
723
724    fn input_fill_with(&mut self, value: &T) {
725        self.in_buffer.fill_with(value);
726    }
727
728    fn output_copy_frames_within(&mut self, src: usize, dest: usize, count: usize) {
729        self.out_buffer.copy_within(
730            src * self.channels..count * self.channels,
731            dest * self.channels,
732        );
733    }
734}
735
736/// Extend the given Vec with the contents of a channel from the given [`Adapter`].
737///
738/// If the adapter does not contain enough frames, then only the available number of
739/// frames will be appended to the Vec.
740///
741/// Returns the number of frames that were appended to the Vec.
742///
743/// # Panics
744/// * Panics if `buffer_in_channel >= buffer_in.channels()`
745pub fn extend_from_adapter_channel<T: Sample>(
746    out_buffer: &mut Vec<T>,
747    buffer_in: &dyn Adapter<T>,
748    buffer_in_skip: usize,
749    buffer_in_channel: usize,
750    frames: usize,
751) -> usize {
752    assert!(buffer_in_channel < buffer_in.channels());
753
754    let out_buffer_len = out_buffer.len();
755    let available = out_buffer.capacity() - out_buffer_len;
756    if available < frames {
757        out_buffer.reserve(frames);
758    }
759
760    // Safety:
761    // * We ensured that the output buffer has enough capacity above.
762    // * All the new frames in the output buffer will be filled with data below, and
763    // we correctly truncate any frames which did not get filled with data.
764    unsafe {
765        out_buffer.set_len(out_buffer_len + frames);
766    }
767
768    let frames_copied = buffer_in.copy_from_channel_to_slice(
769        buffer_in_channel,
770        buffer_in_skip,
771        &mut out_buffer[out_buffer_len..out_buffer_len + frames],
772    );
773
774    // Truncate any unused data.
775    if frames_copied < frames {
776        // Safety:
777        // * The new length is less than the old length.
778        // * T requires `Copy`, so there is no need to call the destructor on each sample.
779        unsafe {
780            out_buffer.set_len(out_buffer_len + frames_copied);
781        }
782    }
783
784    frames_copied
785}