Line data Source code
1 : /******************************************************************************
2 : * ETSI TS 103 634 V1.5.1 *
3 : * Low Complexity Communication Codec Plus (LC3plus) *
4 : * *
5 : * Copyright licence is solely granted through ETSI Intellectual Property *
6 : * Rights Policy, 3rd April 2019. No patent licence is granted by implication, *
7 : * estoppel or otherwise. *
8 : ******************************************************************************/
9 :
10 : #include "functions.h"
11 :
12 : static void Parcor2Index(const Word16 parCoeff[] /*Q15*/, Word16 index[], Word16 order);
13 : static void Index2Parcor(const Word16 index[], Word16 parCoeff[], Word16 order);
14 : static Word32 FIRLattice(Word16 order, const Word16 *parCoeff /*Q15*/, Word32 *state, Word32 x /* Q0 */);
15 :
16 : /*************************************************************************/
17 :
18 0 : void processTnsCoder_fx(Word16 *bits, Word16 indexes[], Word32 x[], Word16 BW_cutoff_idx, Word16 order[],
19 : Word16 *numfilters, Word16 enable_lpc_weighting, Word16 nSubdivisions, Word16 frame_dms,
20 : Word16 maxLen, Word8 *scratchBuffer
21 : #ifdef ENABLE_HR_MODE
22 : , Word16 hrmode
23 : #endif
24 : , Word16 near_nyquist_flag
25 : )
26 : {
27 : Dyn_Mem_Deluxe_In(Word16 * tmpbuf; Word32 * rxx, epsP, *state, L_tmp, *A, predictionGain, alpha; Word16 * RC, inv;
28 : Word16 n, n2, headroom, shift, tmp, shifts, facs, facs_e, stopfreq, xLen, maxOrder;
29 : Word16 startfreq[TNS_NUMFILTERS_MAX]; const Word16 *subdiv_startfreq, *subdiv_stopfreq;
30 : Counter i, j, iSubdivisions, lag; Word8 * LevinsonBuffer;);
31 :
32 : /* Buffer alignment */
33 0 : tmpbuf = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * MAX_LEN */
34 :
35 0 : rxx = (Word32 *)scratchAlign(tmpbuf, sizeof(*tmpbuf) * maxLen); /* Size = 4 * (MAXLAG + 1) = 36 bytes */
36 :
37 0 : state = (Word32 *)scratchAlign(rxx, sizeof(*rxx) * (MAXLAG + 1)); /* Size = 4 * MAXLAG = 32 bytes */
38 :
39 0 : A = (Word32 *)scratchAlign(state, sizeof(*state) * MAXLAG); /* Size = 4 * (MAXLAG + 1) = 36 bytes */
40 :
41 0 : RC = (Word16 *)scratchAlign(A, sizeof(*A) * (MAXLAG + 1)); /* Size = 2 * MAXLAG = 16 bytes */
42 :
43 0 : LevinsonBuffer = (Word8 *)scratchAlign(RC, sizeof(*RC) * (MAXLAG)); /* Size = 4 * (M_LTPF + 1) = 100 bytes */
44 :
45 : /* Init */
46 0 : *bits = 0;
47 0 : move16();
48 0 : maxOrder = MAXLAG;
49 0 : move16();
50 0 : *numfilters = 1;
51 0 : move16();
52 :
53 : #ifdef ENABLE_HR_MODE
54 0 : if (hrmode)
55 : {
56 0 : xLen = BW_cutoff_bin_all_HR[BW_cutoff_idx];
57 : }
58 : else
59 : #endif
60 : {
61 0 : xLen = BW_cutoff_bin_all[BW_cutoff_idx];
62 : }
63 0 : move16();
64 :
65 0 : SWITCH (frame_dms)
66 : {
67 0 : case 25:
68 0 : startfreq[0] = 3;
69 0 : move16();
70 :
71 : #ifdef ENABLE_HR_MODE
72 0 : if (hrmode)
73 : {
74 0 : subdiv_startfreq = tns_subdiv_startfreq_2_5ms_HR[BW_cutoff_idx - 4];
75 0 : move16();
76 0 : subdiv_stopfreq = tns_subdiv_stopfreq_2_5ms_HR[BW_cutoff_idx - 4];
77 0 : move16();
78 : }
79 : else
80 : #endif
81 : {
82 0 : subdiv_startfreq = tns_subdiv_startfreq_2_5ms[BW_cutoff_idx];
83 0 : move16();
84 0 : subdiv_stopfreq = tns_subdiv_stopfreq_2_5ms[BW_cutoff_idx];
85 0 : move16();
86 : }
87 0 : xLen = shr_pos(xLen, 2);
88 0 : maxOrder = 4;
89 0 : move16();
90 0 : BREAK;
91 0 : case 50:
92 0 : startfreq[0] = 6;
93 0 : move16();
94 :
95 : #ifdef ENABLE_HR_MODE
96 0 : if (hrmode)
97 : {
98 0 : subdiv_startfreq = tns_subdiv_startfreq_5ms_HR[BW_cutoff_idx - 4];
99 0 : move16();
100 0 : subdiv_stopfreq = tns_subdiv_stopfreq_5ms_HR[BW_cutoff_idx - 4];
101 0 : move16();
102 : }
103 : else
104 : #endif
105 : {
106 0 : subdiv_startfreq = tns_subdiv_startfreq_5ms[BW_cutoff_idx];
107 0 : move16();
108 0 : subdiv_stopfreq = tns_subdiv_stopfreq_5ms[BW_cutoff_idx];
109 0 : move16();
110 : }
111 0 : xLen = shr_pos(xLen, 1);
112 0 : maxOrder = 4;
113 0 : BREAK;
114 0 : case 75:
115 0 : startfreq[0] = 9;
116 0 : move16();
117 0 : subdiv_startfreq = tns_subdiv_startfreq_7_5ms[BW_cutoff_idx];
118 0 : move16();
119 0 : subdiv_stopfreq = tns_subdiv_stopfreq_7_5ms[BW_cutoff_idx];
120 0 : move16();
121 0 : tmp = shr_pos(xLen, 2);
122 0 : xLen = add(tmp, add(tmp, tmp));
123 0 : maxOrder = 8;
124 0 : BREAK;
125 0 : default: /* 100 */
126 0 : startfreq[0] = 12;
127 0 : move16();
128 :
129 : #ifdef ENABLE_HR_MODE
130 0 : if (hrmode)
131 : {
132 0 : subdiv_startfreq = tns_subdiv_startfreq_HR[BW_cutoff_idx - 4];
133 0 : move16();
134 0 : subdiv_stopfreq = tns_subdiv_stopfreq_HR[BW_cutoff_idx - 4];
135 0 : move16();
136 : }
137 : else
138 : #endif
139 : {
140 0 : subdiv_startfreq = tns_subdiv_startfreq[BW_cutoff_idx];
141 0 : move16();
142 0 : subdiv_stopfreq = tns_subdiv_stopfreq[BW_cutoff_idx];
143 0 : move16();
144 : }
145 0 : BREAK;
146 : }
147 :
148 0 : IF (sub(BW_cutoff_idx, 3) >= 0 && frame_dms >= 50)
149 : {
150 0 : *numfilters = 2;
151 0 : startfreq[1] = shr_pos(xLen, 1);
152 : }
153 :
154 0 : basop_memset(state, 0, MAXLAG * sizeof(*state));
155 :
156 0 : FOR (j = 0; j < *numfilters; j++)
157 : {
158 0 : basop_memset(rxx, 0, (maxOrder + 1) * sizeof(*rxx));
159 :
160 0 : FOR (iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++)
161 : {
162 0 : n = sub(subdiv_stopfreq[nSubdivisions * j + iSubdivisions],
163 0 : subdiv_startfreq[nSubdivisions * j + iSubdivisions]);
164 :
165 : /*norms[iFilter][iSubdivisions] = norm2FLOAT(pSpectrum+iStartLine, iEndLine-iStartLine);*/
166 0 : headroom = getScaleFactor32_lc3plus(x + subdiv_startfreq[nSubdivisions * j + iSubdivisions], n);
167 :
168 : /* Calculate norm of spectrum band */
169 0 : L_tmp = Norm32Norm(x + subdiv_startfreq[nSubdivisions * j + iSubdivisions], headroom, n, &shift);
170 :
171 : /* Rounding to avoid overflow when computing the autocorrelation below */
172 0 : tmp = sub(norm_l(L_tmp), 1);
173 0 : L_tmp = L_shl(L_tmp, tmp);
174 0 : shift = sub(shift, tmp);
175 0 : L_tmp = L_add(L_tmp, 0x8000);
176 0 : L_tmp = L_and(L_tmp, 0x7FFF0000);
177 :
178 0 : IF (L_tmp == 0)
179 : {
180 0 : rxx[0] = 0x7FFFFFFF;
181 0 : move32();
182 0 : basop_memset(&rxx[1], 0, (maxOrder) * sizeof(*rxx));
183 0 : BREAK;
184 : }
185 :
186 : /* get pre-shift for autocorrelation */
187 0 : tmp = sub(shift, norm_l(L_tmp)); /* exponent for normalized L_tmp */
188 0 : tmp = shr_pos(sub(1, tmp), 1); /* pre-shift to apply before autocorrelation */
189 0 : shifts = s_min(tmp, headroom);
190 :
191 : /* calc normalization factor */
192 0 : facs_e = shl_pos(sub(tmp, shifts), 1);
193 :
194 0 : SWITCH (frame_dms)
195 : {
196 0 : case 25: facs_e = add(facs_e, 1); BREAK;
197 0 : case 50: facs_e = add(facs_e, 1); BREAK;
198 0 : case 75: BREAK;
199 0 : case 100: BREAK;
200 : }
201 :
202 0 : tmp = sub(1, shl_pos(tmp, 1)); /* exponent of autocorrelation */
203 0 : L_tmp = L_shl(L_tmp, sub(shift, tmp)); /* shift L_tmp to that exponent */
204 : /* calc factor (with 2 bits headroom for sum of 3 subdivisions) */
205 0 : facs = div_s(0x2000, round_fx(L_tmp)); /* L_tmp is >= 0x2000000 */
206 :
207 0 : FOR (i = 0; i < n; i++)
208 : {
209 0 : tmpbuf[i] = round_fx_sat(L_shl_sat(x[subdiv_startfreq[nSubdivisions * j + iSubdivisions] + i], shifts));
210 0 : move16();
211 : }
212 :
213 0 : FOR (lag = 0; lag <= maxOrder; lag++)
214 : {
215 0 : n2 = sub(n, lag);
216 0 : L_tmp = L_deposit_l(0);
217 0 : FOR (i = 0; i < n2; i++)
218 : {
219 0 : L_tmp = L_mac0(L_tmp, tmpbuf[i], tmpbuf[i + lag]);
220 : }
221 0 : if (lag != 0)
222 0 : L_tmp = Mpy_32_32_lc3plus(L_tmp, tnsAcfWindow_lc3plus[lag - 1]);
223 :
224 0 : L_tmp = Mpy_32_16_lc3plus(L_tmp, facs);
225 0 : L_tmp = L_shl(L_tmp, facs_e);
226 :
227 0 : rxx[lag] = L_add(rxx[lag], L_tmp);
228 0 : move32();
229 : }
230 : }
231 :
232 : /* Levinson-Durbin */
233 0 : processLevinson_fx(A, rxx, maxOrder, RC, &epsP, LevinsonBuffer);
234 :
235 : /* Prediction Gain */
236 0 : shift = norm_l(epsP);
237 0 : inv = div_s(16383, extract_h(L_shl_pos(epsP, shift)));
238 0 : predictionGain = Mpy_32_32_lc3plus(rxx[0], Mpy_32_16_lc3plus(L_sub(MAX_32, Mpy_32_16_lc3plus(L_shl(epsP, shift), inv)), inv));
239 :
240 0 : IF (L_sub(predictionGain, L_shr_pos_pos(0x30000000, shift)) > 0 && near_nyquist_flag == 0)
241 : {
242 : /* If Prediction Gain is low */
243 0 : test();
244 0 : IF (enable_lpc_weighting != 0 && L_sub(predictionGain, L_shr_pos_pos(0x40000000, shift)) < 0)
245 : {
246 : /* LPC weighting */
247 0 : alpha = L_add(0x6CCCCCCD,
248 : Mpy_32_32_lc3plus(0x13333333, L_shl_pos(L_sub(L_shl_pos(predictionGain, shift), 0x30000000), 3)));
249 0 : L_tmp = alpha;
250 0 : FOR (i = 1; i < maxOrder; i++)
251 : {
252 0 : A[i] = Mpy_32_32_lc3plus(A[i], L_tmp);
253 0 : move32();
254 0 : L_tmp = Mpy_32_32_lc3plus(L_tmp, alpha);
255 : }
256 0 : A[maxOrder] = Mpy_32_32_lc3plus(A[maxOrder], L_tmp);
257 0 : move32();
258 :
259 : /* LPC -> RC */
260 0 : lpc2rc(A, RC, maxOrder);
261 : }
262 :
263 : /* Reflection Coefficients Quantization */
264 0 : Parcor2Index(RC, &indexes[MAXLAG * j], maxOrder);
265 :
266 : /* reduce filter order by truncating trailing zeros */
267 0 : i = sub(maxOrder, 1);
268 0 : WHILE ((i >= 0) && (indexes[MAXLAG * j + i] == INDEX_SHIFT))
269 : {
270 0 : i = sub(i, 1);
271 : }
272 0 : order[j] = add(i, 1);
273 :
274 : // Disable TNS if order is 0:
275 0 : IF (order[j] == 0) {
276 : // Jump to else statement
277 0 : goto tns_disabled;
278 : }
279 : /* Count bits */
280 0 : L_tmp = L_deposit_l(ac_tns_order_bits[enable_lpc_weighting][order[j] - 1]);
281 0 : FOR (i = 0; i < order[j]; i++)
282 : {
283 0 : L_tmp = L_add(L_tmp, L_deposit_l(ac_tns_coef_bits[i][indexes[MAXLAG * j + i]]));
284 : }
285 0 : *bits = add(*bits, add(2, extract_l(L_shr_pos(L_sub(L_tmp, 1), 11))));
286 0 : move16();
287 :
288 : /* Unquantize Reflection Coefficients */
289 0 : Index2Parcor(&indexes[MAXLAG * j], RC, order[j]);
290 :
291 : /* Stop frequency */
292 0 : stopfreq = xLen;
293 0 : move16();
294 0 : IF (sub(*numfilters, 2) == 0 && j == 0)
295 : {
296 0 : stopfreq = startfreq[1];
297 : }
298 :
299 : /* Filter */
300 0 : FOR (i = startfreq[j]; i < stopfreq; i++)
301 : {
302 0 : x[i] = FIRLattice(order[j], RC, state, x[i]);
303 0 : move32();
304 : }
305 : }
306 : ELSE
307 : {
308 0 : tns_disabled:
309 : /* TNS disabled */
310 0 : *bits = add(*bits, 1);
311 0 : order[j] = 0;
312 : }
313 : }
314 :
315 : Dyn_Mem_Deluxe_Out();
316 0 : }
317 :
318 : /*************************************************************************/
319 :
320 0 : static void Parcor2Index(const Word16 parCoeff[] /*Q15*/, Word16 index[], Word16 order)
321 : {
322 : Dyn_Mem_Deluxe_In(Counter i; Word16 iIndex; Word16 x;);
323 :
324 0 : FOR (i = 0; i < order; i++)
325 : {
326 0 : move16();
327 0 : move16();
328 0 : iIndex = 1;
329 0 : x = parCoeff[i];
330 :
331 0 : WHILE ((iIndex < TNS_COEF_RES) && (x > tnsQuantThr[iIndex - 1]))
332 : {
333 0 : iIndex = add(iIndex, 1);
334 : }
335 0 : index[i] = sub(iIndex, 1);
336 0 : move16();
337 : }
338 :
339 : Dyn_Mem_Deluxe_Out();
340 0 : }
341 :
342 0 : static void Index2Parcor(const Word16 index[], Word16 parCoeff[], Word16 order)
343 : {
344 : Counter i;
345 0 : FOR (i = 0; i < order; i++)
346 : {
347 0 : parCoeff[i] = tnsQuantPts[index[i]];
348 0 : move16();
349 : }
350 0 : }
351 :
352 0 : static Word32 FIRLattice(Word16 order, const Word16 *parCoeff /*Q15*/, Word32 *state, Word32 x /* Q0 */)
353 : {
354 : Dyn_Mem_Deluxe_In(Counter i; Word32 tmpSave, tmp;);
355 :
356 0 : tmpSave = L_add(x, 0);
357 :
358 0 : FOR (i = 0; i < order - 1; i++)
359 : {
360 0 : tmp = L_add(state[i], Mpy_32_16_lc3plus(x, parCoeff[i]));
361 0 : x = L_add(x, Mpy_32_16_lc3plus(state[i], parCoeff[i])); /* exponent: 31+0 */
362 0 : state[i] = tmpSave;
363 0 : move32();
364 0 : tmpSave = L_add(tmp, 0);
365 : }
366 :
367 : /* last stage: only need half operations */
368 0 : x = L_add(x, Mpy_32_16_lc3plus(state[order - 1], parCoeff[order - 1]));
369 0 : state[order - 1] = tmpSave;
370 0 : move32();
371 : Dyn_Mem_Deluxe_Out();
372 0 : return x;
373 : }
374 :
|