Coverage Report

Created: 2026-06-10 06:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libxaac/encoder/drc_src/impd_drc_enc.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 <string.h>
22
#include "ixheaac_type_def.h"
23
#include "ixheaac_error_standards.h"
24
#include "ixheaace_error_codes.h"
25
26
#include "iusace_bitbuffer.h"
27
#include "impd_drc_common_enc.h"
28
#include "impd_drc_uni_drc.h"
29
#include "impd_drc_tables.h"
30
#include "impd_drc_api.h"
31
#include "impd_drc_uni_drc_eq.h"
32
#include "impd_drc_uni_drc_filter_bank.h"
33
#include "impd_drc_gain_enc.h"
34
#include "impd_drc_struct_def.h"
35
#include "impd_drc_enc.h"
36
37
static VOID impd_drc_util_stft_read_gain_config(
38
    ia_drc_stft_gain_calc_struct *pstr_stft_drc_gain_handle, WORD32 band_count,
39
433
    ia_drc_gain_set_params_struct *str_gain_set_params) {
40
433
  LOOPIDX i, j;
41
433
  WORD32 num_points;
42
43
1.36k
  for (i = 0; i < band_count; i++) {
44
929
    num_points = str_gain_set_params->gain_params[i].nb_points;
45
929
    pstr_stft_drc_gain_handle[i].nb_points = num_points;
46
5.61k
    for (j = 0; j < num_points; j++) {
47
4.68k
      pstr_stft_drc_gain_handle[i].str_segment[2 * (j + 1)].x =
48
4.68k
          str_gain_set_params->gain_params[i].gain_points[j].x;
49
4.68k
      pstr_stft_drc_gain_handle[i].str_segment[2 * (j + 1)].y =
50
4.68k
          str_gain_set_params->gain_params[i].gain_points[j].y;
51
4.68k
    }
52
53
929
    pstr_stft_drc_gain_handle[i].width_db = str_gain_set_params->gain_params[i].width;
54
929
    pstr_stft_drc_gain_handle[i].attack_ms = str_gain_set_params->gain_params[i].attack;
55
929
    pstr_stft_drc_gain_handle[i].release_ms = str_gain_set_params->gain_params[i].decay;
56
929
  }
57
433
}
58
59
static VOID impd_drc_util_td_read_gain_config(
60
1.67k
    ia_drc_compand_struct *pstr_drc_compand, ia_drc_gain_set_params_struct *str_gain_set_params) {
61
1.67k
  LOOPIDX idx;
62
1.67k
  WORD32 num_points;
63
64
1.67k
  num_points = str_gain_set_params->gain_params[0].nb_points;
65
1.67k
  pstr_drc_compand->nb_points = num_points;
66
9.96k
  for (idx = 0; idx < num_points; idx++) {
67
8.29k
    pstr_drc_compand->str_segment[2 * (idx + 1)].x =
68
8.29k
        str_gain_set_params->gain_params[0].gain_points[idx].x;
69
8.29k
    pstr_drc_compand->str_segment[2 * (idx + 1)].y =
70
8.29k
        str_gain_set_params->gain_params[0].gain_points[idx].y;
71
8.29k
  }
72
73
1.67k
  pstr_drc_compand->width_db = str_gain_set_params->gain_params[0].width;
74
1.67k
  pstr_drc_compand->str_channel_param.attack = str_gain_set_params->gain_params[0].attack;
75
1.67k
  pstr_drc_compand->str_channel_param.decay = str_gain_set_params->gain_params[0].decay;
76
77
1.67k
  pstr_drc_compand->str_channel_param.attack /= 1000.0;
78
1.67k
  pstr_drc_compand->str_channel_param.decay /= 1000.0;
79
1.67k
}
80
81
IA_ERRORCODE impd_drc_gain_enc_init(ia_drc_gain_enc_struct *pstr_gain_enc,
82
                                    ia_drc_uni_drc_config_struct *pstr_uni_drc_config,
83
                                    ia_drc_loudness_info_set_struct *pstr_loudness_info_set,
84
                                    const WORD32 frame_size, const WORD32 sample_rate,
85
1.41k
                                    const WORD32 delay_mode, const WORD32 domain) {
86
1.41k
  IA_ERRORCODE err_code = IA_NO_ERROR;
87
1.41k
  LOOPIDX i, j, k, l, m, ch;
88
1.41k
  WORD32 num_gain_values_max;
89
1.41k
  UWORD8 found_ch_idx;
90
1.41k
  UWORD32 ch_idx;
91
92
1.41k
  ia_drc_uni_drc_config_ext_struct *pstr_uni_drc_config_ext =
93
1.41k
      &pstr_uni_drc_config->str_uni_drc_config_ext;
94
1.41k
  ia_drc_coefficients_uni_drc_struct *pstr_drc_coefficients_uni_drc =
95
1.41k
      &pstr_uni_drc_config->str_drc_coefficients_uni_drc[0];
96
1.41k
  ia_drc_coefficients_uni_drc_struct *pstr_drc_coefficients_uni_drc_v1 =
97
1.41k
      &pstr_uni_drc_config_ext->str_drc_coefficients_uni_drc_v1[0];
98
99
1.41k
  if (pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count <= 0) {
100
993
    WORD32 all_band_gain_count = 0;
101
993
    WORD32 gain_set_count = pstr_drc_coefficients_uni_drc->gain_set_count;
102
3.17k
    for (i = 0; i < gain_set_count; i++) {
103
2.18k
      all_band_gain_count += pstr_drc_coefficients_uni_drc->str_gain_set_params[i].band_count;
104
2.18k
    }
105
993
    pstr_gain_enc->n_sequences = all_band_gain_count;
106
993
  } else {
107
1.12k
    for (i = 0; i < pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count; i++) {
108
709
      WORD32 all_band_gain_count = 0;
109
2.27k
      for (j = 0; j < pstr_drc_coefficients_uni_drc_v1[i].gain_set_count; j++) {
110
1.56k
        all_band_gain_count +=
111
1.56k
            pstr_drc_coefficients_uni_drc_v1[i].str_gain_set_params[j].band_count;
112
1.56k
      }
113
709
      pstr_drc_coefficients_uni_drc_v1[i].gain_sequence_count = all_band_gain_count;
114
709
      pstr_gain_enc->n_sequences += all_band_gain_count;
115
709
    }
116
419
  }
117
118
1.41k
  if (pstr_gain_enc->n_sequences > IMPD_DRCMAX_NSEQ) {
119
0
    return IA_EXHEAACE_CONFIG_FATAL_DRC_PARAM_OUT_OF_RANGE;
120
0
  }
121
122
1.41k
  if ((pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count > 0) &&
123
419
      (pstr_drc_coefficients_uni_drc_v1->drc_frame_size_present)) {
124
0
    pstr_gain_enc->drc_frame_size = pstr_drc_coefficients_uni_drc_v1->drc_frame_size;
125
1.41k
  } else if ((pstr_uni_drc_config->drc_coefficients_uni_drc_count > 0) &&
126
587
             (pstr_drc_coefficients_uni_drc->drc_frame_size_present)) {
127
102
    pstr_gain_enc->drc_frame_size = pstr_drc_coefficients_uni_drc->drc_frame_size;
128
1.31k
  } else {
129
1.31k
    pstr_gain_enc->drc_frame_size = frame_size;
130
1.31k
  }
131
132
1.41k
  if (pstr_gain_enc->drc_frame_size > IMPD_DRCMAX_FRAMESIZE) {
133
0
    return IA_EXHEAACE_CONFIG_FATAL_DRC_PARAM_OUT_OF_RANGE;
134
0
  }
135
1.41k
  if (pstr_gain_enc->drc_frame_size < 1) {
136
0
    return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
137
0
  }
138
139
1.41k
  if (!pstr_uni_drc_config->sample_rate_present) {
140
297
    pstr_gain_enc->sample_rate = sample_rate;
141
1.11k
  } else {
142
1.11k
    pstr_gain_enc->sample_rate = pstr_uni_drc_config->sample_rate;
143
1.11k
  }
144
145
1.41k
  pstr_gain_enc->domain = domain;
146
1.41k
  pstr_gain_enc->delay_mode = delay_mode;
147
1.41k
  pstr_gain_enc->delta_tmin_default = impd_drc_get_delta_t_min(pstr_gain_enc->sample_rate);
148
149
1.41k
  if ((pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count > 0) &&
150
419
      (pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[0].time_delta_min_present == 1)) {
151
295
    pstr_gain_enc->delta_tmin =
152
295
        pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[0].delta_tmin;
153
1.11k
  } else if ((pstr_uni_drc_config->drc_coefficients_uni_drc_count > 0) &&
154
587
             (pstr_drc_coefficients_uni_drc->str_gain_set_params[0].time_delta_min_present ==
155
587
              1)) {
156
433
    pstr_gain_enc->delta_tmin = pstr_drc_coefficients_uni_drc->str_gain_set_params[0].delta_tmin;
157
684
  } else {
158
684
    pstr_gain_enc->delta_tmin = impd_drc_get_delta_t_min(pstr_gain_enc->sample_rate);
159
684
  }
160
161
1.41k
  num_gain_values_max = pstr_gain_enc->drc_frame_size / pstr_gain_enc->delta_tmin;
162
1.41k
  pstr_gain_enc->base_ch_count = pstr_uni_drc_config->str_channel_layout.base_ch_count;
163
164
1.41k
  memcpy(&pstr_gain_enc->str_uni_drc_config, pstr_uni_drc_config,
165
1.41k
         sizeof(ia_drc_uni_drc_config_struct));
166
1.41k
  memcpy(&pstr_gain_enc->str_loudness_info_set, pstr_loudness_info_set,
167
1.41k
         sizeof(ia_drc_loudness_info_set_struct));
168
169
1.41k
  k = 0;
170
1.41k
  if (pstr_uni_drc_config->drc_coefficients_uni_drc_count > 0) {
171
2.66k
    for (j = 0; j < pstr_drc_coefficients_uni_drc->gain_set_count; j++) {
172
2.11k
      ch_idx = 0;
173
2.11k
      found_ch_idx = 0;
174
2.11k
      ia_drc_gain_set_params_struct *pstr_gain_set_params =
175
2.11k
          &pstr_drc_coefficients_uni_drc->str_gain_set_params[j];
176
177
3.65k
      for (m = 0; m < pstr_uni_drc_config->drc_instructions_uni_drc_count; m++) {
178
1.58k
        if (pstr_uni_drc_config->str_drc_instructions_uni_drc[m].drc_location ==
179
1.58k
            pstr_drc_coefficients_uni_drc->drc_location) {
180
5.19k
          for (ch = 0; ch < MAX_CHANNEL_COUNT; ch++) {
181
4.63k
            if (pstr_uni_drc_config->str_drc_instructions_uni_drc[m].gain_set_index[ch] == j) {
182
50
              ch_idx = ch;
183
50
              found_ch_idx = 1;
184
50
              break;
185
50
            }
186
4.63k
          }
187
617
        }
188
1.58k
        if (found_ch_idx) {
189
50
          break;
190
50
        }
191
1.58k
      }
192
2.11k
      if (ch_idx >= (UWORD32)pstr_gain_enc->base_ch_count) {
193
10
        return IA_EXHEAACE_INIT_FATAL_DRC_INVALID_CHANNEL_INDEX;
194
10
      }
195
2.10k
      if (pstr_gain_set_params->band_count > 1) {
196
118
        impd_drc_util_stft_read_gain_config(pstr_gain_enc->str_drc_stft_gain_handle[0][j],
197
118
                                            pstr_gain_set_params->band_count,
198
118
                                            pstr_gain_set_params);
199
200
367
        for (l = 0; l < pstr_gain_set_params->band_count; l++) {
201
264
          err_code = impd_drc_stft_drc_gain_calc_init(pstr_gain_enc, 0, j, l);
202
264
          if (err_code) {
203
15
            return err_code;
204
15
          }
205
249
          pstr_gain_enc->str_drc_stft_gain_handle[0][j][l].ch_idx = ch_idx;
206
249
          pstr_gain_enc->str_drc_stft_gain_handle[0][j][l].is_valid = 1;
207
249
        }
208
1.99k
      } else if (pstr_gain_set_params->band_count == 1) {
209
929
        impd_drc_util_td_read_gain_config(&pstr_gain_enc->str_drc_compand[0][j],
210
929
                                          pstr_gain_set_params);
211
212
929
        pstr_gain_enc->str_drc_compand[0][j].initial_volume = 0.0f;
213
214
929
        err_code = impd_drc_td_drc_gain_calc_init(pstr_gain_enc, 0, j);
215
929
        if (err_code) {
216
15
          return err_code;
217
15
        }
218
914
        pstr_gain_enc->str_drc_compand[0][j].ch_idx = ch_idx;
219
914
        pstr_gain_enc->str_drc_compand[0][j].is_valid = 1;
220
914
      }
221
222
3.23k
      for (l = 0; l < pstr_gain_set_params->band_count; l++) {
223
1.15k
        pstr_gain_enc->str_drc_gain_seq_buf[k].str_drc_group.n_gain_values = 1;
224
1.15k
        pstr_gain_enc->str_drc_gain_seq_buf[k].str_gain_set_params =
225
1.15k
            pstr_drc_coefficients_uni_drc->str_gain_set_params[j];
226
1.15k
        k++;
227
1.15k
      }
228
2.07k
    }
229
587
  }
230
1.37k
  k = 0;
231
2.02k
  for (i = 0; i < pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count; i++) {
232
695
    pstr_drc_coefficients_uni_drc_v1 =
233
695
        &pstr_uni_drc_config_ext->str_drc_coefficients_uni_drc_v1[i];
234
2.15k
    for (j = 0; j < pstr_drc_coefficients_uni_drc_v1->gain_set_count; j++) {
235
1.49k
      ch_idx = 0;
236
1.49k
      found_ch_idx = 0;
237
1.49k
      ia_drc_gain_set_params_struct *pstr_gain_set_params =
238
1.49k
          &pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[j];
239
240
5.17k
      for (m = 0; m < pstr_uni_drc_config_ext->drc_instructions_uni_drc_v1_count; m++) {
241
3.71k
        if (pstr_uni_drc_config_ext->str_drc_instructions_uni_drc_v1[m].drc_location ==
242
3.71k
            pstr_drc_coefficients_uni_drc_v1->drc_location) {
243
1.16k
          for (ch = 0; ch < MAX_CHANNEL_COUNT; ch++) {
244
1.04k
            if (pstr_uni_drc_config_ext->str_drc_instructions_uni_drc_v1[m].gain_set_index[ch] ==
245
1.04k
                j) {
246
37
              ch_idx = ch;
247
37
              found_ch_idx = 1;
248
37
              break;
249
37
            }
250
1.04k
          }
251
156
        }
252
3.71k
        if (found_ch_idx) {
253
37
          break;
254
37
        }
255
3.71k
      }
256
257
1.49k
      if (ch_idx >= (UWORD32)pstr_gain_enc->base_ch_count) {
258
13
        return IA_EXHEAACE_INIT_FATAL_DRC_INVALID_CHANNEL_INDEX;
259
13
      }
260
261
1.48k
      if (pstr_gain_set_params->band_count > 1) {
262
315
        impd_drc_util_stft_read_gain_config(pstr_gain_enc->str_drc_stft_gain_handle[i][j],
263
315
                                            pstr_gain_set_params->band_count,
264
315
                                            pstr_gain_set_params);
265
266
960
        for (l = 0; l < pstr_gain_set_params->band_count; l++) {
267
654
          err_code = impd_drc_stft_drc_gain_calc_init(pstr_gain_enc, i, j, l);
268
654
          if (err_code) {
269
9
            return err_code;
270
9
          }
271
645
          pstr_gain_enc->str_drc_stft_gain_handle[i][j][l].ch_idx = ch_idx;
272
645
          pstr_gain_enc->str_drc_stft_gain_handle[i][j][l].is_valid = 1;
273
645
        }
274
1.16k
      } else if (pstr_gain_set_params->band_count == 1) {
275
742
        impd_drc_util_td_read_gain_config(&pstr_gain_enc->str_drc_compand[i][j],
276
742
                                          pstr_gain_set_params);
277
278
742
        pstr_gain_enc->str_drc_compand[i][j].initial_volume = 0.0f;
279
280
742
        err_code = impd_drc_td_drc_gain_calc_init(pstr_gain_enc, i, j);
281
742
        if (err_code) {
282
16
          return err_code;
283
16
        }
284
726
        pstr_gain_enc->str_drc_compand[i][j].ch_idx = ch_idx;
285
726
        pstr_gain_enc->str_drc_compand[i][j].is_valid = 1;
286
726
      }
287
288
2.82k
      for (l = 0; l < pstr_gain_set_params->band_count; l++) {
289
1.36k
        pstr_gain_enc->str_drc_gain_seq_buf[k].str_drc_group.n_gain_values = 1;
290
1.36k
        pstr_gain_enc->str_drc_gain_seq_buf[k].str_gain_set_params =
291
1.36k
            pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[j];
292
1.36k
        k++;
293
1.36k
      }
294
1.45k
    }
295
695
  }
296
297
1.33k
  impd_drc_generate_delta_time_code_table(num_gain_values_max,
298
1.33k
                                          pstr_gain_enc->str_delta_time_code_table);
299
300
91.7k
  for (i = num_gain_values_max - 1; i >= 0; i--) {
301
90.3k
    pstr_gain_enc->delta_time_quant_table[i] = pstr_gain_enc->delta_tmin * (i + 1);
302
90.3k
  }
303
304
1.33k
  return err_code;
305
1.37k
}
306
307
IA_ERRORCODE impd_drc_encode_uni_drc_gain(ia_drc_gain_enc_struct *pstr_gain_enc,
308
74.4k
                                          FLOAT32 *ptr_gain_buffer, VOID *pstr_scratch) {
309
74.4k
  LOOPIDX idx;
310
74.4k
  IA_ERRORCODE err_code = IA_NO_ERROR;
311
242k
  for (idx = 0; idx < pstr_gain_enc->n_sequences; idx++) {
312
168k
    err_code = impd_drc_quantize_and_encode_drc_gain(
313
168k
        pstr_gain_enc, &ptr_gain_buffer[idx * MAX_DRC_FRAME_SIZE],
314
168k
        &(pstr_gain_enc->drc_gain_per_sample_with_prev_frame[idx][0]),
315
168k
        pstr_gain_enc->str_delta_time_code_table, &(pstr_gain_enc->str_drc_gain_seq_buf[idx]),
316
168k
        pstr_scratch);
317
318
168k
    if (err_code) {
319
0
      return err_code;
320
0
    }
321
168k
  }
322
74.4k
  return err_code;
323
74.4k
}
324
325
6.32k
WORD32 impd_drc_get_delta_t_min(const WORD32 sample_rate) {
326
6.32k
  WORD32 lower_bound;
327
6.32k
  WORD32 result = 1;
328
6.32k
  WORD32 sample_rate_local = sample_rate;
329
330
6.32k
  if (sample_rate_local < 1000) {
331
0
    sample_rate_local = 1000;
332
0
  }
333
6.32k
  lower_bound = (WORD32)((0.0005f * sample_rate_local) + 0.5f);
334
335
36.6k
  while (result <= lower_bound) {
336
30.3k
    result = result << 1;
337
30.3k
  }
338
6.32k
  return result;
339
6.32k
}