From cc0ef9a9e93ed3042db4b6286576154da21a533f Mon Sep 17 00:00:00 2001 From: Shriram Shastry Date: Fri, 5 Jul 2024 21:20:28 +0530 Subject: [PATCH] Audio: Use generic saturation logic for improved efficiency This check-in refactors saturation functions to use bitwise operations for handling overflow and underflow, improving efficiency. - Replaced if-else checks with bitwise masks to handle overflow and underflow for int32, int24, int16, and int8 saturation functions. - For each bit width, created masks by shifting the results of comparisons (x - MIN_VAL) and (MAX_VAL - x) to the respective overflow/underflow detection bits. - Mask >> 31 or >> 63 results in either 0 (no overflow/underflow) or -1 (overflow/underflow occurred). - Applied bitwise operations to conditionally replace original values with boundary values (MIN or MAX) based on the computed masks. - This approach avoids branching, improves efficiency, and ensures accurate saturation within specified bit-width limits. Signed-off-by: Shriram Shastry --- src/include/sof/audio/format_generic.h | 92 +++++++++++++++++++------- 1 file changed, 67 insertions(+), 25 deletions(-) diff --git a/src/include/sof/audio/format_generic.h b/src/include/sof/audio/format_generic.h index b63284cb872e..df61b2b519f8 100644 --- a/src/include/sof/audio/format_generic.h +++ b/src/include/sof/audio/format_generic.h @@ -1,6 +1,8 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright(c) 2021 Intel Corporation. All rights reserved. + * + * Author: Shriram Shastry */ #ifndef __SOF_AUDIO_FORMAT_GENERIC_H__ @@ -9,45 +11,85 @@ #include /* Saturation inline functions */ - +/** + * @brief Saturate an int64_t value to fit within the range of int32_t. + * + * This function ensures that the input value 'x' fits within the range of + * int32_t. If 'x' exceeds this range, it will be bound to INT32_MAX or INT32_MIN + * accordingly. + * + * @param x The input value to saturate. + * @return int32_t The saturated int32_t value. + */ static inline int32_t sat_int32(int64_t x) { - if (x > INT32_MAX) - return INT32_MAX; - else if (x < INT32_MIN) - return INT32_MIN; - else - return (int32_t)x; + int64_t mask_overflow = (INT32_MAX - x) >> 63; + int64_t mask_underflow = (x - INT32_MIN) >> 63; + + x = (x & ~mask_overflow) | (INT32_MAX & mask_overflow); + x = (x & ~mask_underflow) | (INT32_MIN & mask_underflow); + return (int32_t)x; + } +/** + * @brief Saturate an int32_t value to fit within the range of a 24-bit integer. + * + * This function ensures that the input value 'x' fits within the range of a + * 24-bit integer. If 'x' exceeds this range, it will be bound to INT24_MAXVALUE + * or INT24_MINVALUE accordingly. + * + * @param x The input value to saturate. + * @return int32_t The saturated int32_t value. + */ static inline int32_t sat_int24(int32_t x) { - if (x > INT24_MAXVALUE) - return INT24_MAXVALUE; - else if (x < INT24_MINVALUE) - return INT24_MINVALUE; - else - return x; + int32_t mask_overflow = (INT24_MAXVALUE - x) >> 31; + int32_t mask_underflow = (x - INT24_MINVALUE) >> 31; + + x = (x & ~mask_overflow) | (INT24_MAXVALUE & mask_overflow); + x = (x & ~mask_underflow) | (INT24_MINVALUE & mask_underflow); + return x; } +/** + * @brief Saturate an int32_t value to fit within the range of a 16-bit integer. + * + * This function ensures that the input value 'x' fits within the range of a + * 16-bit integer. If 'x' exceeds this range, it will be bound to INT16_MAX or INT16_MIN + * accordingly. + * + * @param x The input value to saturate. + * @return int16_t The saturated int16_t value. + */ static inline int16_t sat_int16(int32_t x) { - if (x > INT16_MAX) - return INT16_MAX; - else if (x < INT16_MIN) - return INT16_MIN; - else - return (int16_t)x; + int32_t mask_overflow = (INT16_MAX - x) >> 31; + int32_t mask_underflow = (x - INT16_MIN) >> 31; + + x = (x & ~mask_overflow) | (INT16_MAX & mask_overflow); + x = (x & ~mask_underflow) | (INT16_MIN & mask_underflow); + return (int16_t)x; } +/** + * @brief Saturate an int32_t value to fit within the range of an 8-bit integer. + * + * This function ensures that the input value 'x' fits within the range of an + * 8-bit integer. If 'x' exceeds this range, it will be bound to INT8_MAX or INT8_MIN + * accordingly. + * + * @param x The input value to saturate. + * @return int8_t The saturated int8_t value. + */ static inline int8_t sat_int8(int32_t x) { - if (x > INT8_MAX) - return INT8_MAX; - else if (x < INT8_MIN) - return INT8_MIN; - else - return (int8_t)x; + int32_t mask_overflow = (INT8_MAX - x) >> 31; + int32_t mask_underflow = (x - INT8_MIN) >> 31; + + x = (x & ~mask_overflow) | (INT8_MAX & mask_overflow); + x = (x & ~mask_underflow) | (INT8_MIN & mask_underflow); + return (int8_t)x; } #endif /* __SOF_AUDIO_FORMAT_GENERIC_H__ */