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