[Sound-open-firmware] [PATCH 1/2] volume: fix errors in volume scaling multiplication
Ranjani Sridharan
ranjani.sridharan at linux.intel.com
Mon Mar 19 22:16:22 CET 2018
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
--
2.14.1
More information about the Sound-open-firmware
mailing list