Coverage Report

Created: 2025-10-10 06:12

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
321
    ia_drc_gain_set_params_struct *str_gain_set_params) {
40
321
  LOOPIDX i, j;
41
321
  WORD32 num_points;
42
43
964
  for (i = 0; i < band_count; i++) {
44
643
    num_points = str_gain_set_params->gain_params[i].nb_points;
45
643
    pstr_stft_drc_gain_handle[i].nb_points = num_points;
46
2.42k
    for (j = 0; j < num_points; j++) {
47
1.78k
      pstr_stft_drc_gain_handle[i].str_segment[2 * (j + 1)].x =
48
1.78k
          str_gain_set_params->gain_params[i].gain_points[j].x;
49
1.78k
      pstr_stft_drc_gain_handle[i].str_segment[2 * (j + 1)].y =
50
1.78k
          str_gain_set_params->gain_params[i].gain_points[j].y;
51
1.78k
    }
52
53
643
    pstr_stft_drc_gain_handle[i].width_db = str_gain_set_params->gain_params[i].width;
54
643
    pstr_stft_drc_gain_handle[i].attack_ms = str_gain_set_params->gain_params[i].attack;
55
643
    pstr_stft_drc_gain_handle[i].release_ms = str_gain_set_params->gain_params[i].decay;
56
643
  }
57
321
}
58
59
static VOID impd_drc_util_td_read_gain_config(
60
1.17k
    ia_drc_compand_struct *pstr_drc_compand, ia_drc_gain_set_params_struct *str_gain_set_params) {
61
1.17k
  LOOPIDX idx;
62
1.17k
  WORD32 num_points;
63
64
1.17k
  num_points = str_gain_set_params->gain_params[0].nb_points;
65
1.17k
  pstr_drc_compand->nb_points = num_points;
66
8.15k
  for (idx = 0; idx < num_points; idx++) {
67
6.98k
    pstr_drc_compand->str_segment[2 * (idx + 1)].x =
68
6.98k
        str_gain_set_params->gain_params[0].gain_points[idx].x;
69
6.98k
    pstr_drc_compand->str_segment[2 * (idx + 1)].y =
70
6.98k
        str_gain_set_params->gain_params[0].gain_points[idx].y;
71
6.98k
  }
72
73
1.17k
  pstr_drc_compand->width_db = str_gain_set_params->gain_params[0].width;
74
1.17k
  pstr_drc_compand->str_channel_param.attack = str_gain_set_params->gain_params[0].attack;
75
1.17k
  pstr_drc_compand->str_channel_param.decay = str_gain_set_params->gain_params[0].decay;
76
77
1.17k
  pstr_drc_compand->str_channel_param.attack /= 1000.0;
78
1.17k
  pstr_drc_compand->str_channel_param.decay /= 1000.0;
79
1.17k
}
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.42k
                                    const WORD32 delay_mode, const WORD32 domain) {
86
1.42k
  IA_ERRORCODE err_code = IA_NO_ERROR;
87
1.42k
  LOOPIDX i, j, k, l, m, ch;
88
1.42k
  WORD32 num_gain_values_max;
89
1.42k
  UWORD8 found_ch_idx;
90
1.42k
  UWORD32 ch_idx;
91
92
1.42k
  ia_drc_uni_drc_config_ext_struct *pstr_uni_drc_config_ext =
93
1.42k
      &pstr_uni_drc_config->str_uni_drc_config_ext;
94
1.42k
  ia_drc_coefficients_uni_drc_struct *pstr_drc_coefficients_uni_drc =
95
1.42k
      &pstr_uni_drc_config->str_drc_coefficients_uni_drc[0];
96
1.42k
  ia_drc_coefficients_uni_drc_struct *pstr_drc_coefficients_uni_drc_v1 =
97
1.42k
      &pstr_uni_drc_config_ext->str_drc_coefficients_uni_drc_v1[0];
98
99
1.42k
  if (pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count <= 0) {
100
1.05k
    WORD32 all_band_gain_count = 0;
101
1.05k
    WORD32 gain_set_count = pstr_drc_coefficients_uni_drc->gain_set_count;
102
2.97k
    for (i = 0; i < gain_set_count; i++) {
103
1.92k
      all_band_gain_count += pstr_drc_coefficients_uni_drc->str_gain_set_params[i].band_count;
104
1.92k
    }
105
1.05k
    pstr_gain_enc->n_sequences = all_band_gain_count;
106
1.05k
  } else {
107
1.04k
    for (i = 0; i < pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count; i++) {
108
672
      WORD32 all_band_gain_count = 0;
109
2.01k
      for (j = 0; j < pstr_drc_coefficients_uni_drc_v1[i].gain_set_count; j++) {
110
1.34k
        all_band_gain_count +=
111
1.34k
            pstr_drc_coefficients_uni_drc_v1[i].str_gain_set_params[j].band_count;
112
1.34k
      }
113
672
      pstr_drc_coefficients_uni_drc_v1[i].gain_sequence_count = all_band_gain_count;
114
672
      pstr_gain_enc->n_sequences += all_band_gain_count;
115
672
    }
116
372
  }
117
118
1.42k
  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.42k
  if ((pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count > 0) &&
123
372
      (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.42k
  } else if ((pstr_uni_drc_config->drc_coefficients_uni_drc_count > 0) &&
126
525
             (pstr_drc_coefficients_uni_drc->drc_frame_size_present)) {
127
110
    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.42k
  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.42k
  if (pstr_gain_enc->drc_frame_size < 1) {
136
0
    return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
137
0
  }
138
139
1.42k
  if (!pstr_uni_drc_config->sample_rate_present) {
140
245
    pstr_gain_enc->sample_rate = sample_rate;
141
1.17k
  } else {
142
1.17k
    pstr_gain_enc->sample_rate = pstr_uni_drc_config->sample_rate;
143
1.17k
  }
144
145
1.42k
  pstr_gain_enc->domain = domain;
146
1.42k
  pstr_gain_enc->delay_mode = delay_mode;
147
1.42k
  pstr_gain_enc->delta_tmin_default = impd_drc_get_delta_t_min(pstr_gain_enc->sample_rate);
148
149
1.42k
  if ((pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count > 0) &&
150
372
      (pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[0].time_delta_min_present == 1)) {
151
293
    pstr_gain_enc->delta_tmin =
152
293
        pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[0].delta_tmin;
153
1.13k
  } else if ((pstr_uni_drc_config->drc_coefficients_uni_drc_count > 0) &&
154
525
             (pstr_drc_coefficients_uni_drc->str_gain_set_params[0].time_delta_min_present ==
155
525
              1)) {
156
370
    pstr_gain_enc->delta_tmin = pstr_drc_coefficients_uni_drc->str_gain_set_params[0].delta_tmin;
157
761
  } else {
158
761
    pstr_gain_enc->delta_tmin = impd_drc_get_delta_t_min(pstr_gain_enc->sample_rate);
159
761
  }
160
161
1.42k
  num_gain_values_max = pstr_gain_enc->drc_frame_size / pstr_gain_enc->delta_tmin;
162
1.42k
  pstr_gain_enc->base_ch_count = pstr_uni_drc_config->str_channel_layout.base_ch_count;
163
164
1.42k
  memcpy(&pstr_gain_enc->str_uni_drc_config, pstr_uni_drc_config,
165
1.42k
         sizeof(ia_drc_uni_drc_config_struct));
166
1.42k
  memcpy(&pstr_gain_enc->str_loudness_info_set, pstr_loudness_info_set,
167
1.42k
         sizeof(ia_drc_loudness_info_set_struct));
168
169
1.42k
  k = 0;
170
1.42k
  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.86k
      ch_idx = 0;
173
1.86k
      found_ch_idx = 0;
174
1.86k
      ia_drc_gain_set_params_struct *pstr_gain_set_params =
175
1.86k
          &pstr_drc_coefficients_uni_drc->str_gain_set_params[j];
176
177
2.86k
      for (m = 0; m < pstr_uni_drc_config->drc_instructions_uni_drc_count; m++) {
178
1.03k
        if (pstr_uni_drc_config->str_drc_instructions_uni_drc[m].drc_location ==
179
1.03k
            pstr_drc_coefficients_uni_drc->drc_location) {
180
3.01k
          for (ch = 0; ch < MAX_CHANNEL_COUNT; ch++) {
181
2.68k
            if (pstr_uni_drc_config->str_drc_instructions_uni_drc[m].gain_set_index[ch] == j) {
182
42
              ch_idx = ch;
183
42
              found_ch_idx = 1;
184
42
              break;
185
42
            }
186
2.68k
          }
187
367
        }
188
1.03k
        if (found_ch_idx) {
189
42
          break;
190
42
        }
191
1.03k
      }
192
1.86k
      if (ch_idx >= (UWORD32)pstr_gain_enc->base_ch_count) {
193
10
        return IA_EXHEAACE_INIT_FATAL_DRC_INVALID_CHANNEL_INDEX;
194
10
      }
195
1.85k
      if (pstr_gain_set_params->band_count > 1) {
196
30
        impd_drc_util_stft_read_gain_config(pstr_gain_enc->str_drc_stft_gain_handle[0][j],
197
30
                                            pstr_gain_set_params->band_count,
198
30
                                            pstr_gain_set_params);
199
200
82
        for (l = 0; l < pstr_gain_set_params->band_count; l++) {
201
57
          err_code = impd_drc_stft_drc_gain_calc_init(pstr_gain_enc, 0, j, l);
202
57
          if (err_code) {
203
5
            return err_code;
204
5
          }
205
52
          pstr_gain_enc->str_drc_stft_gain_handle[0][j][l].ch_idx = ch_idx;
206
52
          pstr_gain_enc->str_drc_stft_gain_handle[0][j][l].is_valid = 1;
207
52
        }
208
1.82k
      } else if (pstr_gain_set_params->band_count == 1) {
209
509
        impd_drc_util_td_read_gain_config(&pstr_gain_enc->str_drc_compand[0][j],
210
509
                                          pstr_gain_set_params);
211
212
509
        pstr_gain_enc->str_drc_compand[0][j].initial_volume = 0.0f;
213
214
509
        err_code = impd_drc_td_drc_gain_calc_init(pstr_gain_enc, 0, j);
215
509
        if (err_code) {
216
12
          return err_code;
217
12
        }
218
497
        pstr_gain_enc->str_drc_compand[0][j].ch_idx = ch_idx;
219
497
        pstr_gain_enc->str_drc_compand[0][j].is_valid = 1;
220
497
      }
221
222
2.38k
      for (l = 0; l < pstr_gain_set_params->band_count; l++) {
223
547
        pstr_gain_enc->str_drc_gain_seq_buf[k].str_drc_group.n_gain_values = 1;
224
547
        pstr_gain_enc->str_drc_gain_seq_buf[k].str_gain_set_params =
225
547
            pstr_drc_coefficients_uni_drc->str_gain_set_params[j];
226
547
        k++;
227
547
      }
228
1.83k
    }
229
525
  }
230
1.39k
  k = 0;
231
2.03k
  for (i = 0; i < pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count; i++) {
232
668
    pstr_drc_coefficients_uni_drc_v1 =
233
668
        &pstr_uni_drc_config_ext->str_drc_coefficients_uni_drc_v1[i];
234
1.94k
    for (j = 0; j < pstr_drc_coefficients_uni_drc_v1->gain_set_count; j++) {
235
1.30k
      ch_idx = 0;
236
1.30k
      found_ch_idx = 0;
237
1.30k
      ia_drc_gain_set_params_struct *pstr_gain_set_params =
238
1.30k
          &pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[j];
239
240
2.78k
      for (m = 0; m < pstr_uni_drc_config_ext->drc_instructions_uni_drc_v1_count; m++) {
241
1.49k
        if (pstr_uni_drc_config_ext->str_drc_instructions_uni_drc_v1[m].drc_location ==
242
1.49k
            pstr_drc_coefficients_uni_drc_v1->drc_location) {
243
231
          for (ch = 0; ch < MAX_CHANNEL_COUNT; ch++) {
244
210
            if (pstr_uni_drc_config_ext->str_drc_instructions_uni_drc_v1[m].gain_set_index[ch] ==
245
210
                j) {
246
14
              ch_idx = ch;
247
14
              found_ch_idx = 1;
248
14
              break;
249
14
            }
250
210
          }
251
35
        }
252
1.49k
        if (found_ch_idx) {
253
14
          break;
254
14
        }
255
1.49k
      }
256
257
1.30k
      if (ch_idx >= (UWORD32)pstr_gain_enc->base_ch_count) {
258
8
        return IA_EXHEAACE_INIT_FATAL_DRC_INVALID_CHANNEL_INDEX;
259
8
      }
260
261
1.29k
      if (pstr_gain_set_params->band_count > 1) {
262
291
        impd_drc_util_stft_read_gain_config(pstr_gain_enc->str_drc_stft_gain_handle[i][j],
263
291
                                            pstr_gain_set_params->band_count,
264
291
                                            pstr_gain_set_params);
265
266
866
        for (l = 0; l < pstr_gain_set_params->band_count; l++) {
267
580
          err_code = impd_drc_stft_drc_gain_calc_init(pstr_gain_enc, i, j, l);
268
580
          if (err_code) {
269
5
            return err_code;
270
5
          }
271
575
          pstr_gain_enc->str_drc_stft_gain_handle[i][j][l].ch_idx = ch_idx;
272
575
          pstr_gain_enc->str_drc_stft_gain_handle[i][j][l].is_valid = 1;
273
575
        }
274
1.00k
      } else if (pstr_gain_set_params->band_count == 1) {
275
666
        impd_drc_util_td_read_gain_config(&pstr_gain_enc->str_drc_compand[i][j],
276
666
                                          pstr_gain_set_params);
277
278
666
        pstr_gain_enc->str_drc_compand[i][j].initial_volume = 0.0f;
279
280
666
        err_code = impd_drc_td_drc_gain_calc_init(pstr_gain_enc, i, j);
281
666
        if (err_code) {
282
15
          return err_code;
283
15
        }
284
651
        pstr_gain_enc->str_drc_compand[i][j].ch_idx = ch_idx;
285
651
        pstr_gain_enc->str_drc_compand[i][j].is_valid = 1;
286
651
      }
287
288
2.50k
      for (l = 0; l < pstr_gain_set_params->band_count; l++) {
289
1.22k
        pstr_gain_enc->str_drc_gain_seq_buf[k].str_drc_group.n_gain_values = 1;
290
1.22k
        pstr_gain_enc->str_drc_gain_seq_buf[k].str_gain_set_params =
291
1.22k
            pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[j];
292
1.22k
        k++;
293
1.22k
      }
294
1.27k
    }
295
668
  }
296
297
1.36k
  impd_drc_generate_delta_time_code_table(num_gain_values_max,
298
1.36k
                                          pstr_gain_enc->str_delta_time_code_table);
299
300
100k
  for (i = num_gain_values_max - 1; i >= 0; i--) {
301
98.9k
    pstr_gain_enc->delta_time_quant_table[i] = pstr_gain_enc->delta_tmin * (i + 1);
302
98.9k
  }
303
304
1.36k
  return err_code;
305
1.39k
}
306
307
IA_ERRORCODE impd_drc_encode_uni_drc_gain(ia_drc_gain_enc_struct *pstr_gain_enc,
308
55.9k
                                          FLOAT32 *ptr_gain_buffer, VOID *pstr_scratch) {
309
55.9k
  LOOPIDX idx;
310
55.9k
  IA_ERRORCODE err_code = IA_NO_ERROR;
311
146k
  for (idx = 0; idx < pstr_gain_enc->n_sequences; idx++) {
312
90.6k
    err_code = impd_drc_quantize_and_encode_drc_gain(
313
90.6k
        pstr_gain_enc, &ptr_gain_buffer[idx * MAX_DRC_FRAME_SIZE],
314
90.6k
        &(pstr_gain_enc->drc_gain_per_sample_with_prev_frame[idx][0]),
315
90.6k
        pstr_gain_enc->str_delta_time_code_table, &(pstr_gain_enc->str_drc_gain_seq_buf[idx]),
316
90.6k
        pstr_scratch);
317
318
90.6k
    if (err_code) {
319
0
      return err_code;
320
0
    }
321
90.6k
  }
322
55.9k
  return err_code;
323
55.9k
}
324
325
5.68k
WORD32 impd_drc_get_delta_t_min(const WORD32 sample_rate) {
326
5.68k
  WORD32 lower_bound;
327
5.68k
  WORD32 result = 1;
328
5.68k
  WORD32 sample_rate_local = sample_rate;
329
330
5.68k
  if (sample_rate_local < 1000) {
331
0
    sample_rate_local = 1000;
332
0
  }
333
5.68k
  lower_bound = (WORD32)((0.0005f * sample_rate_local) + 0.5f);
334
335
32.5k
  while (result <= lower_bound) {
336
26.8k
    result = result << 1;
337
26.8k
  }
338
5.68k
  return result;
339
5.68k
}