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