comparison libtwamr/pitch_fr.c @ 391:be8edf9e6bc1

libtwamr: integrate pitch_fr.c
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 06 May 2024 18:30:00 +0000
parents
children
comparison
equal deleted inserted replaced
390:bde9f5804670 391:be8edf9e6bc1
1 /*
2 ********************************************************************************
3 *
4 * GSM AMR-NB speech codec R98 Version 7.6.0 December 12, 2001
5 * R99 Version 3.3.0
6 * REL-4 Version 4.1.0
7 *
8 ********************************************************************************
9 *
10 * File : pitch_fr.c
11 * Purpose : Find the pitch period with 1/3 or 1/6 subsample
12 * : resolution (closed loop).
13 *
14 ********************************************************************************
15 */
16 /*
17 ********************************************************************************
18 * MODULE INCLUDE FILE AND VERSION ID
19 ********************************************************************************
20 */
21 #include "namespace.h"
22 #include "pitch_fr.h"
23 /*
24 ********************************************************************************
25 * INCLUDE FILES
26 ********************************************************************************
27 */
28 #include "typedef.h"
29 #include "basic_op.h"
30 #include "oper_32b.h"
31 #include "no_count.h"
32 #include "cnst.h"
33 #include "enc_lag3.h"
34 #include "enc_lag6.h"
35 #include "inter_36.h"
36 #include "inv_sqrt.h"
37 #include "convolve.h"
38
39 /*
40 ********************************************************************************
41 * LOCAL VARIABLES AND TABLES
42 ********************************************************************************
43 */
44
45 /*
46 * mode dependent parameters used in Pitch_fr()
47 * Note: order of MRxx in 'enum Mode' is important!
48 */
49 static const struct {
50 Word16 max_frac_lag; /* lag up to which fractional lags are used */
51 Word16 flag3; /* enable 1/3 instead of 1/6 fract. resolution */
52 Word16 first_frac; /* first fractional to check */
53 Word16 last_frac; /* last fractional to check */
54 Word16 delta_int_low; /* integer lag below TO to start search from */
55 Word16 delta_int_range; /* integer range around T0 */
56 Word16 delta_frc_low; /* fractional below T0 */
57 Word16 delta_frc_range; /* fractional range around T0 */
58 Word16 pit_min; /* minimum pitch */
59 } mode_dep_parm[8] = {
60 /* MR475 */ { 84, 1, -2, 2, 5, 10, 5, 9, PIT_MIN },
61 /* MR515 */ { 84, 1, -2, 2, 5, 10, 5, 9, PIT_MIN },
62 /* MR59 */ { 84, 1, -2, 2, 3, 6, 5, 9, PIT_MIN },
63 /* MR67 */ { 84, 1, -2, 2, 3, 6, 5, 9, PIT_MIN },
64 /* MR74 */ { 84, 1, -2, 2, 3, 6, 5, 9, PIT_MIN },
65 /* MR795 */ { 84, 1, -2, 2, 3, 6, 10, 19, PIT_MIN },
66 /* MR102 */ { 84, 1, -2, 2, 3, 6, 5, 9, PIT_MIN },
67 /* MR122 */ { 94, 0, -3, 3, 3, 6, 5, 9, PIT_MIN_MR122 }
68 };
69
70 /*
71 ********************************************************************************
72 * LOCAL PROGRAM CODE
73 ********************************************************************************
74 */
75 /*************************************************************************
76 *
77 * FUNCTION: Norm_Corr()
78 *
79 * PURPOSE: Find the normalized correlation between the target vector
80 * and the filtered past excitation.
81 *
82 * DESCRIPTION:
83 * The normalized correlation is given by the correlation between the
84 * target and filtered past excitation divided by the square root of
85 * the energy of filtered excitation.
86 * corr[k] = <x[], y_k[]>/sqrt(y_k[],y_k[])
87 * where x[] is the target vector and y_k[] is the filtered past
88 * excitation at delay k.
89 *
90 *************************************************************************/
91 static void Norm_Corr (Word16 exc[], Word16 xn[], Word16 h[], Word16 L_subfr,
92 Word16 t_min, Word16 t_max, Word16 corr_norm[])
93 {
94 Word16 i, j, k;
95 Word16 corr_h, corr_l, norm_h, norm_l;
96 Word32 s;
97
98 /* Usally dynamic allocation of (L_subfr) */
99 Word16 excf[L_SUBFR];
100 Word16 scaling, h_fac, *s_excf, scaled_excf[L_SUBFR];
101
102 k = -t_min; move16 ();
103
104 /* compute the filtered excitation for the first delay t_min */
105
106 Convolve (&exc[k], h, excf, L_subfr);
107
108 /* scale "excf[]" to avoid overflow */
109
110 for (j = 0; j < L_subfr; j++) {
111 scaled_excf[j] = shr (excf[j], 2); move16 ();
112 }
113
114 /* Compute 1/sqrt(energy of excf[]) */
115
116 s = 0; move32 ();
117 for (j = 0; j < L_subfr; j++) {
118 s = L_mac (s, excf[j], excf[j]);
119 }
120 test ();
121 if (L_sub (s, 67108864L) <= 0) { /* if (s <= 2^26) */
122 s_excf = excf; move16 ();
123 h_fac = 15 - 12; move16 ();
124 scaling = 0; move16 ();
125 }
126 else {
127 /* "excf[]" is divided by 2 */
128 s_excf = scaled_excf; move16 ();
129 h_fac = 15 - 12 - 2; move16 ();
130 scaling = 2; move16 ();
131 }
132
133 /* loop for every possible period */
134
135 for (i = t_min; i <= t_max; i++) {
136 /* Compute 1/sqrt(energy of excf[]) */
137
138 s = 0; move32 ();
139 for (j = 0; j < L_subfr; j++) {
140 s = L_mac (s, s_excf[j], s_excf[j]);
141 }
142
143 s = Inv_sqrt (s);
144 L_Extract (s, &norm_h, &norm_l);
145
146 /* Compute correlation between xn[] and excf[] */
147
148 s = 0; move32 ();
149 for (j = 0; j < L_subfr; j++) {
150 s = L_mac (s, xn[j], s_excf[j]);
151 }
152 L_Extract (s, &corr_h, &corr_l);
153
154 /* Normalize correlation = correlation * (1/sqrt(energy)) */
155
156 s = Mpy_32 (corr_h, corr_l, norm_h, norm_l);
157
158 corr_norm[i] = extract_h (L_shl (s, 16));
159 move16 ();
160
161 /* modify the filtered excitation excf[] for the next iteration */
162
163 test ();
164 if (sub (i, t_max) != 0) {
165 k--;
166 for (j = L_subfr - 1; j > 0; j--) {
167 s = L_mult (exc[k], h[j]);
168 s = L_shl (s, h_fac);
169 s_excf[j] = add (extract_h (s), s_excf[j - 1]); move16 ();
170 }
171 s_excf[0] = shr (exc[k], scaling); move16 ();
172 }
173 }
174 return;
175 }
176
177 /*************************************************************************
178 *
179 * FUNCTION: searchFrac()
180 *
181 * PURPOSE: Find fractional pitch
182 *
183 * DESCRIPTION:
184 * The function interpolates the normalized correlation at the
185 * fractional positions around lag T0. The position at which the
186 * interpolation function reaches its maximum is the fractional pitch.
187 * Starting point of the search is frac, end point is last_frac.
188 * frac is overwritten with the fractional pitch.
189 *
190 *************************************************************************/
191 static void searchFrac (
192 Word16 *lag, /* i/o : integer pitch */
193 Word16 *frac, /* i/o : start point of search -
194 fractional pitch */
195 Word16 last_frac, /* i : endpoint of search */
196 Word16 corr[], /* i : normalized correlation */
197 Word16 flag3 /* i : subsample resolution
198 (3: =1 / 6: =0) */
199 )
200 {
201 Word16 i;
202 Word16 max;
203 Word16 corr_int;
204
205 /* Test the fractions around T0 and choose the one which maximizes */
206 /* the interpolated normalized correlation. */
207
208 max = Interpol_3or6 (&corr[*lag], *frac, flag3); move16 (); /* function result */
209
210 for (i = add (*frac, 1); i <= last_frac; i++) {
211 corr_int = Interpol_3or6 (&corr[*lag], i, flag3);
212 move16 ();
213 test ();
214 if (sub (corr_int, max) > 0) {
215 max = corr_int; move16 ();
216 *frac = i; move16 ();
217 }
218 }
219
220 test();
221 if (flag3 == 0) {
222 /* Limit the fraction value in the interval [-2,-1,0,1,2,3] */
223
224 test ();
225 if (sub (*frac, -3) == 0) {
226 *frac = 3; move16 ();
227 *lag = sub (*lag, 1);
228 }
229 }
230 else {
231 /* limit the fraction value between -1 and 1 */
232
233 test ();
234 if (sub (*frac, -2) == 0) {
235 *frac = 1; move16 ();
236 *lag = sub (*lag, 1);
237 }
238 test ();
239 if (sub (*frac, 2) == 0) {
240 *frac = -1; move16 ();
241 *lag = add (*lag, 1);
242 }
243 }
244 }
245
246 /*************************************************************************
247 *
248 * FUNCTION: getRange()
249 *
250 * PURPOSE: Sets range around open-loop pitch or integer pitch of last subframe
251 *
252 * DESCRIPTION:
253 * Takes integer pitch T0 and calculates a range around it with
254 * t0_min = T0-delta_low and t0_max = (T0-delta_low) + delta_range
255 * t0_min and t0_max are bounded by pitmin and pitmax
256 *
257 *************************************************************************/
258 static void getRange (
259 Word16 T0, /* i : integer pitch */
260 Word16 delta_low, /* i : search start offset */
261 Word16 delta_range, /* i : search range */
262 Word16 pitmin, /* i : minimum pitch */
263 Word16 pitmax, /* i : maximum pitch */
264 Word16 *t0_min, /* o : search range minimum */
265 Word16 *t0_max) /* o : search range maximum */
266 {
267 *t0_min = sub(T0, delta_low);
268 test ();
269 if (sub(*t0_min, pitmin) < 0) {
270 *t0_min = pitmin; move16();
271 }
272 *t0_max = add(*t0_min, delta_range);
273 test ();
274 if (sub(*t0_max, pitmax) > 0) {
275 *t0_max = pitmax; move16();
276 *t0_min = sub(*t0_max, delta_range);
277 }
278 }
279
280 /*
281 ********************************************************************************
282 * PUBLIC PROGRAM CODE
283 ********************************************************************************
284 */
285
286 /*************************************************************************
287 *
288 * Function: Pitch_fr_reset
289 * Purpose: Initializes state memory to zero
290 *
291 **************************************************************************
292 */
293 void Pitch_fr_reset (Pitch_frState *state)
294 {
295 state->T0_prev_subframe = 0;
296 }
297
298 /*************************************************************************
299 *
300 * FUNCTION: Pitch_fr()
301 *
302 * PURPOSE: Find the pitch period with 1/3 or 1/6 subsample resolution
303 * (closed loop).
304 *
305 * DESCRIPTION:
306 * - find the normalized correlation between the target and filtered
307 * past excitation in the search range.
308 * - select the delay with maximum normalized correlation.
309 * - interpolate the normalized correlation at fractions -3/6 to 3/6
310 * with step 1/6 around the chosen delay.
311 * - The fraction which gives the maximum interpolated value is chosen.
312 *
313 *************************************************************************/
314 Word16 Pitch_fr ( /* o : pitch period (integer) */
315 Pitch_frState *st, /* i/o : State struct */
316 enum Mode mode, /* i : codec mode */
317 Word16 T_op[], /* i : open loop pitch lags */
318 Word16 exc[], /* i : excitation buffer Q0 */
319 Word16 xn[], /* i : target vector Q0 */
320 Word16 h[], /* i : impulse response of synthesis and
321 weighting filters Q12 */
322 Word16 L_subfr, /* i : Length of subframe */
323 Word16 i_subfr, /* i : subframe offset */
324 Word16 *pit_frac, /* o : pitch period (fractional) */
325 Word16 *resu3, /* o : subsample resolution 1/3 (=1) or 1/6 (=0) */
326 Word16 *ana_index /* o : index of encoding */
327 )
328 {
329 Word16 i;
330 Word16 t_min, t_max;
331 Word16 t0_min, t0_max;
332 Word16 max, lag, frac;
333 Word16 tmp_lag;
334 Word16 *corr;
335 Word16 corr_v[40]; /* Total length = t0_max-t0_min+1+2*L_INTER_SRCH */
336
337 Word16 max_frac_lag;
338 Word16 flag3, flag4;
339 Word16 last_frac;
340 Word16 delta_int_low, delta_int_range;
341 Word16 delta_frc_low, delta_frc_range;
342 Word16 pit_min;
343 Word16 frame_offset;
344 Word16 delta_search;
345
346 /*-----------------------------------------------------------------------*
347 * set mode specific variables *
348 *-----------------------------------------------------------------------*/
349
350 max_frac_lag = mode_dep_parm[mode].max_frac_lag; move16 ();
351 flag3 = mode_dep_parm[mode].flag3; move16 ();
352 frac = mode_dep_parm[mode].first_frac; move16 ();
353 last_frac = mode_dep_parm[mode].last_frac; move16 ();
354 delta_int_low = mode_dep_parm[mode].delta_int_low; move16 ();
355 delta_int_range = mode_dep_parm[mode].delta_int_range; move16 ();
356
357 delta_frc_low = mode_dep_parm[mode].delta_frc_low; move16 ();
358 delta_frc_range = mode_dep_parm[mode].delta_frc_range; move16 ();
359 pit_min = mode_dep_parm[mode].pit_min; move16 ();
360
361 /*-----------------------------------------------------------------------*
362 * decide upon full or differential search *
363 *-----------------------------------------------------------------------*/
364
365 delta_search = 1; move16 ();
366
367 test (); test ();
368 if ((i_subfr == 0) || (sub(i_subfr,L_FRAME_BY2) == 0)) {
369
370 /* Subframe 1 and 3 */
371
372 test (); test (); test ();
373 if (((sub(mode, MR475) != 0) && (sub(mode, MR515) != 0)) ||
374 (sub(i_subfr,L_FRAME_BY2) != 0)) {
375
376 /* set t0_min, t0_max for full search */
377 /* this is *not* done for mode MR475, MR515 in subframe 3 */
378
379 delta_search = 0; /* no differential search */ move16 ();
380
381 /* calculate index into T_op which contains the open-loop */
382 /* pitch estimations for the 2 big subframes */
383
384 frame_offset = 1; move16 ();
385 test ();
386 if (i_subfr == 0)
387 frame_offset = 0; move16 ();
388
389 /* get T_op from the corresponding half frame and */
390 /* set t0_min, t0_max */
391
392 getRange (T_op[frame_offset], delta_int_low, delta_int_range,
393 pit_min, PIT_MAX, &t0_min, &t0_max);
394 }
395 else {
396
397 /* mode MR475, MR515 and 3. Subframe: delta search as well */
398 getRange (st->T0_prev_subframe, delta_frc_low, delta_frc_range,
399 pit_min, PIT_MAX, &t0_min, &t0_max);
400 }
401 }
402 else {
403
404 /* for Subframe 2 and 4 */
405 /* get range around T0 of previous subframe for delta search */
406
407 getRange (st->T0_prev_subframe, delta_frc_low, delta_frc_range,
408 pit_min, PIT_MAX, &t0_min, &t0_max);
409 }
410
411 /*-----------------------------------------------------------------------*
412 * Find interval to compute normalized correlation *
413 *-----------------------------------------------------------------------*/
414
415 t_min = sub (t0_min, L_INTER_SRCH);
416 t_max = add (t0_max, L_INTER_SRCH);
417
418 corr = &corr_v[-t_min]; move16 ();
419
420 /*-----------------------------------------------------------------------*
421 * Compute normalized correlation between target and filtered excitation *
422 *-----------------------------------------------------------------------*/
423
424 Norm_Corr (exc, xn, h, L_subfr, t_min, t_max, corr);
425
426 /*-----------------------------------------------------------------------*
427 * Find integer pitch *
428 *-----------------------------------------------------------------------*/
429
430 max = corr[t0_min]; move16 ();
431 lag = t0_min; move16 ();
432
433 for (i = t0_min + 1; i <= t0_max; i++) {
434 test ();
435 if (sub (corr[i], max) >= 0) {
436 max = corr[i]; move16 ();
437 lag = i; move16 ();
438 }
439 }
440
441 /*-----------------------------------------------------------------------*
442 * Find fractional pitch *
443 *-----------------------------------------------------------------------*/
444 test (); test ();
445 if ((delta_search == 0) && (sub (lag, max_frac_lag) > 0)) {
446
447 /* full search and integer pitch greater than max_frac_lag */
448 /* fractional search is not needed, set fractional to zero */
449
450 frac = 0; move16 ();
451 }
452 else {
453
454 /* if differential search AND mode MR475 OR MR515 OR MR59 OR MR67 */
455 /* then search fractional with 4 bits resolution */
456
457 test (); test (); test (); test (); test ();
458 if ((delta_search != 0) &&
459 ((sub (mode, MR475) == 0) ||
460 (sub (mode, MR515) == 0) ||
461 (sub (mode, MR59) == 0) ||
462 (sub (mode, MR67) == 0))) {
463
464 /* modify frac or last_frac according to position of last */
465 /* integer pitch: either search around integer pitch, */
466 /* or only on left or right side */
467
468 tmp_lag = st->T0_prev_subframe; move16 ();
469 test ();
470 if ( sub( sub(tmp_lag, t0_min), 5) > 0)
471 tmp_lag = add (t0_min, 5);
472 test ();
473 if ( sub( sub(t0_max, tmp_lag), 4) > 0)
474 tmp_lag = sub (t0_max, 4);
475
476 test (); test ();
477 if ((sub (lag, tmp_lag) == 0) ||
478 (sub (lag, sub(tmp_lag, 1)) == 0)) {
479
480 /* normal search in fractions around T0 */
481
482 searchFrac (&lag, &frac, last_frac, corr, flag3);
483
484 }
485 else if (sub (lag, sub (tmp_lag, 2)) == 0) {
486 test ();
487 /* limit search around T0 to the right side */
488 frac = 0; move16 ();
489 searchFrac (&lag, &frac, last_frac, corr, flag3);
490 }
491 else if (sub (lag, add(tmp_lag, 1)) == 0) {
492 test (); test ();
493 /* limit search around T0 to the left side */
494 last_frac = 0; move16 ();
495 searchFrac (&lag, &frac, last_frac, corr, flag3);
496 }
497 else {
498 test (); test ();
499 /* no fractional search */
500 frac = 0; move16 ();
501 }
502 }
503 else
504 /* test the fractions around T0 */
505 searchFrac (&lag, &frac, last_frac, corr, flag3);
506 }
507
508 /*-----------------------------------------------------------------------*
509 * encode pitch *
510 *-----------------------------------------------------------------------*/
511
512 test ();
513 if (flag3 != 0) {
514 /* flag4 indicates encoding with 4 bit resolution; */
515 /* this is needed for mode MR475, MR515 and MR59 */
516
517 flag4 = 0; move16 ();
518 test (); test (); test (); test ();
519 if ( (sub (mode, MR475) == 0) ||
520 (sub (mode, MR515) == 0) ||
521 (sub (mode, MR59) == 0) ||
522 (sub (mode, MR67) == 0) ) {
523 flag4 = 1; move16 ();
524 }
525
526 /* encode with 1/3 subsample resolution */
527
528 *ana_index = Enc_lag3(lag, frac, st->T0_prev_subframe,
529 t0_min, t0_max, delta_search, flag4); move16 (); /* function result */
530
531 }
532 else
533 {
534 /* encode with 1/6 subsample resolution */
535
536 *ana_index = Enc_lag6(lag, frac, t0_min, delta_search); move16 (); /* function result */
537 }
538
539 /*-----------------------------------------------------------------------*
540 * update state variables *
541 *-----------------------------------------------------------------------*/
542
543 st->T0_prev_subframe = lag; move16 ();
544
545 /*-----------------------------------------------------------------------*
546 * update output variables *
547 *-----------------------------------------------------------------------*/
548
549 *resu3 = flag3; move16 ();
550
551 *pit_frac = frac; move16 ();
552
553 return (lag);
554 }