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 :
13 0 : void processNoiseFactor_fx(Word16 *fac_ns_idx, Word16 x_e, Word32 x[],
14 : #ifdef ENABLE_HR_MODE
15 : Word32 xq[],
16 : #else
17 : Word16 xq[],
18 : #endif
19 : Word16 gg, Word16 gg_e, Word16 BW_cutoff_idx, Word16 frame_dms, Word16 target_bytes,
20 : Word8 *scratchBuffer
21 : #ifdef ENABLE_HR_MODE
22 : ,Word16 hrmode
23 : #endif
24 : )
25 : {
26 : Dyn_Mem_Deluxe_In(Counter k; Word16 nzeros, s1, s2, s3, c, idx, fac_unq, *ind;
27 : Word16 noisefillwidth, noisefillstart, N; Word32 Lsum;);
28 :
29 :
30 :
31 0 : ind = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * MAX_LEN bytes */
32 :
33 0 : noisefillwidth = 0;
34 0 : noisefillstart = 0;
35 0 : c = 0;
36 0 : move16();
37 :
38 : #ifdef ENABLE_HR_MODE
39 0 : if (hrmode)
40 : {
41 0 : N = BW_cutoff_bin_all_HR[BW_cutoff_idx];
42 0 : move16();
43 : }
44 : else
45 : #endif
46 : {
47 0 : N = BW_cutoff_bin_all[BW_cutoff_idx];
48 0 : move16();
49 : }
50 :
51 0 : SWITCH (frame_dms)
52 : {
53 0 : case 25:
54 0 : N = shr_pos(N, 2);
55 0 : noisefillwidth = NOISEFILLWIDTH_2_5MS;
56 0 : noisefillstart = NOISEFILLSTART_2_5MS;
57 0 : BREAK;
58 0 : case 50:
59 0 : N = shr_pos(N, 1);
60 0 : noisefillwidth = NOISEFILLWIDTH_5MS;
61 0 : noisefillstart = NOISEFILLSTART_5MS;
62 0 : BREAK;
63 0 : case 75:
64 0 : N = add(shr_pos(N, 2), add(shr_pos(N, 2), shr_pos(N, 2)));
65 0 : noisefillwidth = NOISEFILLWIDTH_7_5MS;
66 0 : noisefillstart = NOISEFILLSTART_7_5MS;
67 0 : BREAK;
68 0 : case 100:
69 0 : noisefillwidth = NOISEFILLWIDTH;
70 0 : noisefillstart = NOISEFILLSTART;
71 0 : BREAK;
72 : }
73 :
74 0 : nzeros = -2 * noisefillwidth - 1;
75 0 : move16();
76 :
77 0 : FOR (k = noisefillstart - noisefillwidth; k < noisefillstart + noisefillwidth; k++)
78 : {
79 0 : if (xq[k] != 0)
80 : {
81 0 : nzeros = -2 * noisefillwidth - 1;
82 0 : move16();
83 : }
84 0 : if (xq[k] == 0)
85 : {
86 0 : nzeros = add(nzeros, 1);
87 : }
88 : }
89 :
90 0 : FOR (k = noisefillstart; k < N - noisefillwidth; k++)
91 : {
92 0 : if (xq[k + noisefillwidth] != 0)
93 : {
94 0 : nzeros = -2 * noisefillwidth - 1;
95 0 : move16();
96 : }
97 0 : if (xq[k + noisefillwidth] == 0)
98 : {
99 0 : nzeros = add(nzeros, 1);
100 : }
101 0 : if (nzeros >= 0)
102 : {
103 0 : ind[c++] = k;
104 0 : move16();
105 : }
106 : }
107 :
108 0 : FOR (k = N - noisefillwidth; k < N; k++)
109 : {
110 0 : nzeros = add(nzeros, 1);
111 0 : if (nzeros >= 0)
112 : {
113 0 : ind[c++] = k;
114 0 : move16();
115 : }
116 : }
117 :
118 0 : IF (c == 0)
119 : {
120 0 : fac_unq = 0;
121 0 : move16();
122 : }
123 : ELSE
124 : {
125 :
126 0 : IF (target_bytes <= 20 && frame_dms == 100)
127 0 : {
128 : Word32 ind_sum;
129 : Word16 mean_ind;
130 :
131 : Word16 fac_unq1, fac_unq2;
132 :
133 : /* calculate mean index */
134 0 : ind_sum = ind[0];
135 0 : move32();
136 0 : FOR (k = 1; k < c; k++)
137 : {
138 0 : ind_sum = L_add(ind_sum, ind[k]);
139 : }
140 :
141 0 : mean_ind = BASOP_Util_Divide3216_Scale_lc3plus(ind_sum, c, &s2);
142 0 : mean_ind = shl(mean_ind, s2 + 1);
143 :
144 0 : assert(0 <= mean_ind && mean_ind <= ind[c - 1]);
145 :
146 : /* calculate noise filling gain for low frequencies */
147 0 : s2 = 0; move16();
148 0 : if (sub(mean_ind, ind[0]) > 0)
149 : {
150 : /* calculate scale to ensure that Lsum does not overflow */
151 0 : s2 = s_max(sub(sub(14, norm_s(c)), getScaleFactor32_lc3plus(&x[ind[0]], sub(mean_ind, ind[0]))), 0);
152 : }
153 0 : Lsum = L_shr_pos_pos(L_abs(x[ind[0]]), s2);
154 :
155 0 : FOR (k = 1; k < c && ind[k] <= mean_ind; k++)
156 : {
157 : /* scale before adding to Lsum */
158 0 : Lsum = L_add(Lsum, L_shr_pos_pos(L_abs(x[ind[k]]), s2));
159 : }
160 0 : fac_unq1 = BASOP_Util_Divide3216_Scale_lc3plus(Lsum, k, &s1);
161 : /* add scale applied during summing */
162 0 : s1 = add(s1, s2);
163 0 : fac_unq1 = BASOP_Util_Divide1616_Scale_lc3plus(fac_unq1, gg, &s2);
164 0 : s3 = sub(15, add(x_e, add(s1, sub(s2, gg_e))));
165 0 : s2 = norm_s(fac_unq1);
166 0 : test();
167 0 : IF (fac_unq1 != 0 && add(s3, s2) < 0)
168 : {
169 0 : fac_unq1 = MAX_16;
170 0 : move16();
171 : }
172 : ELSE
173 : {
174 0 : s3 = s_min(s_max(s3, -15), 15);
175 0 : fac_unq1 = shr_r(fac_unq1, s3);
176 : }
177 :
178 : /* calculate noise filling gain for high frequencies */
179 0 : Lsum = 0;
180 0 : move16();
181 0 : idx = sub(c, k);
182 0 : FOR (; k < c; k++)
183 : {
184 0 : Lsum = L_add(Lsum, L_abs(x[ind[k]]));
185 : }
186 0 : fac_unq2 = BASOP_Util_Divide3216_Scale_lc3plus(Lsum, idx, &s1);
187 0 : fac_unq2 = BASOP_Util_Divide1616_Scale_lc3plus(fac_unq2, gg, &s2);
188 0 : s3 = sub(15, add(x_e, add(s1, sub(s2, gg_e))));
189 0 : s2 = norm_s(fac_unq1);
190 0 : test();
191 0 : IF (fac_unq2 != 0 && add(s3, s2) < 0)
192 : {
193 0 : fac_unq2 = MAX_16;
194 0 : move16();
195 : }
196 : ELSE
197 : {
198 0 : s3 = s_min(s_max(s3, -15), 15);
199 0 : fac_unq2 = shr_r(fac_unq2, s3);
200 : }
201 :
202 : /* calculate noise filling gain as minimum over high and low frequencies */
203 0 : fac_unq = s_min(fac_unq1, fac_unq2);
204 : }
205 : ELSE
206 : {
207 : /* calculate scale to ensure that Lsum does not overflow */
208 0 : s2 = s_max(sub(sub(14, norm_s(c)), getScaleFactor32_lc3plus(&x[ind[0]], sub(N,ind[0]))), 0);
209 0 : Lsum = L_abs(x[ind[0]]);
210 0 : FOR (k = 1; k < c; k++)
211 : {
212 : /* scale before adding to Lsum */
213 0 : Lsum = L_add(Lsum, L_shr_pos_pos(L_abs(x[ind[k]]), s2));
214 : }
215 0 : fac_unq = BASOP_Util_Divide3216_Scale_lc3plus(Lsum, c, &s1);
216 : /* add scale applied during summing */
217 0 : s1 = add(s1, s2);
218 0 : fac_unq = BASOP_Util_Divide1616_Scale_lc3plus(fac_unq, gg, &s2);
219 0 : s3 = sub(15, add(x_e, add(s1, sub(s2, gg_e))));
220 0 : s2 = norm_s(fac_unq);
221 0 : test();
222 0 : IF (fac_unq != 0 && add(s3, s2) < 0)
223 : {
224 0 : fac_unq = MAX_16;
225 0 : move16();
226 : }
227 : ELSE
228 : {
229 0 : fac_unq = shr_r(fac_unq, s_max(s_min(s3, 15), -15));
230 : }
231 : }
232 : }
233 :
234 0 : idx = round_fx(L_sub(0x80000, L_mult(fac_unq, 16)));
235 0 : if (sub(idx, 7) > 0)
236 : {
237 0 : idx = 7;
238 0 : move16();
239 : }
240 0 : if (idx < 0)
241 : {
242 0 : idx = 0;
243 0 : move16();
244 : }
245 0 : *fac_ns_idx = idx;
246 0 : move16();
247 :
248 : Dyn_Mem_Deluxe_Out();
249 0 : }
250 :
|