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