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 #include "aptXbtenc.h"
17 
18 #include "AptxEncoder.h"
19 #include "AptxParameters.h"
20 #include "AptxTables.h"
21 #include "CodewordPacker.h"
22 #include "SyncInserter.h"
23 #include "swversion.h"
24 
25 typedef struct aptxbtenc_t {
26   /* m_endian should either be 0 (little endian) or 8 (big endian). */
27   int32_t m_endian;
28 
29   /* m_sync_mode is an enumerated type and will be
30      0 (stereo sync),
31      1 (for dual mono sync), or
32      2 (for dual channel with no autosync).
33   */
34   int32_t m_sync_mode;
35 
36   /* Autosync inserter & Checker for use with the stereo aptX codec. */
37   /* The current phase of the sync word insertion (7 down to 0) */
38   uint32_t m_syncWordPhase;
39 
40   /* Stereo channel aptX encoder (annotated to produce Kalimba test vectors
41    * for it's I/O. This will process valid PCM from a WAV file). */
42   /* Each Encoder_data structure requires 1592 bytes */
43   Encoder_data m_encoderData[2];
44   Qmf_storage m_qmf_l;
45   Qmf_storage m_qmf_r;
46 } aptxbtenc;
47 
48 /* Log to linear lookup table used in inverse quantiser*/
49 /* Size of Table: 32*4 = 128 bytes */
50 static const int32_t IQuant_tableLogT[32] = {
51     16384 * 256, 16744 * 256, 17112 * 256, 17488 * 256, 17864 * 256,
52     18256 * 256, 18656 * 256, 19064 * 256, 19480 * 256, 19912 * 256,
53     20344 * 256, 20792 * 256, 21248 * 256, 21712 * 256, 22192 * 256,
54     22672 * 256, 23168 * 256, 23680 * 256, 24200 * 256, 24728 * 256,
55     25264 * 256, 25824 * 256, 26384 * 256, 26968 * 256, 27552 * 256,
56     28160 * 256, 28776 * 256, 29408 * 256, 30048 * 256, 30704 * 256,
57     31376 * 256, 32064 * 256};
58 
clearmem(void * mem,int32_t sz)59 static void clearmem(void* mem, int32_t sz) {
60   int8_t* m = (int8_t*)mem;
61   int32_t i = 0;
62   for (; i < sz; i++) {
63     *m = 0;
64     m++;
65   }
66 }
67 
SizeofAptxbtenc(void)68 APTXBTENCEXPORT int SizeofAptxbtenc(void) { return (sizeof(aptxbtenc)); }
69 
aptxbtenc_version()70 APTXBTENCEXPORT const char* aptxbtenc_version() { return (swversion); }
71 
aptxbtenc_init(void * _state,short endian)72 APTXBTENCEXPORT int aptxbtenc_init(void* _state, short endian) {
73   aptxbtenc* state = (aptxbtenc*)_state;
74   int32_t j = 0;
75   int32_t k;
76   int32_t t;
77 
78   clearmem(_state, sizeof(aptxbtenc));
79 
80   if (state == 0) {
81     return 1;
82   }
83   state->m_syncWordPhase = 7L;
84 
85   if (endian == 0) {
86     state->m_endian = 0;
87   } else {
88     state->m_endian = 8;
89   }
90 
91   /* default setting should be stereo autosync,
92   for backwards-compatibility with legacy applications that use this library */
93   state->m_sync_mode = stereo;
94 
95   for (j = 0; j < 2; j++) {
96     Encoder_data* encode_dat = &state->m_encoderData[j];
97     uint32_t i;
98 
99     /* Create a quantiser and subband processor for each subband */
100     for (i = LL; i <= HH; i++) {
101       encode_dat->m_codewordHistory = 0L;
102 
103       encode_dat->m_qdata[i].thresholdTablePtr =
104           subbandParameters[i].threshTable;
105       encode_dat->m_qdata[i].thresholdTablePtr_sl1 =
106           subbandParameters[i].threshTable_sl1;
107       encode_dat->m_qdata[i].ditherTablePtr = subbandParameters[i].dithTable;
108       encode_dat->m_qdata[i].minusLambdaDTable =
109           subbandParameters[i].minusLambdaDTable;
110       encode_dat->m_qdata[i].codeBits = subbandParameters[i].numBits;
111       encode_dat->m_qdata[i].qCode = 0L;
112       encode_dat->m_qdata[i].altQcode = 0L;
113       encode_dat->m_qdata[i].distPenalty = 0L;
114 
115       /* initialisation of inverseQuantiser data */
116       encode_dat->m_SubbandData[i].m_iqdata.thresholdTablePtr =
117           subbandParameters[i].threshTable;
118       encode_dat->m_SubbandData[i].m_iqdata.thresholdTablePtr_sl1 =
119           subbandParameters[i].threshTable_sl1;
120       encode_dat->m_SubbandData[i].m_iqdata.ditherTablePtr_sf1 =
121           subbandParameters[i].dithTable_sh1;
122       encode_dat->m_SubbandData[i].m_iqdata.incrTablePtr =
123           subbandParameters[i].incrTable;
124       encode_dat->m_SubbandData[i].m_iqdata.maxLogDelta =
125           subbandParameters[i].maxLogDelta;
126       encode_dat->m_SubbandData[i].m_iqdata.minLogDelta =
127           subbandParameters[i].minLogDelta;
128       encode_dat->m_SubbandData[i].m_iqdata.delta = 0;
129       encode_dat->m_SubbandData[i].m_iqdata.logDelta = 0;
130       encode_dat->m_SubbandData[i].m_iqdata.invQ = 0;
131       encode_dat->m_SubbandData[i].m_iqdata.iquantTableLogPtr =
132           &IQuant_tableLogT[0];
133 
134       // Initializing data for predictor filter
135       encode_dat->m_SubbandData[i].m_predData.m_zeroDelayLine.modulo =
136           subbandParameters[i].numZeros;
137 
138       for (t = 0; t < 48; t++) {
139         encode_dat->m_SubbandData[i].m_predData.m_zeroDelayLine.buffer[t] = 0;
140       }
141 
142       encode_dat->m_SubbandData[i].m_predData.m_zeroDelayLine.pointer = 0;
143       /* Initialise the previous zero filter output and predictor output to zero
144        */
145       encode_dat->m_SubbandData[i].m_predData.m_zeroVal = 0L;
146       encode_dat->m_SubbandData[i].m_predData.m_predVal = 0L;
147       encode_dat->m_SubbandData[i].m_predData.m_numZeros =
148           subbandParameters[i].numZeros;
149       /* Initialise the contents of the pole data delay line to zero */
150       encode_dat->m_SubbandData[i].m_predData.m_poleDelayLine[0] = 0L;
151       encode_dat->m_SubbandData[i].m_predData.m_poleDelayLine[1] = 0L;
152 
153       for (k = 0; k < 24; k++) {
154         encode_dat->m_SubbandData[i].m_ZeroCoeffData.m_zeroCoeff[k] = 0;
155       }
156       // Initializing data for zerocoeff update function.
157       encode_dat->m_SubbandData[i].m_ZeroCoeffData.m_numZeros =
158           subbandParameters[i].numZeros;
159 
160       /* Initializing data for PoleCoeff Update function.
161        * Fill the adaptation delay line with +1 initially */
162       encode_dat->m_SubbandData[i].m_PoleCoeffData.m_poleAdaptDelayLine.s32 =
163           0x00010001;
164 
165       /* Zero the pole coefficients */
166       encode_dat->m_SubbandData[i].m_PoleCoeffData.m_poleCoeff[0] = 0L;
167       encode_dat->m_SubbandData[i].m_PoleCoeffData.m_poleCoeff[1] = 0L;
168     }
169   }
170   return 0;
171 }
172 
aptxbtenc_setsync_mode(void * _state,int32_t sync_mode)173 APTXBTENCEXPORT int aptxbtenc_setsync_mode(void* _state, int32_t sync_mode) {
174   aptxbtenc* state = (aptxbtenc*)_state;
175   state->m_sync_mode = sync_mode;
176 
177   return 0;
178 }
179 
aptxbtenc_encodestereo(void * _state,void * _pcmL,void * _pcmR,void * _buffer)180 APTXBTENCEXPORT int aptxbtenc_encodestereo(void* _state, void* _pcmL,
181                                            void* _pcmR, void* _buffer) {
182   aptxbtenc* state = (aptxbtenc*)_state;
183   int32_t* pcmL = (int32_t*)_pcmL;
184   int32_t* pcmR = (int32_t*)_pcmR;
185   int16_t* buffer = (int16_t*)_buffer;
186   int16_t tmp_reg;
187   int16_t tmp_out;
188   // Feed the PCM to the dual aptX encoders
189   aptxEncode(pcmL, &state->m_qmf_l, &state->m_encoderData[0]);
190   aptxEncode(pcmR, &state->m_qmf_r, &state->m_encoderData[1]);
191 
192   // only insert sync information if we are not in non-autosync mode.
193   // The Non-autosync mode changes only take effect in the packCodeword()
194   // function.
195   if (state->m_sync_mode != no_sync) {
196     if (state->m_sync_mode == stereo) {
197       // Insert the autosync information into the stereo quantised codes
198       xbtEncinsertSync(&state->m_encoderData[0], &state->m_encoderData[1],
199                        &state->m_syncWordPhase);
200     } else {
201       // Insert the autosync information into the two individual mono quantised
202       // codes
203       xbtEncinsertSyncDualMono(&state->m_encoderData[0],
204                                &state->m_encoderData[1],
205                                &state->m_syncWordPhase);
206     }
207   }
208 
209   aptxPostEncode(&state->m_encoderData[0]);
210   aptxPostEncode(&state->m_encoderData[1]);
211 
212   // Pack the (possibly adjusted) codes into a 16-bit codeword per channel
213   tmp_reg = packCodeword(&state->m_encoderData[0], state->m_sync_mode);
214   // Swap bytes to output data in big-endian as expected by bc5 code...
215   tmp_out = tmp_reg >> state->m_endian;
216   tmp_out |= tmp_reg << state->m_endian;
217 
218   buffer[0] = tmp_out;
219   tmp_reg = packCodeword(&state->m_encoderData[1], state->m_sync_mode);
220   // Swap bytes to output data in big-endian as expected by bc5 code...
221   tmp_out = tmp_reg >> state->m_endian;
222   tmp_out |= tmp_reg << state->m_endian;
223 
224   buffer[1] = tmp_out;
225 
226   return 0;
227 }
228