/******************************************************************************
 *                                                                            *
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *****************************************************************************
 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
 */

#include <string.h>
#include <math.h>
#include <limits.h>

#include "ixheaac_type_def.h"
#include "ixheaac_constants.h"
#include "ixheaace_aac_constants.h"
#include "ixheaac_error_standards.h"
#include "ixheaace_error_codes.h"
#include "ixheaac_basic_ops32.h"
#include "ixheaac_basic_ops16.h"
#include "ixheaac_basic_ops40.h"
#include "ixheaac_basic_ops.h"

#include "ixheaace_sbr_header.h"
#include "ixheaace_sbr_def.h"
#include "ixheaace_resampler.h"

#include "ixheaace_sbr_rom.h"
#include "ixheaace_common_rom.h"
#include "ixheaace_sbr_hbe.h"
#include "ixheaace_sbr_qmf_enc.h"
#include "ixheaace_sbr_tran_det.h"
#include "ixheaace_sbr_frame_info_gen.h"
#include "ixheaace_sbr_env_est.h"
#include "ixheaace_sbr_code_envelope.h"
#include "ixheaace_sbr_main.h"
#include "ixheaace_sbr_missing_harmonics_det.h"
#include "ixheaace_sbr_inv_filtering_estimation.h"
#include "ixheaace_sbr_noise_floor_est.h"

#include "ixheaace_common_rom.h"
#include "ixheaace_sbr_ton_corr.h"
#include "iusace_esbr_pvc.h"
#include "iusace_esbr_inter_tes.h"
#include "ixheaace_sbr.h"

#include "ixheaace_bitbuffer.h"

#include "ixheaace_sbr_cmondata.h"
#include "ixheaace_sbr_write_bitstream.h"

#include "ixheaace_sbr_hybrid.h"
#include "ixheaace_sbr_ps_enc.h"

#include "ixheaace_common_utils.h"

#include "ixheaace_sbr_header.h"
#include "ixheaace_sbr_def.h"
#include "ixheaace_resampler.h"
#include "ixheaace_sbr_rom.h"
#include "ixheaace_common_rom.h"
#include "ixheaace_sbr_hbe.h"
#include "ixheaace_sbr_qmf_enc.h"
#include "ixheaace_sbr_tran_det.h"
#include "ixheaace_sbr_frame_info_gen.h"
#include "ixheaace_sbr_env_est.h"
#include "ixheaace_sbr_code_envelope.h"
#include "ixheaace_psy_const.h"
#include "ixheaace_tns.h"
#include "ixheaace_tns_params.h"
#include "ixheaace_rom.h"
#include "ixheaace_common_rom.h"
#include "ixheaace_bitbuffer.h"

#include "ixheaace_sbr_main.h"
#include "ixheaace_common_rom.h"
#include "ixheaace_sbr_missing_harmonics_det.h"
#include "ixheaace_sbr_inv_filtering_estimation.h"
#include "ixheaace_sbr_noise_floor_est.h"
#include "ixheaace_sbr_ton_corr.h"
#include "iusace_esbr_pvc.h"
#include "ixheaace_sbr.h"

#include "ixheaace_sbr_freq_scaling.h"

#include "ixheaace_bitbuffer.h"

#include "ixheaace_sbr_hybrid.h"
#include "ixheaace_sbr_ps_enc.h"

#include "ixheaace_sbr_crc.h"
#include "ixheaace_sbr_cmondata.h"
#include "ixheaace_sbr_enc_struct.h"
#include "ixheaace_sbr_write_bitstream.h"

#include "ixheaace_common_utils.h"

static WORD32 ixheaace_map_panorama(WORD32 nrg_val, WORD32 amp_res, WORD32 *ptr_quant_error) {
  WORD32 i = 0;
  ;
  WORD32 min_val, val;
  WORD32 pan_tab[2][10] = {{0, 2, 4, 6, 8, 12, 16, 20, 24}, {0, 2, 4, 8, 12}};
  WORD32 max_index[2] = {9, 5};

  WORD32 pan_index;
  WORD32 sign;

  sign = nrg_val > 0 ? 1 : -1;

  nrg_val = sign * nrg_val;

  min_val = INT_MAX;
  pan_index = 0;

  while (i < max_index[amp_res]) {
    val = ixheaac_abs32(nrg_val - pan_tab[amp_res][i]);
    if (val < min_val) {
      min_val = val;
      pan_index = i;
    }
    i++;
  }

  *ptr_quant_error = min_val;

  return pan_tab[amp_res][max_index[amp_res] - 1] + sign * pan_tab[amp_res][pan_index];
}

static VOID ixheaace_sbr_noise_floor_levels_quantisation(WORD32 *ptr_noise_levels,
                                                         FLOAT32 *ptr_flt_noise_levels,
                                                         WORD32 coupling) {
  WORD32 i = 0;
  WORD32 dummy;

  while (i < MAXIMUM_NUM_NOISE_VALUES) {
    WORD32 tmp;

    tmp = ptr_flt_noise_levels[i] > 30.0f ? 30 : (WORD32)(ptr_flt_noise_levels[i] + 0.5f);

    if (coupling) {
      tmp = tmp < -30 ? -30 : tmp;
      tmp = ixheaace_map_panorama(tmp, 1, &dummy);
    }
    ptr_noise_levels[i] = tmp;

    i++;
  }
}

static VOID ixheaace_couple_noise_floor(FLOAT32 *ptr_noise_lvl_left,
                                        FLOAT32 *ptr_noise_lvl_right) {
  WORD32 i = 0;

  while (i < MAXIMUM_NUM_NOISE_VALUES) {
    FLOAT32 pow_left, pow_right;

    pow_left = (FLOAT32)pow(2.0f, (SBR_NOISE_FLOOR_OFFSET - ptr_noise_lvl_left[i]));
    pow_right = (FLOAT32)pow(2.0f, (SBR_NOISE_FLOOR_OFFSET - ptr_noise_lvl_right[i]));

    ptr_noise_lvl_right[i] -= ptr_noise_lvl_left[i];
    ptr_noise_lvl_left[i] =
        (FLOAT32)(SBR_NOISE_FLOOR_OFFSET - log((pow_left * pow_right) / 2) * SBR_INV_LOG_2);
    i++;
  }
}

