• 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 <string.h>
22 #include <math.h>
23 
24 #include "ixheaacd_type_def.h"
25 #include "ixheaacd_bitbuffer.h"
26 #include "ixheaacd_interface.h"
27 #include "ixheaacd_tns_usac.h"
28 #include "ixheaacd_cnst.h"
29 #include "ixheaacd_acelp_info.h"
30 #include "ixheaacd_td_mdct.h"
31 #include "ixheaacd_sbrdecsettings.h"
32 #include "ixheaacd_info.h"
33 #include "ixheaacd_sbr_common.h"
34 #include "ixheaacd_drc_data_struct.h"
35 #include "ixheaacd_drc_dec.h"
36 #include "ixheaacd_sbrdecoder.h"
37 #include "ixheaacd_mps_polyphase.h"
38 #include "ixheaacd_sbr_const.h"
39 #include "ixheaacd_main.h"
40 #include "ixheaacd_arith_dec.h"
41 #include "ixheaacd_windows.h"
42 #include "ixheaacd_constants.h"
43 #include "ixheaacd_basic_ops32.h"
44 #include "ixheaacd_basic_ops40.h"
45 #include "ixheaacd_func_def.h"
46 #include "ixheaacd_acelp_com.h"
47 
ixheaacd_mult32_m(WORD32 a,WORD32 b)48 static PLATFORM_INLINE WORD32 ixheaacd_mult32_m(WORD32 a, WORD32 b) {
49   WORD32 result;
50   WORD64 temp_result;
51 
52   temp_result = (WORD64)a * (WORD64)b;
53   result = (WORD32)(temp_result >> 31);
54 
55   return (result);
56 }
57 
ixheaacd_weighted_synthesis_filter(WORD32 * a,WORD32 * ap)58 static VOID ixheaacd_weighted_synthesis_filter(WORD32 *a, WORD32 *ap) {
59   WORD32 f;
60   WORD32 i;
61   ap[0] = a[0];
62   f = IGAMMA1;
63   for (i = 1; i <= ORDER; i++) {
64     ap[i] = ixheaacd_mult32_m(f, a[i]);
65     f = ixheaacd_mult32_m(f, IGAMMA1);
66   }
67   return;
68 }
69 
ixheaacd_synthesis_tool(WORD32 a[],WORD32 x[],WORD32 l,WORD32 qshift,WORD32 * preshift)70 static VOID ixheaacd_synthesis_tool(WORD32 a[], WORD32 x[], WORD32 l,
71                                     WORD32 qshift, WORD32 *preshift) {
72   WORD32 s;
73   WORD32 i, j;
74 
75   for (i = 0; i < l; i++) {
76     s = x[i];
77     for (j = 1; j <= ORDER; j += 4) {
78       s = ixheaacd_sub32_sat(
79           s, ixheaacd_mul32_sh(a[j], x[i - j], (WORD8)(qshift)));
80       s = ixheaacd_sub32_sat(
81           s, ixheaacd_mul32_sh(a[j + 1], x[i - (j + 1)], (WORD8)(qshift)));
82       s = ixheaacd_sub32_sat(
83           s, ixheaacd_mul32_sh(a[j + 2], x[i - (j + 2)], (WORD8)(qshift)));
84       s = ixheaacd_sub32_sat(
85           s, ixheaacd_mul32_sh(a[j + 3], x[i - (j + 3)], (WORD8)(qshift)));
86     }
87     x[i] = s;
88   }
89 
90   (*preshift)++;
91   return;
92 }
93 
ixheaacd_fwd_alias_cancel_tool(ia_usac_data_struct * usac_data,ia_td_frame_data_struct * pstr_td_frame_data,WORD32 fac_length,FLOAT32 * lp_filt_coeff,WORD32 gain)94 WORD32 ixheaacd_fwd_alias_cancel_tool(
95     ia_usac_data_struct *usac_data, ia_td_frame_data_struct *pstr_td_frame_data,
96     WORD32 fac_length, FLOAT32 *lp_filt_coeff, WORD32 gain) {
97   WORD32 i;
98   FLOAT32 lp_filt_coeff_a[ORDER + 1];
99   WORD32 qshift = 0;
100   WORD32 err = 0;
101 
102   WORD32 *x_in = pstr_td_frame_data->fac_data;
103   WORD32 *ptr_scratch = &usac_data->scratch_buffer[0];
104   WORD32 *fac_signal = &usac_data->x_ac_dec[16];
105   FLOAT32 fac_signal_flt[128 + 16];
106   FLOAT32 *ptr_fac_signal_flt = &fac_signal_flt[16];
107   WORD32 *ptr_overlap_buf =
108       &(usac_data->overlap_data_ptr[usac_data->present_chan]
109                                    [(usac_data->ccfl / 2) - fac_length]);
110 
111   memset(fac_signal - 16, 0, ORDER * sizeof(WORD32));
112 
113   err = ixheaacd_acelp_mdct(x_in, fac_signal, &qshift, fac_length, ptr_scratch);
114   if (err == -1) return err;
115 
116   ixheaacd_lpc_coeff_wt_apply(lp_filt_coeff, lp_filt_coeff_a);
117 
118   for (i = 0; i < fac_length; i++)
119     ptr_fac_signal_flt[i] =
120         (FLOAT32)((FLOAT32)fac_signal[i] / (1 << (16 - qshift)));
121 
122   memset(ptr_fac_signal_flt - 16, 0, 16 * sizeof(FLOAT32));
123 
124   ixheaacd_synthesis_tool_float1(lp_filt_coeff_a, ptr_fac_signal_flt,
125                                  fac_length);
126 
127   for (i = 0; i < fac_length; i++)
128     fac_signal[i] = (WORD32)(ptr_fac_signal_flt[i] * (1 << (16 - qshift)));
129 
130   for (i = 0; i < fac_length; i++)
131     ptr_overlap_buf[i] = ixheaacd_add32_sat(
132         ptr_overlap_buf[i],
133         (WORD32)ixheaacd_mul32_sh(fac_signal[i], gain, (WORD8)(16 - qshift)));
134 
135   return err;
136 }
137 
ixheaacd_fr_alias_cnx_fix(WORD32 * x_in,WORD32 len,WORD32 fac_length,WORD32 * lp_filt_coeff,WORD32 * izir,WORD32 * fac_data_out,WORD8 * qshift1,WORD8 qshift2,WORD8 qshift3,WORD32 * preshift,WORD32 * ptr_scratch)138 WORD32 ixheaacd_fr_alias_cnx_fix(WORD32 *x_in, WORD32 len, WORD32 fac_length,
139                                  WORD32 *lp_filt_coeff, WORD32 *izir,
140                                  WORD32 *fac_data_out, WORD8 *qshift1,
141                                  WORD8 qshift2, WORD8 qshift3, WORD32 *preshift,
142                                  WORD32 *ptr_scratch) {
143   WORD32 i;
144   const WORD32 *sine_window;
145   WORD32 fac_window[2 * FAC_LENGTH];
146   WORD32 lp_filt_coeff_a[ORDER + 1];
147   WORD32 err = 0;
148 
149   if (fac_length == 48) {
150     sine_window = ixheaacd_sine_win_96;
151   } else if (fac_length == 64) {
152     sine_window = ixheaacd_sine_win_128;
153   } else if (fac_length == 96) {
154     sine_window = ixheaacd_sine_win_192;
155   } else {
156     sine_window = ixheaacd_sine_win_256;
157   }
158   if (FAC_LENGTH < fac_length) {
159     return -1;
160   }
161 
162   if (FAC_LENGTH < fac_length) {
163     return -1;
164   }
165   if ((1 + (len / 2)) < (fac_length + 1)) {
166     return -1;
167   }
168   if ((len / 2 + 1) > (2 * LEN_FRAME - fac_length - 1)) {
169     return -1;
170   }
171 
172   if (lp_filt_coeff != NULL && fac_data_out != NULL) {
173     memset(fac_data_out - 16, 0, ORDER * sizeof(WORD32));
174     err = ixheaacd_acelp_mdct(x_in, fac_data_out, preshift, fac_length,
175                               ptr_scratch);
176     if (err == -1) return err;
177 
178     ixheaacd_weighted_synthesis_filter(lp_filt_coeff, lp_filt_coeff_a);
179 
180     memset(fac_data_out + fac_length, 0, fac_length * sizeof(WORD32));
181 
182     ixheaacd_synthesis_tool(lp_filt_coeff_a, fac_data_out, 2 * fac_length,
183                             qshift2, preshift);
184 
185     if (izir != NULL) {
186       for (i = 0; i < fac_length; i++) {
187         fac_window[i] = ixheaacd_mult32_m(
188             sine_window[i], sine_window[(2 * fac_length) - 1 - i]);
189         fac_window[fac_length + i] =
190             2147483647 - ixheaacd_mult32_m(sine_window[fac_length + i],
191                                            sine_window[fac_length + i]);
192       }
193       for (i = 0; i < fac_length; i++) {
194         WORD32 temp1;
195         WORD32 temp2;
196 
197         temp1 = ixheaacd_mul32_sh(
198             izir[1 + (len / 2) + i], fac_window[fac_length + i],
199             (char)((qshift3 - *qshift1 + 31 + (WORD8)(*preshift))));
200 
201         temp2 = ixheaacd_mul32_sh(
202             izir[1 + (len / 2) - 1 - i], fac_window[fac_length - 1 - i],
203             (char)((qshift3 - *qshift1 + 31 + (WORD8)(*preshift))));
204 
205         fac_data_out[i] =
206             ixheaacd_add32_sat3((fac_data_out[i] / 2), temp1, temp2);
207 
208         fac_data_out[fac_length + i] = (fac_data_out[fac_length + i] / 2);
209       }
210     }
211   }
212 
213   return err;
214 }
215