1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1127fe999a8fe09ea7a39318e00262b30e38caa83ckma@webrtc.org#include <assert.h>
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1327fe999a8fe09ea7a39318e00262b30e38caa83ckma@webrtc.org#include "webrtc/modules/audio_coding/codecs/isac/fix/source/codec.h"
14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Autocorrelation function in fixed point.
16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// NOTE! Different from SPLIB-version in how it scales the signal.
17fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsacfix_AutocorrC(int32_t* __restrict r,
18fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                            const int16_t* __restrict x,
19fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                            int16_t N,
20fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                            int16_t order,
21fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                            int16_t* __restrict scale) {
22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int i = 0;
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int j = 0;
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int16_t scaling = 0;
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int32_t sum = 0;
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint32_t temp = 0;
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int64_t prod = 0;
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2927fe999a8fe09ea7a39318e00262b30e38caa83ckma@webrtc.org  // The ARM assembly code assumptoins.
3027fe999a8fe09ea7a39318e00262b30e38caa83ckma@webrtc.org  assert(N % 4 == 0);
3127fe999a8fe09ea7a39318e00262b30e38caa83ckma@webrtc.org  assert(N >= 8);
3227fe999a8fe09ea7a39318e00262b30e38caa83ckma@webrtc.org
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Calculate r[0].
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (i = 0; i < N; i++) {
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    prod += WEBRTC_SPL_MUL_16_16(x[i], x[i]);
36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Calculate scaling (the value of shifting).
39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  temp = (uint32_t)(prod >> 31);
40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if(temp == 0) {
41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    scaling = 0;
42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    scaling = 32 - WebRtcSpl_NormU32(temp);
44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  r[0] = (int32_t)(prod >> scaling);
46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Perform the actual correlation calculation.
48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (i = 1; i < order + 1; i++) {
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    prod = 0;
50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (j = 0; j < N - i; j++) {
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      prod += WEBRTC_SPL_MUL_16_16(x[j], x[i + j]);
52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum = (int32_t)(prod >> scaling);
54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    r[i] = sum;
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *scale = scaling;
58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return(order + 1);
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
62fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic const int32_t kApUpperQ15[ALLPASSSECTIONS] = { 1137, 12537 };
63fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic const int32_t kApLowerQ15[ALLPASSSECTIONS] = { 5059, 24379 };
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
66fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic void AllpassFilterForDec32(int16_t         *InOut16, //Q0
67fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                  const int32_t   *APSectionFactors, //Q15
68fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                  int16_t         lengthInOut,
69fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                  int32_t          *FilterState) //Q16
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int n, j;
72fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t a, b;
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (j=0; j<ALLPASSSECTIONS; j++) {
75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n=0;n<lengthInOut;n+=2){
76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      a = WEBRTC_SPL_MUL_16_32_RSFT16(InOut16[n], APSectionFactors[j]); //Q0*Q31=Q31 shifted 16 gives Q15
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      a = WEBRTC_SPL_LSHIFT_W32(a, 1); // Q15 -> Q16
78347671c843ed5c93d25bf1a23f9295d35ce3df4abjornv@webrtc.org      b = WebRtcSpl_AddSatW32(a, FilterState[j]);  //Q16+Q16=Q16
79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      a = WEBRTC_SPL_MUL_16_32_RSFT16(
80fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org          (int16_t) WEBRTC_SPL_RSHIFT_W32(b, 16),
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          -APSectionFactors[j]); //Q0*Q31=Q31 shifted 16 gives Q15
82347671c843ed5c93d25bf1a23f9295d35ce3df4abjornv@webrtc.org      FilterState[j] = WebRtcSpl_AddSatW32(
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          WEBRTC_SPL_LSHIFT_W32(a,1),
84fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org          WEBRTC_SPL_LSHIFT_W32((uint32_t)InOut16[n], 16)); // Q15<<1 + Q0<<16 = Q16 + Q16 = Q16
85fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      InOut16[n] = (int16_t) WEBRTC_SPL_RSHIFT_W32(b, 16); //Save as Q0
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
93fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgvoid WebRtcIsacfix_DecimateAllpass32(const int16_t *in,
94fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                     int32_t *state_in,        /* array of size: 2*ALLPASSSECTIONS+1 */
95fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                     int16_t N,                /* number of input samples */
96fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                     int16_t *out)             /* array of size N/2 */
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int n;
99fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t data_vec[PITCH_FRAME_LEN];
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* copy input */
102fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  memcpy(data_vec+1, in, WEBRTC_SPL_MUL_16_16(sizeof(int16_t), (N-1)));
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
105fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  data_vec[0] = (int16_t) WEBRTC_SPL_RSHIFT_W32(state_in[WEBRTC_SPL_MUL_16_16(2, ALLPASSSECTIONS)],16);   //the z^(-1) state
106fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  state_in[WEBRTC_SPL_MUL_16_16(2, ALLPASSSECTIONS)] = WEBRTC_SPL_LSHIFT_W32((uint32_t)in[N-1],16);
107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  AllpassFilterForDec32(data_vec+1, kApUpperQ15, N, state_in);
111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  AllpassFilterForDec32(data_vec, kApLowerQ15, N, state_in+ALLPASSSECTIONS);
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (n=0;n<N/2;n++) {
114347671c843ed5c93d25bf1a23f9295d35ce3df4abjornv@webrtc.org    out[n] = WebRtcSpl_AddSatW16(data_vec[WEBRTC_SPL_MUL_16_16(2, n)],
115347671c843ed5c93d25bf1a23f9295d35ce3df4abjornv@webrtc.org                                 data_vec[WEBRTC_SPL_MUL_16_16(2, n) + 1]);
116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
118