static IA_ERRORCODE ixheaace_calculate_sbr_envelope(
    FLOAT32 **ptr_y_buf_left, FLOAT32 **ptr_y_buf_right,
    const ixheaace_str_frame_info_sbr *pstr_const_frame_info, WORD32 *ptr_sfb_ene_l,
    WORD32 *ptr_sfb_ene_r, ixheaace_pstr_sbr_config_data pstr_sbr_cfg,
    ixheaace_pstr_enc_channel pstr_sbr, ixheaace_sbr_stereo_mode stereo_mode,
    WORD32 *ptr_max_quant_err) {
  WORD32 i, j, k, l, count, m = 0;
  WORD32 num_bands, start_pos, stop_pos, li, ui;
  ixheaace_freq_res freq_res;

  WORD32 ca = 2 - pstr_sbr->enc_env_data.init_sbr_amp_res;
  WORD32 n_envelopes = pstr_const_frame_info->n_envelopes;
  WORD32 short_env = pstr_const_frame_info->short_env - 1;
  WORD32 time_step = pstr_sbr->str_sbr_extract_env.time_step;
  WORD32 missing_harmonic = 0;

  if ((ca != 1) && (ca != 2)) {
    return IA_EXHEAACE_EXE_FATAL_SBR_INVALID_AMP_RES;
  }

  if (stereo_mode == SBR_COUPLING) {
    *ptr_max_quant_err = 0;
  }

  i = 0;
  while (i < n_envelopes) {
    start_pos = time_step * pstr_const_frame_info->borders[i];
    stop_pos = time_step * pstr_const_frame_info->borders[i + 1];
    freq_res = pstr_const_frame_info->freq_res[i];
    num_bands = pstr_sbr_cfg->num_scf[freq_res];

    if (i == short_env) {
      if (pstr_sbr_cfg->is_ld_sbr) {
        WORD32 temp = 2;
        if (temp < time_step) {
          temp = time_step;
        }
        if (stop_pos - start_pos > temp) {
          stop_pos = stop_pos - temp;
        }
      } else {
        stop_pos = stop_pos - time_step;
      }
    }
    for (j = 0; j < num_bands; j++) {
      FLOAT32 energy_left = 0, energy_right = 0, tmp_ene_l = 0, tmp_ene_r = 0;
      li = pstr_sbr_cfg->ptr_freq_band_tab[freq_res][j];
      ui = pstr_sbr_cfg->ptr_freq_band_tab[freq_res][j + 1];

      if ((freq_res == FREQ_RES_HIGH) && (j == 0 && ui - li > 1)) {
        li++;
      } else {
        if (j == 0 && ui - li > 2) {
          li++;
        }
      }

      missing_harmonic = 0;

      if (pstr_sbr->enc_env_data.add_harmonic_flag) {
        if (freq_res == FREQ_RES_HIGH) {
          if (pstr_sbr->enc_env_data.add_harmonic[j]) {
            missing_harmonic = 1;
          }
        } else {
          WORD32 band;
          WORD32 start_band_high = 0;
          WORD32 stop_band_high = 0;

          while (pstr_sbr_cfg->ptr_freq_band_tab[FREQ_RES_HIGH][start_band_high] <
                 pstr_sbr_cfg->ptr_freq_band_tab[FREQ_RES_LOW][j]) {
            start_band_high++;
          }

          while (pstr_sbr_cfg->ptr_freq_band_tab[FREQ_RES_HIGH][stop_band_high] <
                 pstr_sbr_cfg->ptr_freq_band_tab[FREQ_RES_LOW][j + 1]) {
            stop_band_high++;
          }

          for (band = start_band_high; band < stop_band_high; band++) {
            if (pstr_sbr->enc_env_data.add_harmonic[band]) {
              missing_harmonic = 1;
            }
          }
        }
      }

      if (missing_harmonic) {
        count = stop_pos - start_pos;
        for (l = start_pos; l < stop_pos; l++) {
          energy_left += ptr_y_buf_left[l / 2][li];
        }

        k = li + 1;
        while (k < ui) {
          tmp_ene_l = 0.0f;
          for (l = start_pos; l < stop_pos; l++) {
            tmp_ene_l += ptr_y_buf_left[l / 2][k];
          }

          if (tmp_ene_l > energy_left) {
            energy_left = tmp_ene_l;
          }
          k++;
        }

        if (ui - li > 2) {
          energy_left = energy_left * 0.398107267f;
        } else {
          if (ui - li > 1) {
            energy_left = energy_left * 0.5f;
          }
        }

        if (stereo_mode == SBR_COUPLING) {
          for (l = start_pos; l < stop_pos; l++) {
            energy_right += ptr_y_buf_right[l / 2][li];
          }

          k = li + 1;
          while (k < ui) {
            tmp_ene_r = 0.0f;
            for (l = start_pos; l < stop_pos; l++) {
              tmp_ene_r += ptr_y_buf_right[l / 2][k];
            }

            if (tmp_ene_r > energy_right) {
              energy_right = tmp_ene_r;
            }
            k++;
          }

          if (ui - li > 2) {
            energy_right = energy_right * 0.398107267f;
          } else {
            if (ui - li > 1) {
              energy_right = energy_right * 0.5f;
            }
          }

          tmp_ene_l = energy_left;
          energy_left = (energy_left + energy_right) * 0.5f;
          energy_right = (tmp_ene_l + 1) / (energy_right + 1);
        }
      } else {
        count = (stop_pos - start_pos) * (ui - li);

        k = li;
        while (k < ui) {
          for (l = start_pos; l < stop_pos; l++) {
            if (pstr_sbr_cfg->is_ld_sbr) {
              energy_left += ptr_y_buf_left[l][k];
            } else {
              energy_left += ptr_y_buf_left[l / 2][k];
            }
          }
          k++;
        }

        if (stereo_mode == SBR_COUPLING) {
          k = li;
          while (k < ui) {
            for (l = start_pos; l < stop_pos; l++) {
              energy_right += ptr_y_buf_right[l / 2][k];
            }
            k++;
          }
          tmp_ene_l = energy_left;
          energy_left = (energy_left + energy_right) * 0.5f;
          energy_right = (tmp_ene_l + 1) / (energy_right + 1);
        }
      }

      energy_left = (FLOAT32)(log(energy_left / (count * 64) + EPS) * SBR_INV_LOG_2);

      if (energy_left < 0.0f) {
        energy_left = 0.0f;
      }

      ptr_sfb_ene_l[m] = (WORD32)(ca * energy_left + 0.5);

      if (stereo_mode == SBR_COUPLING) {
        WORD32 quant_err;
        energy_right = (FLOAT32)(log(energy_right) * SBR_INV_LOG_2);
        ptr_sfb_ene_r[m] =
            ixheaace_map_panorama((WORD32)((FLOAT32)ca * energy_right),
                                  pstr_sbr->enc_env_data.init_sbr_amp_res, &quant_err);
        if (quant_err > *ptr_max_quant_err) {
          *ptr_max_quant_err = quant_err;
        }
      }
      m++;
    }

    if (pstr_sbr_cfg->use_parametric_coding) {
      m -= num_bands;

      for (j = 0; j < num_bands; j++) {
        if (freq_res == FREQ_RES_HIGH && pstr_sbr->str_sbr_extract_env.envelope_compensation[j]) {
          ptr_sfb_ene_l[m] -= (WORD32)(
              ca * ixheaac_abs32(pstr_sbr->str_sbr_extract_env.envelope_compensation[j]));
        }

        if (ptr_sfb_ene_l[m] < 0) {
          ptr_sfb_ene_l[m] = 0;
        }
        m++;
      }
    }
    i++;
  }
  return IA_NO_ERROR;
}
static WORD32 ixheaace_get_pitch_bin_deint(FLOAT32 *ptr_fft_data_real, FLOAT32 *ptr_fft_data_im,
                                           const WORD32 *ptr_sfb_tab, WORD32 is_4_1) {
  WORD32 i, j = 0, k = 0;
  WORD32 bin = -1;
  FLOAT32 tmp, prev_val = 0.0f;

  while (ptr_sfb_tab[j] != -1) {
    WORD32 size = ptr_sfb_tab[j];
    tmp = 0;

    for (i = 0; i < size; i++) {
      tmp += ptr_fft_data_real[k / 2] * ptr_fft_data_real[k / 2];
      tmp += ptr_fft_data_im[k / 2] * ptr_fft_data_im[k / 2];
      k += 2;
    }

    tmp = (FLOAT32)log(max(MIN_FLT_VAL, (tmp / (FLOAT32)size)));
    if (j != 0) {
      if (fabs(tmp - prev_val) >= 3.0f) {
        if (1 == is_4_1) {
          bin = ((k - (ptr_sfb_tab[j] * 2)) * 3) / 8;
        } else {
          bin = ((k - (ptr_sfb_tab[j] * 2)) * 3) / 4;
        }
        if (bin > 127) {
          bin = -1;
        }
        break;
      }
    }
    prev_val = tmp;
    j++;
  }

  return bin;
}
static WORD32 ixheaace_get_pitch_bin(FLOAT32 *fft_data, const WORD32 *ptr_sfb_tab,
                                     WORD32 is_4_1) {
  WORD32 i, j = 0, k = 0;
  WORD32 bin = -1;
  FLOAT32 tmp, prev_val = 0;

  while (ptr_sfb_tab[j] != -1) {
    WORD32 size = ptr_sfb_tab[j];
    tmp = 0;

    for (i = 0; i < size; i++) {
      tmp += fft_data[k] * fft_data[k];
      tmp += fft_data[k + 1] * fft_data[k + 1];
      k += 2;
    }

    tmp = (FLOAT32)log(MAX(MIN_FLT_VAL, (tmp / (FLOAT32)size)));
    if (j != 0) {
      if (fabs(tmp - prev_val) >= 3.0f) {
        if (1 == is_4_1) {
          bin = ((k - (ptr_sfb_tab[j] * 2)) * 3) / 8;
        } else {
          bin = ((k - (ptr_sfb_tab[j] * 2)) * 3) / 4;
        }
        if (bin > 127) {
          bin = -1;
        }
        break;
      }
    }
    prev_val = tmp;
    j++;
  }

  return bin;
}
static IA_ERRORCODE ixheaace_hbe_get_pitch_bins(FLOAT32 *ptr_time_in,
                                                ixheaace_pstr_sbr_config_data pstr_sbr_cfg,
                                                FLOAT32 *ptr_esbr_scr,
                                                ixheaace_str_sbr_tabs *ptr_sbr_tab,
                                                WORD32 time_sn_stride, WORD32 num_samples,
                                                WORD32 *bin1, WORD32 *bin2) {
  const WORD32 *ptr_sbr_table = NULL;
  FLOAT32 *ptr_esbr_inp = ptr_esbr_scr;
  ptr_esbr_scr += num_samples * 2;
  FLOAT32 *ptr_esbr_inp_i = ptr_esbr_inp + num_samples;
  FLOAT32 *ptr_scratch_fft = ptr_esbr_scr;
  WORD32 idx, sf, is_4_1 = 0;

  sf = pstr_sbr_cfg->sample_freq;
  if (IXHEAACE_MAX_NUM_SAMPLES == num_samples) {
    sf = sf >> 1;
    is_4_1 = 1;
  }

  switch (sf) {
    case 16000:
      ptr_sbr_table = ptr_sbr_tab->ptr_esbr_sfb_tab->sfb_bins_8k;
      break;
    case 22050:
      ptr_sbr_table = ptr_sbr_tab->ptr_esbr_sfb_tab->sfb_bins_11k;
      break;
    case 24000:
      ptr_sbr_table = ptr_sbr_tab->ptr_esbr_sfb_tab->sfb_bins_12k;
      break;
    case 32000:
      ptr_sbr_table = ptr_sbr_tab->ptr_esbr_sfb_tab->sfb_bins_16k;
      break;
    case 44100:
      ptr_sbr_table = ptr_sbr_tab->ptr_esbr_sfb_tab->sfb_bins_22k;
      break;
    case 48000:
      ptr_sbr_table = ptr_sbr_tab->ptr_esbr_sfb_tab->sfb_bins_24k;
      break;
    default:
      return IA_EXHEAACE_EXE_FATAL_SBR_INVALID_SAMP_FREQ;
  }
  if (1 == pstr_sbr_cfg->num_ch) {
    if (num_samples == 2048) {
      for (idx = 0; idx < num_samples; idx += 2) {
        ptr_esbr_inp[idx] = ptr_time_in[time_sn_stride * idx];
        ptr_esbr_inp[idx + 1] = 0;
        ptr_esbr_inp[num_samples + idx] = ptr_time_in[time_sn_stride * (idx + 1)];
        ptr_esbr_inp[num_samples + idx + 1] = 0;
      }
      iusace_complex_fft_2048(ptr_esbr_inp, ptr_scratch_fft);
      *bin1 = ixheaace_get_pitch_bin(ptr_esbr_inp, ptr_sbr_table, is_4_1);
    } else if (num_samples == IXHEAACE_MAX_NUM_SAMPLES) {
      memset(ptr_esbr_inp_i, 0, num_samples * sizeof(ptr_esbr_inp_i[0]));
      for (idx = 0; idx < num_samples; idx += 2) {
        ptr_esbr_inp[idx / 2] = ptr_time_in[time_sn_stride * idx];
        ptr_esbr_inp[(num_samples + idx) / 2] = ptr_time_in[time_sn_stride * (idx + 1)];
      }
      iusace_complex_fft_4096(ptr_esbr_inp, ptr_esbr_inp_i, ptr_scratch_fft);
      *bin1 = ixheaace_get_pitch_bin_deint(ptr_esbr_inp, ptr_esbr_inp_i, ptr_sbr_table, is_4_1);
    }
  } else {
    if (num_samples == 2048) {
      for (idx = 0; idx < num_samples; idx += 2) {
        ptr_esbr_inp[idx] = ptr_time_in[2 * idx];
        ptr_esbr_inp[idx + 1] = 0;
        ptr_esbr_inp[num_samples + idx] = ptr_time_in[2 * idx + 2];
        ptr_esbr_inp[num_samples + idx + 1] = 0;
      }
      iusace_complex_fft_2048(ptr_esbr_inp, ptr_scratch_fft);
      *bin1 = ixheaace_get_pitch_bin(ptr_esbr_inp, ptr_sbr_table, is_4_1);

      for (idx = 0; idx < num_samples; idx += 2) {
        ptr_esbr_inp[idx] = ptr_time_in[2 * idx + 1];
        ptr_esbr_inp[idx + 1] = 0;
        ptr_esbr_inp[num_samples + idx] = ptr_time_in[2 * idx + 3];
        ptr_esbr_inp[num_samples + idx + 1] = 0;
      }
      iusace_complex_fft_2048(ptr_esbr_inp, ptr_scratch_fft);
      *bin2 = ixheaace_get_pitch_bin(ptr_esbr_inp, ptr_sbr_table, is_4_1);
    } else if (num_samples == IXHEAACE_MAX_NUM_SAMPLES) {
      memset(ptr_esbr_inp_i, 0, num_samples * sizeof(ptr_esbr_inp_i[0]));
      for (idx = 0; idx < num_samples; idx += 2) {
        ptr_esbr_inp[idx / 2] = ptr_time_in[2 * idx];
        ptr_esbr_inp[(num_samples + idx) / 2] = ptr_time_in[2 * idx + 2];
      }
      iusace_complex_fft_4096(ptr_esbr_inp, ptr_esbr_inp_i, ptr_scratch_fft);
      *bin1 = ixheaace_get_pitch_bin_deint(ptr_esbr_inp, ptr_esbr_inp_i, ptr_sbr_table, is_4_1);

      memset(ptr_esbr_inp_i, 0, num_samples * sizeof(ptr_esbr_inp_i[0]));
      for (idx = 0; idx < num_samples; idx += 2) {
        ptr_esbr_inp[idx / 2] = ptr_time_in[2 * idx + 1];
        ptr_esbr_inp[(num_samples + idx) / 2] = ptr_time_in[2 * idx + 3];
      }
      iusace_complex_fft_4096(ptr_esbr_inp, ptr_esbr_inp_i, ptr_scratch_fft);
      *bin2 = ixheaace_get_pitch_bin_deint(ptr_esbr_inp, ptr_esbr_inp_i, ptr_sbr_table, is_4_1);
    }
  }
  return IA_NO_ERROR;
}
static IA_ERRORCODE ixheaace_update_esbr_ext_data(
    FLOAT32 *ptr_time_in, ixheaace_pstr_sbr_config_data pstr_sbr_cfg, FLOAT32 *ptr_esbr_scr,
    ixheaace_str_esbr_bs_data *pstr_esbr, WORD32 transient_info[][3],
    ixheaace_str_sbr_tabs *ptr_sbr_tab, WORD32 coupling, WORD32 time_sn_stride,
    WORD32 num_samples) {
  WORD32 bin, bin1;
  const WORD32 *ptr_sbr_table = NULL;
  FLOAT32 *ptr_esbr_inp = ptr_esbr_scr;
  ptr_esbr_scr += num_samples * 2;
  FLOAT32 *ptr_scratch_fft = ptr_esbr_scr;
  WORD32 idx;
  switch (pstr_sbr_cfg->sample_freq) {
    case 16000:
      ptr_sbr_table = ptr_sbr_tab->ptr_esbr_sfb_tab->sfb_bins_8k;
      break;
    case 22050:
      ptr_sbr_table = ptr_sbr_tab->ptr_esbr_sfb_tab->sfb_bins_11k;
      break;
    case 24000:
      ptr_sbr_table = ptr_sbr_tab->ptr_esbr_sfb_tab->sfb_bins_12k;
      break;
    case 32000:
      ptr_sbr_table = ptr_sbr_tab->ptr_esbr_sfb_tab->sfb_bins_16k;
      break;
    case 44100:
      ptr_sbr_table = ptr_sbr_tab->ptr_esbr_sfb_tab->sfb_bins_22k;
      break;
    case 48000:
      ptr_sbr_table = ptr_sbr_tab->ptr_esbr_sfb_tab->sfb_bins_24k;
      break;
    default:
      return IA_EXHEAACE_EXE_FATAL_SBR_INVALID_SAMP_FREQ;
  }
  if (1 == pstr_sbr_cfg->num_ch) {
    for (idx = 0; idx < num_samples; idx += 2) {
      ptr_esbr_inp[idx] = ptr_time_in[time_sn_stride * idx];
      ptr_esbr_inp[idx + 1] = 0;
      ptr_esbr_inp[num_samples + idx] = ptr_time_in[time_sn_stride * (idx + 1)];
      ptr_esbr_inp[num_samples + idx + 1] = 0;
    }
    iusace_complex_fft_2048(ptr_esbr_inp, ptr_scratch_fft);
    bin = ixheaace_get_pitch_bin(ptr_esbr_inp, ptr_sbr_table, 0);
    pstr_esbr->sbr_num_chan = 1;
    if (transient_info[0][1] != 0) {
      pstr_esbr->sbr_preprocessing = 1;
    } else {
      pstr_esbr->sbr_preprocessing = 0;
    }

    if (transient_info[0][1] != 0 && bin != -1) {
      pstr_esbr->sbr_oversampling_flag[0] = 1;
      pstr_esbr->sbr_patching_mode[0] = 0;
      pstr_esbr->sbr_pitchin_flags[0] = 1;
      pstr_esbr->sbr_pitchin_bins[0] = (UWORD8)MIN(bin, 127);
    } else if (bin != -1) {
      pstr_esbr->sbr_oversampling_flag[0] = 0;
      pstr_esbr->sbr_patching_mode[0] = 0;
      pstr_esbr->sbr_pitchin_flags[0] = 1;
      pstr_esbr->sbr_pitchin_bins[0] = (UWORD8)MIN(bin, 127);
    } else if (transient_info[0][1] != 0) {
      pstr_esbr->sbr_oversampling_flag[0] = 1;
      pstr_esbr->sbr_patching_mode[0] = 0;
      pstr_esbr->sbr_pitchin_flags[0] = 0;
    } else {
      pstr_esbr->sbr_patching_mode[0] = 1;
    }
  } else {
    pstr_esbr->sbr_num_chan = 2;
    pstr_esbr->sbr_coupling = coupling;
    for (idx = 0; idx < num_samples; idx += 2) {
      ptr_esbr_inp[idx] = ptr_time_in[2 * idx];
      ptr_esbr_inp[idx + 1] = 0;
      ptr_esbr_inp[num_samples + idx] = ptr_time_in[2 * idx + 2];
      ptr_esbr_inp[num_samples + idx + 1] = 0;
    }
    iusace_complex_fft_2048(ptr_esbr_inp, ptr_scratch_fft);
    bin = ixheaace_get_pitch_bin(ptr_esbr_inp, ptr_sbr_table, 0);
    for (idx = 0; idx < num_samples; idx += 2) {
      ptr_esbr_inp[idx] = ptr_time_in[2 * idx + 1];
      ptr_esbr_inp[idx + 1] = 0;
      ptr_esbr_inp[num_samples + idx] = ptr_time_in[2 * idx + 3];
      ptr_esbr_inp[num_samples + idx + 1] = 0;
    }
    iusace_complex_fft_2048(ptr_esbr_inp, ptr_scratch_fft);
    bin1 = ixheaace_get_pitch_bin(ptr_esbr_inp, ptr_sbr_table, 0);

    if (coupling) {
      if ((transient_info[0][1] != 0 || transient_info[1][1] != 0)) {
        pstr_esbr->sbr_preprocessing = 1;
      } else {
        pstr_esbr->sbr_preprocessing = 0;
      }
      if ((transient_info[0][1] != 0 || transient_info[1][1] != 0) && bin != -1) {
        pstr_esbr->sbr_oversampling_flag[0] = 1;
        pstr_esbr->sbr_patching_mode[0] = 0;
        pstr_esbr->sbr_pitchin_flags[0] = 1;
        bin = MIN(bin, bin1);
        pstr_esbr->sbr_pitchin_bins[0] = (UWORD8)MIN(bin, 127);
      } else if (bin != -1) {
        pstr_esbr->sbr_oversampling_flag[0] = 0;
        pstr_esbr->sbr_patching_mode[0] = 0;
        pstr_esbr->sbr_pitchin_flags[0] = 1;
        bin = MIN(bin, bin1);
        pstr_esbr->sbr_pitchin_bins[0] = (UWORD8)MIN(bin, 127);
      } else if ((transient_info[0][1] != 0 || transient_info[1][1] != 0)) {
        pstr_esbr->sbr_oversampling_flag[0] = 1;
        pstr_esbr->sbr_patching_mode[0] = 0;
        pstr_esbr->sbr_pitchin_flags[0] = 0;
      } else {
        pstr_esbr->sbr_patching_mode[0] = 1;
      }
    } else {
      pstr_esbr->sbr_preprocessing = 0;
      if ((transient_info[0][1] != 0 || transient_info[1][1] != 0)) {
        pstr_esbr->sbr_preprocessing = 1;
      }

      if (transient_info[0][1] != 0 && bin != -1) {
        pstr_esbr->sbr_oversampling_flag[0] = 1;
        pstr_esbr->sbr_patching_mode[0] = 0;
        pstr_esbr->sbr_pitchin_flags[0] = 1;
        bin = MIN(bin, bin1);
        pstr_esbr->sbr_pitchin_bins[0] = (UWORD8)MIN(bin, 127);
      } else if (bin != -1) {
        pstr_esbr->sbr_oversampling_flag[0] = 0;
        pstr_esbr->sbr_patching_mode[0] = 0;
        pstr_esbr->sbr_pitchin_flags[0] = 1;
        pstr_esbr->sbr_pitchin_bins[0] = (UWORD8)MIN(bin, 127);
      } else if (transient_info[0][1] != 0) {
        pstr_esbr->sbr_oversampling_flag[0] = 1;
        pstr_esbr->sbr_patching_mode[0] = 0;
        pstr_esbr->sbr_pitchin_flags[0] = 0;
      } else {
        pstr_esbr->sbr_patching_mode[0] = 1;
      }

      if (transient_info[1][1] != 0 && bin1 != -1) {
        pstr_esbr->sbr_oversampling_flag[1] = 1;
        pstr_esbr->sbr_patching_mode[1] = 0;
        pstr_esbr->sbr_pitchin_flags[1] = 1;
        pstr_esbr->sbr_pitchin_bins[1] = (UWORD8)MIN(bin1, 127);
      } else if (bin1 != -1) {
        pstr_esbr->sbr_oversampling_flag[1] = 0;
        pstr_esbr->sbr_patching_mode[1] = 0;
        pstr_esbr->sbr_pitchin_flags[1] = 1;
        pstr_esbr->sbr_pitchin_bins[1] = (UWORD8)MIN(bin1, 127);
      } else if (transient_info[1][1] != 0) {
        pstr_esbr->sbr_oversampling_flag[1] = 1;
        pstr_esbr->sbr_patching_mode[1] = 0;
        pstr_esbr->sbr_pitchin_flags[1] = 0;
      } else {
        pstr_esbr->sbr_patching_mode[1] = 1;
      }
    }
  }
  return IA_NO_ERROR;
}

static VOID ixheaace_update_harmonic_sbr_data(
    WORD32 transient_info[][3], WORD32 coupling,
    ixheaace_pstr_enc_channel *pstr_enc_ch, WORD32 num_channels) {
  WORD32 bin, bin1;
  struct ixheaace_str_sbr_env_data *pstr_sbr_env_left = NULL;
  struct ixheaace_str_sbr_env_data *pstr_sbr_env_right = NULL;
  if (1 == num_channels) {
    pstr_sbr_env_left = &pstr_enc_ch[0]->enc_env_data;
    bin = pstr_sbr_env_left->sbr_pitchin_bins;
    if (transient_info[0][1] != 0) {
      pstr_sbr_env_left->sbr_preprocessing = 1;
    } else {
      pstr_sbr_env_left->sbr_preprocessing = 0;
    }

    if (transient_info[0][1] != 0 && bin != -1) {
      pstr_sbr_env_left->sbr_oversampling_flag = 1;
      pstr_sbr_env_left->sbr_patching_mode = 0;
      pstr_sbr_env_left->sbr_pitchin_bins_flag = 1;
      pstr_sbr_env_left->sbr_pitchin_bins = min(bin, 127);
    } else if (bin != -1) {
      pstr_sbr_env_left->sbr_oversampling_flag = 0;
      pstr_sbr_env_left->sbr_patching_mode = 0;
      pstr_sbr_env_left->sbr_pitchin_bins_flag = 1;
      pstr_sbr_env_left->sbr_pitchin_bins = min(bin, 127);
    } else if (transient_info[0][1] != 0) {
      pstr_sbr_env_left->sbr_oversampling_flag = 1;
      pstr_sbr_env_left->sbr_patching_mode = 0;
      pstr_sbr_env_left->sbr_pitchin_bins = 0;
    } else {
      pstr_sbr_env_left->sbr_patching_mode = 1;
    }
  } else {
    pstr_sbr_env_left = &pstr_enc_ch[0]->enc_env_data;
    pstr_sbr_env_right = &pstr_enc_ch[1]->enc_env_data;
    pstr_sbr_env_left->sbr_coupling = coupling;
    pstr_sbr_env_right->sbr_coupling = coupling;
    bin = pstr_sbr_env_left->sbr_pitchin_bins;

    bin1 = pstr_sbr_env_right->sbr_pitchin_bins;

    if (coupling) {
      pstr_sbr_env_right->sbr_preprocessing = 1;
      if ((transient_info[0][1] != 0 || transient_info[1][1] != 0)) {
        pstr_sbr_env_left->sbr_preprocessing = 1;
      } else {
        pstr_sbr_env_left->sbr_preprocessing = 0;
      }
      if ((transient_info[0][1] != 0 || transient_info[1][1] != 0) && bin != -1) {
        pstr_sbr_env_left->sbr_oversampling_flag = 1;
        pstr_sbr_env_left->sbr_patching_mode = 0;
        pstr_sbr_env_left->sbr_pitchin_bins_flag = 1;
        bin = min(bin, bin1);
        pstr_sbr_env_left->sbr_pitchin_bins = min(bin, 127);
      } else if (bin != -1) {
        pstr_sbr_env_left->sbr_oversampling_flag = 0;
        pstr_sbr_env_left->sbr_patching_mode = 0;
        pstr_sbr_env_left->sbr_pitchin_bins_flag = 1;
        bin = min(bin, bin1);
        pstr_sbr_env_left->sbr_pitchin_bins = min(bin, 127);
      } else if ((transient_info[0][1] != 0 || transient_info[1][1] != 0)) {
        pstr_sbr_env_left->sbr_oversampling_flag = 1;
        pstr_sbr_env_left->sbr_patching_mode = 0;
        pstr_sbr_env_left->sbr_pitchin_bins_flag = 0;
      } else {
        pstr_sbr_env_left->sbr_patching_mode = 1;
      }
    } else {
      pstr_sbr_env_left->sbr_preprocessing = 0;
      pstr_sbr_env_right->sbr_preprocessing = 0;
      if ((transient_info[0][1] != 0 || transient_info[1][1] != 0)) {
        pstr_sbr_env_left->sbr_preprocessing = 1;
        pstr_sbr_env_right->sbr_preprocessing = 1;
      }

      if (transient_info[0][1] != 0 && bin != -1) {
        pstr_sbr_env_left->sbr_oversampling_flag = 1;
        pstr_sbr_env_left->sbr_patching_mode = 0;
        pstr_sbr_env_left->sbr_pitchin_bins_flag = 1;
        bin = min(bin, bin1);
        pstr_sbr_env_left->sbr_pitchin_bins = min(bin, 127);
      } else if (bin != -1) {
        pstr_sbr_env_left->sbr_oversampling_flag = 0;
        pstr_sbr_env_left->sbr_patching_mode = 0;
        pstr_sbr_env_left->sbr_pitchin_bins_flag = 1;
        pstr_sbr_env_left->sbr_pitchin_bins = min(bin, 127);
      } else if (transient_info[0][1] != 0) {
        pstr_sbr_env_left->sbr_oversampling_flag = 1;
        pstr_sbr_env_left->sbr_patching_mode = 0;
        pstr_sbr_env_left->sbr_pitchin_bins_flag = 0;
      } else {
        pstr_sbr_env_left->sbr_patching_mode = 1;
      }

      if (transient_info[1][1] != 0 && bin1 != -1) {
        pstr_sbr_env_right->sbr_oversampling_flag = 1;
        pstr_sbr_env_right->sbr_patching_mode = 0;
        pstr_sbr_env_right->sbr_pitchin_bins_flag = 1;
        pstr_sbr_env_right->sbr_pitchin_bins = bin1 < 127 ? bin1 : 127;
      } else if (bin1 != -1) {
        pstr_sbr_env_right->sbr_oversampling_flag = 0;
        pstr_sbr_env_right->sbr_patching_mode = 0;
        pstr_sbr_env_right->sbr_pitchin_bins_flag = 1;
        pstr_sbr_env_right->sbr_pitchin_bins = bin1 < 127 ? bin1 : 127;
      } else if (transient_info[1][1] != 0) {
        pstr_sbr_env_right->sbr_oversampling_flag = 1;
        pstr_sbr_env_right->sbr_patching_mode = 0;
        pstr_sbr_env_right->sbr_pitchin_bins_flag = 0;
      } else {
        pstr_sbr_env_right->sbr_patching_mode = 1;
      }
    }
  }
}

