From 54d26d41bb94b1afe7931b1ea923fb584df10e0c Mon Sep 17 00:00:00 2001 From: Serhiy Katsyuba Date: Wed, 22 Jan 2025 17:03:29 +0100 Subject: [PATCH] ipc4: mixin: Fix HiFi3 impl of 24-bit mixing AE_ADD24S() expects input arguments to be Q9.23 values. Therefore, negative 24-bit values in a 32-bit container should have their sign extended to the upper 8 bits. All other five implementations of 24-bit mixing (IPC3 mixer's generic and HIFI3, IPC4 mixin's generic, IPC4 mixin's mix with gain generic and HIFI3) perform sign extension prior to mixing and do not rely on samples being already sign-extended. Signed-off-by: Serhiy Katsyuba --- src/audio/mixin_mixout/mixin_mixout_hifi3.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/audio/mixin_mixout/mixin_mixout_hifi3.c b/src/audio/mixin_mixout/mixin_mixout_hifi3.c index da22be3634c5..ecd157a28ee0 100644 --- a/src/audio/mixin_mixout/mixin_mixout_hifi3.c +++ b/src/audio/mixin_mixout/mixin_mixout_hifi3.c @@ -255,6 +255,9 @@ static void mix_s24(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixe AE_LA32X2_IP(in_sample, inu, in); AE_LA32X2_IP(out_sample, outu1, out); out--; + /* sign extent in_sample as AE_ADD24S expects Q9.23 arguments */ + in_sample = AE_SLAI24S(AE_MOVF24X2_FROMINT32X2(in_sample), 0); + /* out_sample is already sign extended by other mixin in a loop below */ out_sample = AE_ADD24S(in_sample, out_sample); AE_SA32X2_IP(out_sample, outu2, out); } @@ -264,6 +267,8 @@ static void mix_s24(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixe if (left) { AE_L32_IP(in_sample, (ae_int32 *)in, sizeof(ae_int32)); AE_L32_IP(out_sample, (ae_int32 *)out, 0); + /* sign extension */ + in_sample = AE_SLAI24S(AE_MOVF24X2_FROMINT32X2(in_sample), 0); out_sample = AE_ADD24S(in_sample, out_sample); AE_S32_L_IP(out_sample, (ae_int32 *)out, sizeof(ae_int32)); } @@ -283,12 +288,16 @@ static void mix_s24(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixe left = n & 1; for (i = 0; i < m; i++) { AE_LA32X2_IP(in_sample, inu, in); + /* sign extension */ + in_sample = AE_SLAI24S(AE_MOVF24X2_FROMINT32X2(in_sample), 0); AE_SA32X2_IP(in_sample, outu2, out); } AE_SA64POS_FP(outu2, out); /* process the left sample to avoid memory access overrun */ if (left) { AE_L32_IP(in_sample, (ae_int32 *)in, sizeof(ae_int32)); + /* sign extension */ + in_sample = AE_SLAI24S(AE_MOVF24X2_FROMINT32X2(in_sample), 0); AE_S32_L_IP(in_sample, (ae_int32 *)out, sizeof(ae_int32)); } }