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#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
12pub enum ResampleQuality {
13 VeryLow,
18 Low,
24 #[default]
25 High,
39 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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub struct ResamplerConfig {
64 pub quality: ResampleQuality,
68
69 pub chunk_size: usize,
74
75 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
97pub 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#[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
202pub 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 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 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 pub fn nbr_channels(&self) -> usize {
284 self.num_channels
285 }
286
287 pub fn ratio(&self) -> f64 {
289 self.resampler.resample_ratio()
290 }
291
292 pub fn max_input_block_frames(&self) -> usize {
295 self.resampler.input_frames_max()
296 }
297
298 pub fn max_output_block_frames(&self) -> usize {
302 self.resampler.output_frames_max()
303 }
304
305 pub fn output_delay(&self) -> usize {
308 self.resampler.output_delay()
309 }
310
311 pub fn out_alloc_frames(&self, input_frames: u64) -> u64 {
314 match self.ratio {
315 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 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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
548pub struct LastPacketInfo {
549 pub desired_output_frames: Option<u64>,
555}
556
557pub 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 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 fn input_fill_frames_with(&mut self, start: usize, count: usize, value: &T) -> Option<usize>;
600
601 fn input_fill_with(&mut self, value: &T);
605
606 fn output_copy_frames_within(&mut self, src: usize, dest: usize, count: usize);
614}
615
616pub 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
676pub 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
752pub 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 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 if frames_copied < frames {
792 unsafe {
796 out_buffer.set_len(out_buffer_len + frames_copied);
797 }
798 }
799
800 frames_copied
801}