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 <stdio.h> 21 #include <stdlib.h> 22 #include <math.h> 23 #include <string.h> 24 #include <assert.h> 25 26 #include <ixheaacd_type_def.h> 27 #include "ixheaacd_bitbuffer.h" 28 #include "ixheaacd_config.h" 29 30 #include "ixheaacd_mps_polyphase.h" 31 #include "ixheaacd_mps_dec.h" 32 #include "ixheaacd_mps_interface.h" 33 34 #include "ixheaacd_mps_polyphase.h" 35 36 #include "ixheaacd_mps_decor.h" 37 #include "ixheaacd_mps_hybfilter.h" 38 39 #include "ixheaacd_constants.h" 40 41 static WORD32 ixheaacd_decorr_delay[] = {11, 10, 5, 2}; 42 43 static WORD32 ixheaacd_qmf_split_freq_0[] = {3, 15, 24, 65}; 44 static WORD32 ixheaacd_qmf_split_freq_1[] = {3, 50, 65, 65}; 45 static WORD32 ixheaacd_qmf_split_freq_2[] = {0, 15, 65, 65}; 46 47 static FLOAT32 ixheaacd_lattice_coeff_0_filt_den_coeff[DECORR_FILT_0_ORD + 1] = 48 {1.000000f, -0.314818f, -0.256828f, -0.173641f, -0.115077f, 0.000599f, 49 0.033343f, 0.122672f, -0.356362f, 0.128058f, 0.089800f}; 50 static FLOAT32 ixheaacd_lattice_coeff_0_filt_num_coeff[DECORR_FILT_0_ORD + 1] = 51 {0.089800f, 0.128058f, -0.356362f, 0.122672f, 0.033343f, 0.000599f, 52 -0.115077f, -0.173641f, -0.256828f, -0.314818f, 1.000000f}; 53 54 static FLOAT32 ixheaacd_lattice_coeff_1_filt_den_coeff[DECORR_FILT_1_ORD + 1] = 55 {1.000000f, -0.287137f, -0.088940f, 0.123204f, -0.126111f, 56 0.064218f, 0.045768f, -0.016264f, -0.122100f}; 57 static FLOAT32 ixheaacd_lattice_coeff_1_filt_num_coeff[DECORR_FILT_1_ORD + 1] = 58 {-0.122100f, -0.016264f, 0.045768f, 0.064218f, -0.126111f, 59 0.123204f, -0.088940f, -0.287137f, 1.000000f}; 60 61 static FLOAT32 ixheaacd_lattice_coeff_2_filt_den_coeff[DECORR_FILT_2_ORD + 1] = 62 {1.000000f, 0.129403f, -0.032633f, 0.035700f}; 63 static FLOAT32 ixheaacd_lattice_coeff_2_filt_num_coeff[DECORR_FILT_2_ORD + 1] = 64 {0.035700f, -0.032633f, 0.129403f, 1.000000f}; 65 66 static FLOAT32 ixheaacd_lattice_coeff_3_filt_den_coeff[DECORR_FILT_3_ORD + 1] = 67 {1.000000f, 0.034742f, -0.013000f}; 68 static FLOAT32 ixheaacd_lattice_coeff_3_filt_num_coeff[DECORR_FILT_3_ORD + 1] = 69 {-0.013000f, 0.034742f, 1.000000f}; 70 71 extern WORD32 72 ixheaacd_hybrid_band_71_to_processing_band_28_map[MAX_HYBRID_BANDS_MPS]; 73 74 static WORD32 ixheaacd_hybrid_to_qmf_map[MAX_HYBRID_BANDS_MPS] = { 75 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 76 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 77 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 78 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63}; 79 80 static void ixheaacd_mps_decor_filt_init(ia_mps_decor_filt_struct *self, 81 WORD32 reverb_band) { 82 switch (reverb_band) { 83 case 0: 84 self->num_len = self->den_len = DECORR_FILT_0_ORD + 1; 85 self->num = ixheaacd_lattice_coeff_0_filt_num_coeff; 86 self->den = ixheaacd_lattice_coeff_0_filt_den_coeff; 87 88 break; 89 case 1: 90 self->num_len = self->den_len = DECORR_FILT_1_ORD + 1; 91 self->num = ixheaacd_lattice_coeff_1_filt_num_coeff; 92 self->den = ixheaacd_lattice_coeff_1_filt_den_coeff; 93 94 break; 95 case 2: 96 self->num_len = self->den_len = DECORR_FILT_2_ORD + 1; 97 self->num = ixheaacd_lattice_coeff_2_filt_num_coeff; 98 self->den = ixheaacd_lattice_coeff_2_filt_den_coeff; 99 break; 100 case 3: 101 self->num_len = self->den_len = DECORR_FILT_3_ORD + 1; 102 self->num = ixheaacd_lattice_coeff_3_filt_num_coeff; 103 self->den = ixheaacd_lattice_coeff_3_filt_den_coeff; 104 break; 105 } 106 107 self->state_len = self->num_len; 108 memset(self->state, 0, 109 sizeof(ia_cmplx_flt_struct) * (MAX_DECORR_FIL_ORDER + 1)); 110 111 return; 112 } 113 114 static VOID ixheaacd_mps_allpass_apply(ia_mps_decor_filt_struct *self, 115 ia_cmplx_flt_struct *input, WORD32 len, 116 ia_cmplx_flt_struct *output) { 117 WORD32 i, j; 118 119 for (i = 0; i < len; i++) { 120 output[i].re = self->state[0].re + input[i].re * self->num[0]; 121 output[i].im = self->state[0].im + input[i].im * self->num[0]; 122 123 for (j = 1; j < self->num_len; j++) { 124 self->state[j - 1].re = self->state[j].re + self->num[j] * input[i].re - 125 self->den[j] * output[i].re; 126 self->state[j - 1].im = self->state[j].im + self->num[j] * input[i].im - 127 self->den[j] * output[i].im; 128 } 129 } 130 } 131 132 static VOID ixheaacd_mps_decor_energy_adjustment( 133 ixheaacd_mps_decor_energy_adjust_filt_struct *handle, 134 ia_cmplx_flt_struct in[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS], 135 ia_cmplx_flt_struct out[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS], 136 WORD32 time_slots) { 137 ixheaacd_mps_decor_energy_adjust_filt_struct *self = 138 (ixheaacd_mps_decor_energy_adjust_filt_struct *)handle; 139 FLOAT32 in_energy[MAX_PARAMETER_BANDS] = {0}; 140 FLOAT32 out_energy[MAX_PARAMETER_BANDS] = {0}; 141 FLOAT32 gain[MAX_PARAMETER_BANDS]; 142 WORD32 i, j, k; 143 144 for (i = 0; i < time_slots; i++) { 145 memset(in_energy, 0, sizeof(FLOAT32) * MAX_PARAMETER_BANDS); 146 memset(out_energy, 0, sizeof(FLOAT32) * MAX_PARAMETER_BANDS); 147 148 for (j = 0; j < self->num_bins; j++) { 149 k = ixheaacd_hybrid_band_71_to_processing_band_28_map[j]; 150 151 in_energy[k] += in[i][j].re * in[i][j].re + in[i][j].im * in[i][j].im; 152 out_energy[k] += 153 out[i][j].re * out[i][j].re + out[i][j].im * out[i][j].im; 154 } 155 156 for (k = 0; k < MAX_PARAMETER_BANDS; k++) { 157 self->smooth_in_energy[k] = self->smooth_in_energy[k] * DECOR_ALPHA + 158 in_energy[k] * ONE_MINUS_DECOR_ALPHA; 159 self->smooth_out_energy[k] = self->smooth_out_energy[k] * DECOR_ALPHA + 160 out_energy[k] * ONE_MINUS_DECOR_ALPHA; 161 162 gain[k] = 1.0f; 163 164 if (self->smooth_out_energy[k] > 165 self->smooth_in_energy[k] * DECOR_GAMMA) { 166 gain[k] = (FLOAT32)sqrt(self->smooth_in_energy[k] * DECOR_GAMMA / 167 (self->smooth_out_energy[k] + ABS_THR)); 168 } 169 170 if (self->smooth_in_energy[k] > 171 self->smooth_out_energy[k] * DECOR_GAMMA) { 172 gain[k] = 173 min(2.0f, (FLOAT32)sqrt(self->smooth_in_energy[k] / 174 (DECOR_GAMMA * self->smooth_out_energy[k] + 175 ABS_THR))); 176 } 177 } 178 179 for (j = 0; j < self->num_bins; j++) { 180 k = ixheaacd_hybrid_band_71_to_processing_band_28_map[j]; 181 182 out[i][j].re *= gain[k]; 183 out[i][j].im *= gain[k]; 184 } 185 } 186 } 187 188 void ixheaacd_mps_decor_init(ia_mps_decor_struct_handle self, WORD32 subbands, 189 WORD32 decor_config) { 190 WORD32 i, reverb_band; 191 WORD32 *splitfreq; 192 193 switch (decor_config) { 194 case 0: 195 splitfreq = ixheaacd_qmf_split_freq_0; 196 break; 197 case 1: 198 splitfreq = ixheaacd_qmf_split_freq_1; 199 break; 200 case 2: 201 splitfreq = ixheaacd_qmf_split_freq_2; 202 break; 203 default: 204 return; 205 } 206 207 self->num_bins = subbands; 208 209 for (i = 0; i < self->num_bins; i++) { 210 reverb_band = 0; 211 while ((reverb_band < 3) && 212 (ixheaacd_hybrid_to_qmf_map[i] >= (splitfreq[reverb_band] - 1))) 213 reverb_band++; 214 215 self->delay_sample_count[i] = ixheaacd_decorr_delay[reverb_band]; 216 ixheaacd_mps_decor_filt_init(&self->filter[i], reverb_band); 217 } 218 219 self->decor_nrg_smooth.num_bins = self->num_bins; 220 221 return; 222 } 223 224 VOID ixheaacd_mps_decor_apply( 225 ia_mps_decor_struct_handle self, 226 ia_cmplx_flt_struct in[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS], 227 ia_cmplx_flt_struct out[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS], 228 WORD32 length) { 229 WORD32 idx, sb_sample; 230 231 ia_cmplx_flt_struct scratch[MAX_TIME_SLOTS]; 232 233 for (idx = 0; idx < self->num_bins; idx++) { 234 for (sb_sample = 0; sb_sample < length; sb_sample++) { 235 self->decor_delay_buffer[idx][self->delay_sample_count[idx] + sb_sample] 236 .re = in[sb_sample][idx].re; 237 self->decor_delay_buffer[idx][self->delay_sample_count[idx] + sb_sample] 238 .im = in[sb_sample][idx].im; 239 } 240 ixheaacd_mps_allpass_apply(&self->filter[idx], 241 self->decor_delay_buffer[idx], length, scratch); 242 243 for (sb_sample = 0; sb_sample < length; sb_sample++) { 244 out[sb_sample][idx].re = scratch[sb_sample].re; 245 out[sb_sample][idx].im = scratch[sb_sample].im; 246 } 247 248 for (sb_sample = 0; sb_sample < self->delay_sample_count[idx]; 249 sb_sample++) { 250 self->decor_delay_buffer[idx][sb_sample].re = 251 self->decor_delay_buffer[idx][length + sb_sample].re; 252 self->decor_delay_buffer[idx][sb_sample].im = 253 self->decor_delay_buffer[idx][length + sb_sample].im; 254 } 255 } 256 257 ixheaacd_mps_decor_energy_adjustment(&self->decor_nrg_smooth, in, out, 258 length); 259 } 260