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 "aptXHDbtenc.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 aptxhdbtenc_t {
26   /* m_endian should either be 0 (little endian) or 8 (big endian). */
27   int32_t m_endian;
28 
29   /* Autosync inserter & Checker for use with the stereo aptX HD codec. */
30   /* The current phase of the sync word insertion (7 down to 0) */
31   uint32_t m_syncWordPhase;
32 
33   /* Stereo channel aptX HD encoder (annotated to produce Kalimba test vectors
34    * for it's I/O. This will process valid PCM from a WAV file). */
35   /* Each Encoder_data structure requires 1592 bytes */
36   Encoder_data m_encoderData[2];
37   Qmf_storage m_qmf_l;
38   Qmf_storage m_qmf_r;
39 } aptxhdbtenc;
40 
41 /* Constants */
42 /* Log to linear lookup table used in inverse quantiser*/
43 /* Size of Table: 32*4 = 128 bytes */
44 static const int32_t IQuant_tableLogT[32] = {
45     16384 * 256, 16744 * 256, 17112 * 256, 17488 * 256, 17864 * 256,
46     18256 * 256, 18656 * 256, 19064 * 256, 19480 * 256, 19912 * 256,
47     20344 * 256, 20792 * 256, 21248 * 256, 21712 * 256, 22192 * 256,
48     22672 * 256, 23168 * 256, 23680 * 256, 24200 * 256, 24728 * 256,
49     25264 * 256, 25824 * 256, 26384 * 256, 26968 * 256, 27552 * 256,
50     28160 * 256, 28776 * 256, 29408 * 256, 30048 * 256, 30704 * 256,
51     31376 * 256, 32064 * 256};
52 
clearmem_HD(void * mem,int32_t sz)53 static void clearmem_HD(void* mem, int32_t sz) {
54   int8_t* m = (int8_t*)mem;
55   int32_t i = 0;
56   for (; i < sz; i++) {
57     *m = 0;
58     m++;
59   }
60 }
61 
SizeofAptxhdbtenc()62 APTXHDBTENCEXPORT int SizeofAptxhdbtenc() { return (sizeof(aptxhdbtenc)); }
63 
aptxhdbtenc_version()64 APTXHDBTENCEXPORT const char* aptxhdbtenc_version() { return (swversion); }
65 
aptxhdbtenc_init(void * _state,short endian)66 APTXHDBTENCEXPORT int aptxhdbtenc_init(void* _state, short endian) {
67   aptxhdbtenc* state = (aptxhdbtenc*)_state;
68 
69   clearmem_HD(_state, sizeof(aptxhdbtenc));
70 
71   if (state == 0) {
72     return 1;
73   }
74   state->m_syncWordPhase = 7L;
75 
76   if (endian == 0) {
77     state->m_endian = 0;
78   } else {
79     state->m_endian = 8;
80   }
81 
82   for (int j = 0; j < 2; j++) {
83     Encoder_data* encode_dat = &state->m_encoderData[j];
84     uint32_t i;
85 
86     /* Create a quantiser and subband processor for each suband */
87     for (i = LL; i <= HH; i++) {
88       encode_dat->m_codewordHistory = 0L;
89 
90       encode_dat->m_qdata[i].thresholdTablePtr =
91           subbandParameters[i].threshTable;
92       encode_dat->m_qdata[i].thresholdTablePtr_sl1 =
93           subbandParameters[i].threshTable_sl1;
94       encode_dat->m_qdata[i].ditherTablePtr = subbandParameters[i].dithTable;
95       encode_dat->m_qdata[i].minusLambdaDTable =
96           subbandParameters[i].minusLambdaDTable;
97       encode_dat->m_qdata[i].codeBits = subbandParameters[i].numBits;
98       encode_dat->m_qdata[i].qCode = 0L;
99       encode_dat->m_qdata[i].altQcode = 0L;
100       encode_dat->m_qdata[i].distPenalty = 0L;
101 
102       /* initialisation of inverseQuantiser data */
103       encode_dat->m_SubbandData[i].m_iqdata.thresholdTablePtr =
104           subbandParameters[i].threshTable;
105       encode_dat->m_SubbandData[i].m_iqdata.thresholdTablePtr_sl1 =
106           subbandParameters[i].threshTable_sl1;
107       encode_dat->m_SubbandData[i].m_iqdata.ditherTablePtr_sf1 =
108           subbandParameters[i].dithTable_sh1;
109       encode_dat->m_SubbandData[i].m_iqdata.incrTablePtr =
110           subbandParameters[i].incrTable;
111       encode_dat->m_SubbandData[i].m_iqdata.maxLogDelta =
112           subbandParameters[i].maxLogDelta;
113       encode_dat->m_SubbandData[i].m_iqdata.minLogDelta =
114           subbandParameters[i].minLogDelta;
115       encode_dat->m_SubbandData[i].m_iqdata.delta = 0;
116       encode_dat->m_SubbandData[i].m_iqdata.logDelta = 0;
117       encode_dat->m_SubbandData[i].m_iqdata.invQ = 0;
118       encode_dat->m_SubbandData[i].m_iqdata.iquantTableLogPtr =
119           &IQuant_tableLogT[0];
120 
121       // Initializing data for predictor filter
122       encode_dat->m_SubbandData[i].m_predData.m_zeroDelayLine.modulo =
123           subbandParameters[i].numZeros;
124 
125       for (int t = 0; t < 48; t++) {
126         encode_dat->m_SubbandData[i].m_predData.m_zeroDelayLine.buffer[t] = 0;
127       }
128 
129       encode_dat->m_SubbandData[i].m_predData.m_zeroDelayLine.pointer = 0;
130       /* Initialise the previous zero filter output and predictor output to zero
131        */
132       encode_dat->m_SubbandData[i].m_predData.m_zeroVal = 0L;
133       encode_dat->m_SubbandData[i].m_predData.m_predVal = 0L;
134       encode_dat->m_SubbandData[i].m_predData.m_numZeros =
135           subbandParameters[i].numZeros;
136       /* Initialise the contents of the pole data delay line to zero */
137       encode_dat->m_SubbandData[i].m_predData.m_poleDelayLine[0] = 0L;
138       encode_dat->m_SubbandData[i].m_predData.m_poleDelayLine[1] = 0L;
139 
140       for (int k = 0; k < 24; k++) {
141         encode_dat->m_SubbandData[i].m_ZeroCoeffData.m_zeroCoeff[k] = 0;
142       }
143 
144       // Initializing data for zerocoeff update function.
145       encode_dat->m_SubbandData[i].m_ZeroCoeffData.m_numZeros =
146           subbandParameters[i].numZeros;
147 
148       /* Initializing data for PoleCoeff Update function.
149        * Fill the adaptation delay line with +1 initially */
150       encode_dat->m_SubbandData[i].m_PoleCoeffData.m_poleAdaptDelayLine.s32 =
151           0x00010001;
152 
153       /* Zero the pole coefficients */
154       encode_dat->m_SubbandData[i].m_PoleCoeffData.m_poleCoeff[0] = 0L;
155       encode_dat->m_SubbandData[i].m_PoleCoeffData.m_poleCoeff[1] = 0L;
156     }
157   }
158   return 0;
159 }
160 
aptxhdbtenc_encodestereo(void * _state,void * _pcmL,void * _pcmR,void * _buffer)161 APTXHDBTENCEXPORT int aptxhdbtenc_encodestereo(void* _state, void* _pcmL,
162                                                void* _pcmR, void* _buffer) {
163   aptxhdbtenc* state = (aptxhdbtenc*)_state;
164   int32_t* pcmL = (int32_t*)_pcmL;
165   int32_t* pcmR = (int32_t*)_pcmR;
166   int32_t* buffer = (int32_t*)_buffer;
167 
168   // Feed the PCM to the dual aptX HD encoders
169   aptxhdEncode(pcmL, &state->m_qmf_l, &state->m_encoderData[0]);
170   aptxhdEncode(pcmR, &state->m_qmf_r, &state->m_encoderData[1]);
171 
172   // Insert the autosync information into the stereo quantised codes
173   xbtEncinsertSync(&state->m_encoderData[0], &state->m_encoderData[1],
174                    &state->m_syncWordPhase);
175 
176   aptxhdPostEncode(&state->m_encoderData[0]);
177   aptxhdPostEncode(&state->m_encoderData[1]);
178 
179   // Pack the (possibly adjusted) codes into a 24-bit codeword per channel
180   buffer[0] = packCodeword(&state->m_encoderData[0]);
181   buffer[1] = packCodeword(&state->m_encoderData[1]);
182 
183   return 0;
184 }
185