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;
51#[cfg(feature = "fft_resampler")]
52mod synchro;
53mod windows;
54
55pub mod sinc_interpolator;
56
57pub use crate::asynchro::{Async, FixedAsync};
58pub use crate::asynchro_fast::PolynomialDegree;
59pub use crate::asynchro_sinc::{SincInterpolationParameters, SincInterpolationType};
60pub use crate::error::{
61 CpuFeature, MissingCpuFeature, ResampleError, ResampleResult, ResamplerConstructionError,
62};
63pub use crate::sample::Sample;
64#[cfg(feature = "fft_resampler")]
65pub use crate::synchro::{Fft, FixedSync};
66pub use crate::windows::{calculate_cutoff, WindowFunction};
67
68#[derive(Debug, Clone)]
74pub struct Indexing {
75 pub input_offset: usize,
79
80 pub output_offset: usize,
84
85 pub partial_len: Option<usize>,
99
100 pub active_channels_mask: Option<Vec<bool>>,
106}
107
108pub(crate) fn get_offsets(indexing: &Option<&Indexing>) -> (usize, usize) {
109 indexing
110 .as_ref()
111 .map(|idx| (idx.input_offset, idx.output_offset))
112 .unwrap_or((0, 0))
113}
114
115pub(crate) fn get_partial_len(indexing: &Option<&Indexing>) -> Option<usize> {
116 indexing.as_ref().and_then(|idx| idx.partial_len)
117}
118
119pub(crate) fn update_mask(indexing: &Option<&Indexing>, mask: &mut [bool]) {
121 if let Some(idx) = indexing {
122 if let Some(new_mask) = &idx.active_channels_mask {
123 mask.copy_from_slice(new_mask);
124 return;
125 }
126 }
127 mask.iter_mut().for_each(|v| *v = true);
128}
129
130pub trait Resampler<T>: Send
133where
134 T: Sample,
135{
136 fn process(
147 &mut self,
148 buffer_in: &dyn Adapter<'_, T>,
149 input_offset: usize,
150 active_channels_mask: Option<&[bool]>,
151 ) -> ResampleResult<InterleavedOwned<T>> {
152 let frames = self.output_frames_next();
153 let channels = self.nbr_channels();
154 let mut buffer_out = InterleavedOwned::<T>::new(T::coerce_from(0.0), channels, frames);
155
156 let indexing = Indexing {
157 input_offset,
158 output_offset: 0,
159 partial_len: None,
160 active_channels_mask: active_channels_mask.map(|m| m.to_vec()),
161 };
162 self.process_into_buffer(buffer_in, &mut buffer_out, Some(&indexing))?;
163 Ok(buffer_out)
164 }
165
166 fn process_into_buffer<'a, 'b>(
198 &mut self,
199 buffer_in: &dyn Adapter<'a, T>,
200 buffer_out: &mut dyn AdapterMut<'b, T>,
201 indexing: Option<&Indexing>,
202 ) -> ResampleResult<(usize, usize)>;
203
204 fn process_all_into_buffer<'a, 'b>(
220 &mut self,
221 buffer_in: &dyn Adapter<'a, T>,
222 buffer_out: &mut dyn AdapterMut<'b, T>,
223 input_len: usize,
224 active_channels_mask: Option<&[bool]>,
225 ) -> ResampleResult<(usize, usize)> {
226 let expected_output_len = (self.resample_ratio() * input_len as f64).ceil() as usize;
227
228 let mut indexing = Indexing {
229 input_offset: 0,
230 output_offset: 0,
231 active_channels_mask: active_channels_mask.map(|m| m.to_vec()),
232 partial_len: None,
233 };
234
235 let mut frames_left = input_len;
236 let mut output_len = 0;
237 let mut frames_to_trim = self.output_delay();
238 debug!(
239 "resamping {} input frames to {} output frames, delay to trim off {} frames",
240 input_len, expected_output_len, frames_to_trim
241 );
242
243 let next_nbr_input_frames = self.input_frames_next();
244 while frames_left > next_nbr_input_frames {
245 debug!("process, {} input frames left", frames_left);
246 let (nbr_in, nbr_out) =
247 self.process_into_buffer(buffer_in, buffer_out, Some(&indexing))?;
248 frames_left -= nbr_in;
249 output_len += nbr_out;
250 indexing.input_offset += nbr_in;
251 indexing.output_offset += nbr_out;
252 if frames_to_trim > 0 && output_len > frames_to_trim {
253 debug!(
254 "output, {} is longer than delay to trim, {}, trimming..",
255 output_len, frames_to_trim
256 );
257 buffer_out.copy_frames_within(frames_to_trim, 0, frames_to_trim);
259 output_len -= frames_to_trim;
261 indexing.output_offset -= frames_to_trim;
262 frames_to_trim = 0;
263 }
264 }
265 if frames_left > 0 {
266 debug!("process the last partial chunk, len {}", frames_left);
267 indexing.partial_len = Some(frames_left);
268 let (_nbr_in, nbr_out) =
269 self.process_into_buffer(buffer_in, buffer_out, Some(&indexing))?;
270 output_len += nbr_out;
271 indexing.output_offset += nbr_out;
272 }
273 indexing.partial_len = Some(0);
274 while output_len < expected_output_len {
275 debug!(
276 "output is still too short, {} < {}, pump zeros..",
277 output_len, expected_output_len
278 );
279 let (_nbr_in, nbr_out) =
280 self.process_into_buffer(buffer_in, buffer_out, Some(&indexing))?;
281 output_len += nbr_out;
282 indexing.output_offset += nbr_out;
283 }
284 Ok((input_len, expected_output_len))
285 }
286
287 fn process_all_needed_output_len(&mut self, input_len: usize) -> usize {
295 let delay_frames = self.output_delay();
296 let output_frames_max = self.output_frames_max();
297 let expected_output_len = (self.resample_ratio() * input_len as f64).ceil() as usize;
298 delay_frames + output_frames_max + expected_output_len
299 }
300
301 fn input_frames_max(&self) -> usize;
303
304 fn input_frames_next(&self) -> usize;
307
308 fn nbr_channels(&self) -> usize;
310
311 fn output_frames_max(&self) -> usize;
313
314 fn output_frames_next(&self) -> usize;
317
318 fn output_delay(&self) -> usize;
321
322 fn set_resample_ratio(&mut self, new_ratio: f64, ramp: bool) -> ResampleResult<()>;
336
337 fn resample_ratio(&self) -> f64;
339
340 fn set_resample_ratio_relative(&mut self, rel_ratio: f64, ramp: bool) -> ResampleResult<()>;
353
354 fn reset(&mut self);
356
357 fn set_chunk_size(&mut self, _chunksize: usize) -> ResampleResult<()> {
370 Err(ResampleError::ChunkSizeNotAdjustable)
371 }
372}
373
374pub(crate) fn validate_buffers<'a, 'b, T: 'a + 'b>(
375 wave_in: &dyn Adapter<'a, T>,
376 wave_out: &dyn AdapterMut<'b, T>,
377 mask: &[bool],
378 channels: usize,
379 min_input_len: usize,
380 min_output_len: usize,
381) -> ResampleResult<()> {
382 if wave_in.channels() != channels {
383 return Err(ResampleError::WrongNumberOfInputChannels {
384 expected: channels,
385 actual: wave_in.channels(),
386 });
387 }
388 if mask.len() != channels {
389 return Err(ResampleError::WrongNumberOfMaskChannels {
390 expected: channels,
391 actual: mask.len(),
392 });
393 }
394 if wave_in.frames() < min_input_len {
395 return Err(ResampleError::InsufficientInputBufferSize {
396 expected: min_input_len,
397 actual: wave_in.frames(),
398 });
399 }
400 if wave_out.channels() != channels {
401 return Err(ResampleError::WrongNumberOfOutputChannels {
402 expected: channels,
403 actual: wave_out.channels(),
404 });
405 }
406 if wave_out.frames() < min_output_len {
407 return Err(ResampleError::InsufficientOutputBufferSize {
408 expected: min_output_len,
409 actual: wave_out.frames(),
410 });
411 }
412 Ok(())
413}
414
415#[cfg(test)]
416pub mod tests {
417 #[cfg(feature = "fft_resampler")]
418 use crate::Fft;
419 use crate::Resampler;
420 use crate::{
421 Async, FixedAsync, SincInterpolationParameters, SincInterpolationType, WindowFunction,
422 };
423 use audioadapter::Adapter;
424 use audioadapter_buffers::direct::SequentialSliceOfVecs;
425
426 #[test_log::test]
427 fn process_all() {
428 let mut resampler = Async::<f64>::new_sinc(
429 88200.0 / 44100.0,
430 1.1,
431 &SincInterpolationParameters {
432 sinc_len: 64,
433 f_cutoff: 0.95,
434 interpolation: SincInterpolationType::Cubic,
435 oversampling_factor: 16,
436 window: WindowFunction::BlackmanHarris2,
437 },
438 1024,
439 2,
440 FixedAsync::Input,
441 )
442 .unwrap();
443 let input_len = 12345;
444 let samples: Vec<f64> = (0..input_len).map(|v| v as f64 / 10.0).collect();
445 let input_data = vec![samples; 2];
446 let input = SequentialSliceOfVecs::new(&input_data, 2, input_len).unwrap();
448 let output_len = resampler.process_all_needed_output_len(input_len);
449 let mut output_data = vec![vec![0.0f64; output_len]; 2];
450 let mut output = SequentialSliceOfVecs::new_mut(&mut output_data, 2, output_len).unwrap();
451 let (nbr_in, nbr_out) = resampler
452 .process_all_into_buffer(&input, &mut output, input_len, None)
453 .unwrap();
454 assert_eq!(nbr_in, input_len);
455 assert_eq!(2 * nbr_in, nbr_out);
457
458 let increment = 0.1 / resampler.resample_ratio();
460 let delay = resampler.output_delay();
461 let margin = (delay as f64 * resampler.resample_ratio()) as usize;
462 let mut expected = margin as f64 * increment;
463 for frame in margin..(nbr_out - margin) {
464 for chan in 0..2 {
465 let val = output.read_sample(chan, frame).unwrap();
466 assert!(
467 val - expected < 100.0 * increment,
468 "frame: {}, value: {}, expected: {}",
469 frame,
470 val,
471 expected
472 );
473 assert!(
474 expected - val < 100.0 * increment,
475 "frame: {}, value: {}, expected: {}",
476 frame,
477 val,
478 expected
479 );
480 }
481 expected += increment;
482 }
483 }
484
485 #[test_log::test]
487 fn boxed_resampler() {
488 let mut boxed: Box<dyn Resampler<f64>> = Box::new(
489 Async::<f64>::new_sinc(
490 88200.0 / 44100.0,
491 1.1,
492 &SincInterpolationParameters {
493 sinc_len: 64,
494 f_cutoff: 0.95,
495 interpolation: SincInterpolationType::Cubic,
496 oversampling_factor: 16,
497 window: WindowFunction::BlackmanHarris2,
498 },
499 1024,
500 2,
501 FixedAsync::Input,
502 )
503 .unwrap(),
504 );
505 let max_frames_out = boxed.output_frames_max();
506 let nbr_frames_in_next = boxed.input_frames_next();
507 let waves = vec![vec![0.0f64; nbr_frames_in_next]; 2];
508 let mut waves_out = vec![vec![0.0f64; max_frames_out]; 2];
509 let input = SequentialSliceOfVecs::new(&waves, 2, nbr_frames_in_next).unwrap();
510 let mut output = SequentialSliceOfVecs::new_mut(&mut waves_out, 2, max_frames_out).unwrap();
511 process_with_boxed(&mut boxed, &input, &mut output);
512 }
513
514 fn process_with_boxed<'a>(
515 resampler: &mut Box<dyn Resampler<f64>>,
516 input: &SequentialSliceOfVecs<&'a [Vec<f64>]>,
517 output: &mut SequentialSliceOfVecs<&'a mut [Vec<f64>]>,
518 ) {
519 resampler.process_into_buffer(input, output, None).unwrap();
520 }
521
522 fn impl_send<T: Send>() {
523 fn is_send<T: Send>() {}
524 is_send::<Async<T>>();
525 #[cfg(feature = "fft_resampler")]
526 {
527 is_send::<Fft<T>>();
528 }
529 }
530
531 #[test]
533 fn test_impl_send() {
534 impl_send::<f32>();
535 impl_send::<f64>();
536 }
537
538 pub fn expected_output_value(idx: usize, delay: usize, ratio: f64) -> f64 {
539 if idx <= delay {
540 return 0.0;
541 }
542 (idx - delay) as f64 * 0.1 / ratio
543 }
544
545 #[macro_export]
546 macro_rules! check_output {
547 ($resampler:ident, $fty:ty) => {
548 let mut ramp_value: $fty = 0.0;
549 let max_input_len = $resampler.input_frames_max();
550 let max_output_len = $resampler.output_frames_max();
551 let ratio = $resampler.resample_ratio() as $fty;
552 let delay = $resampler.output_delay();
553 let mut output_index = 0;
554
555 let out_incr = 0.1 / ratio;
556
557 let nbr_iterations =
558 100000 / ($resampler.output_frames_next() + $resampler.input_frames_next());
559 for _n in 0..nbr_iterations {
560 let expected_frames_in = $resampler.input_frames_next();
561 let expected_frames_out = $resampler.output_frames_next();
562 assert!(expected_frames_in <= max_input_len);
564 assert!(expected_frames_out <= max_output_len);
565 let mut input_data = vec![vec![0.0 as $fty; expected_frames_in]; 2];
566 for m in 0..expected_frames_in {
567 for ch in 0..2 {
568 input_data[ch][m] = ramp_value;
569 }
570 ramp_value += 0.1;
571 }
572 let input = SequentialSliceOfVecs::new(&input_data, 2, expected_frames_in).unwrap();
573 let mut output_data = vec![vec![0.0 as $fty; expected_frames_out]; 2];
574 let mut output =
575 SequentialSliceOfVecs::new_mut(&mut output_data, 2, expected_frames_out)
576 .unwrap();
577
578 trace!("resample...");
579 let (input_frames, output_frames) = $resampler
580 .process_into_buffer(&input, &mut output, None)
581 .unwrap();
582 trace!("assert lengths");
583 assert_eq!(input_frames, expected_frames_in);
584 assert_eq!(output_frames, expected_frames_out);
585 trace!("check output");
586 for idx in 0..output_frames {
587 let expected = expected_output_value(output_index + idx, delay, ratio) as $fty;
588 for ch in 0..2 {
589 let value = output_data[ch][idx];
590 let margin = 3.0 * out_incr;
591 assert!(
592 value > expected - margin,
593 "Value at frame {} is too small, {} < {} - {}",
594 output_index + idx,
595 value,
596 expected,
597 margin
598 );
599 assert!(
600 value < expected + margin,
601 "Value at frame {} is too large, {} > {} + {}",
602 output_index + idx,
603 value,
604 expected,
605 margin
606 );
607 }
608 }
609 output_index += output_frames;
610 }
611 assert!(output_index > 1000, "Too few frames checked!");
612 };
613 }
614
615 #[macro_export]
616 macro_rules! check_ratio {
617 ($resampler:ident, $repetitions:expr, $margin:expr, $fty:ty) => {
618 let ratio = $resampler.resample_ratio();
619 let max_input_len = $resampler.input_frames_max();
620 let max_output_len = $resampler.output_frames_max();
621 let waves_in = vec![vec![0.0 as $fty; max_input_len]; 2];
622 let input = SequentialSliceOfVecs::new(&waves_in, 2, max_input_len).unwrap();
623 let mut waves_out = vec![vec![0.0 as $fty; max_output_len]; 2];
624 let mut output =
625 SequentialSliceOfVecs::new_mut(&mut waves_out, 2, max_output_len).unwrap();
626 let mut total_in = 0;
627 let mut total_out = 0;
628 for _ in 0..$repetitions {
629 let out = $resampler
630 .process_into_buffer(&input, &mut output, None)
631 .unwrap();
632 total_in += out.0;
633 total_out += out.1
634 }
635 let measured_ratio = total_out as f64 / total_in as f64;
636 assert!(
637 measured_ratio / ratio > (1.0 - $margin),
638 "Measured ratio is too small, measured / expected = {}",
639 measured_ratio / ratio
640 );
641 assert!(
642 measured_ratio / ratio < (1.0 + $margin),
643 "Measured ratio is too large, measured / expected = {}",
644 measured_ratio / ratio
645 );
646 };
647 }
648
649 #[macro_export]
650 macro_rules! assert_fi_len {
651 ($resampler:ident, $chunksize:expr) => {
652 let nbr_frames_in_next = $resampler.input_frames_next();
653 let nbr_frames_in_max = $resampler.input_frames_max();
654 assert_eq!(
655 nbr_frames_in_next, $chunksize,
656 "expected {} for next input samples, got {}",
657 $chunksize, nbr_frames_in_next
658 );
659 assert_eq!(
660 nbr_frames_in_next, $chunksize,
661 "expected {} for max input samples, got {}",
662 $chunksize, nbr_frames_in_max
663 );
664 };
665 }
666
667 #[macro_export]
668 macro_rules! assert_fo_len {
669 ($resampler:ident, $chunksize:expr) => {
670 let nbr_frames_out_next = $resampler.output_frames_next();
671 let nbr_frames_out_max = $resampler.output_frames_max();
672 assert_eq!(
673 nbr_frames_out_next, $chunksize,
674 "expected {} for next output samples, got {}",
675 $chunksize, nbr_frames_out_next
676 );
677 assert_eq!(
678 nbr_frames_out_next, $chunksize,
679 "expected {} for max output samples, got {}",
680 $chunksize, nbr_frames_out_max
681 );
682 };
683 }
684
685 #[macro_export]
686 macro_rules! assert_fb_len {
687 ($resampler:ident) => {
688 let nbr_frames_out_next = $resampler.output_frames_next();
689 let nbr_frames_out_max = $resampler.output_frames_max();
690 let nbr_frames_in_next = $resampler.input_frames_next();
691 let nbr_frames_in_max = $resampler.input_frames_max();
692 let ratio = $resampler.resample_ratio();
693 assert_eq!(
694 nbr_frames_out_next, nbr_frames_out_max,
695 "next output frames, {}, is different than max, {}",
696 nbr_frames_out_next, nbr_frames_out_next
697 );
698 assert_eq!(
699 nbr_frames_in_next, nbr_frames_in_max,
700 "next input frames, {}, is different than max, {}",
701 nbr_frames_in_next, nbr_frames_in_max
702 );
703 let frames_ratio = nbr_frames_out_next as f64 / nbr_frames_in_next as f64;
704 assert_abs_diff_eq!(frames_ratio, ratio, epsilon = 0.000001);
705 };
706 }
707
708 #[macro_export]
709 macro_rules! check_reset {
710 ($resampler:ident) => {
711 let frames_in = $resampler.input_frames_next();
712
713 let mut input_data = vec![vec![0.0f64; frames_in]; 2];
714 input_data
715 .iter_mut()
716 .for_each(|ch| ch.iter_mut().for_each(|s| *s = rand::random()));
717
718 let input = SequentialSliceOfVecs::new(&input_data, 2, frames_in).unwrap();
719
720 let frames_out = $resampler.output_frames_next();
721 let mut output_data_1 = vec![vec![0.0; frames_out]; 2];
722 let mut output_1 =
723 SequentialSliceOfVecs::new_mut(&mut output_data_1, 2, frames_out).unwrap();
724 $resampler
725 .process_into_buffer(&input, &mut output_1, None)
726 .unwrap();
727 $resampler.reset();
728 assert_eq!(
729 frames_in,
730 $resampler.input_frames_next(),
731 "Resampler requires different number of frames when new and after a reset."
732 );
733 let mut output_data_2 = vec![vec![0.0; frames_out]; 2];
734 let mut output_2 =
735 SequentialSliceOfVecs::new_mut(&mut output_data_2, 2, frames_out).unwrap();
736 $resampler
737 .process_into_buffer(&input, &mut output_2, None)
738 .unwrap();
739 assert_eq!(
740 output_data_1, output_data_2,
741 "Resampler gives different output when new and after a reset."
742 );
743 };
744 }
745
746 #[macro_export]
747 macro_rules! check_input_offset {
748 ($resampler:ident) => {
749 let frames_in = $resampler.input_frames_next();
750
751 let mut input_data_1 = vec![vec![0.0f64; frames_in]; 2];
752 input_data_1
753 .iter_mut()
754 .for_each(|ch| ch.iter_mut().for_each(|s| *s = rand::random()));
755
756 let offset = 123;
757 let mut input_data_2 = vec![vec![0.0f64; frames_in + offset]; 2];
758 for (ch, data) in input_data_2.iter_mut().enumerate() {
759 data[offset..offset + frames_in].clone_from_slice(&input_data_1[ch][..])
760 }
761
762 let input_1 = SequentialSliceOfVecs::new(&input_data_1, 2, frames_in).unwrap();
763 let input_2 = SequentialSliceOfVecs::new(&input_data_2, 2, frames_in + offset).unwrap();
764
765 let frames_out = $resampler.output_frames_next();
766 let mut output_data_1 = vec![vec![0.0; frames_out]; 2];
767 let mut output_1 =
768 SequentialSliceOfVecs::new_mut(&mut output_data_1, 2, frames_out).unwrap();
769 $resampler
770 .process_into_buffer(&input_1, &mut output_1, None)
771 .unwrap();
772 $resampler.reset();
773 assert_eq!(
774 frames_in,
775 $resampler.input_frames_next(),
776 "Resampler requires different number of frames when new and after a reset."
777 );
778 let mut output_data_2 = vec![vec![0.0; frames_out]; 2];
779 let mut output_2 =
780 SequentialSliceOfVecs::new_mut(&mut output_data_2, 2, frames_out).unwrap();
781
782 let indexing = Indexing {
783 input_offset: offset,
784 output_offset: 0,
785 active_channels_mask: None,
786 partial_len: None,
787 };
788 $resampler
789 .process_into_buffer(&input_2, &mut output_2, Some(&indexing))
790 .unwrap();
791 assert_eq!(
792 output_data_1, output_data_2,
793 "Resampler gives different output when new and after a reset."
794 );
795 };
796 }
797
798 #[macro_export]
799 macro_rules! check_output_offset {
800 ($resampler:ident) => {
801 let frames_in = $resampler.input_frames_next();
802
803 let mut input_data = vec![vec![0.0f64; frames_in]; 2];
804 input_data
805 .iter_mut()
806 .for_each(|ch| ch.iter_mut().for_each(|s| *s = rand::random()));
807
808 let input = SequentialSliceOfVecs::new(&input_data, 2, frames_in).unwrap();
809
810 let frames_out = $resampler.output_frames_next();
811 let mut output_data_1 = vec![vec![0.0; frames_out]; 2];
812 let mut output_1 =
813 SequentialSliceOfVecs::new_mut(&mut output_data_1, 2, frames_out).unwrap();
814 $resampler
815 .process_into_buffer(&input, &mut output_1, None)
816 .unwrap();
817 $resampler.reset();
818 assert_eq!(
819 frames_in,
820 $resampler.input_frames_next(),
821 "Resampler requires different number of frames when new and after a reset."
822 );
823 let offset = 123;
824 let mut output_data_2 = vec![vec![0.0; frames_out + offset]; 2];
825 let mut output_2 =
826 SequentialSliceOfVecs::new_mut(&mut output_data_2, 2, frames_out + offset).unwrap();
827 let indexing = Indexing {
828 input_offset: 0,
829 output_offset: offset,
830 active_channels_mask: None,
831 partial_len: None,
832 };
833 $resampler
834 .process_into_buffer(&input, &mut output_2, Some(&indexing))
835 .unwrap();
836 assert_eq!(
837 output_data_1[0][..],
838 output_data_2[0][offset..],
839 "Resampler gives different output when new and after a reset."
840 );
841 assert_eq!(
842 output_data_1[1][..],
843 output_data_2[1][offset..],
844 "Resampler gives different output when new and after a reset."
845 );
846 };
847 }
848
849 #[macro_export]
850 macro_rules! check_masked {
851 ($resampler:ident) => {
852 let frames_in = $resampler.input_frames_next();
853
854 let mut input_data = vec![vec![0.0f64; frames_in]; 2];
855 input_data
856 .iter_mut()
857 .for_each(|ch| ch.iter_mut().for_each(|s| *s = rand::random()));
858
859 let input = SequentialSliceOfVecs::new(&input_data, 2, frames_in).unwrap();
860
861 let frames_out = $resampler.output_frames_next();
862 let mut output_data = vec![vec![0.0; frames_out]; 2];
863 let mut output =
864 SequentialSliceOfVecs::new_mut(&mut output_data, 2, frames_out).unwrap();
865
866 let indexing = Indexing {
867 input_offset: 0,
868 output_offset: 0,
869 active_channels_mask: Some(vec![false, true]),
870 partial_len: None,
871 };
872 $resampler
873 .process_into_buffer(&input, &mut output, Some(&indexing))
874 .unwrap();
875
876 let non_zero_chan_0 = output_data[0].iter().filter(|&v| *v != 0.0).count();
877 let non_zero_chan_1 = output_data[1].iter().filter(|&v| *v != 0.0).count();
878 assert_eq!(
880 non_zero_chan_0, 0,
881 "Some sample in the non-active channel has a non-zero value"
882 );
883 assert!(
885 non_zero_chan_1 > 0,
886 "No sample in the active channel has a non-zero value"
887 );
888 };
889 }
890
891 #[macro_export]
892 macro_rules! check_resize {
893 ($resampler:ident) => {};
894 }
895}