VOID ixheaace_esbr_qmf_init(ia_sbr_qmf_filter_bank_struct *pstr_codec_qmf_bank,
                            WORD32 sbr_ratio_idx, WORD32 output_frame_size) {
  pstr_codec_qmf_bank->pstr_qmf_dec_tabs =
      (ixheaace_str_qmf_dec_tabs_struct *)&ixheaace_str_aac_qmf_tabs;
  memset(
      pstr_codec_qmf_bank->anal_filter_states_32, 0,
      sizeof(pstr_codec_qmf_bank->anal_filter_states_32[0]) * IXHEAACE_QMF_FILTER_STATE_ANA_SIZE);
  pstr_codec_qmf_bank->num_time_slots = (WORD16)(output_frame_size / 64);
  pstr_codec_qmf_bank->ptr_filter_pos_32 = ixheaace_str_aac_qmf_tabs.esbr_qmf_c;
  pstr_codec_qmf_bank->ptr_state_new_samples_pos_low_32 =
      pstr_codec_qmf_bank->anal_filter_states_32;
  pstr_codec_qmf_bank->ptr_ana_win_coeff_32 = ixheaace_str_aac_qmf_tabs.esbr_qmf_c;

  switch (sbr_ratio_idx) {
    case USAC_SBR_RATIO_INDEX_2_1:
      pstr_codec_qmf_bank->no_channels = 32;
      pstr_codec_qmf_bank->ptr_esbr_cos_twiddle =
          ixheaace_str_aac_qmf_tabs.esbr_sin_cos_twiddle_l32;
      pstr_codec_qmf_bank->ptr_esbr_alt_sin_twiddle =
          ixheaace_str_aac_qmf_tabs.esbr_alt_sin_twiddle_l32;
      pstr_codec_qmf_bank->ptr_esbr_t_cos = ixheaace_str_aac_qmf_tabs.esbr_t_cos_sin_l32;
      break;
    case USAC_SBR_RATIO_INDEX_8_3:
      pstr_codec_qmf_bank->no_channels = 24;
      pstr_codec_qmf_bank->ptr_filter_pos_32 = ixheaace_str_aac_qmf_tabs.esbr_qmf_c_24;
      pstr_codec_qmf_bank->ptr_ana_win_coeff_32 = ixheaace_str_aac_qmf_tabs.esbr_qmf_c_24;
      pstr_codec_qmf_bank->ptr_esbr_cos_twiddle =
          ixheaace_str_aac_qmf_tabs.esbr_sin_cos_twiddle_l24;
      pstr_codec_qmf_bank->ptr_esbr_alt_sin_twiddle =
          ixheaace_str_aac_qmf_tabs.esbr_alt_sin_twiddle_l24;
      pstr_codec_qmf_bank->ptr_esbr_t_cos = ixheaace_str_aac_qmf_tabs.esbr_t_cos_sin_l24;
      break;
    case USAC_SBR_RATIO_INDEX_4_1:
      pstr_codec_qmf_bank->no_channels = 16;
      pstr_codec_qmf_bank->ptr_esbr_cos_twiddle =
          ixheaace_str_aac_qmf_tabs.esbr_sin_cos_twiddle_l16;
      pstr_codec_qmf_bank->ptr_esbr_alt_sin_twiddle =
          ixheaace_str_aac_qmf_tabs.esbr_alt_sin_twiddle_l16;
      pstr_codec_qmf_bank->ptr_esbr_t_cos = ixheaace_str_aac_qmf_tabs.esbr_t_cos_sin_l16;
      break;
    default:
      pstr_codec_qmf_bank->no_channels = 32;
      pstr_codec_qmf_bank->ptr_esbr_cos_twiddle =
          ixheaace_str_aac_qmf_tabs.esbr_sin_cos_twiddle_l32;
      pstr_codec_qmf_bank->ptr_esbr_alt_sin_twiddle =
          ixheaace_str_aac_qmf_tabs.esbr_alt_sin_twiddle_l32;
      pstr_codec_qmf_bank->ptr_esbr_t_cos = ixheaace_str_aac_qmf_tabs.esbr_t_cos_sin_l32;
      break;
  }
}
VOID ixheaace_esbr_qmfanal32_winadd(FLOAT32 *ptr_inp1, FLOAT32 *ptr_inp2, FLOAT32 *ptr_qmf1,
                                    FLOAT32 *ptr_qmf2, FLOAT32 *ptr_out,
                                    WORD32 num_band_anal_qmf) {
  WORD32 n;
  FLOAT32 accu;

  switch (num_band_anal_qmf) {
    case 32: {
      n = 0;
      while (n < num_band_anal_qmf) {
        accu = (ptr_inp1[n + 0] * ptr_qmf1[2 * (n + 0)]);
        accu += (ptr_inp1[n + 2 * num_band_anal_qmf] * ptr_qmf1[2 * (n + 2 * num_band_anal_qmf)]);
        accu += (ptr_inp1[n + 4 * num_band_anal_qmf] * ptr_qmf1[2 * (n + 4 * num_band_anal_qmf)]);
        accu += (ptr_inp1[n + 6 * num_band_anal_qmf] * ptr_qmf1[2 * (n + 6 * num_band_anal_qmf)]);
        accu += (ptr_inp1[n + 8 * num_band_anal_qmf] * ptr_qmf1[2 * (n + 8 * num_band_anal_qmf)]);
        ptr_out[n] = 2 * accu;

        accu = (ptr_inp1[n + 1 + 0] * ptr_qmf1[2 * (n + 1 + 0)]);
        accu += (ptr_inp1[n + 1 + 2 * num_band_anal_qmf] *
                 ptr_qmf1[2 * (n + 1 + 2 * num_band_anal_qmf)]);
        accu += (ptr_inp1[n + 1 + 4 * num_band_anal_qmf] *
                 ptr_qmf1[2 * (n + 1 + 4 * num_band_anal_qmf)]);
        accu += (ptr_inp1[n + 1 + 6 * num_band_anal_qmf] *
                 ptr_qmf1[2 * (n + 1 + 6 * num_band_anal_qmf)]);
        accu += (ptr_inp1[n + 1 + 8 * num_band_anal_qmf] *
                 ptr_qmf1[2 * (n + 1 + 8 * num_band_anal_qmf)]);
        ptr_out[n + 1] = 2 * accu;

        accu = (ptr_inp2[n + 0] * ptr_qmf2[2 * (n + 0)]);
        accu += (ptr_inp2[n + 2 * num_band_anal_qmf] * ptr_qmf2[2 * (n + 2 * num_band_anal_qmf)]);
        accu += (ptr_inp2[n + 4 * num_band_anal_qmf] * ptr_qmf2[2 * (n + 4 * num_band_anal_qmf)]);
        accu += (ptr_inp2[n + 6 * num_band_anal_qmf] * ptr_qmf2[2 * (n + 6 * num_band_anal_qmf)]);
        accu += (ptr_inp2[n + 8 * num_band_anal_qmf] * ptr_qmf2[2 * (n + 8 * num_band_anal_qmf)]);
        ptr_out[n + num_band_anal_qmf] = 2 * accu;

        accu = (ptr_inp2[n + 1 + 0] * ptr_qmf2[2 * (n + 1 + 0)]);
        accu += (ptr_inp2[n + 1 + 2 * num_band_anal_qmf] *
                 ptr_qmf2[2 * (n + 1 + 2 * num_band_anal_qmf)]);
        accu += (ptr_inp2[n + 1 + 4 * num_band_anal_qmf] *
                 ptr_qmf2[2 * (n + 1 + 4 * num_band_anal_qmf)]);
        accu += (ptr_inp2[n + 1 + 6 * num_band_anal_qmf] *
                 ptr_qmf2[2 * (n + 1 + 6 * num_band_anal_qmf)]);
        accu += (ptr_inp2[n + 1 + 8 * num_band_anal_qmf] *
                 ptr_qmf2[2 * (n + 1 + 8 * num_band_anal_qmf)]);
        ptr_out[n + 1 + num_band_anal_qmf] = 2 * accu;

        n += 2;
      }
      break;
    }
    case 24: {
      n = 0;
      while (n < num_band_anal_qmf) {
        accu = (ptr_inp1[n + 0] * ptr_qmf1[(n + 0)]);
        accu += (ptr_inp1[n + 2 * num_band_anal_qmf] * ptr_qmf1[(n + 2 * num_band_anal_qmf)]);
        accu += (ptr_inp1[n + 4 * num_band_anal_qmf] * ptr_qmf1[(n + 4 * num_band_anal_qmf)]);
        accu += (ptr_inp1[n + 6 * num_band_anal_qmf] * ptr_qmf1[(n + 6 * num_band_anal_qmf)]);
        accu += (ptr_inp1[n + 8 * num_band_anal_qmf] * ptr_qmf1[(n + 8 * num_band_anal_qmf)]);
        ptr_out[n] = 2 * accu;

        accu = (ptr_inp1[n + 1 + 0] * ptr_qmf1[(n + 1 + 0)]);
        accu +=
            (ptr_inp1[n + 1 + 2 * num_band_anal_qmf] * ptr_qmf1[(n + 1 + 2 * num_band_anal_qmf)]);
        accu +=
            (ptr_inp1[n + 1 + 4 * num_band_anal_qmf] * ptr_qmf1[(n + 1 + 4 * num_band_anal_qmf)]);
        accu +=
            (ptr_inp1[n + 1 + 6 * num_band_anal_qmf] * ptr_qmf1[(n + 1 + 6 * num_band_anal_qmf)]);
        accu +=
            (ptr_inp1[n + 1 + 8 * num_band_anal_qmf] * ptr_qmf1[(n + 1 + 8 * num_band_anal_qmf)]);
        ptr_out[n + 1] = 2 * accu;

        accu = (ptr_inp2[n + 0] * ptr_qmf2[(n + 0)]);
        accu += (ptr_inp2[n + 2 * num_band_anal_qmf] * ptr_qmf2[(n + 2 * num_band_anal_qmf)]);
        accu += (ptr_inp2[n + 4 * num_band_anal_qmf] * ptr_qmf2[(n + 4 * num_band_anal_qmf)]);
        accu += (ptr_inp2[n + 6 * num_band_anal_qmf] * ptr_qmf2[(n + 6 * num_band_anal_qmf)]);
        accu += (ptr_inp2[n + 8 * num_band_anal_qmf] * ptr_qmf2[(n + 8 * num_band_anal_qmf)]);
        ptr_out[n + num_band_anal_qmf] = 2 * accu;

        accu = (ptr_inp2[n + 1 + 0] * ptr_qmf2[(n + 1 + 0)]);
        accu +=
            (ptr_inp2[n + 1 + 2 * num_band_anal_qmf] * ptr_qmf2[(n + 1 + 2 * num_band_anal_qmf)]);
        accu +=
            (ptr_inp2[n + 1 + 4 * num_band_anal_qmf] * ptr_qmf2[(n + 1 + 4 * num_band_anal_qmf)]);
        accu +=
            (ptr_inp2[n + 1 + 6 * num_band_anal_qmf] * ptr_qmf2[(n + 1 + 6 * num_band_anal_qmf)]);
        accu +=
            (ptr_inp2[n + 1 + 8 * num_band_anal_qmf] * ptr_qmf2[(n + 1 + 8 * num_band_anal_qmf)]);
        ptr_out[n + 1 + num_band_anal_qmf] = 2 * accu;
        n += 2;
      }
      break;
    }
    default: {
      n = 0;
      while (n < num_band_anal_qmf) {
        accu = (ptr_inp1[n + 0] * ptr_qmf1[4 * (n + 0)]);
        accu += (ptr_inp1[n + 2 * num_band_anal_qmf] * ptr_qmf1[4 * (n + 2 * num_band_anal_qmf)]);
        accu += (ptr_inp1[n + 4 * num_band_anal_qmf] * ptr_qmf1[4 * (n + 4 * num_band_anal_qmf)]);
        accu += (ptr_inp1[n + 6 * num_band_anal_qmf] * ptr_qmf1[4 * (n + 6 * num_band_anal_qmf)]);
        accu += (ptr_inp1[n + 8 * num_band_anal_qmf] * ptr_qmf1[4 * (n + 8 * num_band_anal_qmf)]);
        ptr_out[n] = 2 * accu;

        accu = (ptr_inp1[n + 1 + 0] * ptr_qmf1[4 * (n + 1 + 0)]);
        accu += (ptr_inp1[n + 1 + 2 * num_band_anal_qmf] *
                 ptr_qmf1[4 * (n + 1 + 2 * num_band_anal_qmf)]);
        accu += (ptr_inp1[n + 1 + 4 * num_band_anal_qmf] *
                 ptr_qmf1[4 * (n + 1 + 4 * num_band_anal_qmf)]);
        accu += (ptr_inp1[n + 1 + 6 * num_band_anal_qmf] *
                 ptr_qmf1[4 * (n + 1 + 6 * num_band_anal_qmf)]);
        accu += (ptr_inp1[n + 1 + 8 * num_band_anal_qmf] *
                 ptr_qmf1[4 * (n + 1 + 8 * num_band_anal_qmf)]);
        ptr_out[n + 1] = 2 * accu;

        accu = (ptr_inp2[n + 0] * ptr_qmf2[4 * (n + 0)]);
        accu += (ptr_inp2[n + 2 * num_band_anal_qmf] * ptr_qmf2[4 * (n + 2 * num_band_anal_qmf)]);
        accu += (ptr_inp2[n + 4 * num_band_anal_qmf] * ptr_qmf2[4 * (n + 4 * num_band_anal_qmf)]);
        accu += (ptr_inp2[n + 6 * num_band_anal_qmf] * ptr_qmf2[4 * (n + 6 * num_band_anal_qmf)]);
        accu += (ptr_inp2[n + 8 * num_band_anal_qmf] * ptr_qmf2[4 * (n + 8 * num_band_anal_qmf)]);
        ptr_out[n + num_band_anal_qmf] = 2 * accu;

        accu = (ptr_inp2[n + 1 + 0] * ptr_qmf2[4 * (n + 1 + 0)]);
        accu += (ptr_inp2[n + 1 + 2 * num_band_anal_qmf] *
                 ptr_qmf2[4 * (n + 1 + 2 * num_band_anal_qmf)]);
        accu += (ptr_inp2[n + 1 + 4 * num_band_anal_qmf] *
                 ptr_qmf2[4 * (n + 1 + 4 * num_band_anal_qmf)]);
        accu += (ptr_inp2[n + 1 + 6 * num_band_anal_qmf] *
                 ptr_qmf2[4 * (n + 1 + 6 * num_band_anal_qmf)]);
        accu += (ptr_inp2[n + 1 + 8 * num_band_anal_qmf] *
                 ptr_qmf2[4 * (n + 1 + 8 * num_band_anal_qmf)]);
        ptr_out[n + 1 + num_band_anal_qmf] = 2 * accu;
        n += 2;
      }
      break;
    }
  }
}

VOID ixheaace_esbr_radix4bfly(const FLOAT32 *ptr_w_in, FLOAT32 *ptr_x, WORD32 index1,
                              WORD32 index) {
  int i;
  WORD32 l1, l2, h2, fft_jmp;
  FLOAT32 xt0_0, yt0_0, xt1_0, yt1_0, xt2_0, yt2_0;
  FLOAT32 xh0_0, xh1_0, xh20_0, xh21_0, xl0_0, xl1_0, xl20_0, xl21_0;
  FLOAT32 x_0, x_1, x_l1_0, x_l1_1, x_l2_0, x_l2_1;
  FLOAT32 x_h2_0, x_h2_1;
  FLOAT32 si10, si20, si30, co10, co20, co30;

  FLOAT32 mul_1, mul_2, mul_3, mul_4, mul_5, mul_6;
  FLOAT32 mul_7, mul_8, mul_9, mul_10, mul_11, mul_12;

  const FLOAT32 *ptr_w = ptr_w_in;
  WORD32 i1;

  h2 = index << 1;
  l1 = index << 2;
  l2 = (index << 2) + (index << 1);

  fft_jmp = 6 * (index);

  i1 = 0;
  while (i1 < index1) {
    for (i = 0; i < index; i++) {
      si10 = (*ptr_w++);
      co10 = (*ptr_w++);
      si20 = (*ptr_w++);
      co20 = (*ptr_w++);
      si30 = (*ptr_w++);
      co30 = (*ptr_w++);

      x_0 = ptr_x[0];
      x_h2_0 = ptr_x[h2];
      x_l1_0 = ptr_x[l1];
      x_l2_0 = ptr_x[l2];

      xh0_0 = (x_0 + x_l1_0);
      xl0_0 = (x_0 - x_l1_0);

      xh20_0 = (x_h2_0 + x_l2_0);
      xl20_0 = (x_h2_0 - x_l2_0);

      ptr_x[0] = (xh0_0 + xh20_0);
      xt0_0 = (xh0_0 - xh20_0);

      x_1 = ptr_x[1];
      x_h2_1 = ptr_x[h2 + 1];
      x_l1_1 = ptr_x[l1 + 1];
      x_l2_1 = ptr_x[l2 + 1];

      xh1_0 = (x_1 + x_l1_1);
      xl1_0 = (x_1 - x_l1_1);

      xh21_0 = (x_h2_1 + x_l2_1);
      xl21_0 = (x_h2_1 - x_l2_1);

      ptr_x[1] = (xh1_0 + xh21_0);
      yt0_0 = (xh1_0 - xh21_0);

      xt1_0 = (xl0_0 + xl21_0);
      xt2_0 = (xl0_0 - xl21_0);

      yt2_0 = (xl1_0 + xl20_0);
      yt1_0 = (xl1_0 - xl20_0);

      mul_11 = (xt2_0 * co30);
      mul_3 = (yt2_0 * si30);
      ptr_x[l2] = 2 * (mul_3 + mul_11);

      mul_5 = (xt2_0 * si30);
      mul_9 = (yt2_0 * co30);
      ptr_x[l2 + 1] = 2 * (mul_9 - mul_5);

      mul_12 = (xt0_0 * co20);
      mul_2 = (yt0_0 * si20);
      ptr_x[l1] = 2 * (mul_2 + mul_12);

      mul_6 = (xt0_0 * si20);
      mul_8 = (yt0_0 * co20);
      ptr_x[l1 + 1] = 2 * (mul_8 - mul_6);

      mul_4 = (xt1_0 * co10);
      mul_1 = (yt1_0 * si10);
      ptr_x[h2] = 2 * (mul_1 + mul_4);

      mul_10 = (xt1_0 * si10);
      mul_7 = (yt1_0 * co10);
      ptr_x[h2 + 1] = 2 * (mul_7 - mul_10);

      ptr_x += 2;
    }
    ptr_x += fft_jmp;
    ptr_w = ptr_w - fft_jmp;
    i1++;
  }
}

