shithub: opus

Download patch

ref: 798ab38b27e362c58108011f098e5b1b1a040c6b
parent: 0719f6fc25d6ab376f674cd204cf4f4ae2d57e21
author: Jean-Marc Valin <[email protected]>
date: Sun Jul 12 16:41:29 EDT 2009

Using normalised M/S stereo data for folding and use separate folding gains
for M and S.

--- a/libcelt/bands.c
+++ b/libcelt/bands.c
@@ -458,7 +458,7 @@
       /* If pitch isn't available, use intra-frame prediction */
       if ((eBands[i] >= m->pitchEnd && fold) || q<=0)
       {
-         intra_fold(m, X+eBands[i], eBands[i+1]-eBands[i], q, norm, P+eBands[i], eBands[i], B);
+         intra_fold(m, X+eBands[i], eBands[i+1]-eBands[i], &q, norm, P+eBands[i], eBands[i], B);
       } else if (pitch_used && eBands[i] < m->pitchEnd) {
          for (j=eBands[i];j<eBands[i+1];j++)
             P[j] = MULT16_16_Q15(pgains[pband], P[j]);
@@ -502,6 +502,7 @@
    balance = 0;
    for (i=0;i<m->nbEBands;i++)
    {
+      int c;
       int tell;
       int q1, q2;
       celt_word16_t n;
@@ -618,7 +619,8 @@
       /* If pitch isn't available, use intra-frame prediction */
       if ((eBands[i] >= m->pitchEnd && fold) || (q1+q2)<=0)
       {
-         intra_fold(m, X+C*eBands[i], eBands[i+1]-eBands[i], q1+q2, norm, P+C*eBands[i], eBands[i], B);
+         int K[2] = {q1, q2};
+         intra_fold(m, X+C*eBands[i], eBands[i+1]-eBands[i], K, norm, P+C*eBands[i], eBands[i], B);
          deinterleave(P+C*eBands[i], C*N);
       } else if (pitch_used && eBands[i] < m->pitchEnd) {
          stereo_band_mix(m, P, bandE, qb==0, i, 1);
@@ -650,6 +652,10 @@
       mid = (1./32768)*imid;
       side = (1./32768)*iside;
 #endif
+      for (c=0;c<C;c++)
+         for (j=0;j<N;j++)
+            norm[C*(eBands[i]+j)+c] = MULT16_16_Q15(n,X[C*eBands[i]+c*N+j]);
+
       for (j=0;j<N;j++)
          X[C*eBands[i]+j] = MULT16_16_Q15(X[C*eBands[i]+j], mid);
       for (j=0;j<N;j++)
@@ -656,8 +662,6 @@
          X[C*eBands[i]+N+j] = MULT16_16_Q15(X[C*eBands[i]+N+j], side);
 
       interleave(X+C*eBands[i], C*N);
-      for (j=0;j<C*N;j++)
-         norm[C*eBands[i]+j] = MULT16_16_Q15(n,X[C*eBands[i]+j]);
 
 
       stereo_band_mix(m, X, bandE, 0, i, -1);
@@ -738,7 +742,7 @@
       /* If pitch isn't available, use intra-frame prediction */
       if ((eBands[i] >= m->pitchEnd && fold) || q<=0)
       {
-         intra_fold(m, X+eBands[i], eBands[i+1]-eBands[i], q, norm, P+eBands[i], eBands[i], B);
+         intra_fold(m, X+eBands[i], eBands[i+1]-eBands[i], &q, norm, P+eBands[i], eBands[i], B);
       } else if (pitch_used && eBands[i] < m->pitchEnd) {
          for (j=eBands[i];j<eBands[i+1];j++)
             P[j] = MULT16_16_Q15(pgains[pband], P[j]);
@@ -782,6 +786,7 @@
    balance = 0;
    for (i=0;i<m->nbEBands;i++)
    {
+      int c;
       int tell;
       int q1, q2;
       celt_word16_t n;
@@ -885,7 +890,8 @@
       /* If pitch isn't available, use intra-frame prediction */
       if ((eBands[i] >= m->pitchEnd && fold) || (q1+q2)<=0)
       {
-         intra_fold(m, X+C*eBands[i], eBands[i+1]-eBands[i], q1+q2, norm, P+C*eBands[i], eBands[i], B);
+         int K[2] = {q1, q2};
+         intra_fold(m, X+C*eBands[i], eBands[i+1]-eBands[i], K, norm, P+C*eBands[i], eBands[i], B);
          deinterleave(P+C*eBands[i], C*N);
       } else if (pitch_used && eBands[i] < m->pitchEnd) {
          stereo_band_mix(m, P, bandE, qb==0, i, 1);
@@ -918,15 +924,16 @@
       mid = (1./32768)*imid;
       side = (1./32768)*iside;
 #endif
+      for (c=0;c<C;c++)
+         for (j=0;j<N;j++)
+            norm[C*(eBands[i]+j)+c] = MULT16_16_Q15(n,X[C*eBands[i]+c*N+j]);
+
       for (j=0;j<N;j++)
          X[C*eBands[i]+j] = MULT16_16_Q15(X[C*eBands[i]+j], mid);
       for (j=0;j<N;j++)
          X[C*eBands[i]+N+j] = MULT16_16_Q15(X[C*eBands[i]+N+j], side);
-      
-      interleave(X+C*eBands[i], C*N);
-      for (j=0;j<C*N;j++)
-         norm[C*eBands[i]+j] = MULT16_16_Q15(n,X[C*eBands[i]+j]);
 
+      interleave(X+C*eBands[i], C*N);
 
       stereo_band_mix(m, X, bandE, 0, i, -1);
       renormalise_vector(X+C*eBands[i], Q15ONE, N, C);
--- a/libcelt/modes.h
+++ b/libcelt/modes.h
@@ -39,7 +39,7 @@
 #include "psy.h"
 #include "pitch.h"
 
-#define CELT_BITSTREAM_VERSION 0x80000008
+#define CELT_BITSTREAM_VERSION 0x80000009
 
 #ifdef STATIC_MODES
 #include "static_modes.h"
--- a/libcelt/vq.c
+++ b/libcelt/vq.c
@@ -370,17 +370,22 @@
          P[j] = Y[id++];
 }
 
-void intra_fold(const CELTMode *m, celt_norm_t * restrict x, int N, int K, celt_norm_t *Y, celt_norm_t * restrict P, int N0, int B)
+void intra_fold(const CELTMode *m, celt_norm_t * restrict x, int N, int *pulses, celt_norm_t *Y, celt_norm_t * restrict P, int N0, int B)
 {
+   int c;
    celt_word16_t pred_gain;
    const int C = CHANNELS(m);
 
-   if (K==0)
-      pred_gain = Q15ONE;
-   else
-      pred_gain = celt_div((celt_word32_t)MULT16_16(Q15_ONE,N),(celt_word32_t)(N+2*K*(K+1)));
-
    fold(m, N, Y, P, N0, B);
-   renormalise_vector(P, pred_gain, C*N, 1);
+   c=0;
+   do {
+      int K = pulses[c];
+      if (K==0)
+         pred_gain = Q15ONE;
+      else
+         pred_gain = celt_div((celt_word32_t)MULT16_16(Q15_ONE,N),(celt_word32_t)(N+2*K*(K+1)));
+
+      renormalise_vector(P+c, pred_gain, N, C);
+   } while (++c < C);
 }
 
--- a/libcelt/vq.h
+++ b/libcelt/vq.h
@@ -74,6 +74,6 @@
  * @param B Stride (number of channels multiplied by the number of MDCTs per frame)
  * @param N0 Number of valid offsets
  */
-void intra_fold(const CELTMode *m, celt_norm_t * restrict x, int N, int K, celt_norm_t *Y, celt_norm_t * restrict P, int N0, int B);
+void intra_fold(const CELTMode *m, celt_norm_t * restrict x, int N, int *pulses, celt_norm_t *Y, celt_norm_t * restrict P, int N0, int B);
 
 #endif /* VQ_H */