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  *  All declarations relevant for the SyncInserter class. This class exposes a
19  *  public interface that lets a client supply two aptX encoder objects (left
20  *  and right stereo channel) and have the current quantised codes adjusted to
21  *  bury an autosync bit.
22  *
23  *----------------------------------------------------------------------------*/
24 
25 #ifndef SYNCINSERTER_H
26 #define SYNCINSERTER_H
27 #ifdef _GCC
28 #pragma GCC visibility push(hidden)
29 #endif
30 
31 #include "AptxParameters.h"
32 
33 /* Function to insert sync information into one of the 8 quantised codes
34  * spread across 2 aptX codewords (1 codeword per channel) */
xbtEncinsertSync(Encoder_data * leftChannelEncoder,Encoder_data * rightChannelEncoder,uint32_t * syncWordPhase)35 XBT_INLINE_ void xbtEncinsertSync(Encoder_data* leftChannelEncoder,
36                                   Encoder_data* rightChannelEncoder,
37                                   uint32_t* syncWordPhase) {
38   /* Currently using 0x1 as the 8-bit sync pattern */
39   static const uint32_t syncWord = 0x1;
40   uint32_t tmp_var;
41 
42   uint32_t i;
43 
44   /* Variable to hold the XOR of all the quantised code lsbs */
45   uint32_t xorCodeLsbs;
46 
47   /* Variable to point to the quantiser with the minimum calculated distance
48    * penalty. */
49   Quantiser_data* minPenaltyQuantiser;
50 
51   /* Get the vector of quantiser pointers from the left and right encoders */
52   Quantiser_data* leftQuant[4];
53   Quantiser_data* rightQuant[4];
54   leftQuant[0] = &leftChannelEncoder->m_qdata[0];
55   leftQuant[1] = &leftChannelEncoder->m_qdata[1];
56   leftQuant[2] = &leftChannelEncoder->m_qdata[2];
57   leftQuant[3] = &leftChannelEncoder->m_qdata[3];
58   rightQuant[0] = &rightChannelEncoder->m_qdata[0];
59   rightQuant[1] = &rightChannelEncoder->m_qdata[1];
60   rightQuant[2] = &rightChannelEncoder->m_qdata[2];
61   rightQuant[3] = &rightChannelEncoder->m_qdata[3];
62 
63   /* Starting quantiser traversal with the LL quantiser from the left channel.
64    * Initialise the pointer to the minimum penalty quantiser with the details
65    * of the left LL quantiser. Initialise the code lsbs XOR variable with the
66    * left LL quantised code lsbs and also XOR in the left and right random
67    * dither bit generated by the 2 encoders. */
68   xorCodeLsbs = ((rightQuant[LL]->qCode) & 0x1) ^
69                 leftChannelEncoder->m_dithSyncRandBit ^
70                 rightChannelEncoder->m_dithSyncRandBit;
71   minPenaltyQuantiser = rightQuant[LH];
72 
73   /* Traverse across the LH, HL and HH quantisers from the right channel */
74   for (i = LH; i <= HH; i++) {
75     /* XOR in the lsb of the quantised code currently examined */
76     xorCodeLsbs ^= (rightQuant[i]->qCode) & 0x1;
77   }
78 
79   /* If the distance penalty associated with a quantiser is less than the
80    * current minimum, then make that quantiser the minimum penalty
81    * quantiser. */
82   if (rightQuant[HL]->distPenalty < minPenaltyQuantiser->distPenalty) {
83     minPenaltyQuantiser = rightQuant[HL];
84   }
85   if (rightQuant[LL]->distPenalty < minPenaltyQuantiser->distPenalty) {
86     minPenaltyQuantiser = rightQuant[LL];
87   }
88   if (rightQuant[HH]->distPenalty < minPenaltyQuantiser->distPenalty) {
89     minPenaltyQuantiser = rightQuant[HH];
90   }
91 
92   /* Traverse across all quantisers from the left channel */
93   for (i = LL; i <= HH; i++) {
94     /* XOR in the lsb of the quantised code currently examined */
95     xorCodeLsbs ^= (leftQuant[i]->qCode) & 0x1;
96   }
97 
98   /* If the distance penalty associated with a quantiser is less than the
99    * current minimum, then make that quantiser the minimum penalty
100    * quantiser. */
101   if (leftQuant[LH]->distPenalty < minPenaltyQuantiser->distPenalty) {
102     minPenaltyQuantiser = leftQuant[LH];
103   }
104   if (leftQuant[HL]->distPenalty < minPenaltyQuantiser->distPenalty) {
105     minPenaltyQuantiser = leftQuant[HL];
106   }
107   if (leftQuant[LL]->distPenalty < minPenaltyQuantiser->distPenalty) {
108     minPenaltyQuantiser = leftQuant[LL];
109   }
110   if (leftQuant[HH]->distPenalty < minPenaltyQuantiser->distPenalty) {
111     minPenaltyQuantiser = leftQuant[HH];
112   }
113 
114   /* If the lsbs of all 8 quantised codes don't happen to equal the desired
115    * sync bit to embed, then force them to be by replacing the optimum code
116    * with the alternate code in the minimum penalty quantiser (changes the lsb
117    * of the code in this quantiser) */
118   if (xorCodeLsbs != ((syncWord >> (*syncWordPhase)) & 0x1)) {
119     minPenaltyQuantiser->qCode = minPenaltyQuantiser->altQcode;
120   }
121 
122   /* Decrement the selected sync word bit modulo 8 for the next pass. */
123   tmp_var = --(*syncWordPhase);
124   (*syncWordPhase) = tmp_var & 0x7;
125 }
126 
xbtEncinsertSyncDualMono(Encoder_data * leftChannelEncoder,Encoder_data * rightChannelEncoder,uint32_t * syncWordPhase)127 XBT_INLINE_ void xbtEncinsertSyncDualMono(Encoder_data* leftChannelEncoder,
128                                           Encoder_data* rightChannelEncoder,
129                                           uint32_t* syncWordPhase) {
130   /* Currently using 0x1 as the 8-bit sync pattern */
131   static const uint32_t syncWord = 0x1;
132   uint32_t tmp_var;
133 
134   uint32_t i;
135 
136   /* Variable to hold the XOR of all the quantised code lsbs */
137   uint32_t xorCodeLsbs;
138 
139   /* Variable to point to the quantiser with the minimum calculated distance
140    * penalty. */
141   Quantiser_data* minPenaltyQuantiser;
142 
143   /* Get the vector of quantiser pointers from the left and right encoders */
144   Quantiser_data* leftQuant[4];
145   Quantiser_data* rightQuant[4];
146   leftQuant[0] = &leftChannelEncoder->m_qdata[0];
147   leftQuant[1] = &leftChannelEncoder->m_qdata[1];
148   leftQuant[2] = &leftChannelEncoder->m_qdata[2];
149   leftQuant[3] = &leftChannelEncoder->m_qdata[3];
150   rightQuant[0] = &rightChannelEncoder->m_qdata[0];
151   rightQuant[1] = &rightChannelEncoder->m_qdata[1];
152   rightQuant[2] = &rightChannelEncoder->m_qdata[2];
153   rightQuant[3] = &rightChannelEncoder->m_qdata[3];
154 
155   /* Starting quantiser traversal with the LL quantiser from the left channel.
156    * Initialise the pointer to the minimum penalty quantiser with the details
157    * of the left LL quantiser. Initialise the code lsbs XOR variable with the
158    * left LL quantised code lsbs */
159   xorCodeLsbs = leftChannelEncoder->m_dithSyncRandBit;
160 
161   minPenaltyQuantiser = leftQuant[LH];
162 
163   /* Traverse across all the quantisers from the left channel */
164   for (i = LL; i <= HH; i++) {
165     /* XOR in the lsb of the quantised code currently examined */
166     xorCodeLsbs ^= (leftQuant[i]->qCode) & 0x1;
167   }
168 
169   /* If the distance penalty associated with a quantiser is less than the
170    * current minimum, then make that quantiser the minimum penalty
171    * quantiser. */
172   if (leftQuant[LH]->distPenalty < minPenaltyQuantiser->distPenalty) {
173     minPenaltyQuantiser = leftQuant[LH];
174   }
175   if (leftQuant[HL]->distPenalty < minPenaltyQuantiser->distPenalty) {
176     minPenaltyQuantiser = leftQuant[HL];
177   }
178   if (leftQuant[LL]->distPenalty < minPenaltyQuantiser->distPenalty) {
179     minPenaltyQuantiser = leftQuant[LL];
180   }
181   if (leftQuant[HH]->distPenalty < minPenaltyQuantiser->distPenalty) {
182     minPenaltyQuantiser = leftQuant[HH];
183   }
184 
185   /* If the lsbs of all 4 quantised codes don't happen to equal the desired
186    * sync bit to embed, then force them to be by replacing the optimum code
187    * with the alternate code in the minimum penalty quantiser (changes the lsb
188    * of the code in this quantiser) */
189   if (xorCodeLsbs != ((syncWord >> (*syncWordPhase)) & 0x1)) {
190     minPenaltyQuantiser->qCode = minPenaltyQuantiser->altQcode;
191   }
192 
193   /****  Insert sync on the Right channel  ****/
194   xorCodeLsbs = rightChannelEncoder->m_dithSyncRandBit;
195 
196   minPenaltyQuantiser = rightQuant[LH];
197 
198   /* Traverse across all quantisers from the right channel */
199   for (i = LL; i <= HH; i++) {
200     /* XOR in the lsb of the quantised code currently examined */
201     xorCodeLsbs ^= (rightQuant[i]->qCode) & 0x1;
202   }
203 
204   /* If the distance penalty associated with a quantiser is less than the
205    * current minimum, then make that quantiser the minimum penalty
206    * quantiser. */
207   if (rightQuant[LH]->distPenalty < minPenaltyQuantiser->distPenalty) {
208     minPenaltyQuantiser = rightQuant[LH];
209   }
210   if (rightQuant[HL]->distPenalty < minPenaltyQuantiser->distPenalty) {
211     minPenaltyQuantiser = rightQuant[HL];
212   }
213   if (rightQuant[LL]->distPenalty < minPenaltyQuantiser->distPenalty) {
214     minPenaltyQuantiser = rightQuant[LL];
215   }
216   if (rightQuant[HH]->distPenalty < minPenaltyQuantiser->distPenalty) {
217     minPenaltyQuantiser = rightQuant[HH];
218   }
219 
220   /* If the lsbs of all 4 quantised codes don't happen to equal the desired
221    * sync bit to embed, then force them to be by replacing the optimum code
222    * with the alternate code in the minimum penalty quantiser (changes the lsb
223    * of the code in this quantiser) */
224   if (xorCodeLsbs != ((syncWord >> (*syncWordPhase)) & 0x1)) {
225     minPenaltyQuantiser->qCode = minPenaltyQuantiser->altQcode;
226   }
227 
228   /*  End of Right channel autosync insert*/
229   /* Decrement the selected sync word bit modulo 8 for the next pass. */
230   tmp_var = --(*syncWordPhase);
231   (*syncWordPhase) = tmp_var & 0x7;
232 }
233 
234 #ifdef _GCC
235 #pragma GCC visibility pop
236 #endif
237 #endif  // SYNCINSERTER_H
238