From 8f774fcb3563ad8685ff38cacecd39c7f467fc31 Mon Sep 17 00:00:00 2001 From: jrd Date: Fri, 24 Jul 2026 03:36:03 +0000 Subject: [PATCH] Build opus with NEON intrinsics on non-Android 64-bit ARM (#2806) The opus arch-optimisation block only matched the Android ABI names `armeabi-v7a` and `arm64-v8a`. Everywhere else Qt reports 64-bit ARM as `QT_ARCH=arm64` (Apple Silicon macOS, iOS, Linux aarch64), so those builds fell through to the plain-C opus path with no NEON acceleration. In fact the ARM NEON sources were never compiled on any target: the `SOURCES += $$SOURCES_OPUS_ARCH` line only lived in the x86 branch, so even the Android arch match populated the variable but never built it. Add an `arm64` branch that: - defines OPUS_ARM_MAY_HAVE_NEON_INTR (required for opus to include its arm/*.h headers) plus the PRESUME_NEON_INTR / PRESUME_AARCH64_NEON_INTR defines (NEON is part of the base AArch64 ISA, so it is always present); - compiles the NEON intrinsic sources, which need no special compiler flags, straight into SOURCES. Split SOURCES_OPUS_ARM into the self-contained NEON intrinsic files and the two NE10 files, which #include from the external Ne10 library that Jamulus does not bundle; only the NEON subset is compiled. The x86 and Android arch matches are untouched: their generated Makefiles are byte-identical before and after this change. Co-Authored-By: Claude Opus 4.8 --- Jamulus.pro | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/Jamulus.pro b/Jamulus.pro index fa956ef6d5..40e635275f 100644 --- a/Jamulus.pro +++ b/Jamulus.pro @@ -660,7 +660,8 @@ SOURCES_OPUS = libs/opus/celt/bands.c \ libs/opus/src/opus_encoder.c \ libs/opus/src/repacketizer.c -SOURCES_OPUS_ARM = libs/opus/celt/arm/armcpu.c \ +# NEON intrinsic sources: self-contained, need no external library. +SOURCES_OPUS_ARM_NEON = libs/opus/celt/arm/armcpu.c \ libs/opus/celt/arm/arm_celt_map.c \ libs/opus/silk/arm/arm_silk_map.c \ libs/opus/silk/arm/biquad_alt_neon_intr.c \ @@ -668,9 +669,14 @@ SOURCES_OPUS_ARM = libs/opus/celt/arm/armcpu.c \ libs/opus/silk/arm/NSQ_del_dec_neon_intr.c \ libs/opus/silk/arm/NSQ_neon.c \ libs/opus/celt/arm/celt_neon_intr.c \ - libs/opus/celt/arm/pitch_neon_intr.c \ - libs/opus/celt/arm/celt_fft_ne10.c \ + libs/opus/celt/arm/pitch_neon_intr.c +# NE10 sources: FFT/MDCT acceleration via the external Ne10 library, which +# Jamulus does not bundle (they #include unconditionally and are +# gated on HAVE_ARM_NE10, which we never define). Kept listed for completeness +# but never added to SOURCES. +SOURCES_OPUS_ARM_NE10 = libs/opus/celt/arm/celt_fft_ne10.c \ libs/opus/celt/arm/celt_mdct_ne10.c +SOURCES_OPUS_ARM = $$SOURCES_OPUS_ARM_NEON $$SOURCES_OPUS_ARM_NE10 SOURCES_OPUS_X86_SSE = libs/opus/celt/x86/x86cpu.c \ libs/opus/celt/x86/x86_celt_map.c \ @@ -690,6 +696,18 @@ contains(QT_ARCH, armeabi-v7a) | contains(QT_ARCH, arm64-v8a) { SOURCES_OPUS_ARCH += $$SOURCES_OPUS_ARM DEFINES_OPUS += OPUS_ARM_PRESUME_NEON=1 OPUS_ARM_PRESUME_NEON_INTR=1 contains(QT_ARCH, arm64-v8a):DEFINES_OPUS += OPUS_ARM_PRESUME_AARCH64_NEON_INTR +} else:contains(QT_ARCH, arm64) { + # arm64-v8a above is the Android ABI name; plain arm64 is what Qt reports + # for 64-bit ARM everywhere else (Apple Silicon macOS, iOS, Linux aarch64). + # NEON is part of the base AArch64 ISA, so the NEON intrinsics can be + # presumed present and compiled without special compiler flags (see the + # SOURCES_OPUS_ARCH handling below). + # OPUS_ARM_MAY_HAVE_NEON_INTR is required in addition to the PRESUME + # defines: opus gates the inclusion of its arm/*.h headers on it + # (see libs/opus/celt/pitch.h and libs/opus/celt/cpu_support.h). + HEADERS_OPUS += $$HEADERS_OPUS_ARM + SOURCES_OPUS_ARCH += $$SOURCES_OPUS_ARM_NEON + DEFINES_OPUS += OPUS_ARM_MAY_HAVE_NEON_INTR=1 OPUS_ARM_PRESUME_NEON_INTR=1 OPUS_ARM_PRESUME_AARCH64_NEON_INTR=1 } else:contains(QT_ARCH, x86) | contains(QT_ARCH, x86_64) { HEADERS_OPUS += $$HEADERS_OPUS_X86 SOURCES_OPUS_ARCH += $$SOURCES_OPUS_X86_SSE $$SOURCES_OPUS_X86_SSE2 $$SOURCES_OPUS_X86_SSE4 @@ -1172,6 +1190,11 @@ contains(CONFIG, "opus_shared_lib") { sse4_cc.variable_out = OBJECTS QMAKE_EXTRA_COMPILERS += sse_cc sse2_cc sse4_cc } + } else:contains(QT_ARCH, arm64) { + # Unlike the x86 SSE files above, the AArch64 NEON intrinsics need no + # special compiler flags (NEON is part of the base AArch64 ISA), so + # they can be compiled like any other source file. + SOURCES += $$SOURCES_OPUS_ARCH } }