[FFmpeg-cvslog] opusdsp: add ability to modify deemphasis constant

Lynne git at videolan.org
Sat Apr 27 12:14:15 EEST 2024


ffmpeg | branch: master | Lynne <dev at lynne.ee> | Mon Jan 29 04:31:43 2024 +0100| [134dba9544f4251ebf5fbbae72f2cddc390ac195] | committer: Lynne

opusdsp: add ability to modify deemphasis constant

xHE-AAC relies on the same postfilter mechanism
that Opus uses to improve clarity (albeit with a steeper
deemphasis filter).

The code to apply it is identical, it's still just a
simple IIR low-pass filter. This commit makes it possible
to use alternative constants.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=134dba9544f4251ebf5fbbae72f2cddc390ac195
---

 libavcodec/aarch64/opusdsp_init.c |  2 +-
 libavcodec/aarch64/opusdsp_neon.S | 28 +++++-----------------------
 libavcodec/opusdec_celt.c         |  6 ++++--
 libavcodec/opusdsp.c              |  6 ++++--
 libavcodec/opusdsp.h              |  4 +---
 libavcodec/opusenc.c              |  5 +++--
 libavcodec/opustab.c              | 28 ++++++++++++++++++++++++++++
 libavcodec/opustab.h              |  2 ++
 libavcodec/x86/opusdsp.asm        |  9 +++------
 libavcodec/x86/opusdsp_init.c     |  2 +-
 tests/checkasm/opusdsp.c          |  9 +++++----
 11 files changed, 57 insertions(+), 44 deletions(-)

diff --git a/libavcodec/aarch64/opusdsp_init.c b/libavcodec/aarch64/opusdsp_init.c
index bb6d71b66b..a727006593 100644
--- a/libavcodec/aarch64/opusdsp_init.c
+++ b/libavcodec/aarch64/opusdsp_init.c
@@ -23,7 +23,7 @@
 #include "libavcodec/opusdsp.h"
 
 void ff_opus_postfilter_neon(float *data, int period, float *gains, int len);
-float ff_opus_deemphasis_neon(float *out, float *in, float coeff, int len);
+float ff_opus_deemphasis_neon(float *out, float *in, float coeff, const float *weights, int len);
 
 av_cold void ff_opus_dsp_init_aarch64(OpusDSP *ctx)
 {
diff --git a/libavcodec/aarch64/opusdsp_neon.S b/libavcodec/aarch64/opusdsp_neon.S
index e933151ab4..253825aa61 100644
--- a/libavcodec/aarch64/opusdsp_neon.S
+++ b/libavcodec/aarch64/opusdsp_neon.S
@@ -18,29 +18,11 @@
 
 #include "libavutil/aarch64/asm.S"
 
-           // 0.85..^1    0.85..^2    0.85..^3    0.85..^4
-const tab_st, align=4
-        .word 0x3f599a00, 0x3f38f671, 0x3f1d382a, 0x3f05a32f
-endconst
-const tab_x0, align=4
-        .word 0x0,        0x3f599a00, 0x3f38f671, 0x3f1d382a
-endconst
-const tab_x1, align=4
-        .word 0x0,        0x0,        0x3f599a00, 0x3f38f671
-endconst
-const tab_x2, align=4
-        .word 0x0,        0x0,        0x0,        0x3f599a00
-endconst
-
 function ff_opus_deemphasis_neon, export=1
-        movrel          x4, tab_st
-        ld1             {v4.4s}, [x4]
-        movrel          x4, tab_x0
-        ld1             {v5.4s}, [x4]
-        movrel          x4, tab_x1
-        ld1             {v6.4s}, [x4]
-        movrel          x4, tab_x2
-        ld1             {v7.4s}, [x4]
+        ld1             {v4.4s}, [x2], #16
+        ld1             {v5.4s}, [x2], #16
+        ld1             {v6.4s}, [x2], #16
+        ld1             {v7.4s}, [x2]
 
         fmul            v0.4s, v4.4s, v0.s[0]
 
@@ -63,7 +45,7 @@ function ff_opus_deemphasis_neon, export=1
         st1             {v1.4s, v2.4s}, [x0], #32
         fmul            v0.4s, v4.4s, v2.s[3]
 
-        subs            w2, w2, #8
+        subs            w3, w3, #8
         b.gt            1b
 
         mov             s0, v2.s[3]
diff --git a/libavcodec/opusdec_celt.c b/libavcodec/opusdec_celt.c
index fd8e9929e9..b19342337d 100644
--- a/libavcodec/opusdec_celt.c
+++ b/libavcodec/opusdec_celt.c
@@ -460,7 +460,9 @@ int ff_celt_decode_frame(CeltFrame *f, OpusRangeCoder *rc,
         /* deemphasis */
         block->emph_coeff = f->opusdsp.deemphasis(output[i],
                                                   &block->buf[1024 - frame_size],
-                                                  block->emph_coeff, frame_size);
+                                                  block->emph_coeff,
+                                                  ff_opus_deemph_weights,
+                                                  frame_size);
     }
 
     if (channels == 1)
