[Sound-open-firmware] [PATCH 1/2] volume: fix errors in volume scaling multiplication

Ranjani Sridharan ranjani.sridharan at linux.intel.com
Tue Mar 20 17:38:13 CET 2018


Please ignore this patchset for now.

After my discussion with Seppo, I will be modifying the signature to
make it a bit more generic and handle the sign inversions for 16x16 and
32x32. 


On Mon, 2018-03-19 at 14:16 -0700, Ranjani Sridharan wrote:
> This patch fixes the errors in fixed-point multiplication function
> for volume scaling that caused sign inversions. It also breaks up the
> operation into 4 separate functions depending on the source and sink
> formats.
> 
> Signed-off-by: Ranjani Sridharan <ranjani.sridharan at linux.intel.com>
> ---
>  src/include/reef/audio/format.h | 114
> ++++++++++++++++++++++++++++++++++++----
>  1 file changed, 105 insertions(+), 9 deletions(-)
> 
> diff --git a/src/include/reef/audio/format.h
> b/src/include/reef/audio/format.h
> index c9c23ec..669a314 100644
> --- a/src/include/reef/audio/format.h
> +++ b/src/include/reef/audio/format.h
> @@ -153,22 +153,118 @@ static inline int16_t sat_int16(int32_t x)
>  		return (int16_t)x;
>  }
>  
> -/* Fractional multiplication with shift and saturation */
> -static inline int32_t q_multsr_sat_32x32(int32_t x, int32_t y,
> -	const int shift_bits)
> +static inline int32_t sign_extend_s24(int32_t x)
>  {
> -	return sat_int32(((((int64_t)x * y) >> (shift_bits - 1)) +
> 1) >> 1);
> +	return (x << 8) >> 8;
>  }
>  
> -static inline int16_t q_multsr_sat_16x16(int16_t x, int32_t y,
> -	const int shift_bits)
> +/* Truncate a 64-bit int by shift_bits
> + * This function rounds the result before truncating
> + */
> +static inline int64_t shift_64(int64_t x, int shift_bits)
>  {
> -	return sat_int16(((((int32_t)x * y) >> (shift_bits - 1)) +
> 1) >> 1);
> +	return (int64_t)(((x >> (shift_bits - 1)) + 1) >> 1);
>  }
>  
> -static inline int32_t sign_extend_s24(int32_t x)
> +/* Truncate a 32-bit int by shift_bits
> + * This function rounds the result before truncating
> + */
> +static inline int32_t shift_32(int32_t x, int shift_bits)
>  {
> -	return (x << 8) >> 8;
> +	return (int32_t)(((x >> (shift_bits - 1)) + 1) >> 1);
> +}
> +
> +/* Fractional multiplication with shift and saturation
> + * This function multiplies a 16-bit number by a 32-bit unsigned
> number and
> + * copies the result to a 32-bit int
> + */
> +static inline void q_multsr_sat_16x32_32(int16_t *src, uint32_t vol,
> +					 const int shift_bits,
> int32_t *dest,
> +					 int offset, int
> sign_extend)
> +{
> +	int64_t temp;
> +
> +	if (shift_bits == 0) {
> +		/* Samples are Q1.15 and volume unsigned is Q1.16 */
> +		dest[offset] = (int32_t)(src[offset] * vol);
> +		return;
> +	}
> +
> +	/* store the intermediate product in an int64 */
> +	temp = (int64_t)((int64_t)src[offset] * vol);
> +
> +	/* round, truncate and saturate if needed */
> +	dest[offset] = sat_int32(shift_64(temp, shift_bits));
> +}
> +
> +/* Fractional multiplication with shift and saturation
> + * This function multiplies 2 32-bit numbers and stores
> + * copies the result to a 32-bit int
> + */
> +static inline void q_multsr_sat_32x32_32(int32_t *src, uint32_t vol,
> +					 const int shift_bits,
> int32_t *dest,
> +					 int offset, int
> sign_extend)
> +{
> +	int64_t temp;
> +
> +	/* store the intermediate product in an int64 */
> +	if (sign_extend) {
> +		/* Sample are Q1.23 and volume is unsigned Q1.16
> +		 * sign extend the input samples
> +		 */
> +		temp =
> (int64_t)((int64_t)sign_extend_s24(src[offset]) *
> +				 vol);
> +	} else {
> +		/* Sample are Q1.31 and volume unsigned is Q1.16 */
> +		temp = (int64_t)((int64_t)src[offset] * vol);
> +	}
> +
> +	/* round, truncate and saturate if needed */
> +	dest[offset] = sat_int32(shift_64(temp, shift_bits));
> +}
> +
> +/* Fractional multiplication with shift and saturation
> + * This function multiplies a 16-bit number by a 32-bit unsigned
> number and
> + * copies the result to a 16-bit int
> + */
> +static inline void q_multsr_sat_16x16_16(int16_t *src, uint32_t vol,
> +					 const int shift_bits,
> int16_t *dest,
> +					 int offset, int
> sign_extend)
> +{
> +	int32_t temp;
> +
> +	/* Sample are Q1.15 and volume is unsigned Q1.16
> +	 * store the intermediate product in an int32
> +	 */
> +	temp = (int32_t)((int32_t)src[offset] * vol);
> +
> +	/* round, truncate and saturate if needed */
> +	dest[offset] = sat_int16(shift_32(temp, shift_bits));
> +}
> +
> +/* Fractional multiplication with shift and saturation
> + * This function multiplies 2 32-bit numbers and
> + * copies the result to a 16-bit int
> + */
> +static inline void q_multsr_sat_32x32_16(int32_t *src, uint32_t vol,
> +					 const int shift_bits,
> int16_t *dest,
> +					 int offset, int
> sign_extend)
> +{
> +	int64_t temp;
> +
> +	/* store the intermediate product in an int64 */
> +	if (sign_extend) {
> +		/* Sample are Q1.23 and volume is unsigned Q1.16
> +		 * sign extend the input samples
> +		 */
> +		temp =
> (int64_t)((int64_t)sign_extend_s24(src[offset]) * vol);
> +	} else {
> +		/* Sample are Q1.31 and volume is unsigned Q1.16 */
> +		temp = (int64_t)((int64_t)src[offset] * vol);
> +	}
> +
> +	/* round, truncate and saturate if needed */
> +	dest[offset] = (int16_t)sat_int32(shift_64(temp,
> shift_bits));
>  }
>  
>  #endif


More information about the Sound-open-firmware mailing list