Coverage Report

Created: 2026-03-21 07:02

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