Home | History | Annotate | Download | only in source
      1 /*
      2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "webrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
     12 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
     13 #include "webrtc/system_wrappers/include/compile_assert_c.h"
     14 
     15 /* log2[0.2, 0.5, 0.98] in Q8 */
     16 static const int16_t kLogLagWinQ8[3] = {
     17   -594, -256, -7
     18 };
     19 
     20 /* [1 -0.75 0.25] in Q12 */
     21 static const int16_t kACoefQ12[3] = {
     22   4096, -3072, 1024
     23 };
     24 
     25 int32_t WebRtcIsacfix_Log2Q8(uint32_t x) {
     26   int32_t zeros;
     27   int16_t frac;
     28 
     29   zeros=WebRtcSpl_NormU32(x);
     30   frac = (int16_t)(((x << zeros) & 0x7FFFFFFF) >> 23);
     31   /* log2(magn(i)) */
     32 
     33   return ((31 - zeros) << 8) + frac;
     34 }
     35 
     36 static __inline int16_t Exp2Q10(int16_t x) { // Both in and out in Q10
     37 
     38   int16_t tmp16_1, tmp16_2;
     39 
     40   tmp16_2=(int16_t)(0x0400|(x&0x03FF));
     41   tmp16_1 = -(x >> 10);
     42   if(tmp16_1>0)
     43     return tmp16_2 >> tmp16_1;
     44   else
     45     return tmp16_2 << -tmp16_1;
     46 
     47 }
     48 
     49 
     50 
     51 /* 1D parabolic interpolation . All input and output values are in Q8 */
     52 static __inline void Intrp1DQ8(int32_t *x, int32_t *fx, int32_t *y, int32_t *fy) {
     53 
     54   int16_t sign1=1, sign2=1;
     55   int32_t r32, q32, t32, nom32, den32;
     56   int16_t t16, tmp16, tmp16_1;
     57 
     58   if ((fx[0]>0) && (fx[2]>0)) {
     59     r32=fx[1]-fx[2];
     60     q32=fx[0]-fx[1];
     61     nom32=q32+r32;
     62     den32 = (q32 - r32) * 2;
     63     if (nom32<0)
     64       sign1=-1;
     65     if (den32<0)
     66       sign2=-1;
     67 
     68     /* t = (q32+r32)/(2*(q32-r32)) = (fx[0]-fx[1] + fx[1]-fx[2])/(2 * fx[0]-fx[1] - (fx[1]-fx[2]))*/
     69     /* (Signs are removed because WebRtcSpl_DivResultInQ31 can't handle negative numbers) */
     70     /* t in Q31, without signs */
     71     t32 = WebRtcSpl_DivResultInQ31(nom32 * sign1, den32 * sign2);
     72 
     73     t16 = (int16_t)(t32 >> 23);  /* Q8 */
     74     t16=t16*sign1*sign2;        /* t in Q8 with signs */
     75 
     76     *y = x[0]+t16;          /* Q8 */
     77     // *y = x[1]+t16;          /* Q8 */
     78 
     79     /* The following code calculates fy in three steps */
     80     /* fy = 0.5 * t * (t-1) * fx[0] + (1-t*t) * fx[1] + 0.5 * t * (t+1) * fx[2]; */
     81 
     82     /* Part I: 0.5 * t * (t-1) * fx[0] */
     83     tmp16_1 = (int16_t)(t16 * t16);  /* Q8*Q8=Q16 */
     84     tmp16_1 >>= 2;  /* Q16>>2 = Q14 */
     85     t16 <<= 6;  /* Q8<<6 = Q14  */
     86     tmp16 = tmp16_1-t16;
     87     *fy = WEBRTC_SPL_MUL_16_32_RSFT15(tmp16, fx[0]); /* (Q14 * Q8 >>15)/2 = Q8 */
     88 
     89     /* Part II: (1-t*t) * fx[1] */
     90     tmp16 = 16384-tmp16_1;        /* 1 in Q14 - Q14 */
     91     *fy += WEBRTC_SPL_MUL_16_32_RSFT14(tmp16, fx[1]);/* Q14 * Q8 >> 14 = Q8 */
     92 
     93     /* Part III: 0.5 * t * (t+1) * fx[2] */
     94     tmp16 = tmp16_1+t16;
     95     *fy += WEBRTC_SPL_MUL_16_32_RSFT15(tmp16, fx[2]);/* (Q14 * Q8 >>15)/2 = Q8 */
     96   } else {
     97     *y = x[0];
     98     *fy= fx[1];
     99   }
    100 }
    101 
    102 
    103 static void FindFour32(int32_t *in, int16_t length, int16_t *bestind)
    104 {
    105   int32_t best[4]= {-100, -100, -100, -100};
    106   int16_t k;
    107 
    108   for (k=0; k<length; k++) {
    109     if (in[k] > best[3]) {
    110       if (in[k] > best[2]) {
    111         if (in[k] > best[1]) {
    112           if (in[k] > best[0]) { // The Best
    113             best[3] = best[2];
    114             bestind[3] = bestind[2];
    115             best[2] = best[1];
    116             bestind[2] = bestind[1];
    117             best[1] = best[0];
    118             bestind[1] = bestind[0];
    119             best[0] = in[k];
    120             bestind[0] = k;
    121           } else { // 2nd best
    122             best[3] = best[2];
    123             bestind[3] = bestind[2];
    124             best[2] = best[1];
    125             bestind[2] = bestind[1];
    126             best[1] = in[k];
    127             bestind[1] = k;
    128           }
    129         } else { // 3rd best
    130           best[3] = best[2];
    131           bestind[3] = bestind[2];
    132           best[2] = in[k];
    133           bestind[2] = k;
    134         }
    135       } else {  // 4th best
    136         best[3] = in[k];
    137         bestind[3] = k;
    138       }
    139     }
    140   }
    141 }
    142 
    143 
    144 
    145 
    146 
    147 extern void WebRtcIsacfix_PCorr2Q32(const int16_t *in, int32_t *logcorQ8);
    148 
    149 
    150 
    151 void WebRtcIsacfix_InitialPitch(const int16_t *in, /* Q0 */
    152                                 PitchAnalysisStruct *State,
    153                                 int16_t *lagsQ7                   /* Q7 */
    154                                 )
    155 {
    156   int16_t buf_dec16[PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2+2];
    157   int32_t *crrvecQ8_1,*crrvecQ8_2;
    158   int32_t cv1q[PITCH_LAG_SPAN2+2],cv2q[PITCH_LAG_SPAN2+2], peakvq[PITCH_LAG_SPAN2+2];
    159   int k;
    160   int16_t peaks_indq;
    161   int16_t peakiq[PITCH_LAG_SPAN2];
    162   int32_t corr;
    163   int32_t corr32, corr_max32, corr_max_o32;
    164   int16_t npkq;
    165   int16_t best4q[4]={0,0,0,0};
    166   int32_t xq[3],yq[1],fyq[1];
    167   int32_t *fxq;
    168   int32_t best_lag1q, best_lag2q;
    169   int32_t tmp32a,tmp32b,lag32,ratq;
    170   int16_t start;
    171   int16_t oldgQ12, tmp16a, tmp16b, gain_bias16,tmp16c, tmp16d, bias16;
    172   int32_t tmp32c,tmp32d, tmp32e;
    173   int16_t old_lagQ;
    174   int32_t old_lagQ8;
    175   int32_t lagsQ8[4];
    176 
    177   old_lagQ = State->PFstr_wght.oldlagQ7; // Q7
    178   old_lagQ8 = old_lagQ << 1;  // Q8
    179 
    180   oldgQ12= State->PFstr_wght.oldgainQ12;
    181 
    182   crrvecQ8_1=&cv1q[1];
    183   crrvecQ8_2=&cv2q[1];
    184 
    185 
    186   /* copy old values from state buffer */
    187   memcpy(buf_dec16, State->dec_buffer16, sizeof(State->dec_buffer16));
    188 
    189   /* decimation; put result after the old values */
    190   WebRtcIsacfix_DecimateAllpass32(in, State->decimator_state32, PITCH_FRAME_LEN,
    191                                   &buf_dec16[PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2]);
    192 
    193   /* low-pass filtering */
    194   start= PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2;
    195   WebRtcSpl_FilterARFastQ12(&buf_dec16[start],&buf_dec16[start],(int16_t*)kACoefQ12,3, PITCH_FRAME_LEN/2);
    196 
    197   /* copy end part back into state buffer */
    198   for (k = 0; k < (PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2); k++)
    199     State->dec_buffer16[k] = buf_dec16[k+PITCH_FRAME_LEN/2];
    200 
    201 
    202   /* compute correlation for first and second half of the frame */
    203   WebRtcIsacfix_PCorr2Q32(buf_dec16, crrvecQ8_1);
    204   WebRtcIsacfix_PCorr2Q32(buf_dec16 + PITCH_CORR_STEP2, crrvecQ8_2);
    205 
    206 
    207   /* bias towards pitch lag of previous frame */
    208   tmp32a = WebRtcIsacfix_Log2Q8((uint32_t) old_lagQ8) - 2304;
    209       // log2(0.5*oldlag) in Q8
    210   tmp32b = oldgQ12 * oldgQ12 >> 10;  // Q12 & * 4.0;
    211   gain_bias16 = (int16_t) tmp32b;  //Q12
    212   if (gain_bias16 > 3276) gain_bias16 = 3276; // 0.8 in Q12
    213 
    214 
    215   for (k = 0; k < PITCH_LAG_SPAN2; k++)
    216   {
    217     if (crrvecQ8_1[k]>0) {
    218       tmp32b = WebRtcIsacfix_Log2Q8((uint32_t) (k + (PITCH_MIN_LAG/2-2)));
    219       tmp16a = (int16_t) (tmp32b - tmp32a); // Q8 & fabs(ratio)<4
    220       tmp32c = tmp16a * tmp16a >> 6;  // Q10
    221       tmp16b = (int16_t) tmp32c; // Q10 & <8
    222       tmp32d = tmp16b * 177 >> 8;  // mult with ln2 in Q8
    223       tmp16c = (int16_t) tmp32d; // Q10 & <4
    224       tmp16d = Exp2Q10((int16_t) -tmp16c); //Q10
    225       tmp32c = gain_bias16 * tmp16d >> 13;  // Q10  & * 0.5
    226       bias16 = (int16_t) (1024 + tmp32c); // Q10
    227       tmp32b = WebRtcIsacfix_Log2Q8((uint32_t)bias16) - 2560;
    228           // Q10 in -> Q8 out with 10*2^8 offset
    229       crrvecQ8_1[k] += tmp32b ; // -10*2^8 offset
    230     }
    231   }
    232 
    233   /* taper correlation functions */
    234   for (k = 0; k < 3; k++) {
    235     crrvecQ8_1[k] += kLogLagWinQ8[k];
    236     crrvecQ8_2[k] += kLogLagWinQ8[k];
    237 
    238     crrvecQ8_1[PITCH_LAG_SPAN2-1-k] += kLogLagWinQ8[k];
    239     crrvecQ8_2[PITCH_LAG_SPAN2-1-k] += kLogLagWinQ8[k];
    240   }
    241 
    242 
    243   /* Make zeropadded corr vectors */
    244   cv1q[0]=0;
    245   cv2q[0]=0;
    246   cv1q[PITCH_LAG_SPAN2+1]=0;
    247   cv2q[PITCH_LAG_SPAN2+1]=0;
    248   corr_max32 = 0;
    249 
    250   for (k = 1; k <= PITCH_LAG_SPAN2; k++)
    251   {
    252 
    253 
    254     corr32=crrvecQ8_1[k-1];
    255     if (corr32 > corr_max32)
    256       corr_max32 = corr32;
    257 
    258     corr32=crrvecQ8_2[k-1];
    259     corr32 += -4; // Compensate for later (log2(0.99))
    260 
    261     if (corr32 > corr_max32)
    262       corr_max32 = corr32;
    263 
    264   }
    265 
    266   /* threshold value to qualify as a peak */
    267   // corr_max32 += -726; // log(0.14)/log(2.0) in Q8
    268   corr_max32 += -1000; // log(0.14)/log(2.0) in Q8
    269   corr_max_o32 = corr_max32;
    270 
    271 
    272   /* find peaks in corr1 */
    273   peaks_indq = 0;
    274   for (k = 1; k <= PITCH_LAG_SPAN2; k++)
    275   {
    276     corr32=cv1q[k];
    277     if (corr32>corr_max32) { // Disregard small peaks
    278       if ((corr32>=cv1q[k-1]) && (corr32>cv1q[k+1])) { // Peak?
    279         peakvq[peaks_indq] = corr32;
    280         peakiq[peaks_indq++] = k;
    281       }
    282     }
    283   }
    284 
    285 
    286   /* find highest interpolated peak */
    287   corr_max32=0;
    288   best_lag1q =0;
    289   if (peaks_indq > 0) {
    290     FindFour32(peakvq, (int16_t) peaks_indq, best4q);
    291     npkq = WEBRTC_SPL_MIN(peaks_indq, 4);
    292 
    293     for (k=0;k<npkq;k++) {
    294 
    295       lag32 =  peakiq[best4q[k]];
    296       fxq = &cv1q[peakiq[best4q[k]]-1];
    297       xq[0]= lag32;
    298       xq[0] <<= 8;
    299       Intrp1DQ8(xq, fxq, yq, fyq);
    300 
    301       tmp32a= WebRtcIsacfix_Log2Q8((uint32_t) *yq) - 2048; // offset 8*2^8
    302       /* Bias towards short lags */
    303       /* log(pow(0.8, log(2.0 * *y )))/log(2.0) */
    304       tmp32b = (int16_t)tmp32a * -42 >> 8;
    305       tmp32c= tmp32b + 256;
    306       *fyq += tmp32c;
    307       if (*fyq > corr_max32) {
    308         corr_max32 = *fyq;
    309         best_lag1q = *yq;
    310       }
    311     }
    312     tmp32b = (best_lag1q - OFFSET_Q8) * 2;
    313     lagsQ8[0] = tmp32b + PITCH_MIN_LAG_Q8;
    314     lagsQ8[1] = lagsQ8[0];
    315   } else {
    316     lagsQ8[0] = old_lagQ8;
    317     lagsQ8[1] = lagsQ8[0];
    318   }
    319 
    320   /* Bias towards constant pitch */
    321   tmp32a = lagsQ8[0] - PITCH_MIN_LAG_Q8;
    322   ratq = (tmp32a >> 1) + OFFSET_Q8;
    323 
    324   for (k = 1; k <= PITCH_LAG_SPAN2; k++)
    325   {
    326     tmp32a = k << 7; // 0.5*k Q8
    327     tmp32b = tmp32a * 2 - ratq;  // Q8
    328     tmp32c = (int16_t)tmp32b * (int16_t)tmp32b >> 8;  // Q8
    329 
    330     tmp32b = tmp32c + (ratq >> 1);
    331         // (k-r)^2 + 0.5 * r  Q8
    332     tmp32c = WebRtcIsacfix_Log2Q8((uint32_t)tmp32a) - 2048;
    333         // offset 8*2^8 , log2(0.5*k) Q8
    334     tmp32d = WebRtcIsacfix_Log2Q8((uint32_t)tmp32b) - 2048;
    335         // offset 8*2^8 , log2(0.5*k) Q8
    336     tmp32e =  tmp32c - tmp32d;
    337 
    338     cv2q[k] += tmp32e >> 1;
    339 
    340   }
    341 
    342   /* find peaks in corr2 */
    343   corr_max32 = corr_max_o32;
    344   peaks_indq = 0;
    345 
    346   for (k = 1; k <= PITCH_LAG_SPAN2; k++)
    347   {
    348     corr=cv2q[k];
    349     if (corr>corr_max32) { // Disregard small peaks
    350       if ((corr>=cv2q[k-1]) && (corr>cv2q[k+1])) { // Peak?
    351         peakvq[peaks_indq] = corr;
    352         peakiq[peaks_indq++] = k;
    353       }
    354     }
    355   }
    356 
    357 
    358 
    359   /* find highest interpolated peak */
    360   corr_max32 = 0;
    361   best_lag2q =0;
    362   if (peaks_indq > 0) {
    363 
    364     FindFour32(peakvq, (int16_t) peaks_indq, best4q);
    365     npkq = WEBRTC_SPL_MIN(peaks_indq, 4);
    366     for (k=0;k<npkq;k++) {
    367 
    368       lag32 =  peakiq[best4q[k]];
    369       fxq = &cv2q[peakiq[best4q[k]]-1];
    370 
    371       xq[0]= lag32;
    372       xq[0] <<= 8;
    373       Intrp1DQ8(xq, fxq, yq, fyq);
    374 
    375       /* Bias towards short lags */
    376       /* log(pow(0.8, log(2.0f * *y )))/log(2.0f) */
    377       tmp32a= WebRtcIsacfix_Log2Q8((uint32_t) *yq) - 2048; // offset 8*2^8
    378       tmp32b = (int16_t)tmp32a * -82 >> 8;
    379       tmp32c= tmp32b + 256;
    380       *fyq += tmp32c;
    381       if (*fyq > corr_max32) {
    382         corr_max32 = *fyq;
    383         best_lag2q = *yq;
    384       }
    385     }
    386 
    387     tmp32b = (best_lag2q - OFFSET_Q8) * 2;
    388     lagsQ8[2] = tmp32b + PITCH_MIN_LAG_Q8;
    389     lagsQ8[3] = lagsQ8[2];
    390   } else {
    391     lagsQ8[2] = lagsQ8[0];
    392     lagsQ8[3] = lagsQ8[0];
    393   }
    394 
    395   lagsQ7[0] = (int16_t)(lagsQ8[0] >> 1);
    396   lagsQ7[1] = (int16_t)(lagsQ8[1] >> 1);
    397   lagsQ7[2] = (int16_t)(lagsQ8[2] >> 1);
    398   lagsQ7[3] = (int16_t)(lagsQ8[3] >> 1);
    399 }
    400 
    401 
    402 
    403 void WebRtcIsacfix_PitchAnalysis(const int16_t *inn,               /* PITCH_FRAME_LEN samples */
    404                                  int16_t *outQ0,                  /* PITCH_FRAME_LEN+QLOOKAHEAD samples */
    405                                  PitchAnalysisStruct *State,
    406                                  int16_t *PitchLags_Q7,
    407                                  int16_t *PitchGains_Q12)
    408 {
    409   int16_t inbufQ0[PITCH_FRAME_LEN + QLOOKAHEAD];
    410   int16_t k;
    411 
    412   /* inital pitch estimate */
    413   WebRtcIsacfix_InitialPitch(inn, State,  PitchLags_Q7);
    414 
    415 
    416   /* Calculate gain */
    417   WebRtcIsacfix_PitchFilterGains(inn, &(State->PFstr_wght), PitchLags_Q7, PitchGains_Q12);
    418 
    419   /* concatenate previous input's end and current input */
    420   for (k = 0; k < QLOOKAHEAD; k++) {
    421     inbufQ0[k] = State->inbuf[k];
    422   }
    423   for (k = 0; k < PITCH_FRAME_LEN; k++) {
    424     inbufQ0[k+QLOOKAHEAD] = (int16_t) inn[k];
    425   }
    426 
    427   /* lookahead pitch filtering for masking analysis */
    428   WebRtcIsacfix_PitchFilter(inbufQ0, outQ0, &(State->PFstr), PitchLags_Q7,PitchGains_Q12, 2);
    429 
    430 
    431   /* store last part of input */
    432   for (k = 0; k < QLOOKAHEAD; k++) {
    433     State->inbuf[k] = inbufQ0[k + PITCH_FRAME_LEN];
    434   }
    435 }
    436