/src/libxaac/encoder/ixheaace_sbr_freq_scaling.c
Line | Count | Source (jump to first uncovered line) |
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 | 570 | static WORD32 ixheaace_get_start_freq_4_1(WORD32 fs, WORD32 start_freq) { |
41 | 570 | WORD32 minimum_k0; |
42 | 570 | const WORD32 *ptr_start_offset; |
43 | | |
44 | 570 | switch (fs) { |
45 | 85 | case 16000: |
46 | 85 | minimum_k0 = 12; |
47 | 85 | break; |
48 | 160 | case 22050: |
49 | 160 | minimum_k0 = 9; |
50 | 160 | break; |
51 | 254 | case 24000: |
52 | 254 | minimum_k0 = 8; |
53 | 254 | break; |
54 | 63 | case 32000: |
55 | 63 | minimum_k0 = 8; |
56 | 63 | break; |
57 | 1 | case 44100: |
58 | 1 | minimum_k0 = 6; |
59 | 1 | break; |
60 | 7 | case 48000: |
61 | 7 | minimum_k0 = 5; |
62 | 7 | break; |
63 | 0 | default: |
64 | 0 | minimum_k0 = 5; /* illegal fs */ |
65 | 570 | } |
66 | | |
67 | 570 | switch (fs) { |
68 | 85 | case 16000: { |
69 | 85 | ptr_start_offset = &ixheaace_start_freq_16k_4_1[0]; |
70 | 85 | } break; |
71 | | |
72 | 160 | case 22050: { |
73 | 160 | ptr_start_offset = &ixheaace_start_freq_22k_4_1[0]; |
74 | 160 | } break; |
75 | | |
76 | 254 | case 24000: { |
77 | 254 | ptr_start_offset = &ixheaace_start_freq_24k_4_1[0]; |
78 | 254 | } break; |
79 | | |
80 | 63 | case 32000: { |
81 | 63 | ptr_start_offset = &ixheaace_start_freq_32k_4_1[0]; |
82 | 63 | } break; |
83 | | |
84 | 1 | case 44100: |
85 | 8 | case 48000: |
86 | 8 | case 64000: { |
87 | 8 | ptr_start_offset = &ixheaace_start_freq_48k_4_1[0]; |
88 | 8 | } 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 | 0 | default: { |
96 | 0 | ptr_start_offset = &ixheaace_start_freq_dflt_4_1[0]; |
97 | 0 | } |
98 | 570 | } |
99 | 570 | return (minimum_k0 + ptr_start_offset[start_freq]); |
100 | 570 | } |
101 | | |
102 | 570 | static WORD32 ixheaace_get_stop_freq_4_1(WORD32 fs, WORD32 stop_freq) { |
103 | 570 | WORD32 result, i; |
104 | 570 | WORD32 *v_stop_freq = 0; |
105 | 570 | WORD32 k1_min; |
106 | 570 | WORD32 v_dstop[13]; |
107 | | |
108 | | /* counting previous operations */ |
109 | 570 | switch (fs) { |
110 | 85 | case 16000: |
111 | 85 | k1_min = 24; |
112 | 85 | v_stop_freq = (WORD32 *)&ixheaace_stop_freq_16k_4_1[0]; |
113 | 85 | break; |
114 | 160 | case 22050: |
115 | 160 | k1_min = 17; |
116 | 160 | v_stop_freq = (WORD32 *)&ixheaace_stop_freq_22k_4_1[0]; |
117 | 160 | break; |
118 | 254 | case 24000: |
119 | 254 | k1_min = 16; |
120 | 254 | v_stop_freq = (WORD32 *)&ixheaace_stop_freq_24k_4_1[0]; |
121 | 254 | break; |
122 | 63 | case 32000: |
123 | 63 | k1_min = 16; |
124 | 63 | v_stop_freq = (WORD32 *)&ixheaace_stop_freq_32k_4_1[0]; |
125 | 63 | break; |
126 | | |
127 | 1 | case 44100: |
128 | 1 | k1_min = 12; |
129 | 1 | v_stop_freq = (WORD32 *)&ixheaace_stop_freq_44k_4_1[0]; |
130 | 1 | break; |
131 | | |
132 | 7 | case 48000: |
133 | 7 | k1_min = 11; |
134 | 7 | v_stop_freq = (WORD32 *)&ixheaace_stop_freq_48k_4_1[0]; |
135 | 7 | break; |
136 | | |
137 | 0 | default: |
138 | 0 | v_stop_freq = (WORD32 *)&ixheaace_stop_freq_32k_4_1[0]; |
139 | 0 | k1_min = 11; /* illegal fs */ |
140 | 570 | } |
141 | | |
142 | 7.98k | for (i = 0; i <= 12; i++) { |
143 | 7.41k | v_dstop[i] = v_stop_freq[i + 1] - v_stop_freq[i]; |
144 | 7.41k | } |
145 | | |
146 | 570 | ixheaace_shellsort_int(v_dstop, 13); |
147 | | |
148 | 570 | result = k1_min; |
149 | | |
150 | 6.84k | for (i = 0; i < stop_freq; i++) { |
151 | 6.27k | result = result + v_dstop[i]; |
152 | 6.27k | } |
153 | | |
154 | 570 | return result; |
155 | 570 | } |
156 | | |
157 | 20.7k | static WORD32 ixheaace_get_start_freq(WORD32 fs, WORD32 start_freq) { |
158 | 20.7k | WORD32 minimum_k0; |
159 | | |
160 | 20.7k | switch (fs) { |
161 | 180 | case 16000: |
162 | 180 | minimum_k0 = 24; |
163 | 180 | break; |
164 | 92 | case 22050: |
165 | 92 | minimum_k0 = 17; |
166 | 92 | break; |
167 | 274 | case 24000: |
168 | 274 | minimum_k0 = 16; |
169 | 274 | break; |
170 | 5.89k | case 32000: |
171 | 5.89k | minimum_k0 = 16; |
172 | 5.89k | break; |
173 | 6.03k | case 44100: |
174 | 6.03k | minimum_k0 = 12; |
175 | 6.03k | break; |
176 | 7.96k | case 48000: |
177 | 7.96k | minimum_k0 = 11; |
178 | 7.96k | break; |
179 | 94 | case 64000: |
180 | 94 | minimum_k0 = 10; |
181 | 94 | 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 | 172 | default: |
189 | 172 | minimum_k0 = 11; /* illegal fs */ |
190 | 20.7k | } |
191 | | |
192 | 20.7k | switch (fs) { |
193 | 180 | case 16000: { |
194 | 180 | return (minimum_k0 + vector_offset_16k[start_freq]); |
195 | 0 | } break; |
196 | | |
197 | 92 | case 22050: { |
198 | 92 | return (minimum_k0 + vector_offset_22k[start_freq]); |
199 | 0 | } break; |
200 | | |
201 | 274 | case 24000: { |
202 | 274 | return (minimum_k0 + vector_offset_24k[start_freq]); |
203 | 0 | } break; |
204 | | |
205 | 5.89k | case 32000: { |
206 | 5.89k | return (minimum_k0 + vector_offset_32k[start_freq]); |
207 | 0 | } break; |
208 | | |
209 | 6.03k | case 44100: |
210 | 13.9k | case 48000: |
211 | 14.0k | case 64000: { |
212 | 14.0k | return (minimum_k0 + vector_offset_44_48_64[start_freq]); |
213 | 13.9k | } 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 | 172 | default: { |
221 | 172 | return (minimum_k0 + vector_offset_def[start_freq]); |
222 | 0 | } |
223 | 20.7k | } |
224 | 20.7k | } |
225 | | |
226 | 4.76k | static WORD32 ixheaace_get_stop_freq(WORD32 fs, WORD32 stop_freq) { |
227 | 4.76k | WORD32 result, i; |
228 | 4.76k | WORD32 *v_stop_freq = 0; |
229 | 4.76k | WORD32 k1_min; |
230 | 4.76k | WORD32 v_dstop[13]; |
231 | | |
232 | 4.76k | 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.55k | case 32000: |
246 | 1.55k | k1_min = 32; |
247 | | |
248 | 1.55k | v_stop_freq = (WORD32 *)vector_stop_freq_32; |
249 | 1.55k | break; |
250 | | |
251 | 1.63k | case 44100: |
252 | 1.63k | k1_min = 23; |
253 | | |
254 | 1.63k | v_stop_freq = (WORD32 *)vector_stop_freq_44; |
255 | 1.63k | break; |
256 | | |
257 | 1.58k | case 48000: |
258 | 1.58k | k1_min = 21; |
259 | | |
260 | 1.58k | v_stop_freq = (WORD32 *)vector_stop_freq_48; |
261 | 1.58k | break; |
262 | | |
263 | 0 | default: |
264 | 0 | v_stop_freq = (WORD32 *)vector_stop_freq_32; |
265 | 0 | k1_min = 21; /* illegal fs */ |
266 | 4.76k | } |
267 | | |
268 | 66.7k | for (i = 0; i <= 12; i++) { |
269 | 61.9k | v_dstop[i] = v_stop_freq[i + 1] - v_stop_freq[i]; |
270 | 61.9k | } |
271 | | |
272 | 4.76k | ixheaace_shellsort_int(v_dstop, 13); |
273 | | |
274 | 4.76k | result = k1_min; |
275 | | |
276 | 40.5k | for (i = 0; i < stop_freq; i++) { |
277 | 35.7k | result = result + v_dstop[i]; |
278 | 35.7k | } |
279 | | |
280 | 4.76k | return result; |
281 | 4.76k | } |
282 | | |
283 | | static WORD32 ixheaace_get_usac_stop_freq(WORD32 fs, WORD32 stop_freq) |
284 | 3.25k | { |
285 | 3.25k | WORD32 result, i; |
286 | 3.25k | WORD32 *v_stop_freq = 0; |
287 | 3.25k | WORD32 k1_min; |
288 | 3.25k | WORD32 v_dstop[13]; |
289 | | |
290 | 3.25k | switch (fs) |
291 | 3.25k | { |
292 | 62 | case 16000: |
293 | 62 | k1_min = ixheaace_usac_stop_freq_16k[0]; |
294 | 62 | v_stop_freq = (WORD32 *)&ixheaace_usac_stop_freq_16k[0]; |
295 | 62 | break; |
296 | 33 | case 22050: |
297 | 33 | k1_min = ixheaace_usac_stop_freq_22k[0]; |
298 | 33 | v_stop_freq = (WORD32 *)&ixheaace_usac_stop_freq_22k[0]; |
299 | 33 | break; |
300 | 116 | case 24000: |
301 | 116 | k1_min = ixheaace_usac_stop_freq_24k[0]; |
302 | 116 | v_stop_freq = (WORD32 *)&ixheaace_usac_stop_freq_24k[0]; |
303 | 116 | break; |
304 | 741 | case 32000: |
305 | 741 | k1_min = 32; |
306 | 741 | v_stop_freq = (WORD32 *)vector_stop_freq_32; |
307 | 741 | break; |
308 | | |
309 | 720 | case 44100: |
310 | 720 | k1_min = 23; |
311 | 720 | v_stop_freq = (WORD32 *)vector_stop_freq_44; |
312 | 720 | break; |
313 | | |
314 | 1.52k | case 48000: |
315 | 1.52k | k1_min = 21; |
316 | 1.52k | v_stop_freq = (WORD32 *)vector_stop_freq_48; |
317 | 1.52k | break; |
318 | | |
319 | 67 | default: |
320 | 67 | v_stop_freq = (WORD32 *)vector_stop_freq_32; |
321 | 67 | k1_min = 21; /* illegal fs */ |
322 | 3.25k | } |
323 | | |
324 | 45.6k | for (i = 0; i <= 12; i++) |
325 | 42.3k | { |
326 | 42.3k | v_dstop[i] = v_stop_freq[i + 1] - v_stop_freq[i]; |
327 | 42.3k | } |
328 | | |
329 | 3.25k | ixheaace_shellsort_int(v_dstop, 13); |
330 | | |
331 | 3.25k | result = k1_min; |
332 | | |
333 | 38.2k | for (i = 0; i < stop_freq; i++) |
334 | 35.0k | { |
335 | 35.0k | result = result + v_dstop[i]; |
336 | 35.0k | } |
337 | | |
338 | 3.25k | return result; |
339 | 3.25k | } |
340 | | |
341 | | WORD32 |
342 | 12.6k | ixheaace_get_sbr_start_freq_raw(WORD32 start_freq, WORD32 qmf_bands, WORD32 fs) { |
343 | 12.6k | WORD32 result; |
344 | | |
345 | 12.6k | if (start_freq < 0 || start_freq > 15) { |
346 | 0 | return -1; |
347 | 0 | } |
348 | | |
349 | 12.6k | result = ixheaace_get_start_freq(fs, start_freq); |
350 | | |
351 | 12.6k | result = (result * fs / qmf_bands + 1) >> 1; |
352 | | |
353 | 12.6k | return result; |
354 | 12.6k | } |
355 | | |
356 | | static WORD32 ixheaace_number_of_bands(WORD32 b_p_o, WORD32 start, WORD32 stop, |
357 | 14.9k | FLOAT32 warp_fac) { |
358 | 14.9k | WORD32 result = 0; |
359 | 14.9k | result = (WORD32)(b_p_o * log((FLOAT32)(stop) / start) / (2.0 * log(2.0) * warp_fac) + 0.5); |
360 | 14.9k | result <<= 1; |
361 | 14.9k | return result; |
362 | 14.9k | } |
363 | | |
364 | 14.9k | static VOID ixheaace_calc_bands(WORD32 *ptr_diff, WORD32 start, WORD32 stop, WORD32 num_bands) { |
365 | 14.9k | WORD32 i; |
366 | 14.9k | WORD32 previous; |
367 | 14.9k | WORD32 current; |
368 | 14.9k | previous = start; |
369 | 125k | for (i = 1; i <= num_bands; i++) { |
370 | 110k | current = (WORD32)((start * pow((FLOAT32)stop / start, (FLOAT32)i / num_bands)) + 0.5f); |
371 | 110k | ptr_diff[i - 1] = current - previous; |
372 | 110k | previous = current; |
373 | 110k | } |
374 | 14.9k | } |
375 | | |
376 | 503 | static VOID ixheaace_modify_bands(WORD32 max_band_previous, WORD32 *ptr_diff, WORD32 length) { |
377 | 503 | WORD32 change = max_band_previous - ptr_diff[0]; |
378 | | |
379 | 503 | if (change > (ptr_diff[length - 1] - ptr_diff[0]) / 2) { |
380 | 503 | change = (ptr_diff[length - 1] - ptr_diff[0]) / 2; |
381 | 503 | } |
382 | | |
383 | 503 | ptr_diff[0] += change; |
384 | | |
385 | 503 | ptr_diff[length - 1] -= change; |
386 | | |
387 | 503 | ixheaace_shellsort_int(ptr_diff, length); |
388 | 503 | } |
389 | | |
390 | | static VOID ixheaace_cum_sum(WORD32 start_value, WORD32 *ptr_diff, WORD32 length, |
391 | 14.9k | UWORD8 *ptr_start_adress) { |
392 | 14.9k | WORD32 i; |
393 | | |
394 | 14.9k | ptr_start_adress[0] = (UWORD8)start_value; |
395 | | |
396 | 124k | for (i = 1; i <= length; i++) { |
397 | 110k | ptr_start_adress[i] = ptr_start_adress[i - 1] + (UWORD8)ptr_diff[i - 1]; |
398 | 110k | } |
399 | 14.9k | } |
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 | 8.59k | ixheaace_sbr_codec_type sbr_codec) { |
407 | 8.59k | switch (sbr_codec) { |
408 | 3.82k | case USAC_SBR: { |
409 | 3.82k | if (sbr_ratio_idx == USAC_SBR_RATIO_INDEX_4_1) { |
410 | 570 | *ptr_k0 = ixheaace_get_start_freq_4_1(sampling_freq, start_freq); |
411 | 3.25k | } else { |
412 | 3.25k | *ptr_k0 = ixheaace_get_start_freq(sampling_freq, start_freq); |
413 | 3.25k | } |
414 | 3.82k | break; |
415 | 0 | } |
416 | 4.76k | default: { |
417 | 4.76k | *ptr_k0 = ixheaace_get_start_freq(sampling_freq, start_freq); |
418 | 4.76k | break; |
419 | 0 | } |
420 | 8.59k | } |
421 | 8.59k | 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 | 8.59k | if (stop_freq < 14) { |
426 | 8.59k | switch (sbr_codec) { |
427 | 3.82k | case USAC_SBR: { |
428 | 3.82k | if (USAC_SBR_RATIO_INDEX_4_1 == sbr_ratio_idx) { |
429 | 570 | *ptr_k2 = ixheaace_get_stop_freq_4_1(sampling_freq, stop_freq); |
430 | 3.25k | } else { |
431 | 3.25k | *ptr_k2 = ixheaace_get_usac_stop_freq(sampling_freq, stop_freq); |
432 | 3.25k | } |
433 | 3.82k | break; |
434 | 0 | } |
435 | 4.76k | default: { |
436 | 4.76k | *ptr_k2 = ixheaace_get_stop_freq(sampling_freq, stop_freq); |
437 | 4.76k | break; |
438 | 0 | } |
439 | 8.59k | } |
440 | 8.59k | } |
441 | | |
442 | 0 | else { |
443 | 0 | *ptr_k2 = (stop_freq == 14 ? 2 * *ptr_k0 : 3 * *ptr_k0); |
444 | 0 | } |
445 | | |
446 | 8.59k | if (*ptr_k2 > num_channels) { |
447 | 0 | *ptr_k2 = num_channels; |
448 | 0 | } |
449 | 8.59k | if (sbr_codec == USAC_SBR) { |
450 | 3.82k | if (sbr_ratio_idx == USAC_SBR_RATIO_INDEX_4_1) { |
451 | 570 | 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 | 570 | 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 | 570 | 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 | 3.25k | } else { |
461 | 3.25k | if (sampling_freq <= 32000) { |
462 | 1.01k | if ((*ptr_k2 - *ptr_k0) > MAXIMUM_FREQ_COEFFS_LE32KHZ) { |
463 | 0 | return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_FREQ_COEFFS; |
464 | 0 | } |
465 | 2.24k | } else if (sampling_freq == 44100) { |
466 | 720 | if ((*ptr_k2 - *ptr_k0) > MAXIMUM_FREQ_COEFFS_EQ44KHZ) { |
467 | 0 | return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_FREQ_COEFFS; |
468 | 0 | } |
469 | 1.52k | } else if (sampling_freq >= 48000) { |
470 | 1.52k | if ((*ptr_k2 - *ptr_k0) > MAXIMUM_FREQ_COEFFS_GE48KHZ) { |
471 | 46 | return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_FREQ_COEFFS; |
472 | 46 | } |
473 | 1.52k | } else { |
474 | 0 | return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_FREQ_COEFFS; |
475 | 0 | } |
476 | 3.25k | } |
477 | 4.76k | } else { |
478 | 4.76k | if (sampling_freq <= 32000) { |
479 | 1.55k | if ((*ptr_k2 - *ptr_k0) > MAXIMUM_FREQ_COEFFS_LE32KHZ) { |
480 | 0 | return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_FREQ_COEFFS; |
481 | 0 | } |
482 | 3.21k | } else if (sampling_freq == 44100) { |
483 | 1.63k | if ((*ptr_k2 - *ptr_k0) > MAXIMUM_FREQ_COEFFS_EQ44KHZ) { |
484 | 0 | return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_FREQ_COEFFS; |
485 | 0 | } |
486 | 1.63k | } else if (sampling_freq >= 48000) { |
487 | 1.58k | if ((*ptr_k2 - *ptr_k0) > MAXIMUM_FREQ_COEFFS_GE48KHZ) { |
488 | 0 | return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_FREQ_COEFFS; |
489 | 0 | } |
490 | 1.58k | } else { |
491 | 0 | return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_FREQ_COEFFS; |
492 | 0 | } |
493 | 4.76k | } |
494 | | |
495 | 8.55k | if ((*ptr_k2 - *ptr_k0) < 0) { |
496 | 0 | return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_FREQ_COEFFS; |
497 | 0 | } |
498 | | |
499 | 8.55k | return IA_NO_ERROR; |
500 | 8.55k | } |
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 | 8.55k | { |
508 | 8.55k | IA_ERRORCODE err_code = IA_NO_ERROR; |
509 | 8.55k | WORD32 b_p_o = 0; |
510 | 8.55k | WORD32 dk = 0; |
511 | | |
512 | 8.55k | FLOAT32 warp; |
513 | 8.55k | WORD32 k1 = 0, i; |
514 | 8.55k | WORD32 num_bands0; |
515 | 8.55k | WORD32 num_bands1; |
516 | 8.55k | WORD32 diff_tot[IXHEAACE_MAXIMUM_OCTAVE + IXHEAACE_MAXIMUM_SECOND_REGION] = {0}; |
517 | 8.55k | WORD32 *diff0 = diff_tot; |
518 | 8.55k | WORD32 *diff1 = diff_tot + IXHEAACE_MAXIMUM_OCTAVE; |
519 | 8.55k | WORD32 k2_achived; |
520 | 8.55k | WORD32 k2_diff; |
521 | 8.55k | WORD32 incr = 0; |
522 | | |
523 | 8.55k | switch (freq_scale) { |
524 | 4.75k | case 1: |
525 | 4.75k | b_p_o = 12; |
526 | 4.75k | break; |
527 | 1.54k | case 2: |
528 | 1.54k | b_p_o = 10; |
529 | 1.54k | break; |
530 | 2.25k | case 3: |
531 | 2.25k | b_p_o = 8; |
532 | 2.25k | break; |
533 | 8.55k | } |
534 | | |
535 | 8.55k | if (freq_scale > 0) { |
536 | 8.55k | if (alter_scale == 0) { |
537 | 0 | warp = 1.0f; |
538 | 8.55k | } else { |
539 | 8.55k | warp = 1.3f; |
540 | 8.55k | } |
541 | | |
542 | 8.55k | if (IXHEAACE_QUAD_RATE == sbr_rate) { |
543 | 570 | if (k0 < b_p_o) { |
544 | 0 | b_p_o = (k0 >> 1) * 2; |
545 | 0 | } |
546 | 570 | } |
547 | | |
548 | 8.55k | if (4 * k2 >= 9 * k0) { |
549 | 6.41k | k1 = 2 * k0; |
550 | 6.41k | num_bands0 = ixheaace_number_of_bands(b_p_o, k0, k1, 1.0f); |
551 | 6.41k | num_bands1 = ixheaace_number_of_bands(b_p_o, k1, k2, warp); |
552 | | |
553 | 6.41k | ixheaace_calc_bands(diff0, k0, k1, num_bands0); |
554 | 6.41k | ixheaace_shellsort_int(diff0, num_bands0); |
555 | | |
556 | 6.41k | if (diff0[0] == 0) { |
557 | 8 | return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_NUM_BANDS; |
558 | 8 | } |
559 | | |
560 | 6.40k | ixheaace_cum_sum(k0, diff0, num_bands0, ptr_k_master); |
561 | | |
562 | 6.40k | ixheaace_calc_bands(diff1, k1, k2, num_bands1); |
563 | 6.40k | ixheaace_shellsort_int(diff1, num_bands1); |
564 | | |
565 | 6.40k | if (diff0[num_bands0 - 1] > diff1[0]) { |
566 | 503 | ixheaace_modify_bands(diff0[num_bands0 - 1], diff1, num_bands1); |
567 | 503 | } |
568 | | |
569 | 6.40k | ixheaace_cum_sum(k1, diff1, num_bands1, &ptr_k_master[num_bands0]); |
570 | 6.40k | *ptr_num_bands = num_bands0 + num_bands1; |
571 | 6.40k | } else { |
572 | 2.14k | k1 = k2; |
573 | 2.14k | num_bands0 = ixheaace_number_of_bands(b_p_o, k0, k1, 1.0f); |
574 | | |
575 | 2.14k | ixheaace_calc_bands(diff0, k0, k1, num_bands0); |
576 | 2.14k | ixheaace_shellsort_int(diff0, num_bands0); |
577 | | |
578 | 2.14k | if (diff0[0] == 0) { |
579 | 0 | return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_NUM_BANDS; |
580 | 0 | } |
581 | | |
582 | 2.14k | ixheaace_cum_sum(k0, diff0, num_bands0, ptr_k_master); |
583 | | |
584 | 2.14k | *ptr_num_bands = num_bands0; |
585 | 2.14k | } |
586 | 8.55k | } 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 | 8.54k | if (*ptr_num_bands < 1) { |
628 | 0 | return IA_EXHEAACE_INIT_FATAL_SBR_INVALID_NUM_BANDS; |
629 | 0 | } |
630 | | |
631 | 8.54k | if (sbr_rate == IXHEAACE_QUAD_RATE) { |
632 | 8.61k | for (i = 1; i < *ptr_num_bands; i++) { |
633 | 8.04k | 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.04k | } |
637 | 562 | } |
638 | | |
639 | 8.54k | return err_code; |
640 | 8.54k | } |
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 | 8.54k | ixheaace_sr_mode dr_or_sr, WORD32 num_qmf_ch) { |
645 | 8.54k | WORD32 i; |
646 | 8.54k | WORD32 divider; |
647 | 8.54k | WORD32 max1, max2; |
648 | | |
649 | 8.54k | divider = (dr_or_sr == IXHEAACE_DUAL_RATE) ? 2 : 1; |
650 | 8.54k | if (dr_or_sr == IXHEAACE_QUAD_RATE) { |
651 | 562 | divider = 4; |
652 | 562 | } |
653 | | |
654 | 8.54k | if ((ptr_k_master[*ptr_xover_band] > (num_qmf_ch / divider)) || |
655 | 8.54k | (*ptr_xover_band > num_master)) { |
656 | 0 | max1 = 0; |
657 | 0 | max2 = num_master; |
658 | |
|
659 | 0 | while ((ptr_k_master[max1 + 1] < (num_qmf_ch / divider)) && ((max1 + 1) < max2)) { |
660 | 0 | max1++; |
661 | 0 | } |
662 | |
|
663 | 0 | *ptr_xover_band = max1; |
664 | 0 | } |
665 | | |
666 | 8.54k | *ptr_num_hires = num_master - *ptr_xover_band; |
667 | | |
668 | 127k | for (i = *ptr_xover_band; i <= num_master; i++) { |
669 | 118k | ptr_hires[i - *ptr_xover_band] = ptr_k_master[i]; |
670 | 118k | } |
671 | 8.54k | } |
672 | | |
673 | | VOID ixheaace_update_low_res(UWORD8 *ptr_lores, WORD32 *ptr_num_lores, UWORD8 *ptr_hires, |
674 | 8.54k | WORD32 ptr_num_hires) { |
675 | 8.54k | WORD32 i; |
676 | | |
677 | 8.54k | if (ptr_num_hires % 2 == 0) { |
678 | 8.54k | *ptr_num_lores = ptr_num_hires / 2; |
679 | | |
680 | 72.1k | for (i = 0; i <= *ptr_num_lores; i++) { |
681 | 63.5k | ptr_lores[i] = ptr_hires[i * 2]; |
682 | 63.5k | } |
683 | 8.54k | } 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 | 8.54k | } |