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_HAS_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/include/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   const int32_t oneQ8 = 1 << 8;  // 1.00 in Q8
     26   const int16_t* x;
     27   const int16_t* inptr;
     28 
     29   x = in + PITCH_MAX_LAG / 2 + 2;
     30   scaling = WebRtcSpl_GetScalingSquare((int16_t*)in,
     31                                        PITCH_CORR_LEN2,
     32                                        PITCH_CORR_LEN2);
     33   ysum32 = 1;
     34   csum32 = 0;
     35   x = in + PITCH_MAX_LAG / 2 + 2;
     36   for (n = 0; n < PITCH_CORR_LEN2; n++) {
     37     ysum32 += in[n] * in[n] >> scaling;  // Q0
     38     csum32 += x[n] * in[n] >> scaling;  // Q0
     39   }
     40   logcorQ8 += PITCH_LAG_SPAN2 - 1;
     41   lys = WebRtcIsacfix_Log2Q8((uint32_t)ysum32) >> 1; // Q8, sqrt(ysum)
     42   if (csum32 > 0) {
     43     lcs = WebRtcIsacfix_Log2Q8((uint32_t)csum32);  // 2log(csum) in Q8
     44     if (lcs > (lys + oneQ8)) {          // csum/sqrt(ysum) > 2 in Q8
     45       *logcorQ8 = lcs - lys;            // log2(csum/sqrt(ysum))
     46     } else {
     47       *logcorQ8 = oneQ8;                // 1.00
     48     }
     49   } else {
     50     *logcorQ8 = 0;
     51   }
     52 
     53 
     54   for (k = 1; k < PITCH_LAG_SPAN2; k++) {
     55     inptr = &in[k];
     56     ysum32 -= in[k - 1] * in[k - 1] >> scaling;
     57     ysum32 += in[PITCH_CORR_LEN2 + k - 1] * in[PITCH_CORR_LEN2 + k - 1] >>
     58         scaling;
     59 
     60     // TODO(zhongwei.yao): Move this function into a separate NEON code file so
     61     // that WEBRTC_DETECT_NEON could take advantage of it.
     62 #ifdef WEBRTC_HAS_NEON
     63     {
     64       int32_t vbuff[4];
     65       int32x4_t int_32x4_sum = vmovq_n_s32(0);
     66       // Can't shift a Neon register to right with a non-constant shift value.
     67       int32x4_t int_32x4_scale = vdupq_n_s32(-scaling);
     68       // Assert a codition used in loop unrolling at compile-time.
     69       COMPILE_ASSERT(PITCH_CORR_LEN2 %4 == 0);
     70 
     71       for (n = 0; n < PITCH_CORR_LEN2; n += 4) {
     72         int16x4_t int_16x4_x = vld1_s16(&x[n]);
     73         int16x4_t int_16x4_in = vld1_s16(&inptr[n]);
     74         int32x4_t int_32x4 = vmull_s16(int_16x4_x, int_16x4_in);
     75         int_32x4 = vshlq_s32(int_32x4, int_32x4_scale);
     76         int_32x4_sum = vaddq_s32(int_32x4_sum, int_32x4);
     77       }
     78 
     79       // Use vector store to avoid long stall from data trasferring
     80       // from vector to general register.
     81       vst1q_s32(vbuff, int_32x4_sum);
     82       csum32 = vbuff[0] + vbuff[1];
     83       csum32 += vbuff[2];
     84       csum32 += vbuff[3];
     85     }
     86 #else
     87     csum32 = 0;
     88     if(scaling == 0) {
     89       for (n = 0; n < PITCH_CORR_LEN2; n++) {
     90         csum32 += x[n] * inptr[n];
     91       }
     92     } else {
     93       for (n = 0; n < PITCH_CORR_LEN2; n++) {
     94         csum32 += (x[n] * inptr[n]) >> scaling;
     95       }
     96     }
     97 #endif
     98 
     99     logcorQ8--;
    100 
    101     lys = WebRtcIsacfix_Log2Q8((uint32_t)ysum32) >> 1; // Q8, sqrt(ysum)
    102 
    103     if (csum32 > 0) {
    104       lcs = WebRtcIsacfix_Log2Q8((uint32_t)csum32);  // 2log(csum) in Q8
    105       if (lcs > (lys + oneQ8)) {          // csum/sqrt(ysum) > 2
    106         *logcorQ8 = lcs - lys;            // log2(csum/sqrt(ysum))
    107       } else {
    108         *logcorQ8 = oneQ8;                // 1.00
    109       }
    110     } else {
    111       *logcorQ8 = 0;
    112     }
    113   }
    114 }
    115