xref: /aosp_15_r20/external/libxaac/encoder/ixheaace_fd_qc_util.c (revision 15dc779a375ca8b5125643b829a8aa4b70d7f451)
1*15dc779aSAndroid Build Coastguard Worker /******************************************************************************
2*15dc779aSAndroid Build Coastguard Worker  *                                                                            *
3*15dc779aSAndroid Build Coastguard Worker  * Copyright (C) 2023 The Android Open Source Project
4*15dc779aSAndroid Build Coastguard Worker  *
5*15dc779aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
6*15dc779aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
7*15dc779aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at:
8*15dc779aSAndroid Build Coastguard Worker  *
9*15dc779aSAndroid Build Coastguard Worker  * http://www.apache.org/licenses/LICENSE-2.0
10*15dc779aSAndroid Build Coastguard Worker  *
11*15dc779aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
12*15dc779aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
13*15dc779aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*15dc779aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
15*15dc779aSAndroid Build Coastguard Worker  * limitations under the License.
16*15dc779aSAndroid Build Coastguard Worker  *
17*15dc779aSAndroid Build Coastguard Worker  *****************************************************************************
18*15dc779aSAndroid Build Coastguard Worker  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19*15dc779aSAndroid Build Coastguard Worker  */
20*15dc779aSAndroid Build Coastguard Worker 
21*15dc779aSAndroid Build Coastguard Worker #include <string.h>
22*15dc779aSAndroid Build Coastguard Worker #include <math.h>
23*15dc779aSAndroid Build Coastguard Worker #include <stdlib.h>
24*15dc779aSAndroid Build Coastguard Worker #include "iusace_type_def.h"
25*15dc779aSAndroid Build Coastguard Worker #include "iusace_cnst.h"
26*15dc779aSAndroid Build Coastguard Worker #include "iusace_bitbuffer.h"
27*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_common_enc.h"
28*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_uni_drc.h"
29*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_api.h"
30*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_uni_drc_eq.h"
31*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_uni_drc_filter_bank.h"
32*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_gain_enc.h"
33*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_struct_def.h"
34*15dc779aSAndroid Build Coastguard Worker 
35*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_memory_standards.h"
36*15dc779aSAndroid Build Coastguard Worker #include "iusace_tns_usac.h"
37*15dc779aSAndroid Build Coastguard Worker #include "iusace_psy_mod.h"
38*15dc779aSAndroid Build Coastguard Worker #include "iusace_config.h"
39*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_adjust_threshold_data.h"
40*15dc779aSAndroid Build Coastguard Worker #include "iusace_fd_qc_util.h"
41*15dc779aSAndroid Build Coastguard Worker #include "iusace_fd_qc_adjthr.h"
42*15dc779aSAndroid Build Coastguard Worker 
iusace_qc_create(ia_qc_main_struct * pstr_qc_main)43*15dc779aSAndroid Build Coastguard Worker VOID iusace_qc_create(ia_qc_main_struct *pstr_qc_main) {
44*15dc779aSAndroid Build Coastguard Worker   WORD32 i = 0;
45*15dc779aSAndroid Build Coastguard Worker   memset(pstr_qc_main, 0, sizeof(ia_qc_main_struct));
46*15dc779aSAndroid Build Coastguard Worker 
47*15dc779aSAndroid Build Coastguard Worker   for (i = 0; i < 2; i++) {
48*15dc779aSAndroid Build Coastguard Worker     memset(pstr_qc_main->str_qc_out.str_qc_out_chan[i].quant_spec, 0,
49*15dc779aSAndroid Build Coastguard Worker            sizeof(WORD16) * FRAME_LEN_LONG);
50*15dc779aSAndroid Build Coastguard Worker     memset(pstr_qc_main->str_qc_out.str_qc_out_chan[i].scalefactor, 0,
51*15dc779aSAndroid Build Coastguard Worker            sizeof(WORD16) * FRAME_LEN_LONG);
52*15dc779aSAndroid Build Coastguard Worker   }
53*15dc779aSAndroid Build Coastguard Worker   return;
54*15dc779aSAndroid Build Coastguard Worker }
55*15dc779aSAndroid Build Coastguard Worker 
iusace_qc_init(ia_qc_data_struct * pstr_qc_data,const WORD32 max_bits,WORD32 sample_rate,WORD32 bw_limit,WORD32 channels,WORD32 ccfl)56*15dc779aSAndroid Build Coastguard Worker VOID iusace_qc_init(ia_qc_data_struct *pstr_qc_data, const WORD32 max_bits, WORD32 sample_rate,
57*15dc779aSAndroid Build Coastguard Worker                     WORD32 bw_limit, WORD32 channels, WORD32 ccfl) {
58*15dc779aSAndroid Build Coastguard Worker   FLOAT32 mean_pe;
59*15dc779aSAndroid Build Coastguard Worker   pstr_qc_data->tot_avg_bits = pstr_qc_data->avg_bits;
60*15dc779aSAndroid Build Coastguard Worker   pstr_qc_data->static_bits = 1;
61*15dc779aSAndroid Build Coastguard Worker   pstr_qc_data->avg_bits = (pstr_qc_data->avg_bits - pstr_qc_data->static_bits);
62*15dc779aSAndroid Build Coastguard Worker   pstr_qc_data->max_bits = channels * max_bits;
63*15dc779aSAndroid Build Coastguard Worker   pstr_qc_data->max_bitres_bits = channels * max_bits - pstr_qc_data->tot_avg_bits;
64*15dc779aSAndroid Build Coastguard Worker   pstr_qc_data->max_bitres_bits =
65*15dc779aSAndroid Build Coastguard Worker       pstr_qc_data->max_bitres_bits - (pstr_qc_data->max_bitres_bits % 8);
66*15dc779aSAndroid Build Coastguard Worker   pstr_qc_data->bit_res_lvl = pstr_qc_data->max_bitres_bits;
67*15dc779aSAndroid Build Coastguard Worker   pstr_qc_data->padding = sample_rate;
68*15dc779aSAndroid Build Coastguard Worker 
69*15dc779aSAndroid Build Coastguard Worker   pstr_qc_data->max_bit_fac =
70*15dc779aSAndroid Build Coastguard Worker       (FLOAT32)channels * (max_bits - 744) /
71*15dc779aSAndroid Build Coastguard Worker       (FLOAT32)(pstr_qc_data->tot_avg_bits ? pstr_qc_data->tot_avg_bits : 1);
72*15dc779aSAndroid Build Coastguard Worker   mean_pe = 10.0f * ccfl * bw_limit / (sample_rate / 2.0f);
73*15dc779aSAndroid Build Coastguard Worker 
74*15dc779aSAndroid Build Coastguard Worker   iusace_adj_thr_init(&pstr_qc_data->str_adj_thr_ele, mean_pe,
75*15dc779aSAndroid Build Coastguard Worker                       (channels > 0) ? pstr_qc_data->ch_bitrate / channels : 0);
76*15dc779aSAndroid Build Coastguard Worker 
77*15dc779aSAndroid Build Coastguard Worker   return;
78*15dc779aSAndroid Build Coastguard Worker }
79*15dc779aSAndroid Build Coastguard Worker 
iusace_calc_frame_len(WORD32 bit_rate,WORD32 sample_rate,WORD32 mode,WORD32 ccfl)80*15dc779aSAndroid Build Coastguard Worker static WORD32 iusace_calc_frame_len(WORD32 bit_rate, WORD32 sample_rate, WORD32 mode,
81*15dc779aSAndroid Build Coastguard Worker                                     WORD32 ccfl) {
82*15dc779aSAndroid Build Coastguard Worker   WORD32 result;
83*15dc779aSAndroid Build Coastguard Worker 
84*15dc779aSAndroid Build Coastguard Worker   result = ((ccfl) >> 3) * (bit_rate);
85*15dc779aSAndroid Build Coastguard Worker   switch (mode) {
86*15dc779aSAndroid Build Coastguard Worker     case FRAME_LEN_BYTES_MODULO:
87*15dc779aSAndroid Build Coastguard Worker       result %= sample_rate;
88*15dc779aSAndroid Build Coastguard Worker       break;
89*15dc779aSAndroid Build Coastguard Worker     case FRAME_LEN_BYTES_INT:
90*15dc779aSAndroid Build Coastguard Worker       result /= sample_rate;
91*15dc779aSAndroid Build Coastguard Worker       break;
92*15dc779aSAndroid Build Coastguard Worker   }
93*15dc779aSAndroid Build Coastguard Worker 
94*15dc779aSAndroid Build Coastguard Worker   return (result);
95*15dc779aSAndroid Build Coastguard Worker }
96*15dc779aSAndroid Build Coastguard Worker 
iusace_get_frame_padding(WORD32 bit_rate,WORD32 sample_rate,WORD32 * padding,WORD32 ccfl)97*15dc779aSAndroid Build Coastguard Worker static WORD32 iusace_get_frame_padding(WORD32 bit_rate, WORD32 sample_rate, WORD32 *padding,
98*15dc779aSAndroid Build Coastguard Worker                                        WORD32 ccfl) {
99*15dc779aSAndroid Build Coastguard Worker   WORD32 padding_on = 0;
100*15dc779aSAndroid Build Coastguard Worker   WORD32 difference;
101*15dc779aSAndroid Build Coastguard Worker 
102*15dc779aSAndroid Build Coastguard Worker   difference = iusace_calc_frame_len(bit_rate, sample_rate, FRAME_LEN_BYTES_MODULO, ccfl);
103*15dc779aSAndroid Build Coastguard Worker 
104*15dc779aSAndroid Build Coastguard Worker   *padding -= difference;
105*15dc779aSAndroid Build Coastguard Worker 
106*15dc779aSAndroid Build Coastguard Worker   if (*padding <= 0) {
107*15dc779aSAndroid Build Coastguard Worker     padding_on = 1;
108*15dc779aSAndroid Build Coastguard Worker     *padding += sample_rate;
109*15dc779aSAndroid Build Coastguard Worker   }
110*15dc779aSAndroid Build Coastguard Worker 
111*15dc779aSAndroid Build Coastguard Worker   return padding_on;
112*15dc779aSAndroid Build Coastguard Worker }
113*15dc779aSAndroid Build Coastguard Worker 
iusace_adj_bitrate(ia_qc_data_struct * pstr_qc_data,WORD32 bit_rate,WORD32 sample_rate,WORD32 ccfl)114*15dc779aSAndroid Build Coastguard Worker VOID iusace_adj_bitrate(ia_qc_data_struct *pstr_qc_data, WORD32 bit_rate, WORD32 sample_rate,
115*15dc779aSAndroid Build Coastguard Worker                         WORD32 ccfl) {
116*15dc779aSAndroid Build Coastguard Worker   WORD32 padding_on;
117*15dc779aSAndroid Build Coastguard Worker   WORD32 frame_len;
118*15dc779aSAndroid Build Coastguard Worker   WORD32 code_bits;
119*15dc779aSAndroid Build Coastguard Worker   WORD32 code_bits_prev;
120*15dc779aSAndroid Build Coastguard Worker   WORD32 total_bits = 0;
121*15dc779aSAndroid Build Coastguard Worker 
122*15dc779aSAndroid Build Coastguard Worker   padding_on = iusace_get_frame_padding(bit_rate, sample_rate, &pstr_qc_data->padding, ccfl);
123*15dc779aSAndroid Build Coastguard Worker   frame_len =
124*15dc779aSAndroid Build Coastguard Worker       padding_on + iusace_calc_frame_len(bit_rate, sample_rate, FRAME_LEN_BYTES_INT, ccfl);
125*15dc779aSAndroid Build Coastguard Worker 
126*15dc779aSAndroid Build Coastguard Worker   frame_len <<= 3;
127*15dc779aSAndroid Build Coastguard Worker   code_bits_prev = pstr_qc_data->tot_avg_bits - pstr_qc_data->static_bits;
128*15dc779aSAndroid Build Coastguard Worker   code_bits = frame_len - pstr_qc_data->static_bits;
129*15dc779aSAndroid Build Coastguard Worker 
130*15dc779aSAndroid Build Coastguard Worker   if (code_bits != code_bits_prev) {
131*15dc779aSAndroid Build Coastguard Worker     pstr_qc_data->avg_bits = (WORD32)code_bits;
132*15dc779aSAndroid Build Coastguard Worker     total_bits += pstr_qc_data->avg_bits;
133*15dc779aSAndroid Build Coastguard Worker     pstr_qc_data->avg_bits += code_bits - total_bits;
134*15dc779aSAndroid Build Coastguard Worker   }
135*15dc779aSAndroid Build Coastguard Worker 
136*15dc779aSAndroid Build Coastguard Worker   pstr_qc_data->tot_avg_bits = frame_len;
137*15dc779aSAndroid Build Coastguard Worker 
138*15dc779aSAndroid Build Coastguard Worker   return;
139*15dc779aSAndroid Build Coastguard Worker }
140*15dc779aSAndroid Build Coastguard Worker 
iusace_calc_max_val_in_sfb(WORD32 sfb_count,WORD32 max_sfb_per_grp,WORD32 sfb_per_group,WORD32 * ptr_sfb_offset,WORD16 * ptr_quant_spec)141*15dc779aSAndroid Build Coastguard Worker WORD32 iusace_calc_max_val_in_sfb(WORD32 sfb_count, WORD32 max_sfb_per_grp, WORD32 sfb_per_group,
142*15dc779aSAndroid Build Coastguard Worker                                   WORD32 *ptr_sfb_offset, WORD16 *ptr_quant_spec) {
143*15dc779aSAndroid Build Coastguard Worker   WORD32 sfb;
144*15dc779aSAndroid Build Coastguard Worker   WORD32 max = 0;
145*15dc779aSAndroid Build Coastguard Worker   WORD32 sfb_offs;
146*15dc779aSAndroid Build Coastguard Worker 
147*15dc779aSAndroid Build Coastguard Worker   for (sfb_offs = 0; sfb_offs < sfb_count; sfb_offs += sfb_per_group) {
148*15dc779aSAndroid Build Coastguard Worker     for (sfb = 0; sfb < max_sfb_per_grp; sfb++) {
149*15dc779aSAndroid Build Coastguard Worker       WORD32 line;
150*15dc779aSAndroid Build Coastguard Worker       WORD32 local_max = 0;
151*15dc779aSAndroid Build Coastguard Worker       for (line = ptr_sfb_offset[sfb + sfb_offs]; line < ptr_sfb_offset[sfb + sfb_offs + 1];
152*15dc779aSAndroid Build Coastguard Worker            line++) {
153*15dc779aSAndroid Build Coastguard Worker         if (abs(ptr_quant_spec[line]) > local_max) {
154*15dc779aSAndroid Build Coastguard Worker           local_max = abs(ptr_quant_spec[line]);
155*15dc779aSAndroid Build Coastguard Worker         }
156*15dc779aSAndroid Build Coastguard Worker       }
157*15dc779aSAndroid Build Coastguard Worker       if (local_max > max) {
158*15dc779aSAndroid Build Coastguard Worker         max = local_max;
159*15dc779aSAndroid Build Coastguard Worker       }
160*15dc779aSAndroid Build Coastguard Worker     }
161*15dc779aSAndroid Build Coastguard Worker   }
162*15dc779aSAndroid Build Coastguard Worker 
163*15dc779aSAndroid Build Coastguard Worker   return max;
164*15dc779aSAndroid Build Coastguard Worker }
165