From a1608e55c212f93f41098ddf50d85fc3621a1073 Mon Sep 17 00:00:00 2001 From: Be Date: Sun, 11 Dec 2022 15:00:50 -0600 Subject: [PATCH] WIP use audio crate's traits for generic input & output buffers Fixes #51 --- Cargo.toml | 1 + src/asynchro_fast.rs | 367 ++++++++++++++++++++++--------------------- src/asynchro_sinc.rs | 42 ++--- src/error.rs | 12 +- src/lib.rs | 207 +++++++++++------------- src/sample.rs | 3 +- 6 files changed, 309 insertions(+), 323 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4c819b7..07f606a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +audio = { git = "https://github.com/Be-ing/audio.git", branch = "range" } log = { version = "0.4.14", optional = true } realfft = "3.1.0" num-complex = "0.4" diff --git a/src/asynchro_fast.rs b/src/asynchro_fast.rs index 8b3aca1..f21a5d7 100644 --- a/src/asynchro_fast.rs +++ b/src/asynchro_fast.rs @@ -1,6 +1,8 @@ use crate::error::{ResampleError, ResampleResult, ResamplerConstructionError}; use crate::{update_mask_from_buffers, validate_buffers, Resampler, Sample}; +use audio::{buf::Sequential as SequentialBuffer, BufMut, Channel, ChannelMut, ExactSizeBuf}; + const POLYNOMIAL_LEN_U: usize = 8; const POLYNOMIAL_LEN_I: isize = 8; @@ -48,7 +50,7 @@ pub struct FastFixedIn { resample_ratio_original: f64, target_ratio: f64, max_relative_ratio: f64, - buffer: Vec>, + buffer: SequentialBuffer, interpolation: PolynomialDegree, channel_mask: Vec, } @@ -78,25 +80,25 @@ pub struct FastFixedOut { resample_ratio_original: f64, target_ratio: f64, max_relative_ratio: f64, - buffer: Vec>, + buffer: SequentialBuffer, interpolation: PolynomialDegree, channel_mask: Vec, } /// Perform septic polynomial interpolation to get value at x. /// Input points are assumed to be at x = -3, -2, -1, 0, 1, 2, 3, 4 -fn interp_septic(x: T, yvals: &[T]) -> T +fn interp_septic(x: T, yvals: &impl Channel) -> T where T: Sample, { - let a = yvals[0]; - let b = yvals[1]; - let c = yvals[2]; - let d = yvals[3]; - let e = yvals[4]; - let f = yvals[5]; - let g = yvals[6]; - let h = yvals[7]; + let a = yvals.get(0).unwrap(); + let b = yvals.get(1).unwrap(); + let c = yvals.get(2).unwrap(); + let d = yvals.get(3).unwrap(); + let e = yvals.get(4).unwrap(); + let f = yvals.get(5).unwrap(); + let g = yvals.get(6).unwrap(); + let h = yvals.get(7).unwrap(); let k7 = -a + t!(7.0) * b - t!(21.0) * c + t!(35.0) * d - t!(35.0) * e + t!(21.0) * f - t!(7.0) * g + h; @@ -134,16 +136,16 @@ where /// Perform quintic polynomial interpolation to get value at x. /// Input points are assumed to be at x = -2, -1, 0, 1, 2, 3 -fn interp_quintic(x: T, yvals: &[T]) -> T +fn interp_quintic(x: T, yvals: &impl Channel) -> T where T: Sample, { - let a = yvals[0]; - let b = yvals[1]; - let c = yvals[2]; - let d = yvals[3]; - let e = yvals[4]; - let f = yvals[5]; + let a = yvals.get(0).unwrap(); + let b = yvals.get(1).unwrap(); + let c = yvals.get(2).unwrap(); + let d = yvals.get(3).unwrap(); + let e = yvals.get(4).unwrap(); + let f = yvals.get(5).unwrap(); let k5 = -a + t!(5.0) * b - t!(10.0) * c + t!(10.0) * d - t!(5.0) * e + f; let k4 = t!(5.0) * a - t!(20.0) * b + t!(30.0) * c - t!(20.0) * d + t!(5.0) * e; let k3 = -t!(5.0) * a - t!(5.0) * b + t!(50.0) * c - t!(70.0) * d + t!(35.0) * e - t!(5.0) * f; @@ -160,25 +162,25 @@ where /// Perform cubic polynomial interpolation to get value at x. /// Input points are assumed to be at x = -1, 0, 1, 2 -fn interp_cubic(x: T, yvals: &[T]) -> T +fn interp_cubic(x: T, yvals: &impl Channel) -> T where T: Sample, { - let a0 = yvals[1]; - let a1 = -t!(1.0 / 3.0) * yvals[0] - t!(0.5) * yvals[1] + yvals[2] - t!(1.0 / 6.0) * yvals[3]; - let a2 = t!(0.5) * (yvals[0] + yvals[2]) - yvals[1]; - let a3 = t!(0.5) * (yvals[1] - yvals[2]) + t!(1.0 / 6.0) * (yvals[3] - yvals[0]); + let a0 = yvals.get(1).unwrap(); + let a1 = -t!(1.0 / 3.0) * yvals.get(0).unwrap() - t!(0.5) * yvals.get(1).unwrap() + yvals.get(2).unwrap() - t!(1.0 / 6.0) * yvals.get(3).unwrap(); + let a2 = t!(0.5) * (yvals.get(0).unwrap() + yvals.get(2).unwrap()) - yvals.get(1).unwrap(); + let a3 = t!(0.5) * (yvals.get(1).unwrap() - yvals.get(2).unwrap()) + t!(1.0 / 6.0) * (yvals.get(3).unwrap() - yvals.get(0).unwrap()); let x2 = x * x; let x3 = x2 * x; a0 + a1 * x + a2 * x2 + a3 * x3 } /// Linear interpolation between two points at x=0 and x=1 -fn interp_lin(x: T, yvals: &[T]) -> T +fn interp_lin(x: T, yvals: &impl Channel) -> T where T: Sample, { - yvals[0] + x * (yvals[1] - yvals[0]) + yvals.get(0).unwrap() + x * (yvals.get(1).unwrap() - yvals.get(0).unwrap()) } fn validate_ratios( @@ -222,7 +224,8 @@ where validate_ratios(resample_ratio, max_resample_ratio_relative)?; - let buffer = vec![vec![T::zero(); chunk_size + 2 * POLYNOMIAL_LEN_U]; nbr_channels]; + let buffer = + SequentialBuffer::with_topology(nbr_channels, chunk_size + 2 * POLYNOMIAL_LEN_U); let channel_mask = vec![true; nbr_channels]; @@ -245,12 +248,16 @@ impl Resampler for FastFixedIn where T: Sample, { - fn process_into_buffer, Vout: AsMut<[T]>>( + fn process_into_buffer( &mut self, - wave_in: &[Vin], - wave_out: &mut [Vout], + wave_in: &In, + wave_out: &mut Out, active_channels_mask: Option<&[bool]>, - ) -> ResampleResult<(usize, usize)> { + ) -> ResampleResult<(usize, usize)> + where + In: ExactSizeBuf, + Out: ExactSizeBuf + BufMut, + { if let Some(mask) = active_channels_mask { self.channel_mask.copy_from_slice(mask); } else { @@ -272,14 +279,23 @@ where )?; //update buffer with new data - for buf in self.buffer.iter_mut() { - buf.copy_within(self.chunk_size..self.chunk_size + 2 * POLYNOMIAL_LEN_U, 0); + for buf in self.buffer.iter_channels_mut() { + buf.as_mut() + .copy_within(self.chunk_size..self.chunk_size + 2 * POLYNOMIAL_LEN_U, 0); } - for (chan, active) in self.channel_mask.iter().enumerate() { - if *active { - self.buffer[chan][2 * POLYNOMIAL_LEN_U..2 * POLYNOMIAL_LEN_U + self.chunk_size] - .copy_from_slice(&wave_in[chan].as_ref()[..self.chunk_size]); + for ((buffer_channel, input_channel), active) in self + .buffer + .iter_channels_mut() + .zip(wave_in.iter_channels()) + .zip(self.channel_mask) + { + if active { + audio::channel::copy( + input_channel.range(..self.chunk_size), + buffer_channel + .range(2 * POLYNOMIAL_LEN_U..2 * POLYNOMIAL_LEN_U + self.chunk_size), + ); } } @@ -311,18 +327,19 @@ where let start_idx = idx_floor as isize - 3; let frac = idx - idx_floor; let frac_offset = T::coerce(frac); - for (chan, active) in self.channel_mask.iter().enumerate() { - if *active { - unsafe { - let buf = self.buffer.get_unchecked(chan).get_unchecked( - (start_idx + 2 * POLYNOMIAL_LEN_I) as usize - ..(start_idx + 2 * POLYNOMIAL_LEN_I + 8) as usize, - ); - *wave_out - .get_unchecked_mut(chan) - .as_mut() - .get_unchecked_mut(n) = interp_septic(frac_offset, buf); - } + for ((buffer_channel, output_channel), active) in self + .buffer + .iter_channels() + .zip(wave_out.iter_channels_mut()) + .zip(self.channel_mask) + { + if active { + let buffer_range = buffer_channel.range( + (start_idx + 2 * POLYNOMIAL_LEN_I) as usize + ..(start_idx + 2 * POLYNOMIAL_LEN_I + 8) as usize, + ); + *output_channel.get_mut(n).unwrap() = + interp_septic(frac_offset, &buffer_range); } } n += 1; @@ -336,18 +353,18 @@ where let start_idx = idx_floor as isize - 2; let frac = idx - idx_floor; let frac_offset = T::coerce(frac); - for (chan, active) in self.channel_mask.iter().enumerate() { - if *active { - unsafe { - let buf = self.buffer.get_unchecked(chan).get_unchecked( - (start_idx + 2 * POLYNOMIAL_LEN_I) as usize - ..(start_idx + 2 * POLYNOMIAL_LEN_I + 6) as usize, - ); - *wave_out - .get_unchecked_mut(chan) - .as_mut() - .get_unchecked_mut(n) = interp_quintic(frac_offset, buf); - } + for ((buffer_channel, output_channel), active) in self + .buffer + .iter_channels() + .zip(wave_out.iter_channels_mut()) + .zip(self.channel_mask) + { + if active { + let buffer_range = buffer_channel.range( + (start_idx + 2 * POLYNOMIAL_LEN_I) as usize + ..(start_idx + 2 * POLYNOMIAL_LEN_I + 6) as usize + ); + *output_channel.get_mut(n).unwrap() = interp_quintic(frac_offset, &buffer_range); } } n += 1; @@ -361,18 +378,18 @@ where let start_idx = idx_floor as isize - 1; let frac = idx - idx_floor; let frac_offset = T::coerce(frac); - for (chan, active) in self.channel_mask.iter().enumerate() { - if *active { - unsafe { - let buf = self.buffer.get_unchecked(chan).get_unchecked( - (start_idx + 2 * POLYNOMIAL_LEN_I) as usize - ..(start_idx + 2 * POLYNOMIAL_LEN_I + 4) as usize, - ); - *wave_out - .get_unchecked_mut(chan) - .as_mut() - .get_unchecked_mut(n) = interp_cubic(frac_offset, buf); - } + for ((buffer_channel, output_channel), active) in self + .buffer + .iter_channels() + .zip(wave_out.iter_channels_mut()) + .zip(self.channel_mask) + { + if active { + let buffer_range = buffer_channel.range( + (start_idx + 2 * POLYNOMIAL_LEN_I) as usize + ..(start_idx + 2 * POLYNOMIAL_LEN_I + 4) as usize + ); + *output_channel.get_mut(n).unwrap() = interp_cubic(frac_offset, &buffer_range); } } n += 1; @@ -386,18 +403,18 @@ where let start_idx = idx_floor as isize; let frac = idx - idx_floor; let frac_offset = T::coerce(frac); - for (chan, active) in self.channel_mask.iter().enumerate() { - if *active { - unsafe { - let buf = self.buffer.get_unchecked(chan).get_unchecked( - (start_idx + 2 * POLYNOMIAL_LEN_I) as usize - ..(start_idx + 2 * POLYNOMIAL_LEN_I + 2) as usize, - ); - *wave_out - .get_unchecked_mut(chan) - .as_mut() - .get_unchecked_mut(n) = interp_lin(frac_offset, buf); - } + for ((buffer_channel, output_channel), active) in self + .buffer + .iter_channels() + .zip(wave_out.iter_channels_mut()) + .zip(self.channel_mask) + { + if active { + let buffer_range = buffer_channel.range( + (start_idx + 2 * POLYNOMIAL_LEN_I) as usize + ..(start_idx + 2 * POLYNOMIAL_LEN_I + 2) as usize + ); + *output_channel.get_mut(n).unwrap() = interp_lin(frac_offset, &buffer_range); } } n += 1; @@ -408,18 +425,14 @@ where t_ratio += t_ratio_increment; idx += t_ratio; let start_idx = idx.floor() as isize; - for (chan, active) in self.channel_mask.iter().enumerate() { - if *active { - unsafe { - let point = self - .buffer - .get_unchecked(chan) - .get_unchecked((start_idx + 2 * POLYNOMIAL_LEN_I) as usize); - *wave_out - .get_unchecked_mut(chan) - .as_mut() - .get_unchecked_mut(n) = *point; - } + for ((buffer_channel, output_channel), active) in self + .buffer + .iter_channels() + .zip(wave_out.iter_channels_mut()) + .zip(self.channel_mask) + { + if active { + *output_channel.get_mut(n).unwrap() = buffer_channel.get((start_idx + 2 * POLYNOMIAL_LEN_I) as usize).unwrap(); } } n += 1; @@ -487,9 +500,7 @@ where } fn reset(&mut self) { - self.buffer - .iter_mut() - .for_each(|ch| ch.iter_mut().for_each(|s| *s = T::zero())); + self.buffer.fill(T::zero()); self.channel_mask.iter_mut().for_each(|val| *val = true); self.last_index = -(POLYNOMIAL_LEN_I / 2) as f64; self.resample_ratio = self.resample_ratio_original; @@ -527,7 +538,7 @@ where let buffer_channel_length = ((max_resample_ratio_relative + 1.0) * needed_input_size as f64) as usize + 2 * POLYNOMIAL_LEN_U; - let buffer = vec![vec![T::zero(); buffer_channel_length]; nbr_channels]; + let buffer = SequentialBuffer::with_topology(nbr_channels, buffer_channel_length); let channel_mask = vec![true; nbr_channels]; Ok(FastFixedOut { @@ -551,12 +562,16 @@ impl Resampler for FastFixedOut where T: Sample, { - fn process_into_buffer, Vout: AsMut<[T]>>( + fn process_into_buffer( &mut self, - wave_in: &[Vin], - wave_out: &mut [Vout], + wave_in: &In, + wave_out: &mut Out, active_channels_mask: Option<&[bool]>, - ) -> ResampleResult<(usize, usize)> { + ) -> ResampleResult<(usize, usize)> + where + In: ExactSizeBuf, + Out: ExactSizeBuf + BufMut, + { if let Some(mask) = active_channels_mask { self.channel_mask.copy_from_slice(mask); } else { @@ -571,22 +586,27 @@ where self.needed_input_size, self.chunk_size, )?; - for buf in self.buffer.iter_mut() { - buf.copy_within( + for channel in self.buffer.iter_channels_mut() { + channel.as_mut().copy_within( self.current_buffer_fill..self.current_buffer_fill + 2 * POLYNOMIAL_LEN_U, 0, ); } self.current_buffer_fill = self.needed_input_size; - for (chan, wave_in) in wave_in - .iter() - .enumerate() - .filter(|(chan, _)| self.channel_mask[*chan]) + debug_assert!(self.chunk_size <= wave_out.frames()); + for ((buffer_channel, input_channel), active) in self + .buffer + .iter_channels_mut() + .zip(wave_in.iter_channels()) + .zip(self.channel_mask) { - debug_assert!(self.chunk_size <= wave_out[chan].as_mut().len()); - self.buffer[chan][2 * POLYNOMIAL_LEN_U..2 * POLYNOMIAL_LEN_U + self.needed_input_size] - .copy_from_slice(&wave_in.as_ref()[..self.needed_input_size]); + if active { + audio::channel::copy( + input_channel.range(..self.needed_input_size), + buffer_channel.range(2 * POLYNOMIAL_LEN_U..2 * POLYNOMIAL_LEN_U + self.needed_input_size) + ); + } } let mut idx = self.last_index; @@ -603,18 +623,19 @@ where let start_idx = idx_floor as isize - 3; let frac = idx - idx_floor; let frac_offset = T::coerce(frac); - for (chan, active) in self.channel_mask.iter().enumerate() { - if *active { - unsafe { - let buf = self.buffer.get_unchecked(chan).get_unchecked( - (start_idx + 2 * POLYNOMIAL_LEN_I) as usize - ..(start_idx + 2 * POLYNOMIAL_LEN_I + 8) as usize, - ); - *wave_out - .get_unchecked_mut(chan) - .as_mut() - .get_unchecked_mut(n) = interp_septic(frac_offset, buf); - } + for ((buffer_channel, output_channel), active) in self + .buffer + .iter_channels() + .zip(wave_out.iter_channels_mut()) + .zip(self.channel_mask) + { + if active { + let buffer_range = buffer_channel.range( + (start_idx + 2 * POLYNOMIAL_LEN_I) as usize + ..(start_idx + 2 * POLYNOMIAL_LEN_I + 8) as usize, + ); + *output_channel.get_mut(n).unwrap() = + interp_septic(frac_offset, &buffer_range); } } } @@ -627,18 +648,18 @@ where let start_idx = idx_floor as isize - 2; let frac = idx - idx_floor; let frac_offset = T::coerce(frac); - for (chan, active) in self.channel_mask.iter().enumerate() { - if *active { - unsafe { - let buf = self.buffer.get_unchecked(chan).get_unchecked( - (start_idx + 2 * POLYNOMIAL_LEN_I) as usize - ..(start_idx + 2 * POLYNOMIAL_LEN_I + 6) as usize, - ); - *wave_out - .get_unchecked_mut(chan) - .as_mut() - .get_unchecked_mut(n) = interp_quintic(frac_offset, buf); - } + for ((buffer_channel, output_channel), active) in self + .buffer + .iter_channels() + .zip(wave_out.iter_channels_mut()) + .zip(self.channel_mask) + { + if active { + let buffer_range = buffer_channel.range( + (start_idx + 2 * POLYNOMIAL_LEN_I) as usize + ..(start_idx + 2 * POLYNOMIAL_LEN_I + 6) as usize + ); + *output_channel.get_mut(n).unwrap() = interp_quintic(frac_offset, &buffer_range); } } } @@ -651,18 +672,18 @@ where let start_idx = idx_floor as isize - 1; let frac = idx - idx_floor; let frac_offset = T::coerce(frac); - for (chan, active) in self.channel_mask.iter().enumerate() { - if *active { - unsafe { - let buf = self.buffer.get_unchecked(chan).get_unchecked( - (start_idx + 2 * POLYNOMIAL_LEN_I) as usize - ..(start_idx + 2 * POLYNOMIAL_LEN_I + 4) as usize, - ); - *wave_out - .get_unchecked_mut(chan) - .as_mut() - .get_unchecked_mut(n) = interp_cubic(frac_offset, buf); - } + for ((buffer_channel, output_channel), active) in self + .buffer + .iter_channels() + .zip(wave_out.iter_channels_mut()) + .zip(self.channel_mask) + { + if active { + let buffer_range = buffer_channel.range( + (start_idx + 2 * POLYNOMIAL_LEN_I) as usize + ..(start_idx + 2 * POLYNOMIAL_LEN_I + 4) as usize + ); + *output_channel.get_mut(n).unwrap() = interp_cubic(frac_offset, &buffer_range); } } } @@ -675,18 +696,18 @@ where let start_idx = idx_floor as isize; let frac = idx - idx_floor; let frac_offset = T::coerce(frac); - for (chan, active) in self.channel_mask.iter().enumerate() { - if *active { - unsafe { - let buf = self.buffer.get_unchecked(chan).get_unchecked( - (start_idx + 2 * POLYNOMIAL_LEN_I) as usize - ..(start_idx + 2 * POLYNOMIAL_LEN_I + 2) as usize, - ); - *wave_out - .get_unchecked_mut(chan) - .as_mut() - .get_unchecked_mut(n) = interp_lin(frac_offset, buf); - } + for ((buffer_channel, output_channel), active) in self + .buffer + .iter_channels() + .zip(wave_out.iter_channels_mut()) + .zip(self.channel_mask) + { + if active { + let buffer_range = buffer_channel.range( + (start_idx + 2 * POLYNOMIAL_LEN_I) as usize + ..(start_idx + 2 * POLYNOMIAL_LEN_I + 2) as usize + ); + *output_channel.get_mut(n).unwrap() = interp_lin(frac_offset, &buffer_range); } } } @@ -696,18 +717,14 @@ where t_ratio += t_ratio_increment; idx += t_ratio; let start_idx = idx.floor() as isize; - for (chan, active) in self.channel_mask.iter().enumerate() { - if *active { - unsafe { - let point = self - .buffer - .get_unchecked(chan) - .get_unchecked((start_idx + 2 * POLYNOMIAL_LEN_I) as usize); - *wave_out - .get_unchecked_mut(chan) - .as_mut() - .get_unchecked_mut(n) = *point; - } + for ((buffer_channel, output_channel), active) in self + .buffer + .iter_channels() + .zip(wave_out.iter_channels_mut()) + .zip(self.channel_mask) + { + if active { + *output_channel.get_mut(n).unwrap() = buffer_channel.get((start_idx + 2 * POLYNOMIAL_LEN_I) as usize).unwrap(); } } } @@ -788,9 +805,7 @@ where } fn reset(&mut self) { - self.buffer - .iter_mut() - .for_each(|ch| ch.iter_mut().for_each(|s| *s = T::zero())); + self.buffer.fill(T::zero()); self.needed_input_size = (self.chunk_size as f64 / self.resample_ratio_original).ceil() as usize + 2 diff --git a/src/asynchro_sinc.rs b/src/asynchro_sinc.rs index 0fa74cb..6dc7c46 100644 --- a/src/asynchro_sinc.rs +++ b/src/asynchro_sinc.rs @@ -10,6 +10,8 @@ use crate::sinc_interpolator::{ScalarInterpolator, SincInterpolator}; use crate::windows::WindowFunction; use crate::{update_mask_from_buffers, validate_buffers, Resampler, Sample}; +use audio::{buf::Sequential as SequentialBuffer, BufMut, ExactSizeBuf}; + /// A struct holding the parameters for sinc interpolation. #[derive(Debug)] pub struct SincInterpolationParameters { @@ -92,7 +94,7 @@ pub struct SincFixedIn { target_ratio: f64, max_relative_ratio: f64, interpolator: Box>, - buffer: Vec>, + buffer: SequentialBuffer, interpolation: SincInterpolationType, channel_mask: Vec, } @@ -122,7 +124,7 @@ pub struct SincFixedOut { target_ratio: f64, max_relative_ratio: f64, interpolator: Box>, - buffer: Vec>, + buffer: SequentialBuffer, interpolation: SincInterpolationType, channel_mask: Vec, } @@ -286,7 +288,7 @@ where nbr_channels: usize, ) -> Result { validate_ratios(resample_ratio, max_resample_ratio_relative)?; - let buffer = vec![vec![T::zero(); chunk_size + 2 * interpolator.len()]; nbr_channels]; + let buffer = SequentialBuffer::with_topology(nbr_channels, chunk_size + 2 * interpolator.len()); let channel_mask = vec![true; nbr_channels]; @@ -310,12 +312,16 @@ impl Resampler for SincFixedIn where T: Sample, { - fn process_into_buffer, Vout: AsMut<[T]>>( + fn process_into_buffer( &mut self, - wave_in: &[Vin], - wave_out: &mut [Vout], + wave_in: &In, + wave_out: &mut Out, active_channels_mask: Option<&[bool]>, - ) -> ResampleResult<(usize, usize)> { + ) -> ResampleResult<(usize, usize)> + where + In: ExactSizeBuf, + Out: ExactSizeBuf + BufMut, + { if let Some(mask) = active_channels_mask { self.channel_mask.copy_from_slice(mask); } else { @@ -525,9 +531,7 @@ where } fn reset(&mut self) { - self.buffer - .iter_mut() - .for_each(|ch| ch.iter_mut().for_each(|s| *s = T::zero())); + self.buffer.fill(T::zero()); self.channel_mask.iter_mut().for_each(|val| *val = true); self.last_index = -((self.interpolator.len() / 2) as f64); self.resample_ratio = self.resample_ratio_original; @@ -600,7 +604,7 @@ where let buffer_channel_length = ((max_resample_ratio_relative + 1.0) * needed_input_size as f64) as usize + 2 * interpolator.len(); - let buffer = vec![vec![T::zero(); buffer_channel_length]; nbr_channels]; + let buffer = SequentialBuffer::with_topology(nbr_channels, buffer_channel_length); let channel_mask = vec![true; nbr_channels]; Ok(SincFixedOut { @@ -625,12 +629,16 @@ impl Resampler for SincFixedOut where T: Sample, { - fn process_into_buffer, Vout: AsMut<[T]>>( + fn process_into_buffer( &mut self, - wave_in: &[Vin], - wave_out: &mut [Vout], + wave_in: &In, + wave_out: &mut Out, active_channels_mask: Option<&[bool]>, - ) -> ResampleResult<(usize, usize)> { + ) -> ResampleResult<(usize, usize)> + where + In: ExactSizeBuf, + Out: ExactSizeBuf + BufMut, + { if let Some(mask) = active_channels_mask { self.channel_mask.copy_from_slice(mask); } else { @@ -842,9 +850,7 @@ where } fn reset(&mut self) { - self.buffer - .iter_mut() - .for_each(|ch| ch.iter_mut().for_each(|s| *s = T::zero())); + self.buffer.fill(T::zero()); self.needed_input_size = (self.chunk_size as f64 / self.resample_ratio_original).ceil() as usize + 2 diff --git a/src/error.rs b/src/error.rs index 6f8617d..2eff63f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -130,18 +130,10 @@ pub enum ResampleError { WrongNumberOfMaskChannels { expected: usize, actual: usize }, /// Error raised when the number of frames in an input channel is less /// than the minimum expected number of frames. - InsufficientInputBufferSize { - channel: usize, - expected: usize, - actual: usize, - }, + InsufficientInputBufferSize { expected: usize, actual: usize }, /// Error raised when the number of frames in an output channel is less /// than the minimum expected number of frames. - InsufficientOutputBufferSize { - channel: usize, - expected: usize, - actual: usize, - }, + InsufficientOutputBufferSize { expected: usize, actual: usize }, } impl fmt::Display for ResampleError { diff --git a/src/lib.rs b/src/lib.rs index a488a56..04eceba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -169,6 +169,9 @@ mod windows; pub mod sinc_interpolator; +pub use audio::{buf::Sequential as SequentialBuffer, wrap as audio_wrap}; +use audio::{Buf, BufMut, ExactSizeBuf}; + pub use crate::asynchro_fast::{FastFixedIn, FastFixedOut, PolynomialDegree}; pub use crate::asynchro_sinc::{ SincFixedIn, SincFixedOut, SincInterpolationParameters, SincInterpolationType, @@ -193,27 +196,17 @@ where /// that allocates the output buffer with each call. For realtime applications, use /// [process_into_buffer](Resampler::process_into_buffer) with a buffer allocated by /// [output_buffer_allocate](Resampler::output_buffer_allocate) instead of this function. - fn process>( + fn process( &mut self, - wave_in: &[V], + wave_in: &In, active_channels_mask: Option<&[bool]>, - ) -> ResampleResult>> { - let frames = self.output_frames_next(); - let channels = self.nbr_channels(); - let mut wave_out = Vec::with_capacity(channels); - for chan in 0..channels { - let chan_out = if active_channels_mask.map(|mask| mask[chan]).unwrap_or(true) { - vec![T::zero(); frames] - } else { - vec![] - }; - wave_out.push(chan_out); - } - let (_, out_len) = - self.process_into_buffer(wave_in, &mut wave_out, active_channels_mask)?; - for chan_out in wave_out.iter_mut() { - chan_out.truncate(out_len); - } + ) -> ResampleResult> + where + In: ExactSizeBuf, + { + let mut wave_out = + SequentialBuffer::with_topology(self.nbr_channels(), self.output_frames_next()); + let (_, _) = self.process_into_buffer(wave_in, &mut wave_out, active_channels_mask)?; Ok(wave_out) } @@ -245,12 +238,15 @@ where /// Both input and output are allowed to be longer than required. /// The number of input samples consumed and the number output samples written /// per channel is returned in a tuple, `(input_frames, output_frames)`. - fn process_into_buffer, Vout: AsMut<[T]>>( + fn process_into_buffer( &mut self, - wave_in: &[Vin], - wave_out: &mut [Vout], + wave_in: &In, + wave_out: &mut Out, active_channels_mask: Option<&[bool]>, - ) -> ResampleResult<(usize, usize)>; + ) -> ResampleResult<(usize, usize)> + where + In: ExactSizeBuf, + Out: ExactSizeBuf + BufMut; /// This is a convenience method for processing the last frames at the end of a stream. /// Use this when there are fewer frames remaining than what the resampler requires as input. @@ -260,29 +256,21 @@ where /// This can be utilized to push any remaining delayed frames out from the internal buffers. /// Note that this method allocates space for a temporary input buffer. /// Real-time applications should instead call `process_into_buffer` with a zero-padded pre-allocated input buffer. - fn process_partial_into_buffer, Vout: AsMut<[T]>>( + fn process_partial_into_buffer( &mut self, - wave_in: Option<&[Vin]>, - wave_out: &mut [Vout], + wave_in: Option<&In>, + wave_out: &mut Out, active_channels_mask: Option<&[bool]>, - ) -> ResampleResult<(usize, usize)> { - let frames = self.input_frames_next(); - let mut wave_in_padded = Vec::with_capacity(self.nbr_channels()); - for _ in 0..self.nbr_channels() { - wave_in_padded.push(vec![T::zero(); frames]); - } + ) -> ResampleResult<(usize, usize)> + where + In: ExactSizeBuf, + Out: ExactSizeBuf + BufMut, + { + let frames_needed = self.input_frames_next(); + let mut wave_in_padded = + SequentialBuffer::with_topology(self.nbr_channels(), frames_needed); if let Some(input) = wave_in { - for (ch_input, ch_padded) in input.iter().zip(wave_in_padded.iter_mut()) { - let mut frames_in = ch_input.as_ref().len(); - if frames_in > frames { - frames_in = frames; - } - if frames_in > 0 { - ch_padded[..frames_in].copy_from_slice(&ch_input.as_ref()[..frames_in]); - } else { - ch_padded.clear(); - } - } + audio::buf::copy(input, wave_in_padded); } self.process_into_buffer(&wave_in_padded, wave_out, active_channels_mask) } @@ -291,27 +279,18 @@ where /// It is similar to [process_partial_into_buffer](Resampler::process_partial_into_buffer) /// but allocates the output buffer with each call. /// Note that this method allocates space for both input and output. - fn process_partial>( + fn process_partial( &mut self, - wave_in: Option<&[V]>, + wave_in: Option<&In>, active_channels_mask: Option<&[bool]>, - ) -> ResampleResult>> { - let frames = self.output_frames_next(); - let channels = self.nbr_channels(); - let mut wave_out = Vec::with_capacity(channels); - for chan in 0..channels { - let chan_out = if active_channels_mask.map(|mask| mask[chan]).unwrap_or(true) { - vec![T::zero(); frames] - } else { - vec![] - }; - wave_out.push(chan_out); - } + ) -> ResampleResult> + where + In: ExactSizeBuf, + { + let mut wave_out = + SequentialBuffer::with_topology(self.nbr_channels(), self.output_frames_next()); let (_, out_len) = self.process_partial_into_buffer(wave_in, &mut wave_out, active_channels_mask)?; - for chan_out in wave_out.iter_mut() { - chan_out.truncate(out_len); - } Ok(wave_out) } @@ -320,14 +299,8 @@ where /// is big enough to prevent allocating additional heap memory before any call to /// [process_into_buffer](Resampler::process_into_buffer) regardless of the current /// resampling ratio. - fn input_buffer_allocate(&self) -> Vec> { - let frames = self.input_frames_max(); - let channels = self.nbr_channels(); - let mut buffer = Vec::with_capacity(channels); - for _ in 0..channels { - buffer.push(Vec::with_capacity(frames)); - } - buffer + fn input_buffer_allocate(&self) -> SequentialBuffer { + SequentialBuffer::with_topology(self.nbr_channels(), self.input_frames_max()) } /// Get the maximum number of input frames per channel the resampler could require @@ -345,10 +318,8 @@ where /// is big enough to prevent allocating additional heap memory during any call to /// [process_into_buffer](Resampler::process_into_buffer) regardless of the current /// resampling ratio. - fn output_buffer_allocate(&self) -> Vec> { - let frames = self.output_frames_max(); - let channels = self.nbr_channels(); - vec![Vec::with_capacity(frames); channels] + fn output_buffer_allocate(&self) -> SequentialBuffer { + SequentialBuffer::with_topology(self.nbr_channels(), self.output_frames_max()) } /// Get the max number of output frames per channel @@ -416,7 +387,7 @@ macro_rules! implement_resampler { &mut self, wave_in: $in_type, active_channels_mask: Option<&[bool]>, - ) -> rubato::ResampleResult>>; + ) -> rubato::ResampleResult>; /// Refer to [Resampler::process_into_buffer] fn process_into_buffer( @@ -439,10 +410,10 @@ macro_rules! implement_resampler { &mut self, wave_in: Option<$in_type>, active_channels_mask: Option<&[bool]>, - ) -> rubato::ResampleResult>>; + ) -> rubato::ResampleResult>; /// Refer to [Resampler::input_buffer_allocate] - fn input_buffer_allocate(&self) -> Vec>; + fn input_buffer_allocate(&self) -> audio::buf::Sequential; /// Refer to [Resampler::input_frames_max] fn input_frames_max(&self) -> usize; @@ -454,7 +425,7 @@ macro_rules! implement_resampler { fn nbr_channels(&self) -> usize; /// Refer to [Resampler::output_buffer_allocate] - fn output_buffer_allocate(&self) -> Vec>; + fn output_buffer_allocate(&self) -> audio::buf::Sequential; /// Refer to [Resampler::output_frames_max] fn output_frames_max(&self) -> usize; @@ -478,7 +449,7 @@ macro_rules! implement_resampler { &mut self, wave_in: $in_type, active_channels_mask: Option<&[bool]>, - ) -> rubato::ResampleResult>> { + ) -> rubato::ResampleResult> { rubato::Resampler::process(self, wave_in, active_channels_mask) } @@ -499,7 +470,7 @@ macro_rules! implement_resampler { ) -> rubato::ResampleResult<(usize, usize)> { rubato::Resampler::process_partial_into_buffer( self, - wave_in.map(AsRef::as_ref), + wave_in, wave_out, active_channels_mask, ) @@ -509,11 +480,11 @@ macro_rules! implement_resampler { &mut self, wave_in: Option<$in_type>, active_channels_mask: Option<&[bool]>, - ) -> rubato::ResampleResult>> { + ) -> rubato::ResampleResult> { rubato::Resampler::process_partial(self, wave_in, active_channels_mask) } - fn output_buffer_allocate(&self) -> Vec> { + fn output_buffer_allocate(&self) -> audio::buf::Sequential { rubato::Resampler::output_buffer_allocate(self) } @@ -537,7 +508,7 @@ macro_rules! implement_resampler { rubato::Resampler::input_frames_max(self) } - fn input_buffer_allocate(&self) -> Vec> { + fn input_buffer_allocate(&self) -> audio::buf::Sequential { rubato::Resampler::input_buffer_allocate(self) } @@ -552,86 +523,86 @@ macro_rules! implement_resampler { } } -implement_resampler!(VecResampler, &[Vec], &mut [Vec]); +implement_resampler!( + SequentialResampler, + &audio::buf::Sequential, + &mut audio::buf::Sequential +); /// Helper to make a mask where all channels are marked as active. fn update_mask_from_buffers(mask: &mut [bool]) { mask.iter_mut().for_each(|v| *v = true); } -pub(crate) fn validate_buffers, Vout: AsMut<[T]>>( - wave_in: &[Vin], - wave_out: &mut [Vout], +pub(crate) fn validate_buffers( + wave_in: &In, + wave_out: &Out, mask: &[bool], channels: usize, min_input_len: usize, min_output_len: usize, -) -> ResampleResult<()> { - if wave_in.len() != channels { +) -> ResampleResult<()> +where + In: ExactSizeBuf, + Out: ExactSizeBuf, +{ + if wave_in.channels() != channels { return Err(ResampleError::WrongNumberOfInputChannels { expected: channels, - actual: wave_in.len(), + actual: wave_in.channels(), }); } if mask.len() != channels { return Err(ResampleError::WrongNumberOfMaskChannels { expected: channels, - actual: wave_in.len(), + actual: mask.len(), }); } - for (chan, wave_in) in wave_in.iter().enumerate().filter(|(chan, _)| mask[*chan]) { - let actual_len = wave_in.as_ref().len(); - if actual_len < min_input_len { - return Err(ResampleError::InsufficientInputBufferSize { - channel: chan, - expected: min_input_len, - actual: actual_len, - }); - } + + if wave_in.frames() < min_input_len { + return Err(ResampleError::InsufficientInputBufferSize { + expected: min_input_len, + actual: wave_in.frames(), + }); } - if wave_out.len() != channels { + if wave_out.channels() != channels { return Err(ResampleError::WrongNumberOfOutputChannels { expected: channels, - actual: wave_out.len(), + actual: wave_out.channels(), }); } - for (chan, wave_out) in wave_out - .iter_mut() - .enumerate() - .filter(|(chan, _)| mask[*chan]) - { - let actual_len = wave_out.as_mut().len(); - if actual_len < min_output_len { - return Err(ResampleError::InsufficientOutputBufferSize { - channel: chan, - expected: min_output_len, - actual: actual_len, - }); - } + if wave_out.frames() < min_output_len { + return Err(ResampleError::InsufficientOutputBufferSize { + expected: min_output_len, + actual: wave_out.frames(), + }); } Ok(()) } #[cfg(test)] pub mod tests { - use crate::VecResampler; + use crate::SequentialResampler; use crate::{FftFixedIn, FftFixedInOut, FftFixedOut}; use crate::{SincFixedIn, SincFixedOut}; + use audio::buf::Sequential as SequentialBuffer; // This tests that a VecResampler can be boxed. #[test] fn boxed_resampler() { - let boxed: Box> = + let boxed: Box> = Box::new(FftFixedIn::::new(44100, 88200, 1024, 2, 2).unwrap()); let result = process_with_boxed(boxed); - assert_eq!(result.len(), 2); + assert_eq!(result.channels(), 2); assert_eq!(result[0].len(), 2048); assert_eq!(result[1].len(), 2048); } - fn process_with_boxed(mut resampler: Box>) -> Vec> { + fn process_with_boxed( + mut resampler: Box>, + ) -> SequentialBuffer { let frames = resampler.input_frames_next(); - let waves = vec![vec![0.0f64; frames]; 2]; + let waves = SequentialBuffer::with_topology(2, frames); resampler.process(&waves, None).unwrap() } diff --git a/src/sample.rs b/src/sample.rs index e318cbc..f23f28b 100644 --- a/src/sample.rs +++ b/src/sample.rs @@ -24,7 +24,8 @@ where + AvxSample + SseSample + NeonSample - + Send, + + Send + + audio::Sample, { const PI: Self;