Coverage Report

Created: 2025-12-31 07:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opus/celt/pitch.c
Line
Count
Source
1
/* Copyright (c) 2007-2008 CSIRO
2
   Copyright (c) 2007-2009 Xiph.Org Foundation
3
   Written by Jean-Marc Valin */
4
/**
5
   @file pitch.c
6
   @brief Pitch analysis
7
 */
8
9
/*
10
   Redistribution and use in source and binary forms, with or without
11
   modification, are permitted provided that the following conditions
12
   are met:
13
14
   - Redistributions of source code must retain the above copyright
15
   notice, this list of conditions and the following disclaimer.
16
17
   - Redistributions in binary form must reproduce the above copyright
18
   notice, this list of conditions and the following disclaimer in the
19
   documentation and/or other materials provided with the distribution.
20
21
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24
   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
25
   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
*/
33
34
#ifdef HAVE_CONFIG_H
35
#include "config.h"
36
#endif
37
38
#include "pitch.h"
39
#include "os_support.h"
40
#include "modes.h"
41
#include "stack_alloc.h"
42
#include "mathops.h"
43
#include "celt_lpc.h"
44
45
static void find_best_pitch(opus_val32 *xcorr, opus_val16 *y, int len,
46
                            int max_pitch, int *best_pitch
47
#ifdef FIXED_POINT
48
                            , int yshift, opus_val32 maxcorr
49
#endif
50
                            )
51
41.2k
{
52
41.2k
   int i, j;
53
41.2k
   opus_val32 Syy=1;
54
41.2k
   opus_val16 best_num[2];
55
41.2k
   opus_val32 best_den[2];
56
#ifdef FIXED_POINT
57
   int xshift;
58
59
   xshift = celt_ilog2(maxcorr)-14;
60
#endif
61
62
41.2k
   best_num[0] = -1;
63
41.2k
   best_num[1] = -1;
64
41.2k
   best_den[0] = 0;
65
41.2k
   best_den[1] = 0;
66
41.2k
   best_pitch[0] = 0;
67
41.2k
   best_pitch[1] = 1;
68
20.5M
   for (j=0;j<len;j++)
69
20.5M
      Syy = ADD32(Syy, SHR32(MULT16_16(y[j],y[j]), yshift));
70
9.62M
   for (i=0;i<max_pitch;i++)
71
9.57M
   {
72
9.57M
      if (xcorr[i]>0)
73
1.39M
      {
74
1.39M
         opus_val16 num;
75
1.39M
         opus_val32 xcorr16;
76
1.39M
         xcorr16 = EXTRACT16(VSHR32(xcorr[i], xshift));
77
1.39M
#ifndef FIXED_POINT
78
         /* Considering the range of xcorr16, this should avoid both underflows
79
            and overflows (inf) when squaring xcorr16 */
80
1.39M
         xcorr16 *= 1e-12f;
81
1.39M
#endif
82
1.39M
         num = MULT16_16_Q15(xcorr16,xcorr16);
83
1.39M
         if (MULT16_32_Q15(num,best_den[1]) > MULT16_32_Q15(best_num[1],Syy))
84
349k
         {
85
349k
            if (MULT16_32_Q15(num,best_den[0]) > MULT16_32_Q15(best_num[0],Syy))
86
251k
            {
87
251k
               best_num[1] = best_num[0];
88
251k
               best_den[1] = best_den[0];
89
251k
               best_pitch[1] = best_pitch[0];
90
251k
               best_num[0] = num;
91
251k
               best_den[0] = Syy;
92
251k
               best_pitch[0] = i;
93
251k
            } else {
94
98.8k
               best_num[1] = num;
95
98.8k
               best_den[1] = Syy;
96
98.8k
               best_pitch[1] = i;
97
98.8k
            }
98
349k
         }
99
1.39M
      }
100
9.57M
      Syy += SHR32(MULT16_16(y[i+len],y[i+len]),yshift) - SHR32(MULT16_16(y[i],y[i]),yshift);
101
9.57M
      Syy = MAX32(1, Syy);
102
9.57M
   }
103
41.2k
}
104
105
static void celt_fir5(opus_val16 *x,
106
         const opus_val16 *num,
107
         int N)
