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 <math.h>
22
23 #include <ixheaacd_type_def.h>
24
25 #include "ixheaacd_bitbuffer.h"
26 #include "ixheaacd_interface.h"
27
28 #include "ixheaacd_tns_usac.h"
29 #include "ixheaacd_cnst.h"
30
31 #include "ixheaacd_acelp_info.h"
32
33 #include "ixheaacd_td_mdct.h"
34
35 #include "ixheaacd_sbrdecsettings.h"
36 #include "ixheaacd_info.h"
37 #include "ixheaacd_sbr_common.h"
38 #include "ixheaacd_drc_data_struct.h"
39 #include "ixheaacd_drc_dec.h"
40 #include "ixheaacd_sbrdecoder.h"
41 #include "ixheaacd_mps_polyphase.h"
42 #include "ixheaacd_sbr_const.h"
43
44 #include "ixheaacd_main.h"
45 #include "ixheaacd_arith_dec.h"
46
47 #include "ixheaacd_func_def.h"
48 #include "ixheaacd_constants.h"
49 #include <ixheaacd_type_def.h>
50 #include <ixheaacd_basic_ops32.h>
51 #include <ixheaacd_basic_ops40.h>
52
53 extern const WORD32 ixheaacd_pre_post_twid_cos_sin_512[4][512];
54 extern const WORD32 ixheaacd_pre_post_twid_cos_sin_384[4][384];
55 extern const WORD32 ixheaacd_pre_post_twid_cos_sin_256[4][256];
56 extern const WORD32 ixheaacd_pre_post_twid_cos_sin_192[4][192];
57 extern const WORD32 ixheaacd_pre_post_twid_cos_sin_128[4][128];
58 extern const WORD32 ixheaacd_pre_post_twid_cos_sin_96[4][96];
59 extern const WORD32 ixheaacd_pre_post_twid_cos_sin_64[4][64];
60 extern const WORD32 ixheaacd_pre_post_twid_cos_sin_48[4][48];
61 extern const WORD32 ixheaacd_pre_post_twid_cos_sin_32[4][32];
62 extern const WORD32 ixheaacd_pre_post_twid_cos_sin_24[4][24];
63
ixheaacd_mul_sub64_sat_32(WORD32 a,WORD32 b,WORD32 c,WORD32 d)64 static PLATFORM_INLINE WORD32 ixheaacd_mul_sub64_sat_32(WORD32 a, WORD32 b,
65 WORD32 c, WORD32 d) {
66 WORD64 diff;
67 WORD64 temp_result1;
68 WORD64 temp_result2;
69
70 temp_result1 = (WORD64)a * (WORD64)c;
71 temp_result2 = (WORD64)b * (WORD64)d;
72
73 diff = (temp_result1 - temp_result2) >> 32;
74
75 if (diff >= 2147483647)
76 diff = 2147483647;
77 else if (diff <= -2147483647 - 1)
78 diff = -2147483647 - 1;
79
80 return ((WORD32)diff);
81 }
82
ixheaacd_mul_add64_sat_32(WORD32 a,WORD32 b,WORD32 c,WORD32 d)83 static PLATFORM_INLINE WORD32 ixheaacd_mul_add64_sat_32(WORD32 a, WORD32 b,
84 WORD32 c, WORD32 d) {
85 WORD64 sum;
86 WORD64 temp_result1;
87 WORD64 temp_result2;
88
89 temp_result1 = (WORD64)a * (WORD64)c;
90 temp_result2 = (WORD64)b * (WORD64)d;
91
92 sum = (temp_result1 + temp_result2) >> 32;
93
94 if (sum >= 2147483647)
95 sum = 2147483647;
96 else if (sum <= -2147483647 - 1)
97 sum = -2147483647 - 1;
98
99 return ((WORD32)sum);
100 }
101
ixheaacd_pre_twid(WORD32 * in,WORD32 * r_ptr,WORD32 * i_ptr,WORD32 nlength,const WORD32 * ptr_pre_cos_sin)102 static void ixheaacd_pre_twid(WORD32 *in, WORD32 *r_ptr, WORD32 *i_ptr,
103 WORD32 nlength, const WORD32 *ptr_pre_cos_sin) {
104 WORD32 i;
105
106 const WORD32 *cos_ptr = &ptr_pre_cos_sin[0];
107 const WORD32 *sin_ptr = &ptr_pre_cos_sin[nlength];
108
109 for (i = 0; i < nlength; i += 4) {
110 *r_ptr++ = ixheaacd_mul_sub64_sat_32(in[i], in[nlength + i], cos_ptr[i],
111 sin_ptr[i]);
112 *i_ptr++ = ixheaacd_mul_add64_sat_32(in[i], in[nlength + i], sin_ptr[i],
113 cos_ptr[i]);
114
115 *r_ptr++ = ixheaacd_mul_sub64_sat_32(in[i + 1], in[nlength + i + 1],
116 cos_ptr[i + 1], sin_ptr[i + 1]);
117 *i_ptr++ = ixheaacd_mul_add64_sat_32(in[i + 1], in[nlength + i + 1],
118 sin_ptr[i + 1], cos_ptr[i + 1]);
119
120 *r_ptr++ = ixheaacd_mul_sub64_sat_32(in[i + 2], in[nlength + i + 2],
121 cos_ptr[i + 2], sin_ptr[i + 2]);
122 *i_ptr++ = ixheaacd_mul_add64_sat_32(in[i + 2], in[nlength + i + 2],
123 sin_ptr[i + 2], cos_ptr[i + 2]);
124
125 *r_ptr++ = ixheaacd_mul_sub64_sat_32(in[i + 3], in[nlength + i + 3],
126 cos_ptr[i + 3], sin_ptr[i + 3]);
127 *i_ptr++ = ixheaacd_mul_add64_sat_32(in[i + 3], in[nlength + i + 3],
128 sin_ptr[i + 3], cos_ptr[i + 3]);
129 }
130 }
131
ixheaacd_post_twid(WORD32 * data_re,WORD32 * data_im,WORD32 * out,WORD32 nlength,const WORD32 * ptr_post_cos_sin)132 static void ixheaacd_post_twid(WORD32 *data_re, WORD32 *data_im, WORD32 *out,
133 WORD32 nlength, const WORD32 *ptr_post_cos_sin) {
134 WORD32 i;
135
136 const WORD32 *cos_ptr = &ptr_post_cos_sin[nlength * 2];
137 const WORD32 *sin_ptr = &ptr_post_cos_sin[nlength * 3];
138
139 WORD32 *out_ptr = &out[2 * nlength - 1];
140 for (i = 0; i < nlength; i += 4) {
141 out[0] = ixheaacd_mul_sub64_sat_32(data_re[i], data_im[i], cos_ptr[i],
142 sin_ptr[i]);
143 out_ptr[0] = -ixheaacd_mul_add64_sat_32(data_re[i], data_im[i], sin_ptr[i],
144 cos_ptr[i]);
145
146 out[2] = ixheaacd_mul_sub64_sat_32(data_re[i + 1], data_im[i + 1],
147 cos_ptr[i + 1], sin_ptr[i + 1]);
148 out_ptr[-2] = -ixheaacd_mul_add64_sat_32(data_re[i + 1], data_im[i + 1],
149 sin_ptr[i + 1], cos_ptr[i + 1]);
150
151 out[4] = ixheaacd_mul_sub64_sat_32(data_re[i + 2], data_im[i + 2],
152 cos_ptr[i + 2], sin_ptr[i + 2]);
153 out_ptr[-4] = -ixheaacd_mul_add64_sat_32(data_re[i + 2], data_im[i + 2],
154 sin_ptr[i + 2], cos_ptr[i + 2]);
155
156 out[6] = ixheaacd_mul_sub64_sat_32(data_re[i + 3], data_im[i + 3],
157 cos_ptr[i + 3], sin_ptr[i + 3]);
158 out_ptr[-6] = -ixheaacd_mul_add64_sat_32(data_re[i + 3], data_im[i + 3],
159 sin_ptr[i + 3], cos_ptr[i + 3]);
160 out += 8;
161 out_ptr -= 8;
162 }
163 }
164
ixheaacd_acelp_mdct(WORD32 * ptr_in,WORD32 * ptr_out,WORD32 * preshift,WORD32 length,WORD32 * ptr_scratch)165 WORD32 ixheaacd_acelp_mdct(WORD32 *ptr_in, WORD32 *ptr_out, WORD32 *preshift,
166 WORD32 length, WORD32 *ptr_scratch) {
167 WORD32 *ptr_data_r = ptr_scratch;
168 WORD32 *ptr_data_i = ptr_scratch + 512;
169 const WORD32 *ptr_pre_post_twid;
170 WORD32 err = 0;
171
172 switch (length) {
173 case 1024:
174 ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_512[0][0];
175 break;
176 case 768:
177 ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_384[0][0];
178 break;
179 case 512:
180 ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_256[0][0];
181 break;
182 case 384:
183 ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_192[0][0];
184 break;
185 case 256:
186 ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_128[0][0];
187 break;
188 case 192:
189 ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_96[0][0];
190 break;
191 case 128:
192 ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_64[0][0];
193 break;
194 case 96:
195 ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_48[0][0];
196 break;
197 case 64:
198 ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_32[0][0];
199 break;
200 case 48:
201 ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_24[0][0];
202 break;
203 default:
204 ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_24[0][0];
205 break;
206 }
207
208 ixheaacd_pre_twid(ptr_in, ptr_data_r, ptr_data_i, length / 2,
209 ptr_pre_post_twid);
210
211 ixheaacd_complex_fft(ptr_data_r, ptr_data_i, length / 2, -1, preshift);
212 *preshift += 1;
213
214 ixheaacd_post_twid(ptr_data_r, ptr_data_i, ptr_out, length / 2,
215 ptr_pre_post_twid);
216 *preshift += 1;
217 return err;
218 }
219
ixheaacd_acelp_mdct_main(ia_usac_data_struct * usac_data,WORD32 * in,WORD32 * out,WORD32 l,WORD32 m,WORD32 * preshift)220 WORD32 ixheaacd_acelp_mdct_main(ia_usac_data_struct *usac_data, WORD32 *in,
221 WORD32 *out, WORD32 l, WORD32 m,
222 WORD32 *preshift) {
223 WORD32 i;
224 WORD32 *ptr_scratch = &usac_data->scratch_buffer[0];
225 WORD32 *output_buffer = &usac_data->x_ac_dec[0];
226 WORD32 err = 0;
227
228 err = ixheaacd_acelp_mdct(in, output_buffer, preshift, l + m, ptr_scratch);
229 if (err == -1) return err;
230
231 for (i = 0; i < m / 2; i++) {
232 out[l + m / 2 - 1 - i] = -output_buffer[m / 2 + l / 2 + i];
233 }
234 for (i = 0; i < l / 2; i++) {
235 out[i] = output_buffer[m + l / 2 + i];
236 out[l - 1 - i] = -output_buffer[m + l / 2 + i];
237 }
238 for (i = 0; i < m / 2; i++) {
239 out[l + m / 2 + i] = -output_buffer[m / 2 + l / 2 - 1 - i];
240 }
241 for (i = 0; i < l / 2; i++) {
242 out[l + m + i] = -output_buffer[l / 2 - 1 - i];
243 out[2 * l + m - 1 - i] = -output_buffer[l / 2 - 1 - i];
244 }
245 return err;
246 }
247