blob: 0549804b4a51553d6966fb758829333e94f80152 [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
Jean-Marc Valinfbf99982013-05-24 17:18:41 -0400105static void celt_fir5(const opus_val16 *x,
106 const opus_val16 *num,
107 opus_val16 *y,
108 int N,
109 opus_val16 *mem)
110{
111 int i;
112 opus_val16 num0, num1, num2, num3, num4;
113 opus_val32 mem0, mem1, mem2, mem3, mem4;
114 num0=num[0];
115 num1=num[1];
116 num2=num[2];
117 num3=num[3];
118 num4=num[4];
119 mem0=mem[0];
120 mem1=mem[1];
121 mem2=mem[2];
122 mem3=mem[3];
123 mem4=mem[4];
124 for (i=0;i<N;i++)
125 {
126 opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
127 sum = MAC16_16(sum,num0,mem0);
128 sum = MAC16_16(sum,num1,mem1);
129 sum = MAC16_16(sum,num2,mem2);
130 sum = MAC16_16(sum,num3,mem3);
131 sum = MAC16_16(sum,num4,mem4);
132 mem4 = mem3;
133 mem3 = mem2;
134 mem2 = mem1;
135 mem1 = mem0;
136 mem0 = x[i];
137 y[i] = ROUND16(sum, SIG_SHIFT);
138 }
139 mem[0]=mem0;
140 mem[1]=mem1;
141 mem[2]=mem2;
142 mem[3]=mem3;
143 mem[4]=mem4;
144}
145
146
Gregory Maxwellde0b5322012-07-18 12:12:35 -0400147void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp,
Ralph Giles120800f2011-11-25 13:02:00 -0800148 int len, int C)
Jean-Marc Valine465c142009-11-26 00:39:36 -0500149{
150 int i;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400151 opus_val32 ac[5];
152 opus_val16 tmp=Q15ONE;
Jean-Marc Valinfbf99982013-05-24 17:18:41 -0400153 opus_val16 lpc[4], mem[5]={0,0,0,0,0};
154 opus_val16 lpc2[5];
155 opus_val16 c1 = QCONST16(.8f,15);
Jean-Marc Valin178758b2012-04-06 23:32:11 -0400156#ifdef FIXED_POINT
157 int shift;
Jean-Marc Valin66ac1022012-05-29 17:01:35 -0400158 opus_val32 maxabs = celt_maxabs32(x[0], len);
Jean-Marc Valin178758b2012-04-06 23:32:11 -0400159 if (C==2)
Jean-Marc Valin66ac1022012-05-29 17:01:35 -0400160 {
161 opus_val32 maxabs_1 = celt_maxabs32(x[1], len);
162 maxabs = MAX32(maxabs, maxabs_1);
163 }
164 if (maxabs<1)
165 maxabs=1;
166 shift = celt_ilog2(maxabs)-10;
167 if (shift<0)
168 shift=0;
Jean-Marc Valin178758b2012-04-06 23:32:11 -0400169 if (C==2)
170 shift++;
171#endif
Jean-Marc Valine465c142009-11-26 00:39:36 -0500172 for (i=1;i<len>>1;i++)
Jean-Marc Valin178758b2012-04-06 23:32:11 -0400173 x_lp[i] = SHR32(HALF32(HALF32(x[0][(2*i-1)]+x[0][(2*i+1)])+x[0][2*i]), shift);
174 x_lp[0] = SHR32(HALF32(HALF32(x[0][1])+x[0][0]), shift);
Jean-Marc Valine465c142009-11-26 00:39:36 -0500175 if (C==2)
176 {
177 for (i=1;i<len>>1;i++)
Jean-Marc Valin178758b2012-04-06 23:32:11 -0400178 x_lp[i] += SHR32(HALF32(HALF32(x[1][(2*i-1)]+x[1][(2*i+1)])+x[1][2*i]), shift);
179 x_lp[0] += SHR32(HALF32(HALF32(x[1][1])+x[1][0]), shift);
Jean-Marc Valine465c142009-11-26 00:39:36 -0500180 }
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400181
182 _celt_autocorr(x_lp, ac, NULL, 0,
183 4, len>>1);
184
185 /* Noise floor -40 dB */
186#ifdef FIXED_POINT
187 ac[0] += SHR32(ac[0],13);
188#else
189 ac[0] *= 1.0001f;
190#endif
191 /* Lag windowing */
192 for (i=1;i<=4;i++)
193 {
194 /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
195#ifdef FIXED_POINT
196 ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
197#else
198 ac[i] -= ac[i]*(.008f*i)*(.008f*i);
199#endif
200 }
201
202 _celt_lpc(lpc, ac, 4);
203 for (i=0;i<4;i++)
204 {
205 tmp = MULT16_16_Q15(QCONST16(.9f,15), tmp);
206 lpc[i] = MULT16_16_Q15(lpc[i], tmp);
207 }
Jean-Marc Valinfbf99982013-05-24 17:18:41 -0400208 /* Add a zero */
209 lpc2[0] = lpc[0] + QCONST16(.8f,SIG_SHIFT);
210 lpc2[1] = lpc[1] + MULT16_16_Q15(c1,lpc[0]);
211 lpc2[2] = lpc[2] + MULT16_16_Q15(c1,lpc[1]);
212 lpc2[3] = lpc[3] + MULT16_16_Q15(c1,lpc[2]);
213 lpc2[4] = MULT16_16_Q15(c1,lpc[3]);
214 celt_fir5(x_lp, lpc2, x_lp, len>>1, mem);
Jean-Marc Valine465c142009-11-26 00:39:36 -0500215}
216
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400217#if 0 /* This is a simple version of the pitch correlation that should work
218 well on DSPs like Blackfin and TI C5x/C6x */
219
220static void pitch_xcorr(opus_val16 *x, opus_val16 *y, opus_val32 *xcorr, int len, int max_pitch
221#ifdef FIXED_POINT
222 ,opus_val32 *maxval
223#endif
224 )
225{
226 int i, j;
227#ifdef FIXED_POINT
Jean-Marc Valin088929d2013-05-24 01:38:06 -0400228 opus_val32 maxcorr=1;
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400229#endif
230 for (i=0;i<max_pitch;i++)
231 {
232 opus_val32 sum = 0;
233 for (j=0;j<len;j++)
234 sum = MAC16_16(sum, x[j],y[i+j]);
235 xcorr[i] = MAX32(-1, sum);
236#ifdef FIXED_POINT
237 maxcorr = MAX32(maxcorr, sum);
238#endif
239 }
240#ifdef FIXED_POINT
241 *maxval = maxcorr;
242#endif
243}
244
245#else /* Unrolled version of the pitch correlation -- runs faster on x86 and ARM */
246
247static void pitch_xcorr(opus_val16 *_x, opus_val16 *_y, opus_val32 *xcorr, int len, int max_pitch
248#ifdef FIXED_POINT
249 ,opus_val32 *maxval
250#endif
251 )
252{
253 int i,j;
254#ifdef FIXED_POINT
Jean-Marc Valin088929d2013-05-24 01:38:06 -0400255 opus_val32 maxcorr=1;
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400256#endif
Jean-Marc Valin85a66182013-05-24 03:41:04 -0400257 /* Truncate slightly if len is not a multiple of 4. */
258 len -= len&3;
259 for (i=0;i<max_pitch-3;i+=4)
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400260 {
261 /* Compute correlation*/
262 /*corr[nb_pitch-1-i]=inner_prod(x, _y+i, len);*/
263 opus_val32 sum1=0;
264 opus_val32 sum2=0;
265 opus_val32 sum3=0;
266 opus_val32 sum4=0;
267 const opus_val16 *y = _y+i;
268 const opus_val16 *x = _x;
269 opus_val16 y0, y1, y2, y3;
270 /*y0=y[0];y1=y[1];y2=y[2];y3=y[3];*/
271 y0=*y++;
272 y1=*y++;
273 y2=*y++;
274 for (j=0;j<len;j+=4)
275 {
276 opus_val16 tmp;
277 tmp = *x++;
278 y3=*y++;
279 sum1 = MAC16_16(sum1,tmp,y0);
280 sum2 = MAC16_16(sum2,tmp,y1);
281 sum3 = MAC16_16(sum3,tmp,y2);
282 sum4 = MAC16_16(sum4,tmp,y3);
283 tmp=*x++;
284 y0=*y++;
285 sum1 = MAC16_16(sum1,tmp,y1);
286 sum2 = MAC16_16(sum2,tmp,y2);
287 sum3 = MAC16_16(sum3,tmp,y3);
288 sum4 = MAC16_16(sum4,tmp,y0);
289 tmp=*x++;
290 y1=*y++;
291 sum1 = MAC16_16(sum1,tmp,y2);
292 sum2 = MAC16_16(sum2,tmp,y3);
293 sum3 = MAC16_16(sum3,tmp,y0);
294 sum4 = MAC16_16(sum4,tmp,y1);
295 tmp=*x++;
296 y2=*y++;
297 sum1 = MAC16_16(sum1,tmp,y3);
298 sum2 = MAC16_16(sum2,tmp,y0);
299 sum3 = MAC16_16(sum3,tmp,y1);
300 sum4 = MAC16_16(sum4,tmp,y2);
301 }
302 xcorr[i]=MAX32(-1, sum1);
303 xcorr[i+1]=MAX32(-1, sum2);
304 xcorr[i+2]=MAX32(-1, sum3);
305 xcorr[i+3]=MAX32(-1, sum4);
306#ifdef FIXED_POINT
307 sum1 = MAX32(sum1, sum2);
308 sum3 = MAX32(sum3, sum4);
309 sum1 = MAX32(sum1, sum3);
310 maxcorr = MAX32(maxcorr, sum1);
311#endif
312 }
Jean-Marc Valin85a66182013-05-24 03:41:04 -0400313 /* In case max_pitch isn't a multiple of 4, do non-unrolled version. */
314 for (;i<max_pitch;i++)
315 {
316 opus_val32 sum = 0;
317 for (j=0;j<len;j++)
318 sum = MAC16_16(sum, _x[j],_y[i+j]);
319 xcorr[i] = MAX32(-1, sum);
320#ifdef FIXED_POINT
321 maxcorr = MAX32(maxcorr, sum);
322#endif
323 }
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400324#ifdef FIXED_POINT
325 *maxval = maxcorr;
326#endif
327}
328
329#endif
Gregory Maxwellde0b5322012-07-18 12:12:35 -0400330void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTRICT y,
Jean-Marc Valine3e2c262011-01-26 13:09:53 -0500331 int len, int max_pitch, int *pitch)
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900332{
333 int i, j;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400334 int lag;
Gregory Maxwell06d57b22011-08-01 22:02:25 -0400335 int best_pitch[2]={0,0};
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400336 VARDECL(opus_val16, x_lp4);
337 VARDECL(opus_val16, y_lp4);
338 VARDECL(opus_val32, xcorr);
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400339#ifdef FIXED_POINT
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400340 opus_val32 maxcorr;
Jean-Marc Valinb7bd4c22013-05-18 23:33:48 -0400341 opus_val32 xmax, ymax;
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900342 int shift=0;
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400343#endif
344 int offset;
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900345
Thorvald Natvig065dafd2009-11-25 01:02:42 +0100346 SAVE_STACK;
347
Gregory Maxwell5d5875a2011-10-03 21:07:39 -0400348 celt_assert(len>0);
349 celt_assert(max_pitch>0);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400350 lag = len+max_pitch;
351
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400352 ALLOC(x_lp4, len>>2, opus_val16);
353 ALLOC(y_lp4, lag>>2, opus_val16);
354 ALLOC(xcorr, max_pitch>>1, opus_val32);
Thorvald Natvig065dafd2009-11-25 01:02:42 +0100355
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900356 /* Downsample by 2 again */
357 for (j=0;j<len>>2;j++)
358 x_lp4[j] = x_lp[2*j];
359 for (j=0;j<lag>>2;j++)
360 y_lp4[j] = y[2*j];
361
362#ifdef FIXED_POINT
Jean-Marc Valin66ac1022012-05-29 17:01:35 -0400363 xmax = celt_maxabs16(x_lp4, len>>2);
364 ymax = celt_maxabs16(y_lp4, lag>>2);
Jean-Marc Valinb7bd4c22013-05-18 23:33:48 -0400365 shift = celt_ilog2(MAX32(1, MAX32(xmax, ymax)))-11;
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900366 if (shift>0)
367 {
368 for (j=0;j<len>>2;j++)
369 x_lp4[j] = SHR16(x_lp4[j], shift);
370 for (j=0;j<lag>>2;j++)
371 y_lp4[j] = SHR16(y_lp4[j], shift);
372 /* Use double the shift for a MAC */
373 shift *= 2;
374 } else {
375 shift = 0;
376 }
377#endif
378
379 /* Coarse search with 4x decimation */
380
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400381 pitch_xcorr(x_lp4, y_lp4, xcorr, len>>2, max_pitch>>2
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400382#ifdef FIXED_POINT
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400383 ,&maxcorr
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400384#endif
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400385 );
386
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400387 find_best_pitch(xcorr, y_lp4, len>>2, max_pitch>>2, best_pitch
388#ifdef FIXED_POINT
389 , 0, maxcorr
390#endif
391 );
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900392
393 /* Finer search with 2x decimation */
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400394#ifdef FIXED_POINT
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900395 maxcorr=1;
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400396#endif
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900397 for (i=0;i<max_pitch>>1;i++)
398 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400399 opus_val32 sum=0;
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900400 xcorr[i] = 0;
401 if (abs(i-2*best_pitch[0])>2 && abs(i-2*best_pitch[1])>2)
402 continue;
403 for (j=0;j<len>>1;j++)
404 sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift);
405 xcorr[i] = MAX32(-1, sum);
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400406#ifdef FIXED_POINT
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900407 maxcorr = MAX32(maxcorr, sum);
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400408#endif
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900409 }
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400410 find_best_pitch(xcorr, y, len>>1, max_pitch>>1, best_pitch
411#ifdef FIXED_POINT
Jean-Marc Valin178758b2012-04-06 23:32:11 -0400412 , shift+1, maxcorr
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400413#endif
414 );
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900415
416 /* Refine by pseudo-interpolation */
417 if (best_pitch[0]>0 && best_pitch[0]<(max_pitch>>1)-1)
418 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400419 opus_val32 a, b, c;
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900420 a = xcorr[best_pitch[0]-1];
421 b = xcorr[best_pitch[0]];
422 c = xcorr[best_pitch[0]+1];
423 if ((c-a) > MULT16_32_Q15(QCONST16(.7f,15),b-a))
424 offset = 1;
425 else if ((a-c) > MULT16_32_Q15(QCONST16(.7f,15),b-c))
426 offset = -1;
Gregory Maxwell71d39ad2011-07-30 00:00:29 -0400427 else
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900428 offset = 0;
429 } else {
430 offset = 0;
431 }
432 *pitch = 2*best_pitch[0]-offset;
433
Thorvald Natvig065dafd2009-11-25 01:02:42 +0100434 RESTORE_STACK;
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900435}
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400436
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400437static 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 -0400438opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
Ralph Giles120800f2011-11-25 13:02:00 -0800439 int N, int *T0_, int prev_period, opus_val16 prev_gain)
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400440{
Gregory Maxwellb8a6b312011-02-03 22:56:01 -0500441 int k, i, T, T0;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400442 opus_val16 g, g0;
443 opus_val16 pg;
444 opus_val32 xy,xx,yy;
445 opus_val32 xcorr[3];
446 opus_val32 best_xy, best_yy;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400447 int offset;
Jean-Marc Valind1212602011-01-25 13:11:36 -0500448 int minperiod0;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400449
Jean-Marc Valind1212602011-01-25 13:11:36 -0500450 minperiod0 = minperiod;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400451 maxperiod /= 2;
452 minperiod /= 2;
Ralph Giles120800f2011-11-25 13:02:00 -0800453 *T0_ /= 2;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400454 prev_period /= 2;
455 N /= 2;
456 x += maxperiod;
Ralph Giles120800f2011-11-25 13:02:00 -0800457 if (*T0_>=maxperiod)
458 *T0_=maxperiod-1;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400459
Ralph Giles120800f2011-11-25 13:02:00 -0800460 T = T0 = *T0_;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400461 xx=xy=yy=0;
462 for (i=0;i<N;i++)
463 {
464 xy = MAC16_16(xy, x[i], x[i-T0]);
465 xx = MAC16_16(xx, x[i], x[i]);
466 yy = MAC16_16(yy, x[i-T0],x[i-T0]);
467 }
468 best_xy = xy;
469 best_yy = yy;
470#ifdef FIXED_POINT
471 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400472 opus_val32 x2y2;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400473 int sh, t;
474 x2y2 = 1+HALF32(MULT32_32_Q31(xx,yy));
475 sh = celt_ilog2(x2y2)>>1;
476 t = VSHR32(x2y2, 2*(sh-7));
477 g = g0 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1);
478 }
479#else
Gregory Maxwell662587d2011-08-01 20:41:54 -0400480 g = g0 = xy/celt_sqrt(1+xx*yy);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400481#endif
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400482 /* Look for any pitch at T/k */
483 for (k=2;k<=15;k++)
484 {
485 int T1, T1b;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400486 opus_val16 g1;
487 opus_val16 cont=0;
Jean-Marc Valin0892c162012-01-12 03:44:49 -0500488 opus_val16 thresh;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400489 T1 = (2*T0+k)/(2*k);
490 if (T1 < minperiod)
491 break;
492 /* Look for another strong correlation at T1b */
493 if (k==2)
494 {
495 if (T1+T0>maxperiod)
496 T1b = T0;
497 else
498 T1b = T0+T1;
499 } else
500 {
501 T1b = (2*second_check[k]*T0+k)/(2*k);
502 }
503 xy=yy=0;
504 for (i=0;i<N;i++)
505 {
506 xy = MAC16_16(xy, x[i], x[i-T1]);
507 yy = MAC16_16(yy, x[i-T1], x[i-T1]);
508
509 xy = MAC16_16(xy, x[i], x[i-T1b]);
510 yy = MAC16_16(yy, x[i-T1b], x[i-T1b]);
511 }
512#ifdef FIXED_POINT
513 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400514 opus_val32 x2y2;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400515 int sh, t;
516 x2y2 = 1+MULT32_32_Q31(xx,yy);
517 sh = celt_ilog2(x2y2)>>1;
518 t = VSHR32(x2y2, 2*(sh-7));
519 g1 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1);
520 }
521#else
Gregory Maxwell662587d2011-08-01 20:41:54 -0400522 g1 = xy/celt_sqrt(1+2.f*xx*1.f*yy);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400523#endif
524 if (abs(T1-prev_period)<=1)
525 cont = prev_gain;
526 else if (abs(T1-prev_period)<=2 && 5*k*k < T0)
527 cont = HALF32(prev_gain);
528 else
529 cont = 0;
Ralph Giles027ec512012-10-23 10:49:18 -0700530 thresh = MAX16(QCONST16(.3f,15), MULT16_16_Q15(QCONST16(.7f,15),g0)-cont);
Jean-Marc Valin0892c162012-01-12 03:44:49 -0500531 /* Bias against very high pitch (very short period) to avoid false-positives
532 due to short-term correlation */
533 if (T1<3*minperiod)
Ralph Giles027ec512012-10-23 10:49:18 -0700534 thresh = MAX16(QCONST16(.4f,15), MULT16_16_Q15(QCONST16(.85f,15),g0)-cont);
Jean-Marc Valin0892c162012-01-12 03:44:49 -0500535 else if (T1<2*minperiod)
Ralph Giles027ec512012-10-23 10:49:18 -0700536 thresh = MAX16(QCONST16(.5f,15), MULT16_16_Q15(QCONST16(.9f,15),g0)-cont);
Jean-Marc Valin0892c162012-01-12 03:44:49 -0500537 if (g1 > thresh)
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400538 {
539 best_xy = xy;
540 best_yy = yy;
541 T = T1;
542 g = g1;
543 }
544 }
Jean-Marc Valinb3deb532012-04-24 17:00:54 -0400545 best_xy = MAX32(0, best_xy);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400546 if (best_yy <= best_xy)
547 pg = Q15ONE;
548 else
549 pg = SHR32(frac_div32(best_xy,best_yy+1),16);
550
551 for (k=0;k<3;k++)
552 {
553 int T1 = T+k-1;
554 xy = 0;
555 for (i=0;i<N;i++)
556 xy = MAC16_16(xy, x[i], x[i-T1]);
557 xcorr[k] = xy;
558 }
559 if ((xcorr[2]-xcorr[0]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[0]))
560 offset = 1;
561 else if ((xcorr[0]-xcorr[2]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[2]))
562 offset = -1;
563 else
564 offset = 0;
565 if (pg > g)
566 pg = g;
Ralph Giles120800f2011-11-25 13:02:00 -0800567 *T0_ = 2*T+offset;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400568
Ralph Giles120800f2011-11-25 13:02:00 -0800569 if (*T0_<minperiod0)
570 *T0_=minperiod0;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400571 return pg;
572}