Coverage Report

Created: 2025-12-31 07:02

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