From 98f1fe84dd8ee9d6e5d487315c2e75feddda93bb Mon Sep 17 00:00:00 2001 From: JasonLG1979 <jasonlevigray3@gmail.com> Date: Mon, 26 Jun 2023 05:11:30 -0500 Subject: [PATCH] Reduce allocations --- playback/src/normaliser.rs | 46 ++++++++++++++------------------- playback/src/resampler.rs | 29 ++++++++++++--------- playback/src/sample_pipeline.rs | 2 +- 3 files changed, 37 insertions(+), 40 deletions(-) diff --git a/playback/src/normaliser.rs b/playback/src/normaliser.rs index a72f61ae..8ee6d10f 100644 --- a/playback/src/normaliser.rs +++ b/playback/src/normaliser.rs @@ -10,32 +10,26 @@ use crate::{ struct NoNormalisation; impl NoNormalisation { - fn normalise(samples: &[f64], volume: f64) -> Vec<f64> { + fn normalise(mut samples: Vec<f64>, volume: f64) -> Vec<f64> { if volume < 1.0 { - let mut output = Vec::with_capacity(samples.len()); - - output.extend(samples.iter().map(|sample| sample * volume)); - - output - } else { - samples.to_vec() + samples.iter_mut().for_each(|sample| *sample *= volume); } + + samples } } struct BasicNormalisation; impl BasicNormalisation { - fn normalise(samples: &[f64], volume: f64, factor: f64) -> Vec<f64> { + fn normalise(mut samples: Vec<f64>, volume: f64, factor: f64) -> Vec<f64> { if volume < 1.0 || factor < 1.0 { - let mut output = Vec::with_capacity(samples.len()); - - output.extend(samples.iter().map(|sample| sample * factor * volume)); - - output - } else { - samples.to_vec() + samples + .iter_mut() + .for_each(|sample| *sample *= factor * volume); } + + samples } } @@ -85,11 +79,9 @@ impl DynamicNormalisation { self.peak = 0.0; } - fn normalise(&mut self, samples: &[f64], volume: f64, factor: f64) -> Vec<f64> { - let mut output = Vec::with_capacity(samples.len()); - - output.extend(samples.iter().map(|sample| { - let mut sample = sample * factor; + fn normalise(&mut self, mut samples: Vec<f64>, volume: f64, factor: f64) -> Vec<f64> { + samples.iter_mut().for_each(|sample| { + *sample *= factor; // Feedforward limiter in the log domain // After: Giannoulis, D., Massberg, M., & Reiss, J.D. (2012). Digital Dynamic @@ -154,13 +146,13 @@ impl DynamicNormalisation { // the default threshold, so that would clip. // steps 7-8: conversion into level and multiplication into gain stage - sample *= db_to_ratio(-self.peak); + *sample *= db_to_ratio(-self.peak); } - sample * volume - })); + *sample *= volume + }); - output + samples } } @@ -204,7 +196,7 @@ impl Normalisation { } } - fn normalise(&mut self, samples: &[f64], volume: f64, factor: f64) -> Vec<f64> { + fn normalise(&mut self, samples: Vec<f64>, volume: f64, factor: f64) -> Vec<f64> { use Normalisation::*; match self { @@ -236,7 +228,7 @@ impl Normaliser { } } - pub fn normalise(&mut self, samples: &[f64]) -> AudioPacket { + pub fn normalise(&mut self, samples: Vec<f64>) -> AudioPacket { let volume = self.volume_getter.attenuation_factor(); AudioPacket::Samples(self.normalisation.normalise(samples, volume, self.factor)) diff --git a/playback/src/resampler.rs b/playback/src/resampler.rs index e847fdaa..3e66791c 100644 --- a/playback/src/resampler.rs +++ b/playback/src/resampler.rs @@ -469,22 +469,27 @@ impl StereoInterleavedResampler { fn interleave_samples(left_samples: &[f64], right_samples: &[f64]) -> Vec<f64> { // Re-interleave the resampled channels. - left_samples - .iter() - .zip(right_samples.iter()) - .flat_map(|(&x, &y)| vec![x, y]) - .collect() + let mut output = Vec::with_capacity(left_samples.len() + right_samples.len()); + + output.extend( + left_samples + .iter() + .zip(right_samples.iter()) + .flat_map(|(&left, &right)| std::iter::once(left).chain(std::iter::once(right))), + ); + + output } fn deinterleave_samples(samples: &[f64]) -> (Vec<f64>, Vec<f64>) { // Split the stereo interleaved samples into left and right channels. - let (left_samples, right_samples): (Vec<f64>, Vec<f64>) = samples - .chunks(2) - .map(|chunk| { - let [left_sample, right_sample] = [chunk[0], chunk[1]]; - (left_sample, right_sample) - }) - .unzip(); + let samples_len = samples.len() / 2; + + let mut left_samples = Vec::with_capacity(samples_len); + let mut right_samples = Vec::with_capacity(samples_len); + + left_samples.extend(samples.iter().step_by(2)); + right_samples.extend(samples.iter().skip(1).step_by(2)); (left_samples, right_samples) } diff --git a/playback/src/sample_pipeline.rs b/playback/src/sample_pipeline.rs index 5b15cb2e..b6bffb89 100644 --- a/playback/src/sample_pipeline.rs +++ b/playback/src/sample_pipeline.rs @@ -70,7 +70,7 @@ impl SamplePipeline { if let AudioPacket::Samples(samples) = packet { self.resampler .resample(&samples) - .map(|processed_samples| self.normaliser.normalise(&processed_samples)) + .map(|processed_samples| self.normaliser.normalise(processed_samples)) .map(|new_packet| self.sink.write(new_packet, &mut self.converter)) .transpose()?; } else {