1 /******************************************************************************
2 * *
3 * Copyright (C) 2023 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************
18 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19 */
20
21 #include <math.h>
22 #include "ixheaac_type_def.h"
23 #include "ixheaac_constants.h"
24 #include "ixheaace_error_codes.h"
25 #include "ixheaac_error_standards.h"
26 #include "ixheaace_aac_constants.h"
27 #include "ixheaac_basic_ops32.h"
28 #include "ixheaac_basic_ops16.h"
29 #include "ixheaac_basic_ops40.h"
30 #include "ixheaac_basic_ops.h"
31
32 #include "ixheaace_common_rom.h"
33 #include "ixheaace_sbr_header.h"
34 #include "ixheaace_sbr_def.h"
35 #include "ixheaace_sbr_freq_scaling.h"
36 #include "ixheaace_sbr_misc.h"
37 #include "ixheaace_resampler.h"
38 #include "ixheaace_sbr_rom.h"
39
ixheaace_get_start_freq_4_1(WORD32 fs,WORD32 start_freq)40 static WORD32 ixheaace_get_start_freq_4_1(WORD32 fs, WORD32 start_freq) {
41 WORD32 minimum_k0;
42 const WORD32 *ptr_start_offset;
43
44 switch (fs) {
45 case 16000:
46 minimum_k0 = 12;
47 break;
48 case 22050:
49 minimum_k0 = 9;
50 break;
51 case 24000:
52 minimum_k0 = 8;
53 break;
54 case 32000:
55 minimum_k0 = 8;
56 break;
57 case 44100:
58 minimum_k0 = 6;
59 break;
60 case 48000:
61 minimum_k0 = 5;
62 break;
63 default:
64 minimum_k0 = 5; /* illegal fs */
65 }
66
67 switch (fs) {
68 case 16000: {
69 ptr_start_offset = &ixheaace_start_freq_16k_4_1[0];
70 } break;
71
72 case 22050: {
73 ptr_start_offset = &ixheaace_start_freq_22k_4_1[0];
74 } break;
75
76 case 24000: {
77 ptr_start_offset = &ixheaace_start_freq_24k_4_1[0];
78 } break;
79
80 case 32000: {
81 ptr_start_offset = &ixheaace_start_freq_32k_4_1[0];
82 } break;
83
84 case 44100:
85 case 48000:
86 case 64000: {
87 ptr_start_offset = &ixheaace_start_freq_48k_4_1[0];
88 } break;
89
90 case 88200:
91 case 96000: {
92 ptr_start_offset = &ixheaace_start_freq_96k_4_1[0];
93 } break;
94
95 default: {
96 ptr_start_offset = &ixheaace_start_freq_dflt_4_1[0];
97 }
98 }
99 return (minimum_k0 + ptr_start_offset[start_freq]);
100 }
101
ixheaace_get_stop_freq_4_1(WORD32 fs,WORD32 stop_freq)102 static WORD32 ixheaace_get_stop_freq_4_1(WORD32 fs, WORD32 stop_freq) {
103 WORD32 result, i;
104 WORD32 *v_stop_freq = 0;
105 WORD32 k1_min;
106 WORD32 v_dstop[13];
107
108 /* counting previous operations */
109 switch (fs) {
110 case 16000:
111 k1_min = 24;
112 v_stop_freq = (WORD32 *)&ixheaace_stop_freq_16k_4_1[0];
113 break;
114 case 22050:
115 k1_min = 17;
116 v_stop_freq = (WORD32 *)&ixheaace_stop_freq_22k_4_1[0];
117 break;
118 case 24000:
119 k1_min = 16;
120 v_stop_freq = (WORD32 *)&ixheaace_stop_freq_24k_4_1[0];
121 break;
122 case 32000:
123 k1_min = 16;
124 v_stop_freq = (WORD32 *)&ixheaace_stop_freq_32k_4_1[0];
125 break;
126
127 case 44100:
128 k1_min = 12;
129 v_stop_freq = (WORD32 *)&ixheaace_stop_freq_44k_4_1[0];
130 break;
131
132 case 48000:
133 k1_min = 11;
134 v_stop_freq = (WORD32 *)&ixheaace_stop_freq_48k_4_1[0];
135 break;
136
137 default:
138 v_stop_freq = (WORD32 *)&ixheaace_stop_freq_32k_4_1[0];
139 k1_min = 11; /* illegal fs */
140 }
141
142 for (i = 0; i <= 12; i++) {
143 v_dstop[i] = v_stop_freq[i + 1] - v_stop_freq[i];
144 }
145
146 ixheaace_shellsort_int(v_dstop, 13);
147
148 result = k1_min;
149
150 for (i = 0; i < stop_freq; i++) {
151 result = result + v_dstop[i];
152 }
153
154 return result;
155 }
156
ixheaace_get_start_freq(WORD32 fs,WORD32 start_freq)157 static WORD32 ixheaace_get_start_freq(WORD32 fs, WORD32 start_freq) {
158 WORD32 minimum_k0;
159
160 switch (fs) {
161 case 16000:
162 minimum_k0 = 24;
163 break;
164 case 22050:
165 minimum_k0 = 17;
166 break;
167 case 24000:
168 minimum_k0 = 16;
169 break;
170 case 32000:
171 minimum_k0 = 16;
172 break;
173 case 44100:
174 minimum_k0 = 12;
175 break;
176 case 48000:
177 minimum_k0 = 11;
178 break;
179 case 64000:
180 minimum_k0 = 10;
181 break;
182 case 88200:
183 minimum_k0 = 7;
184 break;
185 case 96000:
186 minimum_k0 = 7;
187 break;
188 default:
189 minimum_k0 = 11; /* illegal fs */
190 }
191
192 switch (fs) {
193 case 16000: {
194 return (minimum_k0 + vector_offset_16k[start_freq]);
195 } break;
196
197 case 22050: {
198 return (minimum_k0 + vector_offset_22k[start_freq]);
199 } break;
200
201 case 24000: {
202 return (minimum_k0 + vector_offset_24k[start_freq]);
203 } break;
204
205 case 32000: {
206 return (minimum_k0 + vector_offset_32k[start_freq]);
207 } break;
208
209 case 44100:
210 case 48000:
211 case 64000: {
212 return (minimum_k0 + vector_offset_44_48_64[start_freq]);
213 } break;
214
215 case 88200:
216 case 96000: {
217 return (minimum_k0 + vector_offset_88_96[start_freq]);
218 } break;
219
220 default: {
221 return (minimum_k0 + vector_offset_def[start_freq]);
222 }
223 }
224 }
225
ixheaace_get_stop_freq(WORD32 fs,WORD32 stop_freq)226 static WORD32 ixheaace_get_stop_freq(WORD32 fs, WORD32 stop_freq) {
227 WORD32 result, i;
228 WORD32 *v_stop_freq = 0;
229 WORD32 k1_min;
230 WORD32 v_dstop[13];
231
232 switch (fs) {
233 case 16000:
234 k1_min = ixheaace_stop_freq_16k[0];
235 v_stop_freq = (WORD32 *)&ixheaace_stop_freq_16k[0];
236 break;
237 case 22050:
238 k1_min = ixheaace_stop_freq_22k[0];
239 v_stop_freq = (WORD32 *)&ixheaace_stop_freq_22k[0];
240 break;
241 case 24000:
242 k1_min = ixheaace_stop_freq_24k[0];
243 v_stop_freq = (WORD32 *)&ixheaace_stop_freq_24k[0];
244 break;
245 case 32000:
246 k1_min = 32;
247
248 v_stop_freq = (WORD32 *)vector_stop_freq_32;
249 break;
250
251 case 44100:
252 k1_min = 23;
253
254 v_stop_freq = (WORD32 *)vector_stop_freq_44;
255 break;
256
257 case 48000:
258 k1_min = 21;
259
260 v_stop_freq = (WORD32 *)vector_stop_freq_48;
261 break;
262
263 default:
264 v_stop_freq = (WORD32 *)vector_stop_freq_32;
265 k1_min = 21; /* illegal fs */
266 }
267
268 for (i = 0; i <= 12; i++) {
269 v_dstop[i] = v_stop_freq[i + 1] - v_stop_freq[i];
270 }
271
272 ixheaace_shellsort_int(v_dstop, 13);
273
274 result = k1_min;
275
276 for (i = 0; i < stop_freq; i++) {
277 result = result + v_dstop[i];
278 }
279
280 return result;
281 }
282
ixheaace_get_usac_stop_freq(WORD32 fs,WORD32 stop_freq)283 static WORD32 ixheaace_get_usac_stop_freq(WORD32 fs, WORD32 stop_freq)
284 {
285 WORD32 result, i;
286 WORD32 *v_stop_freq = 0;
287 WORD32 k1_min;
288 WORD32 v_dstop[13];
289
290 switch (fs)
291 {
292 case 16000:
293 k1_min = ixheaace_usac_stop_freq_16k[0];
294 v_stop_freq = (WORD32 *)&ixheaace_usac_stop_freq_16k[0];
295 break;
296 case 22050:
297 k1_min = ixheaace_usac_stop_freq_22k[0];
298 v_stop_freq = (WORD32 *)&ixheaace_usac_stop_freq_22k[0];
299 break;
300 case 24000:
301 k1_min = ixheaace_usac_stop_freq_24k[0];
302 v_stop_freq = (WORD32 *)&ixheaace_usac_stop_freq_24k[0];
303 break;
304 case 32000:
305 k1_min = 32;
306 v_stop_freq = (WORD32 *)vector_stop_freq_32;
307 break;
308
309 case 44100:
310 k1_min = 23;
311 v_stop_freq = (WORD32 *)vector_stop_freq_44;
312 break;
313
314 case 48000:
315 k1_min = 21;
316 v_stop_freq = (WORD32 *)vector_stop_freq_48;
317 break;
318
319 default:
320 v_stop_freq = (WORD32 *)vector_stop_freq_32;
321 k1_min = 21; /* illegal fs */
322 }
323
324 for (i = 0; i <= 12; i++)
325 {
326 v_dstop[i] = v_stop_freq[i + 1] - v_stop_freq[i];
327 }
328
329 ixheaace_shellsort_int(v_dstop, 13);
330
331 result = k1_min;
332
333 for (i = 0; i < stop_freq; i++)
334 {
335 result = result + v_dstop[i];
336 }
337
338 return result;
339 }
340
341 WORD32
ixheaace_get_sbr_start_freq_raw(WORD32 start_freq,WORD32 qmf_bands,WORD32 fs)342 ixheaace_get_sbr_start_freq_raw(WORD32 start_freq, WORD32 qmf_bands, WORD32 fs) {
343 WORD32 result;
344
345 if (start_freq < 0 || start_freq > 15) {
346 return -1;
347 }
348
349 result = ixheaace_get_start_freq(fs, start_freq);
350
351 result = (result * fs / qmf_bands + 1) >> 1;
352
353 return result;
354 }
355
ixheaace_number_of_bands(WORD32 b_p_o,WORD32 start,WORD32 stop,FLOAT32 warp_fac)356 static WORD32 ixheaace_number_of_bands(WORD32 b_p_o, WORD32 start, WORD32 stop,
357 FLOAT32 warp_fac) {
358 WORD32 result = 0;
359 result = (WORD32)(b_p_o * log((FLOAT32)(stop) / start) / (2.0 * log(2.0) * warp_fac) + 0.5);
360 result <<= 1;
361 return result;
362 }
363
ixheaace_calc_bands(WORD32 * ptr_diff,WORD32 start,WORD32 stop,WORD32 num_bands)364 static VOID ixheaace_calc_bands(WORD32 *ptr_diff, WORD32 start, WORD32 stop, WORD32 num_bands) {
365 WORD32 i;
366 WORD32 previous;
367 WORD32 current;
368 previous = start;
369 for (i = 1; i <= num_bands; i++) {
370 current = (WORD32)((start * pow((FLOAT32)stop / start, (FLOAT32)i / num_bands)) + 0.5f);
371 ptr_diff[i - 1] = current - previous;
372 previous = current;
373 }
374 }
375
ixheaace_modify_bands(WORD32 max_band_previous,WORD32 * ptr_diff,WORD32 length)376 static VOID ixheaace_modify_bands(WORD32 max_band_previous, WORD32 *ptr_diff, WORD32 length) {
377 WORD32 change = max_band_previous - ptr_diff[0];
378
379 if (change > (ptr_diff[length - 1] - ptr_diff[0]) / 2) {
380 change = (ptr_diff[length - 1] - ptr_diff[0]) / 2;
381 }
382
383 ptr_diff[0] += change;
384
385 ptr_diff[length - 1] -= change;
386
387 ixheaace_shellsort_int(ptr_diff, length);
388 }
389
ixheaace_cum_sum(WORD32 start_value,WORD32 * ptr_diff,WORD32 length,UWORD8 * ptr_start_adress)390 static VOID ixheaace_cum_sum(WORD32 start_value, WORD32 *ptr_diff, WORD32 length,
391 UWORD8 *ptr_start_adress) {
392 WORD32 i;
393
394 ptr_start_adress[0] = (UWORD8)start_value;
395
396 for (i = 1; i <= length; i++) {
397 ptr_start_adress[i] = ptr_start_adress[i - 1] + (UWORD8)ptr_diff[i - 1];
398 }
399 }
400
401 IA_ERRORCODE
ixheaace_find_start_and_stop_band(const WORD32 sampling_freq,const WORD32 num_channels,const WORD32 start_freq,const WORD32 stop_freq,const ixheaace_sr_mode sample_rate_mode,WORD32 * ptr_k0,WORD32 * ptr_k2,WORD32 sbr_ratio_idx,ixheaace_sbr_codec_type sbr_codec)402 ixheaace_find_start_and_stop_band(const WORD32 sampling_freq, const WORD32 num_channels,
403 const WORD32 start_freq, const WORD32 stop_freq,
404 const ixheaace_sr_mode sample_rate_mode, WORD32 *ptr_k0,
405 WORD32 *ptr_k2, WORD32 sbr_ratio_idx,
406 ixheaace_sbr_codec_type sbr_codec) {
407 switch (sbr_codec) {
408 case USAC_SBR: {
409 if (sbr_ratio_idx == USAC_SBR_RATIO_INDEX_4_1) {
410 *ptr_k0 = ixheaace_get_start_freq_4_1(sampling_freq, start_freq);
411 } else {
412 *ptr_k0 = ixheaace_get_start_freq(sampling_freq, start_freq);
413 }
414 break;
415 }
416 default: {
417 *ptr_k0 = ixheaace_get_start_freq(sampling_freq, start_freq);
418 break;
419 }
420 }
421 if ((sample_rate_mode == 1) && (sampling_freq * num_channels < 2 * *ptr_k0 * sampling_freq)) {
422 return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_SAMPLERATE_MODE;
423 }
424
425 if (stop_freq < 14) {
426 switch (sbr_codec) {
427 case USAC_SBR: {
428 if (USAC_SBR_RATIO_INDEX_4_1 == sbr_ratio_idx) {
429 *ptr_k2 = ixheaace_get_stop_freq_4_1(sampling_freq, stop_freq);
430 } else {
431 *ptr_k2 = ixheaace_get_usac_stop_freq(sampling_freq, stop_freq);
432 }
433 break;
434 }
435 default: {
436 *ptr_k2 = ixheaace_get_stop_freq(sampling_freq, stop_freq);
437 break;
438 }
439 }
440 }
441
442 else {
443 *ptr_k2 = (stop_freq == 14 ? 2 * *ptr_k0 : 3 * *ptr_k0);
444 }
445
446 if (*ptr_k2 > num_channels) {
447 *ptr_k2 = num_channels;
448 }
449 if (sbr_codec == USAC_SBR) {
450 if (sbr_ratio_idx == USAC_SBR_RATIO_INDEX_4_1) {
451 if (((*ptr_k2 - *ptr_k0) > MAXIMUM_FREQ_COEFFS_USAC) || (*ptr_k2 <= *ptr_k0)) {
452 return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_FREQ_COEFFS;
453 }
454 if ((2 * sampling_freq == 44100) && ((*ptr_k2 - *ptr_k0) > MAXIMUM_FREQ_COEFFS_USAC)) {
455 return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_FREQ_COEFFS;
456 }
457 if ((2 * sampling_freq >= 48000) && ((*ptr_k2 - *ptr_k0) > MAXIMUM_FREQ_COEFFS_USAC)) {
458 return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_FREQ_COEFFS;
459 }
460 } else {
461 if (sampling_freq <= 32000) {
462 if ((*ptr_k2 - *ptr_k0) > MAXIMUM_FREQ_COEFFS_LE32KHZ) {
463 return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_FREQ_COEFFS;
464 }
465 } else if (sampling_freq == 44100) {
466 if ((*ptr_k2 - *ptr_k0) > MAXIMUM_FREQ_COEFFS_EQ44KHZ) {
467 return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_FREQ_COEFFS;
468 }
469 } else if (sampling_freq >= 48000) {
470 if ((*ptr_k2 - *ptr_k0) > MAXIMUM_FREQ_COEFFS_GE48KHZ) {
471 return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_FREQ_COEFFS;
472 }
473 } else {
474 return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_FREQ_COEFFS;
475 }
476 }
477 } else {
478 if (sampling_freq <= 32000) {
479 if ((*ptr_k2 - *ptr_k0) > MAXIMUM_FREQ_COEFFS_LE32KHZ) {
480 return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_FREQ_COEFFS;
481 }
482 } else if (sampling_freq == 44100) {
483 if ((*ptr_k2 - *ptr_k0) > MAXIMUM_FREQ_COEFFS_EQ44KHZ) {
484 return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_FREQ_COEFFS;
485 }
486 } else if (sampling_freq >= 48000) {
487 if ((*ptr_k2 - *ptr_k0) > MAXIMUM_FREQ_COEFFS_GE48KHZ) {
488 return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_FREQ_COEFFS;
489 }
490 } else {
491 return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_FREQ_COEFFS;
492 }
493 }
494
495 if ((*ptr_k2 - *ptr_k0) < 0) {
496 return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_FREQ_COEFFS;
497 }
498
499 return IA_NO_ERROR;
500 }
501
502 IA_ERRORCODE
ixheaace_update_freq_scale(UWORD8 * ptr_k_master,WORD32 * ptr_num_bands,const WORD32 k0,const WORD32 k2,const WORD32 freq_scale,const WORD32 alter_scale,ixheaace_sr_mode sbr_rate)503 ixheaace_update_freq_scale(UWORD8 *ptr_k_master, WORD32 *ptr_num_bands, const WORD32 k0,
504 const WORD32 k2, const WORD32 freq_scale, const WORD32 alter_scale,
505 ixheaace_sr_mode sbr_rate)
506
507 {
508 IA_ERRORCODE err_code = IA_NO_ERROR;
509 WORD32 b_p_o = 0;
510 WORD32 dk = 0;
511
512 FLOAT32 warp;
513 WORD32 k1 = 0, i;
514 WORD32 num_bands0;
515 WORD32 num_bands1;
516 WORD32 diff_tot[IXHEAACE_MAXIMUM_OCTAVE + IXHEAACE_MAXIMUM_SECOND_REGION] = {0};
517 WORD32 *diff0 = diff_tot;
518 WORD32 *diff1 = diff_tot + IXHEAACE_MAXIMUM_OCTAVE;
519 WORD32 k2_achived;
520 WORD32 k2_diff;
521 WORD32 incr = 0;
522
523 switch (freq_scale) {
524 case 1:
525 b_p_o = 12;
526 break;
527 case 2:
528 b_p_o = 10;
529 break;
530 case 3:
531 b_p_o = 8;
532 break;
533 }
534
535 if (freq_scale > 0) {
536 if (alter_scale == 0) {
537 warp = 1.0f;
538 } else {
539 warp = 1.3f;
540 }
541
542 if (IXHEAACE_QUAD_RATE == sbr_rate) {
543 if (k0 < b_p_o) {
544 b_p_o = (k0 >> 1) * 2;
545 }
546 }
547
548 if (4 * k2 >= 9 * k0) {
549 k1 = 2 * k0;
550 num_bands0 = ixheaace_number_of_bands(b_p_o, k0, k1, 1.0f);
551 num_bands1 = ixheaace_number_of_bands(b_p_o, k1, k2, warp);
552
553 ixheaace_calc_bands(diff0, k0, k1, num_bands0);
554 ixheaace_shellsort_int(diff0, num_bands0);
555
556 if (diff0[0] == 0) {
557 return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_NUM_BANDS;
558 }
559
560 ixheaace_cum_sum(k0, diff0, num_bands0, ptr_k_master);
561
562 ixheaace_calc_bands(diff1, k1, k2, num_bands1);
563 ixheaace_shellsort_int(diff1, num_bands1);
564
565 if (diff0[num_bands0 - 1] > diff1[0]) {
566 ixheaace_modify_bands(diff0[num_bands0 - 1], diff1, num_bands1);
567 }
568
569 ixheaace_cum_sum(k1, diff1, num_bands1, &ptr_k_master[num_bands0]);
570 *ptr_num_bands = num_bands0 + num_bands1;
571 } else {
572 k1 = k2;
573 num_bands0 = ixheaace_number_of_bands(b_p_o, k0, k1, 1.0f);
574
575 ixheaace_calc_bands(diff0, k0, k1, num_bands0);
576 ixheaace_shellsort_int(diff0, num_bands0);
577
578 if (diff0[0] == 0) {
579 return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_NUM_BANDS;
580 }
581
582 ixheaace_cum_sum(k0, diff0, num_bands0, ptr_k_master);
583
584 *ptr_num_bands = num_bands0;
585 }
586 } else {
587 if (alter_scale == 0) {
588 dk = 1;
589 num_bands0 = 2 * ((k2 - k0) / 2);
590 } else {
591 dk = 2;
592 num_bands0 = 2 * (((k2 - k0) / dk + 1) / 2);
593 }
594
595 k2_achived = k0 + num_bands0 * dk;
596 k2_diff = k2 - k2_achived;
597
598 for (i = 0; i < num_bands0; i++) {
599 diff_tot[i] = dk;
600 }
601
602 if (k2_diff < 0) {
603 incr = 1;
604 i = 0;
605 }
606
607 if (k2_diff > 0) {
608 incr = -1;
609
610 i = num_bands0 - 1;
611 }
612
613 while (k2_diff != 0) {
614 if (i < 0) break;
615 diff_tot[i] = diff_tot[i] - incr;
616
617 i = i + incr;
618
619 k2_diff = k2_diff + incr;
620 }
621
622 ixheaace_cum_sum(k0, diff_tot, num_bands0, ptr_k_master);
623
624 *ptr_num_bands = num_bands0;
625 }
626
627 if (*ptr_num_bands < 1) {
628 return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_NUM_BANDS;
629 }
630
631 if (sbr_rate == IXHEAACE_QUAD_RATE) {
632 for (i = 1; i < *ptr_num_bands; i++) {
633 if (!(ptr_k_master[i] - ptr_k_master[i - 1] <= k0 - 2)) {
634 return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_NUM_BANDS;
635 }
636 }
637 }
638
639 return err_code;
640 }
641
ixheaace_update_high_res(UWORD8 * ptr_hires,WORD32 * ptr_num_hires,UWORD8 * ptr_k_master,WORD32 num_master,WORD32 * ptr_xover_band,ixheaace_sr_mode dr_or_sr,WORD32 num_qmf_ch)642 VOID ixheaace_update_high_res(UWORD8 *ptr_hires, WORD32 *ptr_num_hires, UWORD8 *ptr_k_master,
643 WORD32 num_master, WORD32 *ptr_xover_band,
644 ixheaace_sr_mode dr_or_sr, WORD32 num_qmf_ch) {
645 WORD32 i;
646 WORD32 divider;
647 WORD32 max1, max2;
648
649 divider = (dr_or_sr == IXHEAACE_DUAL_RATE) ? 2 : 1;
650 if (dr_or_sr == IXHEAACE_QUAD_RATE) {
651 divider = 4;
652 }
653
654 if ((ptr_k_master[*ptr_xover_band] > (num_qmf_ch / divider)) ||
655 (*ptr_xover_band > num_master)) {
656 max1 = 0;
657 max2 = num_master;
658
659 while ((ptr_k_master[max1 + 1] < (num_qmf_ch / divider)) && ((max1 + 1) < max2)) {
660 max1++;
661 }
662
663 *ptr_xover_band = max1;
664 }
665
666 *ptr_num_hires = num_master - *ptr_xover_band;
667
668 for (i = *ptr_xover_band; i <= num_master; i++) {
669 ptr_hires[i - *ptr_xover_band] = ptr_k_master[i];
670 }
671 }
672
ixheaace_update_low_res(UWORD8 * ptr_lores,WORD32 * ptr_num_lores,UWORD8 * ptr_hires,WORD32 ptr_num_hires)673 VOID ixheaace_update_low_res(UWORD8 *ptr_lores, WORD32 *ptr_num_lores, UWORD8 *ptr_hires,
674 WORD32 ptr_num_hires) {
675 WORD32 i;
676
677 if (ptr_num_hires % 2 == 0) {
678 *ptr_num_lores = ptr_num_hires / 2;
679
680 for (i = 0; i <= *ptr_num_lores; i++) {
681 ptr_lores[i] = ptr_hires[i * 2];
682 }
683 } else {
684 *ptr_num_lores = (ptr_num_hires + 1) / 2;
685
686 ptr_lores[0] = ptr_hires[0];
687
688 for (i = 1; i <= *ptr_num_lores; i++) {
689 ptr_lores[i] = ptr_hires[i * 2 - 1];
690 }
691 }
692 }
693