From 280fd609164a3137c53d760a52fa78bbaf37d5d0 Mon Sep 17 00:00:00 2001 From: Jeongkeun Kim Date: Thu, 6 Aug 2026 00:43:34 +0900 Subject: [PATCH] avcodec/aarch64: add NEON lfe_x96_fixed for DCA DSP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement the fixed-point LFE x96 interpolation filter in AArch64 NEON. Four input samples are processed per iteration. The history sample is kept in a vector lane, and ext constructs the delayed input. Benchmarks by Martin Storsjö using checkasm: a53 a55 a520 a72 a76 a720 1.86x 1.88x 1.24x 1.99x 1.62x 2.30x Author's measurement on Neoverse-N1 (Oracle Cloud, clang 14): 1.29x. Signed-off-by: Jeongkeun Kim --- libavcodec/aarch64/dcadsp_init_aarch64.c | 3 ++ libavcodec/aarch64/dcadsp_neon.S | 38 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/libavcodec/aarch64/dcadsp_init_aarch64.c b/libavcodec/aarch64/dcadsp_init_aarch64.c index 1fc6ec7a32..acb4194e9d 100644 --- a/libavcodec/aarch64/dcadsp_init_aarch64.c +++ b/libavcodec/aarch64/dcadsp_init_aarch64.c @@ -30,6 +30,8 @@ void ff_lfe_fir0_float_neon(float *pcm_samples, const int32_t *lfe_samples, const float *filter_coeff, ptrdiff_t npcmblocks); void ff_lfe_fir1_float_neon(float *pcm_samples, const int32_t *lfe_samples, const float *filter_coeff, ptrdiff_t npcmblocks); +void ff_lfe_x96_fixed_neon(int32_t *dst, const int32_t *src, + int32_t *hist, ptrdiff_t len); av_cold void ff_dcadsp_init_aarch64(DCADSPContext *s) { @@ -38,5 +40,6 @@ av_cold void ff_dcadsp_init_aarch64(DCADSPContext *s) if (have_neon(cpu_flags)) { s->lfe_fir_float[0] = ff_lfe_fir0_float_neon; s->lfe_fir_float[1] = ff_lfe_fir1_float_neon; + s->lfe_x96_fixed = ff_lfe_x96_fixed_neon; } } diff --git a/libavcodec/aarch64/dcadsp_neon.S b/libavcodec/aarch64/dcadsp_neon.S index 2aee95f241..bc7e35f993 100644 --- a/libavcodec/aarch64/dcadsp_neon.S +++ b/libavcodec/aarch64/dcadsp_neon.S @@ -111,3 +111,41 @@ function ff_lfe_fir1_float_neon, export=1 b.gt .Louter1 ret endfunc + +function ff_lfe_x96_fixed_neon, export=1 + ldr w4, [x2] + dup v2.4s, w4 + mov w4, #0x013F + movk w4, #0x0020, lsl #16 + dup v3.4s, w4 + mov w4, #0xFEC1 + movk w4, #0x005F, lsl #16 + dup v4.4s, w4 +.Lx96d_loop: + ld1 {v0.4s}, [x1], #16 + subs x3, x3, #4 + ext v1.16b, v2.16b, v0.16b, #12 + smull v5.2d, v0.2s, v3.2s + smull2 v6.2d, v0.4s, v3.4s + smlal v5.2d, v1.2s, v4.2s + smlal2 v6.2d, v1.4s, v4.4s + smull v7.2d, v0.2s, v4.2s + smull2 v16.2d, v0.4s, v4.4s + smlal v7.2d, v1.2s, v3.2s + smlal2 v16.2d, v1.4s, v3.4s + mov v2.16b, v0.16b + sqrshrn v17.2s, v5.2d, #23 + sqrshrn2 v17.4s, v6.2d, #23 + sqrshrn v18.2s, v7.2d, #23 + sqrshrn2 v18.4s, v16.2d, #23 + sqshl v17.4s, v17.4s, #8 + sqshl v18.4s, v18.4s, #8 + sshr v17.4s, v17.4s, #8 + sshr v18.4s, v18.4s, #8 + zip1 v19.4s, v17.4s, v18.4s + zip2 v20.4s, v17.4s, v18.4s + st1 {v19.4s, v20.4s}, [x0], #32 + b.gt .Lx96d_loop + st1 {v2.s}[3], [x2] + ret +endfunc