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 <stdio.h>
21 #include <stdlib.h>
22 #include <math.h>
23 #include <string.h>
24 #include <ixheaacd_type_def.h>
25 #include "ixheaacd_sbr_const.h"
26
27 #include "ixheaacd_pvc_dec.h"
28 #include "ixheaacd_pvc_rom.h"
29
ixheaacd_pvc_sb_parsing(ia_pvc_data_struct * ptr_pvc_data,WORD16 first_bnd_idx,FLOAT32 * p_qmfh)30 static VOID ixheaacd_pvc_sb_parsing(ia_pvc_data_struct *ptr_pvc_data,
31 WORD16 first_bnd_idx, FLOAT32 *p_qmfh) {
32 WORD32 ksg, k;
33 WORD32 start_band, end_band;
34 WORD32 time_slot;
35
36 FLOAT32 *p_sbr_range_esg = &ptr_pvc_data->sbr_range_esg_arr[0];
37
38 for (time_slot = 0; time_slot < PVC_NUM_TIME_SLOTS; time_slot++) {
39 start_band = first_bnd_idx;
40 end_band = start_band + ptr_pvc_data->nb_high_per_grp - 1;
41
42 for (ksg = 0; ksg < ptr_pvc_data->nb_high; ksg++) {
43 for (k = start_band; k <= end_band; k++) {
44 p_qmfh[k] = (FLOAT32)pow(10.0f, (p_sbr_range_esg[ksg] / 10.0));
45 }
46 start_band += ptr_pvc_data->nb_high_per_grp;
47 if (ksg >= ptr_pvc_data->nb_high - 2) {
48 end_band = SBR_NUM_QMF_BANDS - 1;
49 } else {
50 end_band = start_band + ptr_pvc_data->nb_high_per_grp - 1;
51 if (end_band >= SBR_NUM_QMF_BANDS - 1) {
52 end_band = SBR_NUM_QMF_BANDS - 1;
53 }
54 }
55 }
56 p_sbr_range_esg = p_sbr_range_esg + 8;
57 p_qmfh = p_qmfh + SBR_NUM_QMF_BANDS;
58 }
59 return;
60 }
61
ixheaacd_pvc_qmf_grouping(ia_pvc_data_struct * ptr_pvc_data,WORD16 first_bnd_idx,FLOAT32 * p_qmf_ener,WORD32 first_pvc_timeslot)62 static VOID ixheaacd_pvc_qmf_grouping(ia_pvc_data_struct *ptr_pvc_data,
63 WORD16 first_bnd_idx, FLOAT32 *p_qmf_ener,
64 WORD32 first_pvc_timeslot) {
65 WORD32 ksg, time_slot, ib;
66 WORD32 lbw, start_band, end_band;
67 FLOAT32 esg;
68 FLOAT32 *p_esg = (FLOAT32 *)ptr_pvc_data->esg;
69
70 lbw = 8 / ptr_pvc_data->pvc_rate;
71
72 for (time_slot = 0; time_slot < PVC_NUM_TIME_SLOTS; time_slot++) {
73 for (ksg = 0; ksg < PVC_NB_LOW; ksg++) {
74 start_band = first_bnd_idx - lbw * PVC_NB_LOW + lbw * ksg;
75 end_band = start_band + lbw - 1;
76 if (start_band >= 0) {
77 esg = 0.0f;
78 for (ib = start_band; ib <= end_band; ib++) {
79 esg += p_qmf_ener[ib];
80 }
81 esg = esg / lbw;
82 } else {
83 esg = PVC_ESG_MIN_VAL;
84 }
85
86 if (esg > PVC_ESG_MIN_VAL) {
87 p_esg[(time_slot + 16 - 1) * 3 + ksg] = 10 * ((FLOAT32)log10(esg));
88 } else {
89 p_esg[(time_slot + 16 - 1) * 3 + ksg] = PVC_10LOG10_ESG_MIN_VAL;
90 }
91 }
92 p_qmf_ener = p_qmf_ener + SBR_NUM_QMF_BANDS_2;
93 }
94
95 if ((ptr_pvc_data->prev_pvc_flg == 0) ||
96 ((first_bnd_idx * ptr_pvc_data->pvc_rate) !=
97 (ptr_pvc_data->prev_first_bnd_idx * ptr_pvc_data->prev_pvc_rate))) {
98 for (time_slot = 0; time_slot < 16 - 1 + first_pvc_timeslot; time_slot++) {
99 for (ksg = 0; ksg < PVC_NB_LOW; ksg++) {
100 p_esg[time_slot * 3 + ksg] =
101 p_esg[(16 - 1 + first_pvc_timeslot) * 3 + ksg];
102 }
103 }
104 }
105
106 return;
107 }
108
ixheaacd_pvc_time_smoothing(ia_pvc_data_struct * ptr_pvc_data)109 static VOID ixheaacd_pvc_time_smoothing(ia_pvc_data_struct *ptr_pvc_data) {
110 WORD32 time_slot;
111 FLOAT32 *p_smooth_esg = (FLOAT32 *)&ptr_pvc_data->smooth_esg_arr[0];
112 for (time_slot = 0; time_slot < PVC_NUM_TIME_SLOTS; time_slot++) {
113 WORD32 ksg, time_slot_idx;
114 FLOAT32 *p_esg = (FLOAT32 *)&ptr_pvc_data->esg[time_slot + 16 - 1][2];
115 FLOAT32 *p_smth_wind_coeff = (FLOAT32 *)&ptr_pvc_data->p_smth_wind_coeff[0];
116 memset(p_smooth_esg, (WORD32)0.f, sizeof(FLOAT32) * PVC_NB_LOW);
117 for (time_slot_idx = 0; time_slot_idx < ptr_pvc_data->num_time_slots;
118 time_slot_idx++) {
119 ksg = PVC_NB_LOW - 1;
120 for (; ksg >= 0; ksg--) {
121 p_smooth_esg[ksg] += (*p_esg) * (*p_smth_wind_coeff);
122 p_esg--;
123 }
124 p_smth_wind_coeff++;
125 }
126 p_smooth_esg = p_smooth_esg + 3;
127 }
128 return;
129 }
130
ixheaacd_pvc_pred_env_sf(ia_pvc_data_struct * ptr_pvc_data)131 static VOID ixheaacd_pvc_pred_env_sf(ia_pvc_data_struct *ptr_pvc_data) {
132 WORD32 ksg, kb;
133 WORD32 tab_1_index, tab_2_index;
134 WORD32 time_slot;
135 WORD8 *pred_tab_1, *pred_tab_2;
136
137 FLOAT32 temp;
138 FLOAT32 *p_smooth_esg = &ptr_pvc_data->smooth_esg_arr[0];
139 FLOAT32 *p_sbr_range_esg = &ptr_pvc_data->sbr_range_esg_arr[0];
140
141 for (time_slot = 0; time_slot < PVC_NUM_TIME_SLOTS; time_slot++) {
142 tab_2_index = ptr_pvc_data->pvc_id[time_slot];
143
144 if (tab_2_index < ptr_pvc_data->p_pvc_id_boundary[0]) {
145 tab_1_index = 0;
146 } else if (tab_2_index < ptr_pvc_data->p_pvc_id_boundary[1]) {
147 tab_1_index = 1;
148 } else {
149 tab_1_index = 2;
150 }
151
152 pred_tab_1 =
153 (WORD8 *)(&(ptr_pvc_data->p_pred_coeff_tab_1[tab_1_index * PVC_NB_LOW *
154 ptr_pvc_data->nb_high]));
155 pred_tab_2 = (WORD8 *)(&(
156 ptr_pvc_data->p_pred_coeff_tab_2[tab_2_index * ptr_pvc_data->nb_high]));
157
158 for (ksg = 0; ksg < ptr_pvc_data->nb_high; ksg++) {
159 temp =
160 (FLOAT32)(WORD8)(*(pred_tab_2++)) * ptr_pvc_data->p_q_fac[PVC_NB_LOW];
161 p_sbr_range_esg[ksg] = temp;
162 }
163 for (kb = 0; kb < PVC_NB_LOW; kb++) {
164 for (ksg = 0; ksg < ptr_pvc_data->nb_high; ksg++) {
165 temp = (FLOAT32)(WORD8)(*(pred_tab_1++)) * ptr_pvc_data->p_q_fac[kb];
166 p_sbr_range_esg[ksg] += temp * p_smooth_esg[kb];
167 }
168 }
169 p_smooth_esg = p_smooth_esg + 3;
170 p_sbr_range_esg = p_sbr_range_esg + 8;
171 }
172
173 return;
174 }
175
ixheaacd_pvc_process(ia_pvc_data_struct * ptr_pvc_data,WORD16 first_bnd_idx,WORD32 first_pvc_timeslot,FLOAT32 * p_qmf_ener,FLOAT32 * p_qmfh)176 WORD32 ixheaacd_pvc_process(ia_pvc_data_struct *ptr_pvc_data,
177 WORD16 first_bnd_idx, WORD32 first_pvc_timeslot,
178 FLOAT32 *p_qmf_ener, FLOAT32 *p_qmfh) {
179 switch (ptr_pvc_data->pvc_mode) {
180 case 1:
181 ptr_pvc_data->nb_high = PVC_NB_HIGH_MODE1;
182 ptr_pvc_data->nb_high_per_grp = 8 / ptr_pvc_data->pvc_rate;
183 ptr_pvc_data->p_pred_coeff_tab_1 =
184 (WORD8 *)ixheaacd_pred_coeff_table_1_mode_1;
185 ptr_pvc_data->p_pred_coeff_tab_2 =
186 (WORD8 *)ixheaacd_pred_coeff_table_2_mode_1;
187 ptr_pvc_data->p_pvc_id_boundary =
188 (UWORD8 *)ixheaacd_pred_coeff_pvc_id_boundaries_1;
189 ptr_pvc_data->p_q_fac = (FLOAT32 *)ixheaacd_q_factor_table_mode_1;
190 if (ptr_pvc_data->ns_mode) {
191 ptr_pvc_data->num_time_slots = 4;
192 ptr_pvc_data->p_smth_wind_coeff =
193 (FLOAT32 *)ixheaacd_pvc_smoothing_wind_tab_ns4;
194 } else {
195 ptr_pvc_data->num_time_slots = 16;
196 ptr_pvc_data->p_smth_wind_coeff =
197 (FLOAT32 *)ixheaacd_pvc_smoothing_wind_tab_ns16;
198 }
199 break;
200 case 2:
201 ptr_pvc_data->nb_high = PVC_NB_HIGH_MODE2;
202 ptr_pvc_data->nb_high_per_grp = 12 / ptr_pvc_data->pvc_rate;
203 ptr_pvc_data->p_pred_coeff_tab_1 =
204 (WORD8 *)ixheaacd_pred_coeff_table_1_mode_2;
205 ptr_pvc_data->p_pred_coeff_tab_2 =
206 (WORD8 *)ixheaacd_pred_coeff_table_2_mode_2;
207 ptr_pvc_data->p_pvc_id_boundary =
208 (UWORD8 *)ixheaacd_pred_coeff_pvc_id_boundaries_2;
209 ptr_pvc_data->p_q_fac = (FLOAT32 *)ixheaacd_q_factor_table_mode_2;
210 if (ptr_pvc_data->ns_mode) {
211 ptr_pvc_data->num_time_slots = 3;
212 ptr_pvc_data->p_smth_wind_coeff =
213 (FLOAT32 *)ixheaacd_pvc_smoothing_wind_tab_ns3;
214 } else {
215 ptr_pvc_data->num_time_slots = 12;
216 ptr_pvc_data->p_smth_wind_coeff =
217 (FLOAT32 *)ixheaacd_pvc_smoothing_wind_tab_ns12;
218 }
219 break;
220 default:
221 return -1;
222 }
223 ptr_pvc_data->prev_pvc_id = ptr_pvc_data->pvc_id[PVC_NUM_TIME_SLOTS - 1];
224
225 ixheaacd_pvc_qmf_grouping(ptr_pvc_data, first_bnd_idx, p_qmf_ener,
226 first_pvc_timeslot);
227
228 ixheaacd_pvc_time_smoothing(ptr_pvc_data);
229
230 ixheaacd_pvc_pred_env_sf(ptr_pvc_data);
231
232 ixheaacd_pvc_sb_parsing(ptr_pvc_data, first_bnd_idx, p_qmfh);
233
234 memcpy((FLOAT32 *)(&ptr_pvc_data->esg[0][0]),
235 (FLOAT32 *)(&ptr_pvc_data->esg[PVC_NUM_TIME_SLOTS][0]),
236 sizeof(FLOAT32) * (PVC_NUM_TIME_SLOTS - 1) * 3);
237
238 return 0;
239 }
240