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 "constants.h"
12 : #include "functions.h"
13 :
14 : #ifdef ENABLE_HR_MODE
15 :
16 0 : void Copy_Scale_sig_32(const Word32 x[], /* i : signal to scale input Qx */
17 : Word16 y[], /* o : scaled signal output Qx */
18 : const Word16 lg, /* i : size of x[] Q0 */
19 : const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */
20 : )
21 : {
22 : Counter i;
23 : Word16 tmp;
24 :
25 0 : if (exp0 == 0)
26 : {
27 0 : for (i = 0; i < lg; i++)
28 : {
29 0 : y[i] = extract_h(x[i]);
30 : }
31 :
32 0 : return;
33 : }
34 :
35 0 : tmp = s_max(exp0, -31);
36 0 : tmp = s_min(tmp, 31);
37 :
38 0 : for (i = 0; i < lg; i++)
39 : {
40 0 : y[i] = extract_h(L_shr_r(x[i], -tmp));
41 : }
42 : }
43 : #endif
44 :
45 0 : void processPCupdate_fx(Word16 bfi, Word16 yLen, Word16 q_old_res_fx[], Word16 *q_old_res_fx_exp,
46 : #ifdef ENABLE_HR_MODE
47 : Word32 q_res_fx[],
48 : #else
49 : Word16 q_res_fx[],
50 : #endif
51 : Word16 spec_inv_idx, Word16 gg_idx, Word16 gg_idx_off,
52 : Word16 *prev_gg, Word16 *prev_gg_e, Word16 rframe, Word16 *BW_cutoff_idx_nf,
53 : Word16 *prev_BW_cutoff_idx_nf, Word16 fac_ns_idx, Word16 *prev_fac_ns_fx, Word16 fac,
54 : Word16 fac_e)
55 : {
56 : Word16 global_gain, global_gain_e, s, s2, s3, tmp16;
57 : Word32 tmp32;
58 :
59 : #ifdef DYNMEM_COUNT
60 : struct _dynmem
61 : {
62 : Word16 global_gain, global_gain_e, s, s2, s3, tmp16;
63 : Word32 tmp32;
64 : };
65 : Dyn_Mem_In("processPCupdate_fx", sizeof(struct _dynmem));
66 : #endif
67 :
68 0 : tmp32 = L_shl_pos(L_mult0(add(gg_idx, gg_idx_off), 0x797D), 7);
69 0 : global_gain_e = add(extract_l(L_shr_pos(tmp32, 25)), 1);
70 0 : global_gain = round_fx(BASOP_Util_InvLog2_lc3plus(L_or(tmp32, 0xFE000000)));
71 :
72 0 : *prev_gg = global_gain; move16();
73 0 : *prev_gg_e = global_gain_e; move16();
74 :
75 : #ifdef ENABLE_HR_MODE
76 0 : s = getScaleFactor32_lc3plus(q_res_fx, spec_inv_idx); /* exp = 0 */
77 : #else
78 : s = getScaleFactor16(q_res_fx, spec_inv_idx); /* exp = 0 */
79 : #endif
80 :
81 0 : IF (bfi == 0)
82 : {
83 0 : *q_old_res_fx_exp = negate(s);
84 : #ifdef ENABLE_HR_MODE
85 0 : Copy_Scale_sig_32(q_res_fx, q_old_res_fx, yLen, s);
86 0 : *q_old_res_fx_exp = *q_old_res_fx_exp + 16;
87 : #else
88 : Copy_Scale_sig(q_res_fx, q_old_res_fx, yLen, s);
89 : #endif
90 : }
91 : ELSE
92 : {
93 : #ifdef ENABLE_HR_MODE
94 0 : s2 = getScaleFactor32_lc3plus(&q_res_fx[spec_inv_idx], sub(yLen, spec_inv_idx)); /* exp = q_old_res_fx_exp */
95 0 : IF (s2 == 0)
96 0 : s2 = 16;
97 0 : s3 = add(s, *q_old_res_fx_exp);
98 0 : IF (sub(s3, s2) > 0)
99 : {
100 0 : tmp16 = sub(s3, s2);
101 0 : s = sub(s, tmp16);
102 : }
103 0 : s2 = add(s, *q_old_res_fx_exp);
104 0 : *q_old_res_fx_exp = negate(s) + 16;
105 :
106 :
107 0 : if (s2 > -32)
108 : {
109 0 : Copy_Scale_sig_32(&q_res_fx[spec_inv_idx], &q_old_res_fx[spec_inv_idx], sub(yLen, spec_inv_idx), s2);
110 : }
111 : #else
112 : s2 = getScaleFactor16(&q_res_fx[spec_inv_idx], sub(yLen, spec_inv_idx)); /* exp = q_old_res_fx_exp */
113 : s3 = add(s, *q_old_res_fx_exp);
114 : IF (sub(s3, s2) > 0)
115 : {
116 : tmp16 = sub(s3, s2);
117 : s = sub(s, tmp16);
118 : }
119 : s2 = add(s, *q_old_res_fx_exp);
120 : *q_old_res_fx_exp = negate(s);
121 :
122 : s = s_max(s_min(s, 15), -15);
123 : s2 = s_max(s_min(s2, 15), -15);
124 : Copy_Scale_sig(q_res_fx, q_old_res_fx, spec_inv_idx, s);
125 : Copy_Scale_sig(&q_res_fx[spec_inv_idx], &q_old_res_fx[spec_inv_idx], sub(yLen, spec_inv_idx), s2);
126 : #endif
127 : }
128 :
129 0 : IF (rframe == 0)
130 : {
131 0 : *prev_BW_cutoff_idx_nf = *BW_cutoff_idx_nf;
132 0 : *prev_fac_ns_fx = shl_pos(sub(8, fac_ns_idx), 11);
133 : }
134 0 : ELSE IF(sub(bfi, 2) == 0 && sub(*BW_cutoff_idx_nf, *prev_BW_cutoff_idx_nf) != 0
135 : && sub(spec_inv_idx, yLen) < 0)
136 : {
137 0 : *BW_cutoff_idx_nf = *prev_BW_cutoff_idx_nf;
138 0 : *prev_fac_ns_fx = shl_sat(mult(*prev_fac_ns_fx, fac), fac_e);
139 0 : *prev_fac_ns_fx = s_max(*prev_fac_ns_fx, 2048);
140 0 : *prev_fac_ns_fx = s_min(*prev_fac_ns_fx, 16384);
141 : }
142 :
143 : #ifdef DYNMEM_COUNT
144 : Dyn_Mem_Out();
145 : #endif
146 0 : }
147 :
148 :
|