• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(const int32_t invQ, const int32_t prevZfiltOutput,
34                                                  PoleCoeff_data* PoleCoeffDataPt) {
35   int32_t adaptSum;
36   int32_t sgnP[3];
37   int32_t newCoeffs[2];
38   int32_t Bacc;
39   int32_t acc;
40   int32_t acc2;
41   int32_t tmp3_round0;
42   int16_t tmp2_round0;
43   int16_t tmp_round0;
44   /* Various constants in various Q formats */
45   const int32_t oneQ22 = 4194304L;
46   const int32_t minusOneQ22 = -4194304L;
47   const int32_t pointFiveQ21 = 1048576L;
48   const int32_t minusPointFiveQ21 = -1048576L;
49   const int32_t pointSevenFiveQ22 = 3145728L;
50   const int32_t minusPointSevenFiveQ22 = -3145728L;
51   const int32_t oneMinusTwoPowerMinusFourQ22 = 3932160L;
52 
53   /* Symbolic indices for the pole coefficient arrays. Here we are using a1
54    * to represent the first pole filter coefficient and a2 the second. This
55    * seems to be common ADPCM terminology. */
56   enum { a1 = 0, a2 = 1 };
57 
58   /* Symbolic indices for the sgn array (k, k-1 and k-2 respectively) */
59   enum { k = 0, k_1 = 1, k_2 = 2 };
60 
61   /* Form the sum of the inverse quantiser and previous zero filter values */
62   adaptSum = invQ + prevZfiltOutput;
63   adaptSum = ssat24(adaptSum);
64 
65   /* Form the sgn of the sum just formed (note +1 and -1 are Q22) */
66   if (adaptSum < 0L) {
67     sgnP[k] = minusOneQ22;
68     sgnP[k_1] = -(((int32_t)PoleCoeffDataPt->m_poleAdaptDelayLine.s16.l) << 22);
69     sgnP[k_2] = -(((int32_t)PoleCoeffDataPt->m_poleAdaptDelayLine.s16.h) << 22);
70     PoleCoeffDataPt->m_poleAdaptDelayLine.s16.h = PoleCoeffDataPt->m_poleAdaptDelayLine.s16.l;
71     PoleCoeffDataPt->m_poleAdaptDelayLine.s16.l = -1;
72   }
73   if (adaptSum == 0L) {
74     sgnP[k] = 0L;
75     sgnP[k_1] = 0L;
76     sgnP[k_2] = 0L;
77     PoleCoeffDataPt->m_poleAdaptDelayLine.s16.h = PoleCoeffDataPt->m_poleAdaptDelayLine.s16.l;
78     PoleCoeffDataPt->m_poleAdaptDelayLine.s16.l = 1;
79   }
80   if (adaptSum > 0L) {
81     sgnP[k] = oneQ22;
82     sgnP[k_1] = ((int32_t)PoleCoeffDataPt->m_poleAdaptDelayLine.s16.l) << 22;
83     sgnP[k_2] = ((int32_t)PoleCoeffDataPt->m_poleAdaptDelayLine.s16.h) << 22;
84     PoleCoeffDataPt->m_poleAdaptDelayLine.s16.h = PoleCoeffDataPt->m_poleAdaptDelayLine.s16.l;
85     PoleCoeffDataPt->m_poleAdaptDelayLine.s16.l = 1;
86   }
87 
88   /* Clear the accumulator and form -a1(k) * sgn(p(k))sgn(p(k-1)) in Q21. Clip
89    * it to +/- 0.5 (Q21) so that we can take f(a1) = 4 * a1. This is a partial
90    * result for the new a2 */
91   acc = 0;
92   acc -= PoleCoeffDataPt->m_poleCoeff[a1] * (sgnP[k_1] >> 22);
93 
94   tmp3_round0 = acc & 0x3L;
95 
96   acc += 0x001;
97   acc >>= 1;
98   if (tmp3_round0 == 0x001L) {
99     acc--;
100   }
101 
102   newCoeffs[a2] = acc;
103 
104   if (newCoeffs[a2] < minusPointFiveQ21) {
105     newCoeffs[a2] = minusPointFiveQ21;
106   }
107   if (newCoeffs[a2] > pointFiveQ21) {
108     newCoeffs[a2] = pointFiveQ21;
109   }
110 
111   /* Load the accumulator with sgn(p(k))sgn(p(k-2)) right-shifted by 3. The
112    * 3-position shift is to multiply it by 0.25 and convert from Q22 to Q21. */
113   Bacc = (sgnP[k_2] >> 3);
114   /* Add the current a2 update value to the accumulator (Q21) */
115   Bacc += newCoeffs[a2];
116   /* Shift the accumulator right by 4 positions.
117    * Right 7 places to multiply by 2^(-7)
118    * Left 2 places to scale by 4 (0.25A + B -> A + 4B)
119    * Left 1 place to convert from Q21 to Q22 */
120   Bacc >>= 4;
121   /* Add a2(k-1) * (1 - 2^(-7)) to the accumulator. Note that the constant is
122    * expressed as Q23, hence the product is Q22. Get the accumulator value
123    * back out. */
124   acc2 = PoleCoeffDataPt->m_poleCoeff[a2] << 8;
125   acc2 -= PoleCoeffDataPt->m_poleCoeff[a2] << 1;
126   Bacc = (int32_t)((uint32_t)Bacc << 8);
127   Bacc += acc2;
128 
129   tmp2_round0 = (int16_t)Bacc & 0x01FFL;
130 
131   Bacc += 0x0080L;
132   Bacc >>= 8;
133 
134   if (tmp2_round0 == 0x0080L) {
135     Bacc--;
136   }
137 
138   newCoeffs[a2] = Bacc;
139 
140   /* Clip the new a2(k) value to +/- 0.75 (Q22) */
141   if (newCoeffs[a2] < minusPointSevenFiveQ22) {
142     newCoeffs[a2] = minusPointSevenFiveQ22;
143   }
144   if (newCoeffs[a2] > pointSevenFiveQ22) {
145     newCoeffs[a2] = pointSevenFiveQ22;
146   }
147   PoleCoeffDataPt->m_poleCoeff[a2] = newCoeffs[a2];
148 
149   /* Form sgn(p(k))sgn(p(k-1)) * (3 * 2^(-8)). The constant is Q23, hence the
150    * product is Q22. */
151   /* Add a1(k-1) * (1 - 2^(-8)) to the accumulator. The constant is Q23, hence
152    * the product is Q22. Get the value from the accumulator. */
153   acc2 = PoleCoeffDataPt->m_poleCoeff[a1] << 8;
154   acc2 -= PoleCoeffDataPt->m_poleCoeff[a1];
155   acc2 += (sgnP[k_1] << 2);
156   acc2 -= (sgnP[k_1]);
157 
158   tmp_round0 = (int16_t)acc2 & 0x01FF;
159 
160   acc2 += 0x0080;
161   acc = (acc2 >> 8);
162   if (tmp_round0 == 0x0080) {
163     acc--;
164   }
165 
166   newCoeffs[a1] = acc;
167 
168   /* Clip the new value of a1(k) to +/- (1 - 2^4 - a2(k)). The constant 1 -
169    * 2^4 is expressed in Q22 format (as is a1 and a2) */
170   if (newCoeffs[a1] < (newCoeffs[a2] - oneMinusTwoPowerMinusFourQ22)) {
171     newCoeffs[a1] = newCoeffs[a2] - oneMinusTwoPowerMinusFourQ22;
172   }
173   if (newCoeffs[a1] > (oneMinusTwoPowerMinusFourQ22 - newCoeffs[a2])) {
174     newCoeffs[a1] = oneMinusTwoPowerMinusFourQ22 - newCoeffs[a2];
175   }
176 
177   PoleCoeffDataPt->m_poleCoeff[a1] = newCoeffs[a1];
178 }
179 
180 #ifdef _GCC
181 #pragma GCC visibility pop
182 #endif
183 #endif  // SUBBANDFUNCTIONS_H
184