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 0 : void ProcessingIMDCT(
13 : Word32 y[], /* i: spectra data */
14 : Word16 * y_e, /* i: spectral data exponent */
15 : #ifdef ENABLE_HR_MODE
16 : const Word32 w[], /* i: window coefficients including normalization of sqrt(2/N) and scaled by 2^4 */
17 : Word32 mem[], /* i/o: overlap add memory */
18 : #else
19 : const Word16 w[], /* i: window coefficients including normalization of sqrt(2/N) and scaled by 2^4 */
20 : Word16 mem[], /* i/o: overlap add memory */
21 : #endif
22 : Word16 * mem_e, /* i/o: overlap add exponent */
23 : #ifdef ENABLE_HR_MODE
24 : Word32 x[], /* o: time signal out */
25 : #else
26 : Word16 x[], /* o: time signal out */
27 : #endif
28 : Word16 wLen, /* i: window length */
29 : Word16 N, /* i: block size */
30 : Word16 memLen, /* i: overlap add buffer size */
31 : Word16 frame_dms, /* i: frame size in ms */
32 : Word16 concealMethod, /* i: concealment method */
33 : Word16 bfi, /* i: bad frame indicator */
34 : Word16 prev_bfi, /* i: previous bad frame indicator */
35 : Word16 nbLostFramesInRow, /* i: number of consecutive lost frames */
36 : AplcSetup *plcAd, /* i: advanced plc struct */
37 : Word8 *scratchBuffer
38 : #ifdef ENABLE_HR_MODE
39 : , Word16 hrmode
40 : #endif
41 : )
42 : {
43 : Counter i;
44 : Word16 o, z, m, s;
45 : Word16 y_s, mem_s, max_bw;
46 : Word32 L_tmp;
47 : Word32 *workBuffer;
48 :
49 : #ifdef DYNMEM_COUNT
50 : struct _dynmem
51 : {
52 : Word16 o, z, m, s;
53 : Word16 y_s, mem_s, max_bw;
54 : Word32 L_tmp;
55 : Counter i;
56 : Word32 *workBuffer;
57 : Word16 mem_i_win;
58 : Word16 w_taper_win;
59 : };
60 : Dyn_Mem_In("ProcessingIMDCT", sizeof(struct _dynmem));
61 : #endif
62 :
63 :
64 0 : test(); test(); test();
65 0 : IF (sub(bfi, 1) != 0 || sub(concealMethod, LC3_CON_TEC_NS_STD) == 0 || sub(concealMethod, LC3_CON_TEC_NS_ADV) == 0 || sub(concealMethod, LC3_CON_TEC_FREQ_MUTING) == 0)
66 : {
67 0 : workBuffer = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = 4 * MAX_LEN bytes */
68 :
69 : /* Init (constant per sample rate) */
70 0 : z = 2 * N - wLen; /* number of leading zeros in window */
71 0 : m = N >> 1; /* half block size */
72 0 : o = m - z;
73 0 : max_bw = 0;
74 :
75 : #ifdef ENABLE_HR_MODE
76 0 : if (hrmode)
77 : {
78 0 : max_bw = N;
79 : }
80 : else
81 : #endif
82 : {
83 0 : SWITCH (frame_dms)
84 : {
85 0 : case 25:
86 0 : max_bw = MAX_BW >> 2; move16();
87 0 : BREAK;
88 0 : case 50:
89 0 : max_bw = MAX_BW >> 1; move16();
90 0 : BREAK;
91 0 : case 75:
92 0 : max_bw = (MAX_BW >> 2) * 3; move16();
93 0 : BREAK;
94 0 : case 100:
95 0 : max_bw = MAX_BW; move16();
96 0 : BREAK;
97 : }
98 0 : }
99 :
100 0 : if (N > max_bw)
101 0 : basop_memset(&y[max_bw], 0, (N - max_bw) * sizeof(*y));
102 :
103 : /* Start Processing */
104 0 : y_s = getScaleFactor32_0(y, N);
105 0 : IF (sub(y_s, 32) < 0)
106 : {
107 0 : FOR (i = 0; i < N; i++)
108 : {
109 0 : y[i] = L_shl(y[i], y_s);
110 : }
111 0 : *y_e = sub(*y_e, y_s);
112 : #ifdef ENABLE_HR_MODE
113 0 : dct_IV(y, y_e, N,
114 : hrmode,
115 : workBuffer);
116 : #else
117 : dct_IV(y, y_e, N, workBuffer);
118 : #endif
119 0 : y_s = getScaleFactor32_lc3plus(y, N);
120 0 : y_s = sub(y_s, 1);
121 0 : *y_e = sub(*y_e, y_s + 3); /* mdct window is scaled by pow(2,x) */
122 : /* N<=20 only happens for 2.5ms frames in NB */
123 0 : if (sub(N, 20) <= 0)
124 : {
125 0 : *y_e = add(*y_e, 2);
126 : }
127 0 : else if (sub(N, 120) <= 0)
128 : {
129 0 : *y_e = add(*y_e, 1);
130 : }
131 : }
132 : ELSE
133 : {
134 0 : *y_e = 0; move16();
135 : }
136 :
137 : #ifdef ENABLE_HR_MODE
138 0 : mem_s = getScaleFactor32_0(mem, memLen);
139 : #else
140 : mem_s = getScaleFactor16_0(mem, memLen);
141 : #endif
142 :
143 : #ifdef ENABLE_HR_MODE
144 0 : IF (sub(mem_s, 32) < 0)
145 : #else
146 : IF (sub(mem_s, 16) < 0)
147 : #endif
148 : {
149 0 : mem_s = sub(mem_s, 1);
150 0 : *mem_e = sub(*mem_e, mem_s);
151 : }
152 : ELSE
153 : {
154 0 : *mem_e = *y_e; move16();
155 : }
156 :
157 0 : s = sub(*mem_e, *y_e);
158 :
159 0 : IF (s > 0)
160 : {
161 0 : y_s = sub(y_s, s);
162 0 : *y_e = add(*y_e, s);
163 : }
164 : ELSE
165 : {
166 0 : mem_s = add(mem_s, s);
167 0 : *mem_e = sub(*mem_e, s);
168 : }
169 :
170 0 : mem_s = s_max(mem_s, -31);
171 0 : y_s = s_max(y_s, -31);
172 :
173 0 : if (sub(y_s, 32) >= 0)
174 : {
175 0 : y_s = 0; move16();
176 : }
177 : #ifdef ENABLE_HR_MODE
178 0 : if (sub(mem_s, 32) >= 0)
179 : {
180 0 : mem_s = 0; move16();
181 : }
182 : #else
183 : if (sub(mem_s, 16) >= 0)
184 : {
185 : mem_s = 0; move16();
186 : }
187 : #endif
188 :
189 : UNUSED(prev_bfi);
190 : UNUSED(nbLostFramesInRow);
191 : UNUSED(plcAd);
192 :
193 : { /* regular operation */
194 0 : FOR (i = 0; i < o; i++)
195 : {
196 : #ifdef ENABLE_HR_MODE
197 0 : L_tmp = L_sub(L_shl(mem[i], mem_s), Mpy_32_32_lc3plus(L_shl(y[m + i + z], y_s), w[4 * m - 1 - i - z]));
198 0 : x[i] = L_tmp;
199 0 : move32();
200 : #else
201 : L_tmp = L_sub(L_shl(L_deposit_h(mem[i]), mem_s), Mpy_32_16_lc3plus(L_shl(y[m + i + z], y_s), w[4 * m - 1 - i - z]));
202 : x[i] = round_fx(L_tmp);
203 : move16();
204 : #endif
205 : }
206 0 : FOR (i = 0; i < m; i++)
207 : {
208 : #ifdef ENABLE_HR_MODE
209 0 : L_tmp = L_add(L_shl(mem[i + o], mem_s), Mpy_32_32_lc3plus(L_shl(y[2 * m - 1 - i], y_s), w[3 * m - 1 - i]));
210 0 : x[i + o] = L_tmp;
211 0 : move32();
212 : #else
213 : L_tmp = L_add(L_shl(L_deposit_h(mem[i + o]), mem_s), Mpy_32_16_lc3plus(L_shl(y[2 * m - 1 - i], y_s), w[3 * m - 1 - i]));
214 : x[i + o] = round_fx(L_tmp);
215 : move16();
216 : #endif
217 : }
218 : }
219 :
220 0 : FOR (i = 0; i < m; i++)
221 : {
222 : #ifdef ENABLE_HR_MODE
223 0 : L_tmp = L_negate(Mpy_32_32_lc3plus(L_shl(y[i], y_s), w[m - 1 - i]));
224 0 : x[3 * m - z + i] = L_tmp;
225 0 : move32();
226 : #else
227 : L_tmp = L_negate(Mpy_32_16_lc3plus(L_shl(y[i], y_s), w[m - 1 - i]));
228 : x[3 * m - z + i] = round_fx(L_tmp);
229 : move16();
230 : #endif
231 : }
232 :
233 0 : FOR (i = 0; i < m; i++)
234 : {
235 : #ifdef ENABLE_HR_MODE
236 0 : L_tmp = L_negate(Mpy_32_32_lc3plus(L_shl(y[i], y_s), w[m + i]));
237 0 : x[3 * m - z - 1 - i] = L_tmp;
238 0 : move32();
239 : #else
240 : L_tmp = L_negate(Mpy_32_16_lc3plus(L_shl(y[i], y_s), w[m + i]));
241 : x[3 * m - z - 1 - i] = round_fx(L_tmp);
242 : move16();
243 : #endif
244 : }
245 :
246 : #ifdef ENABLE_HR_MODE
247 0 : basop_memmove(mem, &x[N], memLen * sizeof(Word32));
248 : #else
249 : basop_memmove(mem, &x[N], memLen * sizeof(Word16));
250 : #endif
251 :
252 0 : *mem_e = *y_e; move16();
253 : }
254 :
255 : #ifdef DYNMEM_COUNT
256 : Dyn_Mem_Out();
257 : #endif
258 0 : }
259 : /* End Processing */
260 :
261 0 : void Processing_ITDA_WIN_OLA(
262 : Word32 L_x_tda[], /* i: X_TDA buffer data = "y" DCT-IV output */
263 : Word16 * y_e, /* i/o: x_tda input exponent "y_e" , x output exponent */
264 : #ifdef ENABLE_HR_MODE
265 : const Word32 w[], /* i: window coefficients including normalization of sqrt(2/N) and scaled by 2^4 */
266 : #else
267 : const Word16 w[], /* i: window coefficients including normalization of sqrt(2/N) and scaled by 2^4 */
268 : #endif
269 : Word16 mem[], /* i/o: overlap add memory */
270 : Word16 * mem_e, /* i/o: overlap add exponent */
271 : Word16 x[], /* o: time signal out */
272 : Word16 wLen, /* i: window length */
273 : Word16 N, /* i: block size */
274 : Word16 memLen /* i: overlap add buffer size */
275 : )
276 : {
277 : /* Declarations */
278 : Word16 i, o, z, m, s;
279 : Word16 y_s, mem_s;
280 : Word32 L_tmp;
281 : Word32 *L_y;
282 : Word16 fs_idx, tmp_w, w_factor;
283 0 : Word16 factorITDA[5]= { 25905 , 18318 , 22435 , 25905 , 31727};
284 :
285 : #ifdef DYNMEM_COUNT
286 : Dyn_Mem_In("Processing_ITDA_WIN_OLA", sizeof(struct {
287 : Word16 i, o, z, m, s;
288 : Word16 y_s, mem_s;
289 : Word32 L_tmp;
290 : Word32 *L_y;
291 : }));
292 : #endif
293 :
294 :
295 : /* Init (constants per sample rate) */
296 0 : z = 2 * N - wLen; /* number of leading zeros in window */
297 0 : m = N >> 1; /* half block size */
298 0 : o = m - z;
299 :
300 :
301 0 : L_y = L_x_tda; /* use same variables naming as in IMDCT for DCT-IV output signal y */
302 :
303 0 : y_s = getScaleFactor32_lc3plus(L_y, N);
304 :
305 0 : y_s = sub(y_s, 1); /* add 1 bit margin , y_s is now initial tda upscaling factor */
306 :
307 :
308 0 : *y_e = sub(add(*y_e,1),y_s); /* handle W scale down by 2^(3) , as mdct synthesis window was upscaled by pow(2,x) x=2 for NB otherwise 3 */
309 :
310 :
311 :
312 0 : mem_s = getScaleFactor16_0(mem, memLen);
313 :
314 0 : IF (sub(mem_s, 16) < 0)
315 : {
316 0 : mem_s = sub(mem_s, 1); /* one bit margin */
317 0 : *mem_e = sub(*mem_e, mem_s); /*adjusted mem exponent due to new scale */
318 : }
319 : ELSE
320 : {
321 0 : *mem_e = 0; move16();
322 : }
323 :
324 0 : s = sub(*mem_e, *y_e); /* */
325 :
326 0 : IF (s > 0)
327 : {
328 0 : y_s = sub(y_s, s); /* new , reduced upshift of TDA in window application loop */
329 0 : *y_e = add(*y_e, s); /* resulting new exp y_e for output signal */
330 : }
331 : ELSE
332 : {
333 0 : mem_s = add(mem_s, s); /* s negative or zero, new , decreased upshift of OLAmem in loop */
334 0 : *mem_e = sub(*mem_e, s); /* resulting new exp mem_e for OLA_mem output signal */
335 : }
336 :
337 0 : fs_idx = mult(N,(Word16)(32768.0/99.0)); /* truncation needed , i.e no rounding can be applied here */
338 0 : w_factor = factorITDA[fs_idx]; move16();
339 0 : y_s = s_max(s_min(y_s, 31), -31);
340 :
341 0 : FOR (i = 0; i < o; i++)
342 : {
343 0 : tmp_w = mult_r(extractW16(w[4 * m - 1 - i - z]), w_factor);
344 0 : L_tmp = L_sub(L_shl_sat(L_deposit_h(mem[i]), mem_s), Mpy_32_16_lc3plus(L_shl(L_y[m + i + z], y_s), tmp_w));
345 0 : x[i] = round_fx_sat(L_tmp);
346 0 : move16();
347 : }
348 :
349 0 : FOR (i = 0; i < m; i++)
350 : {
351 0 : tmp_w = mult_r(extractW16(w[3 * m - 1 - i]), w_factor);
352 0 : L_tmp = L_add(L_shl_sat(L_deposit_h(mem[i + o]), mem_s), Mpy_32_16_lc3plus(L_shl(L_y[2 * m - 1 - i], y_s), tmp_w));
353 0 : x[i + o] = round_fx_sat(L_tmp);
354 0 : move16();
355 : }
356 :
357 0 : FOR (i = 0; i < m; i++)
358 : {
359 0 : tmp_w = mult_r(extractW16(w[m - 1 - i]), w_factor);
360 0 : L_tmp = L_negate(Mpy_32_16_lc3plus(L_shl(L_y[i], y_s), tmp_w));
361 0 : x[3 * m - z + i] = round_fx(L_tmp); move16();
362 : }
363 :
364 0 : FOR (i = 0; i < m; i++)
365 : {
366 0 : tmp_w = mult_r(extractW16(w[m + i]), w_factor);
367 0 : L_tmp = L_negate(Mpy_32_16_lc3plus(L_shl(L_y[i], y_s), tmp_w ));
368 0 : x[3 * m - z - 1 - i] = round_fx(L_tmp); move16();
369 : }
370 :
371 0 : FOR (i = 0; i < memLen; i++)
372 : {
373 0 : mem[i] = x[N + i]; move16();
374 : }
375 0 : *mem_e = *y_e; move16(); /* set OLA mem exp to x_Fx exponent*/
376 :
377 :
378 :
379 : #ifdef DYNMEM_COUNT
380 : Dyn_Mem_Out();
381 : #endif
382 0 : }
383 :
|