VOID ixheaace_esbr_postradixcompute2(FLOAT32 *ptr_y, FLOAT32 *ptr_x,
                                     const FLOAT32 *ptr_dig_rev_tbl, WORD32 npoints) {
  WORD32 i, k;
  WORD32 h2;
  FLOAT32 x_0, x_1, x_2, x_3;
  FLOAT32 x_4, x_5, x_6, x_7;
  FLOAT32 x_8, x_9, x_a, x_b, x_c, x_d, x_e, x_f;
  FLOAT32 n00, n10, n20, n30, n01, n11, n21, n31;
  FLOAT32 n02, n12, n22, n32, n03, n13, n23, n33;

  FLOAT32 *ptr_x2, *ptr_x0;
  FLOAT32 *ptr_y0, *ptr_y1, *ptr_y2, *ptr_y3;

  ptr_y0 = ptr_y;
  ptr_y2 = ptr_y + (WORD32)npoints;
  ptr_x0 = ptr_x;
  ptr_x2 = ptr_x + (WORD32)(npoints >> 1);

  ptr_y1 = ptr_y0 + (WORD32)(npoints >> 2);
  ptr_y3 = ptr_y2 + (WORD32)(npoints >> 2);

  for (k = 0; k < 2; k++) {
    for (i = 0; i<npoints>> 1; i += 8) {
      h2 = (WORD32)*ptr_dig_rev_tbl++ / 4;

      x_0 = *ptr_x0++;
      x_1 = *ptr_x0++;
      x_2 = *ptr_x0++;
      x_3 = *ptr_x0++;
      x_4 = *ptr_x0++;
      x_5 = *ptr_x0++;
      x_6 = *ptr_x0++;
      x_7 = *ptr_x0++;

      n00 = (x_0 + x_2);
      n01 = (x_1 + x_3);

      n20 = (x_0 - x_2);
      n21 = (x_1 - x_3);

      n10 = (x_4 + x_6);
      n11 = (x_5 + x_7);

      n30 = (x_4 - x_6);
      n31 = (x_5 - x_7);

      ptr_y0[h2] = n00;
      ptr_y0[h2 + 1] = n01;
      ptr_y1[h2] = n10;
      ptr_y1[h2 + 1] = n11;
      ptr_y2[h2] = n20;
      ptr_y2[h2 + 1] = n21;
      ptr_y3[h2] = n30;
      ptr_y3[h2 + 1] = n31;

      x_8 = *ptr_x2++;
      x_9 = *ptr_x2++;
      x_a = *ptr_x2++;
      x_b = *ptr_x2++;
      x_c = *ptr_x2++;
      x_d = *ptr_x2++;
      x_e = *ptr_x2++;
      x_f = *ptr_x2++;

      n02 = (x_8 + x_a);
      n03 = (x_9 + x_b);

      n22 = (x_8 - x_a);
      n23 = (x_9 - x_b);

      n12 = (x_c + x_e);
      n13 = (x_d + x_f);

      n32 = (x_c - x_e);
      n33 = (x_d - x_f);

      ptr_y0[h2 + 2] = n02;
      ptr_y0[h2 + 3] = n03;
      ptr_y1[h2 + 2] = n12;
      ptr_y1[h2 + 3] = n13;
      ptr_y2[h2 + 2] = n22;
      ptr_y2[h2 + 3] = n23;
      ptr_y3[h2 + 2] = n32;
      ptr_y3[h2 + 3] = n33;
    }
    ptr_x0 += (WORD32)npoints >> 1;
    ptr_x2 += (WORD32)npoints >> 1;
  }
}

VOID ixheaace_esbr_postradixcompute4(FLOAT32 *ptr_y, FLOAT32 *ptr_x,
                                     const FLOAT32 *ptr_dig_rev_tbl, WORD32 npoints) {
  WORD32 i, k;
  WORD32 h2;
  FLOAT32 xh0_0, xh1_0, xl0_0, xl1_0;
  FLOAT32 xh0_1, xh1_1, xl0_1, xl1_1;
  FLOAT32 x_0, x_1, x_2, x_3;
  FLOAT32 xh0_2, xh1_2, xl0_2, xl1_2, xh0_3, xh1_3, xl0_3, xl1_3;
  FLOAT32 x_4, x_5, x_6, x_7;
  FLOAT32 x_8, x_9, x_a, x_b, x_c, x_d, x_e, x_f;
  FLOAT32 n00, n10, n20, n30, n01, n11, n21, n31;
  FLOAT32 n02, n12, n22, n32, n03, n13, n23, n33;

  FLOAT32 *ptr_x2, *ptr_x0;
  FLOAT32 *ptr_y0, *ptr_y1, *ptr_y2, *ptr_y3;

  ptr_y0 = ptr_y;
  ptr_y2 = ptr_y + npoints;
  ptr_x0 = ptr_x;
  ptr_x2 = ptr_x + (WORD32)(npoints >> 1);

  ptr_y1 = ptr_y0 + (WORD32)(npoints >> 1);
  ptr_y3 = ptr_y2 + (WORD32)(npoints >> 1);

  for (k = 0; k < 2; k++) {
    for (i = 0; i<npoints>> 1; i += 8) {
      h2 = (WORD32)*ptr_dig_rev_tbl++ / 4;
      x_0 = *ptr_x0++;
      x_1 = *ptr_x0++;
      x_2 = *ptr_x0++;
      x_3 = *ptr_x0++;
      x_4 = *ptr_x0++;
      x_5 = *ptr_x0++;
      x_6 = *ptr_x0++;
      x_7 = *ptr_x0++;

      xh0_0 = (x_0 + x_4);
      xh1_0 = (x_1 + x_5);

      xl0_0 = (x_0 - x_4);
      xl1_0 = (x_1 - x_5);

      xh0_1 = (x_2 + x_6);
      xh1_1 = (x_3 + x_7);

      xl0_1 = (x_2 - x_6);
      xl1_1 = (x_3 - x_7);

      n00 = (xh0_0 + xh0_1);
      n01 = (xh1_0 + xh1_1);
      n10 = (xl0_0 + xl1_1);

      n11 = (xl1_0 - xl0_1);
      n20 = (xh0_0 - xh0_1);
      n21 = (xh1_0 - xh1_1);
      n30 = (xl0_0 - xl1_1);

      n31 = (xl1_0 + xl0_1);

      ptr_y0[h2] = n00;
      ptr_y0[h2 + 1] = n01;
      ptr_y1[h2] = n10;
      ptr_y1[h2 + 1] = n11;
      ptr_y2[h2] = n20;
      ptr_y2[h2 + 1] = n21;
      ptr_y3[h2] = n30;
      ptr_y3[h2 + 1] = n31;

      x_8 = *ptr_x2++;
      x_9 = *ptr_x2++;
      x_a = *ptr_x2++;
      x_b = *ptr_x2++;
      x_c = *ptr_x2++;
      x_d = *ptr_x2++;
      x_e = *ptr_x2++;
      x_f = *ptr_x2++;

      xh0_2 = (x_8 + x_c);
      xh1_2 = (x_9 + x_d);

      xl0_2 = (x_8 - x_c);
      xl1_2 = (x_9 - x_d);

      xh0_3 = (x_a + x_e);
      xh1_3 = (x_b + x_f);

      xl0_3 = (x_a - x_e);
      xl1_3 = (x_b - x_f);

      n02 = (xh0_2 + xh0_3);
      n03 = (xh1_2 + xh1_3);
      n12 = (xl0_2 + xl1_3);

      n13 = (xl1_2 - xl0_3);
      n22 = (xh0_2 - xh0_3);
      n23 = (xh1_2 - xh1_3);
      n32 = (xl0_2 - xl1_3);

      n33 = (xl1_2 + xl0_3);

      ptr_y0[h2 + 2] = n02;
      ptr_y0[h2 + 3] = n03;
      ptr_y1[h2 + 2] = n12;
      ptr_y1[h2 + 3] = n13;
      ptr_y2[h2 + 2] = n22;
      ptr_y2[h2 + 3] = n23;
      ptr_y3[h2 + 2] = n32;
      ptr_y3[h2 + 3] = n33;
    }
    ptr_x0 += (WORD32)npoints >> 1;
    ptr_x2 += (WORD32)npoints >> 1;
  }
}

VOID ixheaace_esbr_cos_sin_mod(FLOAT32 *subband, ia_sbr_qmf_filter_bank_struct *pstr_qmf_bank,
                               FLOAT32 *ptr_twiddle, FLOAT32 *ptr_dig_rev_tbl) {
  WORD32 z;
  FLOAT32 temp[128] = {0};

  FLOAT32 re2, re3;
  FLOAT32 wim, wre;

  WORD32 i, M_2;
  WORD32 M = pstr_qmf_bank->no_channels / 2;

  const FLOAT32 *ptr_sin;
  const FLOAT32 *ptr_sin_cos;

  FLOAT32 subband_tmp[128] = {0};
  FLOAT32 re;
  FLOAT32 im;
  FLOAT32 *ptr_subband, *ptr_subband1;
  FLOAT32 *ptr_subband_t, *ptr_subband1_t;
  FLOAT32 *ptr_subband2, *ptr_subband12;
  FLOAT32 *ptr_subband_t2, *ptr_subband1_t2;

  M_2 = M / 2;

  ptr_sin_cos = pstr_qmf_bank->ptr_esbr_cos_twiddle;

  ptr_subband = &subband[0];
  ptr_subband1 = &subband[2 * M - 1];
  ptr_subband_t = subband_tmp;
  ptr_subband1_t = &subband_tmp[2 * M - 1];

  ptr_subband2 = &subband[64];
  ptr_subband12 = &subband[2 * M - 1 + 64];
  ptr_subband_t2 = &subband_tmp[64];
  ptr_subband1_t2 = &subband_tmp[2 * M - 1 + 64];

  i = (M_2 >> 1) - 1;
  while (i >= 0) {
    re = *ptr_subband++;
    im = *ptr_subband1--;

    wim = *ptr_sin_cos++;
    wre = *ptr_sin_cos++;

    *ptr_subband_t++ = (re * wre) + (im * wim);
    *ptr_subband_t++ = (im * wre) - (re * wim);

    re = *ptr_subband2++;
    im = *ptr_subband12--;

    *ptr_subband_t2++ = (im * wim) - (re * wre);
    *ptr_subband_t2++ = (re * wim) + (im * wre);

    re = *ptr_subband1--;
    im = *ptr_subband++;

    wim = *ptr_sin_cos++;
    wre = *ptr_sin_cos++;

    *ptr_subband1_t-- = (im * wre) - (re * wim);
    *ptr_subband1_t-- = (re * wre) + (im * wim);

    re = *ptr_subband12--;
    im = *ptr_subband2++;

    *ptr_subband1_t2-- = (re * wim) + (im * wre);
    *ptr_subband1_t2-- = (im * wim) - (re * wre);

    re = *ptr_subband++;
    im = *ptr_subband1--;

    wim = *ptr_sin_cos++;
    wre = *ptr_sin_cos++;

    *ptr_subband_t++ = (re * wre) + (im * wim);
    *ptr_subband_t++ = (im * wre) - (re * wim);

    re = *ptr_subband2++;
    im = *ptr_subband12--;

    *ptr_subband_t2++ = (im * wim) - (re * wre);
    *ptr_subband_t2++ = (re * wim) + (im * wre);

    re = *ptr_subband1--;
    im = *ptr_subband++;

    wim = *ptr_sin_cos++;
    wre = *ptr_sin_cos++;

    *ptr_subband1_t-- = (im * wre) - (re * wim);
    *ptr_subband1_t-- = (re * wre) + (im * wim);

    re = *ptr_subband12--;
    im = *ptr_subband2++;

    *ptr_subband1_t2-- = (re * wim) + (im * wre);
    *ptr_subband1_t2-- = (im * wim) - (re * wre);

    i--;
  }

  switch (M) {
    case M_32:
      ixheaace_esbr_radix4bfly(ptr_twiddle, subband_tmp, 1, 8);
      ixheaace_esbr_radix4bfly(ptr_twiddle + 48, subband_tmp, 4, 2);
      ixheaace_esbr_postradixcompute2(subband, subband_tmp, ptr_dig_rev_tbl, 32);

      ixheaace_esbr_radix4bfly(ptr_twiddle, &subband_tmp[64], 1, 8);
      ixheaace_esbr_radix4bfly(ptr_twiddle + 48, &subband_tmp[64], 4, 2);
      ixheaace_esbr_postradixcompute2(&subband[64], &subband_tmp[64], ptr_dig_rev_tbl, 32);
      break;

    case M_16:
      ixheaace_esbr_radix4bfly(ptr_twiddle, subband_tmp, 1, 4);
      ixheaace_esbr_postradixcompute4(subband, subband_tmp, ptr_dig_rev_tbl, 16);

      ixheaace_esbr_radix4bfly(ptr_twiddle, &subband_tmp[64], 1, 4);
      ixheaace_esbr_postradixcompute4(&subband[64], &subband_tmp[64], ptr_dig_rev_tbl, 16);
      break;

    case M_12:

      for (z = 0; z < (pstr_qmf_bank->no_channels >> 1); z++) {
        temp[z] = subband_tmp[2 * z];
        temp[12 + z] = subband_tmp[2 * z + 1];
      }

      // convert re and im data to interleave
      FLOAT32 intermediate[24];
      WORD32 cnt = 0;
      while (cnt < M_12) {
        intermediate[2 * cnt] = temp[cnt];
        intermediate[2 * cnt + 1] = temp[12 + cnt];
        cnt++;
      }

      iusace_complex_fft_p3_no_scratch(intermediate, 12);
      // de-interleave
      for (cnt = 0; cnt < 12; cnt++) {
        temp[cnt] = intermediate[2 * cnt];
        temp[12 + cnt] = intermediate[2 * cnt + 1];
      }

      z = 0;
      while (z < (pstr_qmf_bank->no_channels >> 1)) {
        subband[2 * z] = temp[z];
        subband[2 * z + 1] = temp[z + 12];
        z++;
      }

      z = 0;
      while (z < (pstr_qmf_bank->no_channels >> 1)) {
        temp[z] = subband_tmp[64 + 2 * z];
        temp[12 + z] = subband_tmp[64 + 2 * z + 1];
        z++;
      }

      // convert re and im data to interleave
      cnt = 0;
      while (cnt < 12) {
        intermediate[2 * cnt] = temp[cnt];
        intermediate[2 * cnt + 1] = temp[12 + cnt];
        cnt++;
      }
      iusace_complex_fft_p3_no_scratch(intermediate, 12);
      // de-interleave

      cnt = 0;
      while (cnt < 12) {
        temp[cnt] = intermediate[2 * cnt];
        temp[12 + cnt] = intermediate[2 * cnt + 1];
        cnt++;
      }

      z = 0;
      while (z < (pstr_qmf_bank->no_channels >> 1)) {
        subband[64 + 2 * z] = temp[z];
        subband[64 + 2 * z + 1] = temp[z + 12];
        z++;
      }
      break;

    default:
      z = 0;
      while (z < (pstr_qmf_bank->no_channels >> 1)) {
        temp[z] = subband_tmp[2 * z];
        temp[8 + z] = subband_tmp[2 * z + 1];
        z++;
      }

      FLOAT32 scratch[1024];
      cnt = 0;
      while (cnt < 8) {
        intermediate[2 * cnt] = temp[cnt];
        intermediate[2 * cnt + 1] = temp[8 + cnt];
        cnt++;
      }

      iusace_complex_fft_p2(intermediate, 8, scratch);
      // de-interleave
      cnt = 0;
      while (cnt < 8) {
        temp[cnt] = intermediate[2 * cnt];
        temp[8 + cnt] = intermediate[2 * cnt + 1];
        cnt++;
      }

      z = 0;
      while (z < (pstr_qmf_bank->no_channels >> 1)) {
        subband[2 * z] = temp[z];
        subband[2 * z + 1] = temp[z + 8];
        z++;
      }
      z = 0;
      while (z < (pstr_qmf_bank->no_channels >> 1)) {
        temp[z] = subband_tmp[64 + 2 * z];
        temp[8 + z] = subband_tmp[64 + 2 * z + 1];
        z++;
      }

      // convert re and im data to interleave
      cnt = 0;
      while (cnt < 8) {
        intermediate[2 * cnt] = temp[cnt];
        intermediate[2 * cnt + 1] = temp[8 + cnt];
        cnt++;
      }

      iusace_complex_fft_p2(intermediate, 8, scratch);

      // de-interleave
      cnt = 0;
      while (cnt < 8) {
        temp[cnt] = intermediate[2 * cnt];
        temp[8 + cnt] = intermediate[2 * cnt + 1];
        cnt++;
      }

      z = 0;
      while (z < (pstr_qmf_bank->no_channels >> 1)) {
        subband[64 + 2 * z] = temp[z];
        subband[64 + 2 * z + 1] = temp[8 + z];
        z++;
      }
      break;
  }

  ptr_subband = &subband[0];
  ptr_subband1 = &subband[2 * M - 1];

  re = *ptr_subband1;

  *ptr_subband = *ptr_subband / 2;
  ptr_subband++;
  *ptr_subband1 = -(*ptr_subband / 2);
  ptr_subband1--;

  ptr_sin = pstr_qmf_bank->ptr_esbr_alt_sin_twiddle;

  wim = *ptr_sin++;
  wre = *ptr_sin++;

  im = *ptr_subband1;

  *ptr_subband1-- = (re * wre) + (im * wim);
  *ptr_subband++ = (im * wre) - (re * wim);

  ptr_subband2 = &subband[64];
  ptr_subband12 = &subband[2 * M - 1 + 64];

  re = *ptr_subband12;

  *ptr_subband12-- = -(*ptr_subband2 / 2);

  *ptr_subband2 = ptr_subband2[1] / 2;

  ptr_subband2++;

  im = *ptr_subband12;

  *ptr_subband2++ = -((re * wre) + (im * wim));
  *ptr_subband12-- = (re * wim) - (im * wre);

  i = (M_2 - 2);
  while (i >= 0) {
    im = ptr_subband[0];

    re = ptr_subband[1];

    re2 = *ptr_subband1;

    *ptr_subband++ = (re * wim) + (im * wre);
    *ptr_subband1-- = (im * wim) - (re * wre);

    im = ptr_subband2[0];

    re = ptr_subband2[1];

    re3 = *ptr_subband12;

    *ptr_subband12-- = -((re * wim) + (im * wre));
    *ptr_subband2++ = (re * wre) - (im * wim);

    wim = *ptr_sin++;
    wre = *ptr_sin++;
    im = ptr_subband1[0];

    *ptr_subband1-- = (re2 * wre) + (im * wim);
    *ptr_subband++ = (im * wre) - (re2 * wim);

    im = ptr_subband12[0];

    *ptr_subband2++ = -((re3 * wre) + (im * wim));
    *ptr_subband12-- = (re3 * wim) - (im * wre);
    i--;
  }
}

