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(
324 &mut self,
325 buffer_in: &dyn Adapter<T>,
326 buffer_out: &mut dyn AdapterMut<T>,
327 input_len: usize,
328 active_channels_mask: Option<&[bool]>,
329 ) -> ResampleResult<(usize, usize)> {
330 let expected_output_len = (self.resample_ratio() * input_len as f64).ceil() as usize;
331
332 let mut indexing = Indexing {
333 input_offset: 0,
334 output_offset: 0,
335 active_channels_mask: active_channels_mask.map(|m| m.to_vec()),
336 partial_len: None,
337 };
338
339 let mut frames_left = input_len;
340 let mut output_len = 0;
341 let mut frames_to_trim = self.output_delay();
342 debug!(
343 "resamping {} input frames to {} output frames, delay to trim off {} frames",
344 input_len, expected_output_len, frames_to_trim
345 );
346
347 let next_nbr_input_frames = self.input_frames_next();
348 while frames_left > next_nbr_input_frames {
349 debug!("process, {} input frames left", frames_left);
350 let (nbr_in, nbr_out) =
351 self.process_into_buffer(buffer_in, buffer_out, Some(&indexing))?;
352 frames_left -= nbr_in;
353 output_len += nbr_out;
354 indexing.input_offset += nbr_in;
355 indexing.output_offset += nbr_out;
356 if frames_to_trim > 0 && output_len > frames_to_trim {
357 debug!(
358 "output, {} is longer than delay to trim, {}, trimming..",
359 output_len, frames_to_trim
360 );
361 buffer_out.copy_frames_within(frames_to_trim, 0, frames_to_trim);
363 output_len -= frames_to_trim;
365 indexing.output_offset -= frames_to_trim;
366 frames_to_trim = 0;
367 }
368 }
369 if frames_left > 0 {
370 debug!("process the last partial chunk, len {}", frames_left);
371 indexing.partial_len = Some(frames_left);
372 let (_nbr_in, nbr_out) =
373 self.process_into_buffer(buffer_in, buffer_out, Some(&indexing))?;
374 output_len += nbr_out;
375 indexing.output_offset += nbr_out;
376 }
377 indexing.partial_len = Some(0);
378 while output_len < expected_output_len {
379 debug!(
380 "output is still too short, {} < {}, pump zeros..",
381 output_len, expected_output_len
382 );
383 let (_nbr_in, nbr_out) =
384 self.process_into_buffer(buffer_in, buffer_out, Some(&indexing))?;
385 output_len += nbr_out;
386 indexing.output_offset += nbr_out;
387 }
388 Ok((input_len, expected_output_len))
389 }
390
391 fn process_all(
415 &mut self,
416 buffer_in: &dyn Adapter<T>,
417 input_len: usize,
418 active_channels_mask: Option<&[bool]>,
419 ) -> ResampleResult<InterleavedOwned<T>> {
420 self.reset();
421 let channels = self.nbr_channels();
422 let needed_len = self.process_all_needed_output_len(input_len);
423 let mut buffer_out = InterleavedOwned::<T>::new(T::coerce_from(0.0), channels, needed_len);
424 let (_input_len, output_len) = self.process_all_into_buffer(
425 buffer_in,
426 &mut buffer_out,
427 input_len,
428 active_channels_mask,
429 )?;
430
431 let mut data = buffer_out.take_data();
435 data.truncate(output_len * channels);
436 Ok(InterleavedOwned::new_from(data, channels, output_len)
437 .expect("trimmed length is consistent with the channel count"))
438 }
439
440 fn process_all_needed_output_len(&mut self, input_len: usize) -> usize {
448 let delay_frames = self.output_delay();
449 let output_frames_max = self.output_frames_max();
450 let expected_output_len = (self.resample_ratio() * input_len as f64).ceil() as usize;
451 delay_frames + output_frames_max + expected_output_len
452 }
453
454 fn input_frames_max(&self) -> usize;
456
457 fn input_frames_next(&self) -> usize;
460
461 fn nbr_channels(&self) -> usize;
463
464 fn output_frames_max(&self) -> usize;
466
467 fn output_frames_next(&self) -> usize;
470
471 fn output_delay(&self) -> usize;
474
475 fn resample_ratio(&self) -> f64;
477
478 fn reset(&mut self);
480
481 fn as_adjustable(&mut self) -> Option<&mut dyn Adjustable<T>>;
498
499 fn is_adjustable(&self) -> bool {
506 false
507 }
508
509 fn as_resizable(&mut self) -> Option<&mut dyn Resizable<T>>;
516
517 fn is_resizable(&self) -> bool {
524 false
525 }
526}
527
528pub trait Adjustable<T>: Resampler<T>
537where
538 T: Sample,
539{
540 fn set_resample_ratio(&mut self, new_ratio: f64, ramp: bool) -> ResampleResult<()>;
550
551 fn set_resample_ratio_relative(&mut self, rel_ratio: f64, ramp: bool) -> ResampleResult<()>;
560}
561
562pub trait Resizable<T>: Resampler<T>
566where
567 T: Sample,
568{
569 fn set_chunk_size(&mut self, chunksize: usize) -> ResampleResult<()>;
578}
579
580pub(crate) fn validate_buffers<T>(
581 wave_in: &dyn Adapter<T>,
582 wave_out: &dyn AdapterMut<T>,
583 channels: usize,
584 min_input_len: usize,
585 min_output_len: usize,
586) -> ResampleResult<()> {
587 if wave_in.channels() != channels {
588 return Err(ResampleError::WrongNumberOfInputChannels {
589 expected: channels,
590 actual: wave_in.channels(),
591 });
592 }
593 if wave_in.frames() < min_input_len {
594 return Err(ResampleError::InsufficientInputBufferSize {
595 expected: min_input_len,
596 actual: wave_in.frames(),
597 });
598 }
599 if wave_out.channels() != channels {
600 return Err(ResampleError::WrongNumberOfOutputChannels {
601 expected: channels,
602 actual: wave_out.channels(),
603 });
604 }
605 if wave_out.frames() < min_output_len {
606 return Err(ResampleError::InsufficientOutputBufferSize {
607 expected: min_output_len,
608 actual: wave_out.frames(),
609 });
610 }
611 Ok(())
612}
613
614#[cfg(test)]
615pub mod tests {
616 use crate::Resampler;
617 use crate::{
618 Async, FixedAsync, Indexing, ResampleError, SincInterpolationParameters,
619 SincInterpolationType, Slip, WindowFunction,
620 };
621 #[cfg(feature = "fft_resampler")]
622 use crate::{Fft, FixedSync};
623 use audioadapter::Adapter;
624 use audioadapter_buffers::direct::SequentialSliceOfVecs;
625
626 fn test_sinc_resampler() -> Async<f64> {
627 Async::<f64>::new_sinc(
628 88200.0 / 44100.0,
629 1.1,
630 &SincInterpolationParameters {
631 sinc_len: 64,
632 f_cutoff: Some(0.95),
633 interpolation: SincInterpolationType::Cubic,
634 oversampling_factor: 16,
635 window: WindowFunction::BlackmanHarris2,
636 },
637 1024,
638 2,
639 FixedAsync::Input,
640 )
641 .unwrap()
642 }
643
644 #[test_log::test]
645 fn process_single_chunk() {
646 let mut resampler = test_sinc_resampler();
647 let in_len = resampler.input_frames_next();
648 let samples: Vec<f64> = (0..in_len).map(|v| v as f64 / 10.0).collect();
649 let input_data = vec![samples; 2];
650 let input = SequentialSliceOfVecs::new(&input_data, 2, in_len).unwrap();
651
652 let expected = resampler.output_frames_next();
654 let out = resampler.process(&input, None).unwrap();
655 assert_eq!(out.channels(), 2);
656 assert_eq!(out.frames(), expected);
657
658 let expected = resampler.output_frames_next();
661 let out = resampler
662 .process(&input, Some(&Indexing::new().partial_len(in_len / 2)))
663 .unwrap();
664 assert_eq!(out.frames(), expected);
665 }
666
667 #[test_log::test]
668 fn wrong_length_mask_returns_error() {
669 let mut resampler = test_sinc_resampler();
671 let in_len = resampler.input_frames_next();
672 let input_data = vec![vec![0.0f64; in_len]; 2];
673 let input = SequentialSliceOfVecs::new(&input_data, 2, in_len).unwrap();
674
675 let indexing = Indexing::new().active_channels_mask(vec![true, true, true]);
676 let result = resampler.process(&input, Some(&indexing));
677 assert!(matches!(
678 result,
679 Err(ResampleError::WrongNumberOfMaskChannels {
680 expected: 2,
681 actual: 3
682 })
683 ));
684 }
685
686 #[test_log::test]
687 fn process_all() {
688 let mut resampler = Async::<f64>::new_sinc(
689 88200.0 / 44100.0,
690 1.1,
691 &SincInterpolationParameters {
692 sinc_len: 64,
693 f_cutoff: Some(0.95),
694 interpolation: SincInterpolationType::Cubic,
695 oversampling_factor: 16,
696 window: WindowFunction::BlackmanHarris2,
697 },
698 1024,
699 2,
700 FixedAsync::Input,
701 )
702 .unwrap();
703 let input_len = 12345;
704 let samples: Vec<f64> = (0..input_len).map(|v| v as f64 / 10.0).collect();
705 let input_data = vec![samples; 2];
706 let input = SequentialSliceOfVecs::new(&input_data, 2, input_len).unwrap();
708 let output_len = resampler.process_all_needed_output_len(input_len);
709 let mut output_data = vec![vec![0.0f64; output_len]; 2];
710 let mut output = SequentialSliceOfVecs::new_mut(&mut output_data, 2, output_len).unwrap();
711 let (nbr_in, nbr_out) = resampler
712 .process_all_into_buffer(&input, &mut output, input_len, None)
713 .unwrap();
714 assert_eq!(nbr_in, input_len);
715 assert_eq!(2 * nbr_in, nbr_out);
717
718 let increment = 0.1 / resampler.resample_ratio();
720 let delay = resampler.output_delay();
721 let margin = (delay as f64 * resampler.resample_ratio()) as usize;
722 let mut expected = margin as f64 * increment;
723 for frame in margin..(nbr_out - margin) {
724 for chan in 0..2 {
725 let val = output.read_sample(chan, frame).unwrap();
726 assert!(
727 val - expected < 100.0 * increment,
728 "frame: {}, value: {}, expected: {}",
729 frame,
730 val,
731 expected
732 );
733 assert!(
734 expected - val < 100.0 * increment,
735 "frame: {}, value: {}, expected: {}",
736 frame,
737 val,
738 expected
739 );
740 }
741 expected += increment;
742 }
743 }
744
745 #[test_log::test]
746 fn process_all_allocating() {
747 let mut resampler = Async::<f64>::new_sinc(
748 88200.0 / 44100.0,
749 1.1,
750 &SincInterpolationParameters {
751 sinc_len: 64,
752 f_cutoff: Some(0.95),
753 interpolation: SincInterpolationType::Cubic,
754 oversampling_factor: 16,
755 window: WindowFunction::BlackmanHarris2,
756 },
757 1024,
758 2,
759 FixedAsync::Input,
760 )
761 .unwrap();
762 let input_len = 12345;
763 let samples: Vec<f64> = (0..input_len).map(|v| v as f64 / 10.0).collect();
764 let input_data = vec![samples; 2];
765 let input = SequentialSliceOfVecs::new(&input_data, 2, input_len).unwrap();
766
767 let output = resampler.process_all(&input, input_len, None).unwrap();
768 let expected_len = 2 * input_len;
771 assert_eq!(output.channels(), 2);
772 assert_eq!(output.frames(), expected_len);
773
774 let increment = 0.1 / resampler.resample_ratio();
776 let margin = (resampler.output_delay() as f64 * resampler.resample_ratio()) as usize;
777 for frame in margin..(expected_len - margin) {
778 let expected = frame as f64 * increment;
779 for chan in 0..2 {
780 let val = output.read_sample(chan, frame).unwrap();
781 assert!(
782 (val - expected).abs() < 100.0 * increment,
783 "frame: {}, value: {}, expected: {}",
784 frame,
785 val,
786 expected
787 );
788 }
789 }
790
791 let output2 = resampler.process_all(&input, input_len, None).unwrap();
793 assert_eq!(output2.frames(), expected_len);
794 for frame in 0..expected_len {
795 for chan in 0..2 {
796 assert_eq!(
797 output.read_sample(chan, frame),
798 output2.read_sample(chan, frame)
799 );
800 }
801 }
802 }
803
804 #[test_log::test]
805 fn capability_queries() {
806 let mut resampler = test_sinc_resampler();
808 assert!(resampler.is_adjustable());
809 assert!(resampler.is_resizable());
810 resampler
811 .as_adjustable()
812 .expect("Async should be adjustable")
813 .set_resample_ratio_relative(1.05, false)
814 .unwrap();
815 assert!(resampler.as_resizable().is_some());
816
817 let mut boxed: Box<dyn Resampler<f64>> = Box::new(test_sinc_resampler());
820 let shared: &dyn Resampler<f64> = boxed.as_ref();
821 assert!(shared.is_adjustable());
822 assert!(shared.is_resizable());
823 assert!(boxed.as_adjustable().is_some());
824 assert!(boxed.as_resizable().is_some());
825
826 let mut slip = Slip::<f64>::new(1024, 2, FixedAsync::Output).unwrap();
828 assert!(slip.is_adjustable());
829 assert!(slip.is_resizable());
830 assert!(slip.as_adjustable().is_some());
831 assert!(slip.as_resizable().is_some());
832
833 #[cfg(feature = "fft_resampler")]
835 {
836 let mut fft = Fft::<f64>::new(44100, 48000, 1024, 2, FixedSync::Both).unwrap();
837 assert!(!fft.is_adjustable());
838 assert!(!fft.is_resizable());
839 assert!(fft.as_adjustable().is_none());
840 assert!(fft.as_resizable().is_none());
841 }
842 }
843
844 #[test_log::test]
846 fn boxed_resampler() {
847 let mut boxed: Box<dyn Resampler<f64>> = Box::new(
848 Async::<f64>::new_sinc(
849 88200.0 / 44100.0,
850 1.1,
851 &SincInterpolationParameters {
852 sinc_len: 64,
853 f_cutoff: Some(0.95),
854 interpolation: SincInterpolationType::Cubic,
855 oversampling_factor: 16,
856 window: WindowFunction::BlackmanHarris2,
857 },
858 1024,
859 2,
860 FixedAsync::Input,
861 )
862 .unwrap(),
863 );
864 let max_frames_out = boxed.output_frames_max();
865 let nbr_frames_in_next = boxed.input_frames_next();
866 let waves = vec![vec![0.0f64; nbr_frames_in_next]; 2];
867 let mut waves_out = vec![vec![0.0f64; max_frames_out]; 2];
868 let input = SequentialSliceOfVecs::new(&waves, 2, nbr_frames_in_next).unwrap();
869 let mut output = SequentialSliceOfVecs::new_mut(&mut waves_out, 2, max_frames_out).unwrap();
870 process_with_boxed(&mut boxed, &input, &mut output);
871 }
872
873 fn process_with_boxed<'a>(
874 resampler: &mut Box<dyn Resampler<f64>>,
875 input: &SequentialSliceOfVecs<&'a [Vec<f64>]>,
876 output: &mut SequentialSliceOfVecs<&'a mut [Vec<f64>]>,
877 ) {
878 resampler.process_into_buffer(input, output, None).unwrap();
879 }
880
881 fn impl_send<T: Send>() {
882 fn is_send<T: Send>() {}
883 is_send::<Async<T>>();
884 is_send::<Slip<T>>();
885 #[cfg(feature = "fft_resampler")]
886 {
887 is_send::<Fft<T>>();
888 }
889 }
890
891 #[test]
893 fn test_impl_send() {
894 impl_send::<f32>();
895 impl_send::<f64>();
896 }
897
898 pub fn expected_output_value(idx: usize, delay: usize, ratio: f64) -> f64 {
899 if idx <= delay {
900 return 0.0;
901 }
902 (idx - delay) as f64 * 0.1 / ratio
903 }
904
905 #[macro_export]
906 macro_rules! check_output {
907 ($resampler:ident, $fty:ty) => {
908 let mut ramp_value: $fty = 0.0;
909 let max_input_len = $resampler.input_frames_max();
910 let max_output_len = $resampler.output_frames_max();
911 let ratio = $resampler.resample_ratio() as $fty;
912 let delay = $resampler.output_delay();
913 let mut output_index = 0;
914
915 let out_incr = 0.1 / ratio;
916
917 let nbr_iterations =
918 100000 / ($resampler.output_frames_next() + $resampler.input_frames_next());
919 for _n in 0..nbr_iterations {
920 let expected_frames_in = $resampler.input_frames_next();
921 let expected_frames_out = $resampler.output_frames_next();
922 assert!(expected_frames_in <= max_input_len);
924 assert!(expected_frames_out <= max_output_len);
925 let mut input_data = vec![vec![0.0 as $fty; expected_frames_in]; 2];
926 for m in 0..expected_frames_in {
927 for ch in 0..2 {
928 input_data[ch][m] = ramp_value;
929 }
930 ramp_value += 0.1;
931 }
932 let input = SequentialSliceOfVecs::new(&input_data, 2, expected_frames_in).unwrap();
933 let mut output_data = vec![vec![0.0 as $fty; expected_frames_out]; 2];
934 let mut output =
935 SequentialSliceOfVecs::new_mut(&mut output_data, 2, expected_frames_out)
936 .unwrap();
937
938 trace!("resample...");
939 let (input_frames, output_frames) = $resampler
940 .process_into_buffer(&input, &mut output, None)
941 .unwrap();
942 trace!("assert lengths");
943 assert_eq!(input_frames, expected_frames_in);
944 assert_eq!(output_frames, expected_frames_out);
945 trace!("check output");
946 for idx in 0..output_frames {
947 let expected = expected_output_value(output_index + idx, delay, ratio) as $fty;
948 for ch in 0..2 {
949 let value = output_data[ch][idx];
950 let margin = 3.0 * out_incr;
951 assert!(
952 value > expected - margin,
953 "Value at frame {} is too small, {} < {} - {}",
954 output_index + idx,
955 value,
956 expected,
957 margin
958 );
959 assert!(
960 value < expected + margin,
961 "Value at frame {} is too large, {} > {} + {}",
962 output_index + idx,
963 value,
964 expected,
965 margin
966 );
967 }
968 }
969 output_index += output_frames;
970 }
971 assert!(output_index > 1000, "Too few frames checked!");
972 };
973 }
974
975 #[macro_export]
976 macro_rules! check_ratio {
977 ($resampler:ident, $repetitions:expr, $margin:expr, $fty:ty) => {
978 let ratio = $resampler.resample_ratio();
979 let max_input_len = $resampler.input_frames_max();
980 let max_output_len = $resampler.output_frames_max();
981 let waves_in = vec![vec![0.0 as $fty; max_input_len]; 2];
982 let input = SequentialSliceOfVecs::new(&waves_in, 2, max_input_len).unwrap();
983 let mut waves_out = vec![vec![0.0 as $fty; max_output_len]; 2];
984 let mut output =
985 SequentialSliceOfVecs::new_mut(&mut waves_out, 2, max_output_len).unwrap();
986 let mut total_in = 0;
987 let mut total_out = 0;
988 for _ in 0..$repetitions {
989 let out = $resampler
990 .process_into_buffer(&input, &mut output, None)
991 .unwrap();
992 total_in += out.0;
993 total_out += out.1
994 }
995 let measured_ratio = total_out as f64 / total_in as f64;
996 assert!(
997 measured_ratio / ratio > (1.0 - $margin),
998 "Measured ratio is too small, measured / expected = {}",
999 measured_ratio / ratio
1000 );
1001 assert!(
1002 measured_ratio / ratio < (1.0 + $margin),
1003 "Measured ratio is too large, measured / expected = {}",
1004 measured_ratio / ratio
1005 );
1006 };
1007 }
1008
1009 #[macro_export]
1010 macro_rules! assert_fi_len {
1011 ($resampler:ident, $chunksize:expr) => {
1012 let nbr_frames_in_next = $resampler.input_frames_next();
1013 let nbr_frames_in_max = $resampler.input_frames_max();
1014 assert_eq!(
1015 nbr_frames_in_next, $chunksize,
1016 "expected {} for next input samples, got {}",
1017 $chunksize, nbr_frames_in_next
1018 );
1019 assert_eq!(
1020 nbr_frames_in_next, $chunksize,
1021 "expected {} for max input samples, got {}",
1022 $chunksize, nbr_frames_in_max
1023 );
1024 };
1025 }
1026
1027 #[macro_export]
1028 macro_rules! assert_fo_len {
1029 ($resampler:ident, $chunksize:expr) => {
1030 let nbr_frames_out_next = $resampler.output_frames_next();
1031 let nbr_frames_out_max = $resampler.output_frames_max();
1032 assert_eq!(
1033 nbr_frames_out_next, $chunksize,
1034 "expected {} for next output samples, got {}",
1035 $chunksize, nbr_frames_out_next
1036 );
1037 assert_eq!(
1038 nbr_frames_out_next, $chunksize,
1039 "expected {} for max output samples, got {}",
1040 $chunksize, nbr_frames_out_max
1041 );
1042 };
1043 }
1044
1045 #[macro_export]
1046 macro_rules! assert_fb_len {
1047 ($resampler:ident) => {
1048 let nbr_frames_out_next = $resampler.output_frames_next();
1049 let nbr_frames_out_max = $resampler.output_frames_max();
1050 let nbr_frames_in_next = $resampler.input_frames_next();
1051 let nbr_frames_in_max = $resampler.input_frames_max();
1052 let ratio = $resampler.resample_ratio();
1053 assert_eq!(
1054 nbr_frames_out_next, nbr_frames_out_max,
1055 "next output frames, {}, is different than max, {}",
1056 nbr_frames_out_next, nbr_frames_out_next
1057 );
1058 assert_eq!(
1059 nbr_frames_in_next, nbr_frames_in_max,
1060 "next input frames, {}, is different than max, {}",
1061 nbr_frames_in_next, nbr_frames_in_max
1062 );
1063 let frames_ratio = nbr_frames_out_next as f64 / nbr_frames_in_next as f64;
1064 assert_abs_diff_eq!(frames_ratio, ratio, epsilon = 0.000001);
1065 };
1066 }
1067
1068 #[macro_export]
1069 macro_rules! check_reset {
1070 ($resampler:ident) => {
1071 let frames_in = $resampler.input_frames_next();
1072
1073 let mut input_data = vec![vec![0.0f64; frames_in]; 2];
1074 input_data
1075 .iter_mut()
1076 .for_each(|ch| ch.iter_mut().for_each(|s| *s = rand::random()));
1077
1078 let input = SequentialSliceOfVecs::new(&input_data, 2, frames_in).unwrap();
1079
1080 let frames_out = $resampler.output_frames_next();
1081 let mut output_data_1 = vec![vec![0.0; frames_out]; 2];
1082 let mut output_1 =
1083 SequentialSliceOfVecs::new_mut(&mut output_data_1, 2, frames_out).unwrap();
1084 $resampler
1085 .process_into_buffer(&input, &mut output_1, None)
1086 .unwrap();
1087 $resampler.reset();
1088 assert_eq!(
1089 frames_in,
1090 $resampler.input_frames_next(),
1091 "Resampler requires different number of frames when new and after a reset."
1092 );
1093 let mut output_data_2 = vec![vec![0.0; frames_out]; 2];
1094 let mut output_2 =
1095 SequentialSliceOfVecs::new_mut(&mut output_data_2, 2, frames_out).unwrap();
1096 $resampler
1097 .process_into_buffer(&input, &mut output_2, None)
1098 .unwrap();
1099 assert_eq!(
1100 output_data_1, output_data_2,
1101 "Resampler gives different output when new and after a reset."
1102 );
1103 };
1104 }
1105
1106 #[macro_export]
1107 macro_rules! check_input_offset {
1108 ($resampler:ident) => {
1109 let frames_in = $resampler.input_frames_next();
1110
1111 let mut input_data_1 = vec![vec![0.0f64; frames_in]; 2];
1112 input_data_1
1113 .iter_mut()
1114 .for_each(|ch| ch.iter_mut().for_each(|s| *s = rand::random()));
1115
1116 let offset = 123;
1117 let mut input_data_2 = vec![vec![0.0f64; frames_in + offset]; 2];
1118 for (ch, data) in input_data_2.iter_mut().enumerate() {
1119 data[offset..offset + frames_in].clone_from_slice(&input_data_1[ch][..])
1120 }
1121
1122 let input_1 = SequentialSliceOfVecs::new(&input_data_1, 2, frames_in).unwrap();
1123 let input_2 = SequentialSliceOfVecs::new(&input_data_2, 2, frames_in + offset).unwrap();
1124
1125 let frames_out = $resampler.output_frames_next();
1126 let mut output_data_1 = vec![vec![0.0; frames_out]; 2];
1127 let mut output_1 =
1128 SequentialSliceOfVecs::new_mut(&mut output_data_1, 2, frames_out).unwrap();
1129 $resampler
1130 .process_into_buffer(&input_1, &mut output_1, None)
1131 .unwrap();
1132 $resampler.reset();
1133 assert_eq!(
1134 frames_in,
1135 $resampler.input_frames_next(),
1136 "Resampler requires different number of frames when new and after a reset."
1137 );
1138 let mut output_data_2 = vec![vec![0.0; frames_out]; 2];
1139 let mut output_2 =
1140 SequentialSliceOfVecs::new_mut(&mut output_data_2, 2, frames_out).unwrap();
1141
1142 let indexing = Indexing {
1143 input_offset: offset,
1144 output_offset: 0,
1145 active_channels_mask: None,
1146 partial_len: None,
1147 };
1148 $resampler
1149 .process_into_buffer(&input_2, &mut output_2, Some(&indexing))
1150 .unwrap();
1151 assert_eq!(
1152 output_data_1, output_data_2,
1153 "Resampler gives different output when new and after a reset."
1154 );
1155 };
1156 }
1157
1158 #[macro_export]
1159 macro_rules! check_output_offset {
1160 ($resampler:ident) => {
1161 let frames_in = $resampler.input_frames_next();
1162
1163 let mut input_data = vec![vec![0.0f64; frames_in]; 2];
1164 input_data
1165 .iter_mut()
1166 .for_each(|ch| ch.iter_mut().for_each(|s| *s = rand::random()));
1167
1168 let input = SequentialSliceOfVecs::new(&input_data, 2, frames_in).unwrap();
1169
1170 let frames_out = $resampler.output_frames_next();
1171 let mut output_data_1 = vec![vec![0.0; frames_out]; 2];
1172 let mut output_1 =
1173 SequentialSliceOfVecs::new_mut(&mut output_data_1, 2, frames_out).unwrap();
1174 $resampler
1175 .process_into_buffer(&input, &mut output_1, None)
1176 .unwrap();
1177 $resampler.reset();
1178 assert_eq!(
1179 frames_in,
1180 $resampler.input_frames_next(),
1181 "Resampler requires different number of frames when new and after a reset."
1182 );
1183 let offset = 123;
1184 let mut output_data_2 = vec![vec![0.0; frames_out + offset]; 2];
1185 let mut output_2 =
1186 SequentialSliceOfVecs::new_mut(&mut output_data_2, 2, frames_out + offset).unwrap();
1187 let indexing = Indexing {
1188 input_offset: 0,
1189 output_offset: offset,
1190 active_channels_mask: None,
1191 partial_len: None,
1192 };
1193 $resampler
1194 .process_into_buffer(&input, &mut output_2, Some(&indexing))
1195 .unwrap();
1196 assert_eq!(
1197 output_data_1[0][..],
1198 output_data_2[0][offset..],
1199 "Resampler gives different output when new and after a reset."
1200 );
1201 assert_eq!(
1202 output_data_1[1][..],
1203 output_data_2[1][offset..],
1204 "Resampler gives different output when new and after a reset."
1205 );
1206 };
1207 }
1208
1209 #[macro_export]
1210 macro_rules! check_masked {
1211 ($resampler:ident) => {
1212 let frames_in = $resampler.input_frames_next();
1213
1214 let mut input_data = vec![vec![0.0f64; frames_in]; 2];
1215 input_data
1216 .iter_mut()
1217 .for_each(|ch| ch.iter_mut().for_each(|s| *s = rand::random()));
1218
1219 let input = SequentialSliceOfVecs::new(&input_data, 2, frames_in).unwrap();
1220
1221 let frames_out = $resampler.output_frames_next();
1222 let mut output_data = vec![vec![0.0; frames_out]; 2];
1223 let mut output =
1224 SequentialSliceOfVecs::new_mut(&mut output_data, 2, frames_out).unwrap();
1225
1226 let indexing = Indexing {
1227 input_offset: 0,
1228 output_offset: 0,
1229 active_channels_mask: Some(vec![false, true]),
1230 partial_len: None,
1231 };
1232 $resampler
1233 .process_into_buffer(&input, &mut output, Some(&indexing))
1234 .unwrap();
1235
1236 let non_zero_chan_0 = output_data[0].iter().filter(|&v| *v != 0.0).count();
1237 let non_zero_chan_1 = output_data[1].iter().filter(|&v| *v != 0.0).count();
1238 assert_eq!(
1240 non_zero_chan_0, 0,
1241 "Some sample in the non-active channel has a non-zero value"
1242 );
1243 assert!(
1245 non_zero_chan_1 > 0,
1246 "No sample in the active channel has a non-zero value"
1247 );
1248 };
1249 }
1250
1251 #[macro_export]
1252 macro_rules! check_resize {
1253 ($resampler:ident) => {};
1254 }
1255}