From cad6f822e1e6ba9fef3cc3cbce4d60457ba10db7 Mon Sep 17 00:00:00 2001 From: Serhiy Katsyuba Date: Fri, 24 Jan 2025 11:38:38 +0100 Subject: [PATCH] ipc4: mixin: Fix HiFi5 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. Our other implementations of 24-bit mixing all 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_hifi5.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/audio/mixin_mixout/mixin_mixout_hifi5.c b/src/audio/mixin_mixout/mixin_mixout_hifi5.c index 19b73ef1051a..cc49bf7a79de 100644 --- a/src/audio/mixin_mixout/mixin_mixout_hifi5.c +++ b/src/audio/mixin_mixout/mixin_mixout_hifi5.c @@ -142,7 +142,11 @@ static void mix_s24(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixe AE_LA32X2X2_IP(in_sample, in_sample1, inu, in); AE_LA32X2X2_IP(out_sample, out_sample1, outu1, out); out--; - out_sample = AE_ADD24S(in_sample, out_sample); + /* sign extent in samples as AE_ADD24S expects Q9.23 arguments */ + in_sample = AE_SLAI24S(AE_MOVF24X2_FROMINT32X2(in_sample), 0); + in_sample1 = AE_SLAI24S(AE_MOVF24X2_FROMINT32X2(in_sample1), 0); + /* out samples are already sign extended by other mixin in a loop below */ + out_sample = AE_ADD24S(in_sample, out_sample); out_sample1 = AE_ADD24S(in_sample1, out_sample1); AE_SA32X2X2_IP(out_sample, out_sample1, outu2, out); } @@ -152,6 +156,8 @@ static void mix_s24(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixe for (i = 0; i < left; i++) { 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)); } @@ -171,12 +177,17 @@ static void mix_s24(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixe left = n & 3; for (i = 0; i < m; i++) { AE_LA32X2X2_IP(in_sample, in_sample1, inu, in); + /* sign extension */ + in_sample = AE_SLAI24S(AE_MOVF24X2_FROMINT32X2(in_sample), 0); + in_sample1 = AE_SLAI24S(AE_MOVF24X2_FROMINT32X2(in_sample1), 0); AE_SA32X2X2_IP(in_sample, in_sample1, outu2, out); } AE_SA128POS_FP(outu2, out); /* process the left samples to avoid memory access overrun */ for (i = 0; i < left; i++) { 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)); } }