Coverage Report

Created: 2025-11-10 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libxaac/decoder/ixheaacd_usac_ec.c
Line
Count
Source
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
#include <string.h>
21
#include <ixheaac_type_def.h>
22
#include <ixheaac_constants.h>
23
#include <ixheaac_basic_ops32.h>
24
#include <ixheaac_basic_ops16.h>
25
#include <ixheaac_basic_ops40.h>
26
#include "ixheaacd_sbr_common.h"
27
#include "ixheaacd_intrinsics.h"
28
#include "ixheaacd_common_rom.h"
29
#include "ixheaacd_sbrdecsettings.h"
30
#include "ixheaacd_bitbuffer.h"
31
#include "ixheaacd_defines.h"
32
#include "ixheaacd_pns.h"
33
#include <ixheaacd_aac_rom.h>
34
#include "ixheaacd_pulsedata.h"
35
#include "ixheaacd_lt_predict.h"
36
#include "ixheaacd_cnst.h"
37
#include "ixheaacd_drc_data_struct.h"
38
#include "ixheaacd_ec_defines.h"
39
#include "ixheaacd_ec_rom.h"
40
#include "ixheaacd_ec_struct_def.h"
41
#include "ixheaacd_channelinfo.h"
42
#include "ixheaacd_interface.h"
43
#include "ixheaacd_acelp_info.h"
44
#include "ixheaacd_tns_usac.h"
45
#include "ixheaacd_info.h"
46
#include "ixheaacd_drc_dec.h"
47
#include "ixheaacd_sbrdecoder.h"
48
#include "ixheaacd_mps_polyphase.h"
49
#include "ixheaac_sbr_const.h"
50
#include "ixheaacd_ec_defines.h"
51
#include "ixheaacd_ec_struct_def.h"
52
#include "ixheaacd_main.h"
53
#include "ixheaacd_acelp_com.h"
54
55
0
static WORD32 ixheaacd_usac_ec_get_win_seq(WORD32 prev_win_seq) {
56
0
  if (prev_win_seq == LONG_START_SEQUENCE || prev_win_seq == EIGHT_SHORT_SEQUENCE) {
57
0
    return LONG_STOP_SEQUENCE;
58
0
  } else {
59
0
    return ONLY_LONG_SEQUENCE;
60
0
  }
61
0
}
62
63
static VOID ixheaacd_usac_flip_spec_sign(WORD32 *ptr_spec_coeff, WORD32 samples_per_frame,
64
0
                                         UWORD32 *seed_value) {
65
0
  WORD32 i;
66
0
  for (i = 0; i < samples_per_frame; i++) {
67
0
    ptr_spec_coeff[i] = ixheaac_mult32x16in32_sat(ptr_spec_coeff[i],
68
0
                            (WORD16)ixheaacd_randomsign(seed_value));
69
0
  }
70
0
}
71
72
static VOID iexheaace_ec_sfb_nrg_q(WORD32 *ptr_spectrum, ia_ec_sfb_str *pstr_ec_sfb,
73
0
                                   WORD32 win_seq, WORD32 win_trans, WORD32 *ptr_sfb_enrg) {
74
0
  WORD16 *ptr_sfb_offset = pstr_ec_sfb->ptr_sfb_long;
75
0
  WORD32 l = 0, sfb, num_sfb = pstr_ec_sfb->num_sfb_long;
76
0
  switch (win_seq) {
77
0
    case EIGHT_SHORT_SEQUENCE:
78
0
      if (win_trans == NO_TRANSITION) {
79
0
        num_sfb = pstr_ec_sfb->num_sfb_short;
80
0
        ptr_sfb_offset = pstr_ec_sfb->ptr_sfb_short;
81
0
        for (sfb = 0; sfb < num_sfb; sfb++) {
82
0
          WORD64 accu = (WORD64)1;
83
0
          WORD32 q_nrg = (sizeof(accu) << 3) -
84
0
                         ixheaac_norm32(ptr_sfb_offset[sfb + 1] - ptr_sfb_offset[sfb]);
85
0
          for (; l < ptr_sfb_offset[sfb + 1]; l++) {
86
0
            accu += ixheaac_mul32_sh(ptr_spectrum[l], ptr_spectrum[l], q_nrg);
87
0
          }
88
0
          ptr_sfb_enrg[sfb] = ixheaac_norm32((WORD32)accu);
89
0
        }
90
0
      } else {
91
0
        num_sfb = pstr_ec_sfb->num_sfb_long;
92
0
        ptr_sfb_offset = pstr_ec_sfb->ptr_sfb_long;
93
94
0
        for (sfb = 0; sfb < num_sfb; sfb++) {
95
0
          WORD64 accu = (WORD64)1;
96
0
          WORD32 q_nrg = (sizeof(accu) << 3) -
97
0
                         ixheaac_norm32(ptr_sfb_offset[sfb + 1] - ptr_sfb_offset[sfb]);
98
0
          for (; l < ptr_sfb_offset[sfb + 1]; l++) {
99
0
            accu += ixheaac_mul32_sh(ptr_spectrum[(l >> 3)], ptr_spectrum[(l >> 3)], q_nrg);
100
0
          }
101
0
          ptr_sfb_enrg[sfb] = ixheaac_norm32((WORD32)accu);
102
0
        }
103
0
      }
104
0
      break;
105
0
    case ONLY_LONG_SEQUENCE:
106
0
    case LONG_START_SEQUENCE:
107
0
    case LONG_STOP_SEQUENCE:
108
0
      if (win_trans == NO_TRANSITION) {
109
0
        num_sfb = pstr_ec_sfb->num_sfb_long;
110
0
        ptr_sfb_offset = pstr_ec_sfb->ptr_sfb_long;
111
112
0
        for (sfb = 0; sfb < num_sfb; sfb++) {
113
0
          WORD64 accu = (WORD64)1;
114
0
          WORD32 q_nrg = (sizeof(accu) << 3) -
115
0
                         ixheaac_norm32(ptr_sfb_offset[sfb + 1] - ptr_sfb_offset[sfb]);
116
0
          for (; l < ptr_sfb_offset[sfb + 1]; l++) {
117
0
            accu += ixheaac_mul32_sh(ptr_spectrum[l], ptr_spectrum[l], q_nrg);
118
0
          }
119
0
          ptr_sfb_enrg[sfb] = ixheaac_norm32((WORD32)accu);
120
0
        }
121
0
      } else {
122
0
        num_sfb = pstr_ec_sfb->num_sfb_short;
123
0
        ptr_sfb_offset = pstr_ec_sfb->ptr_sfb_short;
124
125
0
        for (sfb = 0; sfb < num_sfb; sfb++) {
126
0
          WORD64 accu = (WORD64)1;
127
0
          WORD32 q_nrg = (sizeof(accu) << 3) -
128
0
                         ixheaac_norm32(ptr_sfb_offset[sfb + 1] - ptr_sfb_offset[sfb]);
129
0
          for (; l < ptr_sfb_offset[sfb + 1] << 3; l++) {
130
0
            accu += (accu + (ixheaac_mul32_sh(ptr_spectrum[l], ptr_spectrum[l], q_nrg))) >> 3;
131
0
          }
132
0
          ptr_sfb_enrg[sfb] = ixheaac_norm32((WORD32)accu);
133
0
        }
134
0
      }
135
0
      break;
136
0
  }
137
0
}
138
139
static VOID ixheaacd_usac_ec_interpolate(WORD32 *ptr_spectrum, WORD16 *pq_spec_coeff_prev,
140
                                         WORD16 *pq_spec_coeff_act, WORD16 *pq_spec_coeff_out,
141
                                         WORD32 *ptr_nrg_prev, WORD32 *ptr_nrg_act,
142
0
                                         WORD32 num_sfb, WORD16 *ptr_sfb_offset) {
143
0
  WORD32 sfb, l = 0;
144
0
  WORD32 fac_shift;
145
0
  WORD32 fac_mod;
146
147
0
  for (sfb = 0; sfb < num_sfb; sfb++) {
148
0
    fac_shift =
149
0
        ptr_nrg_prev[sfb] - ptr_nrg_act[sfb] + ((*pq_spec_coeff_act - *pq_spec_coeff_prev) << 1);
150
0
    fac_mod = fac_shift & 3;
151
0
    fac_shift = (fac_shift >> 2) + 1;
152
0
    fac_shift += *pq_spec_coeff_prev - ixheaac_max16(*pq_spec_coeff_prev, *pq_spec_coeff_act);
153
0
    fac_shift = ixheaac_max32(ixheaac_min32(fac_shift, INT_BITS - 1), -(INT_BITS - 1));
154
155
0
    for (; l < ptr_sfb_offset[sfb + 1]; l++) {
156
0
      WORD32 accu = ixheaac_shl32_sat(
157
0
          ixheaac_mult32x32in32(ptr_spectrum[l], (WORD32)(ia_ec_interpolation_fac[fac_mod])), 1);
158
0
      ptr_spectrum[l] = ixheaac_shl32_dir_sat((WORD32)accu, fac_shift);
159
0
    }
160
0
  }
161
0
  *pq_spec_coeff_out = ixheaac_max16(*pq_spec_coeff_prev, *pq_spec_coeff_act);
162
0
}
163
164
static VOID ixheaacd_usac_ec_interpolate_frame(ia_usac_data_struct *pstr_usac_data,
165
                                               ia_ec_state_str *pstr_ec_state,
166
                                               const ia_usac_samp_rate_info *pstr_samp_rate_info,
167
0
                                               WORD32 frame_ok, WORD32 chn) {
168
0
  WORD32 frame_length = pstr_usac_data->ccfl;
169
0
  WORD32 *ptr_spec_coeff = pstr_usac_data->coef_fix[chn];
170
0
  WORD16 *ptr_spec_sf = pstr_usac_data->spec_scale[chn];
171
172
0
  WORD32 i;
173
0
  ia_ec_scratch_str *pstr_ec_scratch = pstr_ec_state->pstr_ec_scratch;
174
0
  WORD16 num_sfb_long;
175
0
  WORD16 *ptr_sfb_long = NULL;
176
0
  WORD16 num_sfb_short;
177
0
  WORD16 *ptr_sfb_short = NULL;
178
179
0
  if (pstr_usac_data->core_mode == CORE_MODE_FD) {
180
0
    num_sfb_long = pstr_samp_rate_info->num_sfb_1024;
181
0
    ptr_sfb_long = (WORD16 *)pstr_samp_rate_info->ptr_sfb_1024;
182
0
    num_sfb_short = pstr_samp_rate_info->num_sfb_128;
183
0
    ptr_sfb_short = (WORD16 *)pstr_samp_rate_info->ptr_sfb_128;
184
0
    if (pstr_usac_data->ccfl == WIN_LEN_768) {
185
0
      num_sfb_long = pstr_samp_rate_info->num_sfb_768;
186
0
      ptr_sfb_long = (WORD16 *)pstr_samp_rate_info->ptr_sfb_768;
187
0
      num_sfb_short = pstr_samp_rate_info->num_sfb_96;
188
0
      ptr_sfb_short = (WORD16 *)pstr_samp_rate_info->ptr_sfb_96;
189
0
    }
190
0
    pstr_ec_state->str_ec_sfb.num_sfb_long = num_sfb_long;
191
0
    pstr_ec_state->str_ec_sfb.num_sfb_long = num_sfb_long;
192
0
    pstr_ec_state->str_ec_sfb.ptr_sfb_long = ptr_sfb_long;
193
0
    pstr_ec_state->str_ec_sfb.ptr_sfb_long = ptr_sfb_long;
194
195
0
    memset(pstr_ec_scratch->prev_sfb_nrg, 0, sizeof(pstr_ec_scratch->prev_sfb_nrg));
196
0
    memset(pstr_ec_scratch->pres_sfb_nrg, 0, sizeof(pstr_ec_scratch->pres_sfb_nrg));
197
198
0
    if (!frame_ok) {
199
0
      pstr_usac_data->window_shape[chn] = pstr_ec_state->win_shape;
200
0
      pstr_usac_data->window_sequence[chn] = pstr_ec_state->win_seq;
201
0
      memcpy(ptr_spec_coeff, pstr_ec_state->spectral_coeff,
202
0
             sizeof(*ptr_spec_coeff) * frame_length);
203
0
      memcpy(ptr_spec_sf, pstr_ec_state->q_spec_coeff, sizeof(pstr_ec_state->q_spec_coeff));
204
0
    }
205
0
  }
206
207
0
  if (!pstr_ec_state->prev_frame_ok[1]) {
208
0
    if (frame_ok && pstr_ec_state->prev_frame_ok[0] &&
209
0
        pstr_usac_data->core_mode == CORE_MODE_FD) {
210
0
      if (pstr_usac_data->window_sequence[chn] == EIGHT_SHORT_SEQUENCE) {
211
0
        WORD32 wnd;
212
213
0
        if (pstr_ec_state->win_seq == EIGHT_SHORT_SEQUENCE) {
214
0
          WORD32 num_sfb = num_sfb_short;
215
0
          WORD16 *ptr_sfb_offset = ptr_sfb_short;
216
0
          pstr_usac_data->window_shape[chn] = 1;
217
0
          pstr_usac_data->window_sequence[chn] = EIGHT_SHORT_SEQUENCE;
218
219
0
          for (wnd = 0; wnd < 8; wnd++) {
220
0
            iexheaace_ec_sfb_nrg_q(&ptr_spec_coeff[wnd * (frame_length >> 3)],
221
0
                                   &pstr_ec_state->str_ec_sfb, EIGHT_SHORT_SEQUENCE,
222
0
                                   NO_TRANSITION, pstr_ec_scratch->prev_sfb_nrg);
223
224
0
            iexheaace_ec_sfb_nrg_q(&pstr_ec_state->spectral_coeff[wnd * (frame_length >> 3)],
225
0
                                   &pstr_ec_state->str_ec_sfb, EIGHT_SHORT_SEQUENCE,
226
0
                                   NO_TRANSITION, pstr_ec_scratch->pres_sfb_nrg);
227
228
0
            ixheaacd_usac_ec_interpolate(&ptr_spec_coeff[wnd * (frame_length / 8)],
229
0
                                         &ptr_spec_sf[wnd], &pstr_ec_state->q_spec_coeff[wnd],
230
0
                                         &ptr_spec_sf[wnd], pstr_ec_scratch->prev_sfb_nrg,
231
0
                                         pstr_ec_scratch->pres_sfb_nrg, num_sfb, ptr_sfb_offset);
232
0
          }
233
0
        } else {
234
0
          WORD32 num_sfb = num_sfb_long;
235
0
          WORD16 *ptr_sfb_offset = ptr_sfb_long;
236
0
          WORD16 q_spec_coeff_out;
237
238
0
          iexheaace_ec_sfb_nrg_q(&ptr_spec_coeff[frame_length - (frame_length >> 3)],
239
0
                                 &pstr_ec_state->str_ec_sfb, EIGHT_SHORT_SEQUENCE,
240
0
                                 TRANS_SHORT_LONG, pstr_ec_scratch->pres_sfb_nrg);
241
242
0
          iexheaace_ec_sfb_nrg_q(pstr_ec_state->spectral_coeff, &pstr_ec_state->str_ec_sfb,
243
0
                                 ONLY_LONG_SEQUENCE, NO_TRANSITION,
244
0
                                 pstr_ec_scratch->prev_sfb_nrg);
245
246
0
          pstr_usac_data->window_shape[chn] = 0;
247
0
          pstr_usac_data->window_sequence[chn] = LONG_STOP_SEQUENCE;
248
0
          memcpy(&ptr_spec_coeff[0], pstr_ec_state->spectral_coeff,
249
0
                 frame_length * sizeof(ptr_spec_coeff[0]));
250
251
0
          for (i = 0; i < 8; i++) {
252
0
            if (ptr_spec_sf[i] > ptr_spec_sf[0]) {
253
0
              ptr_spec_sf[0] = ptr_spec_sf[i];
254
0
            }
255
0
          }
256
257
0
          ixheaacd_usac_ec_interpolate(ptr_spec_coeff, &pstr_ec_state->q_spec_coeff[0],
258
0
                                       &ptr_spec_sf[0], &q_spec_coeff_out,
259
0
                                       pstr_ec_scratch->prev_sfb_nrg,
260
0
                                       pstr_ec_scratch->pres_sfb_nrg, num_sfb, ptr_sfb_offset);
261
262
0
          ptr_spec_sf[0] = q_spec_coeff_out;
263
0
        }
264
0
      } else {
265
0
        WORD32 num_sfb = num_sfb_long;
266
0
        WORD16 *ptr_sfb_offset = ptr_sfb_long;
267
0
        WORD16 q_spec_coeff_act = pstr_ec_state->q_spec_coeff[0];
268
269
0
        iexheaace_ec_sfb_nrg_q(ptr_spec_coeff, &pstr_ec_state->str_ec_sfb, ONLY_LONG_SEQUENCE,
270
0
                               NO_TRANSITION, pstr_ec_scratch->prev_sfb_nrg);
271
272
0
        if (pstr_ec_state->win_seq == EIGHT_SHORT_SEQUENCE) {
273
0
          pstr_usac_data->window_shape[chn] = 1;
274
0
          pstr_usac_data->window_sequence[chn] = LONG_START_SEQUENCE;
275
276
0
          for (i = 1; i < 8; i++) {
277
0
            if (pstr_ec_state->q_spec_coeff[i] > q_spec_coeff_act) {
278
0
              q_spec_coeff_act = pstr_ec_state->q_spec_coeff[i];
279
0
            }
280
0
          }
281
282
0
          iexheaace_ec_sfb_nrg_q(pstr_ec_state->spectral_coeff, &pstr_ec_state->str_ec_sfb,
283
0
                                 EIGHT_SHORT_SEQUENCE, TRANS_SHORT_LONG,
284
0
                                 pstr_ec_scratch->pres_sfb_nrg);
285
0
        } else {
286
0
          pstr_usac_data->window_shape[chn] = 0;
287
0
          pstr_usac_data->window_sequence[chn] = ONLY_LONG_SEQUENCE;
288
0
          iexheaace_ec_sfb_nrg_q(pstr_ec_state->spectral_coeff, &pstr_ec_state->str_ec_sfb,
289
0
                                 ONLY_LONG_SEQUENCE, NO_TRANSITION,
290
0
                                 pstr_ec_scratch->pres_sfb_nrg);
291
0
        }
292
0
        ixheaacd_usac_ec_interpolate(ptr_spec_coeff, &ptr_spec_sf[0], &q_spec_coeff_act,
293
0
                                     &ptr_spec_sf[0], pstr_ec_scratch->prev_sfb_nrg,
294
0
                                     pstr_ec_scratch->pres_sfb_nrg, num_sfb, ptr_sfb_offset);
295
0
      }
296
0
    }
297
0
    ixheaacd_usac_flip_spec_sign(ptr_spec_coeff, frame_length, &pstr_usac_data->seed_value[chn]);
298
0
  }
299
300
0
  if (FRAME_MUTE == pstr_ec_state->conceal_state) {
301
0
    pstr_usac_data->window_shape[chn] = pstr_ec_state->win_shape;
302
0
    pstr_usac_data->window_sequence[chn] = ixheaacd_usac_ec_get_win_seq(pstr_ec_state->win_seq);
303
0
    pstr_ec_state->win_seq = pstr_usac_data->window_sequence[chn];
304
0
    memset(ptr_spec_coeff, 0, frame_length * sizeof(ptr_spec_coeff[0]));
305
0
  }
306
307
0
  return;
308
0
}
309
310
0
static VOID ixheaacd_usac_lpc_ec_state(ia_ec_state_str *pstr_ec_state, WORD32 frame_ok) {
311
0
  if (frame_ok == 0) {
312
0
    if (pstr_ec_state->fade_idx < MAX_FADE_FRAMES) {
313
0
      pstr_ec_state->fade_idx++;
314
0
    }
315
0
    pstr_ec_state->conceal_state = FRAME_CONCEAL_SINGLE;
316
0
  } else {
317
0
    if (pstr_ec_state->fade_idx > 0) {
318
0
      pstr_ec_state->fade_idx--;
319
0
    }
320
0
    pstr_ec_state->conceal_state = FRAME_OKAY;
321
0
  }
322
0
  if (pstr_ec_state->fade_idx >= MAX_FADE_FRAMES) {
323
0
    pstr_ec_state->fade_idx = MAX_FADE_FRAMES;
324
0
    pstr_ec_state->conceal_state = FRAME_MUTE;
325
0
  }
326
0
  if (pstr_ec_state->fade_idx < 0) {
327
0
    pstr_ec_state->fade_idx = 0;
328
0
  }
329
0
  return;
330
0
}
331
332
0
static VOID ixheaacd_usac_ec_state(ia_ec_state_str *pstr_ec_state, WORD32 frame_ok) {
333
0
  WORD32 ec_state_val = (pstr_ec_state->prev_frame_ok[0] << 2) +
334
0
                        (pstr_ec_state->prev_frame_ok[1] << 1) + (frame_ok);
335
336
0
  switch (ec_state_val) {
337
0
    case 0:
338
0
    case 4:
339
0
      if (pstr_ec_state->fade_idx < MAX_FADE_FRAMES) {
340
0
        pstr_ec_state->fade_idx++;
341
0
      }
342
0
      pstr_ec_state->conceal_state = FRAME_CONCEAL_SINGLE;
343
0
      break;
344
0
    case 1:
345
0
    case 2:
346
0
      if (pstr_ec_state->fade_idx > 0) {
347
0
        pstr_ec_state->fade_idx--;
348
0
      }
349
0
      pstr_ec_state->conceal_state = FRAME_FADE;
350
0
      break;
351
0
    case 5:
352
0
      if (pstr_ec_state->fade_idx > 0) {
353
0
        pstr_ec_state->fade_idx--;
354
0
      }
355
0
      pstr_ec_state->conceal_state = FRAME_OKAY;
356
0
      break;
357
0
      break;
358
0
    case 3:
359
0
    case 6:
360
0
    case 7:
361
0
      if (pstr_ec_state->fade_idx > 0) {
362
0
        pstr_ec_state->fade_idx--;
363
0
      }
364
0
      pstr_ec_state->conceal_state = FRAME_OKAY;
365
0
      break;
366
0
    default:
367
0
      pstr_ec_state->conceal_state = FRAME_OKAY;
368
0
  }
369
0
  if (pstr_ec_state->fade_idx > MAX_FADE_FRAMES) {
370
0
    pstr_ec_state->fade_idx = MAX_FADE_FRAMES;
371
0
  }
372
0
  if (pstr_ec_state->fade_idx == MAX_FADE_FRAMES) {
373
0
    pstr_ec_state->conceal_state = FRAME_MUTE;
374
0
  }
375
0
  if (pstr_ec_state->fade_idx < 0) {
376
0
    pstr_ec_state->fade_idx = 0;
377
0
  }
378
0
}
379
380
47.4k
VOID ixheaacd_usac_ec_init(ia_ec_state_str *pstr_ec_state, WORD32 core_coder_mode) {
381
47.4k
  pstr_ec_state->win_shape = 1;
382
47.4k
  pstr_ec_state->win_seq = ONLY_LONG_SEQUENCE;
383
47.4k
  pstr_ec_state->prev_win_group_len = 1;
384
385
47.4k
  pstr_ec_state->conceal_state = FRAME_OKAY;
386
387
47.4k
  memset(pstr_ec_state->spectral_coeff, 0, sizeof(pstr_ec_state->spectral_coeff));
388
47.4k
  memset(pstr_ec_state->q_spec_coeff, 0, sizeof(pstr_ec_state->q_spec_coeff));
389
390
47.4k
  pstr_ec_state->prev_frame_ok[0] = 1;
391
47.4k
  pstr_ec_state->prev_frame_ok[1] = 1;
392
393
47.4k
  pstr_ec_state->fade_idx = 0;
394
395
47.4k
  pstr_ec_state->prev_core_mode = core_coder_mode;
396
47.4k
}
397
398
VOID ixheaacd_usac_lpc_ec(FLOAT32 lsp[][ORDER], FLOAT32 *lpc4_lsf, FLOAT32 *lsf_adaptive_mean,
399
0
                          const WORD32 first_lpd_flag) {
400
0
  WORD32 i, j;
401
402
0
  if (first_lpd_flag) {
403
0
    memcpy(lsp[0], lsf_init, sizeof(lsf_init));
404
0
    memcpy(lpc4_lsf, lsf_init, sizeof(lsf_init));
405
0
  } else {
406
0
    memcpy(lsp[0], lpc4_lsf, ORDER * sizeof(lpc4_lsf[0]));
407
0
  }
408
409
0
  for (i = 0; i < ORDER; i++) {
410
0
    FLOAT32 lsf_mean = (BETA * lsf_init[i]) + (ONE_BETA * lsf_adaptive_mean[i]);
411
0
    lsp[1][i] = (BFI_FAC * lpc4_lsf[i]) + (ONE_BFI_FAC * lsf_mean);
412
0
  }
413
414
0
  for (j = 2; j <= 4; j++) {
415
0
    for (i = 0; i < ORDER; i++) {
416
0
      FLOAT32 lsf_mean = ((BETA + (j * ONE_BFI_FAC)) * lsf_init[i]) +
417
0
                         ((ONE_BETA - (j * ONE_BFI_FAC)) * lsf_adaptive_mean[i]);
418
0
      lsp[j][i] = (BFI_FAC * lsp[j - 1][i]) + (ONE_BFI_FAC * lsf_mean);
419
0
    }
420
0
  }
421
422
0
  memcpy(lpc4_lsf, lsp[4], ORDER * sizeof(lpc4_lsf[0]));
423
0
}
424
425
VOID ixheaacd_usac_ec_save_states(ia_ec_state_str *pstr_ec_state,
426
0
                                  ia_usac_data_struct *pstr_usac_data, WORD32 ch) {
427
0
  if (pstr_usac_data->core_mode == CORE_MODE_FD &&
428
0
      (pstr_usac_data->frame_ok == 1 && pstr_ec_state->prev_frame_ok[1] == 1)) {
429
0
    WORD32 *ptr_spec_coeff = pstr_usac_data->coef_fix[ch];
430
0
    WORD16 *ptr_spec_scale = pstr_usac_data->spec_scale[ch];
431
0
    WORD16 q_spec_coeff[MAX_SPEC_SCALE_LEN_EC];
432
0
    UWORD8 win_shape = pstr_ec_state->win_shape;
433
0
    UWORD8 win_shape_prev = pstr_ec_state->win_shape_prev;
434
0
    WORD32 win_seq = pstr_ec_state->win_seq;
435
0
    WORD32 td_frame_prev = pstr_ec_state->td_frame_prev;
436
0
    WORD32 fac_data_present = pstr_ec_state->fac_data_present;
437
438
0
    ia_sfb_info_struct *sfb_info =
439
0
        pstr_usac_data->pstr_usac_winmap[pstr_usac_data->window_sequence[ch]];
440
0
    WORD32 *ptr_scratch_buf = &pstr_ec_state->pstr_ec_scratch->spec_coeff[0];
441
442
0
    memcpy(q_spec_coeff, pstr_ec_state->q_spec_coeff, sizeof(q_spec_coeff));
443
0
    pstr_ec_state->win_seq = pstr_usac_data->window_sequence[ch];
444
0
    pstr_ec_state->win_shape = pstr_usac_data->window_shape[ch];
445
0
    pstr_ec_state->td_frame_prev = pstr_usac_data->td_frame_prev[ch];
446
0
    pstr_ec_state->fac_data_present = pstr_usac_data->fac_data_present[ch];
447
0
    pstr_ec_state->win_shape_prev = pstr_usac_data->window_shape_prev[ch];
448
0
    pstr_ec_state->prev_win_group_len = (WORD32)sfb_info->group_len[sfb_info->num_groups - 1];
449
450
0
    memcpy(pstr_ec_state->q_spec_coeff, ptr_spec_scale, sizeof(pstr_ec_state->q_spec_coeff));
451
452
0
    memcpy(ptr_scratch_buf, ptr_spec_coeff, pstr_usac_data->ccfl * sizeof(ptr_scratch_buf[0]));
453
0
    memcpy(ptr_spec_coeff, &pstr_ec_state->spectral_coeff[0],
454
0
           pstr_usac_data->ccfl * sizeof(ptr_spec_coeff[0]));
455
0
    memcpy(&pstr_ec_state->spectral_coeff[0], ptr_scratch_buf,
456
0
           pstr_usac_data->ccfl * sizeof(ptr_spec_coeff[0]));
457
458
0
    if (!pstr_usac_data->first_frame) {
459
0
      pstr_usac_data->window_sequence[ch] = win_seq;
460
0
      pstr_usac_data->window_shape[ch] = win_shape;
461
0
      pstr_usac_data->td_frame_prev_ec[ch] = td_frame_prev;
462
0
      pstr_usac_data->fac_data_present[ch] = fac_data_present;
463
0
      pstr_usac_data->window_shape_prev[ch] = win_shape_prev;
464
0
    }
465
466
0
    memcpy(ptr_spec_scale, q_spec_coeff, sizeof(q_spec_coeff));
467
0
  }
468
0
}
469
470
VOID ixheaacd_usac_apply_ec(ia_usac_data_struct *pstr_usac_data,
471
0
                            const ia_usac_samp_rate_info *pstr_samp_rate_info, WORD32 ch) {
472
0
  WORD32 frame_ok = pstr_usac_data->frame_ok;
473
0
  ia_ec_state_str *pstr_ec_state = &pstr_usac_data->str_error_concealment[ch];
474
475
0
  if (pstr_usac_data->core_mode == CORE_MODE_FD) {
476
0
    if (pstr_ec_state->win_shape == (UWORD8)-1) {
477
0
      pstr_ec_state->win_shape = pstr_usac_data->window_shape[ch];
478
0
    }
479
480
0
    ixheaacd_usac_ec_state(pstr_ec_state, frame_ok);
481
482
0
    if (pstr_ec_state->conceal_state == FRAME_OKAY) {
483
0
      pstr_ec_state->prev_core_mode = pstr_usac_data->core_mode;
484
0
      ixheaacd_usac_ec_save_states(pstr_ec_state, pstr_usac_data, ch);
485
0
    } else if (pstr_ec_state->conceal_state == FRAME_CONCEAL_SINGLE) {
486
0
      ixheaacd_usac_ec_interpolate_frame(pstr_usac_data, pstr_ec_state, pstr_samp_rate_info,
487
0
                                         frame_ok, ch);
488
0
    } else {
489
0
    }
490
0
    if (!frame_ok) {
491
0
      WORD32 *ptr_spec_coeff = pstr_usac_data->coef_fix[ch];
492
0
      WORD16 *ptr_spec_scale = pstr_usac_data->spec_scale[ch];
493
494
0
      pstr_usac_data->window_sequence[ch] = pstr_ec_state->win_seq;
495
0
      pstr_usac_data->window_shape[ch] = pstr_ec_state->win_shape;
496
497
0
      if (pstr_ec_state->conceal_state != FRAME_MUTE) {
498
0
        memcpy(ptr_spec_scale, pstr_ec_state->q_spec_coeff, sizeof(pstr_ec_state->q_spec_coeff));
499
0
        memcpy(ptr_spec_coeff, pstr_ec_state->spectral_coeff,
500
0
               sizeof(pstr_ec_state->spectral_coeff));
501
0
      } else {
502
0
        memset(ptr_spec_scale, 0, MAX_SPEC_SCALE_LEN * sizeof(ptr_spec_scale[0]));
503
0
        memset(ptr_spec_coeff, 0, pstr_usac_data->ccfl * sizeof(ptr_spec_coeff[0]));
504
0
      }
505
0
    }
506
0
  } else {
507
0
    ixheaacd_usac_lpc_ec_state(pstr_ec_state, frame_ok);
508
509
0
    if (pstr_ec_state->conceal_state == FRAME_OKAY) {
510
0
      memcpy(pstr_ec_state->lsf4, pstr_usac_data->lpc4_lsf, sizeof(pstr_ec_state->lsf4));
511
0
    } else if (pstr_ec_state->conceal_state == FRAME_CONCEAL_SINGLE) {
512
0
      WORD32 frame_length = pstr_usac_data->ccfl;
513
0
      WORD32 *ptr_spec_coeff = pstr_usac_data->tcx_spec_coeffs[ch];
514
515
0
      ixheaacd_usac_flip_spec_sign(ptr_spec_coeff, frame_length,
516
0
                                   &pstr_usac_data->seed_value[ch]);
517
0
    } else {
518
0
      WORD32 *ptr_spec_coeff = pstr_usac_data->tcx_spec_coeffs[ch];
519
0
      memset(ptr_spec_coeff, 0, pstr_usac_data->ccfl * sizeof(ptr_spec_coeff[0]));
520
0
    }
521
0
    if (!frame_ok) {
522
0
      memcpy(pstr_usac_data->lpc4_lsf, pstr_ec_state->lsf4, sizeof(pstr_usac_data->lpc4_lsf));
523
0
    }
524
0
  }
525
526
0
  pstr_ec_state->prev_frame_ok[0] = pstr_ec_state->prev_frame_ok[1];
527
0
  pstr_ec_state->prev_frame_ok[1] = frame_ok;
528
529
0
  return;
530
0
}
531
532
0
static VOID ixheaacd_lpc_wt_tool(FLOAT32 a[], WORD32 l) {
533
0
  WORD32 i;
534
535
0
  for (i = 0; i < l; i++) {
536
0
    a[i] = a[i] * ixheaacd_gamma_table[i];
537
0
  }
538
539
0
  return;
540
0
}
541
static VOID ixheaacd_lpc_coef_gen_ec(FLOAT32 lsf_old[], FLOAT32 lsf_new[], FLOAT32 a[],
542
0
                                     WORD32 m) {
543
0
  FLOAT32 lsf[ORDER], *ptr_a;
544
0
  FLOAT32 inc, fnew, fold;
545
0
  WORD32 i;
546
547
0
  ptr_a = a;
548
549
0
  inc = 1.0f / (FLOAT32)m;
550
0
  fnew = 0.5f - (0.5f * inc);
551
0
  fold = 1.0f - fnew;
552
553
0
  for (i = 0; i < ORDER; i++) {
554
0
    lsf[i] = (lsf_old[i] * fold) + (lsf_new[i] * fnew);
555
0
  }
556
0
  ixheaacd_lsp_to_lp_conversion(lsf, ptr_a);
557
558
0
  return;
559
0
}
560
561
VOID ixheaacd_usac_tcx_ec(ia_usac_data_struct *pstr_usac_data, ia_usac_lpd_decoder_handle st,
562
0
                          FLOAT32 *ptr_lsp_curr, WORD32 frame_idx, FLOAT32 *lp_flt_coff_a) {
563
0
  WORD32 ch = pstr_usac_data->present_chan;
564
0
  FLOAT32 synth_buf[ORDER + LEN_FRAME], temp;
565
0
  FLOAT32 exc_buf[MAX_PITCH + ORDER + 1 + LEN_FRAME];
566
0
  FLOAT32 *ptr_syn = synth_buf + ORDER;
567
0
  FLOAT32 *ptr_exc = exc_buf + MAX_PITCH + ORDER + 1;
568
0
  FLOAT32 est_fac_est = 0.1f;
569
0
  WORD32 i, sf_idx;
570
0
  FLOAT32 synth_sig_buf[LEN_SUBFR + 1];
571
0
  FLOAT32 *synth_signal = synth_sig_buf + 1;
572
0
  WORD32 num_lost_frames = pstr_usac_data->num_lost_lpd_frames[ch];
573
0
  WORD32 len_subfrm = pstr_usac_data->len_subfrm;
574
0
  FLOAT32 past_tcx_gain = pstr_usac_data->past_gain_tcx[ch];
575
0
  WORD32 l_div_part = MAX_PITCH + ORDER + 1 - len_subfrm;
576
0
  FLOAT32 *synth = pstr_usac_data->synth_buf + MAX_PITCH - LEN_SUBFR;
577
0
  FLOAT32 *ptr_synth = &synth[512 + frame_idx * len_subfrm];
578
0
  FLOAT32 syn_buf[MAX_PITCH + ORDER + 1];
579
0
  FLOAT32 *ptr_syn_buf = &syn_buf[ORDER];
580
581
0
  memcpy(syn_buf, &ptr_synth[-(MAX_PITCH + ORDER + 1)],
582
0
         sizeof(syn_buf));
583
0
  memcpy(st->synth_prev_ec, &syn_buf[MAX_PITCH + 1], sizeof(st->synth_prev_ec));
584
0
  ixheaacd_residual_tool_float(pstr_usac_data->lp_flt_coff_a_ec, ptr_syn_buf, st->xcitation_prev,
585
0
                               pstr_usac_data->len_subfrm, 1);
586
0
  ixheaacd_residual_tool_float(lp_flt_coff_a, &syn_buf[l_div_part],
587
0
                               st->xcitation_prev + l_div_part, pstr_usac_data->len_subfrm, 1);
588
0
  if (st->last_tcx_pitch > MAX_PITCH) {
589
0
    st->last_tcx_pitch = MAX_PITCH;
590
0
  }
591
592
0
  memcpy(synth_buf, st->synth_prev_ec, ORDER * sizeof(FLOAT32));
593
0
  memcpy(exc_buf, st->xcitation_prev, (MAX_PITCH + ORDER + 1) * sizeof(FLOAT32));
594
595
0
  if (num_lost_frames <= 8) {
596
0
    est_fac_est = ixheaacd_exc_fade_fac[num_lost_frames - 1];
597
0
  }
598
599
0
  for (i = 0; i < len_subfrm; i++) {
600
0
    ptr_exc[i] = est_fac_est * ptr_exc[i - st->last_tcx_pitch];
601
0
  }
602
0
  synth_signal[-1] = ptr_exc[-1];
603
604
0
  for (sf_idx = 0; sf_idx < len_subfrm; sf_idx += LEN_SUBFR) {
605
0
    FLOAT32 lp_coef[ORDER + 1];
606
607
0
    ixheaacd_lpc_coef_gen_ec(st->lspold, ptr_lsp_curr, lp_coef, len_subfrm / LEN_SUBFR);
608
609
0
    ixheaacd_synthesis_tool_float(lp_coef, &ptr_exc[sf_idx], &ptr_syn[sf_idx], LEN_SUBFR,
610
0
                                  synth_buf);
611
612
0
    ixheaacd_lpc_wt_tool(lp_coef, ORDER);
613
614
0
    ixheaacd_residual_tool_float(lp_coef, &ptr_syn[sf_idx], synth_signal, LEN_SUBFR, 1);
615
616
0
    ixheaacd_deemphsis_tool(synth_signal, LEN_SUBFR, synth_signal[-1]);
617
618
0
    temp = (est_fac_est * past_tcx_gain);
619
620
0
    for (i = 0; i < LEN_SUBFR; i++) {
621
0
      if (synth_signal[i] > temp) {
622
0
        synth_signal[i] = temp;
623
0
      } else {
624
0
        if (synth_signal[i] < -temp) {
625
0
          synth_signal[i] = -temp;
626
0
        }
627
0
      }
628
0
    }
629
630
0
    for (i = LEN_SUBFR - 1; i >= 0; i--) {
631
0
      synth_signal[i] = (synth_signal[i] - (PREEMPH_FILT_FAC * synth_signal[i - 1]));
632
0
    }
633
0
    ixheaacd_synthesis_tool_float(lp_coef, synth_signal, &ptr_syn[sf_idx], LEN_SUBFR, synth_buf);
634
635
0
    memmove(&ptr_synth[sf_idx], &ptr_syn[sf_idx], LEN_SUBFR * sizeof(FLOAT32));
636
0
  }
637
638
0
  memcpy(st->xcitation_prev, ptr_exc + len_subfrm - (MAX_PITCH + ORDER + 1),
639
0
         sizeof(FLOAT32) * (MAX_PITCH + ORDER + 1));
640
0
  memcpy(st->synth_prev_ec, synth_buf + len_subfrm, sizeof(FLOAT32) * ORDER);
641
0
  return;
642
0
}