xref: /aosp_15_r20/external/libxaac/encoder/ixheaace_mps_bitstream.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 <stdlib.h>
22 #include <math.h>
23 #include "ixheaac_type_def.h"
24 #include "impd_drc_common_enc.h"
25 #include "impd_drc_uni_drc.h"
26 #include "impd_drc_tables.h"
27 #include "impd_drc_api.h"
28 #include "ixheaace_api.h"
29 #include "ixheaac_error_standards.h"
30 #include "ixheaace_error_codes.h"
31 #include "ixheaace_mps_common_fix.h"
32 #include "ixheaace_mps_defines.h"
33 #include "ixheaace_mps_common_define.h"
34 #include "ixheaace_bitbuffer.h"
35 
36 #include "ixheaace_mps_nlc_enc.h"
37 #include "ixheaac_constants.h"
38 #include "ixheaace_aac_constants.h"
39 #include "ixheaace_common_rom.h"
40 
41 #include "ixheaace_mps_struct_def.h"
42 #include "ixheaace_mps_sac_polyphase.h"
43 #include "ixheaace_mps_sac_nlc_enc.h"
44 #include "ixheaace_mps_sac_hybfilter.h"
45 #include "ixheaace_mps_bitstream.h"
46 #include "ixheaace_mps_spatial_bitstream.h"
47 #include "ixheaace_mps_param_extract.h"
48 #include "ixheaace_mps_tree.h"
49 #include "ixheaace_mps_rom.h"
50 
ixheaace_mps_212_get_bs_freq_res_stride(const WORD32 index)51 static UWORD8 ixheaace_mps_212_get_bs_freq_res_stride(const WORD32 index) {
52   WORD32 freq_res_stride_table_size = 0;
53   const UWORD8 *ptr_freq_res_stride_table = NULL;
54 
55   ptr_freq_res_stride_table = freq_res_stride_table_212;
56   freq_res_stride_table_size =
57       sizeof(freq_res_stride_table_212) / sizeof(*freq_res_stride_table_212);
58 
59   return (((index >= 0) && (index < freq_res_stride_table_size))
60               ? ptr_freq_res_stride_table[index]
61               : 1);
62 }
63 
ixheaace_mps_212_get_bs_freq_res_index(const WORD32 num_bands,WORD32 * const ptr_bs_freq_res_index,WORD32 aot)64 static IA_ERRORCODE ixheaace_mps_212_get_bs_freq_res_index(const WORD32 num_bands,
65                                                            WORD32 *const ptr_bs_freq_res_index,
66                                                            WORD32 aot) {
67   IA_ERRORCODE error = IA_NO_ERROR;
68   WORD32 idx;
69   const UWORD8 *p_freq_res_bin_table;
70   *ptr_bs_freq_res_index = -1;
71 
72   if (aot == AOT_AAC_ELD) {
73     p_freq_res_bin_table = freq_res_bin_table_ld;
74   } else {
75     p_freq_res_bin_table = freq_res_bin_table_usac;
76   }
77   for (idx = 0; idx < MAX_FREQ_RES_INDEX; idx++) {
78     if (num_bands == p_freq_res_bin_table[idx]) {
79       *ptr_bs_freq_res_index = idx;
80       break;
81     }
82   }
83   if (*ptr_bs_freq_res_index < 0 || *ptr_bs_freq_res_index >= MAX_FREQ_RES_INDEX) {
84     return IA_EXHEAACE_CONFIG_NONFATAL_MPS_INVALID_CONFIG;
85   }
86   return error;
87 }
88 
ixheaace_mps_212_get_sampling_frequency_index(const UWORD32 bs_sampling_frequency,WORD32 * const ptr_bs_sampling_frequency_index)89 static VOID ixheaace_mps_212_get_sampling_frequency_index(
90     const UWORD32 bs_sampling_frequency, WORD32 *const ptr_bs_sampling_frequency_index) {
91   WORD32 idx;
92   *ptr_bs_sampling_frequency_index = SAMPLING_FREQUENCY_INDEX_ESCAPE;
93 
94   for (idx = 0; idx < MAX_SAMPLING_FREQUENCY_INDEX; idx++) {
95     if (bs_sampling_frequency == ia_sampl_freq_table[idx]) {
96       *ptr_bs_sampling_frequency_index = idx;
97       break;
98     }
99   }
100 }
101 
ixheaace_mps_212_ec_data(ixheaace_bit_buf_handle pstr_bit_buf,WORD8 data[MAX_NUM_PARAMS][MAX_NUM_BINS],WORD8 old_data[MAX_NUM_BINS],UWORD8 quant_coarse_xxx_prev[MAX_NUM_PARAMS],ixheaace_mps_lossless_data * const pstr_lossless_data,const WORD32 data_type,const WORD32 param_idx,const WORD32 num_param_sets,const WORD32 independency_flag,const WORD32 start_band,const WORD32 stop_band,const WORD32 default_value)102 static IA_ERRORCODE ixheaace_mps_212_ec_data(
103     ixheaace_bit_buf_handle pstr_bit_buf, WORD8 data[MAX_NUM_PARAMS][MAX_NUM_BINS],
104     WORD8 old_data[MAX_NUM_BINS], UWORD8 quant_coarse_xxx_prev[MAX_NUM_PARAMS],
105     ixheaace_mps_lossless_data *const pstr_lossless_data, const WORD32 data_type,
106     const WORD32 param_idx, const WORD32 num_param_sets, const WORD32 independency_flag,
107     const WORD32 start_band, const WORD32 stop_band, const WORD32 default_value) {
108   IA_ERRORCODE error;
109   WORD32 ps, pb, str_offset, pb_stride, i;
110   WORD16 data_bands;
111   WORD32 a_strides[MAX_NUM_BINS + 1] = {0};
112   WORD16 cmp_idx_data[2][MAX_NUM_BINS] = {{0}};
113   WORD16 cmp_old_data[MAX_NUM_BINS] = {0};
114 
115   if (num_param_sets > MAX_NUM_PARAMS) {
116     return IA_EXHEAACE_EXE_FATAL_MPS_INVALID_NUM_PARAM_SETS;
117   }
118 
119   if (independency_flag || (pstr_lossless_data->bs_quant_coarse_xxx[param_idx][0] !=
120                             quant_coarse_xxx_prev[param_idx])) {
121     pstr_lossless_data->bs_xxx_data_mode[param_idx][0] = IXHEAACE_MPS_DATA_MODE_FINECOARSE;
122   } else {
123     pstr_lossless_data->bs_xxx_data_mode[param_idx][0] = IXHEAACE_MPS_DATA_MODE_KEEP;
124     for (i = start_band; i < stop_band; i++) {
125       if (data[0][i] != old_data[i]) {
126         pstr_lossless_data->bs_xxx_data_mode[param_idx][0] = IXHEAACE_MPS_DATA_MODE_FINECOARSE;
127         break;
128       }
129     }
130   }
131 
132   ixheaace_write_bits(pstr_bit_buf, pstr_lossless_data->bs_xxx_data_mode[param_idx][0], 2);
133 
134   for (ps = 1; ps < num_param_sets; ps++) {
135     if (pstr_lossless_data->bs_quant_coarse_xxx[param_idx][ps] !=
136         pstr_lossless_data->bs_quant_coarse_xxx[param_idx][ps - 1]) {
137       pstr_lossless_data->bs_xxx_data_mode[param_idx][ps] = IXHEAACE_MPS_DATA_MODE_FINECOARSE;
138     } else {
139       pstr_lossless_data->bs_xxx_data_mode[param_idx][ps] = IXHEAACE_MPS_DATA_MODE_KEEP;
140       for (i = start_band; i < stop_band; i++) {
141         if (data[ps][i] != data[ps - 1][i]) {
142           pstr_lossless_data->bs_xxx_data_mode[param_idx][ps] = IXHEAACE_MPS_DATA_MODE_FINECOARSE;
143           break;
144         }
145       }
146     }
147 
148     ixheaace_write_bits(pstr_bit_buf, pstr_lossless_data->bs_xxx_data_mode[param_idx][ps], 2);
149   }
150 
151   for (ps = 0; ps < (num_param_sets - 1); ps++) {
152     if (pstr_lossless_data->bs_xxx_data_mode[param_idx][ps] ==
153         IXHEAACE_MPS_DATA_MODE_FINECOARSE) {
154       if (pstr_lossless_data->bs_xxx_data_mode[param_idx][ps + 1] ==
155           IXHEAACE_MPS_DATA_MODE_FINECOARSE) {
156         if ((pstr_lossless_data->bs_quant_coarse_xxx[param_idx][ps + 1] ==
157              pstr_lossless_data->bs_quant_coarse_xxx[param_idx][ps]) &&
158             (pstr_lossless_data->bs_freq_res_stride_xxx[param_idx][ps + 1] ==
159              pstr_lossless_data->bs_freq_res_stride_xxx[param_idx][ps])) {
160           pstr_lossless_data->bs_data_pair[param_idx][ps] = 1;
161           pstr_lossless_data->bs_data_pair[param_idx][ps + 1] = 1;
162           ps++;
163           continue;
164         }
165       }
166 
167       pstr_lossless_data->bs_data_pair[param_idx][ps] = 0;
168 
169       pstr_lossless_data->bs_data_pair[param_idx][ps + 1] = 0;
170     } else {
171       pstr_lossless_data->bs_data_pair[param_idx][ps] = 0;
172       pstr_lossless_data->bs_data_pair[param_idx][ps + 1] = 0;
173     }
174   }
175 
176   for (ps = 0; ps < num_param_sets; ps++) {
177     if (pstr_lossless_data->bs_xxx_data_mode[param_idx][ps] == IXHEAACE_MPS_DATA_MODE_DEFAULT) {
178       for (i = start_band; i < stop_band; i++) {
179         old_data[i] = (WORD8)default_value;
180       }
181       quant_coarse_xxx_prev[param_idx] = 0;
182     }
183 
184     if (pstr_lossless_data->bs_xxx_data_mode[param_idx][ps] ==
185         IXHEAACE_MPS_DATA_MODE_FINECOARSE) {
186       ixheaace_write_bits(pstr_bit_buf, pstr_lossless_data->bs_data_pair[param_idx][ps], 1);
187       ixheaace_write_bits(pstr_bit_buf, pstr_lossless_data->bs_quant_coarse_xxx[param_idx][ps],
188                           1);
189       ixheaace_write_bits(pstr_bit_buf, pstr_lossless_data->bs_freq_res_stride_xxx[param_idx][ps],
190                           2);
191 
192       if (pstr_lossless_data->bs_quant_coarse_xxx[param_idx][ps] !=
193           quant_coarse_xxx_prev[param_idx]) {
194         if (quant_coarse_xxx_prev[param_idx]) {
195           for (i = start_band; i < stop_band; i++) {
196             old_data[i] *= 2;
197           }
198 
199           if (data_type == IXHEAACE_MPS_SAC_DATA_TYPE_CLD) {
200             for (i = start_band; i < stop_band; i++) {
201               if (old_data[i] == -14) {
202                 old_data[i] = -15;
203               } else if (old_data[i] == 14) {
204                 old_data[i] = 15;
205               }
206             }
207           }
208         } else {
209           for (i = start_band; i < stop_band; i++) {
210             old_data[i] /= 2;
211           }
212         }
213       }
214 
215       pb_stride = ixheaace_mps_212_get_bs_freq_res_stride(
216           pstr_lossless_data->bs_freq_res_stride_xxx[param_idx][ps]);
217       data_bands = (WORD16)((stop_band - start_band - 1) / pb_stride + 1);
218 
219       a_strides[0] = start_band;
220       for (pb = 1; pb <= data_bands; pb++) {
221         a_strides[pb] = a_strides[pb - 1] + pb_stride;
222       }
223 
224       str_offset = 0;
225       while (a_strides[data_bands] > stop_band) {
226         if (str_offset < data_bands) {
227           str_offset++;
228         }
229         for (i = str_offset; i <= data_bands; i++) {
230           a_strides[i]--;
231         }
232       }
233 
234       for (pb = 0; pb < data_bands; pb++) {
235         cmp_old_data[start_band + pb] = old_data[a_strides[pb]];
236         cmp_idx_data[0][start_band + pb] = data[ps][a_strides[pb]];
237 
238         if (pstr_lossless_data->bs_data_pair[param_idx][ps]) {
239           cmp_idx_data[1][start_band + pb] = data[ps + 1][a_strides[pb]];
240         }
241       }
242 
243       if (pstr_lossless_data->bs_data_pair[param_idx][ps]) {
244         error = ixheaace_mps_212_ec_data_pair_enc(
245             pstr_bit_buf, cmp_idx_data, cmp_old_data, data_type, 0, start_band, data_bands,
246             pstr_lossless_data->bs_quant_coarse_xxx[param_idx][ps],
247             independency_flag && (ps == 0));
248         if (error != IA_NO_ERROR) {
249           return error;
250         }
251       } else {
252         error = ixheaace_mps_212_ec_data_single_enc(
253             pstr_bit_buf, cmp_idx_data, cmp_old_data, data_type, 0, start_band, data_bands,
254             pstr_lossless_data->bs_quant_coarse_xxx[param_idx][ps],
255             independency_flag && (ps == 0));
256         if (error != IA_NO_ERROR) {
257           return error;
258         }
259       }
260       for (i = start_band; i < stop_band; i++) {
261         if (pstr_lossless_data->bs_data_pair[param_idx][ps]) {
262           old_data[i] = data[ps + 1][i];
263         } else {
264           old_data[i] = data[ps][i];
265         }
266       }
267 
268       quant_coarse_xxx_prev[param_idx] = pstr_lossless_data->bs_quant_coarse_xxx[param_idx][ps];
269 
270       if (pstr_lossless_data->bs_data_pair[param_idx][ps]) {
271         ps++;
272       }
273     }
274   }
275   return IA_NO_ERROR;
276 }
277 
ixheaace_mps_212_write_smg_data(ixheaace_bit_buf_handle pstr_bit_buf,const ixheaace_mps_smg_data * const pstr_smg_data,const WORD32 num_param_sets,const WORD32 data_bands)278 static VOID ixheaace_mps_212_write_smg_data(ixheaace_bit_buf_handle pstr_bit_buf,
279                                             const ixheaace_mps_smg_data *const pstr_smg_data,
280                                             const WORD32 num_param_sets,
281                                             const WORD32 data_bands) {
282   WORD32 param, band;
283 
284   for (param = 0; param < num_param_sets; param++) {
285     ixheaace_write_bits(pstr_bit_buf, pstr_smg_data->bs_smooth_mode[param], 2);
286     if (pstr_smg_data->bs_smooth_mode[param] >= 2) {
287       ixheaace_write_bits(pstr_bit_buf, pstr_smg_data->bs_smooth_time[param], 2);
288     }
289     if (pstr_smg_data->bs_smooth_mode[param] == 3) {
290       WORD32 stride =
291           ixheaace_mps_212_get_bs_freq_res_stride(pstr_smg_data->bs_freq_res_stride[param]);
292       ixheaace_write_bits(pstr_bit_buf, pstr_smg_data->bs_freq_res_stride[param], 2);
293       for (band = 0; band < data_bands; band += stride) {
294         ixheaace_write_bits(pstr_bit_buf, pstr_smg_data->bs_smg_data[param][band], 1);
295       }
296     }
297   }
298 }
299 
ixheaace_mps_212_write_ott_data(ixheaace_bit_buf_handle pstr_bit_buf,ixheaace_mps_prev_ott_data * const pstr_prev_ott_data,ixheaace_mps_ott_data * const pstr_ott_data,const ixheaace_mps_ott_config ott_config[IXHEAACE_MPS_MAX_NUM_BOXES],ixheaace_mps_lossless_data * const pstr_cld_lossless_data,ixheaace_mps_lossless_data * const pstr_icc_lossless_data,const WORD32 num_ott_boxes,const WORD32 num_bands,const WORD32 num_param_sets,const WORD32 bs_independency_flag)300 static IA_ERRORCODE ixheaace_mps_212_write_ott_data(
301     ixheaace_bit_buf_handle pstr_bit_buf, ixheaace_mps_prev_ott_data *const pstr_prev_ott_data,
302     ixheaace_mps_ott_data *const pstr_ott_data,
303     const ixheaace_mps_ott_config ott_config[IXHEAACE_MPS_MAX_NUM_BOXES],
304     ixheaace_mps_lossless_data *const pstr_cld_lossless_data,
305     ixheaace_mps_lossless_data *const pstr_icc_lossless_data, const WORD32 num_ott_boxes,
306     const WORD32 num_bands, const WORD32 num_param_sets, const WORD32 bs_independency_flag) {
307   IA_ERRORCODE error = IA_NO_ERROR;
308   WORD32 box;
309   for (box = 0; box < num_ott_boxes; box++) {
310     error = ixheaace_mps_212_ec_data(
311         pstr_bit_buf, pstr_ott_data->cld[box], pstr_prev_ott_data->cld_old[box],
312         pstr_prev_ott_data->quant_coarse_cld_prev[box], pstr_cld_lossless_data,
313         IXHEAACE_MPS_SAC_DATA_TYPE_CLD, box, num_param_sets, bs_independency_flag, 0,
314         ott_config[box].bs_ott_bands, 15);
315     if (error != IA_NO_ERROR) {
316       return error;
317     }
318   }
319   for (box = 0; box < num_ott_boxes; box++) {
320     error = ixheaace_mps_212_ec_data(pstr_bit_buf, pstr_ott_data->icc[box],
321                                      pstr_prev_ott_data->icc_old[box],
322                                      pstr_prev_ott_data->quant_coarse_icc_prev[box],
323                                      pstr_icc_lossless_data, IXHEAACE_MPS_SAC_DATA_TYPE_ICC, box,
324                                      num_param_sets, bs_independency_flag, 0, num_bands, 0);
325     if (error != IA_NO_ERROR) {
326       return error;
327     }
328   }
329 
330   return IA_NO_ERROR;
331 }
332 
ixheaace_mps_212_write_framing_info(ixheaace_bit_buf_handle pstr_bit_buf,const ixheaace_mps_framing_info * const pstr_framing_info,const WORD32 frame_length)333 static VOID ixheaace_mps_212_write_framing_info(
334     ixheaace_bit_buf_handle pstr_bit_buf,
335     const ixheaace_mps_framing_info *const pstr_framing_info, const WORD32 frame_length) {
336   ixheaace_write_bits(pstr_bit_buf, pstr_framing_info->bs_framing_type, 1);
337   ixheaace_write_bits(pstr_bit_buf, pstr_framing_info->num_param_sets - 1, 1);
338 
339   if (pstr_framing_info->bs_framing_type) {
340     WORD32 ps = 0;
341     UWORD8 bits_param_slot = 0;
342     WORD32 num_param_sets = pstr_framing_info->num_param_sets;
343     while ((1 << bits_param_slot) < (frame_length + 1)) {
344       bits_param_slot++;
345     }
346     if (bits_param_slot > 0) {
347       for (ps = 0; ps < num_param_sets; ps++) {
348         ixheaace_write_bits(pstr_bit_buf, pstr_framing_info->bs_param_slots[ps], bits_param_slot);
349       }
350     }
351   }
352 }
353 
ixheaace_mps_515_ec_data(ixheaace_bit_buf_handle pstr_bit_buf,WORD32 data[MAX_NUM_PARAMS][MAX_NUM_BINS],WORD32 old_data[MAX_NUM_BINS],ixheaace_mps_sac_lossless_data * pstr_lossless_data,WORD32 data_type,WORD32 param_idx,WORD32 num_param_sets,WORD32 independency_flag,WORD32 start_band,WORD32 stop_band)354 static IA_ERRORCODE ixheaace_mps_515_ec_data(ixheaace_bit_buf_handle pstr_bit_buf,
355                                              WORD32 data[MAX_NUM_PARAMS][MAX_NUM_BINS],
356                                              WORD32 old_data[MAX_NUM_BINS],
357                                              ixheaace_mps_sac_lossless_data *pstr_lossless_data,
358                                              WORD32 data_type, WORD32 param_idx,
359                                              WORD32 num_param_sets, WORD32 independency_flag,
360                                              WORD32 start_band, WORD32 stop_band) {
361   WORD32 param_set, set_idx, pb_stride, data_bands, bin, data_sets;
362   WORD32 param_set_index[MAX_NUM_PARAMS] = {0};
363 
364   for (param_set = 0; param_set < num_param_sets; param_set++) {
365     pstr_lossless_data->bs_xxx_data_mode[param_idx][param_set] =
366         IXHEAACE_MPS_DATA_MODE_FINECOARSE;
367     ixheaace_write_bits(pstr_bit_buf, pstr_lossless_data->bs_xxx_data_mode[param_idx][param_set],
368                         2);
369   }
370 
371   for (param_set = 0, set_idx = 0; param_set < num_param_sets; param_set++) {
372     param_set_index[set_idx] = param_set;
373     if (param_set != num_param_sets - 1) {
374       pstr_lossless_data->bs_data_pair[param_idx][set_idx] = 1;
375       pstr_lossless_data->bs_data_pair[param_idx][set_idx + 1] = 1;
376       param_set++;
377       set_idx += 2;
378     } else {
379       pstr_lossless_data->bs_data_pair[param_idx][set_idx] = 0;
380       set_idx++;
381     }
382   }
383   data_sets = set_idx;
384 
385   for (set_idx = 0; set_idx < data_sets;) {
386     ixheaace_write_bits(pstr_bit_buf, pstr_lossless_data->bs_data_pair[param_idx][set_idx], 1);
387     ixheaace_write_bits(pstr_bit_buf, pstr_lossless_data->bs_quant_coarse_xxx[param_idx][set_idx],
388                         1);
389     ixheaace_write_bits(pstr_bit_buf,
390                         pstr_lossless_data->bs_freq_res_stride_xxx[param_idx][set_idx], 2);
391 
392     pb_stride =
393         freq_res_stride_table[pstr_lossless_data->bs_freq_res_stride_xxx[param_idx][set_idx]];
394     data_bands = (stop_band - start_band - 1) / pb_stride + 1;
395 
396     ixheaace_mps_515_ec_data_pair_enc(
397         pstr_bit_buf, data, old_data, data_type, param_set_index[set_idx], start_band, data_bands,
398         pstr_lossless_data->bs_data_pair[param_idx][set_idx],
399         pstr_lossless_data->bs_quant_coarse_xxx[param_idx][set_idx], independency_flag);
400 
401     if (pstr_lossless_data->bs_data_pair[param_idx][set_idx]) {
402       if (pstr_lossless_data->bs_freq_res_stride_xxx[param_idx][set_idx + 1] !=
403           pstr_lossless_data->bs_freq_res_stride_xxx[param_idx][set_idx]) {
404         return IA_EXHEAACE_EXE_FATAL_MPS_INVALID_RES_STRIDE;
405       }
406       if (pstr_lossless_data->bs_quant_coarse_xxx[param_idx][set_idx + 1] !=
407           pstr_lossless_data->bs_quant_coarse_xxx[param_idx][set_idx]) {
408         return IA_EXHEAACE_EXE_FATAL_MPS_INVALID_QUANT_COARSE;
409       }
410     }
411 
412     for (bin = 0; bin < MAX_NUM_BINS; bin++) {
413       old_data[bin] = data[param_set_index[set_idx] +
414                            pstr_lossless_data->bs_data_pair[param_idx][set_idx]][bin];
415     }
416 
417     set_idx += pstr_lossless_data->bs_data_pair[param_idx][set_idx] + 1;
418   }
419   return IA_NO_ERROR;
420 }
421 
ixheaace_mps_515_icc_quant(FLOAT32 val)422 WORD32 ixheaace_mps_515_icc_quant(FLOAT32 val) {
423   FLOAT32 p_qsteps[7] = {0.9685f, 0.88909f, 0.72105f, 0.48428f, 0.18382f, -0.2945f, -0.7895f};
424   WORD32 i;
425 
426   if (val >= p_qsteps[0]) {
427     return 0;
428   }
429   for (i = 1; i < 6; i++) {
430     if ((val >= p_qsteps[i]) && (val <= p_qsteps[i - 1])) {
431       return i;
432     }
433   }
434   return 7;
435 }
436 
ixheaace_mps_515_cld_quant(FLOAT32 val)437 WORD32 ixheaace_mps_515_cld_quant(FLOAT32 val) {
438   FLOAT32 p_qsteps[30] = {-47.5, -42.5, -37.5, -32.5, -27.5, -23.5, -20.5, -17.5, -14.5, -11.5,
439                           -9.0,  -7.0,  -5.0,  -3.0,  -1.0,  1.0,   3.0,   5.0,   7.0,   9.0,
440                           11.5,  14.5,  17.5,  20.5,  23.5,  27.5,  32.5,  37.5,  42.5,  47.5};
441 
442   WORD32 i;
443 
444   if (val < p_qsteps[0]) {
445     return 0 - 15;
446   }
447   for (i = 1; i < 30; i++) {
448     if ((val <= p_qsteps[i]) && (val >= p_qsteps[i - 1])) {
449       return i - 15;
450     }
451   }
452   return 30 - 15;
453 }
454 
ixheaace_mps_515_ttt_box(WORD32 slots,FLOAT32 * ptr_real1,FLOAT32 * ptr_imag1,FLOAT32 * ptr_real2,FLOAT32 * ptr_imag2,FLOAT32 * ptr_real3,FLOAT32 * ptr_imag3,WORD32 * ptr_qclds1,WORD32 * ptr_qclds2)455 VOID ixheaace_mps_515_ttt_box(WORD32 slots, FLOAT32 *ptr_real1, FLOAT32 *ptr_imag1,
456                               FLOAT32 *ptr_real2, FLOAT32 *ptr_imag2, FLOAT32 *ptr_real3,
457                               FLOAT32 *ptr_imag3, WORD32 *ptr_qclds1, WORD32 *ptr_qclds2) {
458   WORD32 i, j;
459 
460   FLOAT32 cld_s1[PARAMETER_BANDS] = {0};
461   FLOAT32 cld_s2[PARAMETER_BANDS] = {0};
462   FLOAT32 p_pow1[MAX_HYBRID_BANDS] = {0};
463   FLOAT32 p_pow2[MAX_HYBRID_BANDS] = {0};
464   FLOAT32 p_pow3[MAX_HYBRID_BANDS] = {0};
465 
466   FLOAT32 p_pow_par_band1[PARAMETER_BANDS] = {0};
467   FLOAT32 p_pow_par_band2[PARAMETER_BANDS] = {0};
468   FLOAT32 p_pow_par_band3[PARAMETER_BANDS] = {0};
469 
470   for (i = 0; i < slots; i++) {
471     for (j = 0; j < MAX_HYBRID_BANDS; j++) {
472       p_pow1[j] += ptr_real1[i * MAX_HYBRID_BANDS + j] * ptr_real1[i * MAX_HYBRID_BANDS + j] +
473                    ptr_imag1[i * MAX_HYBRID_BANDS + j] * ptr_imag1[i * MAX_HYBRID_BANDS + j];
474       p_pow2[j] += ptr_real2[i * MAX_HYBRID_BANDS + j] * ptr_real2[i * MAX_HYBRID_BANDS + j] +
475                    ptr_imag2[i * MAX_HYBRID_BANDS + j] * ptr_imag2[i * MAX_HYBRID_BANDS + j];
476       p_pow3[j] += ptr_real3[i * MAX_HYBRID_BANDS + j] * ptr_real3[i * MAX_HYBRID_BANDS + j] +
477                    ptr_imag3[i * MAX_HYBRID_BANDS + j] * ptr_imag3[i * MAX_HYBRID_BANDS + j];
478 
479       ptr_real1[i * MAX_HYBRID_BANDS + j] =
480           (ptr_real1[i * MAX_HYBRID_BANDS + j] + ptr_real3[i * MAX_HYBRID_BANDS + j] * 0.7071f);
481       ptr_imag1[i * MAX_HYBRID_BANDS + j] =
482           (ptr_imag1[i * MAX_HYBRID_BANDS + j] + ptr_imag3[i * MAX_HYBRID_BANDS + j] * 0.7071f);
483 
484       ptr_real2[i * MAX_HYBRID_BANDS + j] =
485           (ptr_real2[i * MAX_HYBRID_BANDS + j] + ptr_real3[i * MAX_HYBRID_BANDS + j] * 0.7071f);
486       ptr_imag2[i * MAX_HYBRID_BANDS + j] =
487           (ptr_imag2[i * MAX_HYBRID_BANDS + j] + ptr_imag3[i * MAX_HYBRID_BANDS + j] * 0.7071f);
488     }
489   }
490   for (i = 0; i < MAX_HYBRID_BANDS; i++) {
491     p_pow_par_band1[kernels_20[i]] += p_pow1[i];
492     p_pow_par_band2[kernels_20[i]] += p_pow2[i];
493     p_pow_par_band3[kernels_20[i]] += p_pow3[i];
494   }
495   for (i = 0; i < PARAMETER_BANDS; i++) {
496     if (p_pow_par_band3[i]) {
497       cld_s1[i] = ((p_pow_par_band1[i] + p_pow_par_band2[i]) / (p_pow_par_band3[i]));
498       cld_s1[i] = (FLOAT32)(10.0 * log(cld_s1[i] + 1e-10) / log(10.0));
499     } else if ((p_pow_par_band1[i] + p_pow_par_band2[i]))
500       cld_s1[i] = 50.0;
501     else
502       cld_s1[i] = -50;
503     ptr_qclds1[i] = ixheaace_mps_515_cld_quant(cld_s1[i]);
504 
505     if (p_pow_par_band2[i]) {
506       cld_s2[i] = (p_pow_par_band1[i] / (p_pow_par_band2[i]));
507       cld_s2[i] = (FLOAT32)(10 * log(cld_s2[i] + 1e-10f) / log(10.0));
508     } else if (p_pow_par_band1[i])
509       cld_s2[i] = 50.0;
510     else
511       cld_s2[i] = -50;
512     ptr_qclds2[i] = ixheaace_mps_515_cld_quant(cld_s2[i]);
513   }
514 }
515 
ixheaace_mps_515_ott_box(WORD32 slots,FLOAT32 * ptr_real1,FLOAT32 * ptr_imag1,FLOAT32 * ptr_real2,FLOAT32 * ptr_imag2,WORD32 * ptr_p_qclds,WORD32 * ptr_qiccs)516 VOID ixheaace_mps_515_ott_box(WORD32 slots, FLOAT32 *ptr_real1, FLOAT32 *ptr_imag1,
517                               FLOAT32 *ptr_real2, FLOAT32 *ptr_imag2, WORD32 *ptr_p_qclds,
518                               WORD32 *ptr_qiccs) {
519   WORD32 i, j;
520 
521   FLOAT32 clds[PARAMETER_BANDS] = {0};
522   FLOAT32 iccs[PARAMETER_BANDS] = {0};
523   FLOAT32 p_pow1[MAX_HYBRID_BANDS] = {0};
524   FLOAT32 p_pow2[MAX_HYBRID_BANDS] = {0};
525   FLOAT32 p_xcor_real[MAX_HYBRID_BANDS] = {0};
526 
527   FLOAT32 p_pow_par_band1[PARAMETER_BANDS] = {0};
528   FLOAT32 p_pow_par_band2[PARAMETER_BANDS] = {0};
529   FLOAT32 p_xcor_par_band[PARAMETER_BANDS] = {0};
530 
531   for (i = 0; i < slots; i++) {
532     for (j = 0; j < MAX_HYBRID_BANDS; j++) {
533       p_pow1[j] += ptr_real1[i * MAX_HYBRID_BANDS + j] * ptr_real1[i * MAX_HYBRID_BANDS + j] +
534                    ptr_imag1[i * MAX_HYBRID_BANDS + j] * ptr_imag1[i * MAX_HYBRID_BANDS + j];
535       p_pow2[j] += ptr_real2[i * MAX_HYBRID_BANDS + j] * ptr_real2[i * MAX_HYBRID_BANDS + j] +
536                    ptr_imag2[i * MAX_HYBRID_BANDS + j] * ptr_imag2[i * MAX_HYBRID_BANDS + j];
537       p_xcor_real[j] +=
538           ptr_real1[i * MAX_HYBRID_BANDS + j] * ptr_real2[i * MAX_HYBRID_BANDS + j] +
539           ptr_imag1[i * MAX_HYBRID_BANDS + j] * ptr_imag2[i * MAX_HYBRID_BANDS + j];
540 
541       ptr_real1[i * MAX_HYBRID_BANDS + j] =
542           (ptr_real1[i * MAX_HYBRID_BANDS + j] + ptr_real2[i * MAX_HYBRID_BANDS + j]);
543       ptr_imag1[i * MAX_HYBRID_BANDS + j] =
544           (ptr_imag1[i * MAX_HYBRID_BANDS + j] + ptr_imag2[i * MAX_HYBRID_BANDS + j]);
545     }
546   }
547   for (i = 0; i < MAX_HYBRID_BANDS; i++) {
548     p_pow_par_band1[kernels_20[i]] += p_pow1[i];
549     p_pow_par_band2[kernels_20[i]] += p_pow2[i];
550     p_xcor_par_band[kernels_20[i]] += p_xcor_real[i];
551   }
552   for (i = 0; i < PARAMETER_BANDS; i++) {
553     if (p_pow_par_band2[i]) {
554       clds[i] = (p_pow_par_band1[i] / (p_pow_par_band2[i]));
555       clds[i] = (FLOAT32)(10 * log(clds[i] + 1e-10) / log(10.0));
556     } else if (p_pow_par_band1[i])
557       clds[i] = 50.0;
558     else
559       clds[i] = -50;  // 0.0;
560     iccs[i] =
561         p_xcor_par_band[i] / (FLOAT32)sqrt((p_pow_par_band1[i] * p_pow_par_band2[i] + 1e-10));
562 
563     ptr_p_qclds[i] = ixheaace_mps_515_cld_quant(clds[i]);
564     ptr_qiccs[i] = ixheaace_mps_515_icc_quant(iccs[i]);
565   }
566 }
567 
ixheaace_mps_212_write_spatial_specific_config(ixheaace_mps_spatial_specific_config * const pstr_spatial_specific_config,UWORD8 * const ptr_output_buffer,const WORD32 output_buffer_size,WORD32 * const ptr_output_bits,WORD32 aot)568 IA_ERRORCODE ixheaace_mps_212_write_spatial_specific_config(
569     ixheaace_mps_spatial_specific_config *const pstr_spatial_specific_config,
570     UWORD8 *const ptr_output_buffer, const WORD32 output_buffer_size,
571     WORD32 *const ptr_output_bits, WORD32 aot) {
572   IA_ERRORCODE error = IA_NO_ERROR;
573   WORD32 bs_sampling_frequency_index = 0;
574   WORD32 bs_freq_res = 0;
575   ixheaace_bit_buf bit_buf;
576   ixheaace_bit_buf_handle pstr_bit_buf =
577       ia_enhaacplus_enc_create_bitbuffer(&bit_buf, ptr_output_buffer, output_buffer_size);
578 
579   error = ixheaace_mps_212_get_bs_freq_res_index(pstr_spatial_specific_config->num_bands,
580                                                  &bs_freq_res, aot);
581   if (error) {
582     return error;
583   }
584 
585   if (aot == AOT_AAC_ELD) {
586     ixheaace_mps_212_get_sampling_frequency_index(
587         pstr_spatial_specific_config->bs_sampling_frequency, &bs_sampling_frequency_index);
588     ixheaace_write_bits(pstr_bit_buf, bs_sampling_frequency_index, 4);
589 
590     if (bs_sampling_frequency_index == 15) {
591       ixheaace_write_bits(pstr_bit_buf, pstr_spatial_specific_config->bs_sampling_frequency, 24);
592     }
593 
594     ixheaace_write_bits(pstr_bit_buf, pstr_spatial_specific_config->bs_frame_length, 5);
595 
596     ixheaace_write_bits(pstr_bit_buf, bs_freq_res, 3);
597     ixheaace_write_bits(pstr_bit_buf, pstr_spatial_specific_config->bs_tree_config, 4);
598     ixheaace_write_bits(pstr_bit_buf, pstr_spatial_specific_config->bs_quant_mode, 2);
599 
600     ixheaace_write_bits(pstr_bit_buf, 0, 1);
601 
602     ixheaace_write_bits(pstr_bit_buf, pstr_spatial_specific_config->bs_fixed_gain_dmx, 3);
603 
604     ixheaace_write_bits(pstr_bit_buf, 0, 2);
605     ixheaace_write_bits(pstr_bit_buf, pstr_spatial_specific_config->bs_decorr_config, 2);
606 
607     ixheaace_byte_align_buffer(pstr_bit_buf);
608 
609     if ((*ptr_output_bits = ia_enhaacplus_enc_get_bits_available(pstr_bit_buf)) >
610         (output_buffer_size * 8)) {
611       return IA_EXHEAACE_CONFIG_NONFATAL_MPS_INVALID_CONFIG;
612     }
613 
614     ixheaace_byte_align_buffer(pstr_bit_buf);
615   } else {
616     ixheaace_mps_212_get_sampling_frequency_index(
617         pstr_spatial_specific_config->bs_sampling_frequency, &bs_sampling_frequency_index);
618     ixheaace_write_bits(pstr_bit_buf, bs_freq_res, 3);
619 
620     ixheaace_write_bits(pstr_bit_buf, pstr_spatial_specific_config->bs_fixed_gain_dmx, 3);
621 
622     ixheaace_write_bits(pstr_bit_buf, 0, 2);
623     ixheaace_write_bits(pstr_bit_buf, pstr_spatial_specific_config->bs_decorr_config, 2);
624 
625     ixheaace_write_bits(pstr_bit_buf, 0, 1);
626     ixheaace_write_bits(pstr_bit_buf, 0, 1);
627     ixheaace_write_bits(pstr_bit_buf, 0, 1);
628 
629     ixheaace_write_bits(pstr_bit_buf, 0, 5);
630     ixheaace_write_bits(pstr_bit_buf, 0, 1);
631 
632     *ptr_output_bits = ia_enhaacplus_enc_get_bits_available(pstr_bit_buf);
633   }
634   return error;
635 }
636 
ixheaace_mps_212_write_spatial_frame(UWORD8 * const ptr_output_buffer,const WORD32 output_buffer_size,WORD32 * const ptr_output_bits,ixheaace_mps_pstr_bsf_instance pstr_bsf_instance,WORD32 aot)637 IA_ERRORCODE ixheaace_mps_212_write_spatial_frame(
638     UWORD8 *const ptr_output_buffer, const WORD32 output_buffer_size,
639     WORD32 *const ptr_output_bits, ixheaace_mps_pstr_bsf_instance pstr_bsf_instance, WORD32 aot) {
640   IA_ERRORCODE error = IA_NO_ERROR;
641   WORD32 i, j, num_param_sets, num_ott_boxes;
642   ixheaace_mps_spatial_frame *pstr_spatial_frame = NULL;
643   ixheaace_mps_spatial_specific_config *pstr_specific_config = NULL;
644   ixheaace_bit_buf bit_buf;
645   ixheaace_bit_buf_handle pstr_bit_buf =
646       ia_enhaacplus_enc_create_bitbuffer(&bit_buf, ptr_output_buffer, output_buffer_size);
647   pstr_spatial_frame = &pstr_bsf_instance->frame;
648   pstr_specific_config = &pstr_bsf_instance->spatial_specific_config;
649   num_ott_boxes = pstr_bsf_instance->spatial_specific_config.tree_description.num_ott_boxes;
650   num_param_sets = pstr_spatial_frame->framing_info.num_param_sets;
651 
652   if (pstr_spatial_frame->b_use_bb_cues) {
653     for (i = 0; i < IXHEAACE_MPS_MAX_NUM_BOXES; i++) {
654       if (num_param_sets == 1) {
655         pstr_spatial_frame->cld_lossless_data.bs_freq_res_stride_xxx[i][0] = 3;
656         pstr_spatial_frame->icc_lossless_data.bs_freq_res_stride_xxx[i][0] = 3;
657       } else {
658         for (j = 1; j < MAX_NUM_PARAMS; j++) {
659           pstr_spatial_frame->cld_lossless_data.bs_freq_res_stride_xxx[i][j] = 3;
660           pstr_spatial_frame->icc_lossless_data.bs_freq_res_stride_xxx[i][j] = 3;
661         }
662       }
663     }
664   }
665 
666   if (aot == AOT_AAC_ELD) {
667     ixheaace_mps_212_write_framing_info(
668         pstr_bit_buf, &(pstr_spatial_frame->framing_info),
669         pstr_bsf_instance->spatial_specific_config.bs_frame_length);
670     ixheaace_write_bits(pstr_bit_buf, pstr_spatial_frame->bs_independency_flag, 1);
671   } else if (aot == AOT_USAC) {
672     if (!pstr_spatial_frame->bs_independency_flag) {
673       ixheaace_write_bits(pstr_bit_buf, pstr_spatial_frame->bs_independency_flag, 1);
674     }
675   }
676   error = ixheaace_mps_212_write_ott_data(
677       pstr_bit_buf, &pstr_bsf_instance->prev_frame_data.prev_ott_data,
678       &pstr_spatial_frame->ott_data, pstr_specific_config->ott_config,
679       &pstr_spatial_frame->cld_lossless_data, &pstr_spatial_frame->icc_lossless_data,
680       num_ott_boxes, pstr_specific_config->num_bands, num_param_sets,
681       pstr_spatial_frame->bs_independency_flag);
682   if (error != IA_NO_ERROR) {
683     return error;
684   }
685   if (aot == AOT_AAC_ELD) {
686     ixheaace_mps_212_write_smg_data(pstr_bit_buf, &pstr_spatial_frame->smg_data, num_param_sets,
687                                     pstr_specific_config->num_bands);
688   }
689 
690   *ptr_output_bits = ia_enhaacplus_enc_get_bits_available(pstr_bit_buf);
691   if ((*ptr_output_bits) > (output_buffer_size * 8)) {
692     return IA_EXHEAACE_CONFIG_NONFATAL_MPS_INVALID_CONFIG;
693   }
694   return error;
695 }
696 
697 IA_ERRORCODE
ixheaace_mps_515_write_spatial_specific_config(ixheaace_bit_buf_handle pstr_bit_buf,ixheaace_mps_sac_bsf_instance * pstr_bsf_instance)698 ixheaace_mps_515_write_spatial_specific_config(ixheaace_bit_buf_handle pstr_bit_buf,
699                                                ixheaace_mps_sac_bsf_instance *pstr_bsf_instance) {
700   WORD32 idx, box, bin;
701   WORD32 bs_sampling_frequency_index;
702   ixheaace_mps_sac_spatial_frame *pstr_spatial_frame = &(pstr_bsf_instance->current_frame);
703   ixheaace_mps_sac_specific_config *pstr_specific_config =
704       &(pstr_bsf_instance->spatial_specific_config);
705   ixheaace_mps_sac_tree_description *pstr_tree_description =
706       &(pstr_specific_config->tree_description);
707 
708   pstr_tree_description->num_ott_boxes =
709       tree_config_table[pstr_specific_config->bs_tree_config].num_ott_boxes;
710   pstr_tree_description->num_ttt_boxes =
711       tree_config_table[pstr_specific_config->bs_tree_config].num_ttt_boxes;
712   pstr_tree_description->num_in_chan =
713       tree_config_table[pstr_specific_config->bs_tree_config].num_in_chan;
714   pstr_tree_description->num_out_chan =
715       tree_config_table[pstr_specific_config->bs_tree_config].num_out_chan;
716 
717   if (pstr_specific_config->bs_temp_shape_config == 2) {
718     return IA_EXHEAACE_EXE_FATAL_MPS_UNSUPPORTED_GUIDED_ENV_SHAPE;
719   }
720 
721   if (pstr_specific_config->bs_3d_audio_mode > 0) {
722     return IA_EXHEAACE_EXE_FATAL_MPS_3D_STEREO_MODE_NOT_SUPPORTED;
723   }
724 
725   if (pstr_specific_config->bs_residual_coding == 1) {
726     return IA_EXHEAACE_EXE_FATAL_MPS_UNSUPPORTED_RESIDUAL_CODING;
727   }
728   if (pstr_specific_config->bs_arbitrary_downmix == 2) {
729     return IA_EXHEAACE_EXE_FATAL_MPS_UNSUPPORTED_ARBITARY_DOWNMIX_CODING;
730   }
731   if (pstr_specific_config->tree_description.arbitrary_tree) {
732     return IA_EXHEAACE_EXE_FATAL_MPS_ARBITARY_TREE_NOT_SUPPORTED;
733   }
734 
735   for (box = 0; box < MAX_NUM_BOXES; box++) {
736     pstr_tree_description->ott_mode_lfe[box] =
737         tree_config_table[pstr_specific_config->bs_tree_config].ott_mode_lfe[box];
738   }
739   pstr_bsf_instance->num_bins = freq_res_bin_table[pstr_specific_config->bs_freq_res];
740 
741   bs_sampling_frequency_index = 15;
742   for (idx = 0; idx < 15; idx++) {
743     if (pstr_specific_config->bs_sampling_frequency == ia_sampl_freq_table[idx]) {
744       bs_sampling_frequency_index = idx;
745       break;
746     }
747   }
748 
749   ixheaace_write_bits(pstr_bit_buf, bs_sampling_frequency_index, 4);
750   if (bs_sampling_frequency_index == 15) {
751     ixheaace_write_bits(pstr_bit_buf, pstr_specific_config->bs_sampling_frequency, 24);
752   }
753   ixheaace_write_bits(pstr_bit_buf, pstr_specific_config->bs_frame_length, 5);
754   ixheaace_write_bits(pstr_bit_buf, pstr_specific_config->bs_freq_res, 3);
755   ixheaace_write_bits(pstr_bit_buf, pstr_specific_config->bs_tree_config, 4);
756   ixheaace_write_bits(pstr_bit_buf, pstr_specific_config->bs_quant_mode, 2);
757   ixheaace_write_bits(pstr_bit_buf, pstr_specific_config->bs_one_icc, 1);
758   ixheaace_write_bits(pstr_bit_buf, pstr_specific_config->bs_arbitrary_downmix, 1);
759   ixheaace_write_bits(pstr_bit_buf, pstr_specific_config->bs_fixed_gain_sur, 3);
760   ixheaace_write_bits(pstr_bit_buf, pstr_specific_config->bs_fixed_gain_lfe, 3);
761   ixheaace_write_bits(pstr_bit_buf, pstr_specific_config->bs_fixed_gain_dmx, 3);
762   ixheaace_write_bits(pstr_bit_buf, pstr_specific_config->bs_matrix_mode, 1);
763   ixheaace_write_bits(pstr_bit_buf, pstr_specific_config->bs_temp_shape_config, 2);
764   ixheaace_write_bits(pstr_bit_buf, pstr_specific_config->bs_decorr_config, 2);
765   ixheaace_write_bits(pstr_bit_buf, pstr_specific_config->bs_3d_audio_mode, 1);
766 
767   for (box = 0; box < pstr_tree_description->num_ott_boxes; box++) {
768     if (pstr_tree_description->ott_mode_lfe[box]) {
769       ixheaace_write_bits(pstr_bit_buf, pstr_specific_config->ott_config[box].bs_ott_bands, 5);
770     }
771   }
772   for (box = 0; box < pstr_tree_description->num_ttt_boxes; box++) {
773     ixheaace_write_bits(pstr_bit_buf, pstr_specific_config->ttt_config[box].bs_ttt_dual_mode, 1);
774     ixheaace_write_bits(pstr_bit_buf, pstr_specific_config->ttt_config[box].bs_ttt_mode_low, 3);
775     if (pstr_specific_config->ttt_config[box].bs_ttt_dual_mode == 1) {
776       ixheaace_write_bits(pstr_bit_buf, pstr_specific_config->ttt_config[box].bs_ttt_mode_high,
777                           3);
778       ixheaace_write_bits(pstr_bit_buf, pstr_specific_config->ttt_config[box].bs_ttt_bands_low,
779                           5);
780     }
781   }
782   ixheaace_byte_align_buffer(pstr_bit_buf);
783 
784   for (box = 0; box < MAX_NUM_BOXES; box++) {
785     pstr_specific_config->ttt_config[box].bs_ttt_bands_low = pstr_bsf_instance->num_bins;
786     for (bin = 0; bin < MAX_NUM_BINS; bin++) {
787       pstr_spatial_frame->ott_data.cld_old[box][bin] = 0;
788       pstr_spatial_frame->ott_data.icc_old[box][bin] = 0;
789       pstr_spatial_frame->ttt_data.cpc_cld1_old[box][bin] = 0;
790       pstr_spatial_frame->ttt_data.cpc_cld2_old[box][bin] = 0;
791       pstr_spatial_frame->ttt_data.icc_old[box][bin] = 0;
792     }
793   }
794 
795   for (box = 0; box < pstr_tree_description->num_ott_boxes; box++) {
796     if (!pstr_tree_description->ott_mode_lfe[box]) {
797       pstr_specific_config->ott_config[box].bs_ott_bands = pstr_bsf_instance->num_bins;
798     }
799     if (!pstr_specific_config->ttt_config[box].bs_ttt_dual_mode) {
800       pstr_specific_config->ttt_config[box].bs_ttt_bands_low = pstr_bsf_instance->num_bins;
801     }
802   }
803 
804   return IA_NO_ERROR;
805 }
806 
807 IA_ERRORCODE
ixheaace_mps_515_write_spatial_frame(ixheaace_bit_buf_handle pstr_bit_buf,ixheaace_mps_sac_bsf_instance * pstr_bsf_instance)808 ixheaace_mps_515_write_spatial_frame(ixheaace_bit_buf_handle pstr_bit_buf,
809                                      ixheaace_mps_sac_bsf_instance *pstr_bsf_instance) {
810   IA_ERRORCODE error = IA_NO_ERROR;
811   UWORD8 bits_param_slot;
812   WORD32 param, box, ch, bin;
813   WORD32 prev_bs_param_slot, num_temp_shape_chan;
814   ixheaace_mps_sac_spatial_frame *pstr_spatial_frame = &(pstr_bsf_instance->current_frame);
815   ixheaace_mps_sac_specific_config *pstr_specific_config =
816       &(pstr_bsf_instance->spatial_specific_config);
817   WORD32 bs_independency_flag = pstr_spatial_frame->bs_independency_flag;
818   WORD32 num_param_sets = pstr_spatial_frame->framing_info.bs_num_param_sets;
819   WORD32 num_ott_boxes =
820       pstr_bsf_instance->spatial_specific_config.tree_description.num_ott_boxes;
821   WORD32 num_ttt_boxes =
822       pstr_bsf_instance->spatial_specific_config.tree_description.num_ttt_boxes;
823   WORD32 *ptr_ott_mode_lfe =
824       pstr_bsf_instance->spatial_specific_config.tree_description.ott_mode_lfe;
825 
826   if (pstr_specific_config->bs_arbitrary_downmix) {
827     return IA_EXHEAACE_EXE_FATAL_MPS_UNSUPPORTED_ARBITARY_DOWNMIX_CODING;
828   }
829   if (pstr_specific_config->bs_residual_coding == 1) {
830     return IA_EXHEAACE_EXE_FATAL_MPS_UNSUPPORTED_RESIDUAL_CODING;
831   }
832   if (pstr_specific_config->bs_arbitrary_downmix == 2) {
833     return IA_EXHEAACE_EXE_FATAL_MPS_UNSUPPORTED_ARBITARY_DOWNMIX_CODING;
834   }
835   if (pstr_specific_config->tree_description.arbitrary_tree) {
836     return IA_EXHEAACE_EXE_FATAL_MPS_ARBITARY_TREE_NOT_SUPPORTED;
837   }
838   ixheaace_write_bits(pstr_bit_buf, pstr_spatial_frame->framing_info.bs_framing_type, 1);
839   ixheaace_write_bits(pstr_bit_buf, num_param_sets - 1, 1);
840 
841   if (pstr_spatial_frame->framing_info.bs_framing_type) {
842     prev_bs_param_slot = -1;
843 
844     for (param = 0; param < num_param_sets; param++) {
845       bits_param_slot = 0;
846       while ((1 << bits_param_slot) < (pstr_specific_config->bs_frame_length + 1 -
847                                        num_param_sets + param - prev_bs_param_slot)) {
848         bits_param_slot++;
849       }
850 
851       if (bits_param_slot > 0) {
852         ixheaace_write_bits(
853             pstr_bit_buf,
854             pstr_spatial_frame->framing_info.bs_param_slots[param] - prev_bs_param_slot - 1,
855             bits_param_slot);
856       }
857       prev_bs_param_slot = pstr_spatial_frame->framing_info.bs_param_slots[param];
858     }
859   }
860 
861   ixheaace_write_bits(pstr_bit_buf, pstr_spatial_frame->bs_independency_flag, 1);
862 
863   for (box = 0; box < num_ott_boxes; box++) {
864     error = ixheaace_mps_515_ec_data(
865         pstr_bit_buf, pstr_spatial_frame->ott_data.cld[box],
866         pstr_spatial_frame->ott_data.cld_old[box], &(pstr_spatial_frame->cld_lossless_data),
867         IXHEAACE_MPS_SAC_DATA_TYPE_CLD, box, num_param_sets, bs_independency_flag, 0,
868         pstr_specific_config->ott_config[box].bs_ott_bands);
869     if (error) {
870       return error;
871     }
872   }
873   if (!pstr_bsf_instance->spatial_specific_config.bs_one_icc) {
874     for (box = 0; box < num_ott_boxes; box++) {
875       if (!ptr_ott_mode_lfe[box]) {
876         error = ixheaace_mps_515_ec_data(pstr_bit_buf, pstr_spatial_frame->ott_data.icc[box],
877                                          pstr_spatial_frame->ott_data.icc_old[box],
878                                          &(pstr_spatial_frame->cld_lossless_data),
879                                          IXHEAACE_MPS_SAC_DATA_TYPE_ICC, box, num_param_sets,
880                                          bs_independency_flag, 0, pstr_bsf_instance->num_bins);
881         if (error) {
882           return error;
883         }
884       }
885     }
886   } else {
887     error = ixheaace_mps_515_ec_data(pstr_bit_buf, pstr_spatial_frame->ott_data.icc[0],
888                                      pstr_spatial_frame->ott_data.icc_old[0],
889                                      &(pstr_spatial_frame->cld_lossless_data),
890                                      IXHEAACE_MPS_SAC_DATA_TYPE_ICC, 0, num_param_sets,
891                                      bs_independency_flag, 0, pstr_bsf_instance->num_bins);
892     if (error) {
893       return error;
894     }
895   }
896   for (box = 0; box < num_ttt_boxes; box++) {
897     if (pstr_specific_config->ttt_config[box].bs_ttt_mode_low >= 2) {
898       error = ixheaace_mps_515_ec_data(pstr_bit_buf, pstr_spatial_frame->ttt_data.cpc_cld1[box],
899                                        pstr_spatial_frame->ttt_data.cpc_cld1_old[box],
900                                        &(pstr_spatial_frame->cld_lossless_data),
901                                        IXHEAACE_MPS_SAC_DATA_TYPE_CLD, box, num_param_sets,
902                                        bs_independency_flag, 0,
903                                        pstr_specific_config->ttt_config[box].bs_ttt_bands_low);
904       if (error) {
905         return error;
906       }
907       error = ixheaace_mps_515_ec_data(pstr_bit_buf, pstr_spatial_frame->ttt_data.cpc_cld2[box],
908                                        pstr_spatial_frame->ttt_data.cpc_cld2_old[box],
909                                        &(pstr_spatial_frame->cld_lossless_data),
910                                        IXHEAACE_MPS_SAC_DATA_TYPE_CLD, box, num_param_sets,
911                                        bs_independency_flag, 0,
912                                        pstr_specific_config->ttt_config[box].bs_ttt_bands_low);
913       if (error) {
914         return error;
915       }
916     } else {
917       error = ixheaace_mps_515_ec_data(pstr_bit_buf, pstr_spatial_frame->ttt_data.cpc_cld1[box],
918                                        pstr_spatial_frame->ttt_data.cpc_cld1_old[box],
919                                        &(pstr_spatial_frame->cpc_lossless_data),
920                                        IXHEAACE_MPS_SAC_DATA_TYPE_CPC, box, num_param_sets,
921                                        bs_independency_flag, 0,
922                                        pstr_specific_config->ttt_config[box].bs_ttt_bands_low);
923       if (error) {
924         return error;
925       }
926       error = ixheaace_mps_515_ec_data(pstr_bit_buf, pstr_spatial_frame->ttt_data.cpc_cld2[box],
927                                        pstr_spatial_frame->ttt_data.cpc_cld2_old[box],
928                                        &(pstr_spatial_frame->cpc_lossless_data),
929                                        IXHEAACE_MPS_SAC_DATA_TYPE_CPC, box, num_param_sets,
930                                        bs_independency_flag, 0,
931                                        pstr_specific_config->ttt_config[box].bs_ttt_bands_low);
932       if (error) {
933         return error;
934       }
935       error = ixheaace_mps_515_ec_data(
936           pstr_bit_buf, pstr_spatial_frame->ttt_data.icc[box],
937           pstr_spatial_frame->ttt_data.icc_old[box], &(pstr_spatial_frame->icc_lossless_data),
938           IXHEAACE_MPS_SAC_DATA_TYPE_ICC, box, num_param_sets, bs_independency_flag, 0,
939           pstr_specific_config->ttt_config[box].bs_ttt_bands_low);
940       if (error) {
941         return error;
942       }
943     }
944 
945     if (pstr_specific_config->ttt_config[box].bs_ttt_dual_mode) {
946       if (pstr_specific_config->ttt_config[box].bs_ttt_mode_high >= 2) {
947         error = ixheaace_mps_515_ec_data(
948             pstr_bit_buf, pstr_spatial_frame->ttt_data.cpc_cld1[box],
949             pstr_spatial_frame->ttt_data.cpc_cld1_old[box],
950             &(pstr_spatial_frame->cld_lossless_data), IXHEAACE_MPS_SAC_DATA_TYPE_CLD, box,
951             num_param_sets, bs_independency_flag,
952             pstr_specific_config->ttt_config[box].bs_ttt_bands_low, pstr_bsf_instance->num_bins);
953         if (error) {
954           return error;
955         }
956         error = ixheaace_mps_515_ec_data(
957             pstr_bit_buf, pstr_spatial_frame->ttt_data.cpc_cld2[box],
958             pstr_spatial_frame->ttt_data.cpc_cld2_old[box],
959             &(pstr_spatial_frame->cld_lossless_data), IXHEAACE_MPS_SAC_DATA_TYPE_CLD, box,
960             num_param_sets, bs_independency_flag,
961             pstr_specific_config->ttt_config[box].bs_ttt_bands_low, pstr_bsf_instance->num_bins);
962         if (error) {
963           return error;
964         }
965       } else {
966         error = ixheaace_mps_515_ec_data(
967             pstr_bit_buf, pstr_spatial_frame->ttt_data.cpc_cld1[box],
968             pstr_spatial_frame->ttt_data.cpc_cld1_old[box],
969             &(pstr_spatial_frame->cpc_lossless_data), IXHEAACE_MPS_SAC_DATA_TYPE_CPC, box,
970             num_param_sets, bs_independency_flag,
971             pstr_specific_config->ttt_config[box].bs_ttt_bands_low, pstr_bsf_instance->num_bins);
972         if (error) {
973           return error;
974         }
975         error = ixheaace_mps_515_ec_data(
976             pstr_bit_buf, pstr_spatial_frame->ttt_data.cpc_cld2[box],
977             pstr_spatial_frame->ttt_data.cpc_cld2_old[box],
978             &(pstr_spatial_frame->cpc_lossless_data), IXHEAACE_MPS_SAC_DATA_TYPE_CPC, box,
979             num_param_sets, bs_independency_flag,
980             pstr_specific_config->ttt_config[box].bs_ttt_bands_low, pstr_bsf_instance->num_bins);
981         if (error) {
982           return error;
983         }
984         error = ixheaace_mps_515_ec_data(
985             pstr_bit_buf, pstr_spatial_frame->ttt_data.icc[box],
986             pstr_spatial_frame->ttt_data.icc_old[box], &(pstr_spatial_frame->icc_lossless_data),
987             IXHEAACE_MPS_SAC_DATA_TYPE_ICC, box, num_param_sets, bs_independency_flag,
988             pstr_specific_config->ttt_config[box].bs_ttt_bands_low, pstr_bsf_instance->num_bins);
989         if (error) {
990           return error;
991         }
992       }
993     }
994   }
995   for (param = 0; param < num_param_sets; param++) {
996     ixheaace_write_bits(pstr_bit_buf, pstr_spatial_frame->smg_data.bs_smooth_mode[param], 2);
997 
998     if (pstr_spatial_frame->smg_data.bs_smooth_mode[param] >= 2) {
999       ixheaace_write_bits(pstr_bit_buf, pstr_spatial_frame->smg_data.bs_smooth_time[param], 2);
1000     }
1001     if (pstr_spatial_frame->smg_data.bs_smooth_mode[param] == 3) {
1002       ixheaace_write_bits(pstr_bit_buf, pstr_spatial_frame->smg_data.bs_freq_res_stride[param],
1003                           2);
1004       for (bin = 0; bin < pstr_bsf_instance->num_bins;
1005            bin += pstr_spatial_frame->smg_data.bs_freq_res_stride[param]) {
1006         ixheaace_write_bits(pstr_bit_buf, pstr_spatial_frame->smg_data.bs_smg_data[param][bin],
1007                             1);
1008       }
1009     }
1010   }
1011   if (pstr_specific_config->bs_temp_shape_config != 0) {
1012     ixheaace_write_bits(pstr_bit_buf, pstr_spatial_frame->temp_shape_data.bs_temp_shape_enable,
1013                         1);
1014     if (pstr_spatial_frame->temp_shape_data.bs_temp_shape_enable) {
1015       num_temp_shape_chan = temp_shape_chan_table[pstr_specific_config->bs_temp_shape_config - 1]
1016                                                  [pstr_specific_config->bs_tree_config];
1017       for (ch = 0; ch < num_temp_shape_chan; ch++) {
1018         ixheaace_write_bits(pstr_bit_buf,
1019                             pstr_spatial_frame->temp_shape_data.bs_temp_shape_enable_channel[ch],
1020                             1);
1021       }
1022       if (pstr_specific_config->bs_temp_shape_config == 2) {
1023         return IA_EXHEAACE_EXE_FATAL_MPS_UNSUPPORTED_GUIDED_ENV_SHAPE;
1024       }
1025     }
1026   }
1027 
1028   ixheaace_byte_align_buffer(pstr_bit_buf);
1029 
1030   return IA_NO_ERROR;
1031 }