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