1885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* Copyright (c) 2007-2008 CSIRO
2885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   Copyright (c) 2007-2009 Xiph.Org Foundation
3885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   Written by Jean-Marc Valin */
4885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/*
5885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   Redistribution and use in source and binary forms, with or without
6885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   modification, are permitted provided that the following conditions
7885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   are met:
8885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
9885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   - Redistributions of source code must retain the above copyright
10885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   notice, this list of conditions and the following disclaimer.
11885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
12885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   - Redistributions in binary form must reproduce the above copyright
13885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   notice, this list of conditions and the following disclaimer in the
14885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   documentation and/or other materials provided with the distribution.
15885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
16885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
20885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org*/
28885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
29885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef HAVE_CONFIG_H
30885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "config.h"
31885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif
32885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
33885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "mathops.h"
34885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "cwrs.h"
35885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "vq.h"
36885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "arch.h"
37885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "os_support.h"
38885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "bands.h"
39885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "rate.h"
40885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
41885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgstatic void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_val16 s)
42885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{
43885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   int i;
44885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   celt_norm *Xptr;
45885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   Xptr = X;
46885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   for (i=0;i<len-stride;i++)
47885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   {
48885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      celt_norm x1, x2;
49885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      x1 = Xptr[0];
50885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      x2 = Xptr[stride];
51885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      Xptr[stride] = EXTRACT16(SHR32(MULT16_16(c,x2) + MULT16_16(s,x1), 15));
52885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      *Xptr++      = EXTRACT16(SHR32(MULT16_16(c,x1) - MULT16_16(s,x2), 15));
53885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   }
54885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   Xptr = &X[len-2*stride-1];
55885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   for (i=len-2*stride-1;i>=0;i--)
56885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   {
57885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      celt_norm x1, x2;
58885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      x1 = Xptr[0];
59885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      x2 = Xptr[stride];
60885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      Xptr[stride] = EXTRACT16(SHR32(MULT16_16(c,x2) + MULT16_16(s,x1), 15));
61885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      *Xptr--      = EXTRACT16(SHR32(MULT16_16(c,x1) - MULT16_16(s,x2), 15));
62885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   }
63885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org}
64885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
65885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgstatic void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread)
66885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{
67885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   static const int SPREAD_FACTOR[3]={15,10,5};
68885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   int i;
69885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   opus_val16 c, s;
70885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   opus_val16 gain, theta;
71885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   int stride2=0;
72885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   int factor;
73885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
74885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   if (2*K>=len || spread==SPREAD_NONE)
75885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      return;
76885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   factor = SPREAD_FACTOR[spread-1];
77885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
78885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   gain = celt_div((opus_val32)MULT16_16(Q15_ONE,len),(opus_val32)(len+factor*K));
79885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   theta = HALF16(MULT16_16_Q15(gain,gain));
80885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
81885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   c = celt_cos_norm(EXTEND32(theta));
82885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   s = celt_cos_norm(EXTEND32(SUB16(Q15ONE,theta))); /*  sin(theta) */
83885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
84885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   if (len>=8*stride)
85885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   {
86885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      stride2 = 1;
87885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      /* This is just a simple (equivalent) way of computing sqrt(len/stride) with rounding.
88885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         It's basically incrementing long as (stride2+0.5)^2 < len/stride. */
89885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      while ((stride2*stride2+stride2)*stride + (stride>>2) < len)
90885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         stride2++;
91885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   }
92885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   /*NOTE: As a minor optimization, we could be passing around log2(B), not B, for both this and for
93885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      extract_collapse_mask().*/
94885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   len /= stride;
95885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   for (i=0;i<stride;i++)
96885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   {
97885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      if (dir < 0)
98885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      {
99885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         if (stride2)
100885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org            exp_rotation1(X+i*len, len, stride2, s, c);
101885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         exp_rotation1(X+i*len, len, 1, c, s);
102885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      } else {
103885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         exp_rotation1(X+i*len, len, 1, c, -s);
104885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         if (stride2)
105885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org            exp_rotation1(X+i*len, len, stride2, s, -c);
106885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      }
107885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   }
108885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org}
109885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
110885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/** Takes the pitch vector and the decoded residual vector, computes the gain
111885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    that will give ||p+g*y||=1 and mixes the residual with the pitch. */
112885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgstatic void normalise_residual(int * OPUS_RESTRICT iy, celt_norm * OPUS_RESTRICT X,
113885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      int N, opus_val32 Ryy, opus_val16 gain)
114885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{
115885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   int i;
116885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef FIXED_POINT
117885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   int k;
118885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif
119885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   opus_val32 t;
120885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   opus_val16 g;
121885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
122885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef FIXED_POINT
123885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   k = celt_ilog2(Ryy)>>1;
124885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif
125885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   t = VSHR32(Ryy, 2*(k-7));
126885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   g = MULT16_16_P15(celt_rsqrt_norm(t),gain);
127885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
128885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   i=0;
129885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   do
130885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      X[i] = EXTRACT16(PSHR32(MULT16_16(g, iy[i]), k+1));
131885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   while (++i < N);
132885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org}
133885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
134885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgstatic unsigned extract_collapse_mask(int *iy, int N, int B)
135885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{
136885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   unsigned collapse_mask;
137885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   int N0;
138885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   int i;
139885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   if (B<=1)
140885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      return 1;
141885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   /*NOTE: As a minor optimization, we could be passing around log2(B), not B, for both this and for
142885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      exp_rotation().*/
143885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   N0 = N/B;
144885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   collapse_mask = 0;
145885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   i=0; do {
146885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      int j;
147885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      j=0; do {
148885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         collapse_mask |= (iy[i*N0+j]!=0)<<i;
149885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      } while (++j<N0);
150885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   } while (++i<B);
151885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   return collapse_mask;
152885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org}
153885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
154885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgunsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc
155885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef RESYNTH
156885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   , opus_val16 gain
157885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif
158885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   )
159885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{
160885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   VARDECL(celt_norm, y);
161885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   VARDECL(int, iy);
162885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   VARDECL(opus_val16, signx);
163885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   int i, j;
164885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   opus_val16 s;
165885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   int pulsesLeft;
166885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   opus_val32 sum;
167885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   opus_val32 xy;
168885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   opus_val16 yy;
169885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   unsigned collapse_mask;
170885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   SAVE_STACK;
171885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
172885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   celt_assert2(K>0, "alg_quant() needs at least one pulse");
173885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   celt_assert2(N>1, "alg_quant() needs at least two dimensions");
174885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
175885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   ALLOC(y, N, celt_norm);
176885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   ALLOC(iy, N, int);
177885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   ALLOC(signx, N, opus_val16);
178885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
179885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   exp_rotation(X, N, 1, B, K, spread);
180885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
181885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   /* Get rid of the sign */
182885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   sum = 0;
183885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   j=0; do {
184885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      if (X[j]>0)
185885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         signx[j]=1;
186885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      else {
187885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         signx[j]=-1;
188885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         X[j]=-X[j];
189885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      }
190885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      iy[j] = 0;
191885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      y[j] = 0;
192885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   } while (++j<N);
193885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
194885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   xy = yy = 0;
195885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
196885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   pulsesLeft = K;
197885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
198885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   /* Do a pre-search by projecting on the pyramid */
199885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   if (K > (N>>1))
200885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   {
201885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      opus_val16 rcp;
202885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      j=0; do {
203885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         sum += X[j];
204885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      }  while (++j<N);
205885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
206885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      /* If X is too small, just replace it with a pulse at 0 */
207885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef FIXED_POINT
208885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      if (sum <= K)
209885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#else
210885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      /* Prevents infinities and NaNs from causing too many pulses
211885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         to be allocated. 64 is an approximation of infinity here. */
212885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      if (!(sum > EPSILON && sum < 64))
213885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif
214885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      {
215885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         X[0] = QCONST16(1.f,14);
216885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         j=1; do
217885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org            X[j]=0;
218885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         while (++j<N);
219885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         sum = QCONST16(1.f,14);
220885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      }
221885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      rcp = EXTRACT16(MULT16_32_Q16(K-1, celt_rcp(sum)));
222885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      j=0; do {
223885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef FIXED_POINT
224885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         /* It's really important to round *towards zero* here */
225885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         iy[j] = MULT16_16_Q15(X[j],rcp);
226885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#else
227885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         iy[j] = (int)floor(rcp*X[j]);
228885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif
229885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         y[j] = (celt_norm)iy[j];
230885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         yy = MAC16_16(yy, y[j],y[j]);
231885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         xy = MAC16_16(xy, X[j],y[j]);
232885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         y[j] *= 2;
233885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         pulsesLeft -= iy[j];
234885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      }  while (++j<N);
235885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   }
236885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   celt_assert2(pulsesLeft>=1, "Allocated too many pulses in the quick pass");
237885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
238885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   /* This should never happen, but just in case it does (e.g. on silence)
239885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      we fill the first bin with pulses. */
240885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef FIXED_POINT_DEBUG
241885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   celt_assert2(pulsesLeft<=N+3, "Not enough pulses in the quick pass");
242885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif
243885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   if (pulsesLeft > N+3)
244885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   {
245885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      opus_val16 tmp = (opus_val16)pulsesLeft;
246885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      yy = MAC16_16(yy, tmp, tmp);
247885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      yy = MAC16_16(yy, tmp, y[0]);
248885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      iy[0] += pulsesLeft;
249885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      pulsesLeft=0;
250885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   }
251885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
252885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   s = 1;
253885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   for (i=0;i<pulsesLeft;i++)
254885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   {
255885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      int best_id;
256885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      opus_val32 best_num = -VERY_LARGE16;
257885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      opus_val16 best_den = 0;
258885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef FIXED_POINT
259885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      int rshift;
260885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif
261885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef FIXED_POINT
262885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      rshift = 1+celt_ilog2(K-pulsesLeft+i+1);
263885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif
264885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      best_id = 0;
265885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      /* The squared magnitude term gets added anyway, so we might as well
266885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         add it outside the loop */
267885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      yy = ADD32(yy, 1);
268885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      j=0;
269885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      do {
270885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         opus_val16 Rxy, Ryy;
271885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         /* Temporary sums of the new pulse(s) */
272885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         Rxy = EXTRACT16(SHR32(ADD32(xy, EXTEND32(X[j])),rshift));
273885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         /* We're multiplying y[j] by two so we don't have to do it here */
274885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         Ryy = ADD16(yy, y[j]);
275885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
276885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         /* Approximate score: we maximise Rxy/sqrt(Ryy) (we're guaranteed that
277885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org            Rxy is positive because the sign is pre-computed) */
278885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         Rxy = MULT16_16_Q15(Rxy,Rxy);
279885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         /* The idea is to check for num/den >= best_num/best_den, but that way
280885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org            we can do it without any division */
281885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         /* OPT: Make sure to use conditional moves here */
282885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         if (MULT16_16(best_den, Rxy) > MULT16_16(Ryy, best_num))
283885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         {
284885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org            best_den = Ryy;
285885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org            best_num = Rxy;
286885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org            best_id = j;
287885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         }
288885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      } while (++j<N);
289885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
290885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      /* Updating the sums of the new pulse(s) */
291885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      xy = ADD32(xy, EXTEND32(X[best_id]));
292885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      /* We're multiplying y[j] by two so we don't have to do it here */
293885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      yy = ADD16(yy, y[best_id]);
294885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
295885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      /* Only now that we've made the final choice, update y/iy */
296885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      /* Multiplying y[j] by 2 so we don't have to do it everywhere else */
297885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      y[best_id] += 2*s;
298885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      iy[best_id]++;
299885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   }
300885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
301885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   /* Put the original sign back */
302885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   j=0;
303885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   do {
304885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      X[j] = MULT16_16(signx[j],X[j]);
305885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      if (signx[j] < 0)
306885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         iy[j] = -iy[j];
307885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   } while (++j<N);
308885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   encode_pulses(iy, N, K, enc);
309885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
310885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef RESYNTH
311885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   normalise_residual(iy, X, N, yy, gain);
312885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   exp_rotation(X, N, -1, B, K, spread);
313885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif
314885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
315885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   collapse_mask = extract_collapse_mask(iy, N, B);
316885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   RESTORE_STACK;
317885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   return collapse_mask;
318885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org}
319885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
320885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/** Decode pulse vector and combine the result with the pitch vector to produce
321885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org    the final normalised signal in the current band. */
322885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgunsigned alg_unquant(celt_norm *X, int N, int K, int spread, int B,
323885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      ec_dec *dec, opus_val16 gain)
324885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{
325885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   int i;
326885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   opus_val32 Ryy;
327885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   unsigned collapse_mask;
328885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   VARDECL(int, iy);
329885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   SAVE_STACK;
330885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
331885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   celt_assert2(K>0, "alg_unquant() needs at least one pulse");
332885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   celt_assert2(N>1, "alg_unquant() needs at least two dimensions");
333885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   ALLOC(iy, N, int);
334885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   decode_pulses(iy, N, K, dec);
335885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   Ryy = 0;
336885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   i=0;
337885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   do {
338885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      Ryy = MAC16_16(Ryy, iy[i], iy[i]);
339885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   } while (++i < N);
340885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   normalise_residual(iy, X, N, Ryy, gain);
341885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   exp_rotation(X, N, -1, B, K, spread);
342885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   collapse_mask = extract_collapse_mask(iy, N, B);
343885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   RESTORE_STACK;
344885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   return collapse_mask;
345885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org}
346885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
347885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgvoid renormalise_vector(celt_norm *X, int N, opus_val16 gain)
348885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{
349885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   int i;
350885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef FIXED_POINT
351885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   int k;
352885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif
353885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   opus_val32 E = EPSILON;
354885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   opus_val16 g;
355885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   opus_val32 t;
356885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   celt_norm *xptr = X;
357885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   for (i=0;i<N;i++)
358885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   {
359885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      E = MAC16_16(E, *xptr, *xptr);
360885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      xptr++;
361885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   }
362885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef FIXED_POINT
363885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   k = celt_ilog2(E)>>1;
364885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif
365885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   t = VSHR32(E, 2*(k-7));
366885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   g = MULT16_16_P15(celt_rsqrt_norm(t),gain);
367885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
368885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   xptr = X;
369885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   for (i=0;i<N;i++)
370885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   {
371885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      *xptr = EXTRACT16(PSHR32(MULT16_16(g, *xptr), k+1));
372885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      xptr++;
373885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   }
374885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   /*return celt_sqrt(E);*/
375885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org}
376885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
377885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgint stereo_itheta(celt_norm *X, celt_norm *Y, int stereo, int N)
378885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{
379885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   int i;
380885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   int itheta;
381885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   opus_val16 mid, side;
382885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   opus_val32 Emid, Eside;
383885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
384885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   Emid = Eside = EPSILON;
385885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   if (stereo)
386885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   {
387885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      for (i=0;i<N;i++)
388885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      {
389885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         celt_norm m, s;
390885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         m = ADD16(SHR16(X[i],1),SHR16(Y[i],1));
391885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         s = SUB16(SHR16(X[i],1),SHR16(Y[i],1));
392885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         Emid = MAC16_16(Emid, m, m);
393885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         Eside = MAC16_16(Eside, s, s);
394885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      }
395885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   } else {
396885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      for (i=0;i<N;i++)
397885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      {
398885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         celt_norm m, s;
399885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         m = X[i];
400885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         s = Y[i];
401885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         Emid = MAC16_16(Emid, m, m);
402885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org         Eside = MAC16_16(Eside, s, s);
403885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org      }
404885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   }
405885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   mid = celt_sqrt(Emid);
406885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   side = celt_sqrt(Eside);
407885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef FIXED_POINT
408885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   /* 0.63662 = 2/pi */
409885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   itheta = MULT16_16_Q15(QCONST16(0.63662f,15),celt_atan2p(side, mid));
410885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#else
411885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   itheta = (int)floor(.5f+16384*0.63662f*atan2(side,mid));
412885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif
413885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org
414885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org   return itheta;
415885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org}
416