108
20.6k
{
109
20.6k
   int i;
110
20.6k
   opus_val16 num0, num1, num2, num3, num4;
111
20.6k
   opus_val32 mem0, mem1, mem2, mem3, mem4;
112
20.6k
   num0=num[0];
113
20.6k
   num1=num[1];
114
20.6k
   num2=num[2];
115
20.6k
   num3=num[3];
116
20.6k
   num4=num[4];
117
20.6k
   mem0=0;
118
20.6k
   mem1=0;
119
20.6k
   mem2=0;
120
20.6k
   mem3=0;
121
20.6k
   mem4=0;
122
21.1M
   for (i=0;i<N;i++)
123
21.0M
   {
124
21.0M
      opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
125
21.0M
      sum = MAC16_16(sum,num0,mem0);
126
21.0M
      sum = MAC16_16(sum,num1,mem1);
127
21.0M
      sum = MAC16_16(sum,num2,mem2);
128
21.0M
      sum = MAC16_16(sum,num3,mem3);
129
21.0M
      sum = MAC16_16(sum,num4,mem4);
130
21.0M
      mem4 = mem3;
131
21.0M
      mem3 = mem2;
132
21.0M
      mem2 = mem1;
133
21.0M
      mem1 = mem0;
134
21.0M
      mem0 = x[i];
135
21.0M
      x[i] = ROUND16(sum, SIG_SHIFT);
136
21.0M
   }
137
20.6k
}
138
139
140
void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp,
141
      int len, int C, int factor, int arch)
142
20.6k
{
143
20.6k
   int i;
144
20.6k
   opus_val32 ac[5];
145
20.6k
   opus_val16 tmp=Q15ONE;
146
20.6k
   opus_val16 lpc[4];
147
20.6k
   opus_val16 lpc2[5];
148
20.6k
   opus_val16 c1 = QCONST16(.8f,15);
149
20.6k
   int offset;
150
#ifdef FIXED_POINT
151
   int shift;
152
   opus_val32 maxabs;
153
#endif
154
20.6k
   offset = factor/2;
155
#ifdef FIXED_POINT
156
   maxabs = celt_maxabs32(x[0], len*factor);
157
   if (C==2)
158
   {
159
      opus_val32 maxabs_1 = celt_maxabs32(x[1], len*factor);
160
      maxabs = MAX32(maxabs, maxabs_1);
161
   }
162
   if (maxabs<1)
163
      maxabs=1;
164
   shift = celt_ilog2(maxabs)-10;
165
   if (shift<0)
166
      shift=0;
167
   if (C==2)
168
      shift++;
169
   for (i=1;i<len;i++)
170
      x_lp[i] = SHR32(x[0][(factor*i-offset)], shift+2) + SHR32(x[0][(factor*i+offset)], shift+2) + SHR32(x[0][factor*i], shift+1);
171
   x_lp[0] = SHR32(x[0][offset], shift+2) + SHR32(x[0][0], shift+1);
172
   if (C==2)
173
   {
174
      for (i=1;i<len;i++)
175
         x_lp[i] += SHR32(x[1][(factor*i-offset)], shift+2) + SHR32(x[1][(factor*i+offset)], shift+2) + SHR32(x[1][factor*i], shift+1);
176
      x_lp[0] += SHR32(x[1][offset], shift+2) + SHR32(x[1][0], shift+1);
177
   }
178
#else
179
21.0M
   for (i=1;i<len;i++)
180
21.0M
      x_lp[i] = .25f*x[0][(factor*i-offset)] + .25f*x[0][(factor*i+offset)] + .5f*x[0][factor*i];
181
20.6k
   x_lp[0] = .25f*x[0][offset] + .5f*x[0][0];
182
20.6k
   if (C==2)
183
15.8k
   {
184
16.2M
      for (i=1;i<len;i++)
185
16.2M
         x_lp[i] += .25f*x[1][(factor*i-offset)] + .25f*x[1][(factor*i+offset)] + .5f*x[1][factor*i];
186
15.8k
      x_lp[0] += .25f*x[1][offset] + .5f*x[1][0];
187
15.8k
   }
188
20.6k
#endif
189
20.6k
   _celt_autocorr(x_lp, ac, NULL, 0,
190
20.6k
                  4, len, arch);
191
192
   /* Noise floor -40 dB */
193
#ifdef FIXED_POINT
194
   ac[0] += SHR32(ac[0],13);
195
#else
196
20.6k
   ac[0] *= 1.0001f;
197
20.6k
#endif
198
   /* Lag windowing */
199
103k
   for (i=1;i<=4;i++)
200
82.4k
   {
201
      /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
202
#ifdef FIXED_POINT
203
      ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
204
#else
205
82.4k
      ac[i] -= ac[i]*(.008f*i)*(.008f*i);
206
82.4k
#endif
207
82.4k
   }
208
209
20.6k
   _celt_lpc(lpc, ac, 4);
210
103k
   for (i=0;i<4;i++)
211
82.4k
   {
212
82.4k
      tmp = MULT16_16_Q15(QCONST16(.9f,15), tmp);
213
82.4k
      lpc[i] = MULT16_16_Q15(lpc[i], tmp);
214
82.4k
   }
215
   /* Add a zero */
216
20.6k
   lpc2[0] = lpc[0] + QCONST16(.8f,SIG_SHIFT);
217
20.6k
   lpc2[1] = lpc[1] + MULT16_16_Q15(c1,lpc[0]);
218
20.6k
   lpc2[2] = lpc[2] + MULT16_16_Q15(c1,lpc[1]);
219
20.6k
   lpc2[3] = lpc[3] + MULT16_16_Q15(c1,lpc[2]);
220
20.6k
   lpc2[4] = MULT16_16_Q15(c1,lpc[3]);
221
20.6k
   celt_fir5(x_lp, lpc2, len);
222
20.6k
}
223
224
/* Pure C implementation. */
225
#ifdef FIXED_POINT
226
opus_val32
227
#else
228
void
229
#endif
230
celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y,
231
      opus_val32 *xcorr, int len, int max_pitch, int arch)
