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 "functions.h"
13 :
14 0 : static LC3_INT32 change_bit_at_position(LC3_INT32 value, LC3_UINT8 bit_position, LC3_INT8 bit)
15 : {
16 0 : LC3_INT32 helper_mask = ~(1 << bit_position);
17 0 : LC3_INT32 tmp = value & helper_mask;
18 0 : tmp = tmp | (bit << bit_position);
19 0 : return tmp;
20 : }
21 :
22 0 : static void update_bit_and_byte_positions(LC3_INT16 longterm_analysis_counter_max_bytebuffer, LC3_INT8 *byte_position, LC3_INT8 *bit_position)
23 : {
24 0 : if (*bit_position == 29)
25 : {
26 0 : *bit_position = 0;
27 :
28 0 : if ((*byte_position - longterm_analysis_counter_max_bytebuffer) < -1)
29 : {
30 0 : *byte_position = *byte_position + 1;
31 : } else {
32 0 : *byte_position = 0;
33 : }
34 : } else {
35 0 : *bit_position = *bit_position + 1;
36 : }
37 0 : }
38 :
39 0 : static void array_insert_and_shift(LC3_INT32 *array, LC3_UINT8 value, LC3_INT16 longterm_analysis_counter_max, LC3_INT16 *overall_counter, LC3_INT8 *byte_position, LC3_INT8 *bit_position)
40 : {
41 0 : LC3_INT32 current_byte = 0;
42 :
43 0 : if (overall_counter != NULL)
44 : {
45 0 : *overall_counter = MIN(*overall_counter + 1, longterm_analysis_counter_max);
46 : }
47 :
48 0 : current_byte = array[*byte_position];
49 :
50 0 : current_byte = change_bit_at_position(current_byte, *bit_position, value);
51 :
52 0 : array[*byte_position] = current_byte;
53 0 : }
54 :
55 0 : static void array_calculate(LC3_INT32 *array_tdc, LC3_INT32 *array_ns, int length, LC3_INT16 *counter_tdc, LC3_INT16 *counter_ns, LC3_INT16 longterm_analysis_counter_max)
56 : {
57 : int i, k;
58 0 : LC3_INT32 current_byte_tdc = 0, current_byte_ns = 0;
59 0 : LC3_INT16 counter_loc_tdc = 0, counter_loc_ns = 0, counter_tmp = 0;
60 :
61 0 : for (i = length - 1; i >= 0; i--)
62 : {
63 0 : current_byte_tdc = array_tdc[i];
64 0 : current_byte_ns = array_ns[i];
65 :
66 0 : for (k = 0; k < 30; k++)
67 : {
68 0 : counter_loc_tdc += ((current_byte_tdc >> k) & 1);
69 0 : counter_loc_ns += ((current_byte_ns >> k) & 1);
70 0 : counter_tmp++;
71 :
72 : /* Break from both loops if full 2s buffer has been evaluated */
73 0 : if (counter_tmp >= longterm_analysis_counter_max)
74 : {
75 0 : i = -1;
76 0 : k = 30;
77 0 : break;
78 : }
79 : }
80 : }
81 :
82 0 : *counter_tdc = counter_loc_tdc;
83 0 : *counter_ns = counter_loc_ns;
84 0 : }
85 :
86 : static void plc_xcorr_lc(LC3_FLOAT *pcmbufHist, LC3_INT32 max_len_pcm_plc, LC3_INT32 pitch_int, LC3_INT32 framelength, LC3_INT32 frame_dms, LC3_INT32 fs, LC3_FLOAT *xcorr);
87 : static void spectral_centroid_lc(LC3_FLOAT *gains, LC3_INT32 tilt, const LC3_INT *bands_offset, LC3_INT32 bands_number, LC3_INT32 framelength, LC3_INT32 fs, LC3_FLOAT *sc);
88 :
89 0 : void processPlcClassify_fl(LC3_INT plcMeth, LC3_INT *concealMethod, LC3_INT32 *nbLostCmpt, LC3_INT32 bfi,
90 : LC3_FLOAT *xcorr, LC3_INT32 framelength, LC3_INT32 frame_dms, LC3_INT32 pitch_int,
91 : LC3_INT32 fs, const LC3_INT *band_offsets, LC3_INT32 bands_number, LC3_INT32 tilt, PlcAdvSetup *plcAd
92 : , LC3_INT32 hrmode
93 : )
94 : {
95 : LC3_FLOAT sc, class;
96 : int fs_idx_tmp;
97 :
98 0 : if (plcAd)
99 : {
100 0 : *xcorr = 0;
101 : }
102 :
103 0 : fs_idx_tmp = FS2FS_IDX(fs);
104 : /* Save statistics for 24 kHz, 48 kHz and 96 kHz */
105 0 : if ((bfi == 1) || ((bfi >= 0) && (bfi <= 2) && ((fs_idx_tmp == 2) || (fs_idx_tmp == 4) || (fs_idx_tmp == 5)))) /* Partial Concealment PC(bfi==2) requires allowing value 2 to pass thru as well */
106 : {
107 0 : if (bfi == 1)
108 : {
109 0 : *nbLostCmpt = *nbLostCmpt + 1;
110 : }
111 :
112 : /* Use pitch correlation at ltpf integer lag if available */
113 0 : if ((*nbLostCmpt == 1) || (bfi != 1) )/* PC(bfi==2) requires allowing 2 to pass thru as well */
114 : {
115 0 : *concealMethod = 4; /* Noise Substitution */
116 : UNUSED(plcMeth);
117 :
118 : /* Advanced PLC */
119 0 : if (pitch_int > 0)
120 : {
121 0 : *concealMethod = 3; /* Timedomain PLC assumed */
122 0 : plc_xcorr_lc(plcAd->pcmbufHist, plcAd->max_len_pcm_plc, pitch_int, framelength, frame_dms, fs, xcorr);
123 :
124 0 : spectral_centroid_lc(plcAd->scf_q_old, tilt, band_offsets, bands_number, framelength, fs, &sc);
125 0 : class = *xcorr * 7640.0 / 32768.0 - sc - 5112.0 / 32768.0;
126 :
127 0 : if (class <= 0)
128 : {
129 0 : if (frame_dms == 100 && hrmode == 0)
130 : {
131 0 : *concealMethod = 2; /* PhaseEcu selected */
132 0 : array_insert_and_shift(plcAd->plc_longterm_advc_tdc, 0, plcAd->longterm_analysis_counter_max, &plcAd->overall_counter, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position);
133 0 : array_insert_and_shift(plcAd->plc_longterm_advc_ns, 0, plcAd->longterm_analysis_counter_max, NULL, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position);
134 : }
135 : else
136 : {
137 0 : array_insert_and_shift(plcAd->plc_longterm_advc_tdc, 0, plcAd->longterm_analysis_counter_max, &plcAd->overall_counter, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position);
138 0 : array_insert_and_shift(plcAd->plc_longterm_advc_ns, 0, plcAd->longterm_analysis_counter_max, NULL, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position);
139 : }
140 : }
141 : else {
142 0 : array_insert_and_shift(plcAd->plc_longterm_advc_tdc, 1, plcAd->longterm_analysis_counter_max, &plcAd->overall_counter, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position);
143 0 : array_insert_and_shift(plcAd->plc_longterm_advc_ns, 0, plcAd->longterm_analysis_counter_max, NULL, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position);
144 : }
145 : }
146 : else
147 : {
148 0 : *concealMethod = 4; /* Noise Substitution */
149 0 : array_insert_and_shift(plcAd->plc_longterm_advc_tdc, 0, plcAd->longterm_analysis_counter_max, &plcAd->overall_counter, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position);
150 0 : array_insert_and_shift(plcAd->plc_longterm_advc_ns, 1, plcAd->longterm_analysis_counter_max, NULL, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position);
151 : }
152 :
153 0 : array_calculate(plcAd->plc_longterm_advc_tdc, plcAd->plc_longterm_advc_ns, plcAd->longterm_analysis_counter_max_bytebuffer, &plcAd->longterm_counter_plcTdc, &plcAd->longterm_counter_plcNsAdv, plcAd->longterm_analysis_counter_max);
154 0 : update_bit_and_byte_positions(plcAd->longterm_analysis_counter_max_bytebuffer, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position);
155 : }
156 : }
157 0 : }
158 :
159 0 : static void spectral_centroid_lc(LC3_FLOAT *gains, LC3_INT32 tilt, const LC3_INT *band_offsets, LC3_INT32 bands_number, LC3_INT32 framelength, LC3_INT32 fs, LC3_FLOAT *sc)
160 : {
161 : LC3_FLOAT gains_lin[M], gains_dee[M], numerator, denumerator;
162 : LC3_INT32 i, j, sum, len, start, stop;
163 : LC3_INT band_offsets_local[MAX_BANDS_NUMBER + 1];
164 :
165 0 : numerator = 0;
166 :
167 0 : for (i = 0; i < M; i++)
168 : {
169 0 : gains_lin[i] = LC3_POW(2, gains[i]);
170 : }
171 :
172 0 : for (i = 0; i < M; i++)
173 : {
174 0 : gains_dee[i] = gains_lin[i] / LC3_POW(10, i * (LC3_FLOAT) tilt / (LC3_FLOAT) (M - 1) / 10.0);
175 : }
176 :
177 0 : if (bands_number == 64)
178 : {
179 0 : memmove(band_offsets_local, band_offsets, (bands_number + 1) * sizeof(LC3_INT));
180 : }
181 :
182 0 : if (bands_number < 32)
183 : {
184 0 : band_offsets_local[0] = 0;
185 0 : j = 32 - bands_number;
186 0 : for (i = bands_number - 1; i >= j; i--)
187 : {
188 0 : band_offsets_local[(i + j) * 2 + 1 + 1] = band_offsets[i + 1];
189 0 : band_offsets_local[(i + j) * 2 + 0 + 1] = band_offsets[i + 1];
190 : }
191 0 : for (i = j - 1; i >= 0; i--)
192 : {
193 0 : band_offsets_local[i * 4 + 3 + 1] = band_offsets[i + 1];
194 0 : band_offsets_local[i * 4 + 2 + 1] = band_offsets[i + 1];
195 0 : band_offsets_local[i * 4 + 1 + 1] = band_offsets[i + 1];
196 0 : band_offsets_local[i * 4 + 0 + 1] = band_offsets[i + 1];
197 : }
198 : }
199 : else
200 0 : if (bands_number < 64)
201 : {
202 0 : band_offsets_local[0] = 0;
203 0 : j = 64 - bands_number;
204 0 : for (i = bands_number - 1; i >= j; i--)
205 : {
206 0 : band_offsets_local[i + j + 1] = band_offsets[i + 1];
207 : }
208 0 : for (i = j - 1; i >= 0; i--)
209 : {
210 0 : band_offsets_local[i * 2 + 1 + 1] = band_offsets[i + 1];
211 0 : band_offsets_local[i * 2 + 0 + 1] = band_offsets[i + 1];
212 : }
213 : }
214 :
215 0 : denumerator = 0.001;
216 :
217 0 : for (i = 0; i < M; i++)
218 : {
219 0 : sum = 0; len = 0;
220 0 : start = band_offsets_local[i * 4] + 1; stop = band_offsets_local[i * 4 + 4];
221 :
222 0 : for (j = stop; j >= start; j--)
223 : {
224 0 : sum += j;
225 0 : len++;
226 : }
227 :
228 0 : numerator += gains_dee[i] * ((LC3_FLOAT) sum / (LC3_FLOAT) framelength);
229 0 : denumerator += gains_dee[i] * len;
230 : }
231 :
232 0 : *sc = numerator / denumerator;
233 0 : *sc = *sc * (LC3_FLOAT) fs / 48000.0; /* scaling, because training is for 48kHz */
234 0 : }
235 :
236 0 : static void plc_xcorr_lc(LC3_FLOAT *pcmbufHist, LC3_INT32 max_len_pcm_plc, LC3_INT32 pitch_int, LC3_INT32 framelength,
237 : LC3_INT32 frame_dms, LC3_INT32 fs, LC3_FLOAT *xcorr)
238 : {
239 : LC3_INT32 max_corr_len, pitch_min, corr_len, min_corr_len, pcm_max_corr_len, range1Start, range2Start, i;
240 : LC3_FLOAT norm_w, norm_w_t;
241 :
242 0 : norm_w_t = 0; norm_w = 0;
243 :
244 0 : assert(pitch_int >= 0);
245 0 : assert(pitch_int <= MAX_LEN*100*MAX_PITCH_12K8/12800);
246 :
247 0 : *xcorr = 0;
248 :
249 0 : if (pitch_int > 0)
250 : {
251 0 : pitch_min = fs * MIN_PITCH_12K8/12800;
252 0 : pcm_max_corr_len = max_len_pcm_plc - pitch_int;
253 :
254 0 : min_corr_len = 2 * pitch_min; /* at least 5 ms (=2*pitchmin*) corr length */
255 0 : max_corr_len = framelength*100/frame_dms; /* maximum 10 ms */
256 0 : max_corr_len = MIN( max_corr_len, pcm_max_corr_len );
257 :
258 0 : corr_len = MIN( max_corr_len, pitch_int ); /* pitch_int is prefered, but maximum 10ms or left pcm buf size */
259 0 : corr_len = MAX( min_corr_len, corr_len );
260 :
261 0 : range1Start = max_len_pcm_plc - corr_len;
262 0 : range2Start = range1Start - pitch_int;
263 :
264 0 : assert( corr_len >= min_corr_len );
265 0 : assert( corr_len <= max_corr_len );
266 0 : assert( range2Start >= 0 );
267 :
268 0 : for (i = 0; i < corr_len; i++)
269 : {
270 0 : norm_w += pcmbufHist[range1Start + i] * pcmbufHist[range1Start + i];
271 : }
272 :
273 0 : for (i = 0; i < corr_len; i++)
274 : {
275 0 : norm_w_t += pcmbufHist[range2Start + i] * pcmbufHist[range2Start + i];
276 : }
277 :
278 0 : for (i = 0; i < corr_len; i++)
279 : {
280 0 : *xcorr = *xcorr + pcmbufHist[range1Start + i] * pcmbufHist[range2Start + i];
281 : }
282 :
283 0 : *xcorr = *xcorr / sqrt(norm_w * norm_w_t + 0.1);
284 0 : *xcorr = MAX(0, *xcorr);
285 : } else {
286 0 : *xcorr = 0;
287 : }
288 0 : }
289 :
|