1 /**
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 /*------------------------------------------------------------------------------
17 *
18 * Subband processing consists of:
19 * inverse quantisation (defined in a separate file),
20 * predictor coefficient update (Pole and Zero Coeff update),
21 * predictor filtering.
22 *
23 *----------------------------------------------------------------------------*/
24
25 #ifndef SUBBANDFUNCTIONS_H
26 #define SUBBANDFUNCTIONS_H
27 #ifdef _GCC
28 #pragma GCC visibility push(hidden)
29 #endif
30
31 #include "AptxParameters.h"
32
updatePredictorPoleCoefficients(const int32_t invQ,const int32_t prevZfiltOutput,PoleCoeff_data * PoleCoeffDataPt)33 XBT_INLINE_ void updatePredictorPoleCoefficients(
34 const int32_t invQ, const int32_t prevZfiltOutput,
35 PoleCoeff_data* PoleCoeffDataPt) {
36 int32_t adaptSum;
37 int32_t sgnP[3];
38 int32_t newCoeffs[2];
39 int32_t Bacc;
40 int32_t acc;
41 int32_t acc2;
42 int32_t tmp3_round0;
43 int16_t tmp2_round0;
44 int16_t tmp_round0;
45 /* Various constants in various Q formats */
46 const int32_t oneQ22 = 4194304L;
47 const int32_t minusOneQ22 = -4194304L;
48 const int32_t pointFiveQ21 = 1048576L;
49 const int32_t minusPointFiveQ21 = -1048576L;
50 const int32_t pointSevenFiveQ22 = 3145728L;
51 const int32_t minusPointSevenFiveQ22 = -3145728L;
52 const int32_t oneMinusTwoPowerMinusFourQ22 = 3932160L;
53
54 /* Symbolic indices for the pole coefficient arrays. Here we are using a1
55 * to represent the first pole filter coefficient and a2 the second. This
56 * seems to be common ADPCM terminology. */
57 enum { a1 = 0, a2 = 1 };
58
59 /* Symbolic indices for the sgn array (k, k-1 and k-2 respectively) */
60 enum { k = 0, k_1 = 1, k_2 = 2 };
61
62 /* Form the sum of the inverse quantiser and previous zero filter values */
63 adaptSum = invQ + prevZfiltOutput;
64 adaptSum = ssat24(adaptSum);
65
66 /* Form the sgn of the sum just formed (note +1 and -1 are Q22) */
67 if (adaptSum < 0L) {
68 sgnP[k] = minusOneQ22;
69 sgnP[k_1] = -(((int32_t)PoleCoeffDataPt->m_poleAdaptDelayLine.s16.l) << 22);
70 sgnP[k_2] = -(((int32_t)PoleCoeffDataPt->m_poleAdaptDelayLine.s16.h) << 22);
71 PoleCoeffDataPt->m_poleAdaptDelayLine.s16.h =
72 PoleCoeffDataPt->m_poleAdaptDelayLine.s16.l;
73 PoleCoeffDataPt->m_poleAdaptDelayLine.s16.l = -1;
74 } else if (adaptSum == 0L) {
75 sgnP[k] = 0L;
76 sgnP[k_1] = 0L;
77 sgnP[k_2] = 0L;
78 PoleCoeffDataPt->m_poleAdaptDelayLine.s16.h =
79 PoleCoeffDataPt->m_poleAdaptDelayLine.s16.l;
80 PoleCoeffDataPt->m_poleAdaptDelayLine.s16.l = 1;
81 } else { // adaptSum > 0L
82 sgnP[k] = oneQ22;
83 sgnP[k_1] = ((int32_t)PoleCoeffDataPt->m_poleAdaptDelayLine.s16.l) << 22;
84 sgnP[k_2] = ((int32_t)PoleCoeffDataPt->m_poleAdaptDelayLine.s16.h) << 22;
85 PoleCoeffDataPt->m_poleAdaptDelayLine.s16.h =
86 PoleCoeffDataPt->m_poleAdaptDelayLine.s16.l;
87 PoleCoeffDataPt->m_poleAdaptDelayLine.s16.l = 1;
88 }
89
90 /* Clear the accumulator and form -a1(k) * sgn(p(k))sgn(p(k-1)) in Q21. Clip
91 * it to +/- 0.5 (Q21) so that we can take f(a1) = 4 * a1. This is a partial
92 * result for the new a2 */
93 acc = 0;
94 acc -= PoleCoeffDataPt->m_poleCoeff[a1] * (sgnP[k_1] >> 22);
95
96 tmp3_round0 = acc & 0x3L;
97
98 acc += 0x001;
99 acc >>= 1;
100 if (tmp3_round0 == 0x001L) {
101 acc--;
102 }
103
104 newCoeffs[a2] = acc;
105
106 if (newCoeffs[a2] < minusPointFiveQ21) {
107 newCoeffs[a2] = minusPointFiveQ21;
108 }
109 if (newCoeffs[a2] > pointFiveQ21) {
110 newCoeffs[a2] = pointFiveQ21;
111 }
112
113 /* Load the accumulator with sgn(p(k))sgn(p(k-2)) right-shifted by 3. The
114 * 3-position shift is to multiply it by 0.25 and convert from Q22 to Q21.
115 */
116 Bacc = (sgnP[k_2] >> 3);
117 /* Add the current a2 update value to the accumulator (Q21) */
118 Bacc += newCoeffs[a2];
119 /* Shift the accumulator right by 4 positions.
120 * Right 7 places to multiply by 2^(-7)
121 * Left 2 places to scale by 4 (0.25A + B -> A + 4B)
122 * Left 1 place to convert from Q21 to Q22
123 */
124 Bacc >>= 4;
125 /* Add a2(k-1) * (1 - 2^(-7)) to the accumulator. Note that the constant is
126 * expressed as Q23, hence the product is Q22. Get the accumulator value
127 * back out. */
128 acc2 = PoleCoeffDataPt->m_poleCoeff[a2] << 8;
129 acc2 -= PoleCoeffDataPt->m_poleCoeff[a2] << 1;
130 Bacc = (int32_t)((uint32_t)Bacc << 8);
131 Bacc += acc2;
132
133 tmp2_round0 = (int16_t)Bacc & 0x01FFL;
134
135 Bacc += 0x0080L;
136 Bacc >>= 8;
137
138 if (tmp2_round0 == 0x0080L) {
139 Bacc--;
140 }
141
142 newCoeffs[a2] = Bacc;
143
144 /* Clip the new a2(k) value to +/- 0.75 (Q22) */
145 if (newCoeffs[a2] < minusPointSevenFiveQ22) {
146 newCoeffs[a2] = minusPointSevenFiveQ22;
147 }
148 if (newCoeffs[a2] > pointSevenFiveQ22) {
149 newCoeffs[a2] = pointSevenFiveQ22;
150 }
151 PoleCoeffDataPt->m_poleCoeff[a2] = newCoeffs[a2];
152
153 /* Form sgn(p(k))sgn(p(k-1)) * (3 * 2^(-8)). The constant is Q23, hence the
154 * product is Q22. */
155 /* Add a1(k-1) * (1 - 2^(-8)) to the accumulator. The constant is Q23, hence
156 * the product is Q22. Get the value from the accumulator. */
157 acc2 = PoleCoeffDataPt->m_poleCoeff[a1] << 8;
158 acc2 -= PoleCoeffDataPt->m_poleCoeff[a1];
159 acc2 += (sgnP[k_1] << 2);
160 acc2 -= (sgnP[k_1]);
161
162 tmp_round0 = (int16_t)acc2 & 0x01FF;
163
164 acc2 += 0x0080;
165 acc = (acc2 >> 8);
166 if (tmp_round0 == 0x0080) {
167 acc--;
168 }
169
170 newCoeffs[a1] = acc;
171
172 /* Clip the new value of a1(k) to +/- (1 - 2^4 - a2(k)). The constant 1 -
173 * 2^4 is expressed in Q22 format (as is a1 and a2) */
174 if (newCoeffs[a1] < (newCoeffs[a2] - oneMinusTwoPowerMinusFourQ22)) {
175 newCoeffs[a1] = newCoeffs[a2] - oneMinusTwoPowerMinusFourQ22;
176 }
177 if (newCoeffs[a1] > (oneMinusTwoPowerMinusFourQ22 - newCoeffs[a2])) {
178 newCoeffs[a1] = oneMinusTwoPowerMinusFourQ22 - newCoeffs[a2];
179 }
180 PoleCoeffDataPt->m_poleCoeff[a1] = newCoeffs[a1];
181 }
182
183 #ifdef _GCC
184 #pragma GCC visibility pop
185 #endif
186 #endif // SUBBANDFUNCTIONS_H
187