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 <stdlib.h> 21 #include <stdio.h> 22 #include <string.h> 23 #include <math.h> 24 #include <ixheaacd_type_def.h> 25 #include <ixheaacd_interface.h> 26 #include "ixheaacd_mps_polyphase.h" 27 #include <ixheaacd_type_def.h> 28 #include "ixheaacd_bitbuffer.h" 29 #include "ixheaacd_config.h" 30 #include "ixheaacd_mps_dec.h" 31 #include "ixheaacd_mps_interface.h" 32 #include "ixheaacd_constants.h" 33 #include <ixheaacd_basic_ops32.h> 34 #include "ixheaacd_function_selector.h" 35 36 extern const WORD32 37 ixheaacd_mps_polyphase_filter_coeff_fix[10 * MAX_NUM_QMF_BANDS_SAC / 2]; 38 extern WORD32 ixheaacd_mps_pre_re[64]; 39 extern WORD32 ixheaacd_mps_pre_im[64]; 40 extern WORD32 ixheaacd_mps_post_re[128]; 41 extern WORD32 ixheaacd_mps_post_im[128]; 42 43 static PLATFORM_INLINE WORD32 ixheaacd_mult32(WORD32 a, WORD32 b) { 44 WORD32 result; 45 WORD64 temp_result; 46 47 temp_result = (WORD64)a * (WORD64)b; 48 result = (WORD32)(temp_result >> 31); 49 50 return (result); 51 } 52 53 VOID ixheaacd_mps_synt_create(ia_mps_poly_phase_struct *kernel, 54 WORD32 resolution) { 55 kernel->resolution = resolution; 56 } 57 58 VOID ixheaacd_mps_synt_init(ia_mps_poly_phase_synth_struct *self) { 59 memset(self->state, 0, sizeof(WORD32) * 64 * 20); 60 } 61 62 static VOID ixheaacd_float_to_int32(FLOAT32 *in, WORD32 *out, WORD32 q_factor, 63 WORD32 sample) { 64 WORD32 loop; 65 UWORD32 temp = (1 << q_factor); 66 67 for (loop = 0; loop < sample; loop++) out[loop] = (WORD32)(in[loop] * temp); 68 } 69 70 VOID ixheaacd_mps_synt_pre_twiddle_dec(WORD32 *ptr_in, WORD32 *table_re, 71 WORD32 *table_im, WORD32 resolution) { 72 WORD32 tmp, k; 73 for (k = 0; k < 2 * resolution; k += 2) { 74 tmp = ixheaacd_add32_sat(ixheaacd_mult32(ptr_in[k], table_re[k >> 1]), 75 ixheaacd_mult32(ptr_in[k + 1], table_im[k >> 1])); 76 77 ptr_in[k + 1] = 78 ixheaacd_add32_sat(ixheaacd_mult32(-ptr_in[k], table_im[k >> 1]), 79 ixheaacd_mult32(ptr_in[k + 1], table_re[k >> 1])); 80 81 ptr_in[k] = tmp; 82 } 83 } 84 85 VOID ixheaacd_mps_synt_post_twiddle_dec(WORD32 *ptr_in, WORD32 *table_re, 86 WORD32 *table_im, WORD32 resolution) { 87 WORD32 tmp, k; 88 for (k = 0; k < 2 * resolution; k += 2) { 89 tmp = ixheaacd_add32_sat(ixheaacd_mult32(ptr_in[k], table_re[k]), 90 ixheaacd_mult32(ptr_in[k + 1], table_im[k])); 91 92 ptr_in[k + 1] = 93 ixheaacd_add32_sat(ixheaacd_mult32(-ptr_in[k], table_im[k]), 94 ixheaacd_mult32(ptr_in[k + 1], table_re[k])); 95 96 ptr_in[k] = tmp; 97 } 98 } 99 100 VOID ixheaacd_mps_synt_post_fft_twiddle_dec(WORD32 resolution, WORD32 *fin_re, 101 WORD32 *fin_im, WORD32 *table_re, 102 WORD32 *table_im, WORD32 *state) { 103 WORD32 l; 104 for (l = 0; l < 2 * resolution; l++) { 105 state[2 * resolution - l - 1] = 106 ixheaacd_add32_sat(ixheaacd_mult32(fin_re[l], table_re[l]), 107 ixheaacd_mult32(fin_im[l], table_im[l])); 108 } 109 } 110 111 VOID ixheaacd_mps_synt_out_calc_dec(WORD32 resolution, WORD32 *out, 112 WORD32 *state, const WORD32 *filter_coeff) { 113 WORD32 l, k; 114 WORD32 *out1, *out2, *state1, *state2; 115 out1 = out; 116 out2 = out + resolution; 117 state1 = state; 118 state2 = state + (3 * resolution); 119 120 for (k = 0; k < 5; k++) { 121 for (l = 0; l < resolution; l++) { 122 *out1++ = (WORD32)(((WORD64)(*state1++) * (*filter_coeff++)) >> 31); 123 *out2++ = (WORD32)(((WORD64)(*state2++) * (*filter_coeff++)) >> 31); 124 } 125 out1 += resolution; 126 out2 += resolution; 127 state1 += (3 * resolution); 128 state2 += (3 * resolution); 129 } 130 } 131 132 VOID ixheaacd_mps_synt_calc(ia_mps_dec_state_struct *self) { 133 WORD32 k, l, ts, ch; 134 WORD64 acc; 135 WORD32 ptr_in[128]; 136 WORD32 fin_re[128]; 137 WORD32 fin_im[128]; 138 FLOAT32 temp; 139 WORD32 *state, *tmp_state, *out; 140 const WORD32 *filt_coeff; 141 WORD32 *tmp_buf = self->tmp_buf; 142 143 ia_mps_poly_phase_struct kernel = self->poly_phase_filt_kernel; 144 WORD32 resolution = kernel.resolution; 145 for (ch = 0; ch < self->out_ch_count; ch++) { 146 tmp_state = (&self->qmf_filt_state[ch])->state; 147 state = &tmp_buf[self->time_slots * 2 * resolution]; 148 memcpy(state, tmp_state, sizeof(WORD32) * 20 * resolution); 149 out = &tmp_buf[74 * MAX_NUM_QMF_BANDS_SAC]; 150 151 for (ts = 0; ts < self->time_slots; ts++) { 152 ixheaacd_float_to_int32(&self->qmf_out_dir[ch][ts][0].re, ptr_in, 10, 153 resolution * 2); 154 155 filt_coeff = ixheaacd_mps_polyphase_filter_coeff_fix; 156 157 state -= (2 * resolution); 158 (*ixheaacd_mps_synt_pre_twiddle)(ptr_in, ixheaacd_mps_pre_re, 159 ixheaacd_mps_pre_im, resolution); 160 161 (*ixheaacd_mps_complex_fft_64)(ptr_in, fin_re, fin_im, resolution); 162 163 (*ixheaacd_mps_synt_post_twiddle)(ptr_in, ixheaacd_mps_post_re, 164 ixheaacd_mps_post_im, resolution); 165 166 (*ixheaacd_mps_complex_fft_64)(ptr_in, &fin_re[1], &fin_im[1], 167 resolution); 168 169 (*ixheaacd_mps_synt_post_fft_twiddle)(resolution, fin_re, fin_im, 170 ixheaacd_mps_post_re, 171 ixheaacd_mps_post_im, state); 172 (*ixheaacd_mps_synt_out_calc)(resolution, out, state, filt_coeff); 173 174 for (k = 0; k < resolution; k++) { 175 acc = 0; 176 for (l = 0; l < 10; l++) { 177 acc = acc + out[resolution * l + k]; 178 } 179 if (acc >= 2147483647) 180 temp = 1.0; 181 else if (acc <= -2147483647 - 1) 182 temp = -1.0f; 183 else 184 temp = (FLOAT32)((WORD32)acc) / ((FLOAT32)(1 << 10)); 185 186 self->output_buffer[ch][self->qmf_band_count * ts + k] = (FLOAT32)temp; 187 } 188 } 189 190 memcpy(tmp_state, state, sizeof(WORD32) * 20 * resolution); 191 } 192 } 193