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)]
12pub enum ResampleQuality {
13 VeryLow,
18 Low,
24 #[default]
25 High,
39 HighWithLowLatency,
47}
48
49#[derive(Debug, Clone, Copy, PartialEq, Eq)]
52pub struct ResamplerConfig {
53 pub quality: ResampleQuality,
57
58 pub chunk_size: usize,
63
64 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
86pub 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#[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
191pub 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 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 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 pub fn nbr_channels(&self) -> usize {
273 self.num_channels
274 }
275
276 pub fn ratio(&self) -> f64 {
278 self.resampler.resample_ratio()
279 }
280
281 pub fn max_input_block_frames(&self) -> usize {
284 self.resampler.input_frames_max()
285 }
286
287 pub fn max_output_block_frames(&self) -> usize {
291 self.resampler.output_frames_max()
292 }
293
294 pub fn output_delay(&self) -> usize {
297 self.resampler.output_delay()
298 }
299
300 pub fn out_alloc_frames(&self, input_frames: u64) -> u64 {
303 match self.ratio {
304 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 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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
537pub struct LastPacketInfo {
538 pub desired_output_frames: Option<u64>,
544}
545
546pub 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 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 fn input_fill_frames_with(&mut self, start: usize, count: usize, value: &T) -> Option<usize>;
589
590 fn input_fill_with(&mut self, value: &T);
594
595 fn output_copy_frames_within(&mut self, src: usize, dest: usize, count: usize);
603}
604
605pub 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
665pub 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
741pub 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 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 if frames_copied < frames {
781 unsafe {
785 out_buffer.set_len(out_buffer_len + frames_copied);
786 }
787 }
788
789 frames_copied
790}