annotate src/opus-1.3/celt/pitch.c @ 83:ae30d91d2ffe

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