From eea914cb888209811e6d8f4b58f4f1224f913594 Mon Sep 17 00:00:00 2001
From: Jean-Marc Valin <jean-marc.valin@usherbrooke.ca>
Date: Sun, 12 Sep 2010 20:11:32 -0400
Subject: [PATCH] Simplifies vector renormalisation (and using it less)

---
 libcelt/bands.c | 14 +++++++++-----
 libcelt/vq.c    | 27 ++++++++++++++++++++-------
 libcelt/vq.h    |  4 +++-
 3 files changed, 32 insertions(+), 13 deletions(-)

diff --git a/libcelt/bands.c b/libcelt/bands.c
index 396835ccf..df311f7e1 100644
--- a/libcelt/bands.c
+++ b/libcelt/bands.c
@@ -177,7 +177,7 @@ void renormalise_bands(const CELTMode *m, celt_norm * restrict X, int end, int _
    for (c=0;c<C;c++)
    {
       i=0; do {
-         renormalise_vector(X+M*eBands[i]+c*M*m->shortMdctSize, Q15ONE, M*eBands[i+1]-M*eBands[i], 1);
+         renormalise_vector(X+M*eBands[i]+c*M*m->shortMdctSize, M*eBands[i+1]-M*eBands[i]);
       } while (++i<end);
    }
 }
@@ -563,8 +563,12 @@ static void quant_band(int encode, const CELTMode *m, int i, celt_norm *X, celt_
             if (stereo)
                stereo_band_mix(m, X, Y, bandE, 0, i, 1, N);
 
-            mid = renormalise_vector(X, Q15ONE, N, 1);
-            side = renormalise_vector(Y, Q15ONE, N, 1);
+            mid = vector_norm(X, N);
+            side = vector_norm(Y, N);
+            /* TODO: Renormalising X and Y *may* help fixed-point a bit at very high rate.
+                     Let's do that at higher complexity */
+            /*mid = renormalise_vector(X, Q15ONE, N, 1);
+            side = renormalise_vector(Y, Q15ONE, N, 1);*/
 
             /* theta is the atan() of the ratio between the (normalized)
                side and mid. With just that parameter, we can re-scale both
@@ -801,8 +805,8 @@ static void quant_band(int encode, const CELTMode *m, int i, celt_norm *X, celt_
          stereo_band_mix(m, X, Y, bandE, 0, i, -1, N);
          /* We only need to renormalize because quantization may not
             have preserved orthogonality of mid and side */
-         renormalise_vector(X, Q15ONE, N, 1);
-         renormalise_vector(Y, Q15ONE, N, 1);
+         renormalise_vector(X, N);
+         renormalise_vector(Y, N);
       }
    }
 }
diff --git a/libcelt/vq.c b/libcelt/vq.c
index 4876b5986..1b52ce19f 100644
--- a/libcelt/vq.c
+++ b/libcelt/vq.c
@@ -191,7 +191,7 @@ void alg_quant(celt_norm *X, int N, int K, int spread, int B, celt_norm *lowband
             X[j] = (int)(*seed)>>20;
          }
       }
-      renormalise_vector(X, Q15ONE, N, 1);
+      renormalise_vector(X, N);
       return;
    }
    K = get_pulses(K);
@@ -368,7 +368,7 @@ void alg_unquant(celt_norm *X, int N, int K, int spread, int B, celt_norm *lowba
             X[i] = (int)(*seed)>>20;
          }
       }
-      renormalise_vector(X, Q15ONE, N, 1);
+      renormalise_vector(X, N);
       return;
    }
    K = get_pulses(K);
@@ -384,7 +384,20 @@ void alg_unquant(celt_norm *X, int N, int K, int spread, int B, celt_norm *lowba
    RESTORE_STACK;
 }
 
-celt_word16 renormalise_vector(celt_norm *X, celt_word16 value, int N, int stride)
+celt_word16 vector_norm(const celt_norm *X, int N)
+{
+   int i;
+   celt_word32 E = EPSILON;
+   const celt_norm *xptr = X;
+   for (i=0;i<N;i++)
+   {
+      E = MAC16_16(E, *xptr, *xptr);
+      xptr++;
+   }
+   return celt_sqrt(E);
+}
+
+void renormalise_vector(celt_norm *X, int N)
 {
    int i;
 #ifdef FIXED_POINT
@@ -397,20 +410,20 @@ celt_word16 renormalise_vector(celt_norm *X, celt_word16 value, int N, int strid
    for (i=0;i<N;i++)
    {
       E = MAC16_16(E, *xptr, *xptr);
-      xptr += stride;
+      xptr++;
    }
 #ifdef FIXED_POINT
    k = celt_ilog2(E)>>1;
 #endif
    t = VSHR32(E, (k-7)<<1);
-   g = MULT16_16_Q15(value, celt_rsqrt_norm(t));
+   g = celt_rsqrt_norm(t);
 
    xptr = X;
    for (i=0;i<N;i++)
    {
       *xptr = EXTRACT16(PSHR32(MULT16_16(g, *xptr), k+1));
-      xptr += stride;
+      xptr++;
    }
-   return celt_sqrt(E);
+   /*return celt_sqrt(E);*/
 }
 
diff --git a/libcelt/vq.h b/libcelt/vq.h
index 432c8e580..5bea13205 100644
--- a/libcelt/vq.h
+++ b/libcelt/vq.h
@@ -62,6 +62,8 @@ void alg_quant(celt_norm *X, int N, int K, int spread, int B, celt_norm *lowband
  */
 void alg_unquant(celt_norm *X, int N, int K, int spread, int B, celt_norm *lowband, ec_dec *dec, celt_int32 *seed);
 
-celt_word16 renormalise_vector(celt_norm *X, celt_word16 value, int N, int stride);
+void renormalise_vector(celt_norm *X, int N);
+
+celt_word16 vector_norm(const celt_norm *X, int N);
 
 #endif /* VQ_H */
-- 
GitLab