Coverage Report

Created: 2026-01-17 07:27

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
1.50M
{
52
1.50M
   int i, j;
53
1.50M
   opus_val32 Syy=1;
54
1.50M
   opus_val16 best_num[2];
55
1.50M
   opus_val32 best_den[2];
56
#ifdef FIXED_POINT
57
   int xshift;
58
59
   xshift = celt_ilog2(maxcorr)-14;
60
#endif
61
62
1.50M
   best_num[0] = -1;
63
1.50M
   best_num[1] = -1;
64
1.50M
   best_den[0] = 0;
65
1.50M
   best_den[1] = 0;
66
1.50M
   best_pitch[0] = 0;
67
1.50M
   best_pitch[1] = 1;
68
222M
   for (j=0;j<len;j++)
69
220M
      Syy = ADD32(Syy, SHR32(MULT16_16(y[j],y[j]), yshift));
70
553M
   for (i=0;i<max_pitch;i++)
71
552M
   {
72
552M
      if (xcorr[i]>0)
73
93.6M
      {
74
93.6M
         opus_val16 num;
75
93.6M
         opus_val32 xcorr16;
76
93.6M
         xcorr16 = EXTRACT16(VSHR32(xcorr[i], xshift));
77
93.6M
#ifndef FIXED_POINT
78
         /* Considering the range of xcorr16, this should avoid both underflows
79
            and overflows (inf) when squaring xcorr16 */
80
93.6M
         xcorr16 *= 1e-12f;
81
93.6M
#endif
82
93.6M
         num = MULT16_16_Q15(xcorr16,xcorr16);
83
93.6M
         if (MULT16_32_Q15(num,best_den[1]) > MULT16_32_Q15(best_num[1],Syy))
84
11.8M
         {
85
11.8M
            if (MULT16_32_Q15(num,best_den[0]) > MULT16_32_Q15(best_num[0],Syy))
86
7.86M
            {
87
7.86M
               best_num[1] = best_num[0];
88
7.86M
               best_den[1] = best_den[0];
89
7.86M
               best_pitch[1] = best_pitch[0];
90
7.86M
               best_num[0] = num;
91
7.86M
               best_den[0] = Syy;
92
7.86M
               best_pitch[0] = i;
93
7.86M
            } else {
94
3.93M
               best_num[1] = num;
95
3.93M
               best_den[1] = Syy;
96
3.93M
               best_pitch[1] = i;
97
3.93M
            }
98
11.8M
         }
99
93.6M
      }
100
552M
      Syy += SHR32(MULT16_16(y[i+len],y[i+len]),yshift) - SHR32(MULT16_16(y[i],y[i]),yshift);
101
552M
      Syy = MAX32(1, Syy);
102
552M
   }
103
1.50M
}
104
105
static void celt_fir5(opus_val16 *x,
106
         const opus_val16 *num,
107
         int N)
