Coverage Report

Created: 2026-05-16 07:41

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
6.54M
{
52
6.54M
   int i, j;
53
6.54M
   opus_val32 Syy=1;
54
6.54M
   opus_val16 best_num[2];
55
6.54M
   opus_val32 best_den[2];
56
6.54M
#ifdef FIXED_POINT
57
6.54M
   int xshift;
58
59
6.54M
   xshift = celt_ilog2(maxcorr)-14;
60
6.54M
#endif
61
62
6.54M
   best_num[0] = -1;
63
6.54M
   best_num[1] = -1;
64
6.54M
   best_den[0] = 0;
65
6.54M
   best_den[1] = 0;
66
6.54M
   best_pitch[0] = 0;
67
6.54M
   best_pitch[1] = 1;
68
1.75G
   for (j=0;j<len;j++)
69
1.75G
      Syy = ADD32(Syy, SHR32(MULT16_16(y[j],y[j]), yshift));
70
2.40G
   for (i=0;i<max_pitch;i++)
71
2.40G
   {
72
2.40G
      if (xcorr[i]>0)
73
705M
      {
74
705M
         opus_val16 num;
75
705M
         opus_val32 xcorr16;
76
705M
         xcorr16 = EXTRACT16(VSHR32(xcorr[i], xshift));
77
#ifndef FIXED_POINT
78
         /* Considering the range of xcorr16, this should avoid both underflows
79
            and overflows (inf) when squaring xcorr16 */
80
         xcorr16 *= 1e-12f;
81
#endif
82
705M
         num = MULT16_16_Q15(xcorr16,xcorr16);
83
705M
         if (MULT16_32_Q15(num,best_den[1]) > MULT16_32_Q15(best_num[1],Syy))
84
28.9M
         {
85
28.9M
            if (MULT16_32_Q15(num,best_den[0]) > MULT16_32_Q15(best_num[0],Syy))
86
18.6M
            {
87
18.6M
               best_num[1] = best_num[0];
88
18.6M
               best_den[1] = best_den[0];
89
18.6M
               best_pitch[1] = best_pitch[0];
90
18.6M
               best_num[0] = num;
91
18.6M
               best_den[0] = Syy;
92
18.6M
               best_pitch[0] = i;
93
18.6M
            } else {
94
10.3M
               best_num[1] = num;
95
10.3M
               best_den[1] = Syy;
96
10.3M
               best_pitch[1] = i;
97
10.3M
            }
98
28.9M
         }
99
705M
      }
100
2.40G
      Syy += SHR32(MULT16_16(y[i+len],y[i+len]),yshift) - SHR32(MULT16_16(y[i],y[i]),yshift);
101
2.40G
      Syy = MAX32(1, Syy);
102
2.40G
   }
103
6.54M
}
104
105
static void celt_fir5(opus_val16 *x,
106
         const opus_val16 *num,
107
         int N)
