shithub: opus

Download patch

ref: 5c13840b53e6124fa52ba3e83a42c4f528626211
parent: 7b317ceb12f33499b32690762d07f5f220a321fa
author: Jean-Marc Valin <jeanmarcv@google.com>
date: Thu Jul 4 17:25:45 EDT 2024

Saturate de-emphasis so we can increase SIG_SAT

We were originally saturating the comb filter with enough margin
that the de-emphasis couldn't overflow at low frequency
(1/(1-.85) gain). The problem is that didn't leave enough headroom
for a full-scale HF signal.

--- a/celt/arch.h
+++ b/celt/arch.h
@@ -132,9 +132,14 @@
 #define Q15ONE 32767
 
 #define SIG_SHIFT 12
-/* Safe saturation value for 32-bit signals. Should be less than
-   2^31*(1-0.85) to avoid blowing up on DC at deemphasis.*/
-#define SIG_SAT (300000000)
+/* Safe saturation value for 32-bit signals. We need to make sure that we can
+   add two sig values and that the first stages of the MDCT don't cause an overflow.
+   The most constraining is the ARM_ASM comb filter where we shift left by one
+   and then add two values. Because of that, we use 2^29-1. SIG_SAT must be large
+   enough to fit a full-scale high-freq tone through the prefilter and comb filter,
+   meaning 1.85*1.75*2^(15+SIG_SHIFT) =  434529895.
+   so the limit should be about 2^31*sqrt(.5). */
+#define SIG_SAT (536870911)
 
 #define NORM_SCALING 16384
 
--- a/celt/celt_decoder.c
+++ b/celt/celt_decoder.c
@@ -261,8 +261,8 @@
    {
       celt_sig tmp0, tmp1;
       /* Add VERY_SMALL to x[] first to reduce dependency chain. */
-      tmp0 = x0[j] + VERY_SMALL + m0;
-      tmp1 = x1[j] + VERY_SMALL + m1;
+      tmp0 = SATURATE(x0[j] + VERY_SMALL + m0, SIG_SAT);
+      tmp1 = SATURATE(x1[j] + VERY_SMALL + m1, SIG_SAT);
       m0 = MULT16_32_Q15(coef0, tmp0);
       m1 = MULT16_32_Q15(coef0, tmp1);
       pcm[2*j  ] = SCALEOUT(SIG2WORD16(tmp0));
@@ -314,7 +314,7 @@
          opus_val16 coef3 = coef[3];
          for (j=0;j<N;j++)
          {
-            celt_sig tmp = x[j] + m + VERY_SMALL;
+            celt_sig tmp = SATURATE(x[j] + m + VERY_SMALL, SIG_SAT);
             m = MULT16_32_Q15(coef0, tmp)
                           - MULT16_32_Q15(coef1, x[j]);
             tmp = SHL32(MULT16_32_Q15(coef3, tmp), 2);
@@ -328,7 +328,7 @@
          /* Shortcut for the standard (non-custom modes) case */
          for (j=0;j<N;j++)
          {
-            celt_sig tmp = x[j] + VERY_SMALL + m;
+            celt_sig tmp = SATURATE(x[j] + VERY_SMALL + m, SIG_SAT);
             m = MULT16_32_Q15(coef0, tmp);
             scratch[j] = tmp;
          }
@@ -340,7 +340,7 @@
          {
             for (j=0;j<N;j++)
             {
-               celt_sig tmp = x[j] + m + VERY_SMALL;
+               celt_sig tmp = SATURATE(x[j] + m + VERY_SMALL, SIG_SAT);
                m = MULT16_32_Q15(coef0, tmp);
                y[j*C] = SAT16(ADD32(y[j*C], SCALEOUT(SIG2WORD16(tmp))));
             }
@@ -349,7 +349,7 @@
          {
             for (j=0;j<N;j++)
             {
-               celt_sig tmp = x[j] + VERY_SMALL + m;
+               celt_sig tmp = SATURATE(x[j] + VERY_SMALL + m, SIG_SAT);
                m = MULT16_32_Q15(coef0, tmp);
                y[j*C] = SCALEOUT(SIG2WORD16(tmp));
             }
--