blob: bf581e80a81cdabccc49a10a8b943b7489b43169 [file] [log] [blame]
Jean-Marc Valin8b2ff0d2009-10-17 21:40:10 -04001/* Copyright (c) 2007-2008 CSIRO
2 Copyright (c) 2007-2009 Xiph.Org Foundation
3 Written by Jean-Marc Valin */
Jean-Marc Valin14191b32007-11-30 12:15:49 +11004/**
5 @file pitch.c
6 @brief Pitch analysis
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +11007 */
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:
Gregory Maxwell71d39ad2011-07-30 00:00:29 -040013
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +110014 - Redistributions of source code must retain the above copyright
15 notice, this list of conditions and the following disclaimer.
Gregory Maxwell71d39ad2011-07-30 00:00:29 -040016
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +110017 - 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.
Gregory Maxwell71d39ad2011-07-30 00:00:29 -040020
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +110021 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
Jean-Marc Valincb05e7c2012-04-20 16:40:24 -040024 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
25 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
Jean-Marc Valin879fbfd2008-02-20 17:17:13 +110026 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.
Jean-Marc Valin14191b32007-11-30 12:15:49 +110032*/
33
Jean-Marc Valin02fa9132008-02-20 12:09:29 +110034#ifdef HAVE_CONFIG_H
35#include "config.h"
36#endif
Jean-Marc Valin14191b32007-11-30 12:15:49 +110037
Jean-Marc Valinf3efa3e2007-12-01 01:55:17 +110038#include "pitch.h"
Jean-Marc Valinf93747c2008-03-05 17:20:30 +110039#include "os_support.h"
Jean-Marc Valinf11d6f42008-04-18 23:13:14 +100040#include "modes.h"
Jean-Marc Valinc7e0b762008-03-16 07:55:29 +110041#include "stack_alloc.h"
Jean-Marc Valin9319e3e2009-11-09 13:51:54 +090042#include "mathops.h"
Jean-Marc Valin2779df72011-10-04 13:26:53 -040043#include "celt_lpc.h"
Jean-Marc Valin294863b2009-11-08 22:29:54 +090044
Gregory Maxwell40f956e2011-09-01 19:42:37 -040045static 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 )
Jean-Marc Valin294863b2009-11-08 22:29:54 +090051{
52 int i, j;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -040053 opus_val32 Syy=1;
54 opus_val16 best_num[2];
55 opus_val32 best_den[2];
Jean-Marc Valin294863b2009-11-08 22:29:54 +090056#ifdef FIXED_POINT
57 int xshift;
58
59 xshift = celt_ilog2(maxcorr)-14;
60#endif
61
62 best_num[0] = -1;
63 best_num[1] = -1;
64 best_den[0] = 0;
65 best_den[1] = 0;
66 best_pitch[0] = 0;
67 best_pitch[1] = 1;
68 for (j=0;j<len;j++)
Jean-Marc Valin178758b2012-04-06 23:32:11 -040069 Syy = ADD32(Syy, SHR32(MULT16_16(y[j],y[j]), yshift));
Jean-Marc Valin294863b2009-11-08 22:29:54 +090070 for (i=0;i<max_pitch;i++)
71 {
Jean-Marc Valin294863b2009-11-08 22:29:54 +090072 if (xcorr[i]>0)
73 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -040074 opus_val16 num;
75 opus_val32 xcorr16;
Jean-Marc Valin294863b2009-11-08 22:29:54 +090076 xcorr16 = EXTRACT16(VSHR32(xcorr[i], xshift));
Jean-Marc Valin9faea252012-05-08 13:58:57 -040077#ifndef FIXED_POINT
78 /* Considering the range of xcorr16, this should avoid both underflows
79 and overflows (inf) when squaring xcorr16 */
Ralph Giles027ec512012-10-23 10:49:18 -070080 xcorr16 *= 1e-12f;
Jean-Marc Valin9faea252012-05-08 13:58:57 -040081#endif
Jean-Marc Valin294863b2009-11-08 22:29:54 +090082 num = MULT16_16_Q15(xcorr16,xcorr16);
Jean-Marc Valin294863b2009-11-08 22:29:54 +090083 if (MULT16_32_Q15(num,best_den[1]) > MULT16_32_Q15(best_num[1],Syy))
84 {
85 if (MULT16_32_Q15(num,best_den[0]) > MULT16_32_Q15(best_num[0],Syy))
86 {
87 best_num[1] = best_num[0];
88 best_den[1] = best_den[0];
89 best_pitch[1] = best_pitch[0];
90 best_num[0] = num;
91 best_den[0] = Syy;
92 best_pitch[0] = i;
93 } else {
94 best_num[1] = num;
95 best_den[1] = Syy;
96 best_pitch[1] = i;
97 }
98 }
99 }
100 Syy += SHR32(MULT16_16(y[i+len],y[i+len]),yshift) - SHR32(MULT16_16(y[i],y[i]),yshift);
101 Syy = MAX32(1, Syy);
102 }
103}
104
Gregory Maxwellde0b5322012-07-18 12:12:35 -0400105void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp,
Ralph Giles120800f2011-11-25 13:02:00 -0800106 int len, int C)
Jean-Marc Valine465c142009-11-26 00:39:36 -0500107{
108 int i;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400109 opus_val32 ac[5];
110 opus_val16 tmp=Q15ONE;
111 opus_val16 lpc[4], mem[4]={0,0,0,0};
Jean-Marc Valin178758b2012-04-06 23:32:11 -0400112#ifdef FIXED_POINT
113 int shift;
Jean-Marc Valin66ac1022012-05-29 17:01:35 -0400114 opus_val32 maxabs = celt_maxabs32(x[0], len);
Jean-Marc Valin178758b2012-04-06 23:32:11 -0400115 if (C==2)
Jean-Marc Valin66ac1022012-05-29 17:01:35 -0400116 {
117 opus_val32 maxabs_1 = celt_maxabs32(x[1], len);
118 maxabs = MAX32(maxabs, maxabs_1);
119 }
120 if (maxabs<1)
121 maxabs=1;
122 shift = celt_ilog2(maxabs)-10;
123 if (shift<0)
124 shift=0;
Jean-Marc Valin178758b2012-04-06 23:32:11 -0400125 if (C==2)
126 shift++;
127#endif
Jean-Marc Valine465c142009-11-26 00:39:36 -0500128 for (i=1;i<len>>1;i++)
Jean-Marc Valin178758b2012-04-06 23:32:11 -0400129 x_lp[i] = SHR32(HALF32(HALF32(x[0][(2*i-1)]+x[0][(2*i+1)])+x[0][2*i]), shift);
130 x_lp[0] = SHR32(HALF32(HALF32(x[0][1])+x[0][0]), shift);
Jean-Marc Valine465c142009-11-26 00:39:36 -0500131 if (C==2)
132 {
133 for (i=1;i<len>>1;i++)
Jean-Marc Valin178758b2012-04-06 23:32:11 -0400134 x_lp[i] += SHR32(HALF32(HALF32(x[1][(2*i-1)]+x[1][(2*i+1)])+x[1][2*i]), shift);
135 x_lp[0] += SHR32(HALF32(HALF32(x[1][1])+x[1][0]), shift);
Jean-Marc Valine465c142009-11-26 00:39:36 -0500136 }
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400137
138 _celt_autocorr(x_lp, ac, NULL, 0,
139 4, len>>1);
140
141 /* Noise floor -40 dB */
142#ifdef FIXED_POINT
143 ac[0] += SHR32(ac[0],13);
144#else
145 ac[0] *= 1.0001f;
146#endif
147 /* Lag windowing */
148 for (i=1;i<=4;i++)
149 {
150 /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
151#ifdef FIXED_POINT
152 ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
153#else
154 ac[i] -= ac[i]*(.008f*i)*(.008f*i);
155#endif
156 }
157
158 _celt_lpc(lpc, ac, 4);
159 for (i=0;i<4;i++)
160 {
161 tmp = MULT16_16_Q15(QCONST16(.9f,15), tmp);
162 lpc[i] = MULT16_16_Q15(lpc[i], tmp);
163 }
Jean-Marc Valin7fc2fbd2011-09-01 13:40:39 -0400164 celt_fir(x_lp, lpc, x_lp, len>>1, 4, mem);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400165
166 mem[0]=0;
Jean-Marc Valinb417d832011-01-27 17:19:49 -0500167 lpc[0]=QCONST16(.8f,12);
Jean-Marc Valin7fc2fbd2011-09-01 13:40:39 -0400168 celt_fir(x_lp, lpc, x_lp, len>>1, 1, mem);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400169
Jean-Marc Valine465c142009-11-26 00:39:36 -0500170}
171
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400172#if 0 /* This is a simple version of the pitch correlation that should work
173 well on DSPs like Blackfin and TI C5x/C6x */
174
175static void pitch_xcorr(opus_val16 *x, opus_val16 *y, opus_val32 *xcorr, int len, int max_pitch
176#ifdef FIXED_POINT
177 ,opus_val32 *maxval
178#endif
179 )
180{
181 int i, j;
182#ifdef FIXED_POINT
Jean-Marc Valin088929d2013-05-24 01:38:06 -0400183 opus_val32 maxcorr=1;
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400184#endif
185 for (i=0;i<max_pitch;i++)
186 {
187 opus_val32 sum = 0;
188 for (j=0;j<len;j++)
189 sum = MAC16_16(sum, x[j],y[i+j]);
190 xcorr[i] = MAX32(-1, sum);
191#ifdef FIXED_POINT
192 maxcorr = MAX32(maxcorr, sum);
193#endif
194 }
195#ifdef FIXED_POINT
196 *maxval = maxcorr;
197#endif
198}
199
200#else /* Unrolled version of the pitch correlation -- runs faster on x86 and ARM */
201
202static void pitch_xcorr(opus_val16 *_x, opus_val16 *_y, opus_val32 *xcorr, int len, int max_pitch
203#ifdef FIXED_POINT
204 ,opus_val32 *maxval
205#endif
206 )
207{
208 int i,j;
209#ifdef FIXED_POINT
Jean-Marc Valin088929d2013-05-24 01:38:06 -0400210 opus_val32 maxcorr=1;
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400211#endif
Jean-Marc Valin85a66182013-05-24 03:41:04 -0400212 /* Truncate slightly if len is not a multiple of 4. */
213 len -= len&3;
214 for (i=0;i<max_pitch-3;i+=4)
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400215 {
216 /* Compute correlation*/
217 /*corr[nb_pitch-1-i]=inner_prod(x, _y+i, len);*/
218 opus_val32 sum1=0;
219 opus_val32 sum2=0;
220 opus_val32 sum3=0;
221 opus_val32 sum4=0;
222 const opus_val16 *y = _y+i;
223 const opus_val16 *x = _x;
224 opus_val16 y0, y1, y2, y3;
225 /*y0=y[0];y1=y[1];y2=y[2];y3=y[3];*/
226 y0=*y++;
227 y1=*y++;
228 y2=*y++;
229 for (j=0;j<len;j+=4)
230 {
231 opus_val16 tmp;
232 tmp = *x++;
233 y3=*y++;
234 sum1 = MAC16_16(sum1,tmp,y0);
235 sum2 = MAC16_16(sum2,tmp,y1);
236 sum3 = MAC16_16(sum3,tmp,y2);
237 sum4 = MAC16_16(sum4,tmp,y3);
238 tmp=*x++;
239 y0=*y++;
240 sum1 = MAC16_16(sum1,tmp,y1);
241 sum2 = MAC16_16(sum2,tmp,y2);
242 sum3 = MAC16_16(sum3,tmp,y3);
243 sum4 = MAC16_16(sum4,tmp,y0);
244 tmp=*x++;
245 y1=*y++;
246 sum1 = MAC16_16(sum1,tmp,y2);
247 sum2 = MAC16_16(sum2,tmp,y3);
248 sum3 = MAC16_16(sum3,tmp,y0);
249 sum4 = MAC16_16(sum4,tmp,y1);
250 tmp=*x++;
251 y2=*y++;
252 sum1 = MAC16_16(sum1,tmp,y3);
253 sum2 = MAC16_16(sum2,tmp,y0);
254 sum3 = MAC16_16(sum3,tmp,y1);
255 sum4 = MAC16_16(sum4,tmp,y2);
256 }
257 xcorr[i]=MAX32(-1, sum1);
258 xcorr[i+1]=MAX32(-1, sum2);
259 xcorr[i+2]=MAX32(-1, sum3);
260 xcorr[i+3]=MAX32(-1, sum4);
261#ifdef FIXED_POINT
262 sum1 = MAX32(sum1, sum2);
263 sum3 = MAX32(sum3, sum4);
264 sum1 = MAX32(sum1, sum3);
265 maxcorr = MAX32(maxcorr, sum1);
266#endif
267 }
Jean-Marc Valin85a66182013-05-24 03:41:04 -0400268 /* In case max_pitch isn't a multiple of 4, do non-unrolled version. */
269 for (;i<max_pitch;i++)
270 {
271 opus_val32 sum = 0;
272 for (j=0;j<len;j++)
273 sum = MAC16_16(sum, _x[j],_y[i+j]);
274 xcorr[i] = MAX32(-1, sum);
275#ifdef FIXED_POINT
276 maxcorr = MAX32(maxcorr, sum);
277#endif
278 }
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400279#ifdef FIXED_POINT
280 *maxval = maxcorr;
281#endif
282}
283
284#endif
Gregory Maxwellde0b5322012-07-18 12:12:35 -0400285void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTRICT y,
Jean-Marc Valine3e2c262011-01-26 13:09:53 -0500286 int len, int max_pitch, int *pitch)
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900287{
288 int i, j;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400289 int lag;
Gregory Maxwell06d57b22011-08-01 22:02:25 -0400290 int best_pitch[2]={0,0};
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400291 VARDECL(opus_val16, x_lp4);
292 VARDECL(opus_val16, y_lp4);
293 VARDECL(opus_val32, xcorr);
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400294#ifdef FIXED_POINT
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400295 opus_val32 maxcorr;
Jean-Marc Valinb7bd4c22013-05-18 23:33:48 -0400296 opus_val32 xmax, ymax;
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900297 int shift=0;
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400298#endif
299 int offset;
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900300
Thorvald Natvig065dafd2009-11-25 01:02:42 +0100301 SAVE_STACK;
302
Gregory Maxwell5d5875a2011-10-03 21:07:39 -0400303 celt_assert(len>0);
304 celt_assert(max_pitch>0);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400305 lag = len+max_pitch;
306
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400307 ALLOC(x_lp4, len>>2, opus_val16);
308 ALLOC(y_lp4, lag>>2, opus_val16);
309 ALLOC(xcorr, max_pitch>>1, opus_val32);
Thorvald Natvig065dafd2009-11-25 01:02:42 +0100310
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900311 /* Downsample by 2 again */
312 for (j=0;j<len>>2;j++)
313 x_lp4[j] = x_lp[2*j];
314 for (j=0;j<lag>>2;j++)
315 y_lp4[j] = y[2*j];
316
317#ifdef FIXED_POINT
Jean-Marc Valin66ac1022012-05-29 17:01:35 -0400318 xmax = celt_maxabs16(x_lp4, len>>2);
319 ymax = celt_maxabs16(y_lp4, lag>>2);
Jean-Marc Valinb7bd4c22013-05-18 23:33:48 -0400320 shift = celt_ilog2(MAX32(1, MAX32(xmax, ymax)))-11;
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900321 if (shift>0)
322 {
323 for (j=0;j<len>>2;j++)
324 x_lp4[j] = SHR16(x_lp4[j], shift);
325 for (j=0;j<lag>>2;j++)
326 y_lp4[j] = SHR16(y_lp4[j], shift);
327 /* Use double the shift for a MAC */
328 shift *= 2;
329 } else {
330 shift = 0;
331 }
332#endif
333
334 /* Coarse search with 4x decimation */
335
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400336 pitch_xcorr(x_lp4, y_lp4, xcorr, len>>2, max_pitch>>2
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400337#ifdef FIXED_POINT
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400338 ,&maxcorr
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400339#endif
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400340 );
341
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400342 find_best_pitch(xcorr, y_lp4, len>>2, max_pitch>>2, best_pitch
343#ifdef FIXED_POINT
344 , 0, maxcorr
345#endif
346 );
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900347
348 /* Finer search with 2x decimation */
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400349#ifdef FIXED_POINT
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900350 maxcorr=1;
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400351#endif
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900352 for (i=0;i<max_pitch>>1;i++)
353 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400354 opus_val32 sum=0;
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900355 xcorr[i] = 0;
356 if (abs(i-2*best_pitch[0])>2 && abs(i-2*best_pitch[1])>2)
357 continue;
358 for (j=0;j<len>>1;j++)
359 sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift);
360 xcorr[i] = MAX32(-1, sum);
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400361#ifdef FIXED_POINT
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900362 maxcorr = MAX32(maxcorr, sum);
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400363#endif
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900364 }
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400365 find_best_pitch(xcorr, y, len>>1, max_pitch>>1, best_pitch
366#ifdef FIXED_POINT
Jean-Marc Valin178758b2012-04-06 23:32:11 -0400367 , shift+1, maxcorr
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400368#endif
369 );
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900370
371 /* Refine by pseudo-interpolation */
372 if (best_pitch[0]>0 && best_pitch[0]<(max_pitch>>1)-1)
373 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400374 opus_val32 a, b, c;
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900375 a = xcorr[best_pitch[0]-1];
376 b = xcorr[best_pitch[0]];
377 c = xcorr[best_pitch[0]+1];
378 if ((c-a) > MULT16_32_Q15(QCONST16(.7f,15),b-a))
379 offset = 1;
380 else if ((a-c) > MULT16_32_Q15(QCONST16(.7f,15),b-c))
381 offset = -1;
Gregory Maxwell71d39ad2011-07-30 00:00:29 -0400382 else
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900383 offset = 0;
384 } else {
385 offset = 0;
386 }
387 *pitch = 2*best_pitch[0]-offset;
388
Thorvald Natvig065dafd2009-11-25 01:02:42 +0100389 RESTORE_STACK;
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900390}
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400391
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400392static const int second_check[16] = {0, 0, 3, 2, 3, 2, 5, 2, 3, 2, 3, 2, 5, 2, 3, 2};
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400393opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
Ralph Giles120800f2011-11-25 13:02:00 -0800394 int N, int *T0_, int prev_period, opus_val16 prev_gain)
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400395{
Gregory Maxwellb8a6b312011-02-03 22:56:01 -0500396 int k, i, T, T0;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400397 opus_val16 g, g0;
398 opus_val16 pg;
399 opus_val32 xy,xx,yy;
400 opus_val32 xcorr[3];
401 opus_val32 best_xy, best_yy;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400402 int offset;
Jean-Marc Valind1212602011-01-25 13:11:36 -0500403 int minperiod0;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400404
Jean-Marc Valind1212602011-01-25 13:11:36 -0500405 minperiod0 = minperiod;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400406 maxperiod /= 2;
407 minperiod /= 2;
Ralph Giles120800f2011-11-25 13:02:00 -0800408 *T0_ /= 2;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400409 prev_period /= 2;
410 N /= 2;
411 x += maxperiod;
Ralph Giles120800f2011-11-25 13:02:00 -0800412 if (*T0_>=maxperiod)
413 *T0_=maxperiod-1;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400414
Ralph Giles120800f2011-11-25 13:02:00 -0800415 T = T0 = *T0_;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400416 xx=xy=yy=0;
417 for (i=0;i<N;i++)
418 {
419 xy = MAC16_16(xy, x[i], x[i-T0]);
420 xx = MAC16_16(xx, x[i], x[i]);
421 yy = MAC16_16(yy, x[i-T0],x[i-T0]);
422 }
423 best_xy = xy;
424 best_yy = yy;
425#ifdef FIXED_POINT
426 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400427 opus_val32 x2y2;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400428 int sh, t;
429 x2y2 = 1+HALF32(MULT32_32_Q31(xx,yy));
430 sh = celt_ilog2(x2y2)>>1;
431 t = VSHR32(x2y2, 2*(sh-7));
432 g = g0 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1);
433 }
434#else
Gregory Maxwell662587d2011-08-01 20:41:54 -0400435 g = g0 = xy/celt_sqrt(1+xx*yy);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400436#endif
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400437 /* Look for any pitch at T/k */
438 for (k=2;k<=15;k++)
439 {
440 int T1, T1b;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400441 opus_val16 g1;
442 opus_val16 cont=0;
Jean-Marc Valin0892c162012-01-12 03:44:49 -0500443 opus_val16 thresh;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400444 T1 = (2*T0+k)/(2*k);
445 if (T1 < minperiod)
446 break;
447 /* Look for another strong correlation at T1b */
448 if (k==2)
449 {
450 if (T1+T0>maxperiod)
451 T1b = T0;
452 else
453 T1b = T0+T1;
454 } else
455 {
456 T1b = (2*second_check[k]*T0+k)/(2*k);
457 }
458 xy=yy=0;
459 for (i=0;i<N;i++)
460 {
461 xy = MAC16_16(xy, x[i], x[i-T1]);
462 yy = MAC16_16(yy, x[i-T1], x[i-T1]);
463
464 xy = MAC16_16(xy, x[i], x[i-T1b]);
465 yy = MAC16_16(yy, x[i-T1b], x[i-T1b]);
466 }
467#ifdef FIXED_POINT
468 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400469 opus_val32 x2y2;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400470 int sh, t;
471 x2y2 = 1+MULT32_32_Q31(xx,yy);
472 sh = celt_ilog2(x2y2)>>1;
473 t = VSHR32(x2y2, 2*(sh-7));
474 g1 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1);
475 }
476#else
Gregory Maxwell662587d2011-08-01 20:41:54 -0400477 g1 = xy/celt_sqrt(1+2.f*xx*1.f*yy);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400478#endif
479 if (abs(T1-prev_period)<=1)
480 cont = prev_gain;
481 else if (abs(T1-prev_period)<=2 && 5*k*k < T0)
482 cont = HALF32(prev_gain);
483 else
484 cont = 0;
Ralph Giles027ec512012-10-23 10:49:18 -0700485 thresh = MAX16(QCONST16(.3f,15), MULT16_16_Q15(QCONST16(.7f,15),g0)-cont);
Jean-Marc Valin0892c162012-01-12 03:44:49 -0500486 /* Bias against very high pitch (very short period) to avoid false-positives
487 due to short-term correlation */
488 if (T1<3*minperiod)
Ralph Giles027ec512012-10-23 10:49:18 -0700489 thresh = MAX16(QCONST16(.4f,15), MULT16_16_Q15(QCONST16(.85f,15),g0)-cont);
Jean-Marc Valin0892c162012-01-12 03:44:49 -0500490 else if (T1<2*minperiod)
Ralph Giles027ec512012-10-23 10:49:18 -0700491 thresh = MAX16(QCONST16(.5f,15), MULT16_16_Q15(QCONST16(.9f,15),g0)-cont);
Jean-Marc Valin0892c162012-01-12 03:44:49 -0500492 if (g1 > thresh)
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400493 {
494 best_xy = xy;
495 best_yy = yy;
496 T = T1;
497 g = g1;
498 }
499 }
Jean-Marc Valinb3deb532012-04-24 17:00:54 -0400500 best_xy = MAX32(0, best_xy);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400501 if (best_yy <= best_xy)
502 pg = Q15ONE;
503 else
504 pg = SHR32(frac_div32(best_xy,best_yy+1),16);
505
506 for (k=0;k<3;k++)
507 {
508 int T1 = T+k-1;
509 xy = 0;
510 for (i=0;i<N;i++)
511 xy = MAC16_16(xy, x[i], x[i-T1]);
512 xcorr[k] = xy;
513 }
514 if ((xcorr[2]-xcorr[0]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[0]))
515 offset = 1;
516 else if ((xcorr[0]-xcorr[2]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[2]))
517 offset = -1;
518 else
519 offset = 0;
520 if (pg > g)
521 pg = g;
Ralph Giles120800f2011-11-25 13:02:00 -0800522 *T0_ = 2*T+offset;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400523
Ralph Giles120800f2011-11-25 13:02:00 -0800524 if (*T0_<minperiod0)
525 *T0_=minperiod0;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400526 return pg;
527}