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 "defines.h"
11 : #include "functions.h"
12 :
13 0 : void processPLCDampingScrambling_main_fx(Word16 bfi, Word16 concealMethod, Word16 ns_nbLostFramesInRow, Word16 *cum_fflcAtten,
14 : Word16 pc_nbLostFramesInRow, Word16 *ns_seed, Word16 *pc_seed, Word16 pitch_present_bfi1,
15 : Word16 pitch_present_bfi2, Word32 spec[], Word16 *q_fx_exp, Word16 *q_old_d_fx,
16 : Word16 *q_old_fx_exp, Word16 L_spec, Word16 stabFac, Word16 frame_dms,
17 : Word16 *cum_fading_slow, Word16 *cum_fading_fast, Word16 spec_inv_idx
18 : , UWord8 plc_fadeout_type
19 : )
20 : {
21 : Dyn_Mem_Deluxe_In(
22 : Word16 processDampScramb;
23 : );
24 :
25 0 : IF ( bfi != 0 )
26 : {
27 0 : processDampScramb = 0; move16();
28 0 : test();
29 0 : IF (sub(concealMethod, LC3_CON_TEC_NS_ADV) == 0 || sub(bfi, 2) == 0)
30 : {
31 0 : processDampScramb = 1; move16();
32 : }
33 :
34 0 : IF (sub(ns_nbLostFramesInRow, 1) == 0)
35 : {
36 0 : *cum_fading_slow = 32767; move16();
37 0 : *cum_fading_fast = 32767; move16();
38 0 : *cum_fflcAtten = 32767; move16();
39 : }
40 :
41 0 : IF (sub(bfi, 1) == 0)
42 : {
43 0 : processPLCDampingScrambling_fx(spec, L_spec, ns_nbLostFramesInRow, stabFac,
44 : processDampScramb, cum_fflcAtten,
45 : pitch_present_bfi1, frame_dms, cum_fading_slow,
46 : cum_fading_fast, ns_seed, 0
47 : , plc_fadeout_type
48 : );
49 : }
50 : ELSE /* bfi == 2 */
51 : {
52 0 : processPLCDampingScrambling_fx(spec, L_spec, pc_nbLostFramesInRow, stabFac,
53 : processDampScramb, cum_fflcAtten,
54 : pitch_present_bfi2, frame_dms, cum_fading_slow,
55 : cum_fading_fast, pc_seed, spec_inv_idx
56 : , plc_fadeout_type
57 : );
58 :
59 0 : processPLCupdateSpec_fx(q_old_d_fx, q_old_fx_exp, spec, q_fx_exp, L_spec);
60 : }
61 : }
62 : Dyn_Mem_Deluxe_Out();
63 0 : }
64 :
65 0 : void processPLCDampingScrambling_fx(Word32 spec[], Word16 L_spec, Word16 nbLostFramesInRow, Word16 stabFac, Word16 processDampScramb,
66 : Word16 *cum_fflcAtten, Word16 pitch_present, Word16 frame_dms, Word16 *cum_fading_slow,
67 : Word16 *cum_fading_fast, Word16 *seed, Word16 spec_inv_idx
68 : , UWord8 plc_fadeout_type
69 : )
70 : {
71 : Counter i;
72 : Word16 lossDuration_dms, slow, fast, tmp16;
73 : Word16 plc_start_inFrames, plc_end_inFrames, plc_duration_inFrames, linFuncStartStop;
74 : Word16 randThreshold, ad_threshFac, energThreshold, s, s2, s3, mean_energy16;
75 : Word32 frame_energy, mean_nrg, fac;
76 : Word16 fflcAtten, cum_fading_slow_local, cum_fading_fast_local;
77 :
78 : #ifdef DYNMEM_COUNT
79 : Dyn_Mem_In("processPLCDampingScrambling_fx", sizeof(struct {
80 : Counter i;
81 : Word16 lossDuration_dms, slow, fast, tmp16;
82 : Word16 plc_start_inFrames, plc_end_inFrames, plc_duration_inFrames, linFuncStartStop;
83 : Word16 randThreshold, ad_threshFac, energThreshold, s, s2, s3, mean_energy16;
84 : Word32 frame_energy, mean_nrg, fac;
85 : Word16 fflcAtten, cum_fading_slow_local, cum_fading_fast_local;
86 : }));
87 : #endif
88 :
89 : /** preparation */
90 :
91 : /* get damping factors */
92 0 : tmp16 = mult(6554 /*0.2*/, stabFac);
93 0 : slow = add(26214 /*0.8*/, tmp16);
94 0 : fast = add( 9830 /*0.3*/, tmp16);
95 :
96 :
97 0 : SWITCH (frame_dms)
98 : {
99 0 : case 25:
100 0 : IF (sub(slow, 32767) < 0)
101 : {
102 0 : tmp16 = 0;
103 0 : slow = Sqrt16_lc3plus(slow, &tmp16); move16();
104 0 : slow = shl(slow, tmp16);
105 : }
106 0 : IF (sub(slow, 32767) < 0)
107 : {
108 0 : tmp16 = 0;
109 0 : slow = Sqrt16_lc3plus(slow, &tmp16); move16();
110 0 : slow = shl(slow, tmp16);
111 : }
112 0 : IF (sub(fast, 32767) < 0)
113 : {
114 0 : tmp16 = 0;
115 0 : fast = Sqrt16_lc3plus(fast, &tmp16); move16();
116 0 : fast = shl(fast, tmp16);
117 : }
118 0 : IF (sub(fast, 32767) < 0)
119 : {
120 0 : tmp16 = 0;
121 0 : fast = Sqrt16_lc3plus(fast, &tmp16); move16();
122 0 : fast = shl(fast, tmp16);
123 : }
124 0 : BREAK;
125 0 : case 50:
126 0 : IF (sub(slow, 32767) < 0)
127 : {
128 0 : tmp16 = 0;
129 0 : slow = Sqrt16_lc3plus(slow, &tmp16); move16();
130 0 : slow = shl(slow, tmp16);
131 : }
132 0 : IF (sub(fast, 32767) < 0)
133 : {
134 0 : tmp16 = 0;
135 0 : fast = Sqrt16_lc3plus(fast, &tmp16); move16();
136 0 : fast = shl(fast, tmp16);
137 : }
138 0 : BREAK;
139 0 : case 75:
140 0 : IF (sub(slow, 32767) < 0)
141 : {
142 0 : slow = mult(slow, mult(slow, slow));
143 : }
144 0 : IF (sub(slow, 32767) < 0)
145 : {
146 0 : tmp16 = 0;
147 0 : slow = Sqrt16_lc3plus(slow, &tmp16); move16();
148 0 : slow = shl(slow, tmp16);
149 : }
150 0 : IF (sub(slow, 32767) < 0)
151 : {
152 0 : tmp16 = 0;
153 0 : slow = Sqrt16_lc3plus(slow, &tmp16); move16();
154 0 : slow = shl(slow, tmp16);
155 : }
156 0 : IF (sub(fast, 32767) < 0)
157 : {
158 0 : fast = mult(fast, mult(fast, fast));
159 : }
160 0 : IF (sub(fast, 32767) < 0)
161 : {
162 0 : tmp16 = 0;
163 0 : fast = Sqrt16_lc3plus(fast, &tmp16); move16();
164 0 : fast = shl(fast, tmp16);
165 : }
166 0 : IF (sub(fast, 32767) < 0)
167 : {
168 0 : tmp16 = 0;
169 0 : fast = Sqrt16_lc3plus(fast, &tmp16); move16();
170 0 : fast = shl(fast, tmp16);
171 : }
172 0 : BREAK;
173 : }
174 :
175 0 : if (plc_fadeout_type == 0)
176 : {
177 0 : *cum_fading_slow = mult_r(*cum_fading_slow, slow);
178 0 : *cum_fading_fast = mult_r(*cum_fading_fast, fast);
179 : }
180 :
181 0 : IF ( sub(processDampScramb, 1) == 0 )
182 : {
183 0 : if (plc_fadeout_type != 0)
184 : {
185 0 : Word16 lost_frame_thr1 = 4;
186 0 : Word16 lost_frame_thr2 = 8;
187 :
188 0 : SWITCH (frame_dms)
189 : {
190 0 : case 25:
191 0 : lost_frame_thr1 = 16;
192 0 : lost_frame_thr2 = 32;
193 0 : BREAK;
194 0 : case 50:
195 0 : lost_frame_thr1 = 8;
196 0 : lost_frame_thr2 = 16;
197 0 : BREAK;
198 0 : case 75:
199 0 : lost_frame_thr1 = 6;
200 0 : lost_frame_thr2 = 11;
201 : }
202 0 : IF (sub(nbLostFramesInRow, lost_frame_thr1) < 0)
203 : {
204 0 : cum_fading_slow_local = 32767; move16();
205 : }
206 0 : ELSE IF (sub(nbLostFramesInRow, lost_frame_thr2) < 0)
207 : {
208 0 : cum_fading_slow_local = 29491; move16();
209 : }
210 : ELSE
211 : {
212 0 : cum_fading_slow_local = 27852; move16();
213 : }
214 :
215 0 : *cum_fading_slow = mult_r(*cum_fading_slow, cum_fading_slow_local); move16();
216 0 : cum_fading_slow_local = *cum_fading_slow; move16();
217 : } else {
218 : /** rapid fading for FFLC */
219 0 : fflcAtten = 32767; move16();
220 0 : cum_fading_slow_local = *cum_fading_slow; move16();
221 0 : cum_fading_fast_local = *cum_fading_fast; move16();
222 :
223 0 : IF (spec_inv_idx == 0)
224 : {
225 0 : lossDuration_dms = DEPR_i_mult(nbLostFramesInRow, frame_dms);
226 0 : IF (sub(lossDuration_dms, PLC_FADEOUT_IN_MS*10) > 0)
227 : {
228 0 : *cum_fflcAtten = 0; move16();
229 0 : fflcAtten = 0; move16();
230 : }
231 0 : ELSE IF (sub(lossDuration_dms, 200) > 0)
232 : {
233 0 : SWITCH (frame_dms)
234 : {
235 0 : case 25: fflcAtten = PLC34_ATTEN_FAC_025_FX; BREAK;
236 0 : case 50: fflcAtten = PLC34_ATTEN_FAC_050_FX; BREAK;
237 0 : case 75: fflcAtten = PLC34_ATTEN_FAC_075_FX; BREAK;
238 0 : case 100: fflcAtten = PLC34_ATTEN_FAC_100_FX; BREAK;
239 : }
240 0 : }
241 0 : IF ( sub(fflcAtten, 32767) < 0 )
242 : {
243 0 : *cum_fflcAtten = mult_r(*cum_fflcAtten, fflcAtten);
244 0 : cum_fading_slow_local = mult_r(*cum_fading_slow, *cum_fflcAtten);
245 0 : cum_fading_fast_local = mult_r(*cum_fading_fast, *cum_fflcAtten);
246 : }
247 : }
248 :
249 : /** prepare fade-out function */
250 : /* being 1 up to plc_start_inFrames, being 0 starting with
251 : plc_end_inFrames; decreasing linearly in between */
252 0 : SWITCH (frame_dms)
253 : {
254 0 : case 25:
255 0 : plc_start_inFrames = (10*PLC4_TRANSIT_START_IN_MS) / 25; move16();
256 0 : plc_end_inFrames = (10*PLC4_TRANSIT_END_IN_MS) / 25; move16();
257 0 : BREAK;
258 0 : case 50:
259 0 : plc_start_inFrames = (10*PLC4_TRANSIT_START_IN_MS) / 50; move16();
260 0 : plc_end_inFrames = (10*PLC4_TRANSIT_END_IN_MS) / 50; move16();
261 0 : BREAK;
262 0 : case 75:
263 0 : plc_start_inFrames = (10*PLC4_TRANSIT_START_IN_MS) / 75; move16();
264 0 : plc_end_inFrames = (10*PLC4_TRANSIT_END_IN_MS) / 75; move16();
265 0 : BREAK;
266 0 : default:
267 0 : plc_start_inFrames = (10*PLC4_TRANSIT_START_IN_MS) / 100; move16();
268 0 : plc_end_inFrames = (10*PLC4_TRANSIT_END_IN_MS) / 100; move16();
269 : }
270 :
271 0 : if (pitch_present == 0)
272 : {
273 0 : plc_start_inFrames = 1; move16();
274 : }
275 0 : plc_duration_inFrames = sub(plc_end_inFrames, plc_start_inFrames);
276 :
277 0 : IF (sub(nbLostFramesInRow, plc_start_inFrames) <= 0)
278 : {
279 0 : linFuncStartStop = 32767; move16();
280 : }
281 0 : ELSE IF (sub(nbLostFramesInRow, plc_end_inFrames) >= 0)
282 : {
283 0 : linFuncStartStop = 0; move16();
284 : }
285 : ELSE
286 : {
287 : /*
288 : x = xLostFramesInRow;
289 : m = -1 / plc_duration_inFrames;
290 : b = -plc_end_inFrames; % shift on x axis
291 : linFuncStartStop = m * (x + b);
292 : */
293 0 : linFuncStartStop = div_s(sub(plc_end_inFrames, nbLostFramesInRow), plc_duration_inFrames);
294 : }
295 :
296 : /** sign scrambling */
297 0 : randThreshold = mult(-32768, linFuncStartStop);
298 : }
299 :
300 0 : tmp16 = *seed; move16();
301 0 : FOR (i = spec_inv_idx; i < L_spec; i++)
302 : {
303 0 : tmp16 = extract_l(L_mac0(16831, tmp16, 12821));
304 :
305 0 : IF (tmp16 < 0)
306 : {
307 0 : test();
308 0 : if (plc_fadeout_type != 0 || pitch_present == 0 || sub(tmp16, randThreshold) < 0 )
309 : {
310 0 : spec[i] = L_negate(spec[i]);
311 : }
312 : }
313 :
314 : }
315 0 : *seed = tmp16; move16();
316 :
317 0 : if (plc_fadeout_type == 0)
318 : {
319 : /** adaptive damping */
320 0 : tmp16 = mult(18022 /* 10 - 1.2 */, linFuncStartStop);
321 0 : ad_threshFac = add(shr(tmp16, 1), 1228 /* 1.2 >> 1 */); /* exp = 5 */
322 :
323 0 : s = getScaleFactor32_lc3plus(&spec[spec_inv_idx], sub(L_spec, spec_inv_idx));
324 0 : frame_energy = 0; move32();
325 0 : FOR (i = spec_inv_idx; i < L_spec; i++)
326 : {
327 0 : tmp16 = extract_h(L_shl_sat(spec[i], sub(s, 4)));
328 0 : frame_energy = L_mac0(frame_energy, tmp16, tmp16); /* exp = -(2*(s-16) - 8) */
329 : }
330 0 : mean_energy16 = BASOP_Util_Divide3216_Scale_lc3plus(frame_energy, sub(L_spec, spec_inv_idx), &s2); /* exp = -(2*(s-16) - 8) + 16 - (15-s2) */
331 :
332 0 : energThreshold = mult(ad_threshFac, mean_energy16); /* exp = -(2*(s-16) - 8) + 16 - (15-s2) + 5 */
333 :
334 0 : s3 = add(sub(29, shl(sub(s, 16), 1)), s2);
335 0 : IF (sub(energThreshold, 32767) < 0)
336 : {
337 0 : energThreshold = Sqrt16_lc3plus(energThreshold, &s3);
338 : }
339 0 : s3 = sub(s3, 15);
340 :
341 0 : mean_nrg = L_shl_sat(L_deposit_l(energThreshold), s3); /* exp = 0 */
342 0 : fac = mult(sub(cum_fading_slow_local, cum_fading_fast_local), energThreshold);
343 0 : fac = L_shl_sat(L_deposit_l(fac), s3); /* exp = 0 */
344 : }
345 :
346 0 : FOR (i = spec_inv_idx; i < L_spec; i++)
347 : {
348 0 : if ( ( plc_fadeout_type != 0 ) || (L_sub(L_abs(spec[i]), mean_nrg) < 0) )
349 : {
350 0 : spec[i] = Mpy_32_16_lc3plus(spec[i], cum_fading_slow_local);
351 : }
352 : else
353 : {
354 0 : if (spec[i] > 0)
355 : {
356 0 : spec[i] = L_add_sat(Mpy_32_16_lc3plus(spec[i], cum_fading_fast_local), fac);
357 : }
358 0 : else if (spec[i] == 0)
359 : {
360 0 : spec[i] = Mpy_32_16_lc3plus(spec[i], cum_fading_fast_local);
361 : }
362 : else
363 : {
364 0 : spec[i] = L_sub_sat(Mpy_32_16_lc3plus(spec[i], cum_fading_fast_local), fac);
365 : }
366 : }
367 : }
368 : }
369 :
370 : #ifdef DYNMEM_COUNT
371 : Dyn_Mem_Out();
372 : #endif
373 0 : }
374 :
375 :
|