108
3.27M
{
109
3.27M
   int i;
110
3.27M
   opus_val16 num0, num1, num2, num3, num4;
111
3.27M
   opus_val32 mem0, mem1, mem2, mem3, mem4;
112
3.27M
   num0=num[0];
113
3.27M
   num1=num[1];
114
3.27M
   num2=num[2];
115
3.27M
   num3=num[3];
116
3.27M
   num4=num[4];
117
3.27M
   mem0=0;
118
3.27M
   mem1=0;
119
3.27M
   mem2=0;
120
3.27M
   mem3=0;
121
3.27M
   mem4=0;
122
2.84G
   for (i=0;i<N;i++)
123
2.84G
   {
124
2.84G
      opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
125
2.84G
      sum = MAC16_16(sum,num0,mem0);
126
2.84G
      sum = MAC16_16(sum,num1,mem1);
127
2.84G
      sum = MAC16_16(sum,num2,mem2);
128
2.84G
      sum = MAC16_16(sum,num3,mem3);
129
2.84G
      sum = MAC16_16(sum,num4,mem4);
130
2.84G
      mem4 = mem3;
131
2.84G
      mem3 = mem2;
132
2.84G
      mem2 = mem1;
133
2.84G
      mem1 = mem0;
134
2.84G
      mem0 = x[i];
135
2.84G
      x[i] = ROUND16(sum, SIG_SHIFT);
136
2.84G
   }
137
3.27M
}
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
3.27M
{
143
3.27M
   int i;
144
3.27M
   opus_val32 ac[5];
145
3.27M
   opus_val16 tmp=Q15ONE;
146
3.27M
   opus_val16 lpc[4];
147
3.27M
   opus_val16 lpc2[5];
148
3.27M
   opus_val16 c1 = QCONST16(.8f,15);
149
3.27M
   int offset;
150
3.27M
#ifdef FIXED_POINT
151
3.27M
   int shift;
152
3.27M
   opus_val32 maxabs;
153
3.27M
#endif
154
3.27M
   offset = factor/2;
155
3.27M
#ifdef FIXED_POINT
156
3.27M
   maxabs = celt_maxabs32(x[0], len*factor);
157
3.27M
   if (C==2)
158
825k
   {
159
825k
      opus_val32 maxabs_1 = celt_maxabs32(x[1], len*factor);
160
825k
      maxabs = MAX32(maxabs, maxabs_1);
161
825k
   }
162
3.27M
   if (maxabs<1)
163
0
      maxabs=1;
164
3.27M
   shift = celt_ilog2(maxabs)-10;
165
3.27M
   if (shift<0)
166
2.87M
      shift=0;
167
3.27M
   if (C==2)
168
825k
      shift++;
169
2.84G
   for (i=1;i<len;i++)
170
2.84G
      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
3.27M
   x_lp[0] = SHR32(x[0][offset], shift+2) + SHR32(x[0][0], shift+1);
172
3.27M
   if (C==2)
173
825k
   {
174
763M
      for (i=1;i<len;i++)
175
762M
         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
825k
      x_lp[0] += SHR32(x[1][offset], shift+2) + SHR32(x[1][0], shift+1);
177
825k
   }
178
#else
179
   for (i=1;i<len;i++)
180
      x_lp[i] = .25f*x[0][(factor*i-offset)] + .25f*x[0][(factor*i+offset)] + .5f*x[0][factor*i];
181
   x_lp[0] = .25f*x[0][offset] + .5f*x[0][0];
182
   if (C==2)
183
   {
184
      for (i=1;i<len;i++)
185
         x_lp[i] += .25f*x[1][(factor*i-offset)] + .25f*x[1][(factor*i+offset)] + .5f*x[1][factor*i];
186
      x_lp[0] += .25f*x[1][offset] + .5f*x[1][0];
187
   }
188
#endif
189
3.27M
   _celt_autocorr(x_lp, ac, NULL, 0,
190
3.27M
                  4, len, arch);
191
192
   /* Noise floor -40 dB */
193
3.27M
#ifdef FIXED_POINT
194
3.27M
   ac[0] += SHR32(ac[0],13);
195
#else
196
   ac[0] *= 1.0001f;
197
#endif
198
   /* Lag windowing */
199
16.3M
   for (i=1;i<=4;i++)
200
13.0M
   {
201
      /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
202
13.0M
#ifdef FIXED_POINT
203
13.0M
      ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
204
#else
205
      ac[i] -= ac[i]*(.008f*i)*(.008f*i);
206
#endif
207
13.0M
   }
208
209
3.27M
   _celt_lpc(lpc, ac, 4);
210
16.3M
   for (i=0;i<4;i++)
211
13.0M
   {
212
13.0M
      tmp = MULT16_16_Q15(QCONST16(.9f,15), tmp);
213
13.0M
      lpc[i] = MULT16_16_Q15(lpc[i], tmp);
214
13.0M
   }
215
   /* Add a zero */
216
3.27M
   lpc2[0] = lpc[0] + QCONST16(.8f,SIG_SHIFT);
217
3.27M
   lpc2[1] = lpc[1] + MULT16_16_Q15(c1,lpc[0]);
218
3.27M
   lpc2[2] = lpc[2] + MULT16_16_Q15(c1,lpc[1]);
219
3.27M
   lpc2[3] = lpc[3] + MULT16_16_Q15(c1,lpc[2]);
220
3.27M
   lpc2[4] = MULT16_16_Q15(c1,lpc[3]);
221
3.27M
   celt_fir5(x_lp, lpc2, len);
222
3.27M
}
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
215M
{
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
215M
   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
215M
#ifdef FIXED_POINT
263
215M
   opus_val32 maxcorr=1;
264
215M
#endif
265
215M
   celt_assert(max_pitch>0);
266
215M
   celt_sig_assert(((size_t)_x&3)==0);
267
918M
   for (i=0;i<max_pitch-3;i+=4)
268
702M
   {
269
702M
      opus_val32 sum[4]={0,0,0,0};
270
702M
#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
271
702M
      {
272
702M
         opus_val32 sum_c[4]={0,0,0,0};
273
702M
         xcorr_kernel_c(_x, _y+i, sum_c, len);
274
702M
#endif
275
702M
         xcorr_kernel(_x, _y+i, sum, len, arch);
276
702M
#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
277
702M
         celt_assert(memcmp(sum, sum_c, sizeof(sum)) == 0);
278
702M
      }
279
0
#endif
280
0
      xcorr[i]=sum[0];
281
702M
      xcorr[i+1]=sum[1];
282
702M
      xcorr[i+2]=sum[2];
283
702M
      xcorr[i+3]=sum[3];
284
702M
#ifdef FIXED_POINT
285
702M
      sum[0] = MAX32(sum[0], sum[1]);
286
702M
      sum[2] = MAX32(sum[2], sum[3]);
287
702M
      sum[0] = MAX32(sum[0], sum[2]);
288
702M
      maxcorr = MAX32(maxcorr, sum[0]);
289
702M
#endif
290
702M
   }
291
   /* In case max_pitch isn't a multiple of 4, do non-unrolled version. */
292
587M
   for (;i<max_pitch;i++)
293
372M
   {
294
372M
      opus_val32 sum;
295
372M
      sum = celt_inner_prod(_x, _y+i, len, arch);
296
372M
      xcorr[i] = sum;
297
372M
#ifdef FIXED_POINT
298
372M
      maxcorr = MAX32(maxcorr, sum);
299
372M
#endif
300
372M
   }
301
215M
#ifdef FIXED_POINT
302
215M
   return maxcorr;
303
215M
#endif
304
215M
#endif
305
215M
}
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
3.27M
{
310
3.27M
   int i, j;
311
3.27M
   int lag;
312
3.27M
   int best_pitch[2]={0,0};
313
3.27M
   VARDECL(opus_val16, x_lp4);
314
3.27M
   VARDECL(opus_val16, y_lp4);
315
3.27M
   VARDECL(opus_val32, xcorr);
316
3.27M
#ifdef FIXED_POINT
317
3.27M
   opus_val32 maxcorr;
318
3.27M
   opus_val32 xmax, ymax;
319
3.27M
   int shift=0;
320
3.27M
#endif
321
3.27M
   int offset;
322
323
3.27M
   SAVE_STACK;
324
325
3.27M
   celt_assert(len>0);
326
3.27M
   celt_assert(max_pitch>0);
327
3.27M
   lag = len+max_pitch;
328
329
3.27M
   ALLOC(x_lp4, len>>2, opus_val16);
330
3.27M
   ALLOC(y_lp4, lag>>2, opus_val16);
331
3.27M
   ALLOC(xcorr, max_pitch>>1, opus_val32);
332
333
   /* Downsample by 2 again */
334
586M
   for (j=0;j<len>>2;j++)
335
583M
      x_lp4[j] = x_lp[2*j];
336
1.38G
   for (j=0;j<lag>>2;j++)
337
1.38G
      y_lp4[j] = y[2*j];
338
339
3.27M
#ifdef FIXED_POINT
340
3.27M
   xmax = celt_maxabs16(x_lp4, len>>2);
341
3.27M
   ymax = celt_maxabs16(y_lp4, lag>>2);
342
3.27M
   shift = celt_ilog2(MAX32(1, MAX32(xmax, ymax))) - 14 + celt_ilog2(len)/2;
343
3.27M
   if (shift>0)
344
0
   {
345
0
      for (j=0;j<len>>2;j++)
346
0
         x_lp4[j] = SHR16(x_lp4[j], shift);
347
0
      for (j=0;j<lag>>2;j++)
348
0
         y_lp4[j] = SHR16(y_lp4[j], shift);
349
      /* Use double the shift for a MAC */
350
0
      shift *= 2;
351
3.27M
   } else {
352
3.27M
      shift = 0;
353
3.27M
   }
354
3.27M
#endif
355
356
   /* Coarse search with 4x decimation */
357
358
3.27M
#ifdef FIXED_POINT
359
3.27M
   maxcorr =
360
3.27M
#endif
361
3.27M
   celt_pitch_xcorr(x_lp4, y_lp4, xcorr, len>>2, max_pitch>>2, arch);
362
363
3.27M
   find_best_pitch(xcorr, y_lp4, len>>2, max_pitch>>2, best_pitch
364
3.27M
#ifdef FIXED_POINT
365
3.27M
                   , 0, maxcorr
366
3.27M
#endif
367
3.27M
                   );
368
369
   /* Finer search with 2x decimation */
370
3.27M
#ifdef FIXED_POINT
371
3.27M
   maxcorr=1;
372
3.27M
#endif
373
1.60G
   for (i=0;i<max_pitch>>1;i++)
374
1.60G
   {
375
1.60G
      opus_val32 sum;
376
1.60G
      xcorr[i] = 0;
377
1.60G
      if (abs(i-2*best_pitch[0])>2 && abs(i-2*best_pitch[1])>2)
378
1.57G
         continue;
379
27.1M
#ifdef FIXED_POINT
380
27.1M
      sum = 0;
381
9.79G
      for (j=0;j<len>>1;j++)
382
9.77G
         sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift);
383
#else
384
      sum = celt_inner_prod(x_lp, y+i, len>>1, arch);
385
#endif
386
27.1M
      xcorr[i] = MAX32(-1, sum);
387
27.1M
#ifdef FIXED_POINT
388
27.1M
      maxcorr = MAX32(maxcorr, sum);
389
27.1M
#endif
390
27.1M
   }
