• 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 <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 
ixheaacd_mps_mult32_local(WORD32 a,WORD32 b,WORD16 shift)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 
ixheaacd_mps_hyb_filt_type1(ia_cmplx_w32_struct * input,ia_cmplx_w32_struct output[8][MAX_TIME_SLOTS],WORD32 num_samples,const WORD32 * filt_coeff)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 
ixheaacd_mps_hyb_filt_type2(ia_cmplx_w32_struct * input,ia_cmplx_w32_struct output[2][MAX_TIME_SLOTS],WORD32 num_samples,const WORD32 * filt_coeff)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 
ixheaacd_mps_qmf_hybrid_analysis_init(ia_mps_hybrid_filt_struct * handle)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 
ixheaacd_mps_qmf_hybrid_analysis(ia_mps_hybrid_filt_struct * handle,ia_cmplx_flt_struct in_qmf[MAX_TIME_SLOTS][MAX_NUM_QMF_BANDS_MPS_NEW],WORD32 num_bands,WORD32 num_samples,ia_cmplx_flt_struct hyb[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS])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 
ixheaacd_mps_qmf_hybrid_synthesis(ia_cmplx_flt_struct hyb[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS],WORD32 num_bands,WORD32 num_samples,ia_cmplx_flt_struct in_qmf[MAX_TIME_SLOTS][MAX_NUM_QMF_BANDS_MPS])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