cannam@154
|
1 /* Copyright (c) 2007-2008 CSIRO
|
cannam@154
|
2 Copyright (c) 2007-2009 Xiph.Org Foundation
|
cannam@154
|
3 Written by Jean-Marc Valin */
|
cannam@154
|
4 /*
|
cannam@154
|
5 Redistribution and use in source and binary forms, with or without
|
cannam@154
|
6 modification, are permitted provided that the following conditions
|
cannam@154
|
7 are met:
|
cannam@154
|
8
|
cannam@154
|
9 - Redistributions of source code must retain the above copyright
|
cannam@154
|
10 notice, this list of conditions and the following disclaimer.
|
cannam@154
|
11
|
cannam@154
|
12 - Redistributions in binary form must reproduce the above copyright
|
cannam@154
|
13 notice, this list of conditions and the following disclaimer in the
|
cannam@154
|
14 documentation and/or other materials provided with the distribution.
|
cannam@154
|
15
|
cannam@154
|
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
cannam@154
|
17 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
cannam@154
|
18 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
cannam@154
|
19 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
cannam@154
|
20 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
cannam@154
|
21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
cannam@154
|
22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
cannam@154
|
23 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
cannam@154
|
24 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
cannam@154
|
25 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
cannam@154
|
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
cannam@154
|
27 */
|
cannam@154
|
28
|
cannam@154
|
29 #ifdef HAVE_CONFIG_H
|
cannam@154
|
30 #include "config.h"
|
cannam@154
|
31 #endif
|
cannam@154
|
32
|
cannam@154
|
33 #include "mathops.h"
|
cannam@154
|
34 #include "cwrs.h"
|
cannam@154
|
35 #include "vq.h"
|
cannam@154
|
36 #include "arch.h"
|
cannam@154
|
37 #include "os_support.h"
|
cannam@154
|
38 #include "bands.h"
|
cannam@154
|
39 #include "rate.h"
|
cannam@154
|
40 #include "pitch.h"
|
cannam@154
|
41
|
cannam@154
|
42 #ifndef OVERRIDE_vq_exp_rotation1
|
cannam@154
|
43 static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_val16 s)
|
cannam@154
|
44 {
|
cannam@154
|
45 int i;
|
cannam@154
|
46 opus_val16 ms;
|
cannam@154
|
47 celt_norm *Xptr;
|
cannam@154
|
48 Xptr = X;
|
cannam@154
|
49 ms = NEG16(s);
|
cannam@154
|
50 for (i=0;i<len-stride;i++)
|
cannam@154
|
51 {
|
cannam@154
|
52 celt_norm x1, x2;
|
cannam@154
|
53 x1 = Xptr[0];
|
cannam@154
|
54 x2 = Xptr[stride];
|
cannam@154
|
55 Xptr[stride] = EXTRACT16(PSHR32(MAC16_16(MULT16_16(c, x2), s, x1), 15));
|
cannam@154
|
56 *Xptr++ = EXTRACT16(PSHR32(MAC16_16(MULT16_16(c, x1), ms, x2), 15));
|
cannam@154
|
57 }
|
cannam@154
|
58 Xptr = &X[len-2*stride-1];
|
cannam@154
|
59 for (i=len-2*stride-1;i>=0;i--)
|
cannam@154
|
60 {
|
cannam@154
|
61 celt_norm x1, x2;
|
cannam@154
|
62 x1 = Xptr[0];
|
cannam@154
|
63 x2 = Xptr[stride];
|
cannam@154
|
64 Xptr[stride] = EXTRACT16(PSHR32(MAC16_16(MULT16_16(c, x2), s, x1), 15));
|
cannam@154
|
65 *Xptr-- = EXTRACT16(PSHR32(MAC16_16(MULT16_16(c, x1), ms, x2), 15));
|
cannam@154
|
66 }
|
cannam@154
|
67 }
|
cannam@154
|
68 #endif /* OVERRIDE_vq_exp_rotation1 */
|
cannam@154
|
69
|
cannam@154
|
70 void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread)
|
cannam@154
|
71 {
|
cannam@154
|
72 static const int SPREAD_FACTOR[3]={15,10,5};
|
cannam@154
|
73 int i;
|
cannam@154
|
74 opus_val16 c, s;
|
cannam@154
|
75 opus_val16 gain, theta;
|
cannam@154
|
76 int stride2=0;
|
cannam@154
|
77 int factor;
|
cannam@154
|
78
|
cannam@154
|
79 if (2*K>=len || spread==SPREAD_NONE)
|
cannam@154
|
80 return;
|
cannam@154
|
81 factor = SPREAD_FACTOR[spread-1];
|
cannam@154
|
82
|
cannam@154
|
83 gain = celt_div((opus_val32)MULT16_16(Q15_ONE,len),(opus_val32)(len+factor*K));
|
cannam@154
|
84 theta = HALF16(MULT16_16_Q15(gain,gain));
|
cannam@154
|
85
|
cannam@154
|
86 c = celt_cos_norm(EXTEND32(theta));
|
cannam@154
|
87 s = celt_cos_norm(EXTEND32(SUB16(Q15ONE,theta))); /* sin(theta) */
|
cannam@154
|
88
|
cannam@154
|
89 if (len>=8*stride)
|
cannam@154
|
90 {
|
cannam@154
|
91 stride2 = 1;
|
cannam@154
|
92 /* This is just a simple (equivalent) way of computing sqrt(len/stride) with rounding.
|
cannam@154
|
93 It's basically incrementing long as (stride2+0.5)^2 < len/stride. */
|
cannam@154
|
94 while ((stride2*stride2+stride2)*stride + (stride>>2) < len)
|
cannam@154
|
95 stride2++;
|
cannam@154
|
96 }
|
cannam@154
|
97 /*NOTE: As a minor optimization, we could be passing around log2(B), not B, for both this and for
|
cannam@154
|
98 extract_collapse_mask().*/
|
cannam@154
|
99 len = celt_udiv(len, stride);
|
cannam@154
|
100 for (i=0;i<stride;i++)
|
cannam@154
|
101 {
|
cannam@154
|
102 if (dir < 0)
|
cannam@154
|
103 {
|
cannam@154
|
104 if (stride2)
|
cannam@154
|
105 exp_rotation1(X+i*len, len, stride2, s, c);
|
cannam@154
|
106 exp_rotation1(X+i*len, len, 1, c, s);
|
cannam@154
|
107 } else {
|
cannam@154
|
108 exp_rotation1(X+i*len, len, 1, c, -s);
|
cannam@154
|
109 if (stride2)
|
cannam@154
|
110 exp_rotation1(X+i*len, len, stride2, s, -c);
|
cannam@154
|
111 }
|
cannam@154
|
112 }
|
cannam@154
|
113 }
|
cannam@154
|
114
|
cannam@154
|
115 /** Takes the pitch vector and the decoded residual vector, computes the gain
|
cannam@154
|
116 that will give ||p+g*y||=1 and mixes the residual with the pitch. */
|
cannam@154
|
117 static void normalise_residual(int * OPUS_RESTRICT iy, celt_norm * OPUS_RESTRICT X,
|
cannam@154
|
118 int N, opus_val32 Ryy, opus_val16 gain)
|
cannam@154
|
119 {
|
cannam@154
|
120 int i;
|
cannam@154
|
121 #ifdef FIXED_POINT
|
cannam@154
|
122 int k;
|
cannam@154
|
123 #endif
|
cannam@154
|
124 opus_val32 t;
|
cannam@154
|
125 opus_val16 g;
|
cannam@154
|
126
|
cannam@154
|
127 #ifdef FIXED_POINT
|
cannam@154
|
128 k = celt_ilog2(Ryy)>>1;
|
cannam@154
|
129 #endif
|
cannam@154
|
130 t = VSHR32(Ryy, 2*(k-7));
|
cannam@154
|
131 g = MULT16_16_P15(celt_rsqrt_norm(t),gain);
|
cannam@154
|
132
|
cannam@154
|
133 i=0;
|
cannam@154
|
134 do
|
cannam@154
|
135 X[i] = EXTRACT16(PSHR32(MULT16_16(g, iy[i]), k+1));
|
cannam@154
|
136 while (++i < N);
|
cannam@154
|
137 }
|
cannam@154
|
138
|
cannam@154
|
139 static unsigned extract_collapse_mask(int *iy, int N, int B)
|
cannam@154
|
140 {
|
cannam@154
|
141 unsigned collapse_mask;
|
cannam@154
|
142 int N0;
|
cannam@154
|
143 int i;
|
cannam@154
|
144 if (B<=1)
|
cannam@154
|
145 return 1;
|
cannam@154
|
146 /*NOTE: As a minor optimization, we could be passing around log2(B), not B, for both this and for
|
cannam@154
|
147 exp_rotation().*/
|
cannam@154
|
148 N0 = celt_udiv(N, B);
|
cannam@154
|
149 collapse_mask = 0;
|
cannam@154
|
150 i=0; do {
|
cannam@154
|
151 int j;
|
cannam@154
|
152 unsigned tmp=0;
|
cannam@154
|
153 j=0; do {
|
cannam@154
|
154 tmp |= iy[i*N0+j];
|
cannam@154
|
155 } while (++j<N0);
|
cannam@154
|
156 collapse_mask |= (tmp!=0)<<i;
|
cannam@154
|
157 } while (++i<B);
|
cannam@154
|
158 return collapse_mask;
|
cannam@154
|
159 }
|
cannam@154
|
160
|
cannam@154
|
161 opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch)
|
cannam@154
|
162 {
|
cannam@154
|
163 VARDECL(celt_norm, y);
|
cannam@154
|
164 VARDECL(int, signx);
|
cannam@154
|
165 int i, j;
|
cannam@154
|
166 int pulsesLeft;
|
cannam@154
|
167 opus_val32 sum;
|
cannam@154
|
168 opus_val32 xy;
|
cannam@154
|
169 opus_val16 yy;
|
cannam@154
|
170 SAVE_STACK;
|
cannam@154
|
171
|
cannam@154
|
172 (void)arch;
|
cannam@154
|
173 ALLOC(y, N, celt_norm);
|
cannam@154
|
174 ALLOC(signx, N, int);
|
cannam@154
|
175
|
cannam@154
|
176 /* Get rid of the sign */
|
cannam@154
|
177 sum = 0;
|
cannam@154
|
178 j=0; do {
|
cannam@154
|
179 signx[j] = X[j]<0;
|
cannam@154
|
180 /* OPT: Make sure the compiler doesn't use a branch on ABS16(). */
|
cannam@154
|
181 X[j] = ABS16(X[j]);
|
cannam@154
|
182 iy[j] = 0;
|
cannam@154
|
183 y[j] = 0;
|
cannam@154
|
184 } while (++j<N);
|
cannam@154
|
185
|
cannam@154
|
186 xy = yy = 0;
|
cannam@154
|
187
|
cannam@154
|
188 pulsesLeft = K;
|
cannam@154
|
189
|
cannam@154
|
190 /* Do a pre-search by projecting on the pyramid */
|
cannam@154
|
191 if (K > (N>>1))
|
cannam@154
|
192 {
|
cannam@154
|
193 opus_val16 rcp;
|
cannam@154
|
194 j=0; do {
|
cannam@154
|
195 sum += X[j];
|
cannam@154
|
196 } while (++j<N);
|
cannam@154
|
197
|
cannam@154
|
198 /* If X is too small, just replace it with a pulse at 0 */
|
cannam@154
|
199 #ifdef FIXED_POINT
|
cannam@154
|
200 if (sum <= K)
|
cannam@154
|
201 #else
|
cannam@154
|
202 /* Prevents infinities and NaNs from causing too many pulses
|
cannam@154
|
203 to be allocated. 64 is an approximation of infinity here. */
|
cannam@154
|
204 if (!(sum > EPSILON && sum < 64))
|
cannam@154
|
205 #endif
|
cannam@154
|
206 {
|
cannam@154
|
207 X[0] = QCONST16(1.f,14);
|
cannam@154
|
208 j=1; do
|
cannam@154
|
209 X[j]=0;
|
cannam@154
|
210 while (++j<N);
|
cannam@154
|
211 sum = QCONST16(1.f,14);
|
cannam@154
|
212 }
|
cannam@154
|
213 #ifdef FIXED_POINT
|
cannam@154
|
214 rcp = EXTRACT16(MULT16_32_Q16(K, celt_rcp(sum)));
|
cannam@154
|
215 #else
|
cannam@154
|
216 /* Using K+e with e < 1 guarantees we cannot get more than K pulses. */
|
cannam@154
|
217 rcp = EXTRACT16(MULT16_32_Q16(K+0.8f, celt_rcp(sum)));
|
cannam@154
|
218 #endif
|
cannam@154
|
219 j=0; do {
|
cannam@154
|
220 #ifdef FIXED_POINT
|
cannam@154
|
221 /* It's really important to round *towards zero* here */
|
cannam@154
|
222 iy[j] = MULT16_16_Q15(X[j],rcp);
|
cannam@154
|
223 #else
|
cannam@154
|
224 iy[j] = (int)floor(rcp*X[j]);
|
cannam@154
|
225 #endif
|
cannam@154
|
226 y[j] = (celt_norm)iy[j];
|
cannam@154
|
227 yy = MAC16_16(yy, y[j],y[j]);
|
cannam@154
|
228 xy = MAC16_16(xy, X[j],y[j]);
|
cannam@154
|
229 y[j] *= 2;
|
cannam@154
|
230 pulsesLeft -= iy[j];
|
cannam@154
|
231 } while (++j<N);
|
cannam@154
|
232 }
|
cannam@154
|
233 celt_sig_assert(pulsesLeft>=0);
|
cannam@154
|
234
|
cannam@154
|
235 /* This should never happen, but just in case it does (e.g. on silence)
|
cannam@154
|
236 we fill the first bin with pulses. */
|
cannam@154
|
237 #ifdef FIXED_POINT_DEBUG
|
cannam@154
|
238 celt_sig_assert(pulsesLeft<=N+3);
|
cannam@154
|
239 #endif
|
cannam@154
|
240 if (pulsesLeft > N+3)
|
cannam@154
|
241 {
|
cannam@154
|
242 opus_val16 tmp = (opus_val16)pulsesLeft;
|
cannam@154
|
243 yy = MAC16_16(yy, tmp, tmp);
|
cannam@154
|
244 yy = MAC16_16(yy, tmp, y[0]);
|
cannam@154
|
245 iy[0] += pulsesLeft;
|
cannam@154
|
246 pulsesLeft=0;
|
cannam@154
|
247 }
|
cannam@154
|
248
|
cannam@154
|
249 for (i=0;i<pulsesLeft;i++)
|
cannam@154
|
250 {
|
cannam@154
|
251 opus_val16 Rxy, Ryy;
|
cannam@154
|
252 int best_id;
|
cannam@154
|
253 opus_val32 best_num;
|
cannam@154
|
254 opus_val16 best_den;
|
cannam@154
|
255 #ifdef FIXED_POINT
|
cannam@154
|
256 int rshift;
|
cannam@154
|
257 #endif
|
cannam@154
|
258 #ifdef FIXED_POINT
|
cannam@154
|
259 rshift = 1+celt_ilog2(K-pulsesLeft+i+1);
|
cannam@154
|
260 #endif
|
cannam@154
|
261 best_id = 0;
|
cannam@154
|
262 /* The squared magnitude term gets added anyway, so we might as well
|
cannam@154
|
263 add it outside the loop */
|
cannam@154
|
264 yy = ADD16(yy, 1);
|
cannam@154
|
265
|
cannam@154
|
266 /* Calculations for position 0 are out of the loop, in part to reduce
|
cannam@154
|
267 mispredicted branches (since the if condition is usually false)
|
cannam@154
|
268 in the loop. */
|
cannam@154
|
269 /* Temporary sums of the new pulse(s) */
|
cannam@154
|
270 Rxy = EXTRACT16(SHR32(ADD32(xy, EXTEND32(X[0])),rshift));
|
cannam@154
|
271 /* We're multiplying y[j] by two so we don't have to do it here */
|
cannam@154
|
272 Ryy = ADD16(yy, y[0]);
|
cannam@154
|
273
|
cannam@154
|
274 /* Approximate score: we maximise Rxy/sqrt(Ryy) (we're guaranteed that
|
cannam@154
|
275 Rxy is positive because the sign is pre-computed) */
|
cannam@154
|
276 Rxy = MULT16_16_Q15(Rxy,Rxy);
|
cannam@154
|
277 best_den = Ryy;
|
cannam@154
|
278 best_num = Rxy;
|
cannam@154
|
279 j=1;
|
cannam@154
|
280 do {
|
cannam@154
|
281 /* Temporary sums of the new pulse(s) */
|
cannam@154
|
282 Rxy = EXTRACT16(SHR32(ADD32(xy, EXTEND32(X[j])),rshift));
|
cannam@154
|
283 /* We're multiplying y[j] by two so we don't have to do it here */
|
cannam@154
|
284 Ryy = ADD16(yy, y[j]);
|
cannam@154
|
285
|
cannam@154
|
286 /* Approximate score: we maximise Rxy/sqrt(Ryy) (we're guaranteed that
|
cannam@154
|
287 Rxy is positive because the sign is pre-computed) */
|
cannam@154
|
288 Rxy = MULT16_16_Q15(Rxy,Rxy);
|
cannam@154
|
289 /* The idea is to check for num/den >= best_num/best_den, but that way
|
cannam@154
|
290 we can do it without any division */
|
cannam@154
|
291 /* OPT: It's not clear whether a cmov is faster than a branch here
|
cannam@154
|
292 since the condition is more often false than true and using
|
cannam@154
|
293 a cmov introduces data dependencies across iterations. The optimal
|
cannam@154
|
294 choice may be architecture-dependent. */
|
cannam@154
|
295 if (opus_unlikely(MULT16_16(best_den, Rxy) > MULT16_16(Ryy, best_num)))
|
cannam@154
|
296 {
|
cannam@154
|
297 best_den = Ryy;
|
cannam@154
|
298 best_num = Rxy;
|
cannam@154
|
299 best_id = j;
|
cannam@154
|
300 }
|
cannam@154
|
301 } while (++j<N);
|
cannam@154
|
302
|
cannam@154
|
303 /* Updating the sums of the new pulse(s) */
|
cannam@154
|
304 xy = ADD32(xy, EXTEND32(X[best_id]));
|
cannam@154
|
305 /* We're multiplying y[j] by two so we don't have to do it here */
|
cannam@154
|
306 yy = ADD16(yy, y[best_id]);
|
cannam@154
|
307
|
cannam@154
|
308 /* Only now that we've made the final choice, update y/iy */
|
cannam@154
|
309 /* Multiplying y[j] by 2 so we don't have to do it everywhere else */
|
cannam@154
|
310 y[best_id] += 2;
|
cannam@154
|
311 iy[best_id]++;
|
cannam@154
|
312 }
|
cannam@154
|
313
|
cannam@154
|
314 /* Put the original sign back */
|
cannam@154
|
315 j=0;
|
cannam@154
|
316 do {
|
cannam@154
|
317 /*iy[j] = signx[j] ? -iy[j] : iy[j];*/
|
cannam@154
|
318 /* OPT: The is more likely to be compiled without a branch than the code above
|
cannam@154
|
319 but has the same performance otherwise. */
|
cannam@154
|
320 iy[j] = (iy[j]^-signx[j]) + signx[j];
|
cannam@154
|
321 } while (++j<N);
|
cannam@154
|
322 RESTORE_STACK;
|
cannam@154
|
323 return yy;
|
cannam@154
|
324 }
|
cannam@154
|
325
|
cannam@154
|
326 unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc,
|
cannam@154
|
327 opus_val16 gain, int resynth, int arch)
|
cannam@154
|
328 {
|
cannam@154
|
329 VARDECL(int, iy);
|
cannam@154
|
330 opus_val16 yy;
|
cannam@154
|
331 unsigned collapse_mask;
|
cannam@154
|
332 SAVE_STACK;
|
cannam@154
|
333
|
cannam@154
|
334 celt_assert2(K>0, "alg_quant() needs at least one pulse");
|
cannam@154
|
335 celt_assert2(N>1, "alg_quant() needs at least two dimensions");
|
cannam@154
|
336
|
cannam@154
|
337 /* Covers vectorization by up to 4. */
|
cannam@154
|
338 ALLOC(iy, N+3, int);
|
cannam@154
|
339
|
cannam@154
|
340 exp_rotation(X, N, 1, B, K, spread);
|
cannam@154
|
341
|
cannam@154
|
342 yy = op_pvq_search(X, iy, K, N, arch);
|
cannam@154
|
343
|
cannam@154
|
344 encode_pulses(iy, N, K, enc);
|
cannam@154
|
345
|
cannam@154
|
346 if (resynth)
|
cannam@154
|
347 {
|
cannam@154
|
348 normalise_residual(iy, X, N, yy, gain);
|
cannam@154
|
349 exp_rotation(X, N, -1, B, K, spread);
|
cannam@154
|
350 }
|
cannam@154
|
351
|
cannam@154
|
352 collapse_mask = extract_collapse_mask(iy, N, B);
|
cannam@154
|
353 RESTORE_STACK;
|
cannam@154
|
354 return collapse_mask;
|
cannam@154
|
355 }
|
cannam@154
|
356
|
cannam@154
|
357 /** Decode pulse vector and combine the result with the pitch vector to produce
|
cannam@154
|
358 the final normalised signal in the current band. */
|
cannam@154
|
359 unsigned alg_unquant(celt_norm *X, int N, int K, int spread, int B,
|
cannam@154
|
360 ec_dec *dec, opus_val16 gain)
|
cannam@154
|
361 {
|
cannam@154
|
362 opus_val32 Ryy;
|
cannam@154
|
363 unsigned collapse_mask;
|
cannam@154
|
364 VARDECL(int, iy);
|
cannam@154
|
365 SAVE_STACK;
|
cannam@154
|
366
|
cannam@154
|
367 celt_assert2(K>0, "alg_unquant() needs at least one pulse");
|
cannam@154
|
368 celt_assert2(N>1, "alg_unquant() needs at least two dimensions");
|
cannam@154
|
369 ALLOC(iy, N, int);
|
cannam@154
|
370 Ryy = decode_pulses(iy, N, K, dec);
|
cannam@154
|
371 normalise_residual(iy, X, N, Ryy, gain);
|
cannam@154
|
372 exp_rotation(X, N, -1, B, K, spread);
|
cannam@154
|
373 collapse_mask = extract_collapse_mask(iy, N, B);
|
cannam@154
|
374 RESTORE_STACK;
|
cannam@154
|
375 return collapse_mask;
|
cannam@154
|
376 }
|
cannam@154
|
377
|
cannam@154
|
378 #ifndef OVERRIDE_renormalise_vector
|
cannam@154
|
379 void renormalise_vector(celt_norm *X, int N, opus_val16 gain, int arch)
|
cannam@154
|
380 {
|
cannam@154
|
381 int i;
|
cannam@154
|
382 #ifdef FIXED_POINT
|
cannam@154
|
383 int k;
|
cannam@154
|
384 #endif
|
cannam@154
|
385 opus_val32 E;
|
cannam@154
|
386 opus_val16 g;
|
cannam@154
|
387 opus_val32 t;
|
cannam@154
|
388 celt_norm *xptr;
|
cannam@154
|
389 E = EPSILON + celt_inner_prod(X, X, N, arch);
|
cannam@154
|
390 #ifdef FIXED_POINT
|
cannam@154
|
391 k = celt_ilog2(E)>>1;
|
cannam@154
|
392 #endif
|
cannam@154
|
393 t = VSHR32(E, 2*(k-7));
|
cannam@154
|
394 g = MULT16_16_P15(celt_rsqrt_norm(t),gain);
|
cannam@154
|
395
|
cannam@154
|
396 xptr = X;
|
cannam@154
|
397 for (i=0;i<N;i++)
|
cannam@154
|
398 {
|
cannam@154
|
399 *xptr = EXTRACT16(PSHR32(MULT16_16(g, *xptr), k+1));
|
cannam@154
|
400 xptr++;
|
cannam@154
|
401 }
|
cannam@154
|
402 /*return celt_sqrt(E);*/
|
cannam@154
|
403 }
|
cannam@154
|
404 #endif /* OVERRIDE_renormalise_vector */
|
cannam@154
|
405
|
cannam@154
|
406 int stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N, int arch)
|
cannam@154
|
407 {
|
cannam@154
|
408 int i;
|
cannam@154
|
409 int itheta;
|
cannam@154
|
410 opus_val16 mid, side;
|
cannam@154
|
411 opus_val32 Emid, Eside;
|
cannam@154
|
412
|
cannam@154
|
413 Emid = Eside = EPSILON;
|
cannam@154
|
414 if (stereo)
|
cannam@154
|
415 {
|
cannam@154
|
416 for (i=0;i<N;i++)
|
cannam@154
|
417 {
|
cannam@154
|
418 celt_norm m, s;
|
cannam@154
|
419 m = ADD16(SHR16(X[i],1),SHR16(Y[i],1));
|
cannam@154
|
420 s = SUB16(SHR16(X[i],1),SHR16(Y[i],1));
|
cannam@154
|
421 Emid = MAC16_16(Emid, m, m);
|
cannam@154
|
422 Eside = MAC16_16(Eside, s, s);
|
cannam@154
|
423 }
|
cannam@154
|
424 } else {
|
cannam@154
|
425 Emid += celt_inner_prod(X, X, N, arch);
|
cannam@154
|
426 Eside += celt_inner_prod(Y, Y, N, arch);
|
cannam@154
|
427 }
|
cannam@154
|
428 mid = celt_sqrt(Emid);
|
cannam@154
|
429 side = celt_sqrt(Eside);
|
cannam@154
|
430 #ifdef FIXED_POINT
|
cannam@154
|
431 /* 0.63662 = 2/pi */
|
cannam@154
|
432 itheta = MULT16_16_Q15(QCONST16(0.63662f,15),celt_atan2p(side, mid));
|
cannam@154
|
433 #else
|
cannam@154
|
434 itheta = (int)floor(.5f+16384*0.63662f*fast_atan2f(side,mid));
|
cannam@154
|
435 #endif
|
cannam@154
|
436
|
cannam@154
|
437 return itheta;
|
cannam@154
|
438 }
|