@@ -516,7 +518,7 @@ void ff_celt_flush(CeltFrame *f)
          * a lesser discontinuity when seeking.
          * The deemphasis functions differ from libopus in that they require
          * an initial state divided by the coefficient. */
-        block->emph_coeff = 0.0f / CELT_EMPH_COEFF;
+        block->emph_coeff = 0.0f / ff_opus_deemph_weights[0];
     }
     f->seed = 0;
 
diff --git a/libavcodec/opusdsp.c b/libavcodec/opusdsp.c
index 0764d712e4..e61cc36098 100644
--- a/libavcodec/opusdsp.c
+++ b/libavcodec/opusdsp.c
@@ -18,6 +18,7 @@
 
 #include "config.h"
 #include "libavutil/attributes.h"
+#include "libavutil/mem_internal.h"
 #include "opusdsp.h"
 
 static void postfilter_c(float *data, int period, float *gains, int len)
@@ -43,10 +44,11 @@ static void postfilter_c(float *data, int period, float *gains, int len)
     }
 }
 
-static float deemphasis_c(float *y, float *x, float coeff, int len)
+static float deemphasis_c(float *y, float *x, float coeff, const float *weights, int len)
 {
+    const float c = weights[0];
     for (int i = 0; i < len; i++)
-        coeff = y[i] = x[i] + coeff*CELT_EMPH_COEFF;
+        coeff = y[i] = x[i] + coeff*c;
 
     return coeff;
 }
diff --git a/libavcodec/opusdsp.h b/libavcodec/opusdsp.h
index c2a301e832..9d93336cfe 100644
--- a/libavcodec/opusdsp.h
+++ b/libavcodec/opusdsp.h
@@ -19,11 +19,9 @@
 #ifndef AVCODEC_OPUSDSP_H
 #define AVCODEC_OPUSDSP_H
 
-#define CELT_EMPH_COEFF 0.8500061035f
-
 typedef struct OpusDSP {
     void (*postfilter)(float *data, int period, float *gains, int len);
-    float (*deemphasis)(float *out, float *in, float coeff, int len);
+    float (*deemphasis)(float *out, float *in, float coeff, const float *weights, int len);
 } OpusDSP;
 
 void ff_opus_dsp_init(OpusDSP *ctx);
