From d0ea9631d2c9e0b1be5198061280a3894bce9287 Mon Sep 17 00:00:00 2001 From: Roderick van Domburg Date: Fri, 9 Apr 2021 19:31:26 +0200 Subject: [PATCH] Optimize requantizer to work in `f32`, then round --- audio/src/convert.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/audio/src/convert.rs b/audio/src/convert.rs index 74a4d8f4..e291c804 100644 --- a/audio/src/convert.rs +++ b/audio/src/convert.rs @@ -21,7 +21,16 @@ macro_rules! convert_samples_to { $samples .iter() .map(|sample| { - (*sample as f64 * (std::$type::MAX as f64 + 0.5) - 0.5) as $type >> $drop_bits + // Losslessly represent [-1.0, 1.0] to [$type::MIN, $type::MAX] + // while maintaining DC linearity. There is nothing to be gained + // by doing this in f64, as the significand of a f32 is 24 bits, + // just like the maximum bit depth we are converting to. + let int_value = *sample * (std::$type::MAX as f32 + 0.5) - 0.5; + + // Casting floats to ints truncates by default, which results + // in larger quantization error than rounding arithmetically. + // Flooring is faster, but again with larger error. + int_value.round() as $type >> $drop_bits }) .collect() };