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
246 Self {
247 resampler,
248 ratio,
249 num_channels,
250 buffer: B::new(num_channels, input_frames_max, output_frames_max),
251 active_channels_mask: Some(vec![false; num_channels]),
252 in_buf_len: 0,
253 delay_frames_left: 0,
254 }
255 }
256
257 pub fn nbr_channels(&self) -> usize {
259 self.num_channels
260 }
261
262 pub fn ratio(&self) -> f64 {
264 self.resampler.resample_ratio()
265 }
266
267 pub fn max_input_block_frames(&self) -> usize {
270 self.resampler.input_frames_max()
271 }
272
273 pub fn max_output_block_frames(&self) -> usize {
277 self.resampler.output_frames_max()
278 }
279
280 pub fn output_delay(&self) -> usize {
283 self.resampler.output_delay()
284 }
285
286 pub fn out_alloc_frames(&self, input_frames: u64) -> u64 {
289 match self.ratio {
290 ResampleRatio::IntegerSampleRate {
292 in_sample_rate,
293 out_sample_rate,
294 } => ((input_frames * out_sample_rate as u64) / in_sample_rate as u64) + 1,
295 ResampleRatio::Float(ratio) => (input_frames as f64 * ratio).ceil() as u64,
296 }
297 }
298
299 #[allow(unused)]
300 pub(crate) fn tmp_input_frames(&self) -> usize {
301 self.in_buf_len
302 }
303
304 pub fn process(
334 &mut self,
335 buffer_in: &dyn Adapter<T>,
336 input_range: Option<Range<usize>>,
337 active_channels_mask: Option<&[bool]>,
338 mut on_output_packet: impl FnMut(&B::Output, usize),
339 last_packet: Option<LastPacketInfo>,
340 trim_delay: bool,
341 ) {
342 let (input_start, total_frames) = if let Some(range) = input_range {
343 (range.start, range.end - range.start)
344 } else {
345 (0, buffer_in.frames())
346 };
347
348 let use_indexing =
349 active_channels_mask.is_some() || buffer_in.channels() < self.num_channels;
350
351 let indexing = if use_indexing {
352 let mut m = self.active_channels_mask.take().unwrap();
353
354 if let Some(in_mask) = active_channels_mask {
355 for (in_mask, out_mask) in in_mask.iter().zip(m.iter_mut()) {
356 *out_mask = *in_mask;
357 }
358 } else {
359 for mask in m.iter_mut().take(buffer_in.channels()) {
360 *mask = true;
361 }
362 }
363 for mask in m.iter_mut().skip(buffer_in.channels()) {
364 *mask = false;
365 }
366
367 Some(rubato::Indexing {
368 input_offset: 0,
369 output_offset: 0,
370 partial_len: None,
371 active_channels_mask: Some(m),
372 })
373 } else {
374 None
375 };
376
377 let mut output_frames_processed: u64 = 0;
378
379 let mut frames_left = total_frames;
380 while frames_left > 0 {
381 let needed_input_frames = self.resampler.input_frames_next();
382
383 if self.in_buf_len < needed_input_frames {
384 let block_frames_to_copy = frames_left.min(needed_input_frames - self.in_buf_len);
385
386 for ch_i in 0..self.num_channels {
387 let channel_active = ch_i < buffer_in.channels()
388 && active_channels_mask
389 .as_ref()
390 .map(|m| m.get(ch_i).copied().unwrap_or(false))
391 .unwrap_or(true);
392
393 if channel_active {
394 self.buffer.copy_from_other_to_input_channel(
395 buffer_in,
396 ch_i,
397 ch_i,
398 input_start + (total_frames - frames_left),
399 self.in_buf_len,
400 block_frames_to_copy,
401 );
402 }
403 }
404
405 self.in_buf_len += block_frames_to_copy;
406 frames_left -= block_frames_to_copy;
407 }
408
409 if self.in_buf_len >= needed_input_frames {
410 self.in_buf_len = 0;
411
412 let (_, mut output_frames) = self
413 .buffer
414 .resample(indexing.as_ref(), &mut self.resampler)
415 .unwrap();
416
417 if self.delay_frames_left > 0 {
418 if self.delay_frames_left >= output_frames {
419 self.delay_frames_left -= output_frames;
420
421 if trim_delay {
422 continue;
423 }
424 } else if trim_delay {
425 self.buffer.output_copy_frames_within(
426 self.delay_frames_left,
427 0,
428 output_frames,
429 );
430
431 output_frames -= self.delay_frames_left;
432 self.delay_frames_left = 0;
433 } else {
434 self.delay_frames_left = 0;
435 }
436 }
437
438 output_frames_processed += output_frames as u64;
439
440 (on_output_packet)(self.buffer.output(output_frames), output_frames);
441 }
442 }
443
444 if let Some(info) = &last_packet {
445 if self.in_buf_len > 0 {
446 self.buffer.input_fill_frames_with(
447 self.in_buf_len,
448 self.resampler.input_frames_max(),
449 &T::zero(),
450 );
451 } else {
452 self.buffer.input_fill_with(&T::zero());
453 };
454
455 let desired_output_frames = info.desired_output_frames.unwrap_or_else(|| {
456 output_frames_processed + self.resampler.output_delay() as u64 + 1
457 });
458
459 while output_frames_processed < desired_output_frames {
460 let (_, mut output_frames) = self
461 .buffer
462 .resample(indexing.as_ref(), &mut self.resampler)
463 .unwrap();
464
465 if self.in_buf_len > 0 {
466 self.buffer.input_fill_with(&T::zero());
467 self.in_buf_len = 0;
468 }
469
470 if self.delay_frames_left > 0 {
471 if self.delay_frames_left >= output_frames {
472 self.delay_frames_left -= output_frames;
473
474 if trim_delay {
475 continue;
476 }
477 } else if trim_delay {
478 self.buffer.output_copy_frames_within(
479 self.delay_frames_left,
480 0,
481 output_frames,
482 );
483
484 output_frames -= self.delay_frames_left;
485 self.delay_frames_left = 0;
486 } else {
487 self.delay_frames_left = 0;
488 }
489 }
490
491 output_frames =
492 output_frames.min((desired_output_frames - output_frames_processed) as usize);
493 output_frames_processed += output_frames as u64;
494
495 (on_output_packet)(self.buffer.output(output_frames), output_frames);
496 }
497
498 self.reset();
499 }
500
501 if let Some(i) = indexing {
502 self.active_channels_mask = i.active_channels_mask;
503 }
504 }
505
506 pub fn output_delay_frames_left(&self) -> usize {
507 self.delay_frames_left
508 }
509
510 pub fn reset(&mut self) {
511 self.resampler.reset();
512 self.in_buf_len = 0;
513 self.delay_frames_left = self.resampler.output_delay();
514 }
515
516 pub fn into_inner(self) -> Box<dyn Resampler<T>> {
517 self.resampler
518 }
519}
520
521#[derive(Debug, Clone, Copy, PartialEq, Eq)]
523pub struct LastPacketInfo {
524 pub desired_output_frames: Option<u64>,
530}
531
532pub trait PacketResamplerBuffer<T: Sample> {
536 type Output: ?Sized;
537
538 fn new(channels: usize, input_frames: usize, output_frames: usize) -> Self;
539
540 fn output(&self, frames: usize) -> &Self::Output;
541
542 fn resample(
543 &mut self,
544 indexing: Option<&rubato::Indexing>,
545 resampler: &mut Box<dyn Resampler<T>>,
546 ) -> ResampleResult<(usize, usize)>;
547
548 fn copy_from_other_to_input_channel(
561 &mut self,
562 other: &dyn Adapter<T>,
563 other_channel: usize,
564 self_channel: usize,
565 other_skip: usize,
566 self_skip: usize,
567 take: usize,
568 ) -> Option<usize>;
569
570 fn input_fill_frames_with(&mut self, start: usize, count: usize, value: &T) -> Option<usize>;
575
576 fn input_fill_with(&mut self, value: &T);
580
581 fn output_copy_frames_within(&mut self, src: usize, dest: usize, count: usize);
589}
590
591pub struct Sequential<T: Sample> {
593 in_buffer: SequentialOwned<T>,
594 out_buffer: SequentialOwned<T>,
595}
596
597impl<T: Sample> PacketResamplerBuffer<T> for Sequential<T> {
598 type Output = SequentialOwned<T>;
599
600 fn new(channels: usize, input_frames: usize, output_frames: usize) -> Self {
601 Self {
602 in_buffer: SequentialOwned::new(T::zero(), channels, input_frames),
603 out_buffer: SequentialOwned::new(T::zero(), channels, output_frames),
604 }
605 }
606
607 fn output(&self, _frames: usize) -> &Self::Output {
608 &self.out_buffer
609 }
610
611 fn resample(
612 &mut self,
613 indexing: Option<&rubato::Indexing>,
614 resampler: &mut Box<dyn Resampler<T>>,
615 ) -> ResampleResult<(usize, usize)> {
616 resampler.process_into_buffer(&self.in_buffer, &mut self.out_buffer, indexing)
617 }
618
619 fn copy_from_other_to_input_channel(
620 &mut self,
621 other: &dyn Adapter<T>,
622 other_channel: usize,
623 self_channel: usize,
624 other_skip: usize,
625 self_skip: usize,
626 take: usize,
627 ) -> Option<usize> {
628 self.in_buffer.copy_from_other_to_channel(
629 other,
630 other_channel,
631 self_channel,
632 other_skip,
633 self_skip,
634 take,
635 )
636 }
637
638 fn input_fill_frames_with(&mut self, start: usize, count: usize, value: &T) -> Option<usize> {
639 self.in_buffer.fill_frames_with(start, count, value)
640 }
641
642 fn input_fill_with(&mut self, value: &T) {
643 self.in_buffer.fill_with(value);
644 }
645
646 fn output_copy_frames_within(&mut self, src: usize, dest: usize, count: usize) {
647 self.out_buffer.copy_frames_within(src, dest, count);
648 }
649}
650
651pub struct Interleaved<T: Sample> {
653 in_buffer: InterleavedOwned<T>,
654 out_buffer: Vec<T>,
655 channels: usize,
656 output_frames: usize,
657}
658
659impl<T: Sample> PacketResamplerBuffer<T> for Interleaved<T> {
660 type Output = [T];
661
662 fn new(channels: usize, input_frames: usize, output_frames: usize) -> Self {
663 let out_buffer_size = output_frames * channels;
664 let mut out_buffer = Vec::new();
665 out_buffer.reserve_exact(out_buffer_size);
666 out_buffer.resize(out_buffer_size, T::zero());
667
668 Self {
669 in_buffer: InterleavedOwned::new(T::zero(), channels, input_frames),
670 out_buffer,
671 channels,
672 output_frames,
673 }
674 }
675
676 fn output(&self, frames: usize) -> &Self::Output {
677 &self.out_buffer[0..frames * self.channels]
678 }
679
680 fn resample(
681 &mut self,
682 indexing: Option<&rubato::Indexing>,
683 resampler: &mut Box<dyn Resampler<T>>,
684 ) -> ResampleResult<(usize, usize)> {
685 let mut out_buffer_wrapper = direct::InterleavedSlice::new_mut(
686 &mut self.out_buffer,
687 self.channels,
688 self.output_frames,
689 )
690 .unwrap();
691
692 resampler.process_into_buffer(&self.in_buffer, &mut out_buffer_wrapper, indexing)
693 }
694
695 fn copy_from_other_to_input_channel(
696 &mut self,
697 other: &dyn Adapter<T>,
698 other_channel: usize,
699 self_channel: usize,
700 other_skip: usize,
701 self_skip: usize,
702 take: usize,
703 ) -> Option<usize> {
704 self.in_buffer.copy_from_other_to_channel(
705 other,
706 other_channel,
707 self_channel,
708 other_skip,
709 self_skip,
710 take,
711 )
712 }
713
714 fn input_fill_frames_with(&mut self, start: usize, count: usize, value: &T) -> Option<usize> {
715 self.in_buffer.fill_frames_with(start, count, value)
716 }
717
718 fn input_fill_with(&mut self, value: &T) {
719 self.in_buffer.fill_with(value);
720 }
721
722 fn output_copy_frames_within(&mut self, src: usize, dest: usize, count: usize) {
723 self.out_buffer.copy_within(src..count, dest);
724 }
725}
726
727pub fn extend_from_adapter_channel<T: Sample>(
737 out_buffer: &mut Vec<T>,
738 buffer_in: &dyn Adapter<T>,
739 buffer_in_skip: usize,
740 buffer_in_channel: usize,
741 frames: usize,
742) -> usize {
743 assert!(buffer_in_channel < buffer_in.channels());
744
745 let out_buffer_len = out_buffer.len();
746 let available = out_buffer.capacity() - out_buffer_len;
747 if available < frames {
748 out_buffer.reserve(frames);
749 }
750
751 unsafe {
756 out_buffer.set_len(out_buffer_len + frames);
757 }
758
759 let frames_copied = buffer_in.copy_from_channel_to_slice(
760 buffer_in_channel,
761 buffer_in_skip,
762 &mut out_buffer[out_buffer_len..],
763 );
764
765 if frames_copied < frames {
767 unsafe {
771 out_buffer.set_len(out_buffer_len + frames_copied);
772 }
773 }
774
775 frames_copied
776}