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 <math.h> 21 #include <string.h> 22 #include "ixheaacd_type_def.h" 23 #include "ixheaacd_bitbuffer.h" 24 #include "ixheaacd_config.h" 25 26 #include "ixheaacd_mps_polyphase.h" 27 #include "ixheaacd_mps_dec.h" 28 #include "ixheaacd_mps_interface.h" 29 30 #include "ixheaacd_mps_polyphase.h" 31 #include "ixheaacd_constants.h" 32 #include "ixheaacd_basic_ops32.h" 33 34 #include "ixheaacd_mps_hybfilter.h" 35 36 extern const WORD32 ixheaacd_ia_mps_hyb_filter_coeff_8[QMF_HYBRID_FILT_ORDER]; 37 extern const WORD32 ixheaacd_mps_hyb_filter_coeff_2[QMF_HYBRID_FILT_ORDER]; 38 extern const WORD32 ixheaacd_cosine[8][13]; 39 extern const WORD32 ixheaacd_sine[8][13]; 40 extern const WORD32 ixheaacd_cosine2[2][13]; 41 42 static WORD32 ixheaacd_mps_mult32_local(WORD32 a, WORD32 b, WORD16 shift) { 43 WORD64 temp; 44 45 temp = (WORD64)a * (WORD64)b; 46 temp = temp >> shift; 47 return (WORD32)temp; 48 } 49 50 static VOID ixheaacd_mps_hyb_filt_type1( 51 ia_cmplx_w32_struct *input, ia_cmplx_w32_struct output[8][MAX_TIME_SLOTS], 52 WORD32 num_samples, const WORD32 *filt_coeff) 53 54 { 55 WORD32 i, n, q; 56 57 WORD32 modulation_fac_re, modulation_fac_im; 58 WORD32 in_re, in_im; 59 WORD32 temp; 60 WORD32 coeff; 61 WORD64 acc_re, acc_im; 62 63 WORD16 shift = 8; 64 65 for (i = 0; i < num_samples; i++) { 66 for (q = 0; q < 8; q++) { 67 acc_re = 0; 68 acc_im = 0; 69 for (n = 0; n < QMF_HYBRID_FILT_ORDER; n++) { 70 modulation_fac_re = ixheaacd_cosine[q][n]; 71 modulation_fac_im = ixheaacd_sine[q][n]; 72 73 in_re = (WORD32)(input[n + i].re); 74 in_im = (WORD32)(input[n + i].im); 75 76 in_re = ixheaacd_shl32_sat(in_re, shift); 77 in_im = ixheaacd_shl32_sat(in_im, shift); 78 79 coeff = filt_coeff[QMF_HYBRID_FILT_ORDER - 1 - n]; 80 81 temp = ixheaacd_sub32_sat( 82 ixheaacd_mps_mult32_local(in_re, modulation_fac_re, 30), 83 ixheaacd_mps_mult32_local(in_im, modulation_fac_im, 30)); 84 85 if (temp >= 1073741823) 86 temp = 1073741823; 87 else if (temp <= -1073741824) 88 temp = -1073741824; 89 90 temp = ixheaacd_mps_mult32_local(coeff, temp, 30); 91 acc_re = acc_re + (WORD64)temp; 92 93 temp = ixheaacd_add32_sat( 94 ixheaacd_mps_mult32_local(in_im, modulation_fac_re, 30), 95 ixheaacd_mps_mult32_local(in_re, modulation_fac_im, 30)); 96 97 if (temp >= 1073741823) 98 temp = 1073741823; 99 else if (temp <= -1073741824) 100 temp = -1073741824; 101 102 temp = ixheaacd_mps_mult32_local(coeff, temp, 30); 103 acc_im = acc_im + (WORD64)temp; 104 } 105 106 output[q][i].re = (WORD32)(acc_re >> shift); 107 output[q][i].im = (WORD32)(acc_im >> shift); 108 } 109 } 110 } 111 112 static VOID ixheaacd_mps_hyb_filt_type2( 113 ia_cmplx_w32_struct *input, ia_cmplx_w32_struct output[2][MAX_TIME_SLOTS], 114 WORD32 num_samples, const WORD32 *filt_coeff) 115 116 { 117 WORD32 i, n, q; 118 119 WORD32 modulation_fac_re; 120 WORD32 in_re, in_im; 121 WORD32 temp; 122 WORD32 coeff; 123 WORD64 acc_re, acc_im; 124 125 WORD16 shift = 8; 126 127 for (i = 0; i < num_samples; i++) { 128 for (q = 0; q < 2; q++) { 129 acc_re = 0; 130 acc_im = 0; 131 for (n = 0; n < QMF_HYBRID_FILT_ORDER; n++) { 132 modulation_fac_re = ixheaacd_cosine2[q][n]; 133 134 in_re = (WORD32)(input[n + i].re); 135 in_im = (WORD32)(input[n + i].im); 136 137 in_re = ixheaacd_shl32_sat(in_re, shift); 138 in_im = ixheaacd_shl32_sat(in_im, shift); 139 140 coeff = filt_coeff[QMF_HYBRID_FILT_ORDER - 1 - n]; 141 142 temp = ixheaacd_mps_mult32_local(in_re, modulation_fac_re, 30); 143 144 if (temp >= 1073741823) 145 temp = 1073741823; 146 else if (temp <= -1073741824) 147 temp = -1073741824; 148 149 temp = ixheaacd_mps_mult32_local(coeff, temp, 30); 150 acc_re = acc_re + (WORD64)temp; 151 152 temp = ixheaacd_mps_mult32_local(in_im, modulation_fac_re, 30); 153 154 if (temp >= 1073741823) 155 temp = 1073741823; 156 else if (temp <= -1073741824) 157 temp = -1073741824; 158 159 temp = ixheaacd_mps_mult32_local(coeff, temp, 30); 160 acc_im = acc_im + (WORD64)temp; 161 } 162 163 output[q][i].re = (WORD32)(acc_re >> shift); 164 output[q][i].im = (WORD32)(acc_im >> shift); 165 } 166 } 167 } 168 169 VOID ixheaacd_mps_qmf_hybrid_analysis_init(ia_mps_hybrid_filt_struct *handle) { 170 memset(handle->lf_buffer, 0, 171 QMF_BANDS_TO_HYBRID * BUFFER_LEN_LF_MPS * sizeof(ia_cmplx_w32_struct)); 172 memset(handle->hf_buffer, 0, MAX_NUM_QMF_BANDS_MPS * BUFFER_LEN_HF_MPS * 173 sizeof(ia_cmplx_flt_struct)); 174 } 175 176 VOID ixheaacd_mps_qmf_hybrid_analysis( 177 ia_mps_hybrid_filt_struct *handle, 178 ia_cmplx_flt_struct in_qmf[MAX_TIME_SLOTS][MAX_NUM_QMF_BANDS_MPS_NEW], 179 WORD32 num_bands, WORD32 num_samples, 180 ia_cmplx_flt_struct hyb[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS]) { 181 WORD32 lf_samples_shift; 182 WORD32 hf_samples_shift; 183 WORD32 lf_qmf_bands; 184 WORD32 k, n; 185 186 ia_cmplx_w32_struct scratch[MAX_HYBRID_ONLY_BANDS_PER_QMF][MAX_TIME_SLOTS]; 187 188 lf_samples_shift = BUFFER_LEN_LF_MPS - num_samples; 189 hf_samples_shift = BUFFER_LEN_HF_MPS - num_samples; 190 191 lf_qmf_bands = QMF_BANDS_TO_HYBRID; 192 193 for (k = 0; k < lf_qmf_bands; k++) { 194 for (n = 0; n < lf_samples_shift; n++) { 195 handle->lf_buffer[k][n].re = handle->lf_buffer[k][n + num_samples].re; 196 handle->lf_buffer[k][n].im = handle->lf_buffer[k][n + num_samples].im; 197 } 198 } 199 200 for (k = 0; k < lf_qmf_bands; k++) { 201 for (n = 0; n < num_samples; n++) { 202 handle->lf_buffer[k][n + lf_samples_shift].re = (WORD32)(in_qmf[n][k].re); 203 handle->lf_buffer[k][n + lf_samples_shift].im = (WORD32)(in_qmf[n][k].im); 204 } 205 } 206 207 for (k = 0; k < num_bands - lf_qmf_bands; k++) { 208 for (n = 0; n < hf_samples_shift; n++) { 209 handle->hf_buffer[k][n].re = handle->hf_buffer[k][n + num_samples].re; 210 handle->hf_buffer[k][n].im = handle->hf_buffer[k][n + num_samples].im; 211 } 212 } 213 214 for (k = 0; k < num_bands - lf_qmf_bands; k++) { 215 for (n = 0; n < num_samples; n++) { 216 handle->hf_buffer[k][n + hf_samples_shift].re = 217 (in_qmf[n][k + lf_qmf_bands].re); 218 handle->hf_buffer[k][n + hf_samples_shift].im = 219 (in_qmf[n][k + lf_qmf_bands].im); 220 } 221 } 222 223 ixheaacd_mps_hyb_filt_type1( 224 &(handle->lf_buffer[0][lf_samples_shift + 1 - QMF_HYBRID_FILT_ORDER]), 225 scratch, num_samples, ixheaacd_ia_mps_hyb_filter_coeff_8); 226 227 for (k = 0; k < 2; k++) { 228 for (n = 0; n < num_samples; n++) { 229 hyb[n][k].re = (FLOAT32)scratch[k + 6][n].re; 230 hyb[n][k + 2].re = (FLOAT32)scratch[k][n].re; 231 hyb[n][k + 4].re = (FLOAT32)scratch[k + 2][n].re; 232 hyb[n][k + 4].re += (FLOAT32)scratch[5 - k][n].re; 233 234 hyb[n][k].im = (FLOAT32)scratch[k + 6][n].im; 235 hyb[n][k + 2].im = (FLOAT32)scratch[k][n].im; 236 hyb[n][k + 4].im = (FLOAT32)scratch[k + 2][n].im; 237 hyb[n][k + 4].im += (FLOAT32)scratch[5 - k][n].im; 238 } 239 } 240 241 ixheaacd_mps_hyb_filt_type2( 242 &(handle->lf_buffer[1][lf_samples_shift + 1 - QMF_HYBRID_FILT_ORDER]), 243 scratch, num_samples, ixheaacd_mps_hyb_filter_coeff_2); 244 245 for (k = 0; k < 2; k++) { 246 for (n = 0; n < num_samples; n++) { 247 hyb[n][k + 6].re = (FLOAT32)scratch[1 - k][n].re; 248 hyb[n][k + 6].im = (FLOAT32)scratch[1 - k][n].im; 249 } 250 } 251 252 ixheaacd_mps_hyb_filt_type2( 253 &(handle->lf_buffer[2][lf_samples_shift + 1 - QMF_HYBRID_FILT_ORDER]), 254 scratch, num_samples, ixheaacd_mps_hyb_filter_coeff_2); 255 256 for (k = 0; k < 2; k++) { 257 for (n = 0; n < num_samples; n++) { 258 hyb[n][k + 8].re = (FLOAT32)scratch[k][n].re; 259 hyb[n][k + 8].im = (FLOAT32)scratch[k][n].im; 260 } 261 } 262 263 for (k = 0; k < num_bands - lf_qmf_bands; k++) { 264 for (n = 0; n < num_samples; n++) { 265 hyb[n][k + 10].re = (handle->hf_buffer[k][n + hf_samples_shift].re); 266 hyb[n][k + 10].im = (handle->hf_buffer[k][n + hf_samples_shift].im); 267 } 268 } 269 } 270 271 VOID ixheaacd_mps_qmf_hybrid_synthesis( 272 ia_cmplx_flt_struct hyb[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS], 273 WORD32 num_bands, WORD32 num_samples, 274 ia_cmplx_flt_struct in_qmf[MAX_TIME_SLOTS][MAX_NUM_QMF_BANDS_MPS]) { 275 WORD32 k, n; 276 277 for (n = 0; n < num_samples; n++) { 278 in_qmf[n][0].re = hyb[n][0].re; 279 in_qmf[n][0].im = hyb[n][0].im; 280 281 for (k = 1; k < 6; k++) { 282 in_qmf[n][0].re += hyb[n][k].re; 283 in_qmf[n][0].im += hyb[n][k].im; 284 } 285 286 in_qmf[n][1].re = hyb[n][6].re + hyb[n][7].re; 287 in_qmf[n][1].im = hyb[n][6].im + hyb[n][7].im; 288 289 in_qmf[n][2].re = hyb[n][8].re + hyb[n][9].re; 290 in_qmf[n][2].im = hyb[n][8].im + hyb[n][9].im; 291 292 for (k = 3; k < num_bands; k++) { 293 in_qmf[n][k].re = hyb[n][k - 3 + 10].re; 294 in_qmf[n][k].im = hyb[n][k - 3 + 10].im; 295 } 296 } 297 } 298