Line data Source code
1 : /******************************************************************************************************
2 :
3 : (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
4 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
5 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
6 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
7 : contributors to this repository. All Rights Reserved.
8 :
9 : This software is protected by copyright law and by international treaties.
10 : The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
11 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
12 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
13 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
14 : contributors to this repository retain full ownership rights in their respective contributions in
15 : the software. This notice grants no license of any kind, including but not limited to patent
16 : license, nor is any license granted by implication, estoppel or otherwise.
17 :
18 : Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
19 : contributions.
20 :
21 : This software is provided "AS IS", without any express or implied warranties. The software is in the
22 : development stage. It is intended exclusively for experts who have experience with such software and
23 : solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
24 : and fitness for a particular purpose are hereby disclaimed and excluded.
25 :
26 : Any dispute, controversy or claim arising under or in relation to providing this software shall be
27 : submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
28 : accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
29 : the United Nations Convention on Contracts on the International Sales of Goods.
30 :
31 : *******************************************************************************************************/
32 :
33 : /*====================================================================================
34 : EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
35 : ====================================================================================*/
36 :
37 : #include <stdint.h>
38 : #include "options.h"
39 : #ifdef DEBUGGING
40 : #include "debug.h"
41 : #endif
42 : #include "rom_com.h"
43 : #include "prot.h"
44 : #include "cnst.h"
45 : #include "basop_util.h"
46 : #include "basop_proto_func.h"
47 : #include "wmc_auto.h"
48 :
49 : /*---------------------------------------------------------------------*
50 : * tcq_core_LR_enc()
51 : *
52 : * Main Generic Audio Encoder Routine for LR-MDCT
53 : *---------------------------------------------------------------------*/
54 :
55 34 : ivas_error tcq_core_LR_enc(
56 : BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */
57 : #ifdef DEBUGGING
58 : const int16_t idchan,
59 : #endif
60 : int32_t inp_vector[],
61 : const float coefs_norm[],
62 : float coefs_quant[],
63 : const int16_t bit_budget, /* number of bits */
64 : const int16_t BANDS,
65 : const int16_t *sfm_start,
66 : const int16_t *sfm_end,
67 : const int16_t *sfmsize,
68 : Word32 *Rk_fx,
69 : int16_t *npulses,
70 : int16_t *k_sort,
71 : const int16_t *p2a_flags,
72 : const int16_t p2a_bands,
73 : const int16_t *last_bitalloc,
74 : const int16_t input_frame,
75 : const int16_t adjustFlag,
76 : const int16_t is_transient )
77 : {
78 : int16_t i, j, k, size, nb_bytes;
79 : int32_t nzp;
80 :
81 : float gain;
82 : float step_scale[NB_SFM];
83 :
84 : int16_t pos_index[NB_SFM];
85 : float Rk_sort[NB_SFM];
86 : int16_t USQ_TCQ[NB_SFM]; /* TCQ is selected by default*/
87 : float coefs_norm_dec[L_FRAME32k]; /* New output buffer (TCQ+USQ)*/
88 :
89 : float pulses, crosscorr, selfcorr;
90 : int32_t savedstates[TCQ_MAX_BAND_SIZE];
91 : ARCODEC arenc, *parenc;
92 : TCQ_BITSTREAM bs, *pbs;
93 : int16_t k_num[2];
94 :
95 34 : int8_t flag_wbnb = 0;
96 34 : int16_t lsbtcq_bits = TCQ_AMP;
97 34 : int16_t tcq_arbits = 2;
98 34 : int16_t nzbands = 0;
99 34 : int16_t bcount = 0;
100 : float abuffer[560];
101 : float mbuffer[560];
102 : float sbuffer[560];
103 : int16_t dpath[280];
104 : /*Word32 Rk_fx[NB_SFM];*/ /* Q16 */
105 : Word32 Rk_sort_fx[NB_SFM]; /* Q16 */
106 34 : Word32 bsub_fx = 0;
107 : Word32 est_frame_bits_fx;
108 :
109 34 : Word16 nzb = 0;
110 : Word32 delta_fx;
111 : Word32 surplus_fx;
112 : Word32 bit_surplus_fx[2];
113 :
114 34 : Word32 leftbits = 0;
115 34 : Word32 sepbits = 0;
116 34 : Word32 divider = 0;
117 :
118 : ivas_error error;
119 :
120 34 : error = IVAS_ERR_OK;
121 :
122 34 : set_s( dpath, 0, 280 );
123 34 : set_f( abuffer, 0.f, 560 );
124 34 : set_f( mbuffer, 0.f, 560 );
125 :
126 34 : set_f( sbuffer, FLT_MAX, 560 );
127 :
128 : /* initialization */
129 34 : set_f( Rk_sort, 0.f, NB_SFM );
130 34 : set_s( USQ_TCQ, 0, NB_SFM );
131 34 : set_f( coefs_norm_dec, 0.f, L_FRAME32k );
132 34 : InitLSBTCQ( &bcount );
133 :
134 34 : if ( input_frame <= L_FRAME16k && adjustFlag == 0 && is_transient == 0 )
135 : {
136 0 : flag_wbnb = 1;
137 0 : lsbtcq_bits = 0;
138 0 : tcq_arbits = 0;
139 : }
140 :
141 34 : parenc = &arenc;
142 34 : pbs = &bs;
143 :
144 34 : pbs->curPos = 7;
145 34 : pbs->numbits = 0;
146 34 : pbs->numByte = 0;
147 34850 : for ( i = 0; i < MAX_SIZEBUF_PBITSTREAM; i++ )
148 : {
149 34816 : pbs->buf[i] = 0;
150 : }
151 :
152 34 : ar_encoder_start( parenc, pbs, bit_budget );
153 :
154 : /* TCQ Index initialize */
155 34 : set_s( pos_index, 0, NB_SFM );
156 :
157 : /* Bits distribution analysis */
158 812 : for ( i = 0; i < BANDS; i++ )
159 : {
160 778 : if ( L_sub( ar_div( Rk_fx[i], sfmsize[i] ), 49152 ) >= 0 )
161 : {
162 : /* USQ used for high importance bands*/
163 291 : USQ_TCQ[i] = 1;
164 : }
165 : else
166 : {
167 : /* TCQ used for usual bands */
168 487 : USQ_TCQ[i] = 0;
169 : }
170 778 : if ( Rk_fx[i] > 0 )
171 : {
172 549 : nzbands++;
173 : }
174 : }
175 :
176 812 : for ( j = 0; j < BANDS; j++ )
177 : {
178 778 : if ( Rk_fx[j] > 0 )
179 : {
180 549 : nzb++;
181 : }
182 : }
183 :
184 : #define WMC_TOOL_SKIP
185 34 : bsub_fx = L_shl( L_add( tcq_arbits, lsbtcq_bits ), 16 );
186 34 : IF( bsub_fx > 0 )
187 : {
188 34 : bsub_fx = L_add( bsub_fx, 2048 );
189 : }
190 812 : for ( j = BANDS - 1; j >= 0; j-- )
191 : {
192 778 : if ( Rk_fx[j] > 0 )
193 : {
194 549 : Rk_fx[j] = L_sub( Rk_fx[j], ar_div( bsub_fx, nzb ) );
195 549 : if ( Rk_fx[j] < 0 )
196 : {
197 0 : bsub_fx = L_sub( bsub_fx, L_add( ar_div( bsub_fx, nzb ), Rk_fx[j] ) );
198 0 : Rk_fx[j] = 0;
199 : }
200 : else
201 : {
202 549 : bsub_fx = L_sub( bsub_fx, ar_div( bsub_fx, nzb ) );
203 : }
204 549 : nzb = sub( nzb, 1 );
205 : }
206 : }
207 :
208 34 : srt_vec_ind_fx( Rk_fx, Rk_sort_fx, k_sort, BANDS );
209 : #undef WMC_TOOL_SKIP
210 :
211 : /* Quantize spectral band shapes using TCQ */
212 : /* Select ISC */
213 34 : set_f( coefs_quant, 0.0, sfm_end[BANDS - 1] + 1 );
214 :
215 34 : mvr2r( coefs_norm, coefs_quant, sfm_end[BANDS - 1] + 1 );
216 :
217 34 : delta_fx = 0;
218 34 : est_frame_bits_fx = 0;
219 34 : if ( input_frame <= L_FRAME16k && adjustFlag == 0 && is_transient == 0 )
220 : {
221 0 : surplus_fx = -131072;
222 0 : bit_allocation_second_fx( Rk_fx, Rk_sort_fx, BANDS, sfmsize, k_sort, k_num, p2a_flags, p2a_bands, last_bitalloc, input_frame );
223 :
224 0 : nzbands = 0;
225 0 : for ( j = 0; j < BANDS; j++ )
226 : {
227 0 : if ( sub( j, k_num[0] ) != 0 && sub( j, k_num[1] ) != 0 )
228 : {
229 0 : leftbits = L_add( leftbits, Rk_fx[k_sort[j]] );
230 0 : if ( Rk_fx[k_sort[j]] > 0 )
231 : {
232 0 : nzbands = add( (int16_t) nzbands, 1 );
233 : }
234 : }
235 : else
236 : {
237 0 : sepbits = L_add( sepbits, Rk_fx[k_sort[j]] );
238 : }
239 : }
240 :
241 : /* Separate the position information from the input signal(coefs_norm) */
242 : /* Gather the NZ coefficients*/
243 0 : for ( k = 0; k < BANDS; k++ ) /* Loop through non-zero blocks */
244 : {
245 0 : if ( k != k_num[0] && k != k_num[1] )
246 : {
247 0 : if ( Rk_fx[k_sort[k]] > 0 && USQ_TCQ[k_sort[k]] == 0 ) /* Then have non-zero block AND WILL BE ENCODED BY TCQ */
248 : {
249 : /* Encode Position Info, NZ Info, Signs */
250 0 : size = sfmsize[k_sort[k]];
251 : /* Determine scale step, ISC and TCQ quantizer */
252 0 : GetISCScale( &coefs_quant[sfm_start[k_sort[k]]], size, L_add( Rk_fx[k_sort[k]], delta_fx ), &coefs_norm_dec[sfm_start[k_sort[k]]], &step_scale[k_sort[k]], &surplus_fx, &pulses, savedstates, 0, &nzp, 0, 0, 0, 0 );
253 0 : leftbits = L_sub( leftbits, L_add( Rk_fx[k_sort[k]], delta_fx ) );
254 :
255 0 : npulses[k_sort[k]] = (int16_t) pulses;
256 :
257 0 : encode_position_ari_fx( parenc, &coefs_norm_dec[sfm_start[k_sort[k]]], size, &est_frame_bits_fx );
258 0 : encode_magnitude_tcq_fx( parenc, &coefs_norm_dec[sfm_start[k_sort[k]]], size, npulses[k_sort[k]], (int16_t) nzp, savedstates, &est_frame_bits_fx );
259 0 : encode_signs_fx( parenc, &coefs_norm_dec[sfm_start[k_sort[k]]], size, (int16_t) nzp, &est_frame_bits_fx );
260 0 : nzbands--;
261 : }
262 : /* Have USQ coded band */
263 0 : else if ( Rk_fx[k_sort[k]] > 0 && sub( USQ_TCQ[k_sort[k]], 1 ) == 0 )
264 : {
265 0 : size = sfmsize[k_sort[k]];
266 0 : GetISCScale( &coefs_quant[sfm_start[k_sort[k]]], size, L_add( Rk_fx[k_sort[k]], delta_fx ), &coefs_norm_dec[sfm_start[k_sort[k]]], &step_scale[k_sort[k]], &surplus_fx, &pulses, savedstates, 1, &nzp, 0, 0, 0, 0 );
267 0 : leftbits = L_sub( leftbits, L_add( Rk_fx[k_sort[k]], delta_fx ) );
268 :
269 0 : npulses[k_sort[k]] = (int16_t) pulses;
270 :
271 0 : encode_position_ari_fx( parenc, &coefs_norm_dec[sfm_start[k_sort[k]]], size, &est_frame_bits_fx );
272 0 : encode_magnitude_usq_fx( parenc, &coefs_norm_dec[sfm_start[k_sort[k]]], size, npulses[k_sort[k]], (int16_t) nzp, &est_frame_bits_fx );
273 0 : encode_signs_fx( parenc, &coefs_norm_dec[sfm_start[k_sort[k]]], size, (int16_t) nzp, &est_frame_bits_fx );
274 :
275 0 : nzbands--;
276 : }
277 : else /* Then have zero block */
278 : {
279 0 : npulses[k_sort[k]] = 0;
280 0 : size = sfmsize[k_sort[k]];
281 : }
282 :
283 0 : if ( Rk_fx[k_sort[k]] > 0 && surplus_fx < 0 )
284 : {
285 : #define WMC_TOOL_SKIP
286 0 : IF( nzbands <= 1 )
287 : {
288 0 : divider = 0;
289 : }
290 : ELSE
291 : {
292 0 : divider = 2;
293 : }
294 :
295 0 : IF( L_add( L_add( surplus_fx, sepbits ), ar_div( leftbits, divider ) ) < 0 )
296 : {
297 : /* Overflow possible => start to distribute negative surplus */
298 0 : delta_fx = ar_div( surplus_fx + sepbits, nzbands );
299 : }
300 : else
301 : {
302 0 : delta_fx = 0;
303 : }
304 0 : surplus_fx = L_sub( surplus_fx, delta_fx );
305 : #undef WMC_TOOL_SKIP
306 : }
307 : else
308 : {
309 0 : delta_fx = 0;
310 : }
311 : }
312 : }
313 :
314 : #define WMC_TOOL_SKIP
315 0 : if ( ( L_sub( surplus_fx, 524288 ) > 0 && sub( input_frame, L_FRAME8k ) == 0 ) || ( L_sub( surplus_fx, 786432 ) > 0 && sub( input_frame, L_FRAME16k ) == 0 ) )
316 : {
317 0 : bit_surplus_fx[0] = Mult_32_16( surplus_fx, 24576 ); /* Q16 */
318 0 : bit_surplus_fx[1] = Mult_32_16( surplus_fx, 8192 ); /* Q16 */
319 : }
320 : #undef WMC_TOOL_SKIP
321 : else
322 : {
323 0 : bit_surplus_fx[0] = surplus_fx;
324 0 : bit_surplus_fx[1] = 0;
325 : }
326 0 : for ( k = 0; k < BANDS; k++ )
327 : {
328 0 : for ( j = 0; j < 2; j++ )
329 : {
330 0 : if ( k == k_num[j] )
331 : {
332 : #define WMC_TOOL_SKIP
333 0 : Rk_fx[k_sort[k]] = L_add( Rk_fx[k_sort[k]], bit_surplus_fx[j] );
334 : #undef WMC_TOOL_SKIP
335 :
336 0 : if ( Rk_fx[k_sort[k]] > 0 && USQ_TCQ[k_sort[k]] == 0 ) /* Then have non-zero block AND WILL BE ENCODED BY TCQ */
337 : {
338 : /* Encode Position Info, NZ Info, Signs */
339 0 : size = sfmsize[k_sort[k]];
340 :
341 : /* Determine scale step, ISC and TCQ quantizer */
342 0 : GetISCScale( &coefs_quant[sfm_start[k_sort[k]]], size, Rk_fx[k_sort[k]], &coefs_norm_dec[sfm_start[k_sort[k]]], &step_scale[k_sort[k]], &surplus_fx, &pulses, savedstates, 0, &nzp, 0, 0, 0, 0 );
343 :
344 0 : npulses[k_sort[k]] = (int16_t) pulses;
345 :
346 0 : encode_position_ari_fx( parenc, &coefs_norm_dec[sfm_start[k_sort[k]]], size, &est_frame_bits_fx );
347 0 : encode_magnitude_tcq_fx( parenc, &coefs_norm_dec[sfm_start[k_sort[k]]], size, npulses[k_sort[k]], (int16_t) nzp, savedstates, &est_frame_bits_fx );
348 0 : encode_signs_fx( parenc, &coefs_norm_dec[sfm_start[k_sort[k]]], size, (int16_t) nzp, &est_frame_bits_fx );
349 : }
350 : /* Have USQ coded band */
351 0 : else if ( Rk_fx[k_sort[k]] > 0 && sub( USQ_TCQ[k_sort[k]], 1 ) == 0 )
352 : {
353 0 : size = sfmsize[k_sort[k]];
354 :
355 0 : GetISCScale( &coefs_quant[sfm_start[k_sort[k]]], size, Rk_fx[k_sort[k]], &coefs_norm_dec[sfm_start[k_sort[k]]], &step_scale[k_sort[k]], &surplus_fx, &pulses, savedstates, 1, &nzp, 0, 0, 0, 0 );
356 :
357 0 : npulses[k_sort[k]] = (int16_t) pulses;
358 :
359 0 : encode_position_ari_fx( parenc, &coefs_norm_dec[sfm_start[k_sort[k]]], size, &est_frame_bits_fx );
360 0 : encode_magnitude_usq_fx( parenc, &coefs_norm_dec[sfm_start[k_sort[k]]], size, npulses[k_sort[k]], (int16_t) nzp, &est_frame_bits_fx );
361 0 : encode_signs_fx( parenc, &coefs_norm_dec[sfm_start[k_sort[k]]], size, (int16_t) nzp, &est_frame_bits_fx );
362 : }
363 : else /* Then have zero block */
364 : {
365 0 : npulses[k_sort[k]] = 0;
366 0 : size = sfmsize[k_sort[k]];
367 : }
368 : }
369 : }
370 : }
371 : }
372 : else
373 : {
374 34 : surplus_fx = 0;
375 :
376 : /* Separate the position information from the input signal(coefs_norm) */
377 : /* Gather the NZ coefficients*/
378 812 : for ( k = 0; k < BANDS; k++ ) /* Loop through non-zero blocks */
379 : {
380 778 : if ( Rk_fx[k_sort[k]] > 0 )
381 : {
382 549 : size = sfmsize[k_sort[k]];
383 549 : GetISCScale( &coefs_quant[sfm_start[k_sort[k]]], size, L_add( Rk_fx[k_sort[k]], delta_fx ), &coefs_norm_dec[sfm_start[k_sort[k]]], &step_scale[k_sort[k]], &surplus_fx, &pulses, savedstates, 1, &nzp, &bcount, abuffer, mbuffer, sbuffer );
384 :
385 549 : npulses[k_sort[k]] = (int16_t) pulses;
386 549 : encode_position_ari_fx( parenc, &coefs_norm_dec[sfm_start[k_sort[k]]], size, &est_frame_bits_fx );
387 549 : encode_magnitude_usq_fx( parenc, &coefs_norm_dec[sfm_start[k_sort[k]]], size, npulses[k_sort[k]], (int16_t) nzp, &est_frame_bits_fx );
388 549 : encode_signs_fx( parenc, &coefs_norm_dec[sfm_start[k_sort[k]]], size, (int16_t) nzp, &est_frame_bits_fx );
389 : /* nzbands--; */
390 549 : nzbands = sub( (int16_t) nzbands, 1 );
391 : }
392 : else /* Then have zero block */
393 : {
394 229 : npulses[k_sort[k]] = 0;
395 229 : size = sfmsize[k_sort[k]];
396 : }
397 :
398 : /* Surplus distribution */
399 778 : if ( surplus_fx > 0 && nzbands > 0 )
400 : {
401 515 : delta_fx = ar_div( surplus_fx, nzbands );
402 515 : surplus_fx = L_sub( surplus_fx, delta_fx );
403 : }
404 : }
405 : }
406 :
407 34 : TCQLSB( bcount, abuffer, mbuffer, sbuffer, dpath );
408 :
409 : /* Save TCQ path to bitstream */
410 34 : SaveTCQdata( parenc, dpath, (int16_t) lsbtcq_bits );
411 :
412 : /* Add tcq sequence to decoding buffer */
413 34 : InitLSBTCQ( &bcount );
414 :
415 34 : ar_encoder_done( parenc );
416 :
417 : /* Loop through non-zero blocks */
418 34 : if ( !flag_wbnb )
419 : {
420 812 : for ( k = 0; k < BANDS; k++ )
421 : {
422 778 : if ( Rk_fx[k_sort[k]] > 0 )
423 : {
424 549 : size = sfmsize[k_sort[k]];
425 549 : RestoreTCQ( &coefs_norm_dec[sfm_start[k_sort[k]]], size, &bcount, mbuffer );
426 : }
427 : }
428 : }
429 :
430 34 : nb_bytes = bit_budget >> 3;
431 34 : j = bit_budget - ( nb_bytes << 3 );
432 606 : for ( i = 0; i < nb_bytes; i++ )
433 : {
434 572 : push_indice( hBstr, IND_HQ2_SUBBAND_TCQ, pbs->buf[i], 8 );
435 : }
436 34 : if ( j > 0 )
437 : {
438 29 : push_indice( hBstr, IND_HQ2_SUBBAND_TCQ, ( pbs->buf[nb_bytes] >> ( 8 - j ) ), j );
439 : }
440 :
441 : /* Clear decoding buffer */
442 34 : set_f( coefs_quant, 0.0, sfm_end[BANDS - 1] + 1 );
443 : /* New analysis of decoded frame */
444 812 : for ( i = 0; i < BANDS; i++ )
445 : {
446 778 : if ( Rk_fx[k_sort[i]] > 0 )
447 : {
448 549 : gain = 0.0f;
449 :
450 549 : crosscorr = 0.0f;
451 549 : selfcorr = EPSILON;
452 7901 : for ( j = 0; j < sfmsize[k_sort[i]]; j++ )
453 : {
454 7352 : crosscorr += ( coefs_norm[sfm_start[k_sort[i]] + j] * coefs_norm_dec[sfm_start[k_sort[i]] + j] );
455 7352 : selfcorr += ( coefs_norm_dec[sfm_start[k_sort[i]] + j] * coefs_norm_dec[sfm_start[k_sort[i]] + j] );
456 : }
457 :
458 549 : gain = crosscorr / selfcorr;
459 :
460 549 : if ( gain == 0 )
461 : {
462 28 : gain = 1e-10f;
463 : }
464 :
465 : /* Use optimal gain */
466 7901 : for ( j = 0; j < sfmsize[k_sort[i]]; j++ )
467 : {
468 7352 : inp_vector[sfm_start[k_sort[i]] + j] = round_f( ( ( 1.0f / QTCQ ) * coefs_norm_dec[sfm_start[k_sort[i]] + j] ) );
469 7352 : coefs_quant[sfm_start[k_sort[i]] + j] = gain * coefs_norm_dec[sfm_start[k_sort[i]] + j];
470 : }
471 : }
472 : }
473 :
474 : #ifdef DEBUGGING
475 : if ( parenc->num_bits > bit_budget + 1 )
476 : {
477 : return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "nTCQ too much bits used! \n" );
478 : }
479 :
480 : for ( i = 0; i < BANDS; i++ )
481 : {
482 : float diff[TCQ_MAX_BAND_SIZE];
483 :
484 : if ( npulses[i] > 0 )
485 : {
486 : /* SNR measurement */
487 : for ( j = 0; j < sfmsize[i]; j++ )
488 : {
489 : diff[j] = coefs_norm[sfm_start[i] + j] - coefs_quant[sfm_start[i] + j];
490 : }
491 :
492 : if ( idchan == 0 )
493 : {
494 : snr( &coefs_norm[sfm_start[i]], diff, sfmsize[i], "TCQ_output" );
495 : }
496 : else
497 : {
498 : snr( &coefs_norm[sfm_start[i]], diff, sfmsize[i], "TCQ_output_chan2" );
499 : }
500 : }
501 : }
502 : #endif
503 :
504 34 : return error;
505 : }
|