232
0
{
233
234
#if 0 /* This is a simple version of the pitch correlation that should work
235
         well on DSPs like Blackfin and TI C5x/C6x */
236
   int i, j;
237
#ifdef FIXED_POINT
238
   opus_val32 maxcorr=1;
239
#endif
240
#if !defined(OVERRIDE_PITCH_XCORR)
241
   (void)arch;
242
#endif
243
   for (i=0;i<max_pitch;i++)
244
   {
245
      opus_val32 sum = 0;
246
      for (j=0;j<len;j++)
247
         sum = MAC16_16(sum, _x[j], _y[i+j]);
248
      xcorr[i] = sum;
249
#ifdef FIXED_POINT
250
      maxcorr = MAX32(maxcorr, sum);
251
#endif
252
   }
253
#ifdef FIXED_POINT
254
   return maxcorr;
255
#endif
256
257
#else /* Unrolled version of the pitch correlation -- runs faster on x86 and ARM */
258
0
   int i;
259
   /*The EDSP version requires that max_pitch is at least 1, and that _x is
260
      32-bit aligned.
261
     Since it's hard to put asserts in assembly, put them here.*/
262
#ifdef FIXED_POINT
263
   opus_val32 maxcorr=1;
264
#endif
265
0
   celt_assert(max_pitch>0);
266
0
   celt_sig_assert(((size_t)_x&3)==0);
267
0
   for (i=0;i<max_pitch-3;i+=4)
268
0
   {
269
0
      opus_val32 sum[4]={0,0,0,0};
270
#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
271
      {
272
         opus_val32 sum_c[4]={0,0,0,0};
273
         xcorr_kernel_c(_x, _y+i, sum_c, len);
274
#endif
275
0
         xcorr_kernel(_x, _y+i, sum, len, arch);
276
#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
277
         celt_assert(memcmp(sum, sum_c, sizeof(sum)) == 0);
278
      }
279
#endif
280
0
      xcorr[i]=sum[0];
281
0
      xcorr[i+1]=sum[1];
282
0
      xcorr[i+2]=sum[2];
283
0
      xcorr[i+3]=sum[3];
284
#ifdef FIXED_POINT
285
      sum[0] = MAX32(sum[0], sum[1]);
286
      sum[2] = MAX32(sum[2], sum[3]);
287
      sum[0] = MAX32(sum[0], sum[2]);
288
      maxcorr = MAX32(maxcorr, sum[0]);
289
#endif
290
0
   }
291
   /* In case max_pitch isn't a multiple of 4, do non-unrolled version. */
292
0
   for (;i<max_pitch;i++)
293
0
   {
294
0
      opus_val32 sum;
295
0
      sum = celt_inner_prod(_x, _y+i, len, arch);
296
0
      xcorr[i] = sum;
297
#ifdef FIXED_POINT
298
      maxcorr = MAX32(maxcorr, sum);
299
#endif
300
0
   }
301
#ifdef FIXED_POINT
302
   return maxcorr;
303
#endif
304
0
#endif
305
0
}
306
307
void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTRICT y,
308
                  int len, int max_pitch, int *pitch, int arch)