static VOID ixheaace_esbr_fwd_modulation(const FLOAT32 *ptr_time_sample_buf,
                                         FLOAT32 *ptr_in_real_subband,
                                         FLOAT32 *ptr_in_imag_subband,
                                         ia_sbr_qmf_filter_bank_struct *pstr_qmf_bank,
                                         ixheaace_str_qmf_dec_tabs_struct *pstr_qmf_dec_tabs) {
  WORD32 i;
  const FLOAT32 *ptr_time_sample_buf1 = &ptr_time_sample_buf[2 * pstr_qmf_bank->no_channels - 1];
  FLOAT32 temp1, temp2;
  FLOAT32 *ptr_real_subband = ptr_in_real_subband;
  FLOAT32 *ptr_imag_subband = ptr_in_imag_subband;
  const FLOAT32 *ptr_cos;

  for (i = pstr_qmf_bank->no_channels - 1; i >= 0; i--) {
    temp1 = *ptr_time_sample_buf++ / 16.0f;
    temp2 = *ptr_time_sample_buf1-- / 16.0f;
    *ptr_real_subband++ = (temp1 - temp2);
    *ptr_imag_subband++ = (temp1 + temp2);
  }

  ixheaace_esbr_cos_sin_mod(ptr_in_real_subband, pstr_qmf_bank, pstr_qmf_dec_tabs->esbr_w_16,
                            pstr_qmf_dec_tabs->dig_rev_tab_4_16);

  ptr_cos = pstr_qmf_bank->ptr_esbr_t_cos;

  i = (pstr_qmf_bank->usb - pstr_qmf_bank->lsb - 1);
  while (i >= 0) {
    FLOAT32 cosh, sinh;
    FLOAT32 re, im;

    re = *ptr_in_real_subband;
    im = *ptr_in_imag_subband;
    cosh = *ptr_cos++;
    sinh = *ptr_cos++;
    *ptr_in_real_subband++ = 2 * ((re * cosh) + (im * sinh));
    *ptr_in_imag_subband++ = 2 * ((im * cosh) - (re * sinh));
    i--;
  }
}

