blob: 872582a48a5558aad75fc713a635dbf69aab6be5 [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 Valin2da37212017-10-08 03:21:38 -0400105static void celt_fir5(opus_val16 *x,
Jean-Marc Valinfbf99982013-05-24 17:18:41 -0400106 const opus_val16 *num,
Jean-Marc Valin2da37212017-10-08 03:21:38 -0400107 int N)
Jean-Marc Valinfbf99982013-05-24 17:18:41 -0400108{
109 int i;
110 opus_val16 num0, num1, num2, num3, num4;
111 opus_val32 mem0, mem1, mem2, mem3, mem4;
112 num0=num[0];
113 num1=num[1];
114 num2=num[2];
115 num3=num[3];
116 num4=num[4];
Jean-Marc Valin2da37212017-10-08 03:21:38 -0400117 mem0=0;
118 mem1=0;
119 mem2=0;
120 mem3=0;
121 mem4=0;
Jean-Marc Valinfbf99982013-05-24 17:18:41 -0400122 for (i=0;i<N;i++)
123 {
124 opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
125 sum = MAC16_16(sum,num0,mem0);
126 sum = MAC16_16(sum,num1,mem1);
127 sum = MAC16_16(sum,num2,mem2);
128 sum = MAC16_16(sum,num3,mem3);
129 sum = MAC16_16(sum,num4,mem4);
130 mem4 = mem3;
131 mem3 = mem2;
132 mem2 = mem1;
133 mem1 = mem0;
134 mem0 = x[i];
Jean-Marc Valin2da37212017-10-08 03:21:38 -0400135 x[i] = ROUND16(sum, SIG_SHIFT);
Jean-Marc Valinfbf99982013-05-24 17:18:41 -0400136 }
Jean-Marc Valinfbf99982013-05-24 17:18:41 -0400137}
138
139
Gregory Maxwellde0b5322012-07-18 12:12:35 -0400140void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp,
Timothy B. Terriberry39386e02013-11-18 13:30:13 -0500141 int len, int C, int arch)
Jean-Marc Valine465c142009-11-26 00:39:36 -0500142{
143 int i;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400144 opus_val32 ac[5];
145 opus_val16 tmp=Q15ONE;
Jean-Marc Valin2da37212017-10-08 03:21:38 -0400146 opus_val16 lpc[4];
Jean-Marc Valinfbf99982013-05-24 17:18:41 -0400147 opus_val16 lpc2[5];
148 opus_val16 c1 = QCONST16(.8f,15);
Jean-Marc Valin178758b2012-04-06 23:32:11 -0400149#ifdef FIXED_POINT
150 int shift;
Jean-Marc Valin66ac1022012-05-29 17:01:35 -0400151 opus_val32 maxabs = celt_maxabs32(x[0], len);
Jean-Marc Valin178758b2012-04-06 23:32:11 -0400152 if (C==2)
Jean-Marc Valin66ac1022012-05-29 17:01:35 -0400153 {
154 opus_val32 maxabs_1 = celt_maxabs32(x[1], len);
155 maxabs = MAX32(maxabs, maxabs_1);
156 }
157 if (maxabs<1)
158 maxabs=1;
159 shift = celt_ilog2(maxabs)-10;
160 if (shift<0)
161 shift=0;
Jean-Marc Valin178758b2012-04-06 23:32:11 -0400162 if (C==2)
163 shift++;
164#endif
Jean-Marc Valine465c142009-11-26 00:39:36 -0500165 for (i=1;i<len>>1;i++)
Jean-Marc Valin178758b2012-04-06 23:32:11 -0400166 x_lp[i] = SHR32(HALF32(HALF32(x[0][(2*i-1)]+x[0][(2*i+1)])+x[0][2*i]), shift);
167 x_lp[0] = SHR32(HALF32(HALF32(x[0][1])+x[0][0]), shift);
Jean-Marc Valine465c142009-11-26 00:39:36 -0500168 if (C==2)
169 {
170 for (i=1;i<len>>1;i++)
Jean-Marc Valin178758b2012-04-06 23:32:11 -0400171 x_lp[i] += SHR32(HALF32(HALF32(x[1][(2*i-1)]+x[1][(2*i+1)])+x[1][2*i]), shift);
172 x_lp[0] += SHR32(HALF32(HALF32(x[1][1])+x[1][0]), shift);
Jean-Marc Valine465c142009-11-26 00:39:36 -0500173 }
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400174
175 _celt_autocorr(x_lp, ac, NULL, 0,
Timothy B. Terriberry39386e02013-11-18 13:30:13 -0500176 4, len>>1, arch);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400177
178 /* Noise floor -40 dB */
179#ifdef FIXED_POINT
180 ac[0] += SHR32(ac[0],13);
181#else
182 ac[0] *= 1.0001f;
183#endif
184 /* Lag windowing */
185 for (i=1;i<=4;i++)
186 {
187 /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
188#ifdef FIXED_POINT
189 ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
190#else
191 ac[i] -= ac[i]*(.008f*i)*(.008f*i);
192#endif
193 }
194
195 _celt_lpc(lpc, ac, 4);
196 for (i=0;i<4;i++)
197 {
198 tmp = MULT16_16_Q15(QCONST16(.9f,15), tmp);
199 lpc[i] = MULT16_16_Q15(lpc[i], tmp);
200 }
Jean-Marc Valinfbf99982013-05-24 17:18:41 -0400201 /* Add a zero */
202 lpc2[0] = lpc[0] + QCONST16(.8f,SIG_SHIFT);
203 lpc2[1] = lpc[1] + MULT16_16_Q15(c1,lpc[0]);
204 lpc2[2] = lpc[2] + MULT16_16_Q15(c1,lpc[1]);
205 lpc2[3] = lpc[3] + MULT16_16_Q15(c1,lpc[2]);
206 lpc2[4] = MULT16_16_Q15(c1,lpc[3]);
Jean-Marc Valin2da37212017-10-08 03:21:38 -0400207 celt_fir5(x_lp, lpc2, len>>1);
Jean-Marc Valine465c142009-11-26 00:39:36 -0500208}
209
Timothy B. Terriberryaad28182014-12-01 10:47:25 -0800210/* Pure C implementation. */
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400211#ifdef FIXED_POINT
Jean-Marc Valine8e57a32013-05-25 02:14:25 -0400212opus_val32
213#else
214void
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400215#endif
Timothy B. Terriberryaad28182014-12-01 10:47:25 -0800216celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y,
Timothy B. Terriberryaad28182014-12-01 10:47:25 -0800217 opus_val32 *xcorr, int len, int max_pitch, int arch)
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400218{
Timothy B. Terriberryaad28182014-12-01 10:47:25 -0800219
220#if 0 /* This is a simple version of the pitch correlation that should work
221 well on DSPs like Blackfin and TI C5x/C6x */
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400222 int i, j;
223#ifdef FIXED_POINT
Jean-Marc Valin088929d2013-05-24 01:38:06 -0400224 opus_val32 maxcorr=1;
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400225#endif
Timothy B. Terriberryaad28182014-12-01 10:47:25 -0800226#if !defined(OVERRIDE_PITCH_XCORR)
227 (void)arch;
228#endif
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400229 for (i=0;i<max_pitch;i++)
230 {
231 opus_val32 sum = 0;
232 for (j=0;j<len;j++)
Timothy B. Terriberryaad28182014-12-01 10:47:25 -0800233 sum = MAC16_16(sum, _x[j], _y[i+j]);
Jean-Marc Valine8e57a32013-05-25 02:14:25 -0400234 xcorr[i] = sum;
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400235#ifdef FIXED_POINT
236 maxcorr = MAX32(maxcorr, sum);
237#endif
238 }
239#ifdef FIXED_POINT
Jean-Marc Valine8e57a32013-05-25 02:14:25 -0400240 return maxcorr;
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400241#endif
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400242
243#else /* Unrolled version of the pitch correlation -- runs faster on x86 and ARM */
Jean-Marc Valin57cd8492013-12-09 02:33:42 -0500244 int i;
Timothy B. Terriberry5c02c5f2013-11-26 21:51:39 -0800245 /*The EDSP version requires that max_pitch is at least 1, and that _x is
246 32-bit aligned.
247 Since it's hard to put asserts in assembly, put them here.*/
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400248#ifdef FIXED_POINT
Jean-Marc Valin088929d2013-05-24 01:38:06 -0400249 opus_val32 maxcorr=1;
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400250#endif
Gregory Maxwella65db562014-01-08 11:48:38 -0800251 celt_assert(max_pitch>0);
Jean-Marc Valinef203132018-03-22 17:40:35 -0400252 celt_sig_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0);
Jean-Marc Valin85a66182013-05-24 03:41:04 -0400253 for (i=0;i<max_pitch-3;i+=4)
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400254 {
Jean-Marc Valin068cbd82013-05-26 20:08:35 -0400255 opus_val32 sum[4]={0,0,0,0};
xiangmingzhuc95c9a02014-04-30 15:48:07 +0800256 xcorr_kernel(_x, _y+i, sum, len, arch);
Jean-Marc Valin068cbd82013-05-26 20:08:35 -0400257 xcorr[i]=sum[0];
258 xcorr[i+1]=sum[1];
259 xcorr[i+2]=sum[2];
260 xcorr[i+3]=sum[3];
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400261#ifdef FIXED_POINT
Jean-Marc Valin068cbd82013-05-26 20:08:35 -0400262 sum[0] = MAX32(sum[0], sum[1]);
263 sum[2] = MAX32(sum[2], sum[3]);
264 sum[0] = MAX32(sum[0], sum[2]);
265 maxcorr = MAX32(maxcorr, sum[0]);
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400266#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 {
Jean-Marc Valin57cd8492013-12-09 02:33:42 -0500271 opus_val32 sum;
xiangmingzhuc95c9a02014-04-30 15:48:07 +0800272 sum = celt_inner_prod(_x, _y+i, len, arch);
Jean-Marc Valine8e57a32013-05-25 02:14:25 -0400273 xcorr[i] = sum;
Jean-Marc Valin85a66182013-05-24 03:41:04 -0400274#ifdef FIXED_POINT
275 maxcorr = MAX32(maxcorr, sum);
276#endif
277 }
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400278#ifdef FIXED_POINT
Jean-Marc Valine8e57a32013-05-25 02:14:25 -0400279 return maxcorr;
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400280#endif
Timothy B. Terriberryaad28182014-12-01 10:47:25 -0800281#endif
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400282}
283
Gregory Maxwellde0b5322012-07-18 12:12:35 -0400284void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTRICT y,
Timothy B. Terriberry39386e02013-11-18 13:30:13 -0500285 int len, int max_pitch, int *pitch, int arch)
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900286{
287 int i, j;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400288 int lag;
Gregory Maxwell06d57b22011-08-01 22:02:25 -0400289 int best_pitch[2]={0,0};
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400290 VARDECL(opus_val16, x_lp4);
291 VARDECL(opus_val16, y_lp4);
292 VARDECL(opus_val32, xcorr);
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400293#ifdef FIXED_POINT
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400294 opus_val32 maxcorr;
Jean-Marc Valinb7bd4c22013-05-18 23:33:48 -0400295 opus_val32 xmax, ymax;
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900296 int shift=0;
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400297#endif
298 int offset;
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900299
Thorvald Natvig065dafd2009-11-25 01:02:42 +0100300 SAVE_STACK;
301
Gregory Maxwell5d5875a2011-10-03 21:07:39 -0400302 celt_assert(len>0);
303 celt_assert(max_pitch>0);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400304 lag = len+max_pitch;
305
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400306 ALLOC(x_lp4, len>>2, opus_val16);
307 ALLOC(y_lp4, lag>>2, opus_val16);
308 ALLOC(xcorr, max_pitch>>1, opus_val32);
Thorvald Natvig065dafd2009-11-25 01:02:42 +0100309
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900310 /* Downsample by 2 again */
311 for (j=0;j<len>>2;j++)
312 x_lp4[j] = x_lp[2*j];
313 for (j=0;j<lag>>2;j++)
314 y_lp4[j] = y[2*j];
315
316#ifdef FIXED_POINT
Jean-Marc Valin66ac1022012-05-29 17:01:35 -0400317 xmax = celt_maxabs16(x_lp4, len>>2);
318 ymax = celt_maxabs16(y_lp4, lag>>2);
Jean-Marc Valinb7bd4c22013-05-18 23:33:48 -0400319 shift = celt_ilog2(MAX32(1, MAX32(xmax, ymax)))-11;
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900320 if (shift>0)
321 {
322 for (j=0;j<len>>2;j++)
323 x_lp4[j] = SHR16(x_lp4[j], shift);
324 for (j=0;j<lag>>2;j++)
325 y_lp4[j] = SHR16(y_lp4[j], shift);
326 /* Use double the shift for a MAC */
327 shift *= 2;
328 } else {
329 shift = 0;
330 }
331#endif
332
333 /* Coarse search with 4x decimation */
334
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400335#ifdef FIXED_POINT
Jean-Marc Valine8e57a32013-05-25 02:14:25 -0400336 maxcorr =
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400337#endif
Timothy B. Terriberry39386e02013-11-18 13:30:13 -0500338 celt_pitch_xcorr(x_lp4, y_lp4, xcorr, len>>2, max_pitch>>2, arch);
Jean-Marc Valin559fbe82013-05-24 01:09:31 -0400339
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400340 find_best_pitch(xcorr, y_lp4, len>>2, max_pitch>>2, best_pitch
341#ifdef FIXED_POINT
342 , 0, maxcorr
343#endif
344 );
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900345
346 /* Finer search with 2x decimation */
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400347#ifdef FIXED_POINT
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900348 maxcorr=1;
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400349#endif
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900350 for (i=0;i<max_pitch>>1;i++)
351 {
Jean-Marc Valin57cd8492013-12-09 02:33:42 -0500352 opus_val32 sum;
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900353 xcorr[i] = 0;
354 if (abs(i-2*best_pitch[0])>2 && abs(i-2*best_pitch[1])>2)
355 continue;
Jean-Marc Valin57cd8492013-12-09 02:33:42 -0500356#ifdef FIXED_POINT
357 sum = 0;
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900358 for (j=0;j<len>>1;j++)
359 sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift);
Jean-Marc Valin57cd8492013-12-09 02:33:42 -0500360#else
Linfeng Zhanga1ae8212016-09-07 15:29:03 -0700361 sum = celt_inner_prod(x_lp, y+i, len>>1, arch);
Jean-Marc Valin57cd8492013-12-09 02:33:42 -0500362#endif
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900363 xcorr[i] = MAX32(-1, sum);
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400364#ifdef FIXED_POINT
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900365 maxcorr = MAX32(maxcorr, sum);
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400366#endif
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900367 }
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400368 find_best_pitch(xcorr, y, len>>1, max_pitch>>1, best_pitch
369#ifdef FIXED_POINT
Jean-Marc Valin178758b2012-04-06 23:32:11 -0400370 , shift+1, maxcorr
Gregory Maxwell40f956e2011-09-01 19:42:37 -0400371#endif
372 );
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900373
374 /* Refine by pseudo-interpolation */
375 if (best_pitch[0]>0 && best_pitch[0]<(max_pitch>>1)-1)
376 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400377 opus_val32 a, b, c;
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900378 a = xcorr[best_pitch[0]-1];
379 b = xcorr[best_pitch[0]];
380 c = xcorr[best_pitch[0]+1];
381 if ((c-a) > MULT16_32_Q15(QCONST16(.7f,15),b-a))
382 offset = 1;
383 else if ((a-c) > MULT16_32_Q15(QCONST16(.7f,15),b-c))
384 offset = -1;
Gregory Maxwell71d39ad2011-07-30 00:00:29 -0400385 else
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900386 offset = 0;
387 } else {
388 offset = 0;
389 }
390 *pitch = 2*best_pitch[0]-offset;
391
Thorvald Natvig065dafd2009-11-25 01:02:42 +0100392 RESTORE_STACK;
Jean-Marc Valin294863b2009-11-08 22:29:54 +0900393}
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400394
Jean-Marc Valinddea3a62016-06-18 11:15:25 -0400395#ifdef FIXED_POINT
396static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy)
397{
398 opus_val32 x2y2;
399 int sx, sy, shift;
400 opus_val32 g;
401 opus_val16 den;
402 if (xy == 0 || xx == 0 || yy == 0)
403 return 0;
404 sx = celt_ilog2(xx)-14;
405 sy = celt_ilog2(yy)-14;
406 shift = sx + sy;
Jean-Marc Valin3609a222017-05-24 01:21:51 -0400407 x2y2 = SHR32(MULT16_16(VSHR32(xx, sx), VSHR32(yy, sy)), 14);
Jean-Marc Valinddea3a62016-06-18 11:15:25 -0400408 if (shift & 1) {
409 if (x2y2 < 32768)
410 {
411 x2y2 <<= 1;
412 shift--;
413 } else {
414 x2y2 >>= 1;
415 shift++;
416 }
417 }
418 den = celt_rsqrt_norm(x2y2);
419 g = MULT16_32_Q15(den, xy);
420 g = VSHR32(g, (shift>>1)-1);
421 return EXTRACT16(MIN32(g, Q15ONE));
422}
423#else
424static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy)
425{
426 return xy/celt_sqrt(1+xx*yy);
427}
428#endif
429
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400430static 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 -0400431opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
xiangmingzhuc95c9a02014-04-30 15:48:07 +0800432 int N, int *T0_, int prev_period, opus_val16 prev_gain, int arch)
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400433{
Gregory Maxwellb8a6b312011-02-03 22:56:01 -0500434 int k, i, T, T0;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400435 opus_val16 g, g0;
436 opus_val16 pg;
Jean-Marc Valinb9176a42013-06-17 16:37:41 -0400437 opus_val32 xy,xx,yy,xy2;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400438 opus_val32 xcorr[3];
439 opus_val32 best_xy, best_yy;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400440 int offset;
Jean-Marc Valind1212602011-01-25 13:11:36 -0500441 int minperiod0;
Jean-Marc Valin64ba5022013-05-25 20:13:49 -0400442 VARDECL(opus_val32, yy_lookup);
443 SAVE_STACK;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400444
Jean-Marc Valind1212602011-01-25 13:11:36 -0500445 minperiod0 = minperiod;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400446 maxperiod /= 2;
447 minperiod /= 2;
Ralph Giles120800f2011-11-25 13:02:00 -0800448 *T0_ /= 2;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400449 prev_period /= 2;
450 N /= 2;
451 x += maxperiod;
Ralph Giles120800f2011-11-25 13:02:00 -0800452 if (*T0_>=maxperiod)
453 *T0_=maxperiod-1;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400454
Ralph Giles120800f2011-11-25 13:02:00 -0800455 T = T0 = *T0_;
Jean-Marc Valin64ba5022013-05-25 20:13:49 -0400456 ALLOC(yy_lookup, maxperiod+1, opus_val32);
Jonathan Lennox43120f02015-08-03 17:04:27 -0400457 dual_inner_prod(x, x, x-T0, N, &xx, &xy, arch);
Jean-Marc Valin64ba5022013-05-25 20:13:49 -0400458 yy_lookup[0] = xx;
459 yy=xx;
460 for (i=1;i<=maxperiod;i++)
461 {
462 yy = yy+MULT16_16(x[-i],x[-i])-MULT16_16(x[N-i],x[N-i]);
463 yy_lookup[i] = MAX32(0, yy);
464 }
465 yy = yy_lookup[T0];
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400466 best_xy = xy;
467 best_yy = yy;
Jean-Marc Valinddea3a62016-06-18 11:15:25 -0400468 g = g0 = compute_pitch_gain(xy, xx, yy);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400469 /* Look for any pitch at T/k */
470 for (k=2;k<=15;k++)
471 {
472 int T1, T1b;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400473 opus_val16 g1;
474 opus_val16 cont=0;
Jean-Marc Valin0892c162012-01-12 03:44:49 -0500475 opus_val16 thresh;
Jean-Marc Valin29354ff2014-01-21 10:39:33 -0500476 T1 = celt_udiv(2*T0+k, 2*k);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400477 if (T1 < minperiod)
478 break;
479 /* Look for another strong correlation at T1b */
480 if (k==2)
481 {
482 if (T1+T0>maxperiod)
483 T1b = T0;
484 else
485 T1b = T0+T1;
486 } else
487 {
Jean-Marc Valin29354ff2014-01-21 10:39:33 -0500488 T1b = celt_udiv(2*second_check[k]*T0+k, 2*k);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400489 }
Jonathan Lennox43120f02015-08-03 17:04:27 -0400490 dual_inner_prod(x, &x[-T1], &x[-T1b], N, &xy, &xy2, arch);
Jean-Marc Valinddea3a62016-06-18 11:15:25 -0400491 xy = HALF32(xy + xy2);
492 yy = HALF32(yy_lookup[T1] + yy_lookup[T1b]);
493 g1 = compute_pitch_gain(xy, xx, yy);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400494 if (abs(T1-prev_period)<=1)
495 cont = prev_gain;
496 else if (abs(T1-prev_period)<=2 && 5*k*k < T0)
Jean-Marc Valinb66080a2016-06-20 12:11:05 -0400497 cont = HALF16(prev_gain);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400498 else
499 cont = 0;
Ralph Giles027ec512012-10-23 10:49:18 -0700500 thresh = MAX16(QCONST16(.3f,15), MULT16_16_Q15(QCONST16(.7f,15),g0)-cont);
Jean-Marc Valin0892c162012-01-12 03:44:49 -0500501 /* Bias against very high pitch (very short period) to avoid false-positives
502 due to short-term correlation */
503 if (T1<3*minperiod)
Ralph Giles027ec512012-10-23 10:49:18 -0700504 thresh = MAX16(QCONST16(.4f,15), MULT16_16_Q15(QCONST16(.85f,15),g0)-cont);
Jean-Marc Valin0892c162012-01-12 03:44:49 -0500505 else if (T1<2*minperiod)
Ralph Giles027ec512012-10-23 10:49:18 -0700506 thresh = MAX16(QCONST16(.5f,15), MULT16_16_Q15(QCONST16(.9f,15),g0)-cont);
Jean-Marc Valin0892c162012-01-12 03:44:49 -0500507 if (g1 > thresh)
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400508 {
509 best_xy = xy;
510 best_yy = yy;
511 T = T1;
512 g = g1;
513 }
514 }
Jean-Marc Valinb3deb532012-04-24 17:00:54 -0400515 best_xy = MAX32(0, best_xy);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400516 if (best_yy <= best_xy)
517 pg = Q15ONE;
518 else
519 pg = SHR32(frac_div32(best_xy,best_yy+1),16);
520
521 for (k=0;k<3;k++)
xiangmingzhuc95c9a02014-04-30 15:48:07 +0800522 xcorr[k] = celt_inner_prod(x, x-(T+k-1), N, arch);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400523 if ((xcorr[2]-xcorr[0]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[0]))
524 offset = 1;
525 else if ((xcorr[0]-xcorr[2]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[2]))
526 offset = -1;
527 else
528 offset = 0;
529 if (pg > g)
530 pg = g;
Ralph Giles120800f2011-11-25 13:02:00 -0800531 *T0_ = 2*T+offset;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400532
Ralph Giles120800f2011-11-25 13:02:00 -0800533 if (*T0_<minperiod0)
534 *T0_=minperiod0;
Jean-Marc Valin64ba5022013-05-25 20:13:49 -0400535 RESTORE_STACK;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400536 return pg;
537}