Coverage Report

Created: 2026-04-12 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libxaac/decoder/ixheaacd_mps_temp_reshape.c
Line
Count
Source
1
/******************************************************************************
2
 *                                                                            *
3
 * Copyright (C) 2018 The Android Open Source Project
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at:
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 *****************************************************************************
18
 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19
*/
20
#include <math.h>
21
#include "ixheaac_type_def.h"
22
#include "ixheaac_constants.h"
23
#include "ixheaacd_bitbuffer.h"
24
#include "ixheaacd_common_rom.h"
25
#include "ixheaacd_sbrdecsettings.h"
26
#include "ixheaacd_sbr_scale.h"
27
#include "ixheaacd_env_extr_part.h"
28
#include "ixheaacd_sbr_rom.h"
29
#include "ixheaacd_hybrid.h"
30
#include "ixheaacd_ps_dec.h"
31
#include "ixheaacd_config.h"
32
#include "ixheaacd_qmf_dec.h"
33
#include "ixheaacd_mps_polyphase.h"
34
#include "ixheaacd_mps_struct_def.h"
35
#include "ixheaacd_mps_res_rom.h"
36
#include "ixheaacd_mps_aac_struct.h"
37
#include "ixheaacd_mps_dec.h"
38
39
19.4k
#define DIR_DIFF_IN 0
40
9.73k
#define DOWNMIX_IN 1
41
42
#define LAMDA (4.0f)
43
10.6M
#define GES_ALPHA (0.99637864f)
44
1.06M
#define GES_BETA (0.9643691f)
45
46
extern const WORD32
47
    ixheaacd_hybrid_band_71_to_processing_band_20_map[MAX_HYBRID_BANDS_MPS];
