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