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 "options.h"
11 : #include "wmc_auto.h"
12 : #include "functions.h"
13 :
14 0 : void process_ltpf_decoder_fl(LC3_FLOAT* x, LC3_INT xLen, LC3_FLOAT* y, LC3_INT fs, LC3_FLOAT* mem_old_x, LC3_FLOAT* mem_old_y,
15 : LC3_INT* mem_pitch_int, LC3_INT* mem_pitch_fr, LC3_FLOAT* mem_gain, LC3_INT* mem_beta_idx, LC3_INT bfi,
16 : LC3_INT* param, LC3_INT* mem_param, LC3_INT conf_beta_idx, LC3_FLOAT conf_beta, LC3_INT concealMethod,
17 : LC3_FLOAT damping
18 : , LC3_INT *mem_ltpf_active
19 : , LC3_FLOAT *rel_pitch_change, LC3_INT hrmode, LC3_INT frame_dms
20 : )
21 : {
22 : LC3_INT i, j, n, N, L_past_x, N4, N34,
23 0 : pitch_int, pitch_fr, p1, p2, L_past_y, inter_len, tilt_len = 0,
24 : tilt_len_r, inter_len_r, old_x_len, old_y_len;
25 :
26 : LC3_FLOAT conf_alpha, gain, a1[12], a2[12], b1[11], b2[11],
27 : buf_x[4 * MAX_LEN], buf_y[4 * MAX_LEN], buf_z[4 * MAX_LEN], pitch, sum1, sum2;
28 : LC3_FLOAT *p_x, *p_y, *p_y2, *p_x_init, *p_y_init, *p_a1, *p_b1, *p_a2, *p_b2, fade_fac, current_fade_fac_up, current_fade_fac_down;
29 : LC3_FLOAT pitch_fl_c_old, pitch_delta;
30 : const LC3_FLOAT *inter_filter[4], *tilt_filter[4];
31 :
32 : #ifdef WMOPS
33 : push_wmops("process_ltpf_decoder_fl");
34 : #endif
35 0 : pitch_fl_c_old = (LC3_FLOAT) *mem_pitch_int + (LC3_FLOAT)*mem_pitch_fr / 4.0;
36 0 : conf_alpha = 0.85;
37 :
38 0 : if (bfi != 1) {
39 : /* Decode pitch */
40 0 : if (param[0] == 1) {
41 0 : if (param[2] < (RES4_PITCH_12K8 - MIN_PITCH_12K8) * 4) {
42 0 : pitch_int = MIN_PITCH_12K8 + floor(param[2] / 4);
43 0 : pitch_fr = param[2] - ((pitch_int - MIN_PITCH_12K8) * 4);
44 0 : } else if (param[2] < ((RES4_PITCH_12K8 - MIN_PITCH_12K8) * 4) + ((RES2_PITCH_12K8 - RES4_PITCH_12K8) * 2)) {
45 0 : param[2] = param[2] - ((RES4_PITCH_12K8 - MIN_PITCH_12K8) * 4);
46 0 : pitch_int = RES4_PITCH_12K8 + floor(param[2] / 2);
47 0 : pitch_fr = param[2] - ((pitch_int - RES4_PITCH_12K8) * 2);
48 0 : pitch_fr = pitch_fr * 2;
49 : } else {
50 0 : pitch_int =
51 0 : param[2] + (RES2_PITCH_12K8 - ((RES4_PITCH_12K8 - MIN_PITCH_12K8) * 4) - ((RES2_PITCH_12K8 - RES4_PITCH_12K8) * 2));
52 0 : pitch_fr = 0;
53 : }
54 :
55 0 : pitch = ((LC3_FLOAT)pitch_int + (LC3_FLOAT)pitch_fr / 4.0) * (LC3_FLOAT)fs / 12800.0;
56 0 : pitch = round(pitch * 4.0) / 4.0;
57 0 : pitch_int = floor(pitch);
58 0 : pitch_fr = (LC3_INT)((pitch - (LC3_FLOAT)pitch_int) * 4.0);
59 : } else {
60 0 : pitch_int = 0;
61 0 : pitch_fr = 0;
62 : }
63 :
64 : /* Decode gain */
65 0 : if (conf_beta_idx < 0) {
66 0 : param[1] = 0;
67 : }
68 :
69 0 : if (param[1] == 1) {
70 0 : gain = conf_beta;
71 : } else {
72 0 : gain = 0;
73 : }
74 : }
75 0 : else if (concealMethod > 0) {
76 0 : if (conf_beta_idx < 0) {
77 0 : if (mem_param[1] && *mem_beta_idx >= 0)
78 : {
79 0 : conf_beta_idx = *mem_beta_idx;
80 : }
81 : }
82 :
83 0 : memmove(param, mem_param, sizeof(LC3_INT32) * 3);
84 0 : if (concealMethod == 2)
85 : {
86 : /* cause the ltpf to "fade_out" and only filter during initial 2.5 ms and then its buffer during 7.5 ms */
87 0 : assert(bfi == 1);
88 0 : param[1] = 0; /* ltpf_active = 0 */
89 : }
90 :
91 0 : pitch_int = *mem_pitch_int;
92 0 : pitch_fr = *mem_pitch_fr;
93 0 : gain = (LC3_FLOAT) *mem_gain * damping;
94 : }
95 :
96 0 : if ((conf_beta <= 0) && (*mem_ltpf_active == 0))
97 : {
98 0 : if (fs == 8000 || fs == 16000) {
99 0 : tilt_len = 4 - 2;
100 : }
101 0 : else if (fs == 24000) {
102 0 : tilt_len = 6 - 2;
103 : }
104 0 : else if (fs == 32000) {
105 0 : tilt_len = 8 - 2;
106 : }
107 0 : else if (fs == 44100 || fs == 48000) {
108 0 : tilt_len = 12 - 2;
109 : }
110 :
111 0 : N = xLen;
112 0 : old_x_len = tilt_len;
113 0 : inter_len = MAX(fs, 16000) / 8000;
114 0 : old_y_len = ceilf((LC3_FLOAT)228.0 * fs / 12800.0) + inter_len; /* 228.0 needed to make use of ceil */
115 :
116 0 : move_float(mem_old_y, &mem_old_y[N], (old_y_len - N));
117 0 : move_float(&mem_old_y[old_y_len - N], x, N);
118 0 : move_float(mem_old_x, &x[N - old_x_len], old_x_len);
119 :
120 0 : *mem_ltpf_active = 0;
121 : }
122 : else
123 : {
124 0 : inter_len_r = 0; tilt_len_r = 0;
125 0 : if (fs == 8000 || fs == 16000) {
126 0 : inter_filter[0] = conf_inter_filter_16[0];
127 0 : inter_filter[1] = conf_inter_filter_16[1];
128 0 : inter_filter[2] = conf_inter_filter_16[2];
129 0 : inter_filter[3] = conf_inter_filter_16[3];
130 0 : inter_len_r = 4;
131 :
132 0 : tilt_filter[0] = conf_tilt_filter_16[0];
133 0 : tilt_filter[1] = conf_tilt_filter_16[1];
134 0 : tilt_filter[2] = conf_tilt_filter_16[2];
135 0 : tilt_filter[3] = conf_tilt_filter_16[3];
136 0 : tilt_len = 4 - 2;
137 0 : tilt_len_r = 3;
138 0 : } else if (fs == 24000) {
139 0 : inter_filter[0] = conf_inter_filter_24[0];
140 0 : inter_filter[1] = conf_inter_filter_24[1];
141 0 : inter_filter[2] = conf_inter_filter_24[2];
142 0 : inter_filter[3] = conf_inter_filter_24[3];
143 0 : inter_len_r = 6;
144 :
145 0 : tilt_filter[0] = conf_tilt_filter_24[0];
146 0 : tilt_filter[1] = conf_tilt_filter_24[1];
147 0 : tilt_filter[2] = conf_tilt_filter_24[2];
148 0 : tilt_filter[3] = conf_tilt_filter_24[3];
149 0 : tilt_len = 6 - 2;
150 0 : tilt_len_r = 5;
151 0 : } else if (fs == 32000) {
152 0 : inter_filter[0] = conf_inter_filter_32[0];
153 0 : inter_filter[1] = conf_inter_filter_32[1];
154 0 : inter_filter[2] = conf_inter_filter_32[2];
155 0 : inter_filter[3] = conf_inter_filter_32[3];
156 0 : inter_len_r = 8;
157 :
158 0 : tilt_filter[0] = conf_tilt_filter_32[0];
159 0 : tilt_filter[1] = conf_tilt_filter_32[1];
160 0 : tilt_filter[2] = conf_tilt_filter_32[2];
161 0 : tilt_filter[3] = conf_tilt_filter_32[3];
162 0 : tilt_len = 8 - 2;
163 0 : tilt_len_r = 7;
164 0 : } else if (fs == 44100 || fs == 48000) {
165 0 : inter_filter[0] = conf_inter_filter_48[0];
166 0 : inter_filter[1] = conf_inter_filter_48[1];
167 0 : inter_filter[2] = conf_inter_filter_48[2];
168 0 : inter_filter[3] = conf_inter_filter_48[3];
169 0 : inter_len_r = 12;
170 :
171 0 : tilt_filter[0] = conf_tilt_filter_48[0];
172 0 : tilt_filter[1] = conf_tilt_filter_48[1];
173 0 : tilt_filter[2] = conf_tilt_filter_48[2];
174 0 : tilt_filter[3] = conf_tilt_filter_48[3];
175 0 : tilt_len = 12 - 2;
176 0 : tilt_len_r = 11;
177 : }
178 :
179 0 : inter_len = MAX(fs, 16000) / 8000;
180 :
181 : /* Init buffers */
182 0 : N = xLen;
183 0 : old_x_len = tilt_len;
184 0 : old_y_len = ceilf(228.0 * fs / 12800.0) + inter_len;
185 0 : L_past_x = old_x_len;
186 0 : move_float(buf_x, mem_old_x, old_x_len);
187 0 : move_float(&buf_x[old_x_len], x, xLen);
188 0 : L_past_y = old_y_len;
189 0 : move_float(buf_y, mem_old_y, old_y_len);
190 0 : zero_float(&buf_y[old_y_len], xLen);
191 :
192 0 : N4 = fs * 0.0025;
193 0 : N34 = N - N4;
194 :
195 : /* Init filter parameters */
196 0 : if (mem_param[1] == 1) {
197 0 : for (i = 0; i < inter_len_r; i++) {
198 0 : a1[i] = *mem_gain * inter_filter[*mem_pitch_fr][i];
199 : }
200 :
201 0 : for (i = 0; i < tilt_len_r; i++) {
202 0 : b1[i] = conf_alpha * (*mem_gain) * tilt_filter[*mem_beta_idx][i];
203 : }
204 :
205 0 : p1 = *mem_pitch_int;
206 : }
207 :
208 0 : if (param[1] == 1) {
209 0 : for (i = 0; i < tilt_len_r; i++) {
210 0 : b2[i] = conf_alpha * gain * tilt_filter[conf_beta_idx][i];
211 : }
212 :
213 0 : for (i = 0; i < inter_len_r; i++) {
214 0 : a2[i] = gain * inter_filter[pitch_fr][i];
215 : }
216 :
217 0 : p2 = pitch_int;
218 : }
219 :
220 : /* First quarter of the current frame: cross-fading */
221 0 : fade_fac = 1. / (LC3_FLOAT) N4;
222 0 : current_fade_fac_up = 0.f;
223 0 : current_fade_fac_down = 1.f;
224 : (void) p_x; (void) p_y; (void) p_a1; (void) p_b1;
225 :
226 0 : if (mem_param[1] == 0 && param[1] == 0) {
227 0 : memmove(&buf_y[L_past_y], &buf_x[L_past_x], sizeof(LC3_FLOAT) * N4);
228 :
229 0 : } else if (mem_param[1] == 1 && param[1] == 0) {
230 0 : for (n = 0; n < N4; n++) {
231 0 : sum1 = 0;
232 0 : sum2 = 0;
233 0 : j = 0;
234 0 : for (i = L_past_x + n; i >= L_past_x + n - tilt_len; i--) {
235 0 : sum1 += b1[j] * buf_x[i];
236 0 : j++;
237 : }
238 :
239 0 : j = 0;
240 0 : for (i = L_past_y + n - p1 + inter_len - 1; i >= L_past_y + n - p1 - inter_len; i--) {
241 0 : sum2 += a1[j] * buf_y[i];
242 0 : j++;
243 : }
244 :
245 0 : buf_y[L_past_y + n] = buf_x[L_past_x + n] - current_fade_fac_down * sum1 +
246 0 : current_fade_fac_down * sum2;
247 0 : current_fade_fac_down -= fade_fac;
248 : }
249 :
250 0 : } else if (mem_param[1] == 0 && param[1] == 1) {
251 0 : for (n = 0; n < N4; n++) {
252 0 : sum1 = 0;
253 0 : sum2 = 0;
254 0 : j = 0;
255 0 : for (i = L_past_x + n; i >= L_past_x + n - tilt_len; i--) {
256 0 : sum1 += b2[j] * buf_x[i];
257 0 : j++;
258 : }
259 :
260 0 : j = 0;
261 0 : for (i = L_past_y + n - p2 + inter_len - 1; i >= L_past_y + n - p2 - inter_len; i--) {
262 0 : sum2 += a2[j] * buf_y[i];
263 0 : j++;
264 : }
265 :
266 0 : buf_y[L_past_y + n] = buf_x[L_past_x + n] - current_fade_fac_up * sum1 + current_fade_fac_up * sum2;
267 0 : current_fade_fac_up += fade_fac;
268 : }
269 0 : } else if (*mem_pitch_int == pitch_int && *mem_pitch_fr == pitch_fr) {
270 0 : for (n = 0; n < N4; n++) {
271 0 : sum1 = 0;
272 0 : sum2 = 0;
273 0 : j = 0;
274 0 : for (i = L_past_x + n; i >= L_past_x + n - tilt_len; i--) {
275 0 : sum1 += b2[j] * buf_x[i];
276 0 : j++;
277 : }
278 :
279 0 : j = 0;
280 0 : for (i = L_past_y + n - p2 + inter_len - 1; i >= L_past_y + n - p2 - inter_len; i--) {
281 0 : sum2 += a2[j] * buf_y[i];
282 0 : j++;
283 : }
284 :
285 0 : buf_y[L_past_y + n] = buf_x[L_past_x + n] - sum1 + sum2;
286 : }
287 : } else {
288 0 : p_x_init = &buf_x[L_past_x];
289 0 : p_y_init = &buf_y[L_past_y - p1 + inter_len - 1];
290 0 : p_y2 = &buf_y[L_past_y];
291 0 : for (n = 0; n < N4; n++) {
292 0 : sum1 = 0;
293 0 : sum2 = 0;
294 0 : p_b1 = b1;
295 0 : p_x = p_x_init;
296 0 : for (i = tilt_len; i >= 0; i--) {
297 0 : sum1 += *p_b1 * *p_x;
298 0 : p_b1++;
299 0 : p_x--;
300 : }
301 :
302 0 : p_y = p_y_init;
303 0 : p_a1 = a1;
304 0 : for (i = 2*inter_len - 1; i >= 0; i--) {
305 0 : sum2 += *p_a1 * *p_y;
306 0 : p_a1++;
307 0 : p_y--;
308 : }
309 :
310 0 : *p_y2 = *p_x_init - current_fade_fac_down * sum1 +
311 0 : current_fade_fac_down * sum2;
312 0 : current_fade_fac_down -= fade_fac;
313 0 : p_x_init++;
314 0 : p_y_init++;
315 0 : p_y2++;
316 : }
317 :
318 0 : move_float(buf_z, buf_y, (old_y_len + xLen));
319 0 : p_x_init = &buf_z[L_past_y]; /* buf z in this case */
320 0 : p_y_init = &buf_y[L_past_y - p2 + inter_len - 1];
321 0 : p_y2 = &buf_y[L_past_y];
322 :
323 0 : for (n = 0; n < N4; n++) {
324 0 : sum1 = 0;
325 0 : sum2 = 0;
326 0 : j = 0;
327 0 : p_x = p_x_init;
328 0 : p_b2 = b2;
329 0 : for (i = tilt_len; i >= 0; i--) {
330 0 : sum1 += *p_b2 * *p_x;
331 0 : p_b2++;
332 0 : p_x--;
333 : }
334 :
335 0 : p_y = p_y_init;
336 0 : p_a2 = a2;
337 0 : for (i = 2*inter_len - 1; i >= 0; i--) {
338 0 : sum2 += *p_a2 * *p_y;
339 0 : p_a2++;
340 0 : p_y--;
341 : }
342 :
343 0 : *p_y2 = *p_x_init - current_fade_fac_up * sum1 + current_fade_fac_up * sum2;
344 0 : current_fade_fac_up += fade_fac;
345 0 : p_x_init++;
346 0 : p_y_init++;
347 0 : p_y2++;
348 : }
349 : }
350 :
351 : /* Second quarter of the current frame */
352 0 : if (param[1] == 0) {
353 0 : move_float(&buf_y[L_past_y + N4], &buf_x[L_past_x + N4],
354 : ((L_past_x + N4 + N34) - (L_past_x + N4)));
355 : } else {
356 0 : p_x_init = &buf_x[L_past_x + N4];
357 0 : p_y_init = &buf_y[L_past_y + N4 - p2 + inter_len - 1];
358 0 : p_y2 = &buf_y[L_past_y + N4];
359 0 : for (n = 0; n < N34; n++) {
360 0 : sum1 = 0;
361 0 : sum2 = 0;
362 0 : p_b2 = b2;
363 0 : p_x = p_x_init;
364 :
365 0 : for (i = 0; i <= tilt_len; i++) {
366 0 : sum1 += *p_b2 * *p_x;
367 0 : p_b2++;
368 0 : p_x--;
369 : }
370 :
371 0 : p_a2 = a2;
372 0 : p_y = p_y_init;
373 :
374 0 : for (i = 2*inter_len - 1; i >= 0; i--) {
375 0 : sum2 += *p_a2 * *p_y;
376 0 : p_a2++;
377 0 : p_y--;
378 : }
379 0 : p_y_init++;
380 0 : *p_y2 = *p_x_init - sum1 + sum2;
381 0 : p_x_init++;
382 0 : p_y2++;
383 : }
384 : }
385 : /* Output */
386 0 : move_float(y, &buf_y[L_past_y], N);
387 :
388 : /* Update memory */
389 0 : move_float(mem_old_x, &buf_x[N], old_x_len);
390 0 : move_float(mem_old_y, &buf_y[N], old_y_len);
391 :
392 0 : *mem_ltpf_active = (conf_beta > 0);
393 : }
394 :
395 : /* Update ltpf param memory */
396 0 : move_int(mem_param, param, 3);
397 0 : *mem_pitch_int = pitch_int;
398 0 : *mem_pitch_fr = pitch_fr;
399 0 : *mem_gain = gain;
400 0 : *mem_beta_idx = conf_beta_idx;
401 0 : if (bfi == 0 && hrmode == 1 && (frame_dms == 50 || frame_dms == 25)){
402 0 : pitch_delta = LC3_FABS(pitch_fl_c_old - (LC3_FLOAT)pitch_int - (LC3_FLOAT)(pitch_fr / 4.0));
403 0 : *rel_pitch_change = pitch_delta / MAX(pitch_fl_c_old, 1);
404 : }
405 :
406 : #ifdef WMOPS
407 : pop_wmops();
408 : #endif
409 0 : }
|