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 "options.h"
11 : #include "wmc_auto.h"
12 : #include "defines.h"
13 : #include "functions.h"
14 :
15 : #define BETA_MUTE_FAC 0.5 /* % attenuation factor per additional bad frame, FX uses 0.5 (shift right with 1 bit) */
16 : #define BETA_MUTE_FAC_INI 0.5
17 : #define OFF_FRAMES_LIMIT 30 /* 300 ms for LC3 10 ms */
18 : #define LGW32k 7
19 : #define LGW16k 5
20 :
21 : /* Tables for attentuation of mag_chg, copied from FX */
22 : /* Tables are in Q15 */
23 : /* 0.3 dB attenuation per frame for 16 frames, then 6 dB attenuation per frame */
24 : const LC3_INT32 POW_ATT_TABLE1[OFF_FRAMES_LIMIT + 1] = { 32767, 31656, 30581, 29543, 28540, 27571, 26635, 25731, 24857, 24013,
25 : 23198, 22410, 21650, 20915, 20205, 19519, 9759, 4880, 2440, 1220,
26 : 610, 305, 152, 76, 38, 19, 10, 5, 2, 1,
27 : 0 };
28 : /* % 0.4 dB attenuation per frame for 16 frames, then 6 dB attenuation per frame */
29 : const LC3_INT32 POW_ATT_TABLE0[OFF_FRAMES_LIMIT + 1] = { 32767, 31293, 29885, 28540, 27255, 26029, 24857, 23738, 22670, 21650,
30 : 20675, 19745, 18856, 18007, 17197, 16423, 8211, 4106, 2053, 1026,
31 : 513, 257, 128, 64, 32, 16, 8, 4, 2, 1,
32 : 0 };
33 :
34 : #ifdef PLC2_FADEOUT_IN_MS
35 : #if PLC2_FADEOUT_IN_MS == 0
36 : #else
37 :
38 : const LC3_INT32 POW_ATT_TABLE_p3x9_14_7[OFF_FRAMES_LIMIT + 1] = {
39 : 32767,
40 : 31656, 30581, 29543, 28540, 27571, 26635, 25731, 24857, 24013, /* 9 times .3dB steps , 14 6 dB steps, 7 muted steps */
41 : 12007, 6003, 3002, 1501, 750, 375, 188, 94, 47, 23, 12, 6, 3, 1,
42 : 0, 0, 0, 0, 0, 0, 0 };
43 :
44 : const LC3_INT32 POW_ATT_TABLE_p4x9_14_7[OFF_FRAMES_LIMIT + 1] =
45 : { 32767,
46 : 31293, 29885, 28540, 27255, 26029, 24857, 23738, 22670, 21650, /* 9 times .4dB steps , 14 6 dB steps, 7 muted steps */
47 : 10825, 5413, 2706, 1353, 677, 338, 169, 85, 42, 21, 11, 5, 3, 1,
48 : 0, 0,0,0,0,0,0 };
49 :
50 : const LC3_INT32 POW_ATT_TABLE_p3x8_6[] = {
51 : 32767, 31656, 30581, 29543, 28540, 27571, 26635, 25731, 12865, 6433,
52 : 3216, 1608, 804, 402, 201, 101, 50, 25, 13, 6,
53 : 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
54 : const LC3_INT32 POW_ATT_TABLE_p4x8_6[OFF_FRAMES_LIMIT + 1] = {
55 : 32767, 31293, 29885, 28540, 27255, 26029, 24857, 23738, 11869, 5935,
56 : 2967, 1484, 742, 371, 185, 93, 46, 23, 12, 6,
57 : 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
58 :
59 : const LC3_INT32 POW_ATT_TABLE_p3x4_6[OFF_FRAMES_LIMIT + 1] = {
60 : 32767, 31656, 30581, 29543, 14772, 7386, 3693, 1847, 923, 462,
61 : 231, 115, 58, 29, 14, 7, 4, 2, 1, 0,
62 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
63 : const LC3_INT32 POW_ATT_TABLE_p4x4_6[OFF_FRAMES_LIMIT + 1] = {
64 : 32767, 31293, 29885, 28540, 14270, 7135, 3568, 1784, 892, 446,
65 : 223, 111, 56, 28, 14, 7, 3, 2, 1, 0,
66 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
67 :
68 : const LC3_INT32 POW_ATT_TABLE_p3x2_6[OFF_FRAMES_LIMIT + 1] = {
69 : 32767, 31656, 15828, 7914, 3957, 1979, 989, 495, 247, 124,
70 : 62, 31, 15, 8, 4, 2, 1, 0, 0, 0,
71 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
72 : const LC3_INT32 POW_ATT_TABLE_p4x2_6[OFF_FRAMES_LIMIT + 1] = {
73 : 32767, 31293, 15647, 7823, 3912, 1956, 978, 489, 244, 122,
74 : 61, 31, 15, 8, 4, 2, 1, 0, 0, 0,
75 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
76 :
77 : const LC3_INT32 POW_ATT_TABLE_p3x1_6[OFF_FRAMES_LIMIT + 1] = {
78 : 32767, 16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64,
79 : 32, 16, 8, 4, 2, 1, 1, 0, 0, 0,
80 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
81 : const LC3_INT32 POW_ATT_TABLE_p4x1_6[OFF_FRAMES_LIMIT + 1] = {
82 : 32767, 16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64,
83 : 32, 16, 8, 4, 2, 1, 1, 0, 0, 0,
84 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
85 :
86 : const LC3_INT32 *const POW_ATT_TABLES[1 + 12] =
87 : { NULL,
88 : /*0.3dB col , 0.4dB col */
89 : /* 1*/POW_ATT_TABLE_p3x1_6, POW_ATT_TABLE_p4x1_6, /* 0 0.3dB, 16 6dB, 14mute */ /* 0.4dB version */ /* old short mute tabs */
90 : /* 3*/POW_ATT_TABLE_p3x2_6, POW_ATT_TABLE_p4x2_6, /* 1 0.3dB, 15 6dB ,14mute */ /* 0.4dB version */
91 : /* 5*/POW_ATT_TABLE_p3x4_6, POW_ATT_TABLE_p4x4_6, /* 3 0.3dB, 15 6dB , 12 mute */ /* 0.4dB version */
92 : /* 7*/POW_ATT_TABLE_p3x8_6, POW_ATT_TABLE_p4x8_6, /* 7 0.3dB, 15 6dB , 8 mute */ /* 0.4dB version */
93 : /* 9*/POW_ATT_TABLE_p3x9_14_7, POW_ATT_TABLE_p4x9_14_7, /* 9 0.3dB, 14 6dB , 7 mute */ /* 0.4dB version */ /* opt 120 ms */
94 : /*11*/POW_ATT_TABLE1, POW_ATT_TABLE0, /* 15 0.3dB, 14 6dB , 1 mute */ /* 0.4dB version */ /* original curves */
95 : };
96 :
97 : #endif
98 : #endif
99 :
100 0 : void plc_phEcu_tba_trans_dect_gains(LC3_INT32 burst_len, LC3_INT32 n_grp, LC3_FLOAT *grp_pow_change,
101 : LC3_FLOAT *stPhECU_beta_mute, LC3_FLOAT *stPhECU_mag_chg_1st,
102 : LC3_FLOAT *alpha, LC3_FLOAT *beta, LC3_FLOAT *mag_chg, LC3_FLOAT *ph_dith, LC3_INT32 *tr_dec,
103 : LC3_FLOAT *att_val, LC3_INT32 *attDegreeFrames_dbg, LC3_FLOAT *thresh_dbg
104 : , LC3_UINT8 plc_fadeout_type
105 : )
106 : {
107 :
108 : LC3_INT32 i;
109 : LC3_FLOAT thresh_tr_dB, max_increase_grp_pow;
110 : LC3_FLOAT max_increase_grp_pow_lin;
111 : LC3_FLOAT grp_pow_change_lin[MAX_LGW];
112 : LC3_FLOAT XavgFadeinFactor;
113 :
114 : LC3_INT32 burst_att_thresh;
115 : LC3_INT32 att_per_frame_idx;
116 : LC3_INT32 att_always, attDegreeFrames;
117 : const LC3_INT32 *TABLEQ15;
118 : LC3_INT32 beta_mute_thr; /* time threshold in 10 ms frames to start beta - noise attenuation */
119 : UNUSED(attDegreeFrames_dbg);
120 :
121 : /* constants setup */
122 0 : att_always = 0;
123 :
124 0 : XavgFadeinFactor = -1.0;
125 :
126 : /* 10ms constants */
127 0 : thresh_tr_dB = 10.0; /* dB threshold kept same as for 20ms, even though transient analysis frame size was shortened */
128 0 : max_increase_grp_pow = 0; /* maximum amplification(dB) in case of onset transients, offset always deacy */
129 :
130 0 : max_increase_grp_pow_lin = (LC3_FLOAT)1.0*LC3_POW((LC3_FLOAT)10.0, max_increase_grp_pow / (LC3_FLOAT)10.0)*(LC3_FLOAT)(32767.0 / 32768.0);
131 :
132 0 : if (plc_fadeout_type != 0)
133 : {
134 0 : i = (PLC2_FADEOUT_LONG_IN_MS - PLC2_FADEOUT_IN_MS_MIN) / PLC2_FADEOUT_RES; /*a long fading table entry in fade_scheme_tab */
135 : } else {
136 0 : i = (PLC2_FADEOUT_IN_MS - PLC2_FADEOUT_IN_MS_MIN) / PLC2_FADEOUT_RES; /* a shorter fading entry in fade_scheme_tab */
137 : }
138 0 : assert(i >= 0 && i <= ((PLC2_FADEOUT_IN_MS_MAX - PLC2_FADEOUT_IN_MS_MIN) / PLC2_FADEOUT_RES) && "fade_scheme_tab index error");
139 :
140 0 : att_per_frame_idx = fade_scheme_tab[i][0];
141 0 : burst_att_thresh = fade_scheme_tab[i][1]; /* number of 1.0 frames before muting/mixing phase */
142 : /* band gain muting may can take place earlier due to a band transient */
143 0 : beta_mute_thr = fade_scheme_tab[i][2]; /* muting of Xavg contribution start when slow fadeout is over */
144 :
145 0 : attDegreeFrames = 0;
146 0 : if (burst_len > burst_att_thresh)
147 : {
148 0 : att_always = 1;
149 :
150 : /* Added to be able to able to use tables to be aligned with FX */
151 : /* Limit attDegreeFrames to OFF_FRAMES_LIMIT */
152 0 : attDegreeFrames = burst_len - burst_att_thresh;
153 :
154 0 : if (attDegreeFrames > OFF_FRAMES_LIMIT)
155 : {
156 0 : attDegreeFrames = OFF_FRAMES_LIMIT;
157 : }
158 : }
159 :
160 :
161 0 : set_vec(1.0 * (32767.0/32768.0), mag_chg, n_grp);
162 0 : set_vec(0.0, ph_dith, n_grp);
163 :
164 0 : set_vec(1.0 * (32767.0/32768.0), alpha, n_grp);
165 0 : set_vec(0.0, beta, n_grp);
166 0 : set_vec_int(0, tr_dec, n_grp);
167 :
168 0 : set_vec(1.0 * (32767.0/32768.0), att_val, n_grp);
169 :
170 :
171 :
172 : /* transient detection per band */
173 0 : for (i = 0;i < n_grp; i++) {
174 0 : if(burst_len == 1)
175 : {
176 : /* first bad frame */
177 0 : grp_pow_change_lin[i] = LC3_POW((LC3_FLOAT)10.0, grp_pow_change[i]/(LC3_FLOAT)10.0);
178 :
179 0 : *stPhECU_beta_mute = BETA_MUTE_FAC_INI;
180 0 : *stPhECU_beta_mute = *stPhECU_beta_mute / (LC3_FLOAT)2.0;
181 :
182 : /* transient processing */
183 : /* transients may be both rise and decay transients !! */
184 :
185 0 : if(LC3_FABS(grp_pow_change[i]) >= thresh_tr_dB)
186 : {
187 :
188 0 : tr_dec[i] = 1;
189 : }
190 :
191 :
192 : /* magnitude modification */
193 0 : att_val[i] = 0.0f;
194 0 : if(tr_dec[i] || att_always) {
195 :
196 0 : att_val[i] = MIN(max_increase_grp_pow_lin, grp_pow_change_lin[i]); /* % linear values !! */
197 0 : att_val[i] = LC3_SQRT(att_val[i]);
198 0 : mag_chg[i] = att_val[i];
199 0 : stPhECU_mag_chg_1st[i] = att_val[i];
200 : }
201 : else
202 : {
203 0 : mag_chg[i] = 1.0 * (LC3_FLOAT)(32767.0/32768.0);
204 0 : stPhECU_mag_chg_1st[i] = (LC3_FLOAT)1.0;
205 : }
206 : }
207 : else
208 : {
209 : /* burst handling based on states */
210 :
211 0 : assert(burst_len >= 2); /* states used here */
212 0 : tr_dec[i] = 0;
213 :
214 : {
215 0 : assert(att_per_frame_idx >= 1 && att_per_frame_idx <= (10+2));
216 0 : TABLEQ15 = POW_ATT_TABLES[att_per_frame_idx];
217 0 : att_val[i] = (LC3_FLOAT)1.0 * ( (LC3_FLOAT) TABLEQ15[MIN(OFF_FRAMES_LIMIT, attDegreeFrames )] / (LC3_FLOAT)32768.0); /* Table idx 0...N-1 therefore no + 1 */
218 0 : att_val[i] = att_val[i];
219 : }
220 :
221 0 : if ( (att_val[i] != 0) && (att_val[i] * (LC3_FLOAT)32768.0 < (LC3_FLOAT)0.5) )
222 : {
223 0 : att_val[i] = 0.0; /* for SNR measurments match in float lowest possible level to BASOP representation */
224 : }
225 :
226 : /* Apply attenuation */
227 0 : mag_chg[i] = stPhECU_mag_chg_1st[i];
228 :
229 0 : mag_chg[i] = mag_chg[i] * att_val[i]; /* add additional attenuation from burst attenation logic */
230 :
231 0 : if ((mag_chg[i] != 0) && (mag_chg[i] * (LC3_FLOAT)32768.0 < (LC3_FLOAT)0.5))
232 : {
233 0 : mag_chg[i] = 0; /* for SNR measurments match in float lowest possible level to BASOP representation */
234 : }
235 :
236 : /* note beta_mute decreased once per frame, not once per band */
237 0 : if (i == 0 && burst_len > beta_mute_thr)
238 : {
239 0 : *stPhECU_beta_mute = *stPhECU_beta_mute * (LC3_FLOAT)BETA_MUTE_FAC;
240 : }
241 :
242 0 : alpha[i] = mag_chg[i];
243 :
244 0 : if (alpha[i] >= (LC3_FLOAT)(32766.0 / 32768.0))
245 : {
246 0 : beta[i] = 0; /* align to BASOP more efficent use of beta */
247 : }
248 : else
249 : {
250 0 : beta[i] = LC3_SQRT((LC3_FLOAT)1.0 - alpha[i]* alpha[i]) * *stPhECU_beta_mute;
251 : }
252 :
253 0 : if ( i >= LGW32k-1) {
254 0 : beta[i] = beta[i] * (LC3_FLOAT)0.1;
255 : }
256 0 : else if( i >= LGW16k-1)
257 : {
258 0 : beta[i] = beta[i] * (LC3_FLOAT)0.5;
259 : }
260 :
261 :
262 : /* limit Xavg noise contribution further in case of offset / tr_decay */
263 :
264 0 : if ((burst_len <= burst_att_thresh) && (stPhECU_mag_chg_1st[i] < (LC3_FLOAT)(32767.0 / 32768.0)))
265 : {
266 0 : XavgFadeinFactor = (LC3_FLOAT)(burst_len - (LC3_FLOAT)1.0) / burst_att_thresh;
267 :
268 0 : XavgFadeinFactor = MIN((LC3_FLOAT)1.0, XavgFadeinFactor);
269 :
270 0 : beta[i] = beta[i] * XavgFadeinFactor;
271 :
272 : }
273 : }
274 : }
275 :
276 0 : if (thresh_dbg != NULL)
277 : {
278 0 : *thresh_dbg = XavgFadeinFactor;
279 : }
280 :
281 0 : return;
282 : }
283 :
|