309
20.6k
{
310
20.6k
   int i, j;
311
20.6k
   int lag;
312
20.6k
   int best_pitch[2]={0,0};
313
20.6k
   VARDECL(opus_val16, x_lp4);
314
20.6k
   VARDECL(opus_val16, y_lp4);
315
20.6k
   VARDECL(opus_val32, xcorr);
316
#ifdef FIXED_POINT
317
   opus_val32 maxcorr;
318
   opus_val32 xmax, ymax;
319
   int shift=0;
320
#endif
321
20.6k
   int offset;
322
323
20.6k
   SAVE_STACK;
324
325
20.6k
   celt_assert(len>0);
326
20.6k
   celt_assert(max_pitch>0);
327
20.6k
   lag = len+max_pitch;
328
329
20.6k
   ALLOC(x_lp4, len>>2, opus_val16);
330
20.6k
   ALLOC(y_lp4, lag>>2, opus_val16);
331
20.6k
   ALLOC(xcorr, max_pitch>>1, opus_val32);
332
333
   /* Downsample by 2 again */
334
6.85M
   for (j=0;j<len>>2;j++)
335
6.83M
      x_lp4[j] = x_lp[2*j];
336
10.0M
   for (j=0;j<lag>>2;j++)
337
10.0M
      y_lp4[j] = y[2*j];
338
339
#ifdef FIXED_POINT
340
   xmax = celt_maxabs16(x_lp4, len>>2);
341
   ymax = celt_maxabs16(y_lp4, lag>>2);
342
   shift = celt_ilog2(MAX32(1, MAX32(xmax, ymax))) - 14 + celt_ilog2(len)/2;
343
   if (shift>0)
344
   {
345
      for (j=0;j<len>>2;j++)
346
         x_lp4[j] = SHR16(x_lp4[j], shift);
347
      for (j=0;j<lag>>2;j++)
348
         y_lp4[j] = SHR16(y_lp4[j], shift);
349
      /* Use double the shift for a MAC */
350
      shift *= 2;
351
   } else {
352
      shift = 0;
353
   }
354
#endif
355
356
   /* Coarse search with 4x decimation */
357
358
#ifdef FIXED_POINT
359
   maxcorr =
360
#endif
361
20.6k
   celt_pitch_xcorr(x_lp4, y_lp4, xcorr, len>>2, max_pitch>>2, arch);
362
363
20.6k
   find_best_pitch(xcorr, y_lp4, len>>2, max_pitch>>2, best_pitch
364
#ifdef FIXED_POINT
365
                   , 0, maxcorr
366
#endif
367
20.6k
                   );
368
369
   /* Finer search with 2x decimation */
370
#ifdef FIXED_POINT
371
   maxcorr=1;
372
#endif
373
6.40M
   for (i=0;i<max_pitch>>1;i++)
374
6.38M
   {
375
6.38M
      opus_val32 sum;
376
6.38M
      xcorr[i] = 0;
377
6.38M
      if (abs(i-2*best_pitch[0])>2 && abs(i-2*best_pitch[1])>2)
378
6.20M
         continue;
379
#ifdef FIXED_POINT
380
      sum = 0;
381
      for (j=0;j<len>>1;j++)
382
         sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift);
383
#else
384
181k
      sum = celt_inner_prod(x_lp, y+i, len>>1, arch);
385
181k
#endif
386
181k
      xcorr[i] = MAX32(-1, sum);
387
#ifdef FIXED_POINT
388
      maxcorr = MAX32(maxcorr, sum);
389
#endif
390
181k
   }
