Home | History | Annotate | Download | only in source
      1 /*
      2  *  Copyright (c) 2014 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 
     13 #ifdef WEBRTC_ARCH_ARM_NEON
     14 #include <arm_neon.h>
     15 #endif
     16 
     17 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
     18 #include "webrtc/system_wrappers/interface/compile_assert_c.h"
     19 
     20 extern int32_t WebRtcIsacfix_Log2Q8(uint32_t x);
     21 
     22 void WebRtcIsacfix_PCorr2Q32(const int16_t* in, int32_t* logcorQ8) {
     23   int16_t scaling,n,k;
     24   int32_t ysum32,csum32, lys, lcs;
     25   int32_t oneQ8;
     26   const int16_t* x;
     27   const int16_t* inptr;
     28 
     29   oneQ8 = WEBRTC_SPL_LSHIFT_W32((int32_t)1, 8);  // 1.00 in Q8
     30 
     31   x = in + PITCH_MAX_LAG / 2 + 2;
     32   scaling = WebRtcSpl_GetScalingSquare((int16_t*)in,
     33                                        PITCH_CORR_LEN2,
     34                                        PITCH_CORR_LEN2);
     35   ysum32 = 1;
     36   csum32 = 0;
     37   x = in + PITCH_MAX_LAG / 2 + 2;
     38   for (n = 0; n < PITCH_CORR_LEN2; n++) {
     39     ysum32 += WEBRTC_SPL_MUL_16_16_RSFT((int16_t)in[n],
     40                                         (int16_t)in[n],
     41                                         scaling);  // Q0
     42     csum32 += WEBRTC_SPL_MUL_16_16_RSFT((int16_t)x[n],
     43                                         (int16_t)in[n],
     44                                         scaling);  // Q0
     45   }
     46   logcorQ8 += PITCH_LAG_SPAN2 - 1;
     47   lys = WebRtcIsacfix_Log2Q8((uint32_t)ysum32);    // Q8
     48   lys = WEBRTC_SPL_RSHIFT_W32(lys, 1);  //sqrt(ysum);
     49   if (csum32 > 0) {
     50     lcs = WebRtcIsacfix_Log2Q8((uint32_t)csum32);  // 2log(csum) in Q8
     51     if (lcs > (lys + oneQ8)) {          // csum/sqrt(ysum) > 2 in Q8
     52       *logcorQ8 = lcs - lys;            // log2(csum/sqrt(ysum))
     53     } else {
     54       *logcorQ8 = oneQ8;                // 1.00
     55     }
     56   } else {
     57     *logcorQ8 = 0;
     58   }
     59 
     60 
     61   for (k = 1; k < PITCH_LAG_SPAN2; k++) {
     62     inptr = &in[k];
     63     ysum32 -= WEBRTC_SPL_MUL_16_16_RSFT((int16_t)in[k - 1],
     64                                         (int16_t)in[k - 1],
     65                                         scaling);
     66     ysum32 += WEBRTC_SPL_MUL_16_16_RSFT((int16_t)in[PITCH_CORR_LEN2 + k - 1],
     67                                         (int16_t)in[PITCH_CORR_LEN2 + k - 1],
     68                                         scaling);
     69 #ifdef WEBRTC_ARCH_ARM_NEON
     70     {
     71       int32_t vbuff[4];
     72       int32x4_t int_32x4_sum = vmovq_n_s32(0);
     73       // Can't shift a Neon register to right with a non-constant shift value.
     74       int32x4_t int_32x4_scale = vdupq_n_s32(-scaling);
     75       // Assert a codition used in loop unrolling at compile-time.
     76       COMPILE_ASSERT(PITCH_CORR_LEN2 %4 == 0);
     77 
     78       for (n = 0; n < PITCH_CORR_LEN2; n += 4) {
     79         int16x4_t int_16x4_x = vld1_s16(&x[n]);
     80         int16x4_t int_16x4_in = vld1_s16(&inptr[n]);
     81         int32x4_t int_32x4 = vmull_s16(int_16x4_x, int_16x4_in);
     82         int_32x4 = vshlq_s32(int_32x4, int_32x4_scale);
     83         int_32x4_sum = vaddq_s32(int_32x4_sum, int_32x4);
     84       }
     85 
     86       // Use vector store to avoid long stall from data trasferring
     87       // from vector to general register.
     88       vst1q_s32(vbuff, int_32x4_sum);
     89       csum32 = vbuff[0] + vbuff[1];
     90       csum32 += vbuff[2];
     91       csum32 += vbuff[3];
     92     }
     93 #else
     94     csum32 = 0;
     95     if(scaling == 0) {
     96       for (n = 0; n < PITCH_CORR_LEN2; n++) {
     97         csum32 += x[n] * inptr[n];
     98       }
     99     } else {
    100       for (n = 0; n < PITCH_CORR_LEN2; n++) {
    101         csum32 += (x[n] * inptr[n]) >> scaling;
    102       }
    103     }
    104 #endif
    105 
    106     logcorQ8--;
    107 
    108     lys = WebRtcIsacfix_Log2Q8((uint32_t)ysum32);  // Q8
    109     lys = WEBRTC_SPL_RSHIFT_W32(lys, 1);  //sqrt(ysum);
    110 
    111     if (csum32 > 0) {
    112       lcs = WebRtcIsacfix_Log2Q8((uint32_t)csum32);  // 2log(csum) in Q8
    113       if (lcs > (lys + oneQ8)) {          // csum/sqrt(ysum) > 2
    114         *logcorQ8 = lcs - lys;            // log2(csum/sqrt(ysum))
    115       } else {
    116         *logcorQ8 = oneQ8;                // 1.00
    117       }
    118     } else {
    119       *logcorQ8 = 0;
    120     }
    121   }
    122 }
    123