• 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 
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 
ixheaacd_mps_mult32_local(WORD32 a,WORD32 b,WORD16 shift)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 
ixheaacd_mps_hyb_filt_type1(ia_cmplx_w32_struct * input,ia_cmplx_w32_struct output[8][MAX_TIME_SLOTS],WORD32 num_samples,WORD32 * filt_coeff)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 
ixheaacd_mps_hyb_filt_type2(ia_cmplx_w32_struct * input,ia_cmplx_w32_struct output[2][MAX_TIME_SLOTS],WORD32 num_samples,WORD32 * filt_coeff)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 
ixheaacd_mps_qmf_hybrid_analysis_init(ia_mps_hybrid_filt_struct * handle)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 
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])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 
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])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