Coverage Report

Created: 2026-09-03 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libxaac/encoder/ixheaace_mps_dmx_tdom_enh.c
Line
Count
Source
1
/******************************************************************************
2
 *                                                                            *
3
 * Copyright (C) 2023 The Android Open Source Project
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at:
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 *****************************************************************************
18
 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19
 */
20
21
#include <math.h>
22
#include "ixheaac_type_def.h"
23
#include "ixheaac_constants.h"
24
#include "ixheaac_error_standards.h"
25
#include "ixheaace_error_codes.h"
26
#include "ixheaace_mps_common_fix.h"
27
28
#include "ixheaace_mps_common_define.h"
29
#include "ixheaace_mps_defines.h"
30
#include "ixheaac_constants.h"
31
#include "ixheaace_mps_dmx_tdom_enh.h"
32
#include "ixheaac_basic_ops32.h"
33
#include "ixheaac_basic_ops40.h"
34
#include "ixheaac_basic_ops.h"
35
36
static VOID ixheaace_mps_212_calculate_ratio(const FLOAT32 sqrt_lin_cld_m,
37
                                             const FLOAT32 lin_cld_m, const FLOAT32 icc_m,
38
90.8k
                                             FLOAT32 g_m[2]) {
39
90.8k
  if (icc_m >= 0.f) {
40
88.3k
    g_m[0] = g_m[1] = 1.0f;
41
88.3k
  } else {
42
2.47k
    FLOAT32 max_gain_factor = 2.0f;
43
2.47k
    FLOAT32 numerator, denominator;
44
2.47k
    FLOAT32 q = 0.0f;
45
2.47k
    numerator = (lin_cld_m + 0.5f) + (icc_m * sqrt_lin_cld_m);
46
2.47k
    denominator = (lin_cld_m + 0.5f) - (icc_m * sqrt_lin_cld_m);
47
48
2.47k
    if ((numerator > (0.f)) && (denominator > (0.f))) {
49
2.47k
      FLOAT32 intermediate;
50
2.47k
      intermediate = numerator / denominator;
51
2.47k
      intermediate = (FLOAT32)sqrt(intermediate);
52
2.47k
      intermediate = (FLOAT32)sqrt(intermediate);
53
2.47k
      q = (intermediate >= max_gain_factor) ? max_gain_factor : intermediate;
54
2.47k
    }
55
56
2.47k
    g_m[0] = max_gain_factor - q;
57
2.47k
    g_m[1] = q;
58
2.47k
  }
59
90.8k
}
60
61
static VOID ixheaace_mps_212_calculate_dmx_gains(const FLOAT32 lin_cld_m,
62
                                                 const FLOAT32 lin_cld_2_m, const FLOAT32 icc_m,
63
90.8k
                                                 const FLOAT32 g_m[2], FLOAT32 h_1_m[2]) {
64
90.8k
  const FLOAT32 max_gain_factor = 2.0f;
65
90.8k
  FLOAT32 energy_right, energy_left, cross_energy, inverse_weight_num, inverse_weight_den,
66
90.8k
      inverse_weight, inverse_weight_limited;
67
90.8k
  energy_right = lin_cld_2_m - 0.5f;
68
90.8k
  energy_right = (FLOAT32)sqrt(energy_right);
69
90.8k
  energy_left = lin_cld_m * energy_right;
70
90.8k
  cross_energy = (FLOAT32)sqrt(energy_left * energy_right);
71
90.8k
  inverse_weight_num = energy_right + energy_left;
72
90.8k
  inverse_weight_den = ((g_m[0] * g_m[0]) * energy_left) + ((g_m[1] * g_m[1]) * energy_right);
73
74
90.8k
  inverse_weight_den = ((((g_m[0] * g_m[1]) * cross_energy) * icc_m) * 2) + inverse_weight_den;
75
76
90.8k
  if (inverse_weight_den > (0.f)) {
77
87.6k
    inverse_weight = inverse_weight_num / inverse_weight_den;
78
79
87.6k
    inverse_weight = (FLOAT32)sqrt(inverse_weight);
80
81
87.6k
    inverse_weight_limited =
82
87.6k
        (inverse_weight >= max_gain_factor) ? max_gain_factor : inverse_weight;
83
87.6k
  } else {
84
3.20k
    inverse_weight_limited = max_gain_factor;
85
3.20k
  }
86
87
90.8k
  h_1_m[1] = g_m[1] * inverse_weight_limited;
88
90.8k
  h_1_m[0] = g_m[0] * inverse_weight_limited;
89
90.8k
}
90
91
IA_ERRORCODE ixheaace_mps_212_init_enhanced_time_domain_dmx(
92
    ixheaace_mps_pstr_enhanced_time_domain_dmx pstr_enhanced_time_domain_dmx,
93
    const FLOAT32 *const ptr_input_gain_m_flt, const FLOAT32 output_gain_m_flt,
94
1.26k
    const WORD32 frame_length) {
95
1.26k
  IA_ERRORCODE error = IA_NO_ERROR;
96
1.26k
  WORD32 sample_idx;
97
1.26k
  FLOAT32 delta;
98
1.26k
  if (frame_length > pstr_enhanced_time_domain_dmx->max_frame_length) {
99
0
    return IA_EXHEAACE_INIT_FATAL_MPS_INIT_FAILED;
100
0
  }
101
1.26k
  pstr_enhanced_time_domain_dmx->frame_length = frame_length;
102
1.26k
  delta = (FLOAT32)(PI_FLT / (2.0 * pstr_enhanced_time_domain_dmx->frame_length));
103
2.69M
  for (sample_idx = 0; sample_idx < pstr_enhanced_time_domain_dmx->frame_length + 1;
104
2.69M
       sample_idx++) {
105
2.69M
    FLOAT32 sin_val = (FLOAT32)sin(sample_idx * delta);
106
2.69M
    pstr_enhanced_time_domain_dmx->sinus_window[sample_idx] = ALPHA * sin_val * sin_val;
107
2.69M
  }
108
109
1.26k
  pstr_enhanced_time_domain_dmx->prev_left_energy =
110
1.26k
      pstr_enhanced_time_domain_dmx->prev_right_energy =
111
1.26k
          pstr_enhanced_time_domain_dmx->prev_x_energy = 0.0f;
112
1.26k
  pstr_enhanced_time_domain_dmx->cld_weight =
113
1.26k
      (ptr_input_gain_m_flt[LEFT_CH]) / (ptr_input_gain_m_flt[RIGHT_CH]);
114
1.26k
  pstr_enhanced_time_domain_dmx->gain_weight[LEFT_CH] =
115
1.26k
      (ptr_input_gain_m_flt[LEFT_CH] * output_gain_m_flt);
116
1.26k
  pstr_enhanced_time_domain_dmx->gain_weight[RIGHT_CH] =
117
1.26k
      (ptr_input_gain_m_flt[RIGHT_CH] * output_gain_m_flt);
118
1.26k
  pstr_enhanced_time_domain_dmx->prev_gain[LEFT_CH] =
119
1.26k
      pstr_enhanced_time_domain_dmx->gain_weight[LEFT_CH];
120
1.26k
  pstr_enhanced_time_domain_dmx->prev_gain[RIGHT_CH] =
121
1.26k
      pstr_enhanced_time_domain_dmx->gain_weight[RIGHT_CH];
122
1.26k
  pstr_enhanced_time_domain_dmx->prev_h1[LEFT_CH] =
123
1.26k
      pstr_enhanced_time_domain_dmx->gain_weight[LEFT_CH];
124
1.26k
  pstr_enhanced_time_domain_dmx->prev_h1[RIGHT_CH] =
125
1.26k
      pstr_enhanced_time_domain_dmx->gain_weight[RIGHT_CH];
126
1.26k
  return error;
127
1.26k
}
128
129
IA_ERRORCODE ixheaace_mps_212_apply_enhanced_time_domain_dmx(
130
    ixheaace_mps_pstr_enhanced_time_domain_dmx pstr_enhanced_time_domain_dmx,
131
    FLOAT32 input_time[2][MPS_MAX_FRAME_LENGTH + MAX_DELAY_SURROUND_ANALYSIS],
132
90.8k
    FLOAT32 *const ptr_output_time_dmx, const WORD32 input_delay) {
133
90.8k
  IA_ERRORCODE error = IA_NO_ERROR;
134
135
90.8k
  WORD32 sample_idx;
136
90.8k
  FLOAT32 lin_bb_cld, lin_cld, corr, sqrt_lin_cld, g[2], h1[2], gain_left, gain_right;
137
90.8k
  FLOAT32 prev_energy_left, prev_energy_right, prev_energy, energy_left, energy_right, energy_out;
138
90.8k
  WORD32 granule_length = MIN(128, pstr_enhanced_time_domain_dmx->frame_length);
139
140
90.8k
  sample_idx = 0;
141
90.8k
  prev_energy_left = prev_energy_right = prev_energy = .5f;
142
143
1.55M
  do {
144
1.55M
    WORD32 offset = sample_idx;
145
1.55M
    FLOAT32 partial_left, partial_right, partial_out;
146
1.55M
    partial_left = partial_right = partial_out = 0.0;
147
148
1.55M
    WORD32 value = MIN(offset + granule_length, pstr_enhanced_time_domain_dmx->frame_length);
149
199M
    for (sample_idx = offset; sample_idx < value; sample_idx++) {
150
198M
      FLOAT32 input_left = input_time[LEFT_CH][sample_idx];
151
198M
      FLOAT32 input_right = input_time[RIGHT_CH][sample_idx];
152
153
198M
      partial_left += (FLOAT32)pow(input_left, 2);
154
198M
      partial_right += (FLOAT32)pow(input_right, 2);
155
198M
      partial_out += input_left * input_right;
156
198M
    }
157
158
1.55M
    prev_energy_left = prev_energy_left + partial_left;
159
1.55M
    prev_energy_right = prev_energy_right + partial_right;
160
1.55M
    prev_energy = prev_energy + partial_out;
161
162
1.55M
  } while (sample_idx < pstr_enhanced_time_domain_dmx->frame_length);
163
164
90.8k
  energy_left = pstr_enhanced_time_domain_dmx->prev_left_energy + prev_energy_left;
165
90.8k
  energy_right = pstr_enhanced_time_domain_dmx->prev_right_energy + prev_energy_right;
166
90.8k
  energy_out = pstr_enhanced_time_domain_dmx->prev_x_energy + prev_energy;
167
168
90.8k
  lin_bb_cld = pstr_enhanced_time_domain_dmx->cld_weight * (energy_left / energy_right);
169
90.8k
  corr = energy_out * (1 / (FLOAT32)sqrt(energy_left * energy_right));
170
171
90.8k
  pstr_enhanced_time_domain_dmx->prev_left_energy = prev_energy_left;
172
90.8k
  pstr_enhanced_time_domain_dmx->prev_right_energy = prev_energy_right;
173
90.8k
  pstr_enhanced_time_domain_dmx->prev_x_energy = prev_energy;
174
175
90.8k
  lin_cld = (FLOAT32)sqrt(lin_bb_cld);
176
90.8k
  sqrt_lin_cld = (FLOAT32)sqrt(lin_cld);
177
178
90.8k
  ixheaace_mps_212_calculate_ratio(sqrt_lin_cld, lin_cld, corr, g);
179
180
90.8k
  ixheaace_mps_212_calculate_dmx_gains(lin_cld, lin_bb_cld, corr, g, h1);
181
182
90.8k
  h1[LEFT_CH] = h1[LEFT_CH] * pstr_enhanced_time_domain_dmx->gain_weight[LEFT_CH];
183
90.8k
  h1[RIGHT_CH] = h1[RIGHT_CH] * pstr_enhanced_time_domain_dmx->gain_weight[RIGHT_CH];
184
185
90.8k
  gain_left = pstr_enhanced_time_domain_dmx->prev_gain[LEFT_CH];
186
90.8k
  gain_right = pstr_enhanced_time_domain_dmx->prev_gain[RIGHT_CH];
187
188
198M
  for (sample_idx = 0; sample_idx < pstr_enhanced_time_domain_dmx->frame_length; sample_idx++) {
189
198M
    WORD32 frame_length = pstr_enhanced_time_domain_dmx->frame_length;
190
198M
    FLOAT32 intermediate_gain_left, intermediate_gain_right, temp;
191
192
198M
    intermediate_gain_left =
193
198M
        ((pstr_enhanced_time_domain_dmx->sinus_window[sample_idx] * h1[LEFT_CH]) +
194
198M
         (pstr_enhanced_time_domain_dmx->sinus_window[frame_length - sample_idx] *
195
198M
          pstr_enhanced_time_domain_dmx->prev_h1[LEFT_CH]));
196
197
198M
    intermediate_gain_right =
198
198M
        ((pstr_enhanced_time_domain_dmx->sinus_window[sample_idx] * h1[RIGHT_CH]) +
199
198M
         (pstr_enhanced_time_domain_dmx->sinus_window[frame_length - sample_idx] *
200
198M
          pstr_enhanced_time_domain_dmx->prev_h1[RIGHT_CH]));
201
202
198M
    gain_left = intermediate_gain_left + ((1.f - ALPHA) * gain_left);
203
198M
    gain_right = intermediate_gain_right + ((1.f - ALPHA) * gain_right);
204
198M
    temp = (gain_left * (FLOAT32)input_time[LEFT_CH][sample_idx + input_delay]) +
205
198M
           (gain_right * (FLOAT32)input_time[RIGHT_CH][sample_idx + input_delay]);
206
198M
    ptr_output_time_dmx[sample_idx] = (FLOAT32)temp;
207
198M
  }
208
209
90.8k
  pstr_enhanced_time_domain_dmx->prev_gain[LEFT_CH] = gain_left;
210
90.8k
  pstr_enhanced_time_domain_dmx->prev_gain[RIGHT_CH] = gain_right;
211
90.8k
  pstr_enhanced_time_domain_dmx->prev_h1[LEFT_CH] = h1[LEFT_CH];
212
90.8k
  pstr_enhanced_time_domain_dmx->prev_h1[RIGHT_CH] = h1[RIGHT_CH];
213
214
90.8k
  return error;
215
90.8k
}