391
20.6k
   find_best_pitch(xcorr, y, len>>1, max_pitch>>1, best_pitch
392
#ifdef FIXED_POINT
393
                   , shift+1, maxcorr
394
#endif
395
20.6k
                   );
396
397
   /* Refine by pseudo-interpolation */
398
20.6k
   if (best_pitch[0]>0 && best_pitch[0]<(max_pitch>>1)-1)
399
18.8k
   {
400
18.8k
      opus_val32 a, b, c;
401
18.8k
      a = xcorr[best_pitch[0]-1];
402
18.8k
      b = xcorr[best_pitch[0]];
403
18.8k
      c = xcorr[best_pitch[0]+1];
404
18.8k
      if ((c-a) > MULT16_32_Q15(QCONST16(.7f,15),b-a))
405
3.07k
         offset = 1;
406
15.7k
      else if ((a-c) > MULT16_32_Q15(QCONST16(.7f,15),b-c))
407
4.41k
         offset = -1;
408
11.3k
      else
409
11.3k
         offset = 0;
410
18.8k
   } else {
411
1.77k
      offset = 0;
412
1.77k
   }
413
20.6k
   *pitch = 2*best_pitch[0]-offset;
414
415
20.6k
   RESTORE_STACK;
416
20.6k
}
417
418
#ifdef FIXED_POINT
419
static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy)
420
{
421
   opus_val32 x2y2;
422
   int sx, sy, shift;
423
   opus_val32 g;
424
   opus_val16 den;
425
   if (xy == 0 || xx == 0 || yy == 0)
426
      return 0;
427
   sx = celt_ilog2(xx)-14;
428
   sy = celt_ilog2(yy)-14;
429
   shift = sx + sy;
430
   x2y2 = SHR32(MULT16_16(VSHR32(xx, sx), VSHR32(yy, sy)), 14);
431
   if (shift & 1) {
432
      if (x2y2 < 32768)
433
      {
434
         x2y2 <<= 1;
435
         shift--;
436
      } else {
437
         x2y2 >>= 1;
438
         shift++;
439
      }
440
   }
441
   den = celt_rsqrt_norm(x2y2);
442
   g = MULT16_32_Q15(den, xy);
443
   g = VSHR32(g, (shift>>1)-1);
444
   return EXTRACT16(MAX32(-Q15ONE, MIN32(g, Q15ONE)));
445
}
446
#else
447
static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy)
448
0
{
449
0
   return xy/celt_sqrt(1+xx*yy);
450
0
}
451
#endif
452
453
static const int second_check[16] = {0, 0, 3, 2, 3, 2, 5, 2, 3, 2, 3, 2, 5, 2, 3, 2};
454
opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
455
      int N, int *T0_, int prev_period, opus_val16 prev_gain, int arch)
