1*15dc779aSAndroid Build Coastguard Worker /******************************************************************************
2*15dc779aSAndroid Build Coastguard Worker * *
3*15dc779aSAndroid Build Coastguard Worker * Copyright (C) 2023 The Android Open Source Project
4*15dc779aSAndroid Build Coastguard Worker *
5*15dc779aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
6*15dc779aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
7*15dc779aSAndroid Build Coastguard Worker * You may obtain a copy of the License at:
8*15dc779aSAndroid Build Coastguard Worker *
9*15dc779aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
10*15dc779aSAndroid Build Coastguard Worker *
11*15dc779aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
12*15dc779aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
13*15dc779aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*15dc779aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
15*15dc779aSAndroid Build Coastguard Worker * limitations under the License.
16*15dc779aSAndroid Build Coastguard Worker *
17*15dc779aSAndroid Build Coastguard Worker *****************************************************************************
18*15dc779aSAndroid Build Coastguard Worker * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19*15dc779aSAndroid Build Coastguard Worker */
20*15dc779aSAndroid Build Coastguard Worker
21*15dc779aSAndroid Build Coastguard Worker #include <string.h>
22*15dc779aSAndroid Build Coastguard Worker #include <stdlib.h>
23*15dc779aSAndroid Build Coastguard Worker #include "ixheaac_type_def.h"
24*15dc779aSAndroid Build Coastguard Worker #include "ixheaac_error_standards.h"
25*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_error_codes.h"
26*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_mps_common_fix.h"
27*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_mps_defines.h"
28*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_mps_common_define.h"
29*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_mps_buf.h"
30*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_mps_lib.h"
31*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_mps_main_structure.h"
32*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_mps_tools_rom.h"
33*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_mps_dct.h"
34*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_mps_qmf.h"
35*15dc779aSAndroid Build Coastguard Worker #include "ixheaac_constants.h"
36*15dc779aSAndroid Build Coastguard Worker #include "ixheaac_basic_ops32.h"
37*15dc779aSAndroid Build Coastguard Worker #include "ixheaac_basic_ops40.h"
38*15dc779aSAndroid Build Coastguard Worker #include "ixheaac_basic_ops.h"
39*15dc779aSAndroid Build Coastguard Worker
ixheaace_mps_212_qmf_forward_modulation_hq(ixheaace_mps_pstr_qmf_filter_bank pstr_qmf_filter_bank,const FLOAT32 * time_in,FLOAT32 * real_subband,FLOAT32 * imag_subband,WORD8 * ptr_scratch)40*15dc779aSAndroid Build Coastguard Worker static IA_ERRORCODE ixheaace_mps_212_qmf_forward_modulation_hq(
41*15dc779aSAndroid Build Coastguard Worker ixheaace_mps_pstr_qmf_filter_bank pstr_qmf_filter_bank, const FLOAT32 *time_in,
42*15dc779aSAndroid Build Coastguard Worker FLOAT32 *real_subband, FLOAT32 *imag_subband, WORD8 *ptr_scratch) {
43*15dc779aSAndroid Build Coastguard Worker IA_ERRORCODE error;
44*15dc779aSAndroid Build Coastguard Worker WORD32 idx;
45*15dc779aSAndroid Build Coastguard Worker WORD32 qmf_bands = pstr_qmf_filter_bank->no_channels;
46*15dc779aSAndroid Build Coastguard Worker WORD32 qmf_bands_by_2 = qmf_bands << 1;
47*15dc779aSAndroid Build Coastguard Worker FLOAT32 intermediate_band;
48*15dc779aSAndroid Build Coastguard Worker FLOAT32 x0, x1, y0, y1;
49*15dc779aSAndroid Build Coastguard Worker if (qmf_bands == 64) {
50*15dc779aSAndroid Build Coastguard Worker x0 = time_in[1];
51*15dc779aSAndroid Build Coastguard Worker y0 = time_in[0];
52*15dc779aSAndroid Build Coastguard Worker real_subband[0] = (x0 + y0) / 2;
53*15dc779aSAndroid Build Coastguard Worker imag_subband[0] = (x0 - y0) / 2;
54*15dc779aSAndroid Build Coastguard Worker for (idx = 1; idx < qmf_bands; idx++) {
55*15dc779aSAndroid Build Coastguard Worker x0 = time_in[idx + 1];
56*15dc779aSAndroid Build Coastguard Worker y0 = time_in[qmf_bands_by_2 - idx];
57*15dc779aSAndroid Build Coastguard Worker real_subband[idx] = (x0 - y0) / 2;
58*15dc779aSAndroid Build Coastguard Worker imag_subband[idx] = (x0 + y0) / 2;
59*15dc779aSAndroid Build Coastguard Worker }
60*15dc779aSAndroid Build Coastguard Worker } else {
61*15dc779aSAndroid Build Coastguard Worker for (idx = 0; idx < qmf_bands; idx += 2) {
62*15dc779aSAndroid Build Coastguard Worker x0 = time_in[idx + 0];
63*15dc779aSAndroid Build Coastguard Worker x1 = time_in[idx + 1];
64*15dc779aSAndroid Build Coastguard Worker y0 = time_in[qmf_bands_by_2 - 1 - idx];
65*15dc779aSAndroid Build Coastguard Worker y1 = time_in[qmf_bands_by_2 - 2 - idx];
66*15dc779aSAndroid Build Coastguard Worker
67*15dc779aSAndroid Build Coastguard Worker real_subband[idx + 0] = (x0 - y0) / 2;
68*15dc779aSAndroid Build Coastguard Worker real_subband[idx + 1] = (x1 - y1) / 2;
69*15dc779aSAndroid Build Coastguard Worker imag_subband[idx + 0] = (x0 + y0) / 2;
70*15dc779aSAndroid Build Coastguard Worker imag_subband[idx + 1] = (x1 + y1) / 2;
71*15dc779aSAndroid Build Coastguard Worker }
72*15dc779aSAndroid Build Coastguard Worker }
73*15dc779aSAndroid Build Coastguard Worker error = ixheaace_mps_212_dct_iv(real_subband, qmf_bands, ptr_scratch);
74*15dc779aSAndroid Build Coastguard Worker if (error != IA_NO_ERROR) {
75*15dc779aSAndroid Build Coastguard Worker return error;
76*15dc779aSAndroid Build Coastguard Worker }
77*15dc779aSAndroid Build Coastguard Worker error = ixheaace_mps_212_dst_iv(imag_subband, qmf_bands, ptr_scratch);
78*15dc779aSAndroid Build Coastguard Worker if (error != IA_NO_ERROR) {
79*15dc779aSAndroid Build Coastguard Worker return error;
80*15dc779aSAndroid Build Coastguard Worker }
81*15dc779aSAndroid Build Coastguard Worker
82*15dc779aSAndroid Build Coastguard Worker for (idx = 0; idx < MIN(pstr_qmf_filter_bank->lsb, qmf_bands); idx += 2) {
83*15dc779aSAndroid Build Coastguard Worker intermediate_band = real_subband[idx];
84*15dc779aSAndroid Build Coastguard Worker real_subband[idx] = -imag_subband[idx];
85*15dc779aSAndroid Build Coastguard Worker imag_subband[idx] = intermediate_band;
86*15dc779aSAndroid Build Coastguard Worker
87*15dc779aSAndroid Build Coastguard Worker intermediate_band = -real_subband[idx + 1];
88*15dc779aSAndroid Build Coastguard Worker real_subband[idx + 1] = imag_subband[idx + 1];
89*15dc779aSAndroid Build Coastguard Worker imag_subband[idx + 1] = intermediate_band;
90*15dc779aSAndroid Build Coastguard Worker }
91*15dc779aSAndroid Build Coastguard Worker return IA_NO_ERROR;
92*15dc779aSAndroid Build Coastguard Worker }
93*15dc779aSAndroid Build Coastguard Worker
ixheaace_mps_212_qmf_ana_prototype_fir_slot(FLOAT32 * ptr_analysis_buffer,WORD32 qmf_bands,const FLOAT32 * ptr_filter,WORD32 stride,FLOAT32 * ptr_filter_states)94*15dc779aSAndroid Build Coastguard Worker static VOID ixheaace_mps_212_qmf_ana_prototype_fir_slot(FLOAT32 *ptr_analysis_buffer,
95*15dc779aSAndroid Build Coastguard Worker WORD32 qmf_bands,
96*15dc779aSAndroid Build Coastguard Worker const FLOAT32 *ptr_filter, WORD32 stride,
97*15dc779aSAndroid Build Coastguard Worker FLOAT32 *ptr_filter_states) {
98*15dc779aSAndroid Build Coastguard Worker const FLOAT32 *p_flt = ptr_filter;
99*15dc779aSAndroid Build Coastguard Worker WORD32 poly, band;
100*15dc779aSAndroid Build Coastguard Worker FLOAT32 accumlate;
101*15dc779aSAndroid Build Coastguard Worker
102*15dc779aSAndroid Build Coastguard Worker for (band = 0; band < 2 * qmf_bands; band++) {
103*15dc779aSAndroid Build Coastguard Worker accumlate = 0;
104*15dc779aSAndroid Build Coastguard Worker p_flt += QMF_NO_POLY * (stride - 1);
105*15dc779aSAndroid Build Coastguard Worker for (poly = 0; poly < QMF_NO_POLY; poly++) {
106*15dc779aSAndroid Build Coastguard Worker accumlate += (((*p_flt++) * ptr_filter_states[2 * qmf_bands * poly]));
107*15dc779aSAndroid Build Coastguard Worker }
108*15dc779aSAndroid Build Coastguard Worker ptr_analysis_buffer[2 * qmf_bands - 1 - band] = accumlate;
109*15dc779aSAndroid Build Coastguard Worker ptr_filter_states++;
110*15dc779aSAndroid Build Coastguard Worker }
111*15dc779aSAndroid Build Coastguard Worker }
112*15dc779aSAndroid Build Coastguard Worker
ixheaace_mps_212_qmf_analysis_filtering_slot(ixheaace_mps_pstr_qmf_filter_bank pstr_qmf_filter_bank,FLOAT32 * real_subband,FLOAT32 * imag_subband,const FLOAT32 * time_in,const WORD32 stride,FLOAT32 * p_work_buffer,WORD8 * ptr_scratch)113*15dc779aSAndroid Build Coastguard Worker IA_ERRORCODE ixheaace_mps_212_qmf_analysis_filtering_slot(
114*15dc779aSAndroid Build Coastguard Worker ixheaace_mps_pstr_qmf_filter_bank pstr_qmf_filter_bank, FLOAT32 *real_subband,
115*15dc779aSAndroid Build Coastguard Worker FLOAT32 *imag_subband, const FLOAT32 *time_in, const WORD32 stride, FLOAT32 *p_work_buffer,
116*15dc779aSAndroid Build Coastguard Worker WORD8 *ptr_scratch) {
117*15dc779aSAndroid Build Coastguard Worker IA_ERRORCODE error = IA_NO_ERROR;
118*15dc779aSAndroid Build Coastguard Worker WORD32 idx;
119*15dc779aSAndroid Build Coastguard Worker WORD32 offset = pstr_qmf_filter_bank->no_channels * (QMF_NO_POLY * 2 - 1);
120*15dc779aSAndroid Build Coastguard Worker FLOAT32 *pstr_filter_states_ana_tmp =
121*15dc779aSAndroid Build Coastguard Worker ((FLOAT32 *)pstr_qmf_filter_bank->ptr_filter_states) + offset;
122*15dc779aSAndroid Build Coastguard Worker for (idx = 0; idx < pstr_qmf_filter_bank->no_channels; idx++) {
123*15dc779aSAndroid Build Coastguard Worker *pstr_filter_states_ana_tmp++ = (FLOAT32)*time_in;
124*15dc779aSAndroid Build Coastguard Worker time_in += stride;
125*15dc779aSAndroid Build Coastguard Worker }
126*15dc779aSAndroid Build Coastguard Worker ixheaace_mps_212_qmf_ana_prototype_fir_slot(
127*15dc779aSAndroid Build Coastguard Worker p_work_buffer, pstr_qmf_filter_bank->no_channels, pstr_qmf_filter_bank->pstr_filter,
128*15dc779aSAndroid Build Coastguard Worker pstr_qmf_filter_bank->p_stride, (FLOAT32 *)pstr_qmf_filter_bank->ptr_filter_states);
129*15dc779aSAndroid Build Coastguard Worker
130*15dc779aSAndroid Build Coastguard Worker error = ixheaace_mps_212_qmf_forward_modulation_hq(pstr_qmf_filter_bank, p_work_buffer,
131*15dc779aSAndroid Build Coastguard Worker real_subband, imag_subband, ptr_scratch);
132*15dc779aSAndroid Build Coastguard Worker if (error != IA_NO_ERROR) {
133*15dc779aSAndroid Build Coastguard Worker return error;
134*15dc779aSAndroid Build Coastguard Worker }
135*15dc779aSAndroid Build Coastguard Worker
136*15dc779aSAndroid Build Coastguard Worker memmove(pstr_qmf_filter_bank->ptr_filter_states,
137*15dc779aSAndroid Build Coastguard Worker (FLOAT32 *)pstr_qmf_filter_bank->ptr_filter_states + pstr_qmf_filter_bank->no_channels,
138*15dc779aSAndroid Build Coastguard Worker offset * sizeof(FLOAT32));
139*15dc779aSAndroid Build Coastguard Worker return error;
140*15dc779aSAndroid Build Coastguard Worker }
141*15dc779aSAndroid Build Coastguard Worker
142*15dc779aSAndroid Build Coastguard Worker IA_ERRORCODE
ixheaace_mps_212_qmf_init_filter_bank(ixheaace_mps_pstr_qmf_filter_bank pstr_qmf_filter_bank,VOID * ptr_filter_states,WORD32 num_cols,WORD32 lsb,WORD32 usb,WORD32 no_channels)143*15dc779aSAndroid Build Coastguard Worker ixheaace_mps_212_qmf_init_filter_bank(ixheaace_mps_pstr_qmf_filter_bank pstr_qmf_filter_bank,
144*15dc779aSAndroid Build Coastguard Worker VOID *ptr_filter_states, WORD32 num_cols, WORD32 lsb,
145*15dc779aSAndroid Build Coastguard Worker WORD32 usb, WORD32 no_channels) {
146*15dc779aSAndroid Build Coastguard Worker memset(pstr_qmf_filter_bank, 0, sizeof(ixheaace_mps_qmf_filter_bank));
147*15dc779aSAndroid Build Coastguard Worker pstr_qmf_filter_bank->no_channels = no_channels;
148*15dc779aSAndroid Build Coastguard Worker pstr_qmf_filter_bank->no_col = num_cols;
149*15dc779aSAndroid Build Coastguard Worker pstr_qmf_filter_bank->lsb = MIN(lsb, pstr_qmf_filter_bank->no_channels);
150*15dc779aSAndroid Build Coastguard Worker pstr_qmf_filter_bank->usb = MIN(usb, pstr_qmf_filter_bank->no_channels);
151*15dc779aSAndroid Build Coastguard Worker pstr_qmf_filter_bank->ptr_filter_states = (VOID *)ptr_filter_states;
152*15dc779aSAndroid Build Coastguard Worker memset(pstr_qmf_filter_bank->ptr_filter_states, 0,
153*15dc779aSAndroid Build Coastguard Worker (2 * QMF_NO_POLY - 1) * pstr_qmf_filter_bank->no_channels * sizeof(FLOAT32));
154*15dc779aSAndroid Build Coastguard Worker pstr_qmf_filter_bank->p_stride = 1;
155*15dc779aSAndroid Build Coastguard Worker if (no_channels == 64) {
156*15dc779aSAndroid Build Coastguard Worker pstr_qmf_filter_bank->pstr_filter = qmf_mps_ld_fb_640;
157*15dc779aSAndroid Build Coastguard Worker pstr_qmf_filter_bank->filter_size = 640;
158*15dc779aSAndroid Build Coastguard Worker } else {
159*15dc779aSAndroid Build Coastguard Worker pstr_qmf_filter_bank->pstr_filter = qmf_mps_ld_fb_320;
160*15dc779aSAndroid Build Coastguard Worker pstr_qmf_filter_bank->filter_size = 320;
161*15dc779aSAndroid Build Coastguard Worker }
162*15dc779aSAndroid Build Coastguard Worker
163*15dc779aSAndroid Build Coastguard Worker return IA_NO_ERROR;
164*15dc779aSAndroid Build Coastguard Worker }
165