Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / audio_coding / codecs / isac / fix / source / pitch_estimator_c.c
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 }