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