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