48
49
2.29k
VOID ixheaacd_mps_env_init(ia_mps_dec_state_struct *self) {
50
2.29k
  WORD32 i;
51
9.19k
  for (i = 0; i < 3; i++) {
52
6.89k
    self->guided_env_shaping.avg_energy_prev[i] = 32768.f * 32768.f;
53
6.89k
  }
54
2.29k
}
55
56
static VOID ixheaacd_mps_est_normalized_envelope(ia_mps_dec_state_struct *self,
57
                                                 WORD32 inp, WORD32 ch,
58
14.5k
                                                 FLOAT32 *env) {
59
14.5k
  FLOAT32 slot_energy[MAX_TIME_SLOTS][MAX_PARAMETER_BANDS] = {{0}};
60
14.5k
  FLOAT32 pb_energy[MAX_PARAMETER_BANDS] = {0};
61
14.5k
  FLOAT32 whitening_weight[MAX_PARAMETER_BANDS];
62
14.5k
  WORD32 ii, jj, param_band;
63
64
14.5k
  WORD32 k_start = 10;
65
14.5k
  WORD32 k_stop = 18;
66
67
14.5k
  FLOAT32 total_energy = 0, avg_energy = 0;
68
69
14.5k
  WORD32 ch_offset;
70
71
14.5k
  switch (inp) {
72
9.73k
    case DIR_DIFF_IN:
73
9.73k
      ch_offset = 0;
74
363k
      for (ii = 0; ii < self->time_slots; ii++) {
75
14.0M
        for (jj = 0; jj < self->hyb_band_count_max; jj++) {
76
13.7M
          slot_energy[ii]
77
13.7M
                     [ixheaacd_hybrid_band_71_to_processing_band_20_map[jj]] +=
78
13.7M
              ((self->hyb_dir_out[ch][ii][jj].re +
79
13.7M
                self->hyb_diff_out[ch][ii][jj].re) *
80
13.7M
               (self->hyb_dir_out[ch][ii][jj].re +
81
13.7M
                self->hyb_diff_out[ch][ii][jj].re)) +
82
13.7M
              ((self->hyb_dir_out[ch][ii][jj].im +
83
13.7M
                self->hyb_diff_out[ch][ii][jj].im) *
84
13.7M
               (self->hyb_dir_out[ch][ii][jj].im +
85
13.7M
                self->hyb_diff_out[ch][ii][jj].im));
86
13.7M
        }
87
353k
      }
88
9.73k
      break;
89
4.86k
    case DOWNMIX_IN:
90
4.86k
      ch_offset = self->out_ch_count;
91
4.86k
      if ((self->pre_mix_req | self->bs_tsd_enable)) {
92
19.4k
        for (ii = 0; ii < self->time_slots; ii++) {
93
1.04M
          for (jj = 0; jj < self->hyb_band_count_max; jj++) {
94
1.02M
            slot_energy
95
1.02M
                [ii][ixheaacd_hybrid_band_71_to_processing_band_20_map[jj]] +=
96
1.02M
                self->hyb_in[ch][jj][ii].re * self->hyb_in[ch][jj][ii].re +
97
1.02M
                self->hyb_in[ch][jj][ii].im * self->hyb_in[ch][jj][ii].im;
98
1.02M
          }
99
18.8k
        }
100
4.27k
      } else {
101
162k
        for (ii = 0; ii < self->time_slots; ii++) {
102
5.99M
          for (jj = 0; jj < self->hyb_band_count_max; jj++) {
103
5.83M
            slot_energy
104
5.83M
                [ii][ixheaacd_hybrid_band_71_to_processing_band_20_map[jj]] +=
105
5.83M
                self->w_dir[ch][ii][jj].re * self->w_dir[ch][ii][jj].re +
106
5.83M
                self->w_dir[ch][ii][jj].im * self->w_dir[ch][ii][jj].im;
107
5.83M
          }
108
157k
        }
109
4.27k
      }
110
111
4.86k
      break;
112
0
    default:
113
0
      ch_offset = 0;
114
0
      break;
115
14.5k
  }
116
117
145k
  for (param_band = k_start; param_band <= k_stop; param_band++)
118
131k
    pb_energy[param_band] =
119
131k
        self->guided_env_shaping.pb_energy_prev[ch + ch_offset][param_band];
120
121
14.5k
  avg_energy = self->guided_env_shaping.avg_energy_prev[ch + ch_offset];
122
123
544k
  for (ii = 0; ii < self->time_slots; ii++) {
124
530k
    total_energy = 0;
125
5.30M
    for (param_band = k_start; param_band <= k_stop; param_band++) {
126
4.77M
      pb_energy[param_band] = (1 - GES_ALPHA) * slot_energy[ii][param_band] +
127
4.77M
                              GES_ALPHA * pb_energy[param_band];
128
129
4.77M
      total_energy += slot_energy[ii][param_band];
130
4.77M
    }
131
530k
    total_energy /= (k_stop - k_start + 1);
132
133
530k
    total_energy =
134
530k
        (1 - GES_ALPHA) * total_energy +
135
530k
        GES_ALPHA * self->guided_env_shaping.frame_energy_prev[ch + ch_offset];
136
137
530k
    self->guided_env_shaping.frame_energy_prev[ch + ch_offset] = total_energy;
138
139
5.30M
    for (param_band = k_start; param_band <= k_stop; param_band++) {
140
4.77M
      whitening_weight[param_band] =
141
4.77M
          total_energy / (pb_energy[param_band] + ABS_THR);
142
4.77M
    }
143
144
530k
    env[ii] = 0;
145
5.30M
    for (param_band = k_start; param_band <= k_stop; param_band++) {
146
4.77M
      env[ii] += slot_energy[ii][param_band] * whitening_weight[param_band];
147
4.77M
    }
148
149
530k
    avg_energy = (1 - GES_BETA) * env[ii] + GES_BETA * avg_energy;
150
151
530k
    env[ii] = (FLOAT32)sqrt(env[ii] / (avg_energy + ABS_THR));
152
530k
  }
153
154
145k
  for (param_band = k_start; param_band <= k_stop; param_band++)
155
131k
    self->guided_env_shaping.pb_energy_prev[ch + ch_offset][param_band] =
156
131k
        pb_energy[param_band];
157
158
14.5k
  self->guided_env_shaping.avg_energy_prev[ch + ch_offset] = avg_energy;
159
14.5k
}
160
161
4.86k
VOID ixheaacd_mps_time_env_shaping(ia_mps_dec_state_struct *self) {
162
4.86k
  FLOAT32 dir_energy[MAX_TIME_SLOTS];
163
4.86k
  FLOAT32 dmx_energy[MAX_TIME_SLOTS];
164
4.86k
  WORD32 ch, time_slot, jj;
165
166
4.86k
  WORD32 band_start;
167
4.86k
  FLOAT32 gain, ratio;
168
169
4.86k
  FLOAT32 amp_direct = 0;
170
4.86k
  FLOAT32 amp_diff = 0;
171
4.86k
  FLOAT32 amp_ratio;
172
173
4.86k
  band_start = 6;
174
175
4.86k
  ixheaacd_mps_est_normalized_envelope(self, DOWNMIX_IN, 0, dmx_energy);
176
177
14.5k
  for (ch = 0; ch < self->out_ch_count; ch++) {
178
9.73k
    ixheaacd_mps_est_normalized_envelope(self, DIR_DIFF_IN, ch, dir_energy);
179
180
9.73k
    if (self->temp_shape_enable_ch_ges[ch]) {
181
33.0k
      for (time_slot = 0; time_slot < self->time_slots; time_slot++) {
182
32.0k
        gain = self->env_shape_data[ch][time_slot] * dmx_energy[time_slot] /
183
32.0k
               (dir_energy[time_slot] + 1e-9f);
184
185
32.0k
        amp_direct = 0;
186
32.0k
        amp_diff = 0;
187
188
1.20M
        for (jj = band_start; jj < self->hyb_band_count_max; jj++) {
189
1.17M
          amp_direct += self->hyb_dir_out[ch][time_slot][jj].re *
190
1.17M
                            self->hyb_dir_out[ch][time_slot][jj].re +
191
1.17M
                        self->hyb_dir_out[ch][time_slot][jj].im *
192
1.17M
                            self->hyb_dir_out[ch][time_slot][jj].im;
193
194
1.17M
          amp_diff += self->hyb_diff_out[ch][time_slot][jj].re *
195
1.17M
                          self->hyb_diff_out[ch][time_slot][jj].re +
196
1.17M
                      self->hyb_diff_out[ch][time_slot][jj].im *
197
1.17M
                          self->hyb_diff_out[ch][time_slot][jj].im;
198
1.17M
        }
199
200
32.0k
        amp_ratio = (FLOAT32)sqrt(amp_diff / (amp_direct + ABS_THR));
201
202
32.0k
        ratio = min(max((gain + amp_ratio * (gain - 1)), 1 / LAMDA), LAMDA);
203
204
1.20M
        for (jj = band_start; jj < self->hyb_band_count_max; jj++) {
205
1.17M
          self->hyb_dir_out[ch][time_slot][jj].re *= ratio;
206
1.17M
          self->hyb_dir_out[ch][time_slot][jj].im *= ratio;
207
1.17M
        }
208
32.0k
      }
209
943
    }
210
9.73k
  }
211
4.86k
}