1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
diff --git a/lib/rbcodec/codecs/libopus/celt/mdct.c b/lib/rbcodec/codecs/libopus/celt/mdct.c
index 0f9af9e..8754337 100644
--- a/lib/rbcodec/codecs/libopus/celt/mdct.c
+++ b/lib/rbcodec/codecs/libopus/celt/mdct.c
@@ -238,7 +238,7 @@ void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scala
 
    /* sin(x) ~= x here */
 #ifdef FIXED_POINT
-   sine = TRIG_UPSCALE*(QCONST16(0.7853981f, 15)+N2)/N;
+   sine = TRIG_UPSCALE*(QCONST16(0.7853981f, 15)+N2)/N; /* 0.78... = 2*PI*0.125 */
 #else
    sine = (kiss_twiddle_scalar)2*PI*(.125f)/N;
 #endif
@@ -249,18 +249,38 @@ void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scala
       const kiss_fft_scalar * OPUS_RESTRICT xp1 = in;
       const kiss_fft_scalar * OPUS_RESTRICT xp2 = in+stride*(N2-1);
       kiss_fft_scalar * OPUS_RESTRICT yp = f2;
-      const kiss_twiddle_scalar *t = &l->trig[0];
-      for(i=0;i<N4;i++)
-      {
-         kiss_fft_scalar yr, yi;
-         yr = -S_MUL(*xp2, t[i<<shift]) + S_MUL(*xp1,t[(N4-i)<<shift]);
-         yi =  -S_MUL(*xp2, t[(N4-i)<<shift]) - S_MUL(*xp1,t[i<<shift]);
-         /* works because the cos is nearly one */
-         *yp++ = yr - S_MUL(yi,sine);
-         *yp++ = yi + S_MUL(yr,sine);
-         xp1+=2*stride;
-         xp2-=2*stride;
-      }
+      const kiss_twiddle_scalar *t0 = &l->trig[0];
+      const kiss_twiddle_scalar *t1 = &l->trig[N4<<shift];
+
+      /* stride = 1<<shift */
+      if (stride != 1)
+         for(i=0;i<N4;i++)
+         {
+            kiss_fft_scalar yr, yi;
+            yr = -S_MUL(*xp2,*t0) + S_MUL(*xp1,*t1);
+            yi =  S_MUL(*xp2,*t1) + S_MUL(*xp1,*t0);
+            /* works because the cos is nearly one (yr*cos - yi*sin and yi*cos + yr*sin) */
+            *yp++ = yr + S_MUL(yi,sine);
+            *yp++ = S_MUL(yr,sine) - yi;
+            xp1+=2*stride;
+            xp2-=2*stride;
+            t0 +=stride;
+            t1 -=stride;
+         }
+      else
+         for(i=0;i<N4;i++)
+         {
+            kiss_fft_scalar yr, yi;
+            yr = -S_MUL(*xp2,*t0) + S_MUL(*xp1,*t1);
+            yi =  S_MUL(*xp2,*t1) + S_MUL(*xp1,*t0);
+            /* works because the cos is nearly one (yr*cos - yi*sin and yi*cos + yr*sin) */
+            *yp++ = yr + S_MUL(yi,sine);
+            *yp++ = S_MUL(yr,sine) - yi;
+            xp1+=2;
+            xp2-=2;
+            t0 +=1;
+            t1 -=1;
+         }
    }
 
    /* Inverse N/4 complex FFT. This one should *not* downscale even in fixed-point */
@@ -268,20 +288,25 @@ void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scala
 
    /* Post-rotate */
    {
+      const kiss_fft_scalar * OPUS_RESTRICT fp1 = f;
+      const kiss_fft_scalar * OPUS_RESTRICT fp2 = f+1;
       kiss_fft_scalar * OPUS_RESTRICT fp = f;
-      const kiss_twiddle_scalar *t = &l->trig[0];
+      const kiss_twiddle_scalar *t0 = &l->trig[0];
+      const kiss_twiddle_scalar *t1 = &l->trig[N4<<shift];
 
       for(i=0;i<N4;i++)
       {
-         kiss_fft_scalar re, im, yr, yi;
-         re = fp[0];
-         im = fp[1];
+         kiss_fft_scalar yr, yi;
          /* We'd scale up by 2 here, but instead it's done when mixing the windows */
-         yr = S_MUL(re,t[i<<shift]) - S_MUL(im,t[(N4-i)<<shift]);
-         yi = S_MUL(im,t[i<<shift]) + S_MUL(re,t[(N4-i)<<shift]);
-         /* works because the cos is nearly one */
+         yr = S_MUL(*fp1,*t0) - S_MUL(*fp2,*t1);
+         yi = S_MUL(*fp2,*t0) + S_MUL(*fp1,*t1);
+         /* works because the cos is nearly one (yr*cos - yi*sin and yi*cos + yr*sin) */
          *fp++ = yr - S_MUL(yi,sine);
          *fp++ = yi + S_MUL(yr,sine);
+         fp1+=2;
+         fp2+=2;
+         t0 +=stride;
+         t1 -=stride;
       }
    }
    /* De-shuffle the components for the middle of the window only */