Coverage Report

Created: 2026-03-31 06:52

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
397
    ia_drc_gain_set_params_struct *str_gain_set_params) {
40
397
  LOOPIDX i, j;
41
397
  WORD32 num_points;
42
43
1.23k
  for (i = 0; i < band_count; i++) {
44
835
    num_points = str_gain_set_params->gain_params[i].nb_points;
45
835
    pstr_stft_drc_gain_handle[i].nb_points = num_points;
46
4.47k
    for (j = 0; j < num_points; j++) {
47
3.63k
      pstr_stft_drc_gain_handle[i].str_segment[2 * (j + 1)].x =
48
3.63k
          str_gain_set_params->gain_params[i].gain_points[j].x;
49
3.63k
      pstr_stft_drc_gain_handle[i].str_segment[2 * (j + 1)].y =
50
3.63k
          str_gain_set_params->gain_params[i].gain_points[j].y;
51
3.63k
    }
52
53
835
    pstr_stft_drc_gain_handle[i].width_db = str_gain_set_params->gain_params[i].width;
54
835
    pstr_stft_drc_gain_handle[i].attack_ms = str_gain_set_params->gain_params[i].attack;
55
835
    pstr_stft_drc_gain_handle[i].release_ms = str_gain_set_params->gain_params[i].decay;
56
835
  }
57
397
}
58
59
static VOID impd_drc_util_td_read_gain_config(
60
1.43k
    ia_drc_compand_struct *pstr_drc_compand, ia_drc_gain_set_params_struct *str_gain_set_params) {
61
1.43k
  LOOPIDX idx;
62
1.43k
  WORD32 num_points;
63
64
1.43k
  num_points = str_gain_set_params->gain_params[0].nb_points;
65
1.43k
  pstr_drc_compand->nb_points = num_points;
66
9.23k
  for (idx = 0; idx < num_points; idx++) {
67
7.80k
    pstr_drc_compand->str_segment[2 * (idx + 1)].x =
68
7.80k
        str_gain_set_params->gain_params[0].gain_points[idx].x;
69
7.80k
    pstr_drc_compand->str_segment[2 * (idx + 1)].y =
70
7.80k
        str_gain_set_params->gain_params[0].gain_points[idx].y;
71
7.80k
  }
72
73
1.43k
  pstr_drc_compand->width_db = str_gain_set_params->gain_params[0].width;
74
1.43k
  pstr_drc_compand->str_channel_param.attack = str_gain_set_params->gain_params[0].attack;
75
1.43k
  pstr_drc_compand->str_channel_param.decay = str_gain_set_params->gain_params[0].decay;
76
77
1.43k
  pstr_drc_compand->str_channel_param.attack /= 1000.0;
78
1.43k
  pstr_drc_compand->str_channel_param.decay /= 1000.0;
79
1.43k
}
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.40k
                                    const WORD32 delay_mode, const WORD32 domain) {
86
1.40k
  IA_ERRORCODE err_code = IA_NO_ERROR;
87
1.40k
  LOOPIDX i, j, k, l, m, ch;
88
1.40k
  WORD32 num_gain_values_max;
89
1.40k
  UWORD8 found_ch_idx;
90
1.40k
  UWORD32 ch_idx;
91
92
1.40k
  ia_drc_uni_drc_config_ext_struct *pstr_uni_drc_config_ext =
93
1.40k
      &pstr_uni_drc_config->str_uni_drc_config_ext;
94
1.40k
  ia_drc_coefficients_uni_drc_struct *pstr_drc_coefficients_uni_drc =
95
1.40k
      &pstr_uni_drc_config->str_drc_coefficients_uni_drc[0];
96
1.40k
  ia_drc_coefficients_uni_drc_struct *pstr_drc_coefficients_uni_drc_v1 =
97
1.40k
      &pstr_uni_drc_config_ext->str_drc_coefficients_uni_drc_v1[0];
98
99
1.40k
  if (pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count <= 0) {
100
983
    WORD32 all_band_gain_count = 0;
101
983
    WORD32 gain_set_count = pstr_drc_coefficients_uni_drc->gain_set_count;
102
2.92k
    for (i = 0; i < gain_set_count; i++) {
103
1.93k
      all_band_gain_count += pstr_drc_coefficients_uni_drc->str_gain_set_params[i].band_count;
104
1.93k
    }
105
983
    pstr_gain_enc->n_sequences = all_band_gain_count;
106
983
  } else {
107
1.13k
    for (i = 0; i < pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count; i++) {
108
715
      WORD32 all_band_gain_count = 0;
109
2.29k
      for (j = 0; j < pstr_drc_coefficients_uni_drc_v1[i].gain_set_count; j++) {
110
1.57k
        all_band_gain_count +=
111
1.57k
            pstr_drc_coefficients_uni_drc_v1[i].str_gain_set_params[j].band_count;
112
1.57k
      }
113
715
      pstr_drc_coefficients_uni_drc_v1[i].gain_sequence_count = all_band_gain_count;
114
715
      pstr_gain_enc->n_sequences += all_band_gain_count;
115
715
    }
116
420
  }
117
118
1.40k
  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.40k
  if ((pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count > 0) &&
123
420
      (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.40k
  } else if ((pstr_uni_drc_config->drc_coefficients_uni_drc_count > 0) &&
126
527
             (pstr_drc_coefficients_uni_drc->drc_frame_size_present)) {
127
105
    pstr_gain_enc->drc_frame_size = pstr_drc_coefficients_uni_drc->drc_frame_size;
128
1.29k
  } else {
129
1.29k
    pstr_gain_enc->drc_frame_size = frame_size;
130
1.29k
  }
131
132
1.40k
  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.40k
  if (pstr_gain_enc->drc_frame_size < 1) {
136
0
    return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
137
0
  }
138
139
1.40k
  if (!pstr_uni_drc_config->sample_rate_present) {
140
235
    pstr_gain_enc->sample_rate = sample_rate;
141
1.16k
  } else {
142
1.16k
    pstr_gain_enc->sample_rate = pstr_uni_drc_config->sample_rate;
143
1.16k
  }
144
145
1.40k
  pstr_gain_enc->domain = domain;
146
1.40k
  pstr_gain_enc->delay_mode = delay_mode;
147
1.40k
  pstr_gain_enc->delta_tmin_default = impd_drc_get_delta_t_min(pstr_gain_enc->sample_rate);
148
149
1.40k
  if ((pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count > 0) &&
150
420
      (pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[0].time_delta_min_present == 1)) {
151
301
    pstr_gain_enc->delta_tmin =
152
301
        pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[0].delta_tmin;
153
1.10k
  } else if ((pstr_uni_drc_config->drc_coefficients_uni_drc_count > 0) &&
154
527
             (pstr_drc_coefficients_uni_drc->str_gain_set_params[0].time_delta_min_present ==
155
527
              1)) {
156
375
    pstr_gain_enc->delta_tmin = pstr_drc_coefficients_uni_drc->str_gain_set_params[0].delta_tmin;
157
727
  } else {
158
727
    pstr_gain_enc->delta_tmin = impd_drc_get_delta_t_min(pstr_gain_enc->sample_rate);
159
727
  }
160
161
1.40k
  num_gain_values_max = pstr_gain_enc->drc_frame_size / pstr_gain_enc->delta_tmin;
162
1.40k
  pstr_gain_enc->base_ch_count = pstr_uni_drc_config->str_channel_layout.base_ch_count;
163
164
1.40k
  memcpy(&pstr_gain_enc->str_uni_drc_config, pstr_uni_drc_config,
165
1.40k
         sizeof(ia_drc_uni_drc_config_struct));
166
1.40k
  memcpy(&pstr_gain_enc->str_loudness_info_set, pstr_loudness_info_set,
167
1.40k
         sizeof(ia_drc_loudness_info_set_struct));
168
169
1.40k
  k = 0;
170
1.40k
  if (pstr_uni_drc_config->drc_coefficients_uni_drc_count > 0) {
171
2.36k
    for (j = 0; j < pstr_drc_coefficients_uni_drc->gain_set_count; j++) {
172
1.87k
      ch_idx = 0;
173
1.87k
      found_ch_idx = 0;
174
1.87k
      ia_drc_gain_set_params_struct *pstr_gain_set_params =
175
1.87k
          &pstr_drc_coefficients_uni_drc->str_gain_set_params[j];
176
177
3.37k
      for (m = 0; m < pstr_uni_drc_config->drc_instructions_uni_drc_count; m++) {
178
1.54k
        if (pstr_uni_drc_config->str_drc_instructions_uni_drc[m].drc_location ==
179
1.54k
            pstr_drc_coefficients_uni_drc->drc_location) {
180
4.98k
          for (ch = 0; ch < MAX_CHANNEL_COUNT; ch++) {
181
4.43k
            if (pstr_uni_drc_config->str_drc_instructions_uni_drc[m].gain_set_index[ch] == j) {
182
47
              ch_idx = ch;
183
47
              found_ch_idx = 1;
184
47
              break;
185
47
            }
186
4.43k
          }
187
591
        }
188
1.54k
        if (found_ch_idx) {
189
47
          break;
190
47
        }
191
1.54k
      }
192
1.87k
      if (ch_idx >= (UWORD32)pstr_gain_enc->base_ch_count) {
193
9
        return IA_EXHEAACE_INIT_FATAL_DRC_INVALID_CHANNEL_INDEX;
194
9
      }
195
1.86k
      if (pstr_gain_set_params->band_count > 1) {
196
91
        impd_drc_util_stft_read_gain_config(pstr_gain_enc->str_drc_stft_gain_handle[0][j],
197
91
                                            pstr_gain_set_params->band_count,
198
91
                                            pstr_gain_set_params);
199
200
277
        for (l = 0; l < pstr_gain_set_params->band_count; l++) {
201
198
          err_code = impd_drc_stft_drc_gain_calc_init(pstr_gain_enc, 0, j, l);
202
198
          if (err_code) {
203
12
            return err_code;
204
12
          }
205
186
          pstr_gain_enc->str_drc_stft_gain_handle[0][j][l].ch_idx = ch_idx;
206
186
          pstr_gain_enc->str_drc_stft_gain_handle[0][j][l].is_valid = 1;
207
186
        }
208
1.77k
      } else if (pstr_gain_set_params->band_count == 1) {
209
679
        impd_drc_util_td_read_gain_config(&pstr_gain_enc->str_drc_compand[0][j],
210
679
                                          pstr_gain_set_params);
211
212
679
        pstr_gain_enc->str_drc_compand[0][j].initial_volume = 0.0f;
213
214
679
        err_code = impd_drc_td_drc_gain_calc_init(pstr_gain_enc, 0, j);
215
679
        if (err_code) {
216
16
          return err_code;
217
16
        }
218
663
        pstr_gain_enc->str_drc_compand[0][j].ch_idx = ch_idx;
219
663
        pstr_gain_enc->str_drc_compand[0][j].is_valid = 1;
220
663
      }
221
222
2.67k
      for (l = 0; l < pstr_gain_set_params->band_count; l++) {
223
839
        pstr_gain_enc->str_drc_gain_seq_buf[k].str_drc_group.n_gain_values = 1;
224
839
        pstr_gain_enc->str_drc_gain_seq_buf[k].str_gain_set_params =
225
839
            pstr_drc_coefficients_uni_drc->str_gain_set_params[j];
226
839
        k++;
227
839
      }
228
1.83k
    }
229
527
  }
230
1.36k
  k = 0;
231
2.03k
  for (i = 0; i < pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count; i++) {
232
702
    pstr_drc_coefficients_uni_drc_v1 =
233
702
        &pstr_uni_drc_config_ext->str_drc_coefficients_uni_drc_v1[i];
234
2.17k
    for (j = 0; j < pstr_drc_coefficients_uni_drc_v1->gain_set_count; j++) {
235
1.51k
      ch_idx = 0;
236
1.51k
      found_ch_idx = 0;
237
1.51k
      ia_drc_gain_set_params_struct *pstr_gain_set_params =
238
1.51k
          &pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[j];
239
240
5.23k
      for (m = 0; m < pstr_uni_drc_config_ext->drc_instructions_uni_drc_v1_count; m++) {
241
3.75k
        if (pstr_uni_drc_config_ext->str_drc_instructions_uni_drc_v1[m].drc_location ==
242
3.75k
            pstr_drc_coefficients_uni_drc_v1->drc_location) {
243
713
          for (ch = 0; ch < MAX_CHANNEL_COUNT; ch++) {
244
643
            if (pstr_uni_drc_config_ext->str_drc_instructions_uni_drc_v1[m].gain_set_index[ch] ==
245
643
                j) {
246
35
              ch_idx = ch;
247
35
              found_ch_idx = 1;
248
35
              break;
249
35
            }
250
643
          }
251
105
        }
252
3.75k
        if (found_ch_idx) {
253
35
          break;
254
35
        }
255
3.75k
      }
256
257
1.51k
      if (ch_idx >= (UWORD32)pstr_gain_enc->base_ch_count) {
258
12
        return IA_EXHEAACE_INIT_FATAL_DRC_INVALID_CHANNEL_INDEX;
259
12
      }
260
261
1.49k
      if (pstr_gain_set_params->band_count > 1) {
262
306
        impd_drc_util_stft_read_gain_config(pstr_gain_enc->str_drc_stft_gain_handle[i][j],
263
306
                                            pstr_gain_set_params->band_count,
264
306
                                            pstr_gain_set_params);
265
266
926
        for (l = 0; l < pstr_gain_set_params->band_count; l++) {
267
628
          err_code = impd_drc_stft_drc_gain_calc_init(pstr_gain_enc, i, j, l);
268
628
          if (err_code) {
269
8
            return err_code;
270
8
          }
271
620
          pstr_gain_enc->str_drc_stft_gain_handle[i][j][l].ch_idx = ch_idx;
272
620
          pstr_gain_enc->str_drc_stft_gain_handle[i][j][l].is_valid = 1;
273
620
        }
274
1.19k
      } else if (pstr_gain_set_params->band_count == 1) {
275
753
        impd_drc_util_td_read_gain_config(&pstr_gain_enc->str_drc_compand[i][j],
276
753
                                          pstr_gain_set_params);
277
278
753
        pstr_gain_enc->str_drc_compand[i][j].initial_volume = 0.0f;
279
280
753
        err_code = impd_drc_td_drc_gain_calc_init(pstr_gain_enc, i, j);
281
753
        if (err_code) {
282
16
          return err_code;
283
16
        }
284
737
        pstr_gain_enc->str_drc_compand[i][j].ch_idx = ch_idx;
285
737
        pstr_gain_enc->str_drc_compand[i][j].is_valid = 1;
286
737
      }
287
288
2.82k
      for (l = 0; l < pstr_gain_set_params->band_count; l++) {
289
1.35k
        pstr_gain_enc->str_drc_gain_seq_buf[k].str_drc_group.n_gain_values = 1;
290
1.35k
        pstr_gain_enc->str_drc_gain_seq_buf[k].str_gain_set_params =
291
1.35k
            pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[j];
292
1.35k
        k++;
293
1.35k
      }
294
1.47k
    }
295
702
  }
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
93.6k
  for (i = num_gain_values_max - 1; i >= 0; i--) {
301
92.3k
    pstr_gain_enc->delta_time_quant_table[i] = pstr_gain_enc->delta_tmin * (i + 1);
302
92.3k
  }
303
304
1.33k
  return err_code;
305
1.36k
}
306
307
IA_ERRORCODE impd_drc_encode_uni_drc_gain(ia_drc_gain_enc_struct *pstr_gain_enc,
308
72.5k
                                          FLOAT32 *ptr_gain_buffer, VOID *pstr_scratch) {
309
72.5k
  LOOPIDX idx;
310
72.5k
  IA_ERRORCODE err_code = IA_NO_ERROR;
311
221k
  for (idx = 0; idx < pstr_gain_enc->n_sequences; idx++) {
312
149k
    err_code = impd_drc_quantize_and_encode_drc_gain(
313
149k
        pstr_gain_enc, &ptr_gain_buffer[idx * MAX_DRC_FRAME_SIZE],
314
149k
        &(pstr_gain_enc->drc_gain_per_sample_with_prev_frame[idx][0]),
315
149k
        pstr_gain_enc->str_delta_time_code_table, &(pstr_gain_enc->str_drc_gain_seq_buf[idx]),
316
149k
        pstr_scratch);
317
318
149k
    if (err_code) {
319
0
      return err_code;
320
0
    }
321
149k
  }
322
72.5k
  return err_code;
323
72.5k
}
324
325
6.00k
WORD32 impd_drc_get_delta_t_min(const WORD32 sample_rate) {
326
6.00k
  WORD32 lower_bound;
327
6.00k
  WORD32 result = 1;
328
6.00k
  WORD32 sample_rate_local = sample_rate;
329
330
6.00k
  if (sample_rate_local < 1000) {
331
0
    sample_rate_local = 1000;
332
0
  }
333
6.00k
  lower_bound = (WORD32)((0.0005f * sample_rate_local) + 0.5f);
334
335
34.5k
  while (result <= lower_bound) {
336
28.5k
    result = result << 1;
337
28.5k
  }
338
6.00k
  return result;
339
6.00k
}