From 40c78c503b719e36e146de140bf9216c28d0a18e Mon Sep 17 00:00:00 2001 From: Dario Bartussek Date: Mon, 12 Sep 2022 01:10:15 +0200 Subject: [PATCH 1/2] Fixed ChannelVolume size_hint and added tests --- src/source/channel_volume.rs | 64 +++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/src/source/channel_volume.rs b/src/source/channel_volume.rs index 69dc869e..5eb92bd8 100644 --- a/src/source/channel_volume.rs +++ b/src/source/channel_volume.rs @@ -103,7 +103,25 @@ where #[inline] fn size_hint(&self) -> (usize, Option) { - self.input.size_hint() + let map_size_hint = |input_hint: usize| -> usize { + // The input source provides a number of samples (input_hint / channels); + // We return 1 item per channel per sample => * channel_volumes + let input_provides = + input_hint / (self.input.channels() as usize) * self.channel_volumes.len(); + + // In addition, we may be in the process of emitting additional values from + // self.current_sample + let current_sample = if self.current_sample.is_some() { + self.channel_volumes.len() - self.current_channel + } else { + 0 + }; + + input_provides + current_sample + }; + + let (min, max) = self.input.size_hint(); + (map_size_hint(min), max.map(map_size_hint)) } } @@ -139,3 +157,47 @@ where self.input.total_duration() } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::buffer::SamplesBuffer; + + const SAMPLES: usize = 100; + + fn dummysource(channels: usize) -> SamplesBuffer { + let data: Vec = (1..=(SAMPLES * channels)).map(|v| v as f32).collect(); + SamplesBuffer::new(channels as _, 1, data) + } + + fn make_test(channels_source: usize, channels_result: usize) { + let original = dummysource(channels_source); + assert_eq!(original.size_hint().0, SAMPLES * channels_source); + + let mono = ChannelVolume::new(original, vec![1.0; channels_result]); + + let (hint_min, hint_max) = mono.size_hint(); + assert_eq!(Some(hint_min), hint_max); + + let actual_size = mono.count(); + assert_eq!(hint_min, actual_size); + } + + #[test] + fn size_stereo_mono() { + make_test(2, 1); + } + #[test] + fn size_mono_stereo() { + make_test(1, 2); + } + + #[test] + fn size_stereo_eight() { + make_test(2, 8); + } + #[test] + fn size_stereo_five() { + make_test(2, 5); + } +} From 44f72e33bbe486070534ba3ff29d97830a0996cd Mon Sep 17 00:00:00 2001 From: Dario Bartussek Date: Fri, 16 Sep 2022 01:38:49 +0200 Subject: [PATCH 2/2] ChannelVolume now returns the correct size_hint even if its input yields an odd number of results --- src/source/channel_volume.rs | 64 ++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/src/source/channel_volume.rs b/src/source/channel_volume.rs index 5eb92bd8..995769c0 100644 --- a/src/source/channel_volume.rs +++ b/src/source/channel_volume.rs @@ -104,10 +104,17 @@ where #[inline] fn size_hint(&self) -> (usize, Option) { let map_size_hint = |input_hint: usize| -> usize { - // The input source provides a number of samples (input_hint / channels); + // The input source provides a number of samples ceil(input_hint / channels); // We return 1 item per channel per sample => * channel_volumes - let input_provides = - input_hint / (self.input.channels() as usize) * self.channel_volumes.len(); + let input_channels = self.input.channels() as usize; + let input_chunks = (input_hint / input_channels) + + if input_hint % input_channels != 0 { + 1 + } else { + 0 + }; + + let input_provides = input_chunks * self.channel_volumes.len(); // In addition, we may be in the process of emitting additional values from // self.current_sample @@ -163,16 +170,14 @@ mod tests { use super::*; use crate::buffer::SamplesBuffer; - const SAMPLES: usize = 100; - - fn dummysource(channels: usize) -> SamplesBuffer { - let data: Vec = (1..=(SAMPLES * channels)).map(|v| v as f32).collect(); + fn dummysource(samples: usize, channels: usize) -> SamplesBuffer { + let data: Vec = (1..=(samples * channels)).map(|v| v as f32).collect(); SamplesBuffer::new(channels as _, 1, data) } - fn make_test(channels_source: usize, channels_result: usize) { - let original = dummysource(channels_source); - assert_eq!(original.size_hint().0, SAMPLES * channels_source); + fn make_test(samples: usize, channels_source: usize, channels_result: usize) { + let original = dummysource(samples, channels_source); + assert_eq!(original.size_hint().0, samples * channels_source); let mono = ChannelVolume::new(original, vec![1.0; channels_result]); @@ -185,19 +190,50 @@ mod tests { #[test] fn size_stereo_mono() { - make_test(2, 1); + make_test(100, 2, 1); + } + #[test] + fn size_stereo_mono_offset() { + make_test(101, 2, 1); } #[test] fn size_mono_stereo() { - make_test(1, 2); + make_test(100, 1, 2); } #[test] fn size_stereo_eight() { - make_test(2, 8); + make_test(100, 2, 8); + } + #[test] + fn size_stereo_eight_offset() { + make_test(101, 2, 8); } + #[test] fn size_stereo_five() { - make_test(2, 5); + make_test(100, 2, 5); + } + #[test] + fn size_stereo_five_offset() { + make_test(101, 2, 5); + } + + #[test] + fn size_eight_stereo() { + make_test(100 * 8, 8, 2); + } + #[test] + fn size_eight_stereo_offset() { + make_test(100 * 8 + 1, 8, 2); + } + + #[test] + fn size_five_stereo() { + make_test(100, 5, 2); + } + #[test] + fn size_five_stereo_offset() { + make_test(101, 5, 2); } }