108
753k
{
109
753k
   int i;
110
753k
   opus_val16 num0, num1, num2, num3, num4;
111
753k
   opus_val32 mem0, mem1, mem2, mem3, mem4;
112
753k
   num0=num[0];
113
753k
   num1=num[1];
114
753k
   num2=num[2];
115
753k
   num3=num[3];
116
753k
   num4=num[4];
117
753k
   mem0=0;
118
753k
   mem1=0;
119
753k
   mem2=0;
120
753k
   mem3=0;
121
753k
   mem4=0;
122
533M
   for (i=0;i<N;i++)
123
532M
   {
124
532M
      opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
125
532M
      sum = MAC16_16(sum,num0,mem0);
126
532M
      sum = MAC16_16(sum,num1,mem1);
127
532M
      sum = MAC16_16(sum,num2,mem2);
128
532M
      sum = MAC16_16(sum,num3,mem3);
129
532M
      sum = MAC16_16(sum,num4,mem4);
130
532M
      mem4 = mem3;
131
532M
      mem3 = mem2;
132
532M
      mem2 = mem1;
133
532M
      mem1 = mem0;
134
532M
      mem0 = x[i];
135
532M
      x[i] = ROUND16(sum, SIG_SHIFT);
136
532M
   }
137
753k
}
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
753k
{
143
753k
   int i;
144
753k
   opus_val32 ac[5];
145
753k
   opus_val16 tmp=Q15ONE;
146
753k
   opus_val16 lpc[4];
147
753k
   opus_val16 lpc2[5];
148
753k
   opus_val16 c1 = QCONST16(.8f,15);
149
753k
   int offset;
150
#ifdef FIXED_POINT
151
   int shift;
152
   opus_val32 maxabs;
153
#endif
154
753k
   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
532M
   for (i=1;i<len;i++)
180
532M
      x_lp[i] = .25f*x[0][(factor*i-offset)] + .25f*x[0][(factor*i+offset)] + .5f*x[0][factor*i];
181
753k
   x_lp[0] = .25f*x[0][offset] + .5f*x[0][0];
182
753k
   if (C==2)
183
256k
   {
184
187M
      for (i=1;i<len;i++)
185
187M
         x_lp[i] += .25f*x[1][(factor*i-offset)] + .25f*x[1][(factor*i+offset)] + .5f*x[1][factor*i];
186
256k
      x_lp[0] += .25f*x[1][offset] + .5f*x[1][0];
187
256k
   }
188
753k
#endif
189
753k
   _celt_autocorr(x_lp, ac, NULL, 0,
190
753k
                  4, len, arch);
191
192
   /* Noise floor -40 dB */
193
#ifdef FIXED_POINT
194
   ac[0] += SHR32(ac[0],13);
195
#else
196
753k
   ac[0] *= 1.0001f;
197
753k
#endif
198
   /* Lag windowing */
199
3.76M
   for (i=1;i<=4;i++)
200
3.01M
   {
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
3.01M
      ac[i] -= ac[i]*(.008f*i)*(.008f*i);
206
3.01M
#endif
207
3.01M
   }
208
209
753k
   _celt_lpc(lpc, ac, 4);
210
3.76M
   for (i=0;i<4;i++)
211
3.01M
   {
212
3.01M
      tmp = MULT16_16_Q15(QCONST16(.9f,15), tmp);
213
3.01M
      lpc[i] = MULT16_16_Q15(lpc[i], tmp);
214
3.01M
   }
215
   /* Add a zero */
216
753k
   lpc2[0] = lpc[0] + QCONST16(.8f,SIG_SHIFT);
217
753k
   lpc2[1] = lpc[1] + MULT16_16_Q15(c1,lpc[0]);
218
753k
   lpc2[2] = lpc[2] + MULT16_16_Q15(c1,lpc[1]);
219
753k
   lpc2[3] = lpc[3] + MULT16_16_Q15(c1,lpc[2]);
220
753k
   lpc2[4] = MULT16_16_Q15(c1,lpc[3]);
221
753k
   celt_fir5(x_lp, lpc2, len);
222
753k
}
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
753k
{
310
753k
   int i, j;
311
753k
   int lag;
312
753k
   int best_pitch[2]={0,0};
313
753k
   VARDECL(opus_val16, x_lp4);
314
753k
   VARDECL(opus_val16, y_lp4);
315
753k
   VARDECL(opus_val32, xcorr);
316
#ifdef FIXED_POINT
317
   opus_val32 maxcorr;
318
   opus_val32 xmax, ymax;
319
   int shift=0;
320
#endif
321
753k
   int offset;
322
323
753k
   SAVE_STACK;
324
325
753k
   celt_assert(len>0);
326
753k
   celt_assert(max_pitch>0);
327
753k
   lag = len+max_pitch;
328
329
753k
   ALLOC(x_lp4, len>>2, opus_val16);
330
753k
   ALLOC(y_lp4, lag>>2, opus_val16);
331
753k
   ALLOC(xcorr, max_pitch>>1, opus_val32);
332
333
   /* Downsample by 2 again */
334
74.3M
   for (j=0;j<len>>2;j++)
335
73.5M
      x_lp4[j] = x_lp[2*j];
336
258M
   for (j=0;j<lag>>2;j++)
337
257M
      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
753k
   celt_pitch_xcorr(x_lp4, y_lp4, xcorr, len>>2, max_pitch>>2, arch);
362
363
753k
   find_best_pitch(xcorr, y_lp4, len>>2, max_pitch>>2, best_pitch
364
#ifdef FIXED_POINT
365
                   , 0, maxcorr
366
#endif
367
753k
                   );
368
369
   /* Finer search with 2x decimation */
370
#ifdef FIXED_POINT
371
   maxcorr=1;
372
#endif
373
369M
   for (i=0;i<max_pitch>>1;i++)
374
368M
   {
375
368M
      opus_val32 sum;
376
368M
      xcorr[i] = 0;
377
368M
      if (abs(i-2*best_pitch[0])>2 && abs(i-2*best_pitch[1])>2)
378
360M
         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
7.33M
      sum = celt_inner_prod(x_lp, y+i, len>>1, arch);
385
7.33M
#endif
386
7.33M
      xcorr[i] = MAX32(-1, sum);
387
#ifdef FIXED_POINT
388
      maxcorr = MAX32(maxcorr, sum);
389
#endif
390
7.33M
   }
391
753k
   find_best_pitch(xcorr, y, len>>1, max_pitch>>1, best_pitch
392
#ifdef FIXED_POINT
393
                   , shift+1, maxcorr
394
#endif
395
753k
                   );
396
397
   /* Refine by pseudo-interpolation */
398
753k
   if (best_pitch[0]>0 && best_pitch[0]<(max_pitch>>1)-1)
399
730k
   {
400
730k
      opus_val32 a, b, c;
401
730k
      a = xcorr[best_pitch[0]-1];
402
730k
      b = xcorr[best_pitch[0]];
403
730k
      c = xcorr[best_pitch[0]+1];
404
730k
      if ((c-a) > MULT16_32_Q15(QCONST16(.7f,15),b-a))
405
40.2k
         offset = 1;
406
689k
      else if ((a-c) > MULT16_32_Q15(QCONST16(.7f,15),b-c))
407
42.6k
         offset = -1;
408
647k
      else
409
647k
         offset = 0;
410
730k
   } else {
411
22.8k
      offset = 0;
412
22.8k
   }
413
753k
   *pitch = 2*best_pitch[0]-offset;
414
415
753k
   RESTORE_STACK;
416
753k
}
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
10.2M
{
449
10.2M
   return xy/celt_sqrt(1+xx*yy);
450
10.2M
}
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
753k
{
457
753k
   int k, i, T, T0;
458
753k
   opus_val16 g, g0;
459
753k
   opus_val16 pg;
460
753k
   opus_val32 xy,xx,yy,xy2;
461
753k
   opus_val32 xcorr[3];
462
753k
   opus_val32 best_xy, best_yy;
463
753k
   int offset;
464
753k
   int minperiod0;
465
753k
   VARDECL(opus_val32, yy_lookup);
466
753k
   SAVE_STACK;
467
468
753k
   minperiod0 = minperiod;
469
753k
   maxperiod /= 2;
470
753k
   minperiod /= 2;
471
753k
   *T0_ /= 2;
472
753k
   prev_period /= 2;
473
753k
   N /= 2;
474
753k
   x += maxperiod;
475
753k
   if (*T0_>=maxperiod)
476
12.2k
      *T0_=maxperiod-1;
477
478
753k
   T = T0 = *T0_;
479
753k
   ALLOC(yy_lookup, maxperiod+1, opus_val32);
480
753k
   dual_inner_prod(x, x, x-T0, N, &xx, &xy, arch);
481
753k
   yy_lookup[0] = xx;
482
753k
   yy=xx;
483
386M
   for (i=1;i<=maxperiod;i++)
484
385M
   {
485
385M
      yy = yy+MULT16_16(x[-i],x[-i])-MULT16_16(x[N-i],x[N-i]);
486
385M
      yy_lookup[i] = MAX32(0, yy);
487
385M
   }
488
753k
   yy = yy_lookup[T0];
489
753k
   best_xy = xy;
490
753k
   best_yy = yy;
491
753k
   g = g0 = compute_pitch_gain(xy, xx, yy);
492
   /* Look for any pitch at T/k */
493
10.2M
   for (k=2;k<=15;k++)
494
9.65M
   {
495
9.65M
      int T1, T1b;
496
9.65M
      opus_val16 g1;
497
9.65M
      opus_val16 cont=0;
498
9.65M
      opus_val16 thresh;
499
9.65M
      T1 = celt_udiv(2*T0+k, 2*k);
500
9.65M
      if (T1 < minperiod)
501
178k
         break;
502
      /* Look for another strong correlation at T1b */
503
9.47M
      if (k==2)
504
753k
      {
505
753k
         if (T1+T0>maxperiod)
506
206k
            T1b = T0;
507
547k
         else
508
547k
            T1b = T0+T1;
509
753k
      } else
510
8.72M
      {
511
8.72M
         T1b = celt_udiv(2*second_check[k]*T0+k, 2*k);
512
8.72M
      }
513
9.47M
      dual_inner_prod(x, &x[-T1], &x[-T1b], N, &xy, &xy2, arch);
514
9.47M
      xy = HALF32(xy + xy2);
515
9.47M
      yy = HALF32(yy_lookup[T1] + yy_lookup[T1b]);
516
9.47M
      g1 = compute_pitch_gain(xy, xx, yy);
517
9.47M
      if (abs(T1-prev_period)<=1)
518
282k
         cont = prev_gain;
519
9.19M
      else if (abs(T1-prev_period)<=2 && 5*k*k < T0)
520
11.1k
         cont = HALF16(prev_gain);
521
9.18M
      else
522
9.18M
         cont = 0;
523
9.47M
      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
9.47M
      if (T1<3*minperiod)
527
3.24M
         thresh = MAX16(QCONST16(.4f,15), MULT16_16_Q15(QCONST16(.85f,15),g0)-cont);
528
6.23M
      else if (T1<2*minperiod)
529
0
         thresh = MAX16(QCONST16(.5f,15), MULT16_16_Q15(QCONST16(.9f,15),g0)-cont);
530
9.47M
      if (g1 > thresh)
531
950k
      {
532
950k
         best_xy = xy;
533
950k
         best_yy = yy;
534
950k
         T = T1;
535
950k
         g = g1;
536
950k
      }
537
9.47M
   }
538
753k
   best_xy = MAX32(0, best_xy);
539
753k
   if (best_yy <= best_xy)
540
80.0k
      pg = Q15ONE;
541
673k
   else
542
673k
      pg = SHR32(frac_div32(best_xy,best_yy+1),16);
543
544
3.01M
   for (k=0;k<3;k++)
545
2.25M
      xcorr[k] = celt_inner_prod(x, x-(T+k-1), N, arch);
546
753k
   if ((xcorr[2]-xcorr[0]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[0]))
547
76.1k
      offset = 1;
548
677k
   else if ((xcorr[0]-xcorr[2]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[2]))
549
119k
      offset = -1;
550
557k
   else
551
557k
      offset = 0;
552
753k
   if (pg > g)
553
333k
      pg = g;
554
753k
   *T0_ = 2*T+offset;
555
556
753k
   if (*T0_<minperiod0)
557
1.58k
      *T0_=minperiod0;
558
753k
   RESTORE_STACK;
559
753k
   return pg;
560
753k
}