xref: /aosp_15_r20/external/libxaac/decoder/ixheaacd_mps_temp_reshape.c (revision 15dc779a375ca8b5125643b829a8aa4b70d7f451)
1*15dc779aSAndroid Build Coastguard Worker /******************************************************************************
2*15dc779aSAndroid Build Coastguard Worker  *                                                                            *
3*15dc779aSAndroid Build Coastguard Worker  * Copyright (C) 2018 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 #include <math.h>
21*15dc779aSAndroid Build Coastguard Worker #include "ixheaac_type_def.h"
22*15dc779aSAndroid Build Coastguard Worker #include "ixheaac_constants.h"
23*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_bitbuffer.h"
24*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_common_rom.h"
25*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_sbrdecsettings.h"
26*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_sbr_scale.h"
27*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_env_extr_part.h"
28*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_sbr_rom.h"
29*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_hybrid.h"
30*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_ps_dec.h"
31*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_config.h"
32*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_qmf_dec.h"
33*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_mps_polyphase.h"
34*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_mps_struct_def.h"
35*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_mps_res_rom.h"
36*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_mps_aac_struct.h"
37*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_mps_dec.h"
38*15dc779aSAndroid Build Coastguard Worker 
39*15dc779aSAndroid Build Coastguard Worker #define DIR_DIFF_IN 0
40*15dc779aSAndroid Build Coastguard Worker #define DOWNMIX_IN 1
41*15dc779aSAndroid Build Coastguard Worker 
42*15dc779aSAndroid Build Coastguard Worker #define LAMDA (4.0f)
43*15dc779aSAndroid Build Coastguard Worker #define GES_ALPHA (0.99637864f)
44*15dc779aSAndroid Build Coastguard Worker #define GES_BETA (0.9643691f)
45*15dc779aSAndroid Build Coastguard Worker 
46*15dc779aSAndroid Build Coastguard Worker extern const WORD32
47*15dc779aSAndroid Build Coastguard Worker     ixheaacd_hybrid_band_71_to_processing_band_20_map[MAX_HYBRID_BANDS_MPS];
48*15dc779aSAndroid Build Coastguard Worker 
ixheaacd_mps_env_init(ia_mps_dec_state_struct * self)49*15dc779aSAndroid Build Coastguard Worker VOID ixheaacd_mps_env_init(ia_mps_dec_state_struct *self) {
50*15dc779aSAndroid Build Coastguard Worker   WORD32 i;
51*15dc779aSAndroid Build Coastguard Worker   for (i = 0; i < 3; i++) {
52*15dc779aSAndroid Build Coastguard Worker     self->guided_env_shaping.avg_energy_prev[i] = 32768.f * 32768.f;
53*15dc779aSAndroid Build Coastguard Worker   }
54*15dc779aSAndroid Build Coastguard Worker }
55*15dc779aSAndroid Build Coastguard Worker 
ixheaacd_mps_est_normalized_envelope(ia_mps_dec_state_struct * self,WORD32 inp,WORD32 ch,FLOAT32 * env)56*15dc779aSAndroid Build Coastguard Worker static VOID ixheaacd_mps_est_normalized_envelope(ia_mps_dec_state_struct *self,
57*15dc779aSAndroid Build Coastguard Worker                                                  WORD32 inp, WORD32 ch,
58*15dc779aSAndroid Build Coastguard Worker                                                  FLOAT32 *env) {
59*15dc779aSAndroid Build Coastguard Worker   FLOAT32 slot_energy[MAX_TIME_SLOTS][MAX_PARAMETER_BANDS] = {{0}};
60*15dc779aSAndroid Build Coastguard Worker   FLOAT32 pb_energy[MAX_PARAMETER_BANDS] = {0};
61*15dc779aSAndroid Build Coastguard Worker   FLOAT32 whitening_weight[MAX_PARAMETER_BANDS];
62*15dc779aSAndroid Build Coastguard Worker   WORD32 ii, jj, param_band;
63*15dc779aSAndroid Build Coastguard Worker 
64*15dc779aSAndroid Build Coastguard Worker   WORD32 k_start = 10;
65*15dc779aSAndroid Build Coastguard Worker   WORD32 k_stop = 18;
66*15dc779aSAndroid Build Coastguard Worker 
67*15dc779aSAndroid Build Coastguard Worker   FLOAT32 total_energy = 0, avg_energy = 0;
68*15dc779aSAndroid Build Coastguard Worker 
69*15dc779aSAndroid Build Coastguard Worker   WORD32 ch_offset;
70*15dc779aSAndroid Build Coastguard Worker 
71*15dc779aSAndroid Build Coastguard Worker   switch (inp) {
72*15dc779aSAndroid Build Coastguard Worker     case DIR_DIFF_IN:
73*15dc779aSAndroid Build Coastguard Worker       ch_offset = 0;
74*15dc779aSAndroid Build Coastguard Worker       for (ii = 0; ii < self->time_slots; ii++) {
75*15dc779aSAndroid Build Coastguard Worker         for (jj = 0; jj < self->hyb_band_count_max; jj++) {
76*15dc779aSAndroid Build Coastguard Worker           slot_energy[ii]
77*15dc779aSAndroid Build Coastguard Worker                      [ixheaacd_hybrid_band_71_to_processing_band_20_map[jj]] +=
78*15dc779aSAndroid Build Coastguard Worker               ((self->hyb_dir_out[ch][ii][jj].re +
79*15dc779aSAndroid Build Coastguard Worker                 self->hyb_diff_out[ch][ii][jj].re) *
80*15dc779aSAndroid Build Coastguard Worker                (self->hyb_dir_out[ch][ii][jj].re +
81*15dc779aSAndroid Build Coastguard Worker                 self->hyb_diff_out[ch][ii][jj].re)) +
82*15dc779aSAndroid Build Coastguard Worker               ((self->hyb_dir_out[ch][ii][jj].im +
83*15dc779aSAndroid Build Coastguard Worker                 self->hyb_diff_out[ch][ii][jj].im) *
84*15dc779aSAndroid Build Coastguard Worker                (self->hyb_dir_out[ch][ii][jj].im +
85*15dc779aSAndroid Build Coastguard Worker                 self->hyb_diff_out[ch][ii][jj].im));
86*15dc779aSAndroid Build Coastguard Worker         }
87*15dc779aSAndroid Build Coastguard Worker       }
88*15dc779aSAndroid Build Coastguard Worker       break;
89*15dc779aSAndroid Build Coastguard Worker     case DOWNMIX_IN:
90*15dc779aSAndroid Build Coastguard Worker       ch_offset = self->out_ch_count;
91*15dc779aSAndroid Build Coastguard Worker       if ((self->pre_mix_req | self->bs_tsd_enable)) {
92*15dc779aSAndroid Build Coastguard Worker         for (ii = 0; ii < self->time_slots; ii++) {
93*15dc779aSAndroid Build Coastguard Worker           for (jj = 0; jj < self->hyb_band_count_max; jj++) {
94*15dc779aSAndroid Build Coastguard Worker             slot_energy
95*15dc779aSAndroid Build Coastguard Worker                 [ii][ixheaacd_hybrid_band_71_to_processing_band_20_map[jj]] +=
96*15dc779aSAndroid Build Coastguard Worker                 self->hyb_in[ch][jj][ii].re * self->hyb_in[ch][jj][ii].re +
97*15dc779aSAndroid Build Coastguard Worker                 self->hyb_in[ch][jj][ii].im * self->hyb_in[ch][jj][ii].im;
98*15dc779aSAndroid Build Coastguard Worker           }
99*15dc779aSAndroid Build Coastguard Worker         }
100*15dc779aSAndroid Build Coastguard Worker       } else {
101*15dc779aSAndroid Build Coastguard Worker         for (ii = 0; ii < self->time_slots; ii++) {
102*15dc779aSAndroid Build Coastguard Worker           for (jj = 0; jj < self->hyb_band_count_max; jj++) {
103*15dc779aSAndroid Build Coastguard Worker             slot_energy
104*15dc779aSAndroid Build Coastguard Worker                 [ii][ixheaacd_hybrid_band_71_to_processing_band_20_map[jj]] +=
105*15dc779aSAndroid Build Coastguard Worker                 self->w_dir[ch][ii][jj].re * self->w_dir[ch][ii][jj].re +
106*15dc779aSAndroid Build Coastguard Worker                 self->w_dir[ch][ii][jj].im * self->w_dir[ch][ii][jj].im;
107*15dc779aSAndroid Build Coastguard Worker           }
108*15dc779aSAndroid Build Coastguard Worker         }
109*15dc779aSAndroid Build Coastguard Worker       }
110*15dc779aSAndroid Build Coastguard Worker 
111*15dc779aSAndroid Build Coastguard Worker       break;
112*15dc779aSAndroid Build Coastguard Worker     default:
113*15dc779aSAndroid Build Coastguard Worker       ch_offset = 0;
114*15dc779aSAndroid Build Coastguard Worker       break;
115*15dc779aSAndroid Build Coastguard Worker   }
116*15dc779aSAndroid Build Coastguard Worker 
117*15dc779aSAndroid Build Coastguard Worker   for (param_band = k_start; param_band <= k_stop; param_band++)
118*15dc779aSAndroid Build Coastguard Worker     pb_energy[param_band] =
119*15dc779aSAndroid Build Coastguard Worker         self->guided_env_shaping.pb_energy_prev[ch + ch_offset][param_band];
120*15dc779aSAndroid Build Coastguard Worker 
121*15dc779aSAndroid Build Coastguard Worker   avg_energy = self->guided_env_shaping.avg_energy_prev[ch + ch_offset];
122*15dc779aSAndroid Build Coastguard Worker 
123*15dc779aSAndroid Build Coastguard Worker   for (ii = 0; ii < self->time_slots; ii++) {
124*15dc779aSAndroid Build Coastguard Worker     total_energy = 0;
125*15dc779aSAndroid Build Coastguard Worker     for (param_band = k_start; param_band <= k_stop; param_band++) {
126*15dc779aSAndroid Build Coastguard Worker       pb_energy[param_band] = (1 - GES_ALPHA) * slot_energy[ii][param_band] +
127*15dc779aSAndroid Build Coastguard Worker                               GES_ALPHA * pb_energy[param_band];
128*15dc779aSAndroid Build Coastguard Worker 
129*15dc779aSAndroid Build Coastguard Worker       total_energy += slot_energy[ii][param_band];
130*15dc779aSAndroid Build Coastguard Worker     }
131*15dc779aSAndroid Build Coastguard Worker     total_energy /= (k_stop - k_start + 1);
132*15dc779aSAndroid Build Coastguard Worker 
133*15dc779aSAndroid Build Coastguard Worker     total_energy =
134*15dc779aSAndroid Build Coastguard Worker         (1 - GES_ALPHA) * total_energy +
135*15dc779aSAndroid Build Coastguard Worker         GES_ALPHA * self->guided_env_shaping.frame_energy_prev[ch + ch_offset];
136*15dc779aSAndroid Build Coastguard Worker 
137*15dc779aSAndroid Build Coastguard Worker     self->guided_env_shaping.frame_energy_prev[ch + ch_offset] = total_energy;
138*15dc779aSAndroid Build Coastguard Worker 
139*15dc779aSAndroid Build Coastguard Worker     for (param_band = k_start; param_band <= k_stop; param_band++) {
140*15dc779aSAndroid Build Coastguard Worker       whitening_weight[param_band] =
141*15dc779aSAndroid Build Coastguard Worker           total_energy / (pb_energy[param_band] + ABS_THR);
142*15dc779aSAndroid Build Coastguard Worker     }
143*15dc779aSAndroid Build Coastguard Worker 
144*15dc779aSAndroid Build Coastguard Worker     env[ii] = 0;
145*15dc779aSAndroid Build Coastguard Worker     for (param_band = k_start; param_band <= k_stop; param_band++) {
146*15dc779aSAndroid Build Coastguard Worker       env[ii] += slot_energy[ii][param_band] * whitening_weight[param_band];
147*15dc779aSAndroid Build Coastguard Worker     }
148*15dc779aSAndroid Build Coastguard Worker 
149*15dc779aSAndroid Build Coastguard Worker     avg_energy = (1 - GES_BETA) * env[ii] + GES_BETA * avg_energy;
150*15dc779aSAndroid Build Coastguard Worker 
151*15dc779aSAndroid Build Coastguard Worker     env[ii] = (FLOAT32)sqrt(env[ii] / (avg_energy + ABS_THR));
152*15dc779aSAndroid Build Coastguard Worker   }
153*15dc779aSAndroid Build Coastguard Worker 
154*15dc779aSAndroid Build Coastguard Worker   for (param_band = k_start; param_band <= k_stop; param_band++)
155*15dc779aSAndroid Build Coastguard Worker     self->guided_env_shaping.pb_energy_prev[ch + ch_offset][param_band] =
156*15dc779aSAndroid Build Coastguard Worker         pb_energy[param_band];
157*15dc779aSAndroid Build Coastguard Worker 
158*15dc779aSAndroid Build Coastguard Worker   self->guided_env_shaping.avg_energy_prev[ch + ch_offset] = avg_energy;
159*15dc779aSAndroid Build Coastguard Worker }
160*15dc779aSAndroid Build Coastguard Worker 
ixheaacd_mps_time_env_shaping(ia_mps_dec_state_struct * self)161*15dc779aSAndroid Build Coastguard Worker VOID ixheaacd_mps_time_env_shaping(ia_mps_dec_state_struct *self) {
162*15dc779aSAndroid Build Coastguard Worker   FLOAT32 dir_energy[MAX_TIME_SLOTS];
163*15dc779aSAndroid Build Coastguard Worker   FLOAT32 dmx_energy[MAX_TIME_SLOTS];
164*15dc779aSAndroid Build Coastguard Worker   WORD32 ch, time_slot, jj;
165*15dc779aSAndroid Build Coastguard Worker 
166*15dc779aSAndroid Build Coastguard Worker   WORD32 band_start;
167*15dc779aSAndroid Build Coastguard Worker   FLOAT32 gain, ratio;
168*15dc779aSAndroid Build Coastguard Worker 
169*15dc779aSAndroid Build Coastguard Worker   FLOAT32 amp_direct = 0;
170*15dc779aSAndroid Build Coastguard Worker   FLOAT32 amp_diff = 0;
171*15dc779aSAndroid Build Coastguard Worker   FLOAT32 amp_ratio;
172*15dc779aSAndroid Build Coastguard Worker 
173*15dc779aSAndroid Build Coastguard Worker   band_start = 6;
174*15dc779aSAndroid Build Coastguard Worker 
175*15dc779aSAndroid Build Coastguard Worker   ixheaacd_mps_est_normalized_envelope(self, DOWNMIX_IN, 0, dmx_energy);
176*15dc779aSAndroid Build Coastguard Worker 
177*15dc779aSAndroid Build Coastguard Worker   for (ch = 0; ch < self->out_ch_count; ch++) {
178*15dc779aSAndroid Build Coastguard Worker     ixheaacd_mps_est_normalized_envelope(self, DIR_DIFF_IN, ch, dir_energy);
179*15dc779aSAndroid Build Coastguard Worker 
180*15dc779aSAndroid Build Coastguard Worker     if (self->temp_shape_enable_ch_ges[ch]) {
181*15dc779aSAndroid Build Coastguard Worker       for (time_slot = 0; time_slot < self->time_slots; time_slot++) {
182*15dc779aSAndroid Build Coastguard Worker         gain = self->env_shape_data[ch][time_slot] * dmx_energy[time_slot] /
183*15dc779aSAndroid Build Coastguard Worker                (dir_energy[time_slot] + 1e-9f);
184*15dc779aSAndroid Build Coastguard Worker 
185*15dc779aSAndroid Build Coastguard Worker         amp_direct = 0;
186*15dc779aSAndroid Build Coastguard Worker         amp_diff = 0;
187*15dc779aSAndroid Build Coastguard Worker 
188*15dc779aSAndroid Build Coastguard Worker         for (jj = band_start; jj < self->hyb_band_count_max; jj++) {
189*15dc779aSAndroid Build Coastguard Worker           amp_direct += self->hyb_dir_out[ch][time_slot][jj].re *
190*15dc779aSAndroid Build Coastguard Worker                             self->hyb_dir_out[ch][time_slot][jj].re +
191*15dc779aSAndroid Build Coastguard Worker                         self->hyb_dir_out[ch][time_slot][jj].im *
192*15dc779aSAndroid Build Coastguard Worker                             self->hyb_dir_out[ch][time_slot][jj].im;
193*15dc779aSAndroid Build Coastguard Worker 
194*15dc779aSAndroid Build Coastguard Worker           amp_diff += self->hyb_diff_out[ch][time_slot][jj].re *
195*15dc779aSAndroid Build Coastguard Worker                           self->hyb_diff_out[ch][time_slot][jj].re +
196*15dc779aSAndroid Build Coastguard Worker                       self->hyb_diff_out[ch][time_slot][jj].im *
197*15dc779aSAndroid Build Coastguard Worker                           self->hyb_diff_out[ch][time_slot][jj].im;
198*15dc779aSAndroid Build Coastguard Worker         }
199*15dc779aSAndroid Build Coastguard Worker 
200*15dc779aSAndroid Build Coastguard Worker         amp_ratio = (FLOAT32)sqrt(amp_diff / (amp_direct + ABS_THR));
201*15dc779aSAndroid Build Coastguard Worker 
202*15dc779aSAndroid Build Coastguard Worker         ratio = min(max((gain + amp_ratio * (gain - 1)), 1 / LAMDA), LAMDA);
203*15dc779aSAndroid Build Coastguard Worker 
204*15dc779aSAndroid Build Coastguard Worker         for (jj = band_start; jj < self->hyb_band_count_max; jj++) {
205*15dc779aSAndroid Build Coastguard Worker           self->hyb_dir_out[ch][time_slot][jj].re *= ratio;
206*15dc779aSAndroid Build Coastguard Worker           self->hyb_dir_out[ch][time_slot][jj].im *= ratio;
207*15dc779aSAndroid Build Coastguard Worker         }
208*15dc779aSAndroid Build Coastguard Worker       }
209*15dc779aSAndroid Build Coastguard Worker     }
210*15dc779aSAndroid Build Coastguard Worker   }
211*15dc779aSAndroid Build Coastguard Worker }
212