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