xref: /aosp_15_r20/external/libxaac/encoder/ixheaace_sbr_freq_scaling.c (revision 15dc779a375ca8b5125643b829a8aa4b70d7f451)
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