Home | History | Annotate | Download | only in celt
      1 /* 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 
     45 static 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 
    105 void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp,
    106       int len, int C)
    107 {
    108    int i;
    109    opus_val32 ac[5];
    110    opus_val16 tmp=Q15ONE;
    111    opus_val16 lpc[4], mem[4]={0,0,0,0};
    112 #ifdef FIXED_POINT
    113    int shift;
    114    opus_val32 maxabs = celt_maxabs32(x[0], len);
    115    if (C==2)
    116    {
    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;
    125    if (C==2)
    126       shift++;
    127 #endif
    128    for (i=1;i<len>>1;i++)
    129       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);
    131    if (C==2)
    132    {
    133       for (i=1;i<len>>1;i++)
    134          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);
    136    }
    137 
    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    }
    164    celt_fir(x_lp, lpc, x_lp, len>>1, 4, mem);
    165 
    166    mem[0]=0;
    167    lpc[0]=QCONST16(.8f,12);
    168    celt_fir(x_lp, lpc, x_lp, len>>1, 1, mem);
    169 
    170 }
    171 
    172 void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTRICT y,
    173                   int len, int max_pitch, int *pitch)
    174 {
    175    int i, j;
    176    int lag;
    177    int best_pitch[2]={0,0};
    178    VARDECL(opus_val16, x_lp4);
    179    VARDECL(opus_val16, y_lp4);
    180    VARDECL(opus_val32, xcorr);
    181 #ifdef FIXED_POINT
    182    opus_val32 maxcorr=1;
    183    opus_val16 xmax, ymax;
    184    int shift=0;
    185 #endif
    186    int offset;
    187 
    188    SAVE_STACK;
    189 
    190    celt_assert(len>0);
    191    celt_assert(max_pitch>0);
    192    lag = len+max_pitch;
    193 
    194    ALLOC(x_lp4, len>>2, opus_val16);
    195    ALLOC(y_lp4, lag>>2, opus_val16);
    196    ALLOC(xcorr, max_pitch>>1, opus_val32);
    197 
    198    /* Downsample by 2 again */
    199    for (j=0;j<len>>2;j++)
    200       x_lp4[j] = x_lp[2*j];
    201    for (j=0;j<lag>>2;j++)
    202       y_lp4[j] = y[2*j];
    203 
    204 #ifdef FIXED_POINT
    205    xmax = celt_maxabs16(x_lp4, len>>2);
    206    ymax = celt_maxabs16(y_lp4, lag>>2);
    207    shift = celt_ilog2(MAX16(1, MAX16(xmax, ymax)))-11;
    208    if (shift>0)
    209    {
    210       for (j=0;j<len>>2;j++)
    211          x_lp4[j] = SHR16(x_lp4[j], shift);
    212       for (j=0;j<lag>>2;j++)
    213          y_lp4[j] = SHR16(y_lp4[j], shift);
    214       /* Use double the shift for a MAC */
    215       shift *= 2;
    216    } else {
    217       shift = 0;
    218    }
    219 #endif
    220 
    221    /* Coarse search with 4x decimation */
    222 
    223    for (i=0;i<max_pitch>>2;i++)
    224    {
    225       opus_val32 sum = 0;
    226       for (j=0;j<len>>2;j++)
    227          sum = MAC16_16(sum, x_lp4[j],y_lp4[i+j]);
    228       xcorr[i] = MAX32(-1, sum);
    229 #ifdef FIXED_POINT
    230       maxcorr = MAX32(maxcorr, sum);
    231 #endif
    232    }
    233    find_best_pitch(xcorr, y_lp4, len>>2, max_pitch>>2, best_pitch
    234 #ifdef FIXED_POINT
    235                    , 0, maxcorr
    236 #endif
    237                    );
    238 
    239    /* Finer search with 2x decimation */
    240 #ifdef FIXED_POINT
    241    maxcorr=1;
    242 #endif
    243    for (i=0;i<max_pitch>>1;i++)
    244    {
    245       opus_val32 sum=0;
    246       xcorr[i] = 0;
    247       if (abs(i-2*best_pitch[0])>2 && abs(i-2*best_pitch[1])>2)
    248          continue;
    249       for (j=0;j<len>>1;j++)
    250          sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift);
    251       xcorr[i] = MAX32(-1, sum);
    252 #ifdef FIXED_POINT
    253       maxcorr = MAX32(maxcorr, sum);
    254 #endif
    255    }
    256    find_best_pitch(xcorr, y, len>>1, max_pitch>>1, best_pitch
    257 #ifdef FIXED_POINT
    258                    , shift+1, maxcorr
    259 #endif
    260                    );
    261 
    262    /* Refine by pseudo-interpolation */
    263    if (best_pitch[0]>0 && best_pitch[0]<(max_pitch>>1)-1)
    264    {
    265       opus_val32 a, b, c;
    266       a = xcorr[best_pitch[0]-1];
    267       b = xcorr[best_pitch[0]];
    268       c = xcorr[best_pitch[0]+1];
    269       if ((c-a) > MULT16_32_Q15(QCONST16(.7f,15),b-a))
    270          offset = 1;
    271       else if ((a-c) > MULT16_32_Q15(QCONST16(.7f,15),b-c))
    272          offset = -1;
    273       else
    274          offset = 0;
    275    } else {
    276       offset = 0;
    277    }
    278    *pitch = 2*best_pitch[0]-offset;
    279 
    280    RESTORE_STACK;
    281 }
    282 
    283 static const int second_check[16] = {0, 0, 3, 2, 3, 2, 5, 2, 3, 2, 3, 2, 5, 2, 3, 2};
    284 opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
    285       int N, int *T0_, int prev_period, opus_val16 prev_gain)
    286 {
    287    int k, i, T, T0;
    288    opus_val16 g, g0;
    289    opus_val16 pg;
    290    opus_val32 xy,xx,yy;
    291    opus_val32 xcorr[3];
    292    opus_val32 best_xy, best_yy;
    293    int offset;
    294    int minperiod0;
    295 
    296    minperiod0 = minperiod;
    297    maxperiod /= 2;
    298    minperiod /= 2;
    299    *T0_ /= 2;
    300    prev_period /= 2;
    301    N /= 2;
    302    x += maxperiod;
    303    if (*T0_>=maxperiod)
    304       *T0_=maxperiod-1;
    305 
    306    T = T0 = *T0_;
    307    xx=xy=yy=0;
    308    for (i=0;i<N;i++)
    309    {
    310       xy = MAC16_16(xy, x[i], x[i-T0]);
    311       xx = MAC16_16(xx, x[i], x[i]);
    312       yy = MAC16_16(yy, x[i-T0],x[i-T0]);
    313    }
    314    best_xy = xy;
    315    best_yy = yy;
    316 #ifdef FIXED_POINT
    317       {
    318          opus_val32 x2y2;
    319          int sh, t;
    320          x2y2 = 1+HALF32(MULT32_32_Q31(xx,yy));
    321          sh = celt_ilog2(x2y2)>>1;
    322          t = VSHR32(x2y2, 2*(sh-7));
    323          g = g0 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1);
    324       }
    325 #else
    326       g = g0 = xy/celt_sqrt(1+xx*yy);
    327 #endif
    328    /* Look for any pitch at T/k */
    329    for (k=2;k<=15;k++)
    330    {
    331       int T1, T1b;
    332       opus_val16 g1;
    333       opus_val16 cont=0;
    334       T1 = (2*T0+k)/(2*k);
    335       if (T1 < minperiod)
    336          break;
    337       /* Look for another strong correlation at T1b */
    338       if (k==2)
    339       {
    340          if (T1+T0>maxperiod)
    341             T1b = T0;
    342          else
    343             T1b = T0+T1;
    344       } else
    345       {
    346          T1b = (2*second_check[k]*T0+k)/(2*k);
    347       }
    348       xy=yy=0;
    349       for (i=0;i<N;i++)
    350       {
    351          xy = MAC16_16(xy, x[i], x[i-T1]);
    352          yy = MAC16_16(yy, x[i-T1], x[i-T1]);
    353 
    354          xy = MAC16_16(xy, x[i], x[i-T1b]);
    355          yy = MAC16_16(yy, x[i-T1b], x[i-T1b]);
    356       }
    357 #ifdef FIXED_POINT
    358       {
    359          opus_val32 x2y2;
    360          int sh, t;
    361          x2y2 = 1+MULT32_32_Q31(xx,yy);
    362          sh = celt_ilog2(x2y2)>>1;
    363          t = VSHR32(x2y2, 2*(sh-7));
    364          g1 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1);
    365       }
    366 #else
    367       g1 = xy/celt_sqrt(1+2.f*xx*1.f*yy);
    368 #endif
    369       if (abs(T1-prev_period)<=1)
    370          cont = prev_gain;
    371       else if (abs(T1-prev_period)<=2 && 5*k*k < T0)
    372          cont = HALF32(prev_gain);
    373       else
    374          cont = 0;
    375       if (g1 > QCONST16(.3f,15) + MULT16_16_Q15(QCONST16(.4f,15),g0)-cont)
    376       {
    377          best_xy = xy;
    378          best_yy = yy;
    379          T = T1;
    380          g = g1;
    381       }
    382    }
    383    best_xy = MAX32(0, best_xy);
    384    if (best_yy <= best_xy)
    385       pg = Q15ONE;
    386    else
    387       pg = SHR32(frac_div32(best_xy,best_yy+1),16);
    388 
    389    for (k=0;k<3;k++)
    390    {
    391       int T1 = T+k-1;
    392       xy = 0;
    393       for (i=0;i<N;i++)
    394          xy = MAC16_16(xy, x[i], x[i-T1]);
    395       xcorr[k] = xy;
    396    }
    397    if ((xcorr[2]-xcorr[0]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[0]))
    398       offset = 1;
    399    else if ((xcorr[0]-xcorr[2]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[2]))
    400       offset = -1;
    401    else
    402       offset = 0;
    403    if (pg > g)
    404       pg = g;
    405    *T0_ = 2*T+offset;
    406 
    407    if (*T0_<minperiod0)
    408       *T0_=minperiod0;
    409    return pg;
    410 }
    411