Coverage Report

Created: 2025-08-03 06:57

/src/libxaac/encoder/ixheaace_mps_dmx_tdom_enh.c
Line
Count
Source (jump to first uncovered line)
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
89.6k
                                             FLOAT32 g_m[2]) {
39
89.6k
  if (icc_m >= 0.f) {
40
88.3k
    g_m[0] = g_m[1] = 1.0f;
41
88.3k
  } else {
42
1.27k
    FLOAT32 max_gain_factor = 2.0f;
43
1.27k
    FLOAT32 numerator, denominator;
44
1.27k
    FLOAT32 q = 0.0f;
45
1.27k
    numerator = (lin_cld_m + 0.5f) + (icc_m * sqrt_lin_cld_m);
46
1.27k
    denominator = (lin_cld_m + 0.5f) - (icc_m * sqrt_lin_cld_m);
47
48
1.27k
    if ((numerator > (0.f)) && (denominator > (0.f))) {
49
1.27k
      FLOAT32 intermediate;
50
1.27k
      intermediate = numerator / denominator;
51
1.27k
      intermediate = (FLOAT32)sqrt(intermediate);
52
1.27k
      intermediate = (FLOAT32)sqrt(intermediate);
53
1.27k
      q = (intermediate >= max_gain_factor) ? max_gain_factor : intermediate;
54
1.27k
    }
55
56
1.27k
    g_m[0] = max_gain_factor - q;
57
1.27k
    g_m[1] = q;
58
1.27k
  }
59
89.6k
}
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
89.6k
                                                 const FLOAT32 g_m[2], FLOAT32 h_1_m[2]) {
64
89.6k
  const FLOAT32 max_gain_factor = 2.0f;
65
89.6k
  FLOAT32 energy_right, energy_left, cross_energy, inverse_weight_num, inverse_weight_den,
66
89.6k
      inverse_weight, inverse_weight_limited;
67
89.6k
  energy_right = lin_cld_2_m - 0.5f;
68
89.6k
  energy_right = (FLOAT32)sqrt(energy_right);
69
89.6k
  energy_left = lin_cld_m * energy_right;
70
89.6k
  cross_energy = (FLOAT32)sqrt(energy_left * energy_right);
71
89.6k
  inverse_weight_num = energy_right + energy_left;
72
89.6k
  inverse_weight_den = ((g_m[0] * g_m[0]) * energy_left) + ((g_m[1] * g_m[1]) * energy_right);
73
74
89.6k
  inverse_weight_den = ((((g_m[0] * g_m[1]) * cross_energy) * icc_m) * 2) + inverse_weight_den;
75
76
89.6k
  if (inverse_weight_den > (0.f)) {
77
88.6k
    inverse_weight = inverse_weight_num / inverse_weight_den;
78
79
88.6k
    inverse_weight = (FLOAT32)sqrt(inverse_weight);
80
81
88.6k
    inverse_weight_limited =
82
88.6k
        (inverse_weight >= max_gain_factor) ? max_gain_factor : inverse_weight;
83
88.6k
  } else {
84
1.03k
    inverse_weight_limited = max_gain_factor;
85
1.03k
  }
86
87
89.6k
  h_1_m[1] = g_m[1] * inverse_weight_limited;
88
89.6k
  h_1_m[0] = g_m[0] * inverse_weight_limited;
89
89.6k
}
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.42k
    const WORD32 frame_length) {
95
1.42k
  IA_ERRORCODE error = IA_NO_ERROR;
96
1.42k
  WORD32 sample_idx;
97
1.42k
  FLOAT32 delta;
98
1.42k
  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.42k
  pstr_enhanced_time_domain_dmx->frame_length = frame_length;
102
1.42k
  delta = (FLOAT32)(PI_FLT / (2.0 * pstr_enhanced_time_domain_dmx->frame_length));
103
3.00M
  for (sample_idx = 0; sample_idx < pstr_enhanced_time_domain_dmx->frame_length + 1;
104
2.99M
       sample_idx++) {
105
2.99M
    FLOAT32 sin_val = (FLOAT32)sin(sample_idx * delta);
106
2.99M
    pstr_enhanced_time_domain_dmx->sinus_window[sample_idx] = ALPHA * sin_val * sin_val;
107
2.99M
  }
108
109
1.42k
  pstr_enhanced_time_domain_dmx->prev_left_energy =
110
1.42k
      pstr_enhanced_time_domain_dmx->prev_right_energy =
111
1.42k
          pstr_enhanced_time_domain_dmx->prev_x_energy = 0.0f;
112
1.42k
  pstr_enhanced_time_domain_dmx->cld_weight =
113
1.42k
      (ptr_input_gain_m_flt[LEFT_CH]) / (ptr_input_gain_m_flt[RIGHT_CH]);
114
1.42k
  pstr_enhanced_time_domain_dmx->gain_weight[LEFT_CH] =
115
1.42k
      (ptr_input_gain_m_flt[LEFT_CH] * output_gain_m_flt);
116
1.42k
  pstr_enhanced_time_domain_dmx->gain_weight[RIGHT_CH] =
117
1.42k
      (ptr_input_gain_m_flt[RIGHT_CH] * output_gain_m_flt);
118
1.42k
  pstr_enhanced_time_domain_dmx->prev_gain[LEFT_CH] =
119
1.42k
      pstr_enhanced_time_domain_dmx->gain_weight[LEFT_CH];
120
1.42k
  pstr_enhanced_time_domain_dmx->prev_gain[RIGHT_CH] =
121
1.42k
      pstr_enhanced_time_domain_dmx->gain_weight[RIGHT_CH];
122
1.42k
  pstr_enhanced_time_domain_dmx->prev_h1[LEFT_CH] =
123
1.42k
      pstr_enhanced_time_domain_dmx->gain_weight[LEFT_CH];
124
1.42k
  pstr_enhanced_time_domain_dmx->prev_h1[RIGHT_CH] =
125
1.42k
      pstr_enhanced_time_domain_dmx->gain_weight[RIGHT_CH];
126
1.42k
  return error;
127
1.42k
}
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
89.6k
    FLOAT32 *const ptr_output_time_dmx, const WORD32 input_delay) {
133
89.6k
  IA_ERRORCODE error = IA_NO_ERROR;
134
135
89.6k
  WORD32 sample_idx;
136
89.6k
  FLOAT32 lin_bb_cld, lin_cld, corr, sqrt_lin_cld, g[2], h1[2], gain_left, gain_right;
137
89.6k
  FLOAT32 prev_energy_left, prev_energy_right, prev_energy, energy_left, energy_right, energy_out;
138
89.6k
  WORD32 granule_length = MIN(128, pstr_enhanced_time_domain_dmx->frame_length);
139
140
89.6k
  sample_idx = 0;
141
89.6k
  prev_energy_left = prev_energy_right = prev_energy = .5f;
142
143
1.53M
  do {
144
1.53M
    WORD32 offset = sample_idx;
145
1.53M
    FLOAT32 partial_left, partial_right, partial_out;
146
1.53M
    partial_left = partial_right = partial_out = 0.0;
147
148
1.53M
    WORD32 value = MIN(offset + granule_length, pstr_enhanced_time_domain_dmx->frame_length);
149
196M
    for (sample_idx = offset; sample_idx < value; sample_idx++) {
150
194M
      FLOAT32 input_left = input_time[LEFT_CH][sample_idx];
151
194M
      FLOAT32 input_right = input_time[RIGHT_CH][sample_idx];
152
153
194M
      partial_left += (FLOAT32)pow(input_left, 2);
154
194M
      partial_right += (FLOAT32)pow(input_right, 2);
155
194M
      partial_out += input_left * input_right;
156
194M
    }
157
158
1.53M
    prev_energy_left = prev_energy_left + partial_left;
159
1.53M
    prev_energy_right = prev_energy_right + partial_right;
160
1.53M
    prev_energy = prev_energy + partial_out;
161
162
1.53M
  } while (sample_idx < pstr_enhanced_time_domain_dmx->frame_length);
163
164
89.6k
  energy_left = pstr_enhanced_time_domain_dmx->prev_left_energy + prev_energy_left;
165
89.6k
  energy_right = pstr_enhanced_time_domain_dmx->prev_right_energy + prev_energy_right;
166
89.6k
  energy_out = pstr_enhanced_time_domain_dmx->prev_x_energy + prev_energy;
167
168
89.6k
  lin_bb_cld = pstr_enhanced_time_domain_dmx->cld_weight * (energy_left / energy_right);
169
89.6k
  corr = energy_out * (1 / (FLOAT32)sqrt(energy_left * energy_right));
170
171
89.6k
  pstr_enhanced_time_domain_dmx->prev_left_energy = prev_energy_left;
172
89.6k
  pstr_enhanced_time_domain_dmx->prev_right_energy = prev_energy_right;
173
89.6k
  pstr_enhanced_time_domain_dmx->prev_x_energy = prev_energy;
174
175
89.6k
  lin_cld = (FLOAT32)sqrt(lin_bb_cld);
176
89.6k
  sqrt_lin_cld = (FLOAT32)sqrt(lin_cld);
177
178
89.6k
  ixheaace_mps_212_calculate_ratio(sqrt_lin_cld, lin_cld, corr, g);
179
180
89.6k
  ixheaace_mps_212_calculate_dmx_gains(lin_cld, lin_bb_cld, corr, g, h1);
181
182
89.6k
  h1[LEFT_CH] = h1[LEFT_CH] * pstr_enhanced_time_domain_dmx->gain_weight[LEFT_CH];
183
89.6k
  h1[RIGHT_CH] = h1[RIGHT_CH] * pstr_enhanced_time_domain_dmx->gain_weight[RIGHT_CH];
184
185
89.6k
  gain_left = pstr_enhanced_time_domain_dmx->prev_gain[LEFT_CH];
186
89.6k
  gain_right = pstr_enhanced_time_domain_dmx->prev_gain[RIGHT_CH];
187
188
194M
  for (sample_idx = 0; sample_idx < pstr_enhanced_time_domain_dmx->frame_length; sample_idx++) {
189
194M
    WORD32 frame_length = pstr_enhanced_time_domain_dmx->frame_length;
190
194M
    FLOAT32 intermediate_gain_left, intermediate_gain_right, temp;
191
192
194M
    intermediate_gain_left =
193
194M
        ((pstr_enhanced_time_domain_dmx->sinus_window[sample_idx] * h1[LEFT_CH]) +
194
194M
         (pstr_enhanced_time_domain_dmx->sinus_window[frame_length - sample_idx] *
195
194M
          pstr_enhanced_time_domain_dmx->prev_h1[LEFT_CH]));
196
197
194M
    intermediate_gain_right =
198
194M
        ((pstr_enhanced_time_domain_dmx->sinus_window[sample_idx] * h1[RIGHT_CH]) +
199
194M
         (pstr_enhanced_time_domain_dmx->sinus_window[frame_length - sample_idx] *
200
194M
          pstr_enhanced_time_domain_dmx->prev_h1[RIGHT_CH]));
201
202
194M
    gain_left = intermediate_gain_left + ((1.f - ALPHA) * gain_left);
203
194M
    gain_right = intermediate_gain_right + ((1.f - ALPHA) * gain_right);
204
194M
    temp = (gain_left * (FLOAT32)input_time[LEFT_CH][sample_idx + input_delay]) +
205
194M
           (gain_right * (FLOAT32)input_time[RIGHT_CH][sample_idx + input_delay]);
206
194M
    ptr_output_time_dmx[sample_idx] = (FLOAT32)temp;
207
194M
  }
208
209
89.6k
  pstr_enhanced_time_domain_dmx->prev_gain[LEFT_CH] = gain_left;
210
89.6k
  pstr_enhanced_time_domain_dmx->prev_gain[RIGHT_CH] = gain_right;
211
89.6k
  pstr_enhanced_time_domain_dmx->prev_h1[LEFT_CH] = h1[LEFT_CH];
212
89.6k
  pstr_enhanced_time_domain_dmx->prev_h1[RIGHT_CH] = h1[RIGHT_CH];
213
214
89.6k
  return error;
215
89.6k
}