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 "functions.h"
11 :
12 : #ifdef ENABLE_HR_MODE
13 :
14 0 : void processResidualCoding_fx(Word16 x_e, Word32 x[],
15 : Word32 xq[], Word32 gain,
16 : Word16 gain_e, Word16 L_spec,
17 : Word16 targetBits, Word16 nBits, UWord8 *resBits, Word16 *numResBits
18 : , Word16 hrmode
19 : )
20 : {
21 :
22 : Counter i;
23 : Word16 s, n, m;
24 : Word32 L_tmp;
25 0 : Word16 iter = 0;
26 : Counter idx;
27 0 : Word16 N_nz = 0;
28 : Word16 n1, n2;
29 :
30 : #ifdef DYNMEM_COUNT
31 : Dyn_Mem_In("processResidualCoding_fx", sizeof(struct {
32 : Counter i;
33 : Word16 s, n, m;
34 : Word32 L_tmp;
35 : Word16 iter;
36 : Counter idx;
37 : Word16 N_nz;
38 : Word16 *nz_idx;
39 : Word16 n1, n2;
40 : }));
41 : #endif
42 :
43 0 : n = 0;
44 0 : move16();
45 :
46 0 : IF (hrmode)
47 : {
48 0 : m = add(sub(targetBits, nBits), 14);
49 0 : assert(m <= (MAX_RESBITS_LEN << RESBITS_PACK_SHIFT));
50 : }
51 : ELSE
52 : {
53 0 : m = add(sub(targetBits, nBits), 4);
54 0 : if (m > L_spec)
55 : {
56 0 : m = L_spec;
57 : }
58 : }
59 :
60 0 : basop_memset(resBits, 0, sizeof(*resBits)*((m + RESBITS_PACK_MASK) >> RESBITS_PACK_SHIFT));
61 :
62 0 : s = sub(add(15, gain_e), x_e);
63 :
64 0 : IF(hrmode)
65 : {
66 : /*
67 : x = xval * 2^(31 - x_e)
68 : gain = gainval * 2^(15 - gain_e)
69 :
70 : To bring gain to the same q of x :
71 :
72 : gain (in_Qx_e) = gain * 2^(16 + gain_e - x_e)
73 :
74 : gain*offset (in Qx_e) = gain (in_Qx_e) * 0.25 = gain (in_Qx_e) / 4 = gain * 2^(16 - 2 + gain_e - x_e)
75 : */
76 : Word16 shift_val;
77 0 : shift_val = sub(sub(gain_e, x_e), 2);
78 :
79 : Word32 gain_offset;
80 :
81 0 : IF (shift_val <= -32)
82 0 : gain_offset = 0;
83 : ELSE
84 : {
85 0 : gain_offset = L_shl_sat(gain, shift_val);
86 : }
87 :
88 0 : Word16 exit_iter = 0;
89 :
90 : Word16 nz_idx[MAX_LEN];
91 :
92 : /* enumerate non-zero coefficients */
93 0 : FOR (i = 0; i < L_spec; i++)
94 : {
95 0 : IF (xq[i])
96 : {
97 0 : nz_idx[N_nz] = i; move16();
98 0 : N_nz = add(N_nz, 1);
99 : }
100 : }
101 :
102 0 : s = sub(31, sub(x_e, gain_e));
103 0 : FOR (iter = 0; iter < EXT_RES_ITER_MAX; iter++)
104 : {
105 0 : FOR (i = 0; i < N_nz; i++)
106 : {
107 0 : idx = nz_idx[i];
108 :
109 0 : L_tmp = L_sub(x[idx], Mpy_32_32_lc3plus(L_shl(xq[idx], s), gain));
110 :
111 0 : IF (L_tmp >= 0)
112 : {
113 0 : n1 = shr(n, RESBITS_PACK_SHIFT);
114 0 : n2 = s_and(n, RESBITS_PACK_MASK);
115 0 : resBits[n1] = (UWord8)s_or(resBits[n1], shl(1, n2));
116 0 : move16();
117 0 : x[idx] = L_sub(x[idx], gain_offset);
118 0 : move16();
119 : }
120 : ELSE
121 : {
122 0 : move16();
123 0 : x[idx] = L_add(x[idx], gain_offset);
124 0 : move16();
125 : }
126 0 : n = add(n, 1);
127 0 : IF (sub(n, m) == 0)
128 : {
129 0 : exit_iter = 1;
130 0 : BREAK;
131 : }
132 : }
133 0 : gain_offset = L_shr(gain_offset, 1); /* offset *= 0.5 */
134 :
135 0 : IF (exit_iter)
136 : {
137 0 : BREAK;
138 : }
139 : }
140 : }
141 : ELSE
142 : {
143 0 : s = add(s, 16);
144 0 : gain = round_fx(gain);
145 :
146 0 : FOR (i = 0; i < L_spec; i++)
147 : {
148 0 : IF (xq[i] != 0)
149 : {
150 0 : L_tmp = L_sub(x[i], Mpy_32_16_lc3plus(L_shl(xq[i], s), gain));
151 0 : if (L_tmp >= 0)
152 : {
153 0 : n1 = shr(n, RESBITS_PACK_SHIFT);
154 0 : n2 = s_and(n, RESBITS_PACK_MASK);
155 0 : resBits[n1] = (UWord8) s_or(resBits[n1], shl(1, n2));
156 0 : move16();
157 : }
158 0 : n = add(n, 1);
159 0 : IF (sub(n, m) == 0)
160 : {
161 0 : BREAK;
162 : }
163 : }
164 : }
165 : }
166 0 : *numResBits = n;
167 0 : move16();
168 :
169 : #ifdef DYNMEM_COUNT
170 : Dyn_Mem_Out();
171 : #endif
172 0 : }
173 :
174 : #else
175 :
176 : void processResidualCoding_fx(Word16 x_e, Word32 x[],
177 : Word16 xq[],
178 : Word16 gain, Word16 gain_e, Word16 L_spec,
179 : Word16 targetBits, Word16 nBits, UWord8 *resBits, Word16 *numResBits
180 : )
181 : {
182 :
183 : Counter i;
184 : Word16 s, n, m;
185 : Word32 L_tmp;
186 : #ifdef DYNMEM_COUNT
187 : Dyn_Mem_In("processResidualCoding_fx", sizeof(struct {
188 : Counter i;
189 : Word16 s, n, m;
190 : Word32 L_tmp;
191 : }));
192 : #endif
193 :
194 : n = 0;
195 : move16();
196 : {
197 : m = add(sub(targetBits, nBits), 4);
198 : if (m > L_spec)
199 : {
200 : m = L_spec;
201 : }
202 : }
203 :
204 :
205 : s = sub(add(15, gain_e), x_e);
206 : {
207 : FOR (i = 0; i < L_spec; i++)
208 : {
209 : IF (xq[i] != 0)
210 : {
211 : L_tmp = L_sub(x[i], L_shl(L_mult(xq[i], gain), s));
212 : if (L_tmp < 0)
213 : {
214 : resBits[n] = 0;
215 : move16();
216 : }
217 : if (L_tmp >= 0)
218 : {
219 : resBits[n] = 1;
220 : move16();
221 : }
222 : n = add(n, 1);
223 : IF (sub(n, m) == 0)
224 : {
225 : BREAK;
226 : }
227 : }
228 : }
229 : }
230 : *numResBits = n;
231 : move16();
232 :
233 : #ifdef DYNMEM_COUNT
234 : Dyn_Mem_Out();
235 : #endif
236 : }
237 :
238 : #endif
|