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/*
12 * filters.c
13 *
14 * This file contains function WebRtcIsacfix_AutocorrC,
15 * AllpassFilterForDec32, and WebRtcIsacfix_DecimateAllpass32
16 *
17 */
18
19#include <string.h>
20
21#include "pitch_estimator.h"
22#include "lpc_masking_model.h"
23#include "codec.h"
24
25// Autocorrelation function in fixed point.
26// NOTE! Different from SPLIB-version in how it scales the signal.
27int WebRtcIsacfix_AutocorrC(WebRtc_Word32* __restrict r,
28                            const WebRtc_Word16* __restrict x,
29                            WebRtc_Word16 N,
30                            WebRtc_Word16 order,
31                            WebRtc_Word16* __restrict scale) {
32  int i = 0;
33  int j = 0;
34  int16_t scaling = 0;
35  int32_t sum = 0;
36  uint32_t temp = 0;
37  int64_t prod = 0;
38
39  // Calculate r[0].
40  for (i = 0; i < N; i++) {
41    prod += WEBRTC_SPL_MUL_16_16(x[i], x[i]);
42  }
43
44  // Calculate scaling (the value of shifting).
45  temp = (uint32_t)(prod >> 31);
46  if(temp == 0) {
47    scaling = 0;
48  } else {
49    scaling = 32 - WebRtcSpl_NormU32(temp);
50  }
51  r[0] = (int32_t)(prod >> scaling);
52
53  // Perform the actual correlation calculation.
54  for (i = 1; i < order + 1; i++) {
55    prod = 0;
56    for (j = 0; j < N - i; j++) {
57      prod += WEBRTC_SPL_MUL_16_16(x[j], x[i + j]);
58    }
59    sum = (int32_t)(prod >> scaling);
60    r[i] = sum;
61  }
62
63  *scale = scaling;
64
65  return(order + 1);
66}
67
68static const WebRtc_Word32 kApUpperQ15[ALLPASSSECTIONS] = { 1137, 12537 };
69static const WebRtc_Word32 kApLowerQ15[ALLPASSSECTIONS] = { 5059, 24379 };
70
71
72static void AllpassFilterForDec32(WebRtc_Word16         *InOut16, //Q0
73                                  const WebRtc_Word32   *APSectionFactors, //Q15
74                                  WebRtc_Word16         lengthInOut,
75                                  WebRtc_Word32          *FilterState) //Q16
76{
77  int n, j;
78  WebRtc_Word32 a, b;
79
80  for (j=0; j<ALLPASSSECTIONS; j++) {
81    for (n=0;n<lengthInOut;n+=2){
82      a = WEBRTC_SPL_MUL_16_32_RSFT16(InOut16[n], APSectionFactors[j]); //Q0*Q31=Q31 shifted 16 gives Q15
83      a = WEBRTC_SPL_LSHIFT_W32(a, 1); // Q15 -> Q16
84      b = WEBRTC_SPL_ADD_SAT_W32(a, FilterState[j]); //Q16+Q16=Q16
85      a = WEBRTC_SPL_MUL_16_32_RSFT16(
86          (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(b, 16),
87          -APSectionFactors[j]); //Q0*Q31=Q31 shifted 16 gives Q15
88      FilterState[j] = WEBRTC_SPL_ADD_SAT_W32(
89          WEBRTC_SPL_LSHIFT_W32(a,1),
90          WEBRTC_SPL_LSHIFT_W32((WebRtc_UWord32)InOut16[n], 16)); // Q15<<1 + Q0<<16 = Q16 + Q16 = Q16
91      InOut16[n] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(b, 16); //Save as Q0
92    }
93  }
94}
95
96
97
98
99void WebRtcIsacfix_DecimateAllpass32(const WebRtc_Word16 *in,
100                                     WebRtc_Word32 *state_in,        /* array of size: 2*ALLPASSSECTIONS+1 */
101                                     WebRtc_Word16 N,                /* number of input samples */
102                                     WebRtc_Word16 *out)             /* array of size N/2 */
103{
104  int n;
105  WebRtc_Word16 data_vec[PITCH_FRAME_LEN];
106
107  /* copy input */
108  memcpy(data_vec+1, in, WEBRTC_SPL_MUL_16_16(sizeof(WebRtc_Word16), (N-1)));
109
110
111  data_vec[0] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(state_in[WEBRTC_SPL_MUL_16_16(2, ALLPASSSECTIONS)],16);   //the z^(-1) state
112  state_in[WEBRTC_SPL_MUL_16_16(2, ALLPASSSECTIONS)] = WEBRTC_SPL_LSHIFT_W32((WebRtc_UWord32)in[N-1],16);
113
114
115
116  AllpassFilterForDec32(data_vec+1, kApUpperQ15, N, state_in);
117  AllpassFilterForDec32(data_vec, kApLowerQ15, N, state_in+ALLPASSSECTIONS);
118
119  for (n=0;n<N/2;n++) {
120    out[n]=WEBRTC_SPL_ADD_SAT_W16(data_vec[WEBRTC_SPL_MUL_16_16(2, n)], data_vec[WEBRTC_SPL_MUL_16_16(2, n)+1]);
121  }
122}
123