Line data Source code
1 : /******************************************************************************
2 : * ETSI TS 103 634 V1.6.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 : static LC3_INT searchMaxIndice(LC3_FLOAT* in, LC3_INT len);
15 :
16 0 : LC3_INT searchMaxIndice(LC3_FLOAT* in, LC3_INT len)
17 : {
18 0 : LC3_INT max_i = 0, i;
19 0 : LC3_FLOAT max = 0;
20 :
21 0 : if (len <= 0) {
22 0 : return -128;
23 : }
24 :
25 0 : for (i = 0; i < len; i++) {
26 0 : if (in[i] > max) {
27 0 : max = in[i];
28 0 : max_i = i;
29 : }
30 : }
31 :
32 0 : return max_i;
33 : }
34 :
35 0 : void process_ltpf_coder_fl(LC3_FLOAT* xin, LC3_INT xLen, LC3_INT ltpf_enable, LC3_INT pitch_ol, LC3_FLOAT pitch_ol_norm_corr, LC3PLUS_FrameDuration frame_dms,
36 : LC3_FLOAT* mem_old_x, LC3_INT memLen, LC3_FLOAT* mem_norm_corr_past, LC3_INT* mem_on, LC3_FLOAT* mem_pitch,
37 : LC3_INT* param, LC3_FLOAT* mem_norm_corr_past_past, LC3_INT* bits
38 : , LC3_INT16 hrmode
39 : #ifdef CR9_C_ADD_1p25MS
40 : #ifdef NEW_SIGNALLING_SCHEME_1p25
41 : ,LC3_INT16* Tx_ltpf
42 : #else
43 : ,LC3_INT16 Tx_ltpf
44 : #endif
45 : #endif
46 : )
47 : {
48 0 : LC3_FLOAT buffer[LTPF_MEMIN_LEN + LEN_12K8 + 1 + (LEN_12K8 >> 2)], sum = 0, cor_up[(MAX_PITCH_12K8 - MIN_PITCH_12K8) / 2] = {0}, *x;
49 : LC3_INT i, j, n, step, N, ltpf_active, pitch_search_delta,
50 0 : pitch_search_upsamp = 0, pitch_search_L_interpol1 = 0,
51 0 : t0_min = 0, t0_max = 0, t_min = 0, t_max = 0, temp2 = 0, t1 = 0, pitch_int = 0, pitch_fr = 0, midpoint = 0,
52 0 : delta_up = 0, delta_down = 0, pitch_index = 0, gain = 0, acflen = 0;
53 0 : LC3_FLOAT cor_tmp, cor_int_tmp, norm_corr = 0, cor[MAX_LEN_NR], cor_int[MAX_LEN_NR], sum1 = 0, sum2 = 0, sum3 = 0;
54 0 : LC3_FLOAT pitch = 0;
55 0 : LC3_FLOAT normCorrTh = 0.0f;
56 : #if defined (CR9_C_ADD_1p25MS)
57 : LC3_INT16 activation_due_to_past_corr, activation_due_to_stable_pitch, activation;
58 : #endif
59 :
60 : UNUSED(mem_norm_corr_past_past);
61 :
62 0 : if (hrmode) {
63 0 : normCorrTh = 0.4;
64 : } else {
65 0 : normCorrTh = 0.6;
66 : }
67 :
68 : /* Signal Buffer */
69 0 : N = xLen - 1;
70 0 : acflen = N;
71 :
72 0 : if (frame_dms == LC3PLUS_FRAME_DURATION_5MS)
73 : {
74 0 : acflen = 2 * N;
75 : }
76 0 : if (frame_dms == LC3PLUS_FRAME_DURATION_2p5MS)
77 : {
78 0 : acflen = 4 * N;
79 : }
80 : #ifdef CR9_C_ADD_1p25MS
81 0 : if (frame_dms == LC3PLUS_FRAME_DURATION_1p25MS)
82 : {
83 0 : acflen = 8 * N;
84 : }
85 : #endif
86 :
87 0 : x = &buffer[memLen];
88 :
89 0 : move_float( buffer, mem_old_x, memLen );
90 0 : move_float( x, xin, xLen );
91 0 : move_float( mem_old_x, &buffer[N], xLen + memLen - N );
92 :
93 0 : ltpf_active = 0;
94 0 : norm_corr = 0;
95 :
96 0 : pitch_search_delta = 4;
97 0 : pitch_search_upsamp = 4;
98 0 : pitch_search_L_interpol1 = 4;
99 :
100 0 : if (pitch_ol_norm_corr > normCorrTh) {
101 : /* Search Bounds */
102 0 : t0_min = pitch_ol - pitch_search_delta;
103 0 : t0_max = pitch_ol + pitch_search_delta;
104 0 : t0_min = MAX(t0_min, MIN_PITCH_12K8);
105 0 : t0_max = MIN(t0_max, MAX_PITCH_12K8);
106 :
107 : /* Cross-Correlation Bounds */
108 0 : t_min = t0_min - pitch_search_L_interpol1;
109 0 : t_max = t0_max + pitch_search_L_interpol1;
110 :
111 : #ifndef FIX_LTPF_PITCH_MEM_LEN
112 : acflen = N;
113 :
114 : if ( frame_dms == LC3PLUS_FRAME_DURATION_2p5MS )
115 : {
116 : acflen = 2 * N;
117 : x = x - N;
118 : }
119 : #ifdef CR9_C_ADD_1p25MS
120 : if ( frame_dms == LC3PLUS_FRAME_DURATION_1p25MS )
121 : {
122 : acflen = 4 * N;
123 : x = x - 80;
124 : }
125 : #endif
126 : #else
127 0 : x = x - (memLen - LTPF_MEMIN_LEN);
128 : #endif
129 :
130 : /* Compute norm */
131 0 : sum1 = sum2 = 0;
132 0 : for (j = 0; j < acflen; j++) {
133 0 : sum1 += x[j] * x[j];
134 0 : sum2 += x[j - t_min] * x[j - t_min];
135 : }
136 :
137 : /* Do first iteration outside of loop */
138 0 : sum = mac_loop(x, &x[-t_min], acflen);
139 :
140 0 : sum3 = LC3_SQRT(sum1 * sum2) + 1.00e-05;
141 0 : norm_corr = sum / sum3;
142 :
143 0 : norm_corr = MAX(0, norm_corr);
144 0 : cor[0] = norm_corr;
145 :
146 : /* Compute Cross-Correlation */
147 0 : for (i = t_min + 1; i <= t_max; i++) {
148 0 : sum = mac_loop(x, &x[-i], acflen);
149 :
150 0 : sum2 = sum2 + x[-i]*x[-i]
151 0 : - x[acflen - 1 - ( i - 1 )]*x[acflen - 1 - ( i - 1 )];
152 :
153 0 : sum3 = LC3_SQRT(sum1 * sum2) + 1.00e-05;
154 0 : norm_corr = sum / sum3;
155 :
156 0 : norm_corr = MAX(0, norm_corr);
157 0 : cor[i - t_min] = norm_corr;
158 :
159 : }
160 :
161 : /* Find Integer Pitch-Lag */
162 0 : temp2 = searchMaxIndice(&cor[pitch_search_L_interpol1], t_max - t_min - pitch_search_L_interpol1 - pitch_search_L_interpol1 + 1);
163 :
164 0 : t1 = temp2 + t0_min;
165 0 : assert(t1 >= t0_min && t1 <= t0_max);
166 :
167 : /* Find Fractional Pitch-Lag */
168 0 : if (t1 >= RES2_PITCH_12K8) {
169 0 : pitch_int = t1;
170 0 : pitch_fr = 0;
171 : } else {
172 0 : j = 0;
173 :
174 0 : for (i = 0; i < pitch_search_upsamp * (t_max - t_min) + 1; i = i + pitch_search_upsamp) {
175 0 : cor_up[i] = cor[j];
176 0 : j++;
177 : }
178 :
179 0 : for (i = 0; i < pitch_search_upsamp * (t0_max - t0_min + 1); i++) {
180 0 : sum = mac_loop(&cor_up[i], (const LC3_FLOAT *)inter4_1, 32);
181 :
182 0 : cor_int[i] = sum;
183 : }
184 :
185 0 : if (t1 >= RES4_PITCH_12K8) {
186 0 : step = 2;
187 : } else {
188 0 : step = 1;
189 : }
190 :
191 0 : midpoint = pitch_search_upsamp * (t1 - t0_min) + 1;
192 0 : delta_up = pitch_search_upsamp - step;
193 :
194 0 : if (t1 == t0_min) {
195 0 : delta_down = 0;
196 : } else {
197 0 : delta_down = pitch_search_upsamp - step;
198 : }
199 :
200 0 : j = 0;
201 0 : for (i = midpoint - delta_down - 1; i <= midpoint + delta_up; i = i + step) {
202 0 : cor[j] = cor_int[i];
203 0 : j++;
204 : }
205 :
206 :
207 0 : temp2 = searchMaxIndice(cor, ((midpoint + delta_up) - (midpoint - delta_down)) / step + 1);
208 0 : pitch_fr = temp2 * step - delta_down;
209 :
210 0 : if (pitch_fr >= 0) {
211 0 : pitch_int = t1;
212 : } else {
213 0 : pitch_int = t1 - 1;
214 0 : pitch_fr = pitch_search_upsamp + pitch_fr;
215 : }
216 : }
217 :
218 0 : assert((pitch_int <= MAX_PITCH_12K8 && pitch_int >= RES2_PITCH_12K8 && pitch_fr == 0) ||
219 : (pitch_int < RES2_PITCH_12K8 && pitch_int >= RES4_PITCH_12K8 && (pitch_fr == 0 || pitch_fr == 2)) ||
220 : (pitch_int < RES4_PITCH_12K8 && pitch_int >= MIN_PITCH_12K8 &&
221 : (pitch_fr == 0 || pitch_fr == 1 || pitch_fr == 2 || pitch_fr == 3)));
222 :
223 0 : if (pitch_int < RES4_PITCH_12K8) {
224 0 : pitch_index = pitch_int * 4 + pitch_fr - (MIN_PITCH_12K8 * 4);
225 0 : } else if (pitch_int < RES2_PITCH_12K8) {
226 0 : pitch_index = pitch_int * 2 + floor(pitch_fr / 2) - (RES4_PITCH_12K8 * 2) + ((RES4_PITCH_12K8 - MIN_PITCH_12K8) * 4);
227 : } else {
228 0 : pitch_index = pitch_int - RES2_PITCH_12K8 + ((RES4_PITCH_12K8 - MIN_PITCH_12K8) * 4) + ((RES2_PITCH_12K8 - RES4_PITCH_12K8) * 2);
229 : }
230 :
231 0 : assert(pitch_index >= 0 && pitch_index < 512);
232 0 : pitch = (LC3_FLOAT) pitch_int + (LC3_FLOAT) pitch_fr / 4.0;
233 :
234 :
235 : /* Normalized Correlation */
236 0 : sum1 = sum2 = sum3 = 0;
237 0 : for (n = 0; n < acflen; n++)
238 : {
239 0 : cor_tmp = x[n + 1] * enc_inter_filter[0][0] +
240 0 : x[n] * enc_inter_filter[0][1] +
241 0 : x[n - 1] * enc_inter_filter[0][2];
242 :
243 0 : cor_int_tmp = x[n - pitch_int + 1] * enc_inter_filter[pitch_fr][0] +
244 0 : x[n - pitch_int] * enc_inter_filter[pitch_fr][1] +
245 0 : x[n - pitch_int - 1] * enc_inter_filter[pitch_fr][2] +
246 0 : x[n - pitch_int - 2] * enc_inter_filter[pitch_fr][3];
247 :
248 0 : sum1 += cor_tmp * cor_int_tmp;
249 0 : sum2 += cor_tmp * cor_tmp;
250 0 : sum3 += cor_int_tmp * cor_int_tmp;
251 : }
252 :
253 0 : sum2 = LC3_SQRT(sum2 * sum3) + 1.00e-05;
254 0 : norm_corr = sum1 / sum2;
255 :
256 0 : assert(norm_corr >= -1.00001 && norm_corr <= 1.00001);
257 0 : norm_corr = MIN(1, MAX(-1, norm_corr));
258 0 : if (norm_corr < 0) {
259 0 : norm_corr = 0;
260 : }
261 :
262 0 : if (ltpf_enable == 1)
263 : {
264 : /* Decision if ltpf active */
265 : #if defined (CR9_C_ADD_1p25MS)
266 0 : activation_due_to_past_corr = mem_norm_corr_past[1] > 0.94;
267 0 : activation_due_to_stable_pitch = 1;
268 0 : if (frame_dms == LC3PLUS_FRAME_DURATION_1p25MS)
269 : {
270 0 : activation_due_to_past_corr &= (mem_norm_corr_past[2] > 0.94);
271 0 : activation_due_to_past_corr &= (mem_norm_corr_past[3] > 0.94);
272 0 : activation_due_to_past_corr &= (mem_norm_corr_past[4] > 0.94);
273 :
274 0 : activation_due_to_stable_pitch = LC3_FMAX(pitch, *mem_pitch) * 0.7f < LC3_FMIN(pitch, *mem_pitch);
275 : }
276 0 : activation = activation_due_to_past_corr && activation_due_to_stable_pitch;
277 0 : if ((*mem_on == 0 && (frame_dms == LC3PLUS_FRAME_DURATION_10MS || activation) && mem_norm_corr_past[0] > 0.94 &&
278 0 : norm_corr > 0.94) ||
279 0 : ((*mem_on == 1 && norm_corr > 0.9) && activation_due_to_stable_pitch) ||
280 0 : (*mem_on == 1 && LC3_FABS(pitch - *mem_pitch) < 2 && (norm_corr - mem_norm_corr_past[0]) > -0.1 &&
281 0 : norm_corr > 0.84))
282 : {
283 0 : ltpf_active = 1;
284 : }
285 : #else
286 : if ((*mem_on == 0 && (frame_dms == LC3PLUS_FRAME_DURATION_10MS || *mem_norm_corr_past_past > 0.94) && *mem_norm_corr_past > 0.94 &&
287 : norm_corr > 0.94) ||
288 : (*mem_on == 1 && norm_corr > 0.9) ||
289 : (*mem_on == 1 && LC3_FABS(pitch - *mem_pitch) < 2 && (norm_corr - *mem_norm_corr_past) > -0.1 &&
290 : norm_corr > 0.84))
291 : {
292 : ltpf_active = 1;
293 : }
294 : #endif
295 : }
296 :
297 0 : gain = 4;
298 : } else {
299 0 : gain = 0;
300 0 : norm_corr = pitch_ol_norm_corr;
301 0 : pitch = 0;
302 : }
303 :
304 0 : if (gain > 0) {
305 0 : param[0] = 1;
306 0 : param[1] = ltpf_active;
307 0 : param[2] = pitch_index;
308 0 : *bits = 11;
309 : } else {
310 0 : zero_int(param, 3);
311 :
312 0 : *bits = 1;
313 : }
314 :
315 :
316 : #ifdef CR9_C_ADD_1p25MS
317 : #ifdef NEW_SIGNALLING_SCHEME_1p25
318 0 : if (frame_dms == LC3PLUS_FRAME_DURATION_1p25MS)
319 : {
320 0 : LC3_INT32 tmp = MIN(*Tx_ltpf, 1); /* 0 == phaseA, 1==PhaseB ) */
321 : /* tmp [0 or 1} will points to 2 ltp bits in any case */
322 0 : if ( param[0] == 0 && tmp != 0 )
323 : {
324 : /* pitch correlation dropped from high(ltp active || ltpf_active) to low (no ltp info at all ),
325 : we select to NOT transmit the remaining phaseB lag info for potential use in a next possible PLC frame */
326 0 : *Tx_ltpf = 0; /* kill the lag transmission state from the encoder side */
327 : /* tmp stays 0 or 1 */
328 : }
329 :
330 : /* 00 (ltp=0, ltpf=0, no Phase 2b),
331 : 010 (ltp=1, ltpf=0, phaseA, 7b),
332 : 011 (ltp=1, ltpf=0, phaseB , 7b), lowered lag res for PLC
333 : 10x (ltp=1, ltpf=1) phaseA 6b)
334 : 11x (ltp=1, ltpf=1) phaseB 7b)
335 : */
336 :
337 0 : if (param[0] != 0)
338 : {
339 0 : if (param[1] == 0)
340 : { /* ltp active, PLC usage case LTPF inactive 01[PhaseA]=010=2, or 01[phaseB]=011=3
341 : path ltp active and ltpf inactive */
342 0 : tmp = (0x02 | tmp); /* phase Info in LSB b0, LTPFactive in b1, tmp becomes 2 or 3 */
343 : }
344 : else
345 : { /*param[1] != 0*/ /* ltp active, ltpf active */
346 0 : assert(param[2] >= 0 && param[2] <= 511);
347 0 : tmp = (0x04 | (tmp << 1)); /* LTPF in b2, phase b1, always zero in b0 , tmp becomes 4 or 6 */
348 : /* 100=4 for phase A */
349 : /* 110=6 for phase B */
350 : }
351 : }
352 0 : assert(tmp >= 0 && tmp < 8);
353 0 : *bits = lrsns_ltp_bits[tmp]; /* one of { 2,2, 7,7 , 6,6, 7,7} */
354 : /* tmp=idx is 0,1 2,3 4,5, 6,7 */
355 :
356 0 : assert(*bits == 2 || *bits == 6 || *bits == 7);
357 : }
358 : #endif
359 : #else
360 : assert(*bits == 1 || *bits == 11);
361 : #endif
362 :
363 0 : if (frame_dms < LC3PLUS_FRAME_DURATION_10MS) {
364 : #if defined (CR9_C_ADD_1p25MS)
365 0 : move_float(&mem_norm_corr_past[1], &mem_norm_corr_past[0], LEN_MEM_NORMCORR-1);
366 : #else
367 : *mem_norm_corr_past_past = *mem_norm_corr_past;
368 : #endif
369 : }
370 :
371 0 : *mem_norm_corr_past = norm_corr;
372 0 : *mem_on = ltpf_active;
373 0 : *mem_pitch = pitch;
374 0 : }
|