VOID ixheaace_esbr_analysis_filt_block(
    ia_sbr_qmf_filter_bank_struct *pstr_codec_qmf_bank,
    ixheaace_str_qmf_dec_tabs_struct *pstr_qmf_dec_tabs, FLOAT32 *ptr_core_coder_samples,
    FLOAT32 qmf_buf_real[IXHEAACE_TIMESLOT_BUFFER_SIZE + 2 * 32][IXHEAACE_NUM_QMF_SYNTH_CHANNELS],
    FLOAT32 qmf_buf_imag[IXHEAACE_TIMESLOT_BUFFER_SIZE + 2 * 32][IXHEAACE_NUM_QMF_SYNTH_CHANNELS],
    WORD32 op_delay) {
  FLOAT32 *ptr_filt_states;
  FLOAT32 *ptr_filt_states_1;
  FLOAT32 *ptr_filt_states_2;
  FLOAT32 *ptr_temp;
  FLOAT32 *ptr_win_coeffs_1;
  FLOAT32 *ptr_win_coeffs_2;
  FLOAT32 *ptr_win_coeffs;
  FLOAT32 *ptr_loc_qmf_buf_real;
  FLOAT32 *ptr_loc_qmf_buf_imag;
  FLOAT32 local_qmf_buffer[128] = {0};
  FLOAT32 anal_buf[2 * 32] = {0};
  WORD32 idx, z;
  WORD32 core_syn_ch_index;
  FLOAT32 gain;
  WORD32 filt_offset;
  WORD32 num_columns;

  ia_sbr_qmf_filter_bank_struct *pstr_qmf_anal_bank = pstr_codec_qmf_bank;
  ptr_filt_states = pstr_qmf_anal_bank->ptr_state_new_samples_pos_low_32;
  ptr_win_coeffs_1 = (FLOAT32 *)pstr_qmf_anal_bank->ptr_filter_pos_32;
  num_columns = pstr_qmf_anal_bank->no_channels;

  switch (num_columns) {
    case 16:
      ptr_win_coeffs_2 = ptr_win_coeffs_1 + 64;
      gain = 128.0f;
      filt_offset = 64;
      break;
    case 24:
      ptr_win_coeffs_2 = ptr_win_coeffs_1 + 24;
      gain = 12.0f;
      filt_offset = 24;
      break;
    case 32:
      ptr_win_coeffs_2 = ptr_win_coeffs_1 + 64;
      gain = 256.0f;
      filt_offset = 64;
      break;
    default:
      ptr_win_coeffs_2 = ptr_win_coeffs_1 + 64;
      gain = 256.0f;
      filt_offset = 64;
      break;
  }
  gain = 1.0f / gain;

  pstr_qmf_anal_bank->usb = (WORD16)num_columns;

  ptr_loc_qmf_buf_real = &local_qmf_buffer[0];
  ptr_loc_qmf_buf_imag = &local_qmf_buffer[64];

  ptr_filt_states_1 = pstr_qmf_anal_bank->anal_filter_states_32;
  ptr_filt_states_2 = pstr_qmf_anal_bank->anal_filter_states_32 + num_columns;

  idx = 0;
  while (idx < pstr_codec_qmf_bank->num_time_slots) {
    for (z = 0; z < num_columns; z++) {
      ptr_filt_states[num_columns - 1 - z] = ptr_core_coder_samples[z];
    }

    ixheaace_esbr_qmfanal32_winadd(ptr_filt_states_1, ptr_filt_states_2, ptr_win_coeffs_1,
                                   ptr_win_coeffs_2, anal_buf, num_columns);

    ptr_core_coder_samples += num_columns;

    ptr_filt_states -= num_columns;
    if (ptr_filt_states < pstr_qmf_anal_bank->anal_filter_states_32) {
      ptr_filt_states =
          pstr_qmf_anal_bank->anal_filter_states_32 + 10 * num_columns - num_columns;
    }

    ptr_temp = ptr_filt_states_1;
    ptr_filt_states_1 = ptr_filt_states_2;
    ptr_filt_states_2 = ptr_temp;

    ptr_win_coeffs_1 += filt_offset;
    ptr_win_coeffs_2 += filt_offset;

    ptr_win_coeffs = ptr_win_coeffs_1;
    ptr_win_coeffs_1 = ptr_win_coeffs_2;
    ptr_win_coeffs_2 = ptr_win_coeffs;

    if (ptr_win_coeffs_2 > (pstr_qmf_anal_bank->ptr_ana_win_coeff_32 + filt_offset * 10)) {
      ptr_win_coeffs_1 = (FLOAT32 *)pstr_qmf_anal_bank->ptr_ana_win_coeff_32;
      ptr_win_coeffs_2 = (FLOAT32 *)pstr_qmf_anal_bank->ptr_ana_win_coeff_32 + filt_offset;
    }

    ixheaace_esbr_fwd_modulation(anal_buf, &ptr_loc_qmf_buf_real[0], &ptr_loc_qmf_buf_imag[0],
                                 pstr_qmf_anal_bank, pstr_qmf_dec_tabs);

    core_syn_ch_index = num_columns;

    for (z = 0; z < core_syn_ch_index; z++) {
      qmf_buf_real[op_delay + idx][z] = ((FLOAT32)ptr_loc_qmf_buf_real[z] * gain);
      qmf_buf_imag[op_delay + idx][z] = ((FLOAT32)ptr_loc_qmf_buf_imag[z] * gain);
    }

    idx++;
  }

  pstr_qmf_anal_bank->ptr_filter_pos_32 = ptr_win_coeffs_1;
  pstr_qmf_anal_bank->ptr_state_new_samples_pos_low_32 = ptr_filt_states;
}
IA_ERRORCODE ixheaace_extract_sbr_envelope(FLOAT32 *ptr_in_time, FLOAT32 *ptr_core_buf,
                                           UWORD32 time_sn_stride,
                                           ixheaace_pstr_sbr_enc pstr_env_enc,
                                           ixheaace_str_sbr_tabs *ptr_sbr_tab,
                                           ixheaace_comm_tables *pstr_com_tab,
                                           WORD32 flag_framelength_small) {
  IA_ERRORCODE err_code = IA_NO_ERROR;
  WORD32 ch, i, j, c;
  WORD32 n_envelopes[IXHEAACE_MAX_CH_IN_BS_ELE];
  WORD32 transient_info[IXHEAACE_MAX_CH_IN_BS_ELE][3];
  const ixheaace_str_frame_info_sbr *pstr_const_frame_info[IXHEAACE_MAX_CH_IN_BS_ELE];
  ixheaace_str_frame_info_sbr *pstr_frame_info = NULL;

  ixheaace_pstr_sbr_config_data pstr_sbr_cfg = &pstr_env_enc->str_sbr_cfg;
  ixheaace_pstr_sbr_hdr_data pstr_sbr_hdr = &pstr_env_enc->str_sbr_hdr;
  ixheaace_pstr_sbr_bitstream_data pstr_sbr_bs = &pstr_env_enc->str_sbr_bs;
  struct ixheaace_ps_enc *pstr_ps_enc = pstr_env_enc->pstr_ps_enc;
  ixheaace_pstr_sbr_qmf_filter_bank pstr_synthesis_qmf_bank =
      pstr_env_enc->pstr_synthesis_qmf_bank;
  ixheaace_pstr_common_data pstr_com_data = &pstr_env_enc->str_cmon_data;
  WORD8 *ptr_sbr_scratch = pstr_env_enc->ptr_sbr_enc_scr->sbr_scratch;
  ixheaace_pstr_enc_channel pstr_env_ch[IXHEAACE_MAX_CH_IN_BS_ELE];
  pstr_env_ch[0] = pstr_env_enc->pstr_env_channel[0];
  pstr_env_ch[1] = pstr_env_enc->pstr_env_channel[1];

  WORD32 num_channels = pstr_sbr_cfg->num_ch;
  WORD32 n_in_channels = (pstr_ps_enc) ? 2 : num_channels;

  ixheaace_sbr_stereo_mode stereo_mode = pstr_sbr_cfg->stereo_mode;
  struct ixheaace_str_sbr_env_data *pstr_env_0 = &(pstr_env_ch[0]->enc_env_data);
  struct ixheaace_str_sbr_env_data *pstr_env_1 = NULL;

  if (num_channels > 1) {
    pstr_env_1 = &(pstr_env_ch[1]->enc_env_data);
  }
  ixheaace_freq_res res[MAXIMUM_NUM_NOISE_VALUES];
  WORD32 *ptr_v_tuning;
  WORD32 v_tuning_lc_sbr[6] = {0, 2, 4, 0, 0, 0};
  WORD32 v_tuning_ld_sbr[6] = {0, 2, 3, 0, 0, 0};
  if (pstr_sbr_cfg->is_ld_sbr) {
    ptr_v_tuning = v_tuning_ld_sbr;
  } else {
    ptr_v_tuning = v_tuning_lc_sbr;
  }
  FLOAT32 *ptr_noise_floor[IXHEAACE_MAX_CH_IN_BS_ELE] = {NULL};
  WORD32 *ptr_scale_factor_band_nrg[IXHEAACE_MAX_CH_IN_BS_ELE] = {NULL};
  WORD32 *ptr_noise_level[IXHEAACE_MAX_CH_IN_BS_ELE] = {NULL};

  WORD32 *ptr_sfb_nrg_coupling[IXHEAACE_MAX_CH_IN_BS_ELE];
  WORD32 *ptr_noise_lvl_coupling[IXHEAACE_MAX_CH_IN_BS_ELE];
  WORD32 *ptr_frame_splitter_scratch =
      (WORD32 *)pstr_env_ch[0]->str_sbr_extract_env.ptr_r_buffer[0];

  WORD32 max_quant_error;
  ixheaace_str_esbr_bs_data str_esbr = {0};
  WORD32 samp_ratio_fac = DOWNSAMPLE_FAC_2_1;
  if ((pstr_env_enc->str_sbr_cfg.sbr_codec == USAC_SBR) &&
      (pstr_env_enc->str_sbr_cfg.sbr_ratio_idx == USAC_SBR_RATIO_INDEX_4_1)) {
    samp_ratio_fac = DOWNSAMPLE_FAC_4_1;
  }
  if ((n_in_channels > IXHEAACE_MAX_CH_IN_BS_ELE) || (n_in_channels < num_channels) ||
      (n_in_channels <= 0) || (num_channels <= 0)) {
    return IA_EXHEAACE_EXE_FATAL_SBR_INVALID_IN_CHANNELS;
  }
  ch = 0;
  while (ch < n_in_channels) {
    ptr_sfb_nrg_coupling[ch] = (WORD32 *)pstr_env_ch[ch]->str_sbr_extract_env.ptr_r_buffer[0];
    ptr_noise_lvl_coupling[ch] = (WORD32 *)pstr_env_ch[ch]->str_sbr_extract_env.ptr_i_buffer[0];
    ptr_scale_factor_band_nrg[ch] =
        (WORD32 *)pstr_env_ch[ch]->str_sbr_extract_env.ptr_r_buffer[0] +
        IXHEAACE_MAX_CH_IN_BS_ELE * MAXIMUM_NUM_ENVELOPE_VALUES;
    ptr_noise_level[ch] = (WORD32 *)pstr_env_ch[ch]->str_sbr_extract_env.ptr_i_buffer[0] +
                          IXHEAACE_MAX_CH_IN_BS_ELE * MAXIMUM_NUM_ENVELOPE_VALUES;
    ptr_noise_floor[ch] = pstr_env_ch[ch]->str_sbr_extract_env.ptr_i_buffer[0] +
                          IXHEAACE_MAX_CH_IN_BS_ELE * MAXIMUM_NUM_ENVELOPE_VALUES * 2;
    ch++;
  }
  if ((pstr_sbr_cfg->sbr_codec == USAC_SBR) && (pstr_sbr_hdr->sbr_harmonic)) {
    WORD32 num_sbr_samples = 2048;
    if (pstr_sbr_cfg->sbr_ratio_idx == USAC_SBR_RATIO_INDEX_4_1) {
      num_sbr_samples = IXHEAACE_MAX_NUM_SAMPLES;
    }
    err_code = ixheaace_hbe_get_pitch_bins(
        ptr_in_time, pstr_sbr_cfg, pstr_env_ch[0]->str_sbr_extract_env.ptr_r_buffer[0],
        ptr_sbr_tab, time_sn_stride, num_sbr_samples, &pstr_env_0->sbr_pitchin_bins,
        n_in_channels == 1 ? NULL : &pstr_env_1->sbr_pitchin_bins);
    if (err_code) return err_code;

    WORD32 op_delay, codec_x_delay, num_time_slots;
    op_delay = IXHEAACE_OP_DELAY_OFFSET;
    codec_x_delay = IXHEAACE_ESBR_HBE_DELAY_OFFSET;
    if (pstr_sbr_cfg->sbr_ratio_idx == USAC_SBR_RATIO_INDEX_4_1) {
      op_delay = 2 * op_delay;
      codec_x_delay = 2 * codec_x_delay;
    }

    WORD32 eff_offset = op_delay + IXHEAACE_SBR_HF_ADJ_OFFSET;
    WORD32 memmove_sz1 = (eff_offset + codec_x_delay) *
                         sizeof(pstr_env_ch[0]->pstr_hbe_enc->qmf_buf_real[0][0]) *
                         MAX_QMF_TIME_SLOTS;
    WORD32 memmove_sz2 = eff_offset *
                         sizeof(pstr_env_ch[0]->pstr_hbe_enc->ph_vocod_qmf_real[0][0]) *
                         MAX_QMF_TIME_SLOTS;

    for (ch = 0; ch < n_in_channels; ch++) {
      ixheaace_str_hbe_enc *pstr_hbe_enc = pstr_env_ch[ch]->pstr_hbe_enc;
      num_time_slots =
          pstr_env_ch[ch]->str_sbr_qmf.num_time_slots * pstr_env_ch[ch]->str_sbr_qmf.rate;

      memmove(pstr_hbe_enc->qmf_buf_real[0], pstr_hbe_enc->qmf_buf_real[num_time_slots],
              memmove_sz1);
      memmove(pstr_hbe_enc->qmf_buf_imag[0], pstr_hbe_enc->qmf_buf_imag[num_time_slots],
              memmove_sz1);
      memmove(pstr_hbe_enc->ph_vocod_qmf_real[0], pstr_hbe_enc->ph_vocod_qmf_real[num_time_slots],
              memmove_sz2);
      memmove(pstr_hbe_enc->ph_vocod_qmf_imag, pstr_hbe_enc->ph_vocod_qmf_imag + num_time_slots,
              memmove_sz2);
    }
  }
  i = 0;
  while (i < MAXIMUM_NUM_NOISE_VALUES) {
    res[i] = FREQ_RES_HIGH;
    i++;
  }

  memset(transient_info, 0, sizeof(transient_info));

  ch = 0;
  while (ch < n_in_channels) {
    ixheaace_str_sbr_extr_env *pstr_sbr_extract_env = &(pstr_env_ch[ch]->str_sbr_extract_env);

    ixheaace_sbr_analysis_filtering(
        ptr_in_time ? ptr_in_time + ch : NULL, time_sn_stride,
        pstr_sbr_extract_env->ptr_r_buffer, pstr_sbr_extract_env->ptr_i_buffer,
        &pstr_env_ch[ch]->str_sbr_qmf, ptr_sbr_tab->ptr_qmf_tab,
        pstr_env_ch[ch]->str_sbr_qmf.num_time_slots * pstr_env_ch[ch]->str_sbr_qmf.rate,
        pstr_sbr_cfg->is_ld_sbr, (FLOAT32 *)ptr_sbr_scratch,
        (pstr_ps_enc != NULL && flag_framelength_small));

    if ((1 == n_in_channels) && (USAC_SBR == pstr_sbr_cfg->sbr_codec) &&
        (pstr_sbr_hdr->sbr_pvc_active)) {
      ixheaace_pvc_scratch *pstr_pvc_scr = (ixheaace_pvc_scratch *)ptr_sbr_scratch;
      WORD32 ts, bd;
      FLOAT32 nrg_0, nrg_1;
      FLOAT32 *ptr_r_0, *ptr_r_1, *ptr_i_0, *ptr_i_1;
      FLOAT32 *ptr_r_2, *ptr_r_3, *ptr_i_2, *ptr_i_3, nrg_2, nrg_3;
      WORD32 pvc_rate = pstr_env_enc->pstr_pvc_enc->pvc_param.pvc_rate;

      // update header_active to send SBR header when previous PVC mode is different from
      // current frame's
      if (pstr_env_enc->str_sbr_hdr.sbr_pvc_mode !=
          pstr_env_enc->pstr_pvc_enc->pvc_param.pvc_mode) {
        pstr_sbr_bs->header_active = 1;
      }

      switch (pvc_rate) {
        case 2: {
          for (ts = 0; ts < IXHEAACE_ESBR_PVC_NUM_TS; ts++) {
            ptr_r_0 = pstr_sbr_extract_env->ptr_r_buffer[pvc_rate * ts];
            ptr_r_1 = pstr_sbr_extract_env->ptr_r_buffer[pvc_rate * ts + 1];
            ptr_i_0 = pstr_sbr_extract_env->ptr_i_buffer[pvc_rate * ts];
            ptr_i_1 = pstr_sbr_extract_env->ptr_i_buffer[pvc_rate * ts + 1];

            for (bd = 0; bd < MAX_QMF_TIME_SLOTS; bd++) {
              nrg_0 = ptr_r_0[bd] * ptr_r_0[bd] + ptr_i_0[bd] * ptr_i_0[bd];
              nrg_1 = ptr_r_1[bd] * ptr_r_1[bd] + ptr_i_1[bd] * ptr_i_1[bd];
              pstr_pvc_scr->pvc_qmf_high[ts * IXHEAACE_ESBR_PVC_NUM_QMF_BANDS + bd] =
                  (nrg_0 + nrg_1) / 2.0f;
            }
            WORD32 num_low_bands = MAX_QMF_TIME_SLOTS >> 1;
            for (bd = 0; bd < num_low_bands; bd++) {
              pstr_pvc_scr->pvc_qmf_low[ts * num_low_bands + bd] =
                  pstr_pvc_scr->pvc_qmf_high[ts * IXHEAACE_ESBR_PVC_NUM_QMF_BANDS + bd];
            }
          }
          break;
        }
        case 4: {
          for (ts = 0; ts < IXHEAACE_ESBR_PVC_NUM_TS; ts++) {
            ptr_r_0 = pstr_sbr_extract_env->ptr_r_buffer[pvc_rate * ts];
            ptr_r_1 = pstr_sbr_extract_env->ptr_r_buffer[pvc_rate * ts + 1];
            ptr_r_2 = pstr_sbr_extract_env->ptr_r_buffer[pvc_rate * ts + 2];
            ptr_r_3 = pstr_sbr_extract_env->ptr_r_buffer[pvc_rate * ts + 3];
            ptr_i_0 = pstr_sbr_extract_env->ptr_i_buffer[pvc_rate * ts];
            ptr_i_1 = pstr_sbr_extract_env->ptr_i_buffer[pvc_rate * ts + 1];
            ptr_i_2 = pstr_sbr_extract_env->ptr_i_buffer[pvc_rate * ts + 2];
            ptr_i_3 = pstr_sbr_extract_env->ptr_i_buffer[pvc_rate * ts + 3];

            for (bd = 0; bd < MAX_QMF_TIME_SLOTS; bd++) {
              nrg_0 = ptr_r_0[bd] * ptr_r_0[bd] + ptr_i_0[bd] * ptr_i_0[bd];
              nrg_1 = ptr_r_1[bd] * ptr_r_1[bd] + ptr_i_1[bd] * ptr_i_1[bd];
              nrg_2 = ptr_r_2[bd] * ptr_r_2[bd] + ptr_i_2[bd] * ptr_i_2[bd];
              nrg_3 = ptr_r_3[bd] * ptr_r_3[bd] + ptr_i_3[bd] * ptr_i_3[bd];
              pstr_pvc_scr->pvc_qmf_high[ts * IXHEAACE_ESBR_PVC_NUM_QMF_BANDS + bd] =
                  (nrg_0 + nrg_1 + nrg_2 + nrg_3) / 4.0f;
            }
            WORD32 num_low_bands = (MAX_QMF_TIME_SLOTS >> 2);
            for (bd = 0; bd < num_low_bands; bd++) {
              pstr_pvc_scr->pvc_qmf_low[ts * num_low_bands + bd] =
                  pstr_pvc_scr->pvc_qmf_high[ts * IXHEAACE_ESBR_PVC_NUM_QMF_BANDS + bd];
            }
          }
          break;
        }
      }
      pstr_env_enc->pstr_pvc_enc->pvc_param.usac_indep_flag = pstr_sbr_bs->usac_indep_flag;
      err_code = ixheaace_pvc_encode_frame(
          pstr_env_enc->pstr_pvc_enc, (UWORD8)pstr_env_enc->str_sbr_hdr.sbr_pvc_mode,
          pstr_pvc_scr->pvc_qmf_low, pstr_pvc_scr->pvc_qmf_high,
          pstr_sbr_cfg->ptr_v_k_master[0],
          pstr_sbr_cfg->ptr_v_k_master[pstr_sbr_cfg->num_master] - 1);
      if (err_code) {
        return err_code;
      }

      memcpy(&pstr_env_ch[ch]->enc_env_data.pvc_info, &pstr_env_enc->pstr_pvc_enc->pvc_bs_info,
             sizeof(ixheaace_pvc_bs_info));
    }

    // COPY generated spectrum for inter-TES encoder
    if ((USAC_SBR == pstr_sbr_cfg->sbr_codec) && (1 == pstr_sbr_hdr->sbr_inter_tes_active)) {
      WORD32 ts, num_ts, delay;
      num_ts = pstr_env_ch[ch]->str_sbr_qmf.num_time_slots;

      ixheaace_str_inter_tes_params *pstr_tes_enc = &pstr_env_ch[ch]->str_inter_tes_enc;
      delay = pstr_tes_enc->op_delay + pstr_tes_enc->codec_delay + IXHEAACE_SBR_HF_ADJ_OFFSET;
      ts = 0;
      while (ts < num_ts) {
        memcpy(pstr_tes_enc->qmf_buf_real[delay + ts], pstr_sbr_extract_env->ptr_r_buffer[ts],
               IXHEAACE_QMF_CHANNELS * sizeof(pstr_tes_enc->qmf_buf_real[0][0]));
        memcpy(pstr_tes_enc->qmf_buf_imag[delay + ts], pstr_sbr_extract_env->ptr_i_buffer[ts],
               IXHEAACE_QMF_CHANNELS * sizeof(pstr_tes_enc->qmf_buf_imag[0][0]));
        ts++;
      }
    }

    ch++;
  }
  if ((pstr_sbr_cfg->sbr_codec == USAC_SBR) && (pstr_sbr_hdr->sbr_harmonic)) {
    WORD32 dft_hbe_flag = 0;
    WORD32 op_delay, codec_x_delay, num_time_slots;
    WORD32 esbr_hbe_delay_offsets = IXHEAACE_ESBR_HBE_DELAY_OFFSET;
    WORD32 oversampling_flag = 0;
    op_delay = IXHEAACE_OP_DELAY_OFFSET;
    codec_x_delay = IXHEAACE_ESBR_HBE_DELAY_OFFSET;
    if (pstr_sbr_cfg->sbr_ratio_idx == USAC_SBR_RATIO_INDEX_4_1) {
      op_delay = 2 * IXHEAACE_OP_DELAY_OFFSET;
      codec_x_delay = 2 * codec_x_delay;
      oversampling_flag = 1;
    }
    WORD32 eff_offset = op_delay + IXHEAACE_SBR_HF_ADJ_OFFSET;
    dft_hbe_flag = pstr_sbr_hdr->hq_esbr;
    ch = 0;
    while (ch < n_in_channels) {
      ixheaace_str_hbe_enc *pstr_hbe_enc = pstr_env_ch[ch]->pstr_hbe_enc;
      pstr_hbe_enc->pstr_hbe_txposer->oversampling_flag = oversampling_flag;
      num_time_slots =
          pstr_env_ch[ch]->str_sbr_qmf.num_time_slots * pstr_env_ch[ch]->str_sbr_qmf.rate;

      if (dft_hbe_flag == 1) {
        err_code = ixheaace_dft_hbe_apply(
            pstr_hbe_enc->pstr_hbe_txposer,
            pstr_hbe_enc->qmf_buf_real + eff_offset + esbr_hbe_delay_offsets,
            pstr_hbe_enc->qmf_buf_imag + eff_offset + esbr_hbe_delay_offsets, num_time_slots,
            pstr_hbe_enc->ph_vocod_qmf_real + eff_offset,
            pstr_hbe_enc->ph_vocod_qmf_imag + eff_offset,
            pstr_env_ch[ch]->enc_env_data.sbr_pitchin_bins, (FLOAT32 *)ptr_sbr_scratch);
        if (err_code) {
          return err_code;
        }
      } else {
        // size 4096 samples
        FLOAT32 *ptr_time_data = (FLOAT32 *)ptr_sbr_scratch;
        int cnt = 0;
        if (0 == ch) {
          while (cnt < IXHEAACE_MAX_NUM_SAMPLES) {
            ptr_time_data[cnt] = pstr_env_enc->ptr_hbe_resample_buf[2 * cnt];
            cnt++;
          }
        } else {
          while (cnt < IXHEAACE_MAX_NUM_SAMPLES) {
            ptr_time_data[cnt] = pstr_env_enc->ptr_hbe_resample_buf[2 * cnt + 1];
            cnt++;
          }
        }

        ixheaace_esbr_analysis_filt_block(&(pstr_hbe_enc->str_codec_qmf_bank),
                                          pstr_hbe_enc->str_codec_qmf_bank.pstr_qmf_dec_tabs,
                                          ptr_time_data, pstr_hbe_enc->qmf_buf_real,
                                          pstr_hbe_enc->qmf_buf_imag,
                                          op_delay + codec_x_delay + IXHEAACE_SBR_HF_ADJ_OFFSET);

        err_code = ixheaace_qmf_hbe_apply(
            pstr_hbe_enc->pstr_hbe_txposer,
            pstr_hbe_enc->qmf_buf_real + eff_offset + esbr_hbe_delay_offsets,
            pstr_hbe_enc->qmf_buf_imag + eff_offset + esbr_hbe_delay_offsets, num_time_slots,
            pstr_hbe_enc->ph_vocod_qmf_real + eff_offset,
            pstr_hbe_enc->ph_vocod_qmf_imag + eff_offset,
            pstr_env_ch[ch]->enc_env_data.sbr_pitchin_bins);
        if (err_code) {
          return err_code;
        }

        if (pstr_sbr_cfg->sbr_ratio_idx == USAC_SBR_RATIO_INDEX_4_1) {
          ixheaace_hbe_repl_spec(&pstr_hbe_enc->pstr_hbe_txposer->x_over_qmf[0],
                                 pstr_hbe_enc->ph_vocod_qmf_real + eff_offset,
                                 pstr_hbe_enc->ph_vocod_qmf_imag + eff_offset, num_time_slots,
                                 pstr_hbe_enc->pstr_hbe_txposer->max_stretch);
        }
      }
      ch++;
    }
  }
  if (pstr_ps_enc && pstr_synthesis_qmf_bank) {
    err_code = ixheaace_encode_ps_frame(
        pstr_ps_enc, pstr_env_ch[0]->str_sbr_extract_env.ptr_i_buffer,
        pstr_env_ch[0]->str_sbr_extract_env.ptr_r_buffer,
        pstr_env_ch[1]->str_sbr_extract_env.ptr_i_buffer,
        pstr_env_ch[1]->str_sbr_extract_env.ptr_r_buffer, ptr_sbr_tab->ptr_ps_tab, pstr_com_tab);
    if (err_code) {
      return err_code;
    }
    ixheaace_enc_synthesis_qmf_filtering(
        pstr_env_ch[0]->str_sbr_extract_env.ptr_r_buffer,
        pstr_env_ch[0]->str_sbr_extract_env.ptr_i_buffer, ptr_core_buf,
        (ixheaace_pstr_sbr_qmf_filter_bank)pstr_synthesis_qmf_bank);
  }

  ch = 0;
  while (ch < num_channels) {
    ixheaace_str_hbe_enc *pstr_hbe_enc = pstr_env_ch[ch]->pstr_hbe_enc;
    ixheaace_str_sbr_extr_env *pstr_sbr_extract_env = &(pstr_env_ch[ch]->str_sbr_extract_env);

    ixheaace_get_energy_from_cplx_qmf(
        pstr_sbr_extract_env->ptr_y_buffer + pstr_sbr_extract_env->y_buffer_write_offset,
        pstr_sbr_extract_env->ptr_r_buffer, pstr_sbr_extract_env->ptr_i_buffer,
        pstr_sbr_cfg->is_ld_sbr, pstr_env_ch[ch]->str_sbr_qmf.num_time_slots, samp_ratio_fac,
        pstr_hbe_enc, (IXHEAACE_OP_DELAY_OFFSET + IXHEAACE_ESBR_HBE_DELAY_OFFSET +
        IXHEAACE_SBR_HF_ADJ_OFFSET), pstr_sbr_hdr->sbr_harmonic);

    ixheaace_calculate_tonality_quotas(
        &pstr_env_ch[ch]->str_ton_corr, pstr_sbr_extract_env->ptr_r_buffer,
        pstr_sbr_extract_env->ptr_i_buffer,
        pstr_sbr_cfg->ptr_freq_band_tab[HI][pstr_sbr_cfg->num_scf[HI]],
        pstr_env_ch[ch]->str_sbr_qmf.num_time_slots, pstr_sbr_cfg->is_ld_sbr);
    if (pstr_sbr_cfg->is_ld_sbr) {
      ixheaace_detect_transient_eld(pstr_sbr_extract_env->ptr_y_buffer,
                                    &pstr_env_ch[ch]->str_sbr_trans_detector, transient_info[ch]);
    } else {
      ixheaace_detect_transient(pstr_sbr_extract_env->ptr_y_buffer,
                                &pstr_env_ch[ch]->str_sbr_trans_detector, transient_info[ch],
                                pstr_sbr_extract_env->time_step, pstr_sbr_cfg->sbr_codec);
    }
    if (transient_info[ch][1] == 0) {
      if (pstr_sbr_cfg->is_ld_sbr) {
        err_code = ixheaace_frame_splitter(
            pstr_sbr_extract_env->ptr_y_buffer, &pstr_env_ch[ch]->str_sbr_trans_detector,
            pstr_sbr_cfg->ptr_freq_band_tab[1], pstr_sbr_cfg->num_scf[1],
            pstr_sbr_extract_env->time_step, pstr_sbr_extract_env->time_slots, transient_info[ch],
            (FLOAT32 *)ptr_frame_splitter_scratch, pstr_sbr_cfg->is_ld_sbr);
      } else {
        err_code = ixheaace_frame_splitter(
            pstr_sbr_extract_env->ptr_y_buffer, &pstr_env_ch[ch]->str_sbr_trans_detector,
            pstr_sbr_cfg->ptr_freq_band_tab[1], pstr_sbr_cfg->num_scf[1],
            pstr_sbr_extract_env->time_step, pstr_sbr_extract_env->no_cols, transient_info[ch],
            (FLOAT32 *)ptr_frame_splitter_scratch, pstr_sbr_cfg->is_ld_sbr);
      }
      if (err_code) {
        return err_code;
      }
    }
    ch++;
  }

  if (stereo_mode == SBR_COUPLING) {
    if (transient_info[0][1] && transient_info[1][1]) {
      transient_info[0][0] = ixheaac_min32(transient_info[1][0], transient_info[0][0]);

      transient_info[1][0] = transient_info[0][0];
    } else if (transient_info[0][1] && !transient_info[1][1]) {
      transient_info[1][0] = transient_info[0][0];
    } else if (!transient_info[0][1] && transient_info[1][1]) {
      transient_info[0][0] = transient_info[1][0];
    } else {
      transient_info[0][0] = ixheaac_max32(transient_info[1][0], transient_info[0][0]);

      transient_info[1][0] = transient_info[0][0];
    }
  }

  err_code = ixheaace_frame_info_generator(
      &pstr_env_ch[0]->str_sbr_env_frame, pstr_env_ch[0]->str_sbr_extract_env.pre_transient_info,
      transient_info[0], ptr_v_tuning, ptr_sbr_tab->ptr_qmf_tab,
      pstr_env_ch[0]->str_sbr_qmf.num_time_slots, pstr_sbr_cfg->is_ld_sbr, &pstr_frame_info,
      flag_framelength_small);
  if (pstr_sbr_cfg->is_ld_sbr && transient_info[0][2]) {
    pstr_frame_info->short_env = pstr_frame_info->n_envelopes;
  }
  pstr_const_frame_info[0] = pstr_frame_info;
  if (err_code) {
    return err_code;
  }

  pstr_env_0->pstr_sbr_bs_grid = &pstr_env_ch[0]->str_sbr_env_frame.sbr_grid;

  for (ch = 0; ch < num_channels; ch++) {
    memset(
        ptr_noise_floor[ch], 0,
        IXHEAACE_MAX_CH_IN_BS_ELE * MAXIMUM_NUM_ENVELOPE_VALUES * sizeof(ptr_noise_floor[0][0]));
  }

  switch (stereo_mode) {
    case IXHEAACE_SBR_MODE_LEFT_RIGHT:
    case IXHEAACE_SBR_MODE_SWITCH_LRC:

      err_code = ixheaace_frame_info_generator(
          &pstr_env_ch[1]->str_sbr_env_frame,
          pstr_env_ch[1]->str_sbr_extract_env.pre_transient_info, transient_info[1], ptr_v_tuning,
          ptr_sbr_tab->ptr_qmf_tab, pstr_env_ch[1]->str_sbr_qmf.num_time_slots,
          pstr_sbr_cfg->is_ld_sbr, &pstr_frame_info, flag_framelength_small);

      if (pstr_sbr_cfg->is_ld_sbr && transient_info[1][2]) {
        pstr_frame_info->short_env = pstr_frame_info->n_envelopes;
      }
      pstr_const_frame_info[1] = pstr_frame_info;
      if (err_code) {
        return err_code;
      }

      pstr_env_1->pstr_sbr_bs_grid = &pstr_env_ch[1]->str_sbr_env_frame.sbr_grid;

      if (pstr_const_frame_info[0]->n_envelopes != pstr_const_frame_info[1]->n_envelopes) {
        stereo_mode = IXHEAACE_SBR_MODE_LEFT_RIGHT;
      } else {
        for (i = 0; i < pstr_const_frame_info[0]->n_envelopes + 1; i++) {
          if (pstr_const_frame_info[0]->borders[i] != pstr_const_frame_info[1]->borders[i]) {
            stereo_mode = IXHEAACE_SBR_MODE_LEFT_RIGHT;
            break;
          }
        }

        for (i = 0; i < pstr_const_frame_info[0]->n_envelopes; i++) {
          if (pstr_const_frame_info[0]->freq_res[i] != pstr_const_frame_info[1]->freq_res[i]) {
            stereo_mode = IXHEAACE_SBR_MODE_LEFT_RIGHT;
            break;
          }
        }

        if (pstr_const_frame_info[0]->short_env != pstr_const_frame_info[1]->short_env) {
          stereo_mode = IXHEAACE_SBR_MODE_LEFT_RIGHT;
        }
      }
      break;
    case SBR_COUPLING:

      pstr_const_frame_info[1] = pstr_const_frame_info[0];

      pstr_env_1->pstr_sbr_bs_grid = &pstr_env_ch[0]->str_sbr_env_frame.sbr_grid;
      break;
    case IXHEAACE_SBR_MODE_MONO:
      break;
  }

  for (ch = 0; ch < num_channels; ch++) {
    ixheaace_str_sbr_extr_env *pstr_sbr_extract_env = &(pstr_env_ch[ch]->str_sbr_extract_env);

    pstr_sbr_extract_env->pre_transient_info[0] = transient_info[ch][0];
    pstr_sbr_extract_env->pre_transient_info[1] = transient_info[ch][1];
    pstr_env_ch[ch]->enc_env_data.no_of_envelopes = n_envelopes[ch] =
        pstr_const_frame_info[ch]->n_envelopes;

    for (i = 0; i < n_envelopes[ch]; i++) {
      pstr_env_ch[ch]->enc_env_data.no_scf_bands[i] =
          (pstr_const_frame_info[ch]->freq_res[i] == FREQ_RES_HIGH
               ? pstr_sbr_cfg->num_scf[FREQ_RES_HIGH]
               : pstr_sbr_cfg->num_scf[FREQ_RES_LOW]);
    }

    if ((pstr_env_ch[ch]->enc_env_data.pstr_sbr_bs_grid->frame_type == IXHEAACE_FIXFIX) &&
        (n_envelopes[ch] == 1)) {
      if (pstr_sbr_cfg->is_ld_sbr) {
        pstr_env_ch[ch]->enc_env_data.curr_sbr_amp_res = IXHEAACE_SBR_AMP_RES_3_0;
      } else {
        pstr_env_ch[ch]->enc_env_data.curr_sbr_amp_res = IXHEAACE_SBR_AMP_RES_1_5;
      }
      if (pstr_env_ch[ch]->enc_env_data.init_sbr_amp_res !=
          pstr_env_ch[ch]->enc_env_data.curr_sbr_amp_res) {
        err_code = ixheaace_init_sbr_huffman_tabs(
            &pstr_env_ch[ch]->enc_env_data, &pstr_env_ch[ch]->str_sbr_code_env,
            &pstr_env_ch[ch]->str_sbr_code_noise_floor, IXHEAACE_SBR_AMP_RES_1_5,
            ptr_sbr_tab->ptr_sbr_huff_tab);
        if (err_code) {
          return err_code;
        }
        pstr_env_ch[ch]->sbr_amp_res_init = IXHEAACE_SBR_AMP_RES_1_5;
      }
    } else {
      if (pstr_sbr_hdr->sbr_amp_res != pstr_env_ch[ch]->enc_env_data.init_sbr_amp_res) {
        err_code = ixheaace_init_sbr_huffman_tabs(
            &pstr_env_ch[ch]->enc_env_data, &pstr_env_ch[ch]->str_sbr_code_env,
            &pstr_env_ch[ch]->str_sbr_code_noise_floor, pstr_sbr_hdr->sbr_amp_res,
            ptr_sbr_tab->ptr_sbr_huff_tab);
        if (err_code) {
          return err_code;
        }
        pstr_env_ch[ch]->sbr_amp_res_init = pstr_sbr_hdr->sbr_amp_res;
      }
    }

    ixheaace_ton_corr_param_extr(
        &pstr_env_ch[ch]->str_ton_corr, pstr_env_ch[ch]->enc_env_data.sbr_invf_mode_vec,
        ptr_noise_floor[ch], &pstr_env_ch[ch]->enc_env_data.add_harmonic_flag,
        pstr_env_ch[ch]->enc_env_data.add_harmonic, pstr_sbr_extract_env->envelope_compensation,
        pstr_const_frame_info[ch], transient_info[ch], pstr_sbr_cfg->ptr_freq_band_tab[HI],
        pstr_sbr_cfg->num_scf[HI], pstr_env_ch[ch]->enc_env_data.sbr_xpos_mode, ptr_sbr_scratch,
        pstr_sbr_cfg->is_ld_sbr);

    pstr_env_ch[ch]->enc_env_data.sbr_invf_mode =
        pstr_env_ch[ch]->enc_env_data.sbr_invf_mode_vec[0];
    pstr_env_ch[ch]->enc_env_data.noise_band_count =
        pstr_env_ch[ch]->str_ton_corr.sbr_noise_floor_est.num_of_noise_bands;
  }

  switch (stereo_mode) {
    case IXHEAACE_SBR_MODE_MONO:
      err_code = ixheaace_calculate_sbr_envelope(pstr_env_ch[0]->str_sbr_extract_env.ptr_y_buffer,
                                                 NULL, pstr_const_frame_info[0],
                                                 ptr_scale_factor_band_nrg[0], NULL, pstr_sbr_cfg,
                                                 pstr_env_ch[0], IXHEAACE_SBR_MODE_MONO, NULL);

      if (err_code) {
        return err_code;
      }
      break;

    case IXHEAACE_SBR_MODE_LEFT_RIGHT:

      err_code = ixheaace_calculate_sbr_envelope(pstr_env_ch[0]->str_sbr_extract_env.ptr_y_buffer,
                                                 NULL, pstr_const_frame_info[0],
                                                 ptr_scale_factor_band_nrg[0], NULL, pstr_sbr_cfg,
                                                 pstr_env_ch[0], IXHEAACE_SBR_MODE_MONO, NULL);
      if (err_code) {
        return err_code;
      }

      err_code = ixheaace_calculate_sbr_envelope(pstr_env_ch[1]->str_sbr_extract_env.ptr_y_buffer,
                                                 NULL, pstr_const_frame_info[1],
                                                 ptr_scale_factor_band_nrg[1], NULL, pstr_sbr_cfg,
                                                 pstr_env_ch[1], IXHEAACE_SBR_MODE_MONO, NULL);

      if (err_code) {
        return err_code;
      }

      break;

    case SBR_COUPLING:

      err_code = ixheaace_calculate_sbr_envelope(
          pstr_env_ch[0]->str_sbr_extract_env.ptr_y_buffer,
          pstr_env_ch[1]->str_sbr_extract_env.ptr_y_buffer, pstr_const_frame_info[0],
          ptr_scale_factor_band_nrg[0], ptr_scale_factor_band_nrg[1], pstr_sbr_cfg,
          pstr_env_ch[0], SBR_COUPLING, &max_quant_error);
      if (err_code) {
        return err_code;
      }
      break;

    case IXHEAACE_SBR_MODE_SWITCH_LRC:
      err_code = ixheaace_calculate_sbr_envelope(pstr_env_ch[0]->str_sbr_extract_env.ptr_y_buffer,
                                                 NULL, pstr_const_frame_info[0],
                                                 ptr_scale_factor_band_nrg[0], NULL, pstr_sbr_cfg,
                                                 pstr_env_ch[0], IXHEAACE_SBR_MODE_MONO, NULL);
      if (err_code) {
        return err_code;
      }

      err_code = ixheaace_calculate_sbr_envelope(pstr_env_ch[1]->str_sbr_extract_env.ptr_y_buffer,
                                                 NULL, pstr_const_frame_info[1],
                                                 ptr_scale_factor_band_nrg[1], NULL, pstr_sbr_cfg,
                                                 pstr_env_ch[1], IXHEAACE_SBR_MODE_MONO, NULL);
      if (err_code) {
        return err_code;
      }

      err_code = ixheaace_calculate_sbr_envelope(
          pstr_env_ch[0]->str_sbr_extract_env.ptr_y_buffer,
          pstr_env_ch[1]->str_sbr_extract_env.ptr_y_buffer, pstr_const_frame_info[0],
          ptr_sfb_nrg_coupling[0], ptr_sfb_nrg_coupling[1], pstr_sbr_cfg, pstr_env_ch[0],
          SBR_COUPLING, &max_quant_error);
      if (err_code) {
        return err_code;
      }
      break;
  }

  switch (stereo_mode) {
    case IXHEAACE_SBR_MODE_MONO:

      ixheaace_sbr_noise_floor_levels_quantisation(ptr_noise_level[0], ptr_noise_floor[0], 0);

      err_code = ixheaace_code_envelope(
          ptr_noise_level[0], res, &pstr_env_ch[0]->str_sbr_code_noise_floor,
          pstr_env_0->domain_vec_noise, 0, (pstr_const_frame_info[0]->n_envelopes > 1 ? 2 : 1), 0,
          pstr_sbr_bs->header_active, pstr_sbr_bs->usac_indep_flag, pstr_sbr_cfg->is_ld_sbr);
      if (err_code) {
        return err_code;
      }

      break;

    case IXHEAACE_SBR_MODE_LEFT_RIGHT:
      // We have a error checks for Number of channels to ensure memory is assigned to
      // ptr_noise_floor[]. However, MSVS static analysis is marking this as a potential error.
      // So, suppressed this in source
      ixheaace_sbr_noise_floor_levels_quantisation(ptr_noise_level[0], ptr_noise_floor[0], 0);

      err_code = ixheaace_code_envelope(
          ptr_noise_level[0], res, &pstr_env_ch[0]->str_sbr_code_noise_floor,
          pstr_env_0->domain_vec_noise, 0, (pstr_const_frame_info[0]->n_envelopes > 1 ? 2 : 1), 0,
          pstr_sbr_bs->header_active, pstr_sbr_bs->usac_indep_flag, pstr_sbr_cfg->is_ld_sbr);
      if (err_code) {
        return err_code;
      }

      ixheaace_sbr_noise_floor_levels_quantisation(ptr_noise_level[1], ptr_noise_floor[1], 0);

      err_code = ixheaace_code_envelope(
          ptr_noise_level[1], res, &pstr_env_ch[1]->str_sbr_code_noise_floor,
          pstr_env_1->domain_vec_noise, 0, (pstr_const_frame_info[1]->n_envelopes > 1 ? 2 : 1), 0,
          pstr_sbr_bs->header_active, pstr_sbr_bs->usac_indep_flag, pstr_sbr_cfg->is_ld_sbr);
      if (err_code) {
        return err_code;
      }

      break;

    case SBR_COUPLING:
      ixheaace_couple_noise_floor(ptr_noise_floor[0], ptr_noise_floor[1]);

      ixheaace_sbr_noise_floor_levels_quantisation(ptr_noise_level[0], ptr_noise_floor[0], 0);

      err_code = ixheaace_code_envelope(
          ptr_noise_level[0], res, &pstr_env_ch[0]->str_sbr_code_noise_floor,
          pstr_env_0->domain_vec_noise, 1, (pstr_const_frame_info[0]->n_envelopes > 1 ? 2 : 1), 0,
          pstr_sbr_bs->header_active, pstr_sbr_bs->usac_indep_flag, pstr_sbr_cfg->is_ld_sbr);
      if (err_code) {
        return err_code;
      }

      ixheaace_sbr_noise_floor_levels_quantisation(ptr_noise_level[1], ptr_noise_floor[1], 1);

      err_code = ixheaace_code_envelope(
          ptr_noise_level[1], res, &pstr_env_ch[1]->str_sbr_code_noise_floor,
          pstr_env_1->domain_vec_noise, 1, (pstr_const_frame_info[1]->n_envelopes > 1 ? 2 : 1), 1,
          pstr_sbr_bs->header_active, pstr_sbr_bs->usac_indep_flag, pstr_sbr_cfg->is_ld_sbr);
      if (err_code) {
        return err_code;
      }

      break;

    case IXHEAACE_SBR_MODE_SWITCH_LRC:

      ixheaace_sbr_noise_floor_levels_quantisation(ptr_noise_level[0], ptr_noise_floor[0], 0);

      ixheaace_sbr_noise_floor_levels_quantisation(ptr_noise_level[1], ptr_noise_floor[1], 0);

      ixheaace_couple_noise_floor(ptr_noise_floor[0], ptr_noise_floor[1]);

      ixheaace_sbr_noise_floor_levels_quantisation(ptr_noise_lvl_coupling[0], ptr_noise_floor[0],
                                                   0);

      ixheaace_sbr_noise_floor_levels_quantisation(ptr_noise_lvl_coupling[1], ptr_noise_floor[1],
                                                   1);
      break;
  }

  switch (stereo_mode) {
    case IXHEAACE_SBR_MODE_MONO:

      pstr_sbr_hdr->coupling = 0;
      pstr_env_0->balance = 0;

      err_code = ixheaace_code_envelope(
          ptr_scale_factor_band_nrg[0], pstr_const_frame_info[0]->freq_res,
          &pstr_env_ch[0]->str_sbr_code_env, pstr_env_0->domain_vec, pstr_sbr_hdr->coupling,
          pstr_const_frame_info[0]->n_envelopes, 0, pstr_sbr_bs->header_active,
          pstr_sbr_bs->usac_indep_flag, pstr_sbr_cfg->is_ld_sbr);
      if (err_code) {
        return err_code;
      }
      break;

    case IXHEAACE_SBR_MODE_LEFT_RIGHT:

      pstr_sbr_hdr->coupling = 0;

      pstr_env_0->balance = 0;
      pstr_env_1->balance = 0;

      err_code = ixheaace_code_envelope(
          ptr_scale_factor_band_nrg[0], pstr_const_frame_info[0]->freq_res,
          &pstr_env_ch[0]->str_sbr_code_env, pstr_env_0->domain_vec, pstr_sbr_hdr->coupling,
          pstr_const_frame_info[0]->n_envelopes, 0, pstr_sbr_bs->header_active,
          pstr_sbr_bs->usac_indep_flag, pstr_sbr_cfg->is_ld_sbr);
      if (err_code) {
        return err_code;
      }

      err_code = ixheaace_code_envelope(
          ptr_scale_factor_band_nrg[1], pstr_const_frame_info[1]->freq_res,
          &pstr_env_ch[1]->str_sbr_code_env, pstr_env_1->domain_vec, pstr_sbr_hdr->coupling,
          pstr_const_frame_info[1]->n_envelopes, 0, pstr_sbr_bs->header_active,
          pstr_sbr_bs->usac_indep_flag, pstr_sbr_cfg->is_ld_sbr);
      if (err_code) {
        return err_code;
      }
      break;

    case SBR_COUPLING:

      pstr_sbr_hdr->coupling = 1;
      pstr_env_0->balance = 0;
      pstr_env_1->balance = 1;

      err_code = ixheaace_code_envelope(
          ptr_scale_factor_band_nrg[0], pstr_const_frame_info[0]->freq_res,
          &pstr_env_ch[0]->str_sbr_code_env, pstr_env_0->domain_vec, pstr_sbr_hdr->coupling,
          pstr_const_frame_info[0]->n_envelopes, 0, pstr_sbr_bs->header_active,
          pstr_sbr_bs->usac_indep_flag, pstr_sbr_cfg->is_ld_sbr);
      if (err_code) {
        return err_code;
      }

      err_code = ixheaace_code_envelope(
          ptr_scale_factor_band_nrg[1], pstr_const_frame_info[1]->freq_res,
          &pstr_env_ch[1]->str_sbr_code_env, pstr_env_1->domain_vec, pstr_sbr_hdr->coupling,
          pstr_const_frame_info[1]->n_envelopes, 1, pstr_sbr_bs->header_active,
          pstr_sbr_bs->usac_indep_flag, pstr_sbr_cfg->is_ld_sbr);
      if (err_code) {
        return err_code;
      }
      break;

    case IXHEAACE_SBR_MODE_SWITCH_LRC: {
      WORD32 payloadbits_lr;
      WORD32 payloadbits_coupling;

      WORD32 scale_factor_band_nrg_prev_temp[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_FREQ_COEFFS];
      WORD32 noise_prev_temp[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_NUM_NOISE_COEFFS];
      WORD32 up_date_nrg_temp[IXHEAACE_MAX_CH_IN_BS_ELE];
      WORD32 up_date_noise_temp[IXHEAACE_MAX_CH_IN_BS_ELE];
      WORD32 domain_vec_temp[IXHEAACE_MAX_CH_IN_BS_ELE][IXHEAACE_MAX_ENV];
      WORD32 domain_vec_noise_temp[IXHEAACE_MAX_CH_IN_BS_ELE][IXHEAACE_MAX_ENV];

      WORD32 temp_flag_right = 0;
      WORD32 temp_flag_left = 0;

      ch = 0;
      while (ch < num_channels) {
        memcpy(scale_factor_band_nrg_prev_temp[ch],
               pstr_env_ch[ch]->str_sbr_code_env.sfb_nrg_prev,
               MAXIMUM_FREQ_COEFFS * sizeof(scale_factor_band_nrg_prev_temp[0][0]));

        memcpy(noise_prev_temp[ch], pstr_env_ch[ch]->str_sbr_code_noise_floor.sfb_nrg_prev,
               MAXIMUM_NUM_NOISE_COEFFS * sizeof(noise_prev_temp[0][0]));

        up_date_nrg_temp[ch] = pstr_env_ch[ch]->str_sbr_code_env.update;
        up_date_noise_temp[ch] = pstr_env_ch[ch]->str_sbr_code_noise_floor.update;

        if (pstr_sbr_hdr->prev_coupling) {
          pstr_env_ch[ch]->str_sbr_code_env.update = 0;
          pstr_env_ch[ch]->str_sbr_code_noise_floor.update = 0;
        }
        ch++;
      }

      err_code = ixheaace_code_envelope(
          ptr_scale_factor_band_nrg[0], pstr_const_frame_info[0]->freq_res,
          &pstr_env_ch[0]->str_sbr_code_env, pstr_env_0->domain_vec, 0,
          pstr_const_frame_info[0]->n_envelopes, 0, pstr_sbr_bs->header_active,
          pstr_sbr_bs->usac_indep_flag, pstr_sbr_cfg->is_ld_sbr);
      if (err_code) {
        return err_code;
      }

      err_code = ixheaace_code_envelope(
          ptr_scale_factor_band_nrg[1], pstr_const_frame_info[1]->freq_res,
          &pstr_env_ch[1]->str_sbr_code_env, pstr_env_1->domain_vec, 0,
          pstr_const_frame_info[1]->n_envelopes, 0, pstr_sbr_bs->header_active,
          pstr_sbr_bs->usac_indep_flag, pstr_sbr_cfg->is_ld_sbr);
      if (err_code) {
        return err_code;
      }

      c = 0;
      i = 0;
      while (i < n_envelopes[0]) {
        for (j = 0; j < pstr_env_0->no_scf_bands[i]; j++) {
          pstr_env_0->ienvelope[i][j] = ptr_scale_factor_band_nrg[0][c];
          pstr_env_1->ienvelope[i][j] = ptr_scale_factor_band_nrg[1][c];

          c++;
        }
        i++;
      }

      err_code = ixheaace_code_envelope(
          ptr_noise_level[0], res, &pstr_env_ch[0]->str_sbr_code_noise_floor,
          pstr_env_0->domain_vec_noise, 0, (pstr_const_frame_info[0]->n_envelopes > 1 ? 2 : 1), 0,
          pstr_sbr_bs->header_active, pstr_sbr_bs->usac_indep_flag, pstr_sbr_cfg->is_ld_sbr);
      if (err_code) {
        return err_code;
      }

      i = 0;
      while (i < MAXIMUM_NUM_NOISE_VALUES) {
        pstr_env_0->noise_level[i] = ptr_noise_level[0][i];
        i++;
      }

      err_code = ixheaace_code_envelope(
          ptr_noise_level[1], res, &pstr_env_ch[1]->str_sbr_code_noise_floor,
          pstr_env_1->domain_vec_noise, 0, (pstr_const_frame_info[1]->n_envelopes > 1 ? 2 : 1), 0,
          pstr_sbr_bs->header_active, pstr_sbr_bs->usac_indep_flag, pstr_sbr_cfg->is_ld_sbr);
      if (err_code) {
        return err_code;
      }

      i = 0;
      while (i < MAXIMUM_NUM_NOISE_VALUES) {
        pstr_env_1->noise_level[i] = ptr_noise_level[1][i];
        i++;
      }

      pstr_sbr_hdr->coupling = 0;
      pstr_env_0->balance = 0;
      pstr_env_1->balance = 0;

      err_code = ixheaace_count_sbr_channel_pair_element(
          pstr_sbr_hdr, pstr_sbr_bs, &pstr_env_ch[0]->enc_env_data, &pstr_env_ch[1]->enc_env_data,
          pstr_com_data, ptr_sbr_tab, pstr_sbr_cfg->sbr_codec, pstr_sbr_cfg->is_esbr, &str_esbr,
          &payloadbits_lr);
      if (err_code) {
        return err_code;
      }

      for (ch = 0; ch < num_channels; ch++) {
        WORD32 itmp;

        for (i = 0; i < MAXIMUM_FREQ_COEFFS; i++) {
          itmp = pstr_env_ch[ch]->str_sbr_code_env.sfb_nrg_prev[i];
          pstr_env_ch[ch]->str_sbr_code_env.sfb_nrg_prev[i] =
              scale_factor_band_nrg_prev_temp[ch][i];
          scale_factor_band_nrg_prev_temp[ch][i] = itmp;
        }

        for (i = 0; i < MAXIMUM_NUM_NOISE_COEFFS; i++) {
          itmp = pstr_env_ch[ch]->str_sbr_code_noise_floor.sfb_nrg_prev[i];
          pstr_env_ch[ch]->str_sbr_code_noise_floor.sfb_nrg_prev[i] = noise_prev_temp[ch][i];
          noise_prev_temp[ch][i] = itmp;
        }

        itmp = pstr_env_ch[ch]->str_sbr_code_env.update;
        pstr_env_ch[ch]->str_sbr_code_env.update = up_date_nrg_temp[ch];
        up_date_nrg_temp[ch] = itmp;

        itmp = pstr_env_ch[ch]->str_sbr_code_noise_floor.update;
        pstr_env_ch[ch]->str_sbr_code_noise_floor.update = up_date_noise_temp[ch];
        up_date_noise_temp[ch] = itmp;

        memcpy(domain_vec_temp[ch], pstr_env_ch[ch]->enc_env_data.domain_vec,
               sizeof(domain_vec_temp[0][0]) * IXHEAACE_MAX_ENV);

        memcpy(domain_vec_noise_temp[ch], pstr_env_ch[ch]->enc_env_data.domain_vec_noise,
               sizeof(domain_vec_noise_temp[0][0]) * IXHEAACE_MAX_ENV);

        if (!pstr_sbr_hdr->prev_coupling) {
          pstr_env_ch[ch]->str_sbr_code_env.update = 0;
          pstr_env_ch[ch]->str_sbr_code_noise_floor.update = 0;
        }
      }

      err_code = ixheaace_code_envelope(
          ptr_sfb_nrg_coupling[0], pstr_const_frame_info[0]->freq_res,
          &pstr_env_ch[0]->str_sbr_code_env, pstr_env_0->domain_vec, 1,
          pstr_const_frame_info[0]->n_envelopes, 0, pstr_sbr_bs->header_active,
          pstr_sbr_bs->usac_indep_flag, pstr_sbr_cfg->is_ld_sbr);
      if (err_code) {
        return err_code;
      }

      err_code = ixheaace_code_envelope(
          ptr_sfb_nrg_coupling[1], pstr_const_frame_info[1]->freq_res,
          &pstr_env_ch[1]->str_sbr_code_env, pstr_env_1->domain_vec, 1,
          pstr_const_frame_info[1]->n_envelopes, 1, pstr_sbr_bs->header_active,
          pstr_sbr_bs->usac_indep_flag, pstr_sbr_cfg->is_ld_sbr);
      if (err_code) {
        return err_code;
      }

      c = 0;
      i = 0;
      while (i < n_envelopes[0]) {
        for (j = 0; j < pstr_env_0->no_scf_bands[i]; j++) {
          pstr_env_0->ienvelope[i][j] = ptr_sfb_nrg_coupling[0][c];
          pstr_env_1->ienvelope[i][j] = ptr_sfb_nrg_coupling[1][c];
          c++;
        }
        i++;
      }

      err_code = ixheaace_code_envelope(
          ptr_noise_lvl_coupling[0], res, &pstr_env_ch[0]->str_sbr_code_noise_floor,
          pstr_env_0->domain_vec_noise, 1, (pstr_const_frame_info[0]->n_envelopes > 1 ? 2 : 1), 0,
          pstr_sbr_bs->header_active, pstr_sbr_bs->usac_indep_flag, pstr_sbr_cfg->is_ld_sbr);
      if (err_code) {
        return err_code;
      }

      for (i = 0; i < MAXIMUM_NUM_NOISE_VALUES; i++) {
        pstr_env_0->noise_level[i] = ptr_noise_lvl_coupling[0][i];
      }

      err_code = ixheaace_code_envelope(
          ptr_noise_lvl_coupling[1], res, &pstr_env_ch[1]->str_sbr_code_noise_floor,
          pstr_env_1->domain_vec_noise, 1, ((pstr_const_frame_info[1]->n_envelopes > 1) ? 2 : 1),
          1, pstr_sbr_bs->header_active, pstr_sbr_bs->usac_indep_flag, pstr_sbr_cfg->is_ld_sbr);
      if (err_code) {
        return err_code;
      }

      for (i = 0; i < MAXIMUM_NUM_NOISE_VALUES; i++) {
        pstr_env_1->noise_level[i] = ptr_noise_lvl_coupling[1][i];
      }

      pstr_sbr_hdr->coupling = 1;

      pstr_env_0->balance = 0;
      pstr_env_1->balance = 1;

      temp_flag_left = pstr_env_0->add_harmonic_flag;
      temp_flag_right = pstr_env_1->add_harmonic_flag;

      err_code = ixheaace_count_sbr_channel_pair_element(
          pstr_sbr_hdr, pstr_sbr_bs, &pstr_env_ch[0]->enc_env_data, &pstr_env_ch[1]->enc_env_data,
          pstr_com_data, ptr_sbr_tab, pstr_sbr_cfg->sbr_codec, pstr_sbr_cfg->is_esbr, &str_esbr,
          &payloadbits_coupling);
      if (err_code) {
        return err_code;
      }

      pstr_env_0->add_harmonic_flag = temp_flag_left;
      pstr_env_1->add_harmonic_flag = temp_flag_right;

      if (payloadbits_coupling < payloadbits_lr) {
        ch = 0;
        while (ch < num_channels) {
          memcpy(ptr_scale_factor_band_nrg[ch], ptr_sfb_nrg_coupling[ch],
                 MAXIMUM_NUM_ENVELOPE_VALUES * sizeof(ptr_scale_factor_band_nrg[0][0]));

          memcpy(ptr_noise_level[ch], ptr_noise_lvl_coupling[ch],
                 MAXIMUM_NUM_NOISE_VALUES * sizeof(ptr_noise_level[0][0]));
          ch++;
        }

        pstr_sbr_hdr->coupling = 1;
        pstr_env_0->balance = 0;
        pstr_env_1->balance = 1;
      } else {
        ch = 0;
        while (ch < num_channels) {
          memcpy(pstr_env_ch[ch]->str_sbr_code_env.sfb_nrg_prev,
                 scale_factor_band_nrg_prev_temp[ch],
                 MAXIMUM_FREQ_COEFFS * sizeof(scale_factor_band_nrg_prev_temp[0][0]));

          pstr_env_ch[ch]->str_sbr_code_env.update = up_date_nrg_temp[ch];

          memcpy(pstr_env_ch[ch]->str_sbr_code_noise_floor.sfb_nrg_prev, noise_prev_temp[ch],
                 MAXIMUM_NUM_NOISE_COEFFS * sizeof(noise_prev_temp[0][0]));

          memcpy(pstr_env_ch[ch]->enc_env_data.domain_vec, domain_vec_temp[ch],
                 sizeof(domain_vec_temp[0][0]) * IXHEAACE_MAX_ENV);

          memcpy(pstr_env_ch[ch]->enc_env_data.domain_vec_noise, domain_vec_noise_temp[ch],
                 sizeof(domain_vec_noise_temp[0][0]) * IXHEAACE_MAX_ENV);

          pstr_env_ch[ch]->str_sbr_code_noise_floor.update = up_date_noise_temp[ch];
          ch++;
        }

        pstr_sbr_hdr->coupling = 0;
        pstr_env_0->balance = 0;
        pstr_env_1->balance = 0;
      }
    } break;
  }

  if (num_channels == 1) {
    if (pstr_env_0->domain_vec[0] == TIME) {
      pstr_env_ch[0]->str_sbr_code_env.df_edge_incr_fac++;
    } else {
      pstr_env_ch[0]->str_sbr_code_env.df_edge_incr_fac = 0;
    }
  } else {
    if (pstr_env_0->domain_vec[0] == TIME || pstr_env_1->domain_vec[0] == TIME) {
      pstr_env_ch[0]->str_sbr_code_env.df_edge_incr_fac++;
      pstr_env_ch[1]->str_sbr_code_env.df_edge_incr_fac++;
    } else {
      pstr_env_ch[0]->str_sbr_code_env.df_edge_incr_fac = 0;
      pstr_env_ch[1]->str_sbr_code_env.df_edge_incr_fac = 0;
    }
  }

  for (ch = 0; ch < num_channels; ch++) {
    c = 0;
    i = 0;

    while (i < n_envelopes[ch]) {
      for (j = 0; j < pstr_env_ch[ch]->enc_env_data.no_scf_bands[i]; j++) {
        pstr_env_ch[ch]->enc_env_data.ienvelope[i][j] = ptr_scale_factor_band_nrg[ch][c];
        c++;
      }
      i++;
    }

    i = 0;
    while (i < MAXIMUM_NUM_NOISE_VALUES) {
      pstr_env_ch[ch]->enc_env_data.noise_level[i] = ptr_noise_level[ch][i];
      i++;
    }
  }
  if ((USAC_SBR == pstr_sbr_cfg->sbr_codec) && (1 == pstr_sbr_hdr->sbr_inter_tes_active)) {
    // inter-TES encoder
    WORD32 idx;
    for (ch = 0; ch < num_channels; ch++) {
      ixheaace_str_inter_tes_params *pstr_tes_enc = &pstr_env_ch[ch]->str_inter_tes_enc;

      pstr_tes_enc->num_if_bands = pstr_env_ch[ch]->enc_env_data.noise_band_count;
      pstr_tes_enc->sub_band_start = pstr_sbr_cfg->ptr_freq_band_tab[LO][0];
      pstr_tes_enc->sub_band_end = pstr_sbr_cfg->ptr_freq_band_tab[LO][pstr_sbr_cfg->num_scf[LO]];
      pstr_tes_enc->num_mf_bands = pstr_sbr_cfg->num_master;
      pstr_tes_enc->out_fs = pstr_sbr_cfg->sample_freq;
      pstr_tes_enc->num_env = pstr_env_ch[ch]->str_sbr_env_frame.sbr_grid.bs_num_env;

      for (idx = 0; idx < (IXHEAACE_MAX_ENV + 1); idx++) {
        pstr_tes_enc->border_vec[idx] = (WORD16)pstr_const_frame_info[ch]->borders[idx];
      }

      for (idx = 0; idx < (MAXIMUM_FREQ_COEFFS + 1); idx++) {
        pstr_tes_enc->f_master_tbl[idx] = (WORD16)((UWORD16)pstr_sbr_cfg->ptr_v_k_master[idx]);
      }

      for (idx = 0; idx < MAXIMUM_NUM_NOISE_VALUES; idx++) {
        pstr_tes_enc->inv_filt_mode[idx] =
            (WORD32)pstr_env_ch[ch]->enc_env_data.sbr_invf_mode_vec[idx];
        pstr_tes_enc->invf_band_tbl[idx] =
            (WORD16)pstr_env_ch[ch]->str_ton_corr.sbr_noise_floor_est.s_freq_qmf_band_tbl[idx];
      }
      pstr_tes_enc->invf_band_tbl[MAXIMUM_NUM_NOISE_VALUES] =
          (WORD16)pstr_env_ch[ch]
              ->str_ton_corr.sbr_noise_floor_est.s_freq_qmf_band_tbl[MAXIMUM_NUM_NOISE_VALUES];

      err_code = ixheaace_process_inter_tes(pstr_tes_enc, ptr_sbr_scratch);
      if (err_code) {
        return err_code;
      }

      WORD32 ts, num_ts, delay;
      num_ts = pstr_env_ch[ch]->str_sbr_qmf.num_time_slots;

      delay = pstr_tes_enc->op_delay + pstr_tes_enc->codec_delay + IXHEAACE_SBR_HF_ADJ_OFFSET;

      for (ts = 0; ts < delay; ts++) {
        memcpy(pstr_tes_enc->qmf_buf_real[ts], pstr_tes_enc->qmf_buf_real[num_ts + ts],
               IXHEAACE_QMF_CHANNELS * sizeof(pstr_tes_enc->qmf_buf_real[0][0]));
        memcpy(pstr_tes_enc->qmf_buf_imag[ts], pstr_tes_enc->qmf_buf_imag[num_ts + ts],
               IXHEAACE_QMF_CHANNELS * sizeof(pstr_tes_enc->qmf_buf_imag[0][0]));
      }
    }
  }
  // Pitch detection, pre-processing detection and oversampling decision making
  if ((1 == pstr_sbr_cfg->is_esbr) && (pstr_sbr_cfg->sbr_codec == HEAAC_SBR)) {
    err_code = ixheaace_update_esbr_ext_data(
        ptr_in_time, pstr_sbr_cfg, pstr_env_ch[0]->str_sbr_extract_env.ptr_r_buffer[0], &str_esbr,
        transient_info, ptr_sbr_tab, pstr_sbr_hdr->coupling, time_sn_stride, 2048);
    if (err_code) return err_code;
  }

  if ((pstr_sbr_cfg->sbr_codec == USAC_SBR) && (pstr_sbr_hdr->sbr_harmonic)) {
    ixheaace_update_harmonic_sbr_data(transient_info, pstr_sbr_hdr->coupling,
                                      &pstr_env_ch[0], num_channels);
  }
  if (num_channels == 2) {
    WORD32 num_bits;
    pstr_env_0->usac_indep_flag = pstr_sbr_bs->usac_indep_flag;
    pstr_env_1->usac_indep_flag = pstr_sbr_bs->usac_indep_flag;
    err_code = ixheaace_write_env_channel_pair_element(
        pstr_sbr_hdr, pstr_sbr_bs, &pstr_env_ch[0]->enc_env_data, &pstr_env_ch[1]->enc_env_data,
        pstr_com_data, ptr_sbr_tab, pstr_sbr_cfg->sbr_codec, pstr_sbr_cfg->is_esbr, &str_esbr,
        &num_bits);
    if (err_code) {
      return err_code;
    }
  } else {
    WORD32 num_bits;
    pstr_env_0->sbr_pvc_mode = pstr_sbr_hdr->sbr_pvc_mode;
    pstr_env_0->sbr_sinusoidal_pos_flag = 0;
    pstr_env_0->usac_indep_flag = pstr_sbr_bs->usac_indep_flag;

    err_code = ixheaace_write_env_single_channel_element(
        pstr_sbr_hdr, pstr_sbr_bs, &pstr_env_ch[0]->enc_env_data, pstr_ps_enc, pstr_com_data,
        ptr_sbr_tab, pstr_sbr_cfg->sbr_codec, pstr_sbr_cfg->is_esbr, &str_esbr, &num_bits);
    if (err_code) {
      return err_code;
    }
  }

  ch = 0;
  while (ch < num_channels) {
    ixheaace_str_sbr_extr_env *pstr_sbr_extract_env = &(pstr_env_ch[ch]->str_sbr_extract_env);
    for (i = 0; i < pstr_sbr_extract_env->y_buffer_write_offset; i++) {
      FLOAT32 *ptr_tmp;
      ptr_tmp = pstr_sbr_extract_env->ptr_y_buffer[i];
      pstr_sbr_extract_env->ptr_y_buffer[i] =
          pstr_sbr_extract_env->ptr_y_buffer[i + (pstr_sbr_extract_env->no_cols >> 1)];
      pstr_sbr_extract_env->ptr_y_buffer[i + (pstr_sbr_extract_env->no_cols >> 1)] = ptr_tmp;
    }

    pstr_sbr_extract_env->buffer_flag ^= 1;
    ch++;
  }

  pstr_sbr_hdr->prev_coupling = pstr_sbr_hdr->coupling;

  return err_code;
}
