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
76impl Default for ResamplerConfig {
77 fn default() -> Self {
78 Self {
79 quality: ResampleQuality::default(),
80 chunk_size: 512,
81 }
82 }
83}
84
85pub 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#[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
177pub 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 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 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 pub fn nbr_channels(&self) -> usize {
260 self.num_channels
261 }
262
263 pub fn ratio(&self) -> f64 {
265 self.resampler.resample_ratio()
266 }
267
268 pub fn max_input_block_frames(&self) -> usize {
271 self.resampler.input_frames_max()
272 }
273
274 pub fn max_output_block_frames(&self) -> usize {
278 self.resampler.output_frames_max()
279 }
280
281 pub fn output_delay(&self) -> usize {
284 self.resampler.output_delay()
285 }
286
287 pub fn out_alloc_frames(&self, input_frames: u64) -> u64 {
290 match self.ratio {
291 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 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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
529pub struct LastPacketInfo {
530 pub desired_output_frames: Option<u64>,
536}
537
538pub 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 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 fn input_fill_frames_with(&mut self, start: usize, count: usize, value: &T) -> Option<usize>;
581
582 fn input_fill_with(&mut self, value: &T);
586
587 fn output_copy_frames_within(&mut self, src: usize, dest: usize, count: usize);
595}
596
597pub 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
657pub 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
736pub 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 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 if frames_copied < frames {
776 unsafe {
780 out_buffer.set_len(out_buffer_len + frames_copied);
781 }
782 }
783
784 frames_copied
785}