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