Skip to content

Commit

Permalink
Audio: Use generic saturation logic for improved efficiency
Browse files Browse the repository at this point in the history
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 <malladi.sastry@intel.com>
  • Loading branch information
ShriramShastry committed Jul 5, 2024
1 parent c97bba3 commit 06939dd
Show file tree
Hide file tree
Showing 2 changed files with 100,221 additions and 25 deletions.
92 changes: 67 additions & 25 deletions src/include/sof/audio/format_generic.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright(c) 2021 Intel Corporation. All rights reserved.
*
* Author: Shriram Shastry <malladi.sastry@linux.intel.com>
*/

#ifndef __SOF_AUDIO_FORMAT_GENERIC_H__
Expand All @@ -9,45 +11,85 @@
#include <stdint.h>

/* 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__ */
Loading

0 comments on commit 06939dd

Please sign in to comment.