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