blob: 1d89cb03429aea37d7f83f29cfbbfff856bd2fc5 [file] [log] [blame]
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -08001/* 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
45static 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{
52 int i, j;
53 opus_val32 Syy=1;
54 opus_val16 best_num[2];
55 opus_val32 best_den[2];
56#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++)
69 Syy = ADD32(Syy, SHR32(MULT16_16(y[j],y[j]), yshift));
70 for (i=0;i<max_pitch;i++)
71 {
72 if (xcorr[i]>0)
73 {
74 opus_val16 num;
75 opus_val32 xcorr16;
76 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 num = MULT16_16_Q15(xcorr16,xcorr16);
83 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
105static 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
147void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp,
148 int len, int C, int arch)
149{
150 int i;
151 opus_val32 ac[5];
152 opus_val16 tmp=Q15ONE;
153 opus_val16 lpc[4], mem[5]={0,0,0,0,0};
154 opus_val16 lpc2[5];
155 opus_val16 c1 = QCONST16(.8f,15);
156#ifdef FIXED_POINT
157 int shift;
158 opus_val32 maxabs = celt_maxabs32(x[0], len);
159 if (C==2)
160 {
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;
169 if (C==2)
170 shift++;
171#endif
172 for (i=1;i<len>>1;i++)
173 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);
175 if (C==2)
176 {
177 for (i=1;i<len>>1;i++)
178 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);
180 }
181
182 _celt_autocorr(x_lp, ac, NULL, 0,
183 4, len>>1, arch);
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 }
208 /* 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);
215}
216
flimc91ee5b2016-01-26 14:33:44 +0100217/* Pure C implementation. */
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800218#ifdef FIXED_POINT
219opus_val32
220#else
221void
222#endif
flimc91ee5b2016-01-26 14:33:44 +0100223#if defined(OVERRIDE_PITCH_XCORR)
224celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y,
225 opus_val32 *xcorr, int len, int max_pitch)
226#else
227celt_pitch_xcorr(const opus_val16 *_x, const opus_val16 *_y,
228 opus_val32 *xcorr, int len, int max_pitch, int arch)
229#endif
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800230{
flimc91ee5b2016-01-26 14:33:44 +0100231
232#if 0 /* This is a simple version of the pitch correlation that should work
233 well on DSPs like Blackfin and TI C5x/C6x */
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800234 int i, j;
235#ifdef FIXED_POINT
236 opus_val32 maxcorr=1;
237#endif
flimc91ee5b2016-01-26 14:33:44 +0100238#if !defined(OVERRIDE_PITCH_XCORR)
239 (void)arch;
240#endif
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800241 for (i=0;i<max_pitch;i++)
242 {
243 opus_val32 sum = 0;
244 for (j=0;j<len;j++)
flimc91ee5b2016-01-26 14:33:44 +0100245 sum = MAC16_16(sum, _x[j], _y[i+j]);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800246 xcorr[i] = sum;
247#ifdef FIXED_POINT
248 maxcorr = MAX32(maxcorr, sum);
249#endif
250 }
251#ifdef FIXED_POINT
252 return maxcorr;
253#endif
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800254
255#else /* Unrolled version of the pitch correlation -- runs faster on x86 and ARM */
flimc91ee5b2016-01-26 14:33:44 +0100256 int i;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800257 /*The EDSP version requires that max_pitch is at least 1, and that _x is
258 32-bit aligned.
259 Since it's hard to put asserts in assembly, put them here.*/
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800260#ifdef FIXED_POINT
261 opus_val32 maxcorr=1;
262#endif
flimc91ee5b2016-01-26 14:33:44 +0100263 celt_assert(max_pitch>0);
264 celt_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800265 for (i=0;i<max_pitch-3;i+=4)
266 {
267 opus_val32 sum[4]={0,0,0,0};
flimc91ee5b2016-01-26 14:33:44 +0100268#if defined(OVERRIDE_PITCH_XCORR)
269 xcorr_kernel_c(_x, _y+i, sum, len);
270#else
271 xcorr_kernel(_x, _y+i, sum, len, arch);
272#endif
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800273 xcorr[i]=sum[0];
274 xcorr[i+1]=sum[1];
275 xcorr[i+2]=sum[2];
276 xcorr[i+3]=sum[3];
277#ifdef FIXED_POINT
278 sum[0] = MAX32(sum[0], sum[1]);
279 sum[2] = MAX32(sum[2], sum[3]);
280 sum[0] = MAX32(sum[0], sum[2]);
281 maxcorr = MAX32(maxcorr, sum[0]);
282#endif
283 }
284 /* In case max_pitch isn't a multiple of 4, do non-unrolled version. */
285 for (;i<max_pitch;i++)
286 {
flimc91ee5b2016-01-26 14:33:44 +0100287 opus_val32 sum;
288#if defined(OVERRIDE_PITCH_XCORR)
289 sum = celt_inner_prod_c(_x, _y+i, len);
290#else
291 sum = celt_inner_prod(_x, _y+i, len, arch);
292#endif
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800293 xcorr[i] = sum;
294#ifdef FIXED_POINT
295 maxcorr = MAX32(maxcorr, sum);
296#endif
297 }
298#ifdef FIXED_POINT
299 return maxcorr;
300#endif
flimc91ee5b2016-01-26 14:33:44 +0100301#endif
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800302}
303
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800304void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTRICT y,
305 int len, int max_pitch, int *pitch, int arch)
306{
307 int i, j;
308 int lag;
309 int best_pitch[2]={0,0};
310 VARDECL(opus_val16, x_lp4);
311 VARDECL(opus_val16, y_lp4);
312 VARDECL(opus_val32, xcorr);
313#ifdef FIXED_POINT
314 opus_val32 maxcorr;
315 opus_val32 xmax, ymax;
316 int shift=0;
317#endif
318 int offset;
319
320 SAVE_STACK;
321
322 celt_assert(len>0);
323 celt_assert(max_pitch>0);
324 lag = len+max_pitch;
325
326 ALLOC(x_lp4, len>>2, opus_val16);
327 ALLOC(y_lp4, lag>>2, opus_val16);
328 ALLOC(xcorr, max_pitch>>1, opus_val32);
329
330 /* Downsample by 2 again */
331 for (j=0;j<len>>2;j++)
332 x_lp4[j] = x_lp[2*j];
333 for (j=0;j<lag>>2;j++)
334 y_lp4[j] = y[2*j];
335
336#ifdef FIXED_POINT
337 xmax = celt_maxabs16(x_lp4, len>>2);
338 ymax = celt_maxabs16(y_lp4, lag>>2);
339 shift = celt_ilog2(MAX32(1, MAX32(xmax, ymax)))-11;
340 if (shift>0)
341 {
342 for (j=0;j<len>>2;j++)
343 x_lp4[j] = SHR16(x_lp4[j], shift);
344 for (j=0;j<lag>>2;j++)
345 y_lp4[j] = SHR16(y_lp4[j], shift);
346 /* Use double the shift for a MAC */
347 shift *= 2;
348 } else {
349 shift = 0;
350 }
351#endif
352
353 /* Coarse search with 4x decimation */
354
355#ifdef FIXED_POINT
356 maxcorr =
357#endif
358 celt_pitch_xcorr(x_lp4, y_lp4, xcorr, len>>2, max_pitch>>2, arch);
359
360 find_best_pitch(xcorr, y_lp4, len>>2, max_pitch>>2, best_pitch
361#ifdef FIXED_POINT
362 , 0, maxcorr
363#endif
364 );
365
366 /* Finer search with 2x decimation */
367#ifdef FIXED_POINT
368 maxcorr=1;
369#endif
370 for (i=0;i<max_pitch>>1;i++)
371 {
flimc91ee5b2016-01-26 14:33:44 +0100372 opus_val32 sum;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800373 xcorr[i] = 0;
374 if (abs(i-2*best_pitch[0])>2 && abs(i-2*best_pitch[1])>2)
375 continue;
flimc91ee5b2016-01-26 14:33:44 +0100376#ifdef FIXED_POINT
377 sum = 0;
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800378 for (j=0;j<len>>1;j++)
379 sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift);
flimc91ee5b2016-01-26 14:33:44 +0100380#else
381 sum = celt_inner_prod_c(x_lp, y+i, len>>1);
382#endif
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800383 xcorr[i] = MAX32(-1, sum);
384#ifdef FIXED_POINT
385 maxcorr = MAX32(maxcorr, sum);
386#endif
387 }
388 find_best_pitch(xcorr, y, len>>1, max_pitch>>1, best_pitch
389#ifdef FIXED_POINT
390 , shift+1, maxcorr
391#endif
392 );
393
394 /* Refine by pseudo-interpolation */
395 if (best_pitch[0]>0 && best_pitch[0]<(max_pitch>>1)-1)
396 {
397 opus_val32 a, b, c;
398 a = xcorr[best_pitch[0]-1];
399 b = xcorr[best_pitch[0]];
400 c = xcorr[best_pitch[0]+1];
401 if ((c-a) > MULT16_32_Q15(QCONST16(.7f,15),b-a))
402 offset = 1;
403 else if ((a-c) > MULT16_32_Q15(QCONST16(.7f,15),b-c))
404 offset = -1;
405 else
406 offset = 0;
407 } else {
408 offset = 0;
409 }
410 *pitch = 2*best_pitch[0]-offset;
411
412 RESTORE_STACK;
413}
414
415static const int second_check[16] = {0, 0, 3, 2, 3, 2, 5, 2, 3, 2, 3, 2, 5, 2, 3, 2};
416opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
flimc91ee5b2016-01-26 14:33:44 +0100417 int N, int *T0_, int prev_period, opus_val16 prev_gain, int arch)
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800418{
419 int k, i, T, T0;
420 opus_val16 g, g0;
421 opus_val16 pg;
422 opus_val32 xy,xx,yy,xy2;
423 opus_val32 xcorr[3];
424 opus_val32 best_xy, best_yy;
425 int offset;
426 int minperiod0;
427 VARDECL(opus_val32, yy_lookup);
428 SAVE_STACK;
429
430 minperiod0 = minperiod;
431 maxperiod /= 2;
432 minperiod /= 2;
433 *T0_ /= 2;
434 prev_period /= 2;
435 N /= 2;
436 x += maxperiod;
437 if (*T0_>=maxperiod)
438 *T0_=maxperiod-1;
439
440 T = T0 = *T0_;
441 ALLOC(yy_lookup, maxperiod+1, opus_val32);
flimc91ee5b2016-01-26 14:33:44 +0100442 dual_inner_prod(x, x, x-T0, N, &xx, &xy, arch);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800443 yy_lookup[0] = xx;
444 yy=xx;
445 for (i=1;i<=maxperiod;i++)
446 {
447 yy = yy+MULT16_16(x[-i],x[-i])-MULT16_16(x[N-i],x[N-i]);
448 yy_lookup[i] = MAX32(0, yy);
449 }
450 yy = yy_lookup[T0];
451 best_xy = xy;
452 best_yy = yy;
453#ifdef FIXED_POINT
454 {
455 opus_val32 x2y2;
456 int sh, t;
457 x2y2 = 1+HALF32(MULT32_32_Q31(xx,yy));
458 sh = celt_ilog2(x2y2)>>1;
459 t = VSHR32(x2y2, 2*(sh-7));
460 g = g0 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1);
461 }
462#else
463 g = g0 = xy/celt_sqrt(1+xx*yy);
464#endif
465 /* Look for any pitch at T/k */
466 for (k=2;k<=15;k++)
467 {
468 int T1, T1b;
469 opus_val16 g1;
470 opus_val16 cont=0;
471 opus_val16 thresh;
flimc91ee5b2016-01-26 14:33:44 +0100472 T1 = celt_udiv(2*T0+k, 2*k);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800473 if (T1 < minperiod)
474 break;
475 /* Look for another strong correlation at T1b */
476 if (k==2)
477 {
478 if (T1+T0>maxperiod)
479 T1b = T0;
480 else
481 T1b = T0+T1;
482 } else
483 {
flimc91ee5b2016-01-26 14:33:44 +0100484 T1b = celt_udiv(2*second_check[k]*T0+k, 2*k);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800485 }
flimc91ee5b2016-01-26 14:33:44 +0100486 dual_inner_prod(x, &x[-T1], &x[-T1b], N, &xy, &xy2, arch);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800487 xy += xy2;
488 yy = yy_lookup[T1] + yy_lookup[T1b];
489#ifdef FIXED_POINT
490 {
491 opus_val32 x2y2;
492 int sh, t;
493 x2y2 = 1+MULT32_32_Q31(xx,yy);
494 sh = celt_ilog2(x2y2)>>1;
495 t = VSHR32(x2y2, 2*(sh-7));
496 g1 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1);
497 }
498#else
499 g1 = xy/celt_sqrt(1+2.f*xx*1.f*yy);
500#endif
501 if (abs(T1-prev_period)<=1)
502 cont = prev_gain;
503 else if (abs(T1-prev_period)<=2 && 5*k*k < T0)
504 cont = HALF32(prev_gain);
505 else
506 cont = 0;
507 thresh = MAX16(QCONST16(.3f,15), MULT16_16_Q15(QCONST16(.7f,15),g0)-cont);
508 /* Bias against very high pitch (very short period) to avoid false-positives
509 due to short-term correlation */
510 if (T1<3*minperiod)
511 thresh = MAX16(QCONST16(.4f,15), MULT16_16_Q15(QCONST16(.85f,15),g0)-cont);
512 else if (T1<2*minperiod)
513 thresh = MAX16(QCONST16(.5f,15), MULT16_16_Q15(QCONST16(.9f,15),g0)-cont);
514 if (g1 > thresh)
515 {
516 best_xy = xy;
517 best_yy = yy;
518 T = T1;
519 g = g1;
520 }
521 }
522 best_xy = MAX32(0, best_xy);
523 if (best_yy <= best_xy)
524 pg = Q15ONE;
525 else
526 pg = SHR32(frac_div32(best_xy,best_yy+1),16);
527
528 for (k=0;k<3;k++)
flimc91ee5b2016-01-26 14:33:44 +0100529 xcorr[k] = celt_inner_prod(x, x-(T+k-1), N, arch);
Vignesh Venkatasubramanian2bd8b542014-02-20 10:50:35 -0800530 if ((xcorr[2]-xcorr[0]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[0]))
531 offset = 1;
532 else if ((xcorr[0]-xcorr[2]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[2]))
533 offset = -1;
534 else
535 offset = 0;
536 if (pg > g)
537 pg = g;
538 *T0_ = 2*T+offset;
539
540 if (*T0_<minperiod0)
541 *T0_=minperiod0;
542 RESTORE_STACK;
543 return pg;
544}