Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
-
+
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
-
+
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- - Neither the name of the Xiph.org Foundation nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "stack_alloc.h"
#include "mathops.h"
-void find_best_pitch(celt_word32 *xcorr, celt_word32 maxcorr, celt_word16 *y, int yshift, int len, int max_pitch, int best_pitch[2])
+static void find_best_pitch(opus_val32 *xcorr, opus_val32 maxcorr, opus_val16 *y,
+ int yshift, int len, int max_pitch, int *best_pitch)
{
int i, j;
- celt_word32 Syy=1;
- celt_word16 best_num[2];
- celt_word32 best_den[2];
+ opus_val32 Syy=1;
+ opus_val16 best_num[2];
+ opus_val32 best_den[2];
#ifdef FIXED_POINT
int xshift;
Syy = MAC16_16(Syy, y[j],y[j]);
for (i=0;i<max_pitch;i++)
{
- float score;
if (xcorr[i]>0)
{
- celt_word16 num;
- celt_word32 xcorr16;
+ opus_val16 num;
+ opus_val32 xcorr16;
xcorr16 = EXTRACT16(VSHR32(xcorr[i], xshift));
num = MULT16_16_Q15(xcorr16,xcorr16);
- score = num*1./Syy;
if (MULT16_32_Q15(num,best_den[1]) > MULT16_32_Q15(best_num[1],Syy))
{
if (MULT16_32_Q15(num,best_den[0]) > MULT16_32_Q15(best_num[0],Syy))
}
}
-void find_temporal_pitch(const CELTMode *m, const celt_sig * restrict x, celt_word16 * restrict y, int len, int max_pitch, int *pitch, int _C, celt_sig *xmem)
+#include "plc.h"
+void pitch_downsample(celt_sig * restrict x[], opus_val16 * restrict x_lp,
+ int len, int _C)
{
- int i, j;
+ int i;
+ opus_val32 ac[5];
+ opus_val16 tmp=Q15ONE;
+ opus_val16 lpc[4], mem[4]={0,0,0,0};
const int C = CHANNELS(_C);
- const int lag = MAX_PERIOD;
- const int N = FRAMESIZE(m);
- int best_pitch[2]={0};
- VARDECL(celt_word16, x_lp);
- VARDECL(celt_word16, x_lp4);
- VARDECL(celt_word16, y_lp4);
- VARDECL(celt_word32, xcorr);
- celt_word32 maxcorr=1;
+ for (i=1;i<len>>1;i++)
+ x_lp[i] = SHR32(HALF32(HALF32(x[0][(2*i-1)]+x[0][(2*i+1)])+x[0][2*i]), SIG_SHIFT+3);
+ x_lp[0] = SHR32(HALF32(HALF32(x[0][1])+x[0][0]), SIG_SHIFT+3);
+ if (C==2)
+ {
+ for (i=1;i<len>>1;i++)
+ x_lp[i] += SHR32(HALF32(HALF32(x[1][(2*i-1)]+x[1][(2*i+1)])+x[1][2*i]), SIG_SHIFT+3);
+ x_lp[0] += SHR32(HALF32(HALF32(x[1][1])+x[1][0]), SIG_SHIFT+3);
+ }
+
+ _celt_autocorr(x_lp, ac, NULL, 0,
+ 4, len>>1);
+
+ /* Noise floor -40 dB */
+#ifdef FIXED_POINT
+ ac[0] += SHR32(ac[0],13);
+#else
+ ac[0] *= 1.0001f;
+#endif
+ /* Lag windowing */
+ for (i=1;i<=4;i++)
+ {
+ /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
+#ifdef FIXED_POINT
+ ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
+#else
+ ac[i] -= ac[i]*(.008f*i)*(.008f*i);
+#endif
+ }
+
+ _celt_lpc(lpc, ac, 4);
+ for (i=0;i<4;i++)
+ {
+ tmp = MULT16_16_Q15(QCONST16(.9f,15), tmp);
+ lpc[i] = MULT16_16_Q15(lpc[i], tmp);
+ }
+ fir(x_lp, lpc, x_lp, len>>1, 4, mem);
+
+ mem[0]=0;
+ lpc[0]=QCONST16(.8f,12);
+ fir(x_lp, lpc, x_lp, len>>1, 1, mem);
+
+}
+
+void pitch_search(const opus_val16 * restrict x_lp, opus_val16 * restrict y,
+ int len, int max_pitch, int *pitch)
+{
+ int i, j;
+ int lag;
+ int best_pitch[2]={0,0};
+ VARDECL(opus_val16, x_lp4);
+ VARDECL(opus_val16, y_lp4);
+ VARDECL(opus_val32, xcorr);
+ opus_val32 maxcorr=1;
int offset;
int shift=0;
SAVE_STACK;
- ALLOC(x_lp, len>>1, celt_word16);
- ALLOC(x_lp4, len>>2, celt_word16);
- ALLOC(y_lp4, len>>2, celt_word16);
- ALLOC(xcorr, max_pitch>>1, celt_word32);
+ lag = len+max_pitch;
- /* Down-sample by two and downmix to mono */
- for (i=1;i<len>>1;i++)
- x_lp[i] = SHR32(HALF32(HALF32(x[(2*i-1)*C]+x[(2*i+1)*C])+x[2*i*C]), SIG_SHIFT);
- x_lp[0] = SHR32(HALF32(HALF32(*xmem+x[C])+x[0]), SIG_SHIFT);
- *xmem = x[N-C];
- if (C==2)
- {
- for (i=1;i<len>>1;i++)
- x_lp[i] = SHR32(HALF32(HALF32(x[(2*i-1)*C+1]+x[(2*i+1)*C+1])+x[2*i*C+1]), SIG_SHIFT);
- x_lp[0] += SHR32(HALF32(HALF32(x[C+1])+x[1]), SIG_SHIFT);
- *xmem += x[N-C+1];
- }
+ ALLOC(x_lp4, len>>2, opus_val16);
+ ALLOC(y_lp4, lag>>2, opus_val16);
+ ALLOC(xcorr, max_pitch>>1, opus_val32);
/* Downsample by 2 again */
for (j=0;j<len>>2;j++)
y_lp4[j] = y[2*j];
#ifdef FIXED_POINT
- shift = celt_ilog2(MAX16(celt_maxabs16(x_lp4, len>>2), celt_maxabs16(y_lp4, lag>>2)))-11;
+ shift = celt_ilog2(MAX16(1, MAX16(celt_maxabs16(x_lp4, len>>2), celt_maxabs16(y_lp4, lag>>2))))-11;
if (shift>0)
{
for (j=0;j<len>>2;j++)
for (i=0;i<max_pitch>>2;i++)
{
- celt_word32 sum = 0;
+ opus_val32 sum = 0;
for (j=0;j<len>>2;j++)
sum = MAC16_16(sum, x_lp4[j],y_lp4[i+j]);
xcorr[i] = MAX32(-1, sum);
maxcorr=1;
for (i=0;i<max_pitch>>1;i++)
{
- celt_word32 sum=0;
+ opus_val32 sum=0;
xcorr[i] = 0;
if (abs(i-2*best_pitch[0])>2 && abs(i-2*best_pitch[1])>2)
continue;
/* Refine by pseudo-interpolation */
if (best_pitch[0]>0 && best_pitch[0]<(max_pitch>>1)-1)
{
- celt_word32 a, b, c;
+ opus_val32 a, b, c;
a = xcorr[best_pitch[0]-1];
b = xcorr[best_pitch[0]];
c = xcorr[best_pitch[0]+1];
offset = 1;
else if ((a-c) > MULT16_32_Q15(QCONST16(.7f,15),b-c))
offset = -1;
- else
+ else
offset = 0;
} else {
offset = 0;
}
*pitch = 2*best_pitch[0]-offset;
- CELT_COPY(y, y+(N>>1), (lag-N)>>1);
- CELT_COPY(y+((lag-N)>>1), x_lp, N>>1);
-
RESTORE_STACK;
+}
+
+static const int second_check[16] = {0, 0, 3, 2, 3, 2, 5, 2, 3, 2, 3, 2, 5, 2, 3, 2};
+opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
+ int N, int *_T0, int prev_period, opus_val16 prev_gain)
+{
+ int k, i, T, T0;
+ opus_val16 g, g0;
+ opus_val16 pg;
+ opus_val32 xy,xx,yy;
+ opus_val32 xcorr[3];
+ opus_val32 best_xy, best_yy;
+ int offset;
+ int minperiod0;
+
+ minperiod0 = minperiod;
+ maxperiod /= 2;
+ minperiod /= 2;
+ *_T0 /= 2;
+ prev_period /= 2;
+ N /= 2;
+ x += maxperiod;
+ if (*_T0>=maxperiod)
+ *_T0=maxperiod-1;
+
+ T = T0 = *_T0;
+ xx=xy=yy=0;
+ for (i=0;i<N;i++)
+ {
+ xy = MAC16_16(xy, x[i], x[i-T0]);
+ xx = MAC16_16(xx, x[i], x[i]);
+ yy = MAC16_16(yy, x[i-T0],x[i-T0]);
+ }
+ best_xy = xy;
+ best_yy = yy;
+#ifdef FIXED_POINT
+ {
+ opus_val32 x2y2;
+ int sh, t;
+ x2y2 = 1+HALF32(MULT32_32_Q31(xx,yy));
+ sh = celt_ilog2(x2y2)>>1;
+ t = VSHR32(x2y2, 2*(sh-7));
+ g = g0 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1);
+ }
+#else
+ g = g0 = xy/celt_sqrt(1+xx*yy);
+#endif
+ /* Look for any pitch at T/k */
+ for (k=2;k<=15;k++)
+ {
+ int T1, T1b;
+ opus_val16 g1;
+ opus_val16 cont=0;
+ T1 = (2*T0+k)/(2*k);
+ if (T1 < minperiod)
+ break;
+ /* Look for another strong correlation at T1b */
+ if (k==2)
+ {
+ if (T1+T0>maxperiod)
+ T1b = T0;
+ else
+ T1b = T0+T1;
+ } else
+ {
+ T1b = (2*second_check[k]*T0+k)/(2*k);
+ }
+ xy=yy=0;
+ for (i=0;i<N;i++)
+ {
+ xy = MAC16_16(xy, x[i], x[i-T1]);
+ yy = MAC16_16(yy, x[i-T1], x[i-T1]);
+
+ xy = MAC16_16(xy, x[i], x[i-T1b]);
+ yy = MAC16_16(yy, x[i-T1b], x[i-T1b]);
+ }
+#ifdef FIXED_POINT
+ {
+ opus_val32 x2y2;
+ int sh, t;
+ x2y2 = 1+MULT32_32_Q31(xx,yy);
+ sh = celt_ilog2(x2y2)>>1;
+ t = VSHR32(x2y2, 2*(sh-7));
+ g1 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1);
+ }
+#else
+ g1 = xy/celt_sqrt(1+2.f*xx*1.f*yy);
+#endif
+ if (abs(T1-prev_period)<=1)
+ cont = prev_gain;
+ else if (abs(T1-prev_period)<=2 && 5*k*k < T0)
+ cont = HALF32(prev_gain);
+ else
+ cont = 0;
+ if (g1 > QCONST16(.3f,15) + MULT16_16_Q15(QCONST16(.4f,15),g0)-cont)
+ {
+ best_xy = xy;
+ best_yy = yy;
+ T = T1;
+ g = g1;
+ }
+ }
+ if (best_yy <= best_xy)
+ pg = Q15ONE;
+ else
+ pg = SHR32(frac_div32(best_xy,best_yy+1),16);
+
+ for (k=0;k<3;k++)
+ {
+ int T1 = T+k-1;
+ xy = 0;
+ for (i=0;i<N;i++)
+ xy = MAC16_16(xy, x[i], x[i-T1]);
+ xcorr[k] = xy;
+ }
+ if ((xcorr[2]-xcorr[0]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[0]))
+ offset = 1;
+ else if ((xcorr[0]-xcorr[2]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[2]))
+ offset = -1;
+ else
+ offset = 0;
+ if (pg > g)
+ pg = g;
+ *_T0 = 2*T+offset;
- /*printf ("%d\n", *pitch);*/
+ if (*_T0<minperiod0)
+ *_T0=minperiod0;
+ return pg;
}