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 plc_phEcu_F0_refine_first_fx(Word16 * plocs, /* i/o */
14 : const Word16 n_plocs_in, Word32 *L_f0est, /* i/o Q16 */
15 : const Word16 stPhECU_f0hzLtpBinQ7, const Word16 stPhECU_f0gainLtpQ15,
16 : const Word16 nSubm)
17 :
18 : {
19 : Counter subm, i;
20 : Word16 ploc, n_plocs_ana;
21 0 : Word32 L_tmp = 0, L_diff, L_f0EstQ7, L_sensitivity_Q7;
22 :
23 : #ifdef DYNMEM_COUNT
24 : Dyn_Mem_In("plc_phEcu_F0_refine_first_fx", sizeof(struct {
25 : Counter subm, i;
26 : Word16 ploc, n_plocs_ana;
27 : Word32 L_tmp, L_diff, L_f0EstQ7, L_sensitivity_Q7;
28 : }));
29 : #endif
30 :
31 :
32 :
33 : /* single initial peak F0 correction using available LTP information */
34 :
35 0 : IF (sub(stPhECU_f0gainLtpQ15, ((Word16)(0.25 * 32768.0))) > 0)
36 : {
37 0 : ploc = -1; move16(); /* sentinel */
38 0 : n_plocs_ana = s_min(n_plocs_in, 4); /* only analyze at first 3 deteteced LF peaks */
39 :
40 : /* only apply analysis below nsubm*pitmax_freq ~= 1600Hz */
41 0 : i = sub(n_plocs_ana, 1);
42 0 : WHILE (i >= 0 && sub(plocs[i], (Word16)(1600.0 / 62.5)) > 0)
43 : {
44 0 : i--;
45 : }
46 0 : n_plocs_ana = add(i, 1);
47 :
48 0 : IF ((n_plocs_ana > 0))
49 : {
50 : /* % find/correct first peak in f0est , that is a submultiple of n*f0Ltp*/
51 0 : FOR (i = 0; i < n_plocs_ana; i++)
52 : {
53 :
54 0 : L_sensitivity_Q7 = L_deposit_l(((Word32)1) << (7 - 1)); /* 0.5 in Q7 */
55 0 : if (sub(stPhECU_f0gainLtpQ15, ((Word16)(0.75 * 32768.0))) < 0)
56 : {
57 0 : L_sensitivity_Q7 = L_shr_pos(L_sensitivity_Q7, 1); /* % more picky if correlation is rather low */
58 : }
59 :
60 0 : L_f0EstQ7 = L_shr_pos(L_f0est[i], 9); /* Q16 to Q7 */
61 :
62 0 : FOR (subm = 1; subm <= nSubm; subm++)
63 : {
64 : /*adjf0 = abs(f0est - subm*stPhECU_f0hzLtpBin*ones(size(f0est))) < sensitivity ; % L1 difference,
65 : vector operation over f0
66 : ind = find(adjf0==1,1); */
67 0 : L_diff = L_msu0(L_f0EstQ7, subm, stPhECU_f0hzLtpBinQ7);
68 0 : L_diff = L_abs(L_diff);
69 0 : IF (L_sub(L_diff, L_sensitivity_Q7) < 0)
70 : {
71 0 : L_tmp = L_shl_pos(L_mult0(subm, stPhECU_f0hzLtpBinQ7), 16 - 7); /* to Q16 */
72 0 : ploc = i; move16();
73 0 : BREAK;
74 : }
75 0 : L_sensitivity_Q7 = Mpy_32_16_lc3plus(L_sensitivity_Q7, (Word16)(0.875 * 32768.0 )); /* 2 cycles */
76 : } /* subm*/
77 :
78 0 : IF (ploc >= 0)
79 : {
80 0 : BREAK;
81 : }
82 : } /* i, n_ploc_ana*/
83 : }
84 :
85 0 : if (ploc >= 0)
86 : {
87 0 : L_f0est[ploc] = L_tmp; move32(); /* in Q16 */
88 : /*ideally also integer plocs should be updated , e.g. if f0est goes from 1.45(plocs=1) to 1.6(plocs==2)
89 : */
90 : /* but that is costly and not required as long as corr_phase width is large enough ]*/
91 : }
92 : }
93 :
94 : #ifdef DYNMEM_COUNT
95 : Dyn_Mem_Out();
96 : #endif
97 :
98 0 : }
99 :
100 :
|