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