1#![doc = include_str!("../README.md")]
2
3#[cfg(feature = "log")]
4extern crate log;
5
6pub use audioadapter;
7pub use audioadapter_buffers;
8
9use audioadapter::{Adapter, AdapterMut};
10use audioadapter_buffers::owned::InterleavedOwned;
11
12#[allow(unused)]
14macro_rules! trace { ($($x:tt)*) => (
15 #[cfg(feature = "log")] {
16 log::trace!($($x)*)
17 }
18) }
19#[allow(unused)]
20macro_rules! debug { ($($x:tt)*) => (
21 #[cfg(feature = "log")] {
22 log::debug!($($x)*)
23 }
24) }
25#[allow(unused)]
26macro_rules! info { ($($x:tt)*) => (
27 #[cfg(feature = "log")] {
28 log::info!($($x)*)
29 }
30) }
31#[allow(unused)]
32macro_rules! warn { ($($x:tt)*) => (
33 #[cfg(feature = "log")] {
34 log::warn!($($x)*)
35 }
36) }
37#[allow(unused)]
38macro_rules! error { ($($x:tt)*) => (
39 #[cfg(feature = "log")] {
40 log::error!($($x)*)
41 }
42) }
43
44mod asynchro;
45mod asynchro_fast;
46mod asynchro_sinc;
47mod error;
48mod interpolation;
49mod sample;
50mod sinc;
51mod slip;
52#[cfg(feature = "fft_resampler")]
53mod synchro;
54mod windows;
55
56pub mod sinc_interpolator;
57
58pub use crate::asynchro::{Async, FixedAsync};
59pub use crate::asynchro_fast::PolynomialDegree;
60pub use crate::asynchro_sinc::{SincInterpolationParameters, SincInterpolationType};
61pub use crate::error::{
62 CpuFeature, MissingCpuFeature, ResampleError, ResampleResult, ResamplerConstructionError,
63};
64pub use crate::sample::Sample;
65pub use crate::slip::Slip;
66#[cfg(feature = "fft_resampler")]
67pub use crate::synchro::{Fft, FixedSync};
68pub use crate::windows::{calculate_cutoff, WindowFunction};
69
70#[derive(Debug, Clone, Default)]
76pub struct Indexing {
77 pub input_offset: usize,
81
82 pub output_offset: usize,
86
87 pub partial_len: Option<usize>,
101
102 pub active_channels_mask: Option<Vec<bool>>,
108}
109
110impl Indexing {
111 pub fn new() -> Self {
124 Self::default()
125 }
126
127 #[must_use]
129 pub fn input_offset(mut self, frames: usize) -> Self {
130 self.input_offset = frames;
131 self
132 }
133
134 #[must_use]
136 pub fn output_offset(mut self, frames: usize) -> Self {
137 self.output_offset = frames;
138 self
139 }
140
141 #[must_use]
143 pub fn partial_len(mut self, frames: usize) -> Self {
144 self.partial_len = Some(frames);
145 self
146 }
147
148 #[must_use]
150 pub fn active_channels_mask(mut self, mask: Vec<bool>) -> Self {
151 self.active_channels_mask = Some(mask);
152 self
153 }
154}
155
156pub(crate) fn get_offsets(indexing: &Option<&Indexing>) -> (usize, usize) {
157 indexing
158 .as_ref()
159 .map(|idx| (idx.input_offset, idx.output_offset))
160 .unwrap_or((0, 0))
161}
162
163pub(crate) fn get_partial_len(indexing: &Option<&Indexing>) -> Option<usize> {
164 indexing.as_ref().and_then(|idx| idx.partial_len)
165}
166
167pub(crate) fn update_mask(indexing: &Option<&Indexing>, mask: &mut [bool]) -> ResampleResult<()> {
170 if let Some(idx) = indexing {
171 if let Some(new_mask) = &idx.active_channels_mask {
172 if new_mask.len() != mask.len() {
173 return Err(ResampleError::WrongNumberOfMaskChannels {
174 expected: mask.len(),
175 actual: new_mask.len(),
176 });
177 }
178 mask.copy_from_slice(new_mask);
179 return Ok(());
180 }
181 }
182 mask.iter_mut().for_each(|v| *v = true);
183 Ok(())
184}
185
186pub trait Resampler<T>: Send
189where
190 T: Sample,
191{
192 fn process(
214 &mut self,
215 buffer_in: &dyn Adapter<T>,
216 indexing: Option<&Indexing>,
217 ) -> ResampleResult<InterleavedOwned<T>> {
218 let frames = self.output_frames_next();
219 let channels = self.nbr_channels();
220 let mut buffer_out = InterleavedOwned::<T>::new(T::coerce_from(0.0), channels, frames);
221
222 let indexing = Indexing {
223 input_offset: get_offsets(&indexing).0,
224 output_offset: 0,
225 partial_len: get_partial_len(&indexing),
226 active_channels_mask: indexing.and_then(|idx| idx.active_channels_mask.clone()),
227 };
228 self.process_into_buffer(buffer_in, &mut buffer_out, Some(&indexing))?;
229 Ok(buffer_out)
230 }
231
232 fn process_into_buffer(
264 &mut self,
265 buffer_in: &dyn Adapter<T>,
266 buffer_out: &mut dyn AdapterMut<T>,
267 indexing: Option<&Indexing>,
268 ) -> ResampleResult<(usize, usize)>;
269
270 fn process_all_into_buffer(
286 &mut self,
287 buffer_in: &dyn Adapter<T>,
288 buffer_out: &mut dyn AdapterMut<T>,
289 input_len: usize,
290 active_channels_mask: Option<&[bool]>,
291 ) -> ResampleResult<(usize, usize)> {
292 let expected_output_len = (self.resample_ratio() * input_len as f64).ceil() as usize;
293
294 let mut indexing = Indexing {
295 input_offset: 0,
296 output_offset: 0,
297 active_channels_mask: active_channels_mask.map(|m| m.to_vec()),
298 partial_len: None,
299 };
300
301 let mut frames_left = input_len;
302 let mut output_len = 0;
303 let mut frames_to_trim = self.output_delay();
304 debug!(
305 "resamping {} input frames to {} output frames, delay to trim off {} frames",
306 input_len, expected_output_len, frames_to_trim
307 );
308
309 let next_nbr_input_frames = self.input_frames_next();
310 while frames_left > next_nbr_input_frames {
311 debug!("process, {} input frames left", frames_left);
312 let (nbr_in, nbr_out) =
313 self.process_into_buffer(buffer_in, buffer_out, Some(&indexing))?;
314 frames_left -= nbr_in;
315 output_len += nbr_out;
316 indexing.input_offset += nbr_in;
317 indexing.output_offset += nbr_out;
318 if frames_to_trim > 0 && output_len > frames_to_trim {
319 debug!(
320 "output, {} is longer than delay to trim, {}, trimming..",
321 output_len, frames_to_trim
322 );
323 buffer_out.copy_frames_within(frames_to_trim, 0, frames_to_trim);
325 output_len -= frames_to_trim;
327 indexing.output_offset -= frames_to_trim;
328 frames_to_trim = 0;
329 }
330 }
331 if frames_left > 0 {
332 debug!("process the last partial chunk, len {}", frames_left);
333 indexing.partial_len = Some(frames_left);
334 let (_nbr_in, nbr_out) =
335 self.process_into_buffer(buffer_in, buffer_out, Some(&indexing))?;
336 output_len += nbr_out;
337 indexing.output_offset += nbr_out;
338 }
339 indexing.partial_len = Some(0);
340 while output_len < expected_output_len {
341 debug!(
342 "output is still too short, {} < {}, pump zeros..",
343 output_len, expected_output_len
344 );
345 let (_nbr_in, nbr_out) =
346 self.process_into_buffer(buffer_in, buffer_out, Some(&indexing))?;
347 output_len += nbr_out;
348 indexing.output_offset += nbr_out;
349 }
350 Ok((input_len, expected_output_len))
351 }
352
353 fn process_all(
377 &mut self,
378 buffer_in: &dyn Adapter<T>,
379 input_len: usize,
380 active_channels_mask: Option<&[bool]>,
381 ) -> ResampleResult<InterleavedOwned<T>> {
382 self.reset();
383 let channels = self.nbr_channels();
384 let needed_len = self.process_all_needed_output_len(input_len);
385 let mut buffer_out = InterleavedOwned::<T>::new(T::coerce_from(0.0), channels, needed_len);
386 let (_input_len, output_len) = self.process_all_into_buffer(
387 buffer_in,
388 &mut buffer_out,
389 input_len,
390 active_channels_mask,
391 )?;
392
393 let mut data = buffer_out.take_data();
397 data.truncate(output_len * channels);
398 Ok(InterleavedOwned::new_from(data, channels, output_len)
399 .expect("trimmed length is consistent with the channel count"))
400 }
401
402 fn process_all_needed_output_len(&mut self, input_len: usize) -> usize {
410 let delay_frames = self.output_delay();
411 let output_frames_max = self.output_frames_max();
412 let expected_output_len = (self.resample_ratio() * input_len as f64).ceil() as usize;
413 delay_frames + output_frames_max + expected_output_len
414 }
415
416 fn input_frames_max(&self) -> usize;
418
419 fn input_frames_next(&self) -> usize;
422
423 fn nbr_channels(&self) -> usize;
425
426 fn output_frames_max(&self) -> usize;
428
429 fn output_frames_next(&self) -> usize;
432
433 fn output_delay(&self) -> usize;
436
437 fn resample_ratio(&self) -> f64;
439
440 fn reset(&mut self);
442
443 fn as_adjustable(&mut self) -> Option<&mut dyn Adjustable<T>>;
460
461 fn is_adjustable(&self) -> bool {
468 false
469 }
470
471 fn as_resizable(&mut self) -> Option<&mut dyn Resizable<T>>;
478
479 fn is_resizable(&self) -> bool {
486 false
487 }
488}
489
490pub trait Adjustable<T>: Resampler<T>
499where
500 T: Sample,
501{
502 fn set_resample_ratio(&mut self, new_ratio: f64, ramp: bool) -> ResampleResult<()>;
512
513 fn set_resample_ratio_relative(&mut self, rel_ratio: f64, ramp: bool) -> ResampleResult<()>;
522}
523
524pub trait Resizable<T>: Resampler<T>
528where
529 T: Sample,
530{
531 fn set_chunk_size(&mut self, chunksize: usize) -> ResampleResult<()>;
540}
541
542pub(crate) fn validate_buffers<T>(
543 wave_in: &dyn Adapter<T>,
544 wave_out: &dyn AdapterMut<T>,
545 channels: usize,
546 min_input_len: usize,
547 min_output_len: usize,
548) -> ResampleResult<()> {
549 if wave_in.channels() != channels {
550 return Err(ResampleError::WrongNumberOfInputChannels {
551 expected: channels,
552 actual: wave_in.channels(),
553 });
554 }
555 if wave_in.frames() < min_input_len {
556 return Err(ResampleError::InsufficientInputBufferSize {
557 expected: min_input_len,
558 actual: wave_in.frames(),
559 });
560 }
561 if wave_out.channels() != channels {
562 return Err(ResampleError::WrongNumberOfOutputChannels {
563 expected: channels,
564 actual: wave_out.channels(),
565 });
566 }
567 if wave_out.frames() < min_output_len {
568 return Err(ResampleError::InsufficientOutputBufferSize {
569 expected: min_output_len,
570 actual: wave_out.frames(),
571 });
572 }
573 Ok(())
574}
575
576#[cfg(test)]
577pub mod tests {
578 use crate::Resampler;
579 use crate::{
580 Async, FixedAsync, Indexing, ResampleError, SincInterpolationParameters,
581 SincInterpolationType, Slip, WindowFunction,
582 };
583 #[cfg(feature = "fft_resampler")]
584 use crate::{Fft, FixedSync};
585 use audioadapter::Adapter;
586 use audioadapter_buffers::direct::SequentialSliceOfVecs;
587
588 fn test_sinc_resampler() -> Async<f64> {
589 Async::<f64>::new_sinc(
590 88200.0 / 44100.0,
591 1.1,
592 &SincInterpolationParameters {
593 sinc_len: 64,
594 f_cutoff: Some(0.95),
595 interpolation: SincInterpolationType::Cubic,
596 oversampling_factor: 16,
597 window: WindowFunction::BlackmanHarris2,
598 },
599 1024,
600 2,
601 FixedAsync::Input,
602 )
603 .unwrap()
604 }
605
606 #[test_log::test]
607 fn process_single_chunk() {
608 let mut resampler = test_sinc_resampler();
609 let in_len = resampler.input_frames_next();
610 let samples: Vec<f64> = (0..in_len).map(|v| v as f64 / 10.0).collect();
611 let input_data = vec![samples; 2];
612 let input = SequentialSliceOfVecs::new(&input_data, 2, in_len).unwrap();
613
614 let expected = resampler.output_frames_next();
616 let out = resampler.process(&input, None).unwrap();
617 assert_eq!(out.channels(), 2);
618 assert_eq!(out.frames(), expected);
619
620 let expected = resampler.output_frames_next();
623 let out = resampler
624 .process(&input, Some(&Indexing::new().partial_len(in_len / 2)))
625 .unwrap();
626 assert_eq!(out.frames(), expected);
627 }
628
629 #[test_log::test]
630 fn wrong_length_mask_returns_error() {
631 let mut resampler = test_sinc_resampler();
633 let in_len = resampler.input_frames_next();
634 let input_data = vec![vec![0.0f64; in_len]; 2];
635 let input = SequentialSliceOfVecs::new(&input_data, 2, in_len).unwrap();
636
637 let indexing = Indexing::new().active_channels_mask(vec![true, true, true]);
638 let result = resampler.process(&input, Some(&indexing));
639 assert!(matches!(
640 result,
641 Err(ResampleError::WrongNumberOfMaskChannels {
642 expected: 2,
643 actual: 3
644 })
645 ));
646 }
647
648 #[test_log::test]
649 fn process_all() {
650 let mut resampler = Async::<f64>::new_sinc(
651 88200.0 / 44100.0,
652 1.1,
653 &SincInterpolationParameters {
654 sinc_len: 64,
655 f_cutoff: Some(0.95),
656 interpolation: SincInterpolationType::Cubic,
657 oversampling_factor: 16,
658 window: WindowFunction::BlackmanHarris2,
659 },
660 1024,
661 2,
662 FixedAsync::Input,
663 )
664 .unwrap();
665 let input_len = 12345;
666 let samples: Vec<f64> = (0..input_len).map(|v| v as f64 / 10.0).collect();
667 let input_data = vec![samples; 2];
668 let input = SequentialSliceOfVecs::new(&input_data, 2, input_len).unwrap();
670 let output_len = resampler.process_all_needed_output_len(input_len);
671 let mut output_data = vec![vec![0.0f64; output_len]; 2];
672 let mut output = SequentialSliceOfVecs::new_mut(&mut output_data, 2, output_len).unwrap();
673 let (nbr_in, nbr_out) = resampler
674 .process_all_into_buffer(&input, &mut output, input_len, None)
675 .unwrap();
676 assert_eq!(nbr_in, input_len);
677 assert_eq!(2 * nbr_in, nbr_out);
679
680 let increment = 0.1 / resampler.resample_ratio();
682 let delay = resampler.output_delay();
683 let margin = (delay as f64 * resampler.resample_ratio()) as usize;
684 let mut expected = margin as f64 * increment;
685 for frame in margin..(nbr_out - margin) {
686 for chan in 0..2 {
687 let val = output.read_sample(chan, frame).unwrap();
688 assert!(
689 val - expected < 100.0 * increment,
690 "frame: {}, value: {}, expected: {}",
691 frame,
692 val,
693 expected
694 );
695 assert!(
696 expected - val < 100.0 * increment,
697 "frame: {}, value: {}, expected: {}",
698 frame,
699 val,
700 expected
701 );
702 }
703 expected += increment;
704 }
705 }
706
707 #[test_log::test]
708 fn process_all_allocating() {
709 let mut resampler = Async::<f64>::new_sinc(
710 88200.0 / 44100.0,
711 1.1,
712 &SincInterpolationParameters {
713 sinc_len: 64,
714 f_cutoff: Some(0.95),
715 interpolation: SincInterpolationType::Cubic,
716 oversampling_factor: 16,
717 window: WindowFunction::BlackmanHarris2,
718 },
719 1024,
720 2,
721 FixedAsync::Input,
722 )
723 .unwrap();
724 let input_len = 12345;
725 let samples: Vec<f64> = (0..input_len).map(|v| v as f64 / 10.0).collect();
726 let input_data = vec![samples; 2];
727 let input = SequentialSliceOfVecs::new(&input_data, 2, input_len).unwrap();
728
729 let output = resampler.process_all(&input, input_len, None).unwrap();
730 let expected_len = 2 * input_len;
733 assert_eq!(output.channels(), 2);
734 assert_eq!(output.frames(), expected_len);
735
736 let increment = 0.1 / resampler.resample_ratio();
738 let margin = (resampler.output_delay() as f64 * resampler.resample_ratio()) as usize;
739 for frame in margin..(expected_len - margin) {
740 let expected = frame as f64 * increment;
741 for chan in 0..2 {
742 let val = output.read_sample(chan, frame).unwrap();
743 assert!(
744 (val - expected).abs() < 100.0 * increment,
745 "frame: {}, value: {}, expected: {}",
746 frame,
747 val,
748 expected
749 );
750 }
751 }
752
753 let output2 = resampler.process_all(&input, input_len, None).unwrap();
755 assert_eq!(output2.frames(), expected_len);
756 for frame in 0..expected_len {
757 for chan in 0..2 {
758 assert_eq!(
759 output.read_sample(chan, frame),
760 output2.read_sample(chan, frame)
761 );
762 }
763 }
764 }
765
766 #[test_log::test]
767 fn capability_queries() {
768 let mut resampler = test_sinc_resampler();
770 assert!(resampler.is_adjustable());
771 assert!(resampler.is_resizable());
772 resampler
773 .as_adjustable()
774 .expect("Async should be adjustable")
775 .set_resample_ratio_relative(1.05, false)
776 .unwrap();
777 assert!(resampler.as_resizable().is_some());
778
779 let mut boxed: Box<dyn Resampler<f64>> = Box::new(test_sinc_resampler());
782 let shared: &dyn Resampler<f64> = boxed.as_ref();
783 assert!(shared.is_adjustable());
784 assert!(shared.is_resizable());
785 assert!(boxed.as_adjustable().is_some());
786 assert!(boxed.as_resizable().is_some());
787
788 let mut slip = Slip::<f64>::new(1024, 2, FixedAsync::Output).unwrap();
790 assert!(slip.is_adjustable());
791 assert!(slip.is_resizable());
792 assert!(slip.as_adjustable().is_some());
793 assert!(slip.as_resizable().is_some());
794
795 #[cfg(feature = "fft_resampler")]
797 {
798 let mut fft = Fft::<f64>::new(44100, 48000, 1024, 2, FixedSync::Both).unwrap();
799 assert!(!fft.is_adjustable());
800 assert!(!fft.is_resizable());
801 assert!(fft.as_adjustable().is_none());
802 assert!(fft.as_resizable().is_none());
803 }
804 }
805
806 #[test_log::test]
808 fn boxed_resampler() {
809 let mut boxed: Box<dyn Resampler<f64>> = Box::new(
810 Async::<f64>::new_sinc(
811 88200.0 / 44100.0,
812 1.1,
813 &SincInterpolationParameters {
814 sinc_len: 64,
815 f_cutoff: Some(0.95),
816 interpolation: SincInterpolationType::Cubic,
817 oversampling_factor: 16,
818 window: WindowFunction::BlackmanHarris2,
819 },
820 1024,
821 2,
822 FixedAsync::Input,
823 )
824 .unwrap(),
825 );
826 let max_frames_out = boxed.output_frames_max();
827 let nbr_frames_in_next = boxed.input_frames_next();
828 let waves = vec![vec![0.0f64; nbr_frames_in_next]; 2];
829 let mut waves_out = vec![vec![0.0f64; max_frames_out]; 2];
830 let input = SequentialSliceOfVecs::new(&waves, 2, nbr_frames_in_next).unwrap();
831 let mut output = SequentialSliceOfVecs::new_mut(&mut waves_out, 2, max_frames_out).unwrap();
832 process_with_boxed(&mut boxed, &input, &mut output);
833 }
834
835 fn process_with_boxed<'a>(
836 resampler: &mut Box<dyn Resampler<f64>>,
837 input: &SequentialSliceOfVecs<&'a [Vec<f64>]>,
838 output: &mut SequentialSliceOfVecs<&'a mut [Vec<f64>]>,
839 ) {
840 resampler.process_into_buffer(input, output, None).unwrap();
841 }
842
843 fn impl_send<T: Send>() {
844 fn is_send<T: Send>() {}
845 is_send::<Async<T>>();
846 is_send::<Slip<T>>();
847 #[cfg(feature = "fft_resampler")]
848 {
849 is_send::<Fft<T>>();
850 }
851 }
852
853 #[test]
855 fn test_impl_send() {
856 impl_send::<f32>();
857 impl_send::<f64>();
858 }
859
860 pub fn expected_output_value(idx: usize, delay: usize, ratio: f64) -> f64 {
861 if idx <= delay {
862 return 0.0;
863 }
864 (idx - delay) as f64 * 0.1 / ratio
865 }
866
867 #[macro_export]
868 macro_rules! check_output {
869 ($resampler:ident, $fty:ty) => {
870 let mut ramp_value: $fty = 0.0;
871 let max_input_len = $resampler.input_frames_max();
872 let max_output_len = $resampler.output_frames_max();
873 let ratio = $resampler.resample_ratio() as $fty;
874 let delay = $resampler.output_delay();
875 let mut output_index = 0;
876
877 let out_incr = 0.1 / ratio;
878
879 let nbr_iterations =
880 100000 / ($resampler.output_frames_next() + $resampler.input_frames_next());
881 for _n in 0..nbr_iterations {
882 let expected_frames_in = $resampler.input_frames_next();
883 let expected_frames_out = $resampler.output_frames_next();
884 assert!(expected_frames_in <= max_input_len);
886 assert!(expected_frames_out <= max_output_len);
887 let mut input_data = vec![vec![0.0 as $fty; expected_frames_in]; 2];
888 for m in 0..expected_frames_in {
889 for ch in 0..2 {
890 input_data[ch][m] = ramp_value;
891 }
892 ramp_value += 0.1;
893 }
894 let input = SequentialSliceOfVecs::new(&input_data, 2, expected_frames_in).unwrap();
895 let mut output_data = vec![vec![0.0 as $fty; expected_frames_out]; 2];
896 let mut output =
897 SequentialSliceOfVecs::new_mut(&mut output_data, 2, expected_frames_out)
898 .unwrap();
899
900 trace!("resample...");
901 let (input_frames, output_frames) = $resampler
902 .process_into_buffer(&input, &mut output, None)
903 .unwrap();
904 trace!("assert lengths");
905 assert_eq!(input_frames, expected_frames_in);
906 assert_eq!(output_frames, expected_frames_out);
907 trace!("check output");
908 for idx in 0..output_frames {
909 let expected = expected_output_value(output_index + idx, delay, ratio) as $fty;
910 for ch in 0..2 {
911 let value = output_data[ch][idx];
912 let margin = 3.0 * out_incr;
913 assert!(
914 value > expected - margin,
915 "Value at frame {} is too small, {} < {} - {}",
916 output_index + idx,
917 value,
918 expected,
919 margin
920 );
921 assert!(
922 value < expected + margin,
923 "Value at frame {} is too large, {} > {} + {}",
924 output_index + idx,
925 value,
926 expected,
927 margin
928 );
929 }
930 }
931 output_index += output_frames;
932 }
933 assert!(output_index > 1000, "Too few frames checked!");
934 };
935 }
936
937 #[macro_export]
938 macro_rules! check_ratio {
939 ($resampler:ident, $repetitions:expr, $margin:expr, $fty:ty) => {
940 let ratio = $resampler.resample_ratio();
941 let max_input_len = $resampler.input_frames_max();
942 let max_output_len = $resampler.output_frames_max();
943 let waves_in = vec![vec![0.0 as $fty; max_input_len]; 2];
944 let input = SequentialSliceOfVecs::new(&waves_in, 2, max_input_len).unwrap();
945 let mut waves_out = vec![vec![0.0 as $fty; max_output_len]; 2];
946 let mut output =
947 SequentialSliceOfVecs::new_mut(&mut waves_out, 2, max_output_len).unwrap();
948 let mut total_in = 0;
949 let mut total_out = 0;
950 for _ in 0..$repetitions {
951 let out = $resampler
952 .process_into_buffer(&input, &mut output, None)
953 .unwrap();
954 total_in += out.0;
955 total_out += out.1
956 }
957 let measured_ratio = total_out as f64 / total_in as f64;
958 assert!(
959 measured_ratio / ratio > (1.0 - $margin),
960 "Measured ratio is too small, measured / expected = {}",
961 measured_ratio / ratio
962 );
963 assert!(
964 measured_ratio / ratio < (1.0 + $margin),
965 "Measured ratio is too large, measured / expected = {}",
966 measured_ratio / ratio
967 );
968 };
969 }
970
971 #[macro_export]
972 macro_rules! assert_fi_len {
973 ($resampler:ident, $chunksize:expr) => {
974 let nbr_frames_in_next = $resampler.input_frames_next();
975 let nbr_frames_in_max = $resampler.input_frames_max();
976 assert_eq!(
977 nbr_frames_in_next, $chunksize,
978 "expected {} for next input samples, got {}",
979 $chunksize, nbr_frames_in_next
980 );
981 assert_eq!(
982 nbr_frames_in_next, $chunksize,
983 "expected {} for max input samples, got {}",
984 $chunksize, nbr_frames_in_max
985 );
986 };
987 }
988
989 #[macro_export]
990 macro_rules! assert_fo_len {
991 ($resampler:ident, $chunksize:expr) => {
992 let nbr_frames_out_next = $resampler.output_frames_next();
993 let nbr_frames_out_max = $resampler.output_frames_max();
994 assert_eq!(
995 nbr_frames_out_next, $chunksize,
996 "expected {} for next output samples, got {}",
997 $chunksize, nbr_frames_out_next
998 );
999 assert_eq!(
1000 nbr_frames_out_next, $chunksize,
1001 "expected {} for max output samples, got {}",
1002 $chunksize, nbr_frames_out_max
1003 );
1004 };
1005 }
1006
1007 #[macro_export]
1008 macro_rules! assert_fb_len {
1009 ($resampler:ident) => {
1010 let nbr_frames_out_next = $resampler.output_frames_next();
1011 let nbr_frames_out_max = $resampler.output_frames_max();
1012 let nbr_frames_in_next = $resampler.input_frames_next();
1013 let nbr_frames_in_max = $resampler.input_frames_max();
1014 let ratio = $resampler.resample_ratio();
1015 assert_eq!(
1016 nbr_frames_out_next, nbr_frames_out_max,
1017 "next output frames, {}, is different than max, {}",
1018 nbr_frames_out_next, nbr_frames_out_next
1019 );
1020 assert_eq!(
1021 nbr_frames_in_next, nbr_frames_in_max,
1022 "next input frames, {}, is different than max, {}",
1023 nbr_frames_in_next, nbr_frames_in_max
1024 );
1025 let frames_ratio = nbr_frames_out_next as f64 / nbr_frames_in_next as f64;
1026 assert_abs_diff_eq!(frames_ratio, ratio, epsilon = 0.000001);
1027 };
1028 }
1029
1030 #[macro_export]
1031 macro_rules! check_reset {
1032 ($resampler:ident) => {
1033 let frames_in = $resampler.input_frames_next();
1034
1035 let mut input_data = vec![vec![0.0f64; frames_in]; 2];
1036 input_data
1037 .iter_mut()
1038 .for_each(|ch| ch.iter_mut().for_each(|s| *s = rand::random()));
1039
1040 let input = SequentialSliceOfVecs::new(&input_data, 2, frames_in).unwrap();
1041
1042 let frames_out = $resampler.output_frames_next();
1043 let mut output_data_1 = vec![vec![0.0; frames_out]; 2];
1044 let mut output_1 =
1045 SequentialSliceOfVecs::new_mut(&mut output_data_1, 2, frames_out).unwrap();
1046 $resampler
1047 .process_into_buffer(&input, &mut output_1, None)
1048 .unwrap();
1049 $resampler.reset();
1050 assert_eq!(
1051 frames_in,
1052 $resampler.input_frames_next(),
1053 "Resampler requires different number of frames when new and after a reset."
1054 );
1055 let mut output_data_2 = vec![vec![0.0; frames_out]; 2];
1056 let mut output_2 =
1057 SequentialSliceOfVecs::new_mut(&mut output_data_2, 2, frames_out).unwrap();
1058 $resampler
1059 .process_into_buffer(&input, &mut output_2, None)
1060 .unwrap();
1061 assert_eq!(
1062 output_data_1, output_data_2,
1063 "Resampler gives different output when new and after a reset."
1064 );
1065 };
1066 }
1067
1068 #[macro_export]
1069 macro_rules! check_input_offset {
1070 ($resampler:ident) => {
1071 let frames_in = $resampler.input_frames_next();
1072
1073 let mut input_data_1 = vec![vec![0.0f64; frames_in]; 2];
1074 input_data_1
1075 .iter_mut()
1076 .for_each(|ch| ch.iter_mut().for_each(|s| *s = rand::random()));
1077
1078 let offset = 123;
1079 let mut input_data_2 = vec![vec![0.0f64; frames_in + offset]; 2];
1080 for (ch, data) in input_data_2.iter_mut().enumerate() {
1081 data[offset..offset + frames_in].clone_from_slice(&input_data_1[ch][..])
1082 }
1083
1084 let input_1 = SequentialSliceOfVecs::new(&input_data_1, 2, frames_in).unwrap();
1085 let input_2 = SequentialSliceOfVecs::new(&input_data_2, 2, frames_in + offset).unwrap();
1086
1087 let frames_out = $resampler.output_frames_next();
1088 let mut output_data_1 = vec![vec![0.0; frames_out]; 2];
1089 let mut output_1 =
1090 SequentialSliceOfVecs::new_mut(&mut output_data_1, 2, frames_out).unwrap();
1091 $resampler
1092 .process_into_buffer(&input_1, &mut output_1, None)
1093 .unwrap();
1094 $resampler.reset();
1095 assert_eq!(
1096 frames_in,
1097 $resampler.input_frames_next(),
1098 "Resampler requires different number of frames when new and after a reset."
1099 );
1100 let mut output_data_2 = vec![vec![0.0; frames_out]; 2];
1101 let mut output_2 =
1102 SequentialSliceOfVecs::new_mut(&mut output_data_2, 2, frames_out).unwrap();
1103
1104 let indexing = Indexing {
1105 input_offset: offset,
1106 output_offset: 0,
1107 active_channels_mask: None,
1108 partial_len: None,
1109 };
1110 $resampler
1111 .process_into_buffer(&input_2, &mut output_2, Some(&indexing))
1112 .unwrap();
1113 assert_eq!(
1114 output_data_1, output_data_2,
1115 "Resampler gives different output when new and after a reset."
1116 );
1117 };
1118 }
1119
1120 #[macro_export]
1121 macro_rules! check_output_offset {
1122 ($resampler:ident) => {
1123 let frames_in = $resampler.input_frames_next();
1124
1125 let mut input_data = vec![vec![0.0f64; frames_in]; 2];
1126 input_data
1127 .iter_mut()
1128 .for_each(|ch| ch.iter_mut().for_each(|s| *s = rand::random()));
1129
1130 let input = SequentialSliceOfVecs::new(&input_data, 2, frames_in).unwrap();
1131
1132 let frames_out = $resampler.output_frames_next();
1133 let mut output_data_1 = vec![vec![0.0; frames_out]; 2];
1134 let mut output_1 =
1135 SequentialSliceOfVecs::new_mut(&mut output_data_1, 2, frames_out).unwrap();
1136 $resampler
1137 .process_into_buffer(&input, &mut output_1, None)
1138 .unwrap();
1139 $resampler.reset();
1140 assert_eq!(
1141 frames_in,
1142 $resampler.input_frames_next(),
1143 "Resampler requires different number of frames when new and after a reset."
1144 );
1145 let offset = 123;
1146 let mut output_data_2 = vec![vec![0.0; frames_out + offset]; 2];
1147 let mut output_2 =
1148 SequentialSliceOfVecs::new_mut(&mut output_data_2, 2, frames_out + offset).unwrap();
1149 let indexing = Indexing {
1150 input_offset: 0,
1151 output_offset: offset,
1152 active_channels_mask: None,
1153 partial_len: None,
1154 };
1155 $resampler
1156 .process_into_buffer(&input, &mut output_2, Some(&indexing))
1157 .unwrap();
1158 assert_eq!(
1159 output_data_1[0][..],
1160 output_data_2[0][offset..],
1161 "Resampler gives different output when new and after a reset."
1162 );
1163 assert_eq!(
1164 output_data_1[1][..],
1165 output_data_2[1][offset..],
1166 "Resampler gives different output when new and after a reset."
1167 );
1168 };
1169 }
1170
1171 #[macro_export]
1172 macro_rules! check_masked {
1173 ($resampler:ident) => {
1174 let frames_in = $resampler.input_frames_next();
1175
1176 let mut input_data = vec![vec![0.0f64; frames_in]; 2];
1177 input_data
1178 .iter_mut()
1179 .for_each(|ch| ch.iter_mut().for_each(|s| *s = rand::random()));
1180
1181 let input = SequentialSliceOfVecs::new(&input_data, 2, frames_in).unwrap();
1182
1183 let frames_out = $resampler.output_frames_next();
1184 let mut output_data = vec![vec![0.0; frames_out]; 2];
1185 let mut output =
1186 SequentialSliceOfVecs::new_mut(&mut output_data, 2, frames_out).unwrap();
1187
1188 let indexing = Indexing {
1189 input_offset: 0,
1190 output_offset: 0,
1191 active_channels_mask: Some(vec![false, true]),
1192 partial_len: None,
1193 };
1194 $resampler
1195 .process_into_buffer(&input, &mut output, Some(&indexing))
1196 .unwrap();
1197
1198 let non_zero_chan_0 = output_data[0].iter().filter(|&v| *v != 0.0).count();
1199 let non_zero_chan_1 = output_data[1].iter().filter(|&v| *v != 0.0).count();
1200 assert_eq!(
1202 non_zero_chan_0, 0,
1203 "Some sample in the non-active channel has a non-zero value"
1204 );
1205 assert!(
1207 non_zero_chan_1 > 0,
1208 "No sample in the active channel has a non-zero value"
1209 );
1210 };
1211 }
1212
1213 #[macro_export]
1214 macro_rules! check_resize {
1215 ($resampler:ident) => {};
1216 }
1217}