diff --git a/libavcodec/opusenc.c b/libavcodec/opusenc.c
index e0c1732227..0e4c3752a5 100644
--- a/libavcodec/opusenc.c
+++ b/libavcodec/opusenc.c
@@ -164,6 +164,7 @@ static void celt_apply_preemph_filter(OpusEncContext *s, CeltFrame *f)
 {
     const int subframesize = s->avctx->frame_size;
     const int subframes = OPUS_BLOCK_SIZE(s->packet.framesize) / subframesize;
+    const float c = ff_opus_deemph_weights[0];
 
     /* Filter overlap */
     for (int ch = 0; ch < f->channels; ch++) {
@@ -172,7 +173,7 @@ static void celt_apply_preemph_filter(OpusEncContext *s, CeltFrame *f)
         for (int i = 0; i < CELT_OVERLAP; i++) {
             float sample = b->overlap[i];
             b->overlap[i] = sample - m;
-            m = sample * CELT_EMPH_COEFF;
+            m = sample * c;
         }
         b->emph_coeff = m;
     }
@@ -185,7 +186,7 @@ static void celt_apply_preemph_filter(OpusEncContext *s, CeltFrame *f)
             for (int i = 0; i < subframesize; i++) {
                 float sample = b->samples[sf*subframesize + i];
                 b->samples[sf*subframesize + i] = sample - m;
-                m = sample * CELT_EMPH_COEFF;
+                m = sample * c;
             }
             if (sf != (subframes - 1))
                 b->emph_coeff = m;
diff --git a/libavcodec/opustab.c b/libavcodec/opustab.c
index 2a57511177..47624fe651 100644
--- a/libavcodec/opustab.c
+++ b/libavcodec/opustab.c
@@ -1159,3 +1159,31 @@ const uint32_t * const ff_celt_pvq_u_row[15] = {
     celt_pvq_u + 1207, celt_pvq_u + 1226, celt_pvq_u + 1240,
     celt_pvq_u + 1248, celt_pvq_u + 1254, celt_pvq_u + 1257
 };
+
+/* Deemphasis constant (alpha_p), as specified in RFC6716 as 0.8500061035.
+ * libopus uses a slighly rounded constant, set to 0.85 exactly,
+ * to simplify its fixed-point version, but it's not significant to impact
+ * compliance. */
+#define CELT_EMPH_COEFF 0.8500061035f
+
+DECLARE_ALIGNED(16, const float, ff_opus_deemph_weights)[] = {
+    CELT_EMPH_COEFF,
+    CELT_EMPH_COEFF*CELT_EMPH_COEFF,
+    CELT_EMPH_COEFF*CELT_EMPH_COEFF*CELT_EMPH_COEFF,
+    CELT_EMPH_COEFF*CELT_EMPH_COEFF*CELT_EMPH_COEFF*CELT_EMPH_COEFF,
+
+    0,
+    CELT_EMPH_COEFF,
+    CELT_EMPH_COEFF*CELT_EMPH_COEFF,
+    CELT_EMPH_COEFF*CELT_EMPH_COEFF*CELT_EMPH_COEFF,
+
+    0,
+    0,
+    CELT_EMPH_COEFF,
+    CELT_EMPH_COEFF*CELT_EMPH_COEFF,
+
+    0,
+    0,
+    0,
+    CELT_EMPH_COEFF,
+};
diff --git a/libavcodec/opustab.h b/libavcodec/opustab.h
index 9c9f1b9d98..57e546aef5 100644
--- a/libavcodec/opustab.h
+++ b/libavcodec/opustab.h
@@ -161,6 +161,8 @@ extern const float    ff_celt_window2[120];
 extern const float    ff_celt_window_padded[];
 static const float *const ff_celt_window = &ff_celt_window_padded[8];
 
+extern const float    ff_opus_deemph_weights[];
+
 extern const uint32_t * const ff_celt_pvq_u_row[15];
 FF_VISIBILITY_POP_HIDDEN
 
diff --git a/libavcodec/x86/opusdsp.asm b/libavcodec/x86/opusdsp.asm
index 418cc16330..635f59f83c 100644
--- a/libavcodec/x86/opusdsp.asm
+++ b/libavcodec/x86/opusdsp.asm
@@ -22,16 +22,13 @@
 
 SECTION_RODATA
 
-         ; 0.85..^1    0.85..^2    0.85..^3    0.85..^4
-tab_st: dd 0x3f599a00, 0x3f38f671, 0x3f1d382a, 0x3f05a32f
-
 SECTION .text
 
 INIT_XMM fma3
 %if UNIX64
-cglobal opus_deemphasis, 3, 3, 8, out, in, len
+cglobal opus_deemphasis, 4, 4, 8, out, in, weights, len
 %else
-cglobal opus_deemphasis, 4, 4, 8, out, in, coeff, len
+cglobal opus_deemphasis, 5, 5, 8, out, in, coeff, weights, len
 %endif
 %if ARCH_X86_32
     VBROADCASTSS m0, coeffm
@@ -41,7 +38,7 @@ cglobal opus_deemphasis, 4, 4, 8, out, in, coeff, len
     shufps m0, m0, 0
 %endif
 
-    movaps m4, [tab_st]
+    movaps m4, [weightsq]
     VBROADCASTSS m5, m4
     shufps m6, m4, m4, q1111
     shufps m7, m4, m4, q2222
diff --git a/libavcodec/x86/opusdsp_init.c b/libavcodec/x86/opusdsp_init.c
index 582fbb4f0c..66d6839589 100644
--- a/libavcodec/x86/opusdsp_init.c
+++ b/libavcodec/x86/opusdsp_init.c
@@ -23,7 +23,7 @@
 #include "libavcodec/opusdsp.h"
 
 void ff_opus_postfilter_fma3(float *data, int period, float *gains, int len);
-float ff_opus_deemphasis_fma3(float *out, float *in, float coeff, int len);
+float ff_opus_deemphasis_fma3(float *out, float *in, float coeff, const float *weights, int len);
 
 av_cold void ff_opus_dsp_init_x86(OpusDSP *ctx)
 {
diff --git a/tests/checkasm/opusdsp.c b/tests/checkasm/opusdsp.c
index 34ee5a4edc..b9ecc55240 100644
--- a/tests/checkasm/opusdsp.c
+++ b/tests/checkasm/opusdsp.c
@@ -19,6 +19,7 @@
 #include "libavutil/mem_internal.h"
 
 #include "libavcodec/opusdsp.h"
+#include "libavcodec/opustab.h"
 
 #include "checkasm.h"
 
@@ -69,17 +70,17 @@ static void test_deemphasis(void)
     LOCAL_ALIGNED(16, float, dst1, [FFALIGN(MAX_SIZE, 4)]);
     float coeff0 = (float)rnd() / (UINT_MAX >> 5) - 16.0f, coeff1 = coeff0;
 
-    declare_func_float(float, float *out, float *in, float coeff, int len);
+    declare_func_float(float, float *out, float *in, float coeff, const float *weights, int len);
 
     randomize_float(src, MAX_SIZE);
 
-    coeff0 = call_ref(dst0, src, coeff0, MAX_SIZE);
-    coeff1 = call_new(dst1, src, coeff1, MAX_SIZE);
+    coeff0 = call_ref(dst0, src, coeff0, ff_opus_deemph_weights, MAX_SIZE);
+    coeff1 = call_new(dst1, src, coeff1, ff_opus_deemph_weights, MAX_SIZE);
 
     if (!float_near_abs_eps(coeff0, coeff1, EPS) ||
         !float_near_abs_eps_array(dst0, dst1, EPS, MAX_SIZE))
         fail();
-    bench_new(dst1, src, coeff1, MAX_SIZE);
+    bench_new(dst1, src, coeff1, ff_opus_deemph_weights, MAX_SIZE);
 }
 
 void checkasm_check_opusdsp(void)



More information about the ffmpeg-cvslog mailing list