xref: /aosp_15_r20/external/libxaac/encoder/ixheaace_resampler.c (revision 15dc779a375ca8b5125643b829a8aa4b70d7f451)
1 /******************************************************************************
2  *                                                                            *
3  * Copyright (C) 2023 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 
21 #include <string.h>
22 #include "ixheaac_type_def.h"
23 #include "ixheaac_constants.h"
24 #include "ixheaace_sbr_def.h"
25 #include "ixheaace_resampler.h"
26 #include "iusace_cnst.h"
27 
ia_enhaacplus_enc_downsample_iir_filter(ixheaace_iir21_resampler * pstr_down_sampler,FLOAT32 * ptr_in_samples,FLOAT32 * ptr_out_samples,WORD32 in_stride,WORD32 num_in_samples,WORD32 * num_out_samples,WORD32 out_stride,FLOAT32 * ptr_ring_buf1,FLOAT32 * ptr_ring_buf2)28 static VOID ia_enhaacplus_enc_downsample_iir_filter(
29     ixheaace_iir21_resampler *pstr_down_sampler, FLOAT32 *ptr_in_samples,
30     FLOAT32 *ptr_out_samples, WORD32 in_stride, WORD32 num_in_samples, WORD32 *num_out_samples,
31     WORD32 out_stride, FLOAT32 *ptr_ring_buf1, FLOAT32 *ptr_ring_buf2) {
32   WORD32 i;
33   ixheaace_iir_filter *pstr_iir_filter = &(pstr_down_sampler->iir_filter);
34   FLOAT32 *ptr_iir_ring1, *ptr_iir_ring2;
35   FLOAT32 coeff_temp_a, coeff_temp_b;
36   const FLOAT32 *ptr_coeff_filt = (FLOAT32 *)pstr_iir_filter->ptr_coeff_iir_num;
37   FLOAT32 iir_out = 0;
38   FLOAT32 temp1 = 0.f, temp2 = 0.f;
39 
40   *num_out_samples = 0;
41   ptr_iir_ring1 = ptr_ring_buf1;
42   ptr_iir_ring2 = ptr_ring_buf2;
43 
44   for (i = 0; i < num_in_samples; i++) {
45     temp1 = ptr_in_samples[i * in_stride] / 2;
46     ptr_iir_ring1[i] = temp1;
47     coeff_temp_b = *ptr_coeff_filt;
48     temp1 = coeff_temp_b * (temp1 + ptr_iir_ring1[i - 10]);
49     coeff_temp_a = *(ptr_coeff_filt + 16);
50     iir_out = (ptr_iir_ring2[i - 10] * coeff_temp_a);
51 
52     coeff_temp_b = *(ptr_coeff_filt + 1);
53     temp1 = (coeff_temp_b * (ptr_iir_ring1[i - 1] + ptr_iir_ring1[i - 9])) + temp1;
54     coeff_temp_a = *(ptr_coeff_filt + 7);
55     temp2 = (ptr_iir_ring2[i - 1] * coeff_temp_a) + iir_out;
56     coeff_temp_a = *(ptr_coeff_filt + 15);
57     iir_out = (ptr_iir_ring2[i - 9] * coeff_temp_a) + temp2;
58 
59     coeff_temp_b = *(ptr_coeff_filt + 2);
60     temp1 = (coeff_temp_b * (ptr_iir_ring1[i - 2] + ptr_iir_ring1[i - 8])) + temp1;
61     coeff_temp_a = *(ptr_coeff_filt + 8);
62     temp2 = (ptr_iir_ring2[i - 2] * coeff_temp_a) + iir_out;
63     coeff_temp_a = *(ptr_coeff_filt + 14);
64     iir_out = (ptr_iir_ring2[i - 8] * coeff_temp_a) + temp2;
65 
66     coeff_temp_b = *(ptr_coeff_filt + 3);
67     temp1 = (coeff_temp_b * (ptr_iir_ring1[i - 3] + ptr_iir_ring1[i - 7])) + temp1;
68     coeff_temp_a = *(ptr_coeff_filt + 9);
69     temp2 = (ptr_iir_ring2[i - 3] * coeff_temp_a) + iir_out;
70     coeff_temp_a = *(ptr_coeff_filt + 13);
71     iir_out = (ptr_iir_ring2[i - 7] * coeff_temp_a) + temp2;
72 
73     coeff_temp_b = *(ptr_coeff_filt + 4);
74     temp1 = (coeff_temp_b * (ptr_iir_ring1[i - 4] + ptr_iir_ring1[i - 6])) + temp1;
75     coeff_temp_a = *(ptr_coeff_filt + 10);
76     temp2 = (ptr_iir_ring2[i - 4] * coeff_temp_a) + iir_out;
77     coeff_temp_a = *(ptr_coeff_filt + 12);
78     iir_out = (ptr_iir_ring2[i - 6] * coeff_temp_a) + temp2;
79 
80     coeff_temp_b = *(ptr_coeff_filt + 5);
81     temp1 = (coeff_temp_b * ptr_iir_ring1[i - 5]) + temp1;
82     coeff_temp_a = *(ptr_coeff_filt + 11);
83     iir_out = (ptr_iir_ring2[i - 5] * coeff_temp_a) + iir_out;
84     iir_out = temp1 - iir_out;
85 
86     ptr_iir_ring2[i] = iir_out;
87     iir_out = (iir_out * (4681.0f / 32767.0f) * pstr_iir_filter->max);
88 
89     pstr_down_sampler->pending++;
90 
91     if (pstr_down_sampler->pending == pstr_down_sampler->ratio) {
92       ptr_out_samples[(*num_out_samples) * out_stride] = iir_out;
93       (*num_out_samples)++;
94 
95       pstr_down_sampler->pending = 0;
96     }
97   }
98 }
99 
ia_enhaacplus_enc_copy_ring_buffers(FLOAT32 * ptr_iir_ring1,FLOAT32 * ptr_iir_ring2,FLOAT32 * ptr_ring_buf1,FLOAT32 * ptr_ring_buf2)100 static VOID ia_enhaacplus_enc_copy_ring_buffers(FLOAT32 *ptr_iir_ring1, FLOAT32 *ptr_iir_ring2,
101                                                 FLOAT32 *ptr_ring_buf1, FLOAT32 *ptr_ring_buf2) {
102   WORD32 i;
103   FLOAT32 temp1, temp2, temp3;
104   for (i = (LEN_RING_BUF / 2) - 1; i >= 0; i--) {
105     temp1 = *ptr_iir_ring1++;
106     temp2 = *ptr_iir_ring2++;
107     temp3 = *ptr_iir_ring1++;
108 
109     *ptr_ring_buf1++ = temp1;
110     temp1 = *ptr_iir_ring2++;
111     *ptr_ring_buf2++ = temp2;
112     *ptr_ring_buf1++ = temp3;
113     *ptr_ring_buf2++ = temp1;
114   }
115 }
116 
ia_enhaacplus_enc_copy_ring_buffers_sos(FLOAT32 * ptr_iir_ring1,FLOAT32 * ptr_iir_ring2,FLOAT32 * ptr_ring_buf1,FLOAT32 * ptr_ring_buf2,WORD32 len1,WORD32 len2)117 static VOID ia_enhaacplus_enc_copy_ring_buffers_sos(FLOAT32 *ptr_iir_ring1,
118                                                     FLOAT32 *ptr_iir_ring2,
119                                                     FLOAT32 *ptr_ring_buf1,
120                                                     FLOAT32 *ptr_ring_buf2, WORD32 len1,
121                                                     WORD32 len2) {
122   memcpy(ptr_ring_buf1, ptr_iir_ring1, len1 * sizeof(*ptr_ring_buf1));
123   memcpy(ptr_ring_buf2, ptr_iir_ring2, len2 * sizeof(*ptr_ring_buf2));
124 }
125 
ia_enhaacplus_enc_update_ring_buffer_sos(FLOAT32 * ptr_ring_buf,FLOAT32 * ptr_samples,WORD32 len,WORD32 in_stride,WORD32 coeff_idx)126 static VOID ia_enhaacplus_enc_update_ring_buffer_sos(FLOAT32 *ptr_ring_buf, FLOAT32 *ptr_samples,
127                                                      WORD32 len, WORD32 in_stride,
128                                                      WORD32 coeff_idx) {
129   ptr_ring_buf[2 * coeff_idx] = ptr_samples[len - 2 * in_stride];
130   ptr_ring_buf[2 * coeff_idx + 1] = ptr_samples[len - in_stride];
131 }
132 
ixheaace_get_input_scratch_buf(VOID * ptr_scr,FLOAT32 ** ptr_scratch_buf_inp)133 VOID ixheaace_get_input_scratch_buf(VOID *ptr_scr, FLOAT32 **ptr_scratch_buf_inp) {
134   ixheaace_resampler_scratch *pstr_resampler_scr = (ixheaace_resampler_scratch *)ptr_scr;
135 
136   *ptr_scratch_buf_inp = pstr_resampler_scr->downsampler_in_buffer;
137 }
138 
ixheaace_resampler_scr_size(VOID)139 WORD32 ixheaace_resampler_scr_size(VOID) {
140   return IXHEAAC_GET_SIZE_ALIGNED(sizeof(ixheaace_resampler_scratch), BYTE_ALIGN_8);
141 }
142 
ia_enhaacplus_enc_iir_sos_filter(ixheaace_iir_sos_resampler * pstr_down_sampler,FLOAT32 * ptr_in_samples,WORD32 in_stride,FLOAT32 * ptr_out_samples,WORD32 num_in_samples,FLOAT32 * ptr_ring_buf1,FLOAT32 * ptr_ring_buf2,WORD32 coeff_idx)143 static VOID ia_enhaacplus_enc_iir_sos_filter(ixheaace_iir_sos_resampler *pstr_down_sampler,
144                                              FLOAT32 *ptr_in_samples, WORD32 in_stride,
145                                              FLOAT32 *ptr_out_samples, WORD32 num_in_samples,
146                                              FLOAT32 *ptr_ring_buf1, FLOAT32 *ptr_ring_buf2,
147                                              WORD32 coeff_idx) {
148   WORD32 i;
149   ixheaace_iir_sos_filter *pstr_iir_filter = &(pstr_down_sampler->iir_filter);
150   const FLOAT32 *ptr_coeff_den =
151       (pstr_iir_filter->ptr_coeff_iir_den + (coeff_idx * IIR_SOS_COEFFS));
152   const FLOAT32 *ptr_coeff_num =
153       (pstr_iir_filter->ptr_coeff_iir_num + (coeff_idx * IIR_SOS_COEFFS));
154   FLOAT32 iir_out = 0.f;
155   FLOAT32 temp1 = 0.f, temp2 = 0.f;
156 
157   for (i = 0; i < num_in_samples; i++) {
158     ptr_ring_buf1[2] = ptr_in_samples[i * in_stride];
159 
160     temp1 = ptr_coeff_num[0] * ptr_in_samples[i * in_stride] +
161             ptr_coeff_num[1] * ptr_ring_buf1[1] + ptr_coeff_num[2] * ptr_ring_buf1[0];
162     temp2 = ptr_coeff_den[1] * ptr_ring_buf2[1] + ptr_coeff_den[2] * ptr_ring_buf2[0];
163 
164     iir_out = temp1 - temp2;
165     ptr_ring_buf2[2] = iir_out;
166 
167     ptr_out_samples[i * in_stride] = iir_out;
168 
169     // Shift ring buffers
170     ptr_ring_buf1[0] = ptr_ring_buf1[1];
171     ptr_ring_buf1[1] = ptr_ring_buf1[2];
172 
173     ptr_ring_buf2[0] = ptr_ring_buf2[1];
174     ptr_ring_buf2[1] = ptr_ring_buf2[2];
175   }
176 }
177 
ia_enhaacplus_enc_iir_downsampler(ixheaace_iir21_resampler * pstr_down_sampler,FLOAT32 * ptr_in_samples,WORD32 num_in_samples,WORD32 in_stride,FLOAT32 * ptr_out_samples,WORD32 * num_out_samples,WORD32 out_stride,FLOAT32 * ptr_ring_buf1,FLOAT32 * ptr_ring_buf2,ixheaace_resampler_scratch * pstr_resampler_scratch)178 VOID ia_enhaacplus_enc_iir_downsampler(ixheaace_iir21_resampler *pstr_down_sampler,
179                                        FLOAT32 *ptr_in_samples, WORD32 num_in_samples,
180                                        WORD32 in_stride, FLOAT32 *ptr_out_samples,
181                                        WORD32 *num_out_samples, WORD32 out_stride,
182                                        FLOAT32 *ptr_ring_buf1, FLOAT32 *ptr_ring_buf2,
183                                        ixheaace_resampler_scratch *pstr_resampler_scratch) {
184   ixheaace_iir_filter *pstr_iir_filter = &(pstr_down_sampler->iir_filter);
185   WORD32 k;
186   FLOAT32 *ptr_iir_ring1, *ptr_iir_ring2, *ptr_out_temp;
187 
188   ptr_iir_ring2 = pstr_iir_filter->ring_buf_2;
189   ptr_iir_ring1 = pstr_iir_filter->ring_buf_1;
190   ptr_out_temp = pstr_resampler_scratch->downsampler_out_buffer;
191 
192   ia_enhaacplus_enc_copy_ring_buffers(ptr_iir_ring1, ptr_iir_ring2, ptr_ring_buf1, ptr_ring_buf2);
193 
194   ia_enhaacplus_enc_downsample_iir_filter(
195       pstr_down_sampler, ptr_in_samples, ptr_out_temp, in_stride, num_in_samples, num_out_samples,
196       out_stride, &ptr_ring_buf1[LEN_RING_BUF - 1], &ptr_ring_buf2[LEN_RING_BUF - 1]);
197 
198   for (k = 0; k < *num_out_samples; k++) {
199     ptr_out_samples[k * in_stride] = ptr_out_temp[k * out_stride];
200   }
201 
202   ia_enhaacplus_enc_copy_ring_buffers(&ptr_ring_buf1[num_in_samples],
203                                       &ptr_ring_buf2[num_in_samples], ptr_iir_ring1,
204                                       ptr_iir_ring2);
205 }
206 
ia_enhaacplus_enc_iir_sos_downsampler(ixheaace_iir_sos_resampler * pstr_down_sampler,FLOAT32 * ptr_in_samples,WORD32 num_in_samples,WORD32 in_stride,FLOAT32 * ptr_out_samples,WORD32 * num_out_samples,FLOAT32 * ptr_ring_buf1,FLOAT32 * ptr_ring_buf2,ixheaace_resampler_scratch * pstr_resampler_scratch)207 VOID ia_enhaacplus_enc_iir_sos_downsampler(ixheaace_iir_sos_resampler *pstr_down_sampler,
208                                            FLOAT32 *ptr_in_samples, WORD32 num_in_samples,
209                                            WORD32 in_stride, FLOAT32 *ptr_out_samples,
210                                            WORD32 *num_out_samples, FLOAT32 *ptr_ring_buf1,
211                                            FLOAT32 *ptr_ring_buf2,
212                                            ixheaace_resampler_scratch *pstr_resampler_scratch) {
213   ixheaace_iir_sos_filter *pstr_iir_filter = &(pstr_down_sampler->iir_filter);
214   FLOAT32 *ptr_iir_ring1, *ptr_iir_ring2;
215   FLOAT32 *ptr_out_stage1, *ptr_out_stage2, *ptr_out_stage3, *ptr_out_stage4, *ptr_out_stage5,
216       *ptr_out_final;
217   WORD32 p = 0, idx = 0, offset1 = 0, offset2 = 0;
218   FLOAT32 *ptr_temp_buf1, *ptr_temp_buf2, *ptr_temp_ring_buf;
219   WORD32 upper_lim = num_in_samples * in_stride;
220 
221   ptr_iir_ring1 = pstr_iir_filter->ring_buf_sos_1;
222   ptr_iir_ring2 = pstr_iir_filter->ring_buf_sos_2;
223 
224   ia_enhaacplus_enc_copy_ring_buffers_sos(ptr_iir_ring1, ptr_iir_ring2, ptr_ring_buf1,
225                                           ptr_ring_buf2, LEN_RING_BUF_SOS_1, LEN_RING_BUF_SOS_2);
226 
227   ptr_temp_buf1 = pstr_resampler_scratch->scratch_buf1_temp;
228   ptr_temp_buf2 = pstr_resampler_scratch->scratch_buf2_temp;
229   ptr_temp_ring_buf = pstr_resampler_scratch->ring_buf_temp;
230 
231   ia_enhaacplus_enc_copy_ring_buffers_sos(ptr_ring_buf1, ptr_ring_buf2, ptr_temp_buf1,
232                                           ptr_temp_buf2, LEN_RING_BUF_SOS_1, LEN_RING_BUF_SOS_1);
233 
234   ptr_out_stage1 = pstr_resampler_scratch->downsampler_out_buffer;
235 
236   ia_enhaacplus_enc_update_ring_buffer_sos(ptr_temp_ring_buf, ptr_in_samples, upper_lim,
237                                            in_stride, idx);
238 
239   // Stage 1
240   ia_enhaacplus_enc_iir_sos_filter(pstr_down_sampler, ptr_in_samples, in_stride, ptr_out_stage1,
241                                    num_in_samples, ptr_temp_buf1, ptr_temp_buf2, idx);
242 
243   offset1 = LEN_RING_BUF_SOS_1 * idx;
244   offset2 = LEN_RING_BUF_SOS_1 * (idx + 1);
245 
246   ia_enhaacplus_enc_copy_ring_buffers_sos(ptr_ring_buf2 + offset1, ptr_ring_buf2 + offset2,
247                                           ptr_temp_buf1, ptr_temp_buf2, LEN_RING_BUF_SOS_1,
248                                           LEN_RING_BUF_SOS_1);
249 
250   idx++;
251 
252   ia_enhaacplus_enc_update_ring_buffer_sos(ptr_temp_ring_buf, ptr_out_stage1, upper_lim,
253                                            in_stride, idx);
254 
255   ptr_out_stage2 = pstr_resampler_scratch->downsampler_in_buffer;
256 
257   // Stage 2
258   ia_enhaacplus_enc_iir_sos_filter(pstr_down_sampler, ptr_out_stage1, in_stride, ptr_out_stage2,
259                                    num_in_samples, ptr_temp_buf1, ptr_temp_buf2, idx);
260 
261   offset1 = LEN_RING_BUF_SOS_1 * idx;
262   offset2 = LEN_RING_BUF_SOS_1 * (idx + 1);
263 
264   ia_enhaacplus_enc_copy_ring_buffers_sos(ptr_ring_buf2 + offset1, ptr_ring_buf2 + offset2,
265                                           ptr_temp_buf1, ptr_temp_buf2, LEN_RING_BUF_SOS_1,
266                                           LEN_RING_BUF_SOS_1);
267 
268   idx++;
269 
270   ia_enhaacplus_enc_update_ring_buffer_sos(ptr_temp_ring_buf, ptr_out_stage2, upper_lim,
271                                            in_stride, idx);
272 
273   ptr_out_stage3 = pstr_resampler_scratch->downsampler_out_buffer;
274 
275   // Stage 3
276   ia_enhaacplus_enc_iir_sos_filter(pstr_down_sampler, ptr_out_stage2, in_stride, ptr_out_stage3,
277                                    num_in_samples, ptr_temp_buf1, ptr_temp_buf2, idx);
278 
279   offset1 = LEN_RING_BUF_SOS_1 * idx;
280   offset2 = LEN_RING_BUF_SOS_1 * (idx + 1);
281 
282   ia_enhaacplus_enc_copy_ring_buffers_sos(ptr_ring_buf2 + offset1, ptr_ring_buf2 + offset2,
283                                           ptr_temp_buf1, ptr_temp_buf2, LEN_RING_BUF_SOS_1,
284                                           LEN_RING_BUF_SOS_1);
285 
286   idx++;
287 
288   ia_enhaacplus_enc_update_ring_buffer_sos(ptr_temp_ring_buf, ptr_out_stage3, upper_lim,
289                                            in_stride, idx);
290 
291   ptr_out_stage4 = pstr_resampler_scratch->downsampler_in_buffer;
292 
293   // Stage 4
294   ia_enhaacplus_enc_iir_sos_filter(pstr_down_sampler, ptr_out_stage3, in_stride, ptr_out_stage4,
295                                    num_in_samples, ptr_temp_buf1, ptr_temp_buf2, idx);
296 
297   offset1 = LEN_RING_BUF_SOS_1 * idx;
298   offset2 = LEN_RING_BUF_SOS_1 * (idx + 1);
299 
300   ia_enhaacplus_enc_copy_ring_buffers_sos(ptr_ring_buf2 + offset1, ptr_ring_buf2 + offset2,
301                                           ptr_temp_buf1, ptr_temp_buf2, LEN_RING_BUF_SOS_1,
302                                           LEN_RING_BUF_SOS_1);
303 
304   idx++;
305 
306   ia_enhaacplus_enc_update_ring_buffer_sos(ptr_temp_ring_buf, ptr_out_stage4, upper_lim,
307                                            in_stride, idx);
308 
309   ptr_out_stage5 = pstr_resampler_scratch->downsampler_out_buffer;
310 
311   // Stage 5
312 
313   ia_enhaacplus_enc_iir_sos_filter(pstr_down_sampler, ptr_out_stage4, in_stride, ptr_out_stage5,
314                                    num_in_samples, ptr_temp_buf1, ptr_temp_buf2, idx);
315 
316   idx++;
317 
318   ia_enhaacplus_enc_update_ring_buffer_sos(ptr_temp_ring_buf, ptr_out_stage5, upper_lim,
319                                            in_stride, idx);
320 
321   ptr_out_final = pstr_resampler_scratch->downsampler_in_buffer;
322 
323   // Multiply by gain and perform downsamplng
324   *num_out_samples = 0;
325   for (p = 0; p < num_in_samples * in_stride; p += in_stride) {
326     ptr_out_final[p] = ptr_out_stage5[p] * pstr_down_sampler->iir_filter.gain_sos;
327 
328     pstr_down_sampler->pending++;
329 
330     if (pstr_down_sampler->pending == pstr_down_sampler->ratio) {
331       ptr_out_samples[(*num_out_samples) * in_stride] = ptr_out_final[p];
332 
333       (*num_out_samples)++;
334 
335       pstr_down_sampler->pending = 0;
336     }
337   }
338 
339   // Update ring buffers
340   ia_enhaacplus_enc_copy_ring_buffers_sos(ptr_temp_ring_buf,
341                                           ptr_temp_ring_buf + LEN_RING_BUF_SOS_1, ptr_ring_buf1,
342                                           ptr_ring_buf2, LEN_RING_BUF_SOS_1, LEN_RING_BUF_SOS_2);
343 
344   ia_enhaacplus_enc_copy_ring_buffers_sos(ptr_ring_buf1, ptr_ring_buf2, ptr_iir_ring1,
345                                           ptr_iir_ring2, LEN_RING_BUF_SOS_1, LEN_RING_BUF_SOS_2);
346 }
347 
ia_enhaacplus_enc_iir_sos_upsampler(ixheaace_iir_sos_resampler * pstr_up_sampler,FLOAT32 * ptr_in_samples,WORD32 num_in_samples,WORD32 in_stride,FLOAT32 * ptr_out_samples,WORD32 * num_out_samples,FLOAT32 * ptr_ring_buf1,FLOAT32 * ptr_ring_buf2,ixheaace_resampler_scratch * pstr_resampler_scratch)348 VOID ia_enhaacplus_enc_iir_sos_upsampler(ixheaace_iir_sos_resampler *pstr_up_sampler,
349                                          FLOAT32 *ptr_in_samples, WORD32 num_in_samples,
350                                          WORD32 in_stride, FLOAT32 *ptr_out_samples,
351                                          WORD32 *num_out_samples, FLOAT32 *ptr_ring_buf1,
352                                          FLOAT32 *ptr_ring_buf2,
353                                          ixheaace_resampler_scratch *pstr_resampler_scratch) {
354   ixheaace_iir_sos_filter *pstr_iir_filter = &(pstr_up_sampler->iir_filter);
355   FLOAT32 *ptr_iir_ring1, *ptr_iir_ring2;
356   FLOAT32 *ptr_out_stage1, *ptr_out_stage2, *ptr_out_stage3, *ptr_out_stage4, *ptr_out_stage5;
357   FLOAT32 out_val;
358   FLOAT32 *ptr_temp_buf1, *ptr_temp_buf2, *ptr_temp_ring_buf;
359   WORD32 p = 0, idx = 0, offset1 = 0, offset2 = 0;
360   WORD32 upsample_fac = pstr_up_sampler->ratio;
361   WORD32 upper_lim = num_in_samples * in_stride * upsample_fac;
362 
363   ptr_iir_ring2 = pstr_iir_filter->ring_buf_sos_2;
364   ptr_iir_ring1 = pstr_iir_filter->ring_buf_sos_1;
365 
366   ia_enhaacplus_enc_copy_ring_buffers_sos(ptr_iir_ring1, ptr_iir_ring2, ptr_ring_buf1,
367                                           ptr_ring_buf2, LEN_RING_BUF_SOS_1, LEN_RING_BUF_SOS_2);
368 
369   ptr_temp_buf1 = pstr_resampler_scratch->scratch_buf1_temp;
370   ptr_temp_buf2 = pstr_resampler_scratch->scratch_buf2_temp;
371   ptr_temp_ring_buf = pstr_resampler_scratch->ring_buf_temp;
372 
373   ia_enhaacplus_enc_copy_ring_buffers_sos(ptr_ring_buf1, ptr_ring_buf2, ptr_temp_buf1,
374                                           ptr_temp_buf2, LEN_RING_BUF_SOS_1, LEN_RING_BUF_SOS_1);
375 
376   ptr_out_stage1 = pstr_resampler_scratch->downsampler_out_buffer;
377 
378   ia_enhaacplus_enc_update_ring_buffer_sos(ptr_temp_ring_buf, ptr_in_samples, upper_lim,
379                                            in_stride, idx);
380 
381   // Stage 1
382   ia_enhaacplus_enc_iir_sos_filter(pstr_up_sampler, ptr_in_samples, in_stride, ptr_out_stage1,
383                                    num_in_samples * upsample_fac, ptr_temp_buf1, ptr_temp_buf2,
384                                    idx);
385 
386   offset1 = LEN_RING_BUF_SOS_1 * idx;
387   offset2 = LEN_RING_BUF_SOS_1 * (idx + 1);
388 
389   ia_enhaacplus_enc_copy_ring_buffers_sos(ptr_ring_buf2 + offset1, ptr_ring_buf2 + offset2,
390                                           ptr_temp_buf1, ptr_temp_buf2, LEN_RING_BUF_SOS_1,
391                                           LEN_RING_BUF_SOS_1);
392 
393   idx++;
394 
395   ia_enhaacplus_enc_update_ring_buffer_sos(ptr_temp_ring_buf, ptr_out_stage1, upper_lim,
396                                            in_stride, idx);
397 
398   ptr_out_stage2 = pstr_resampler_scratch->downsampler_in_buffer;
399 
400   // Stage 2
401   ia_enhaacplus_enc_iir_sos_filter(pstr_up_sampler, ptr_out_stage1, in_stride, ptr_out_stage2,
402                                    num_in_samples * upsample_fac, ptr_temp_buf1, ptr_temp_buf2,
403                                    idx);
404 
405   offset1 = LEN_RING_BUF_SOS_1 * idx;
406   offset2 = LEN_RING_BUF_SOS_1 * (idx + 1);
407 
408   ia_enhaacplus_enc_copy_ring_buffers_sos(ptr_ring_buf2 + offset1, ptr_ring_buf2 + offset2,
409                                           ptr_temp_buf1, ptr_temp_buf2, LEN_RING_BUF_SOS_1,
410                                           LEN_RING_BUF_SOS_1);
411 
412   idx++;
413 
414   ia_enhaacplus_enc_update_ring_buffer_sos(ptr_temp_ring_buf, ptr_out_stage2, upper_lim,
415                                            in_stride, idx);
416 
417   ptr_out_stage3 = pstr_resampler_scratch->downsampler_out_buffer;
418 
419   // Stage 3
420   ia_enhaacplus_enc_iir_sos_filter(pstr_up_sampler, ptr_out_stage2, in_stride, ptr_out_stage3,
421                                    num_in_samples * upsample_fac, ptr_temp_buf1, ptr_temp_buf2,
422                                    idx);
423 
424   offset1 = LEN_RING_BUF_SOS_1 * idx;
425   offset2 = LEN_RING_BUF_SOS_1 * (idx + 1);
426 
427   ia_enhaacplus_enc_copy_ring_buffers_sos(ptr_ring_buf2 + offset1, ptr_ring_buf2 + offset2,
428                                           ptr_temp_buf1, ptr_temp_buf2, LEN_RING_BUF_SOS_1,
429                                           LEN_RING_BUF_SOS_1);
430 
431   idx++;
432 
433   ia_enhaacplus_enc_update_ring_buffer_sos(ptr_temp_ring_buf, ptr_out_stage3, upper_lim,
434                                            in_stride, idx);
435 
436   ptr_out_stage4 = pstr_resampler_scratch->downsampler_in_buffer;
437 
438   // Stage 4
439   ia_enhaacplus_enc_iir_sos_filter(pstr_up_sampler, ptr_out_stage3, in_stride, ptr_out_stage4,
440                                    num_in_samples * upsample_fac, ptr_temp_buf1, ptr_temp_buf2,
441                                    idx);
442 
443   offset1 = LEN_RING_BUF_SOS_1 * idx;
444   offset2 = LEN_RING_BUF_SOS_1 * (idx + 1);
445 
446   ia_enhaacplus_enc_copy_ring_buffers_sos(ptr_ring_buf2 + offset1, ptr_ring_buf2 + offset2,
447                                           ptr_temp_buf1, ptr_temp_buf2, LEN_RING_BUF_SOS_1,
448                                           LEN_RING_BUF_SOS_1);
449 
450   idx++;
451 
452   ia_enhaacplus_enc_update_ring_buffer_sos(ptr_temp_ring_buf, ptr_out_stage4, upper_lim,
453                                            in_stride, idx);
454 
455   ptr_out_stage5 = pstr_resampler_scratch->downsampler_out_buffer;
456 
457   // Stage 5
458   ia_enhaacplus_enc_iir_sos_filter(pstr_up_sampler, ptr_out_stage4, in_stride, ptr_out_stage5,
459                                    num_in_samples * upsample_fac, ptr_temp_buf1, ptr_temp_buf2,
460                                    idx);
461 
462   idx++;
463 
464   ia_enhaacplus_enc_update_ring_buffer_sos(ptr_temp_ring_buf, ptr_out_stage5, upper_lim,
465                                            in_stride, idx);
466 
467   // Multiply by gain and perform downsamplng
468   *num_out_samples = 0;
469   for (p = 0; p < num_in_samples * in_stride * upsample_fac; p += in_stride) {
470     out_val = ptr_out_stage5[p] * pstr_up_sampler->iir_filter.gain_sos;
471     ptr_out_samples[p] = out_val;
472     (*num_out_samples)++;
473   }
474 
475   ia_enhaacplus_enc_copy_ring_buffers_sos(ptr_temp_ring_buf,
476                                           ptr_temp_ring_buf + LEN_RING_BUF_SOS_1, ptr_ring_buf1,
477                                           ptr_ring_buf2, LEN_RING_BUF_SOS_1, LEN_RING_BUF_SOS_2);
478 
479   ia_enhaacplus_enc_copy_ring_buffers_sos(ptr_ring_buf1, ptr_ring_buf2, ptr_iir_ring1,
480                                           ptr_iir_ring2, LEN_RING_BUF_SOS_1, LEN_RING_BUF_SOS_2);
481 }
482 
ia_enhaacplus_enc_compute_resampling_ratio(WORD32 ccfl_idx)483 WORD32 ia_enhaacplus_enc_compute_resampling_ratio(WORD32 ccfl_idx) {
484   WORD32 resamp_ratio;
485 
486   if (ccfl_idx == SBR_4_1) {
487     resamp_ratio = 2;
488   } else if (ccfl_idx == SBR_8_3) {
489     resamp_ratio = 4;
490   } else {
491     resamp_ratio = 1;
492   }
493 
494   return resamp_ratio;
495 }
496 
ixheaace_upsampling_inp_buf_generation(FLOAT32 * ptr_inp_buf,FLOAT32 * ptr_temp_buf,WORD32 num_samples,WORD32 upsamp_fac,WORD32 offset)497 VOID ixheaace_upsampling_inp_buf_generation(FLOAT32 *ptr_inp_buf, FLOAT32 *ptr_temp_buf,
498                                             WORD32 num_samples, WORD32 upsamp_fac,
499                                             WORD32 offset) {
500   WORD32 idx, m = 0;
501   FLOAT32 *ptr_in_samples;
502 
503   memset(ptr_temp_buf, 0,
504          (num_samples * IXHEAACE_MAX_CH_IN_BS_ELE * upsamp_fac * sizeof(*ptr_temp_buf)));
505 
506   ptr_in_samples = ptr_inp_buf + offset;
507 
508   // Perform actual upsampling (repeat samples)
509   for (idx = 0; idx < num_samples; idx++) {
510     ptr_temp_buf[m++] = ptr_in_samples[idx * IXHEAACE_MAX_CH_IN_BS_ELE];
511     ptr_temp_buf[m++] = ptr_in_samples[idx * IXHEAACE_MAX_CH_IN_BS_ELE + 1];
512     ptr_temp_buf[m++] =
513         ptr_in_samples[idx *
514                        IXHEAACE_MAX_CH_IN_BS_ELE];  // 1st channel sample repeated for upsampling
515     ptr_temp_buf[m++] = ptr_in_samples[idx * IXHEAACE_MAX_CH_IN_BS_ELE +
516                                        1];  // 2nd channel sample repeated for upsampling
517     ptr_temp_buf[m++] =
518         ptr_in_samples[idx *
519                        IXHEAACE_MAX_CH_IN_BS_ELE];  // 1st channel sample repeated for upsampling
520     ptr_temp_buf[m++] = ptr_in_samples[idx * IXHEAACE_MAX_CH_IN_BS_ELE +
521                                        1];  // 2nd channel sample repeated for upsampling
522   }
523 }