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#include "ixheaacd_mps_polyphase.h"
24#include "ixheaacd_mps_dec.h"
25#include "ixheaacd_mps_interface.h"
26
27#include "ixheaacd_mps_process.h"
28
29#include <math.h>
30#include <float.h>
31#include <memory.h>
32
33#include <assert.h>
34
35#include "ixheaacd_common_rom.h"
36#include "ixheaacd_defines.h"
37
38#include "ixheaacd_pns.h"
39
40#include <ixheaacd_aac_rom.h>
41#include "ixheaacd_pulsedata.h"
42
43#include "ixheaacd_sbrdecsettings.h"
44#include "ixheaacd_sbr_scale.h"
45#include "ixheaacd_lpp_tran.h"
46#include "ixheaacd_env_extr_part.h"
47#include <ixheaacd_sbr_rom.h>
48#include "ixheaacd_hybrid.h"
49#include "ixheaacd_ps_dec.h"
50#include "ixheaacd_env_extr.h"
51
52#include "ixheaacd_qmf_dec.h"
53
54#include "ixheaacd_env_calc.h"
55#include "ixheaacd_sbr_const.h"
56#include "ixheaacd_pvc_dec.h"
57#include "ixheaacd_sbr_dec.h"
58
59#define HP_SIZE (9)
60
61#define STP_LPF_COEFF1 (0.950f)
62#define STP_LPF_COEFF2 (0.450f)
63#define STP_UPDATE_ENERGY_RATE (32)
64#define STP_SCALE_LIMIT (2.82f)
65#define STP_DAMP (0.1f)
66
67#define max(a, b) ((a > b) ? (a) : (b))
68#define min(a, b) ((a < b) ? (a) : (b))
69
70static FLOAT32 ixheaacd_bp[BP_SIZE] = {
71    0.0000f, 0.0005f, 0.0092f, 0.0587f, 0.2580f, 0.7392f, 0.9791f,
72    0.9993f, 1.0000f, 1.0000f, 1.0000f, 1.0000f, 0.9999f, 0.9984f,
73    0.9908f, 0.9639f, 0.8952f, 0.7711f, 0.6127f, 0.4609f, 0.3391f,
74    0.2493f, 0.1848f, 0.1387f, 0.1053f};
75
76static FLOAT32 ixheaacd_gf[BP_SIZE] = {
77    0.f,         0.f,         0.f,         0.f,         0.f,
78    0.f,         1e-008f,     8.1e-007f,   3.61e-006f,  8.41e-006f,
79    1.6e-005f,   2.704e-005f, 3.969e-005f, 5.625e-005f, 7.396e-005f,
80    9.801e-005f, 0.00012321f, 0.00015625f, 0.00019881f, 0.00024964f,
81    0.00032041f, 0.00041209f, 0.00053824f, 0.00070756f, 0.00094249f};
82
83static VOID ixheaacd_mps_temp_process_scale_calc(ia_mps_dec_state_struct* self,
84                                                 WORD32 ts, FLOAT32* scale) {
85  FLOAT32 dir_energy;
86  FLOAT32 diff_energy[2];
87  FLOAT32 temp;
88
89  WORD32 ch, n;
90  WORD32 left_ch = 0, right_ch = 1;
91
92  if (self->subband_var.init_flag == 0) {
93    for (ch = 0; ch < 2; ch++) {
94      self->subband_var.tp_scale_last[ch] = 1.0f;
95      self->subband_var.nrg_diff_prev[ch] = 32768 * 32768;
96    }
97
98    self->subband_var.nrg_dir_prev = 32768 * 32768;
99    self->subband_var.init_flag = 1;
100  }
101
102  if (self->subband_var.update_old_ener == STP_UPDATE_ENERGY_RATE) {
103    self->subband_var.update_old_ener = 1;
104    self->subband_var.nrg_dir_prev = self->subband_var.nrg_dir;
105    for (ch = 0; ch < self->out_ch_count; ch++)
106      self->subband_var.nrg_diff_prev[ch] = self->subband_var.nrg_diff[ch];
107  } else
108    self->subband_var.update_old_ener++;
109
110  dir_energy = 0;
111
112  for (n = 6; n < BP_SIZE; n++) {
113    FLOAT32 dir_left_re = self->hyb_dir_out[left_ch][ts][n + 7].re;
114    FLOAT32 dir_right_re = self->hyb_dir_out[right_ch][ts][n + 7].re;
115    FLOAT32 dir_left_im = self->hyb_dir_out[left_ch][ts][n + 7].im;
116    FLOAT32 dir_right_im = self->hyb_dir_out[right_ch][ts][n + 7].im;
117
118    temp = ((dir_left_re + dir_right_re) * (dir_left_re + dir_right_re)) +
119           ((dir_left_im + dir_right_im) * (dir_left_im + dir_right_im));
120    dir_energy += temp * ixheaacd_bp[n] * ixheaacd_bp[n] * ixheaacd_gf[n] *
121                  ixheaacd_gf[n];
122  }
123
124  self->subband_var.nrg_dir =
125      (FLOAT32)(STP_LPF_COEFF1 * self->subband_var.nrg_dir +
126                (1.0 - STP_LPF_COEFF1) * dir_energy);
127
128  dir_energy /= (self->subband_var.nrg_dir_prev + ABS_THR);
129
130  for (ch = 0; ch < self->out_ch_count; ch++) {
131    diff_energy[ch] = 0;
132    for (n = 6; n < BP_SIZE; n++) {
133      FLOAT32 diff_re = self->hyb_diff_out[ch][ts][n + 7].re;
134      FLOAT32 diff_im = self->hyb_diff_out[ch][ts][n + 7].im;
135
136      temp = (diff_re * diff_re) + (diff_im * diff_im);
137      diff_energy[ch] += temp * ixheaacd_bp[n] * ixheaacd_bp[n] *
138                         ixheaacd_gf[n] * ixheaacd_gf[n];
139    }
140
141    self->subband_var.nrg_diff[ch] =
142        (FLOAT32)(STP_LPF_COEFF1 * self->subband_var.nrg_diff[ch] +
143                  (1.0 - STP_LPF_COEFF1) * diff_energy[ch]);
144    diff_energy[ch] /= (self->subband_var.nrg_diff_prev[ch] + ABS_THR);
145  }
146
147  scale[left_ch] = (FLOAT32)sqrt((dir_energy) / (diff_energy[left_ch] + 1e-9));
148  scale[right_ch] =
149      (FLOAT32)sqrt((dir_energy) / (diff_energy[right_ch] + 1e-9));
150
151  for (ch = 0; ch < self->out_ch_count; ch++) {
152    scale[ch] = STP_DAMP + (1 - STP_DAMP) * scale[ch];
153  }
154
155  for (ch = 0; ch < self->out_ch_count; ch++) {
156    scale[ch] =
157        min(max(scale[ch], (FLOAT32)(1.0 / STP_SCALE_LIMIT)), STP_SCALE_LIMIT);
158  }
159
160  for (ch = 0; ch < self->out_ch_count; ch++) {
161    scale[ch] =
162        (FLOAT32)(STP_LPF_COEFF2 * scale[ch] +
163                  (1.0 - STP_LPF_COEFF2) * self->subband_var.tp_scale_last[ch]);
164    self->subband_var.tp_scale_last[ch] = scale[ch];
165  }
166}
167
168static VOID ixheaacd_mps_subbandtp(ia_mps_dec_state_struct* self, WORD32 ts) {
169  FLOAT32 scale[2];
170  WORD32 ch, n;
171  WORD32 no_scaling;
172  FLOAT32 temp;
173  const WORD32 ixheaacd_hybrid_to_qmf_map[] = {0, 0, 0, 0, 0, 0, 1, 1, 2, 2};
174
175  ixheaacd_mps_temp_process_scale_calc(self, ts, scale);
176
177  for (ch = 0; ch < self->out_ch_count; ch++) {
178    no_scaling = 1;
179
180    if ((self->config->bs_temp_shape_config == 1) ||
181        (self->config->bs_temp_shape_config == 2))
182      no_scaling = !self->temp_shape_enable_ch_stp[ch];
183
184    if (no_scaling == 1) {
185      for (n = 0; n < self->hyb_band_count; n++) {
186        self->hyb_dir_out[ch][ts][n].re += self->hyb_diff_out[ch][ts][n].re;
187        self->hyb_dir_out[ch][ts][n].im += self->hyb_diff_out[ch][ts][n].im;
188      }
189    } else {
190      for (n = 0; n < 10; n++) {
191        temp =
192            (FLOAT32)(scale[ch] * ixheaacd_bp[ixheaacd_hybrid_to_qmf_map[n]]);
193        self->hyb_dir_out[ch][ts][n].re +=
194            (self->hyb_diff_out[ch][ts][n].re * temp);
195        self->hyb_dir_out[ch][ts][n].im +=
196            (self->hyb_diff_out[ch][ts][n].im * temp);
197      }
198      for (; n < HP_SIZE - 3 + 10; n++) {
199        temp = (FLOAT32)(scale[ch] * ixheaacd_bp[n + 3 - 10]);
200        self->hyb_dir_out[ch][ts][n].re +=
201            (self->hyb_diff_out[ch][ts][n].re * temp);
202        self->hyb_dir_out[ch][ts][n].im +=
203            (self->hyb_diff_out[ch][ts][n].im * temp);
204      }
205      for (; n < self->hyb_band_count; n++) {
206        temp = (FLOAT32)(scale[ch]);
207        self->hyb_dir_out[ch][ts][n].re +=
208            (self->hyb_diff_out[ch][ts][n].re * temp);
209        self->hyb_dir_out[ch][ts][n].im +=
210            (self->hyb_diff_out[ch][ts][n].im * temp);
211      }
212    }
213  }
214}
215
216WORD32 ixheaacd_mps_temp_process(ia_mps_dec_state_struct* self) {
217  WORD32 ch, ts, hyb;
218  WORD32 err = 0;
219
220  for (ch = 0; ch < self->out_ch_count; ch++) {
221    for (ts = 0; ts < self->time_slots; ts++) {
222      for (hyb = 0; hyb < HYBRID_BAND_BORDER; hyb++) {
223        self->hyb_dir_out[ch][ts][hyb].re += self->hyb_diff_out[ch][ts][hyb].re;
224        self->hyb_dir_out[ch][ts][hyb].im += self->hyb_diff_out[ch][ts][hyb].im;
225        self->hyb_diff_out[ch][ts][hyb].re = 0;
226        self->hyb_diff_out[ch][ts][hyb].im = 0;
227      }
228    }
229  }
230
231  for (ts = 0; ts < self->time_slots; ts++) ixheaacd_mps_subbandtp(self, ts);
232
233  ixheaacd_mps_qmf_hyb_synthesis(self);
234
235  for (ch = 0; ch < self->out_ch_count; ch++) {
236    err = ixheaacd_sbr_dec_from_mps(&self->qmf_out_dir[ch][0][0].re,
237                                    self->p_sbr_dec[ch], self->p_sbr_frame[ch],
238                                    self->p_sbr_header[ch]);
239    if (err) return err;
240  }
241
242  ixheaacd_mps_synt_calc(self);
243  return err;
244}
245