456
0
{
457
0
   int k, i, T, T0;
458
0
   opus_val16 g, g0;
459
0
   opus_val16 pg;
460
0
   opus_val32 xy,xx,yy,xy2;
461
0
   opus_val32 xcorr[3];
462
0
   opus_val32 best_xy, best_yy;
463
0
   int offset;
464
0
   int minperiod0;
465
0
   VARDECL(opus_val32, yy_lookup);
466
0
   SAVE_STACK;
467
468
0
   minperiod0 = minperiod;
469
0
   maxperiod /= 2;
470
0
   minperiod /= 2;
471
0
   *T0_ /= 2;
472
0
   prev_period /= 2;
473
0
   N /= 2;
474
0
   x += maxperiod;
475
0
   if (*T0_>=maxperiod)
476
0
      *T0_=maxperiod-1;
477
478
0
   T = T0 = *T0_;
479
0
   ALLOC(yy_lookup, maxperiod+1, opus_val32);
480
0
   dual_inner_prod(x, x, x-T0, N, &xx, &xy, arch);
481
0
   yy_lookup[0] = xx;
482
0
   yy=xx;
483
0
   for (i=1;i<=maxperiod;i++)
484
0
   {
485
0
      yy = yy+MULT16_16(x[-i],x[-i])-MULT16_16(x[N-i],x[N-i]);
486
0
      yy_lookup[i] = MAX32(0, yy);
487
0
   }
488
0
   yy = yy_lookup[T0];
489
0
   best_xy = xy;
490
0
   best_yy = yy;
491
0
   g = g0 = compute_pitch_gain(xy, xx, yy);
492
   /* Look for any pitch at T/k */
493
0
   for (k=2;k<=15;k++)
494
0
   {
495
0
      int T1, T1b;
496
0
      opus_val16 g1;
497
0
      opus_val16 cont=0;
498
0
      opus_val16 thresh;
499
0
      T1 = celt_udiv(2*T0+k, 2*k);
500
0
      if (T1 < minperiod)
501
0
         break;
502
      /* Look for another strong correlation at T1b */
503
0
      if (k==2)
504
0
      {
505
0
         if (T1+T0>maxperiod)
506
0
            T1b = T0;
507
0
         else
508
0
            T1b = T0+T1;
509
0
      } else
510
0
      {
511
0
         T1b = celt_udiv(2*second_check[k]*T0+k, 2*k);
512
0
      }
513
0
      dual_inner_prod(x, &x[-T1], &x[-T1b], N, &xy, &xy2, arch);
514
0
      xy = HALF32(xy + xy2);
515
0
      yy = HALF32(yy_lookup[T1] + yy_lookup[T1b]);
516
0
      g1 = compute_pitch_gain(xy, xx, yy);
517
0
      if (abs(T1-prev_period)<=1)
518
0
         cont = prev_gain;
519
0
      else if (abs(T1-prev_period)<=2 && 5*k*k < T0)
520
0
         cont = HALF16(prev_gain);
521
0
      else
522
0
         cont = 0;
523
0
      thresh = MAX16(QCONST16(.3f,15), MULT16_16_Q15(QCONST16(.7f,15),g0)-cont);
524
      /* Bias against very high pitch (very short period) to avoid false-positives
525
         due to short-term correlation */
526
0
      if (T1<3*minperiod)
527
0
         thresh = MAX16(QCONST16(.4f,15), MULT16_16_Q15(QCONST16(.85f,15),g0)-cont);
528
0
      else if (T1<2*minperiod)
529
0
         thresh = MAX16(QCONST16(.5f,15), MULT16_16_Q15(QCONST16(.9f,15),g0)-cont);
530
0
      if (g1 > thresh)
531
0
      {
532
0
         best_xy = xy;
533
0
         best_yy = yy;
534
0
         T = T1;
535
0
         g = g1;
536
0
      }
537
0
   }
538
0
   best_xy = MAX32(0, best_xy);
539
0
   if (best_yy <= best_xy)
540
0
      pg = Q15ONE;
541
0
   else
542
0
      pg = SHR32(frac_div32(best_xy,best_yy+1),16);
543
544
0
   for (k=0;k<3;k++)
545
0
      xcorr[k] = celt_inner_prod(x, x-(T+k-1), N, arch);
546
0
   if ((xcorr[2]-xcorr[0]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[0]))
547
0
      offset = 1;
548
0
   else if ((xcorr[0]-xcorr[2]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[2]))
549
0
      offset = -1;
550
0
   else
551
0
      offset = 0;
552
0
   if (pg > g)
553
0
      pg = g;
554
0
   *T0_ = 2*T+offset;
555
556
0
   if (*T0_<minperiod0)
557
0
      *T0_=minperiod0;
558
0
   RESTORE_STACK;
559
0
   return pg;
560
0
}