391
3.27M
   find_best_pitch(xcorr, y, len>>1, max_pitch>>1, best_pitch
392
3.27M
#ifdef FIXED_POINT
393
3.27M
                   , shift+1, maxcorr
394
3.27M
#endif
395
3.27M
                   );
396
397
   /* Refine by pseudo-interpolation */
398
3.27M
   if (best_pitch[0]>0 && best_pitch[0]<(max_pitch>>1)-1)
399
3.15M
   {
400
3.15M
      opus_val32 a, b, c;
401
3.15M
      a = xcorr[best_pitch[0]-1];
402
3.15M
      b = xcorr[best_pitch[0]];
403
3.15M
      c = xcorr[best_pitch[0]+1];
404
3.15M
      if ((c-a) > MULT16_32_Q15(QCONST16(.7f,15),b-a))
405
1.41M
         offset = 1;
406
1.73M
      else if ((a-c) > MULT16_32_Q15(QCONST16(.7f,15),b-c))
407
25.3k
         offset = -1;
408
1.70M
      else
409
1.70M
         offset = 0;
410
3.15M
   } else {
411
124k
      offset = 0;
412
124k
   }
413
3.27M
   *pitch = 2*best_pitch[0]-offset;
414
415
3.27M
   RESTORE_STACK;
416
3.27M
}
417
418
#ifdef FIXED_POINT
419
static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy)
420
48.5M
{
421
48.5M
   opus_val32 x2y2;
422
48.5M
   int sx, sy, shift;
423
48.5M
   opus_val32 g;
424
48.5M
   opus_val16 den;
425
48.5M
   if (xy == 0 || xx == 0 || yy == 0)
426
1.84M
      return 0;
427
46.7M
   sx = celt_ilog2(xx)-14;
428
46.7M
   sy = celt_ilog2(yy)-14;
429
46.7M
   shift = sx + sy;
430
46.7M
   x2y2 = SHR32(MULT16_16(VSHR32(xx, sx), VSHR32(yy, sy)), 14);
431
46.7M
   if (shift & 1) {
432
606k
      if (x2y2 < 32768)
433
309k
      {
434
309k
         x2y2 <<= 1;
435
309k
         shift--;
436
309k
      } else {
437
296k
         x2y2 >>= 1;
438
296k
         shift++;
439
296k
      }
440
606k
   }
441
46.7M
   den = celt_rsqrt_norm(x2y2);
442
46.7M
   g = MULT16_32_Q15(den, xy);
443
46.7M
   g = VSHR32(g, (shift>>1)-1);
444
46.7M
   return EXTRACT16(MAX32(-Q15ONE, MIN32(g, Q15ONE)));
445
48.5M
}
446
#else
447
static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy)
448
{
449
   return xy/celt_sqrt(1+xx*yy);
450
}
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
3.27M
{
457
3.27M
   int k, i, T, T0;
458
3.27M
   opus_val16 g, g0;
459
3.27M
   opus_val16 pg;
460
3.27M
   opus_val32 xy,xx,yy,xy2;
461
3.27M
   opus_val32 xcorr[3];
462
3.27M
   opus_val32 best_xy, best_yy;
463
3.27M
   int offset;
464
3.27M
   int minperiod0;
465
3.27M
   VARDECL(opus_val32, yy_lookup);
466
3.27M
   SAVE_STACK;
467
468
3.27M
   minperiod0 = minperiod;
469
3.27M
   maxperiod /= 2;
470
3.27M
   minperiod /= 2;
471
3.27M
   *T0_ /= 2;
472
3.27M
   prev_period /= 2;
473
3.27M
   N /= 2;
474
3.27M
   x += maxperiod;
475
3.27M
   if (*T0_>=maxperiod)
476
121k
      *T0_=maxperiod-1;
477
478
3.27M
   T = T0 = *T0_;
479
3.27M
   ALLOC(yy_lookup, maxperiod+1, opus_val32);
480
3.27M
   dual_inner_prod(x, x, x-T0, N, &xx, &xy, arch);
481
3.27M
   yy_lookup[0] = xx;
482
3.27M
   yy=xx;
483
1.67G
   for (i=1;i<=maxperiod;i++)
484
1.67G
   {
485
1.67G
      yy = yy+MULT16_16(x[-i],x[-i])-MULT16_16(x[N-i],x[N-i]);
486
1.67G
      yy_lookup[i] = MAX32(0, yy);
487
1.67G
   }
488
3.27M
   yy = yy_lookup[T0];
489
3.27M
   best_xy = xy;
490
3.27M
   best_yy = yy;
491
3.27M
   g = g0 = compute_pitch_gain(xy, xx, yy);
492
   /* Look for any pitch at T/k */
493
48.5M
   for (k=2;k<=15;k++)
494
45.3M
   {
495
45.3M
      int T1, T1b;
496
45.3M
      opus_val16 g1;
497
45.3M
      opus_val16 cont=0;
498
45.3M
      opus_val16 thresh;
499
45.3M
      T1 = celt_udiv(2*T0+k, 2*k);
500
45.3M
      if (T1 < minperiod)
501
68.8k
         break;
502
      /* Look for another strong correlation at T1b */
503
45.2M
      if (k==2)
504
3.27M
      {
505
3.27M
         if (T1+T0>maxperiod)
506
3.10M
            T1b = T0;
507
173k
         else
508
173k
            T1b = T0+T1;
509
3.27M
      } else
510
42.0M
      {
511
42.0M
         T1b = celt_udiv(2*second_check[k]*T0+k, 2*k);
512
42.0M
      }
513
45.2M
      dual_inner_prod(x, &x[-T1], &x[-T1b], N, &xy, &xy2, arch);
514
45.2M
      xy = HALF32(xy + xy2);
515
45.2M
      yy = HALF32(yy_lookup[T1] + yy_lookup[T1b]);
516
45.2M
      g1 = compute_pitch_gain(xy, xx, yy);
517
45.2M
      if (abs(T1-prev_period)<=1)
518
2.97M
         cont = prev_gain;
519
42.3M
      else if (abs(T1-prev_period)<=2 && 5*k*k < T0)
520
4.15k
         cont = HALF16(prev_gain);
521
42.3M
      else
522
42.3M
         cont = 0;
523
45.2M
      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
45.2M
      if (T1<3*minperiod)
527
1.10M
         thresh = MAX16(QCONST16(.4f,15), MULT16_16_Q15(QCONST16(.85f,15),g0)-cont);
528
44.1M
      else if (T1<2*minperiod)
529
0
         thresh = MAX16(QCONST16(.5f,15), MULT16_16_Q15(QCONST16(.9f,15),g0)-cont);
530
45.2M
      if (g1 > thresh)
531
35.0M
      {
532
35.0M
         best_xy = xy;
533
35.0M
         best_yy = yy;
534
35.0M
         T = T1;
535
35.0M
         g = g1;
536
35.0M
      }
537
45.2M
   }
538
3.27M
   best_xy = MAX32(0, best_xy);
539
3.27M
   if (best_yy <= best_xy)
540
2.88M
      pg = Q15ONE;
541
388k
   else
542
388k
      pg = SHR32(frac_div32(best_xy,best_yy+1),16);
543
544
13.0M
   for (k=0;k<3;k++)
545
9.82M
      xcorr[k] = celt_inner_prod(x, x-(T+k-1), N, arch);
546
3.27M
   if ((xcorr[2]-xcorr[0]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[0]))
547
34.0k
      offset = 1;
548
3.24M
   else if ((xcorr[0]-xcorr[2]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[2]))
549
28.3k
      offset = -1;
550
3.21M
   else
551
3.21M
      offset = 0;
552
3.27M
   if (pg > g)
553
877k
      pg = g;
554
3.27M
   *T0_ = 2*T+offset;
555
556
3.27M
   if (*T0_<minperiod0)
557
9.89k
      *T0_=minperiod0;
558
3.27M
   RESTORE_STACK;
559
3.27M
   return pg;
560
3.27M
}