Coverage Report

Created: 2025-12-10 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
220
    ia_drc_gain_set_params_struct *str_gain_set_params) {
40
220
  LOOPIDX i, j;
41
220
  WORD32 num_points;
42
43
670
  for (i = 0; i < band_count; i++) {
44
450
    num_points = str_gain_set_params->gain_params[i].nb_points;
45
450
    pstr_stft_drc_gain_handle[i].nb_points = num_points;
46
1.32k
    for (j = 0; j < num_points; j++) {
47
872
      pstr_stft_drc_gain_handle[i].str_segment[2 * (j + 1)].x =
48
872
          str_gain_set_params->gain_params[i].gain_points[j].x;
49
872
      pstr_stft_drc_gain_handle[i].str_segment[2 * (j + 1)].y =
50
872
          str_gain_set_params->gain_params[i].gain_points[j].y;
51
872
    }
52
53
450
    pstr_stft_drc_gain_handle[i].width_db = str_gain_set_params->gain_params[i].width;
54
450
    pstr_stft_drc_gain_handle[i].attack_ms = str_gain_set_params->gain_params[i].attack;
55
450
    pstr_stft_drc_gain_handle[i].release_ms = str_gain_set_params->gain_params[i].decay;
56
450
  }
57
220
}
58
59
static VOID impd_drc_util_td_read_gain_config(
60
962
    ia_drc_compand_struct *pstr_drc_compand, ia_drc_gain_set_params_struct *str_gain_set_params) {
61
962
  LOOPIDX idx;
62
962
  WORD32 num_points;
63
64
962
  num_points = str_gain_set_params->gain_params[0].nb_points;
65
962
  pstr_drc_compand->nb_points = num_points;
66
6.70k
  for (idx = 0; idx < num_points; idx++) {
67
5.74k
    pstr_drc_compand->str_segment[2 * (idx + 1)].x =
68
5.74k
        str_gain_set_params->gain_params[0].gain_points[idx].x;
69
5.74k
    pstr_drc_compand->str_segment[2 * (idx + 1)].y =
70
5.74k
        str_gain_set_params->gain_params[0].gain_points[idx].y;
71
5.74k
  }
72
73
962
  pstr_drc_compand->width_db = str_gain_set_params->gain_params[0].width;
74
962
  pstr_drc_compand->str_channel_param.attack = str_gain_set_params->gain_params[0].attack;
75
962
  pstr_drc_compand->str_channel_param.decay = str_gain_set_params->gain_params[0].decay;
76
77
962
  pstr_drc_compand->str_channel_param.attack /= 1000.0;
78
962
  pstr_drc_compand->str_channel_param.decay /= 1000.0;
79
962
}
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.12k
                                    const WORD32 delay_mode, const WORD32 domain) {
86
1.12k
  IA_ERRORCODE err_code = IA_NO_ERROR;
87
1.12k
  LOOPIDX i, j, k, l, m, ch;
88
1.12k
  WORD32 num_gain_values_max;
89
1.12k
  UWORD8 found_ch_idx;
90
1.12k
  UWORD32 ch_idx;
91
92
1.12k
  ia_drc_uni_drc_config_ext_struct *pstr_uni_drc_config_ext =
93
1.12k
      &pstr_uni_drc_config->str_uni_drc_config_ext;
94
1.12k
  ia_drc_coefficients_uni_drc_struct *pstr_drc_coefficients_uni_drc =
95
1.12k
      &pstr_uni_drc_config->str_drc_coefficients_uni_drc[0];
96
1.12k
  ia_drc_coefficients_uni_drc_struct *pstr_drc_coefficients_uni_drc_v1 =
97
1.12k
      &pstr_uni_drc_config_ext->str_drc_coefficients_uni_drc_v1[0];
98
99
1.12k
  if (pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count <= 0) {
100
881
    WORD32 all_band_gain_count = 0;
101
881
    WORD32 gain_set_count = pstr_drc_coefficients_uni_drc->gain_set_count;
102
2.57k
    for (i = 0; i < gain_set_count; i++) {
103
1.69k
      all_band_gain_count += pstr_drc_coefficients_uni_drc->str_gain_set_params[i].band_count;
104
1.69k
    }
105
881
    pstr_gain_enc->n_sequences = all_band_gain_count;
106
881
  } else {
107
659
    for (i = 0; i < pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count; i++) {
108
417
      WORD32 all_band_gain_count = 0;
109
1.31k
      for (j = 0; j < pstr_drc_coefficients_uni_drc_v1[i].gain_set_count; j++) {
110
900
        all_band_gain_count +=
111
900
            pstr_drc_coefficients_uni_drc_v1[i].str_gain_set_params[j].band_count;
112
900
      }
113
417
      pstr_drc_coefficients_uni_drc_v1[i].gain_sequence_count = all_band_gain_count;
114
417
      pstr_gain_enc->n_sequences += all_band_gain_count;
115
417
    }
116
242
  }
117
118
1.12k
  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.12k
  if ((pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count > 0) &&
123
242
      (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.12k
  } else if ((pstr_uni_drc_config->drc_coefficients_uni_drc_count > 0) &&
126
459
             (pstr_drc_coefficients_uni_drc->drc_frame_size_present)) {
127
94
    pstr_gain_enc->drc_frame_size = pstr_drc_coefficients_uni_drc->drc_frame_size;
128
1.02k
  } else {
129
1.02k
    pstr_gain_enc->drc_frame_size = frame_size;
130
1.02k
  }
131
132
1.12k
  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.12k
  if (pstr_gain_enc->drc_frame_size < 1) {
136
0
    return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
137
0
  }
138
139
1.12k
  if (!pstr_uni_drc_config->sample_rate_present) {
140
156
    pstr_gain_enc->sample_rate = sample_rate;
141
967
  } else {
142
967
    pstr_gain_enc->sample_rate = pstr_uni_drc_config->sample_rate;
143
967
  }
144
145
1.12k
  pstr_gain_enc->domain = domain;
146
1.12k
  pstr_gain_enc->delay_mode = delay_mode;
147
1.12k
  pstr_gain_enc->delta_tmin_default = impd_drc_get_delta_t_min(pstr_gain_enc->sample_rate);
148
149
1.12k
  if ((pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count > 0) &&
150
242
      (pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[0].time_delta_min_present == 1)) {
151
181
    pstr_gain_enc->delta_tmin =
152
181
        pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[0].delta_tmin;
153
942
  } else if ((pstr_uni_drc_config->drc_coefficients_uni_drc_count > 0) &&
154
459
             (pstr_drc_coefficients_uni_drc->str_gain_set_params[0].time_delta_min_present ==
155
459
              1)) {
156
333
    pstr_gain_enc->delta_tmin = pstr_drc_coefficients_uni_drc->str_gain_set_params[0].delta_tmin;
157
609
  } else {
158
609
    pstr_gain_enc->delta_tmin = impd_drc_get_delta_t_min(pstr_gain_enc->sample_rate);
159
609
  }
160
161
1.12k
  num_gain_values_max = pstr_gain_enc->drc_frame_size / pstr_gain_enc->delta_tmin;
162
1.12k
  pstr_gain_enc->base_ch_count = pstr_uni_drc_config->str_channel_layout.base_ch_count;
163
164
1.12k
  memcpy(&pstr_gain_enc->str_uni_drc_config, pstr_uni_drc_config,
165
1.12k
         sizeof(ia_drc_uni_drc_config_struct));
166
1.12k
  memcpy(&pstr_gain_enc->str_loudness_info_set, pstr_loudness_info_set,
167
1.12k
         sizeof(ia_drc_loudness_info_set_struct));
168
169
1.12k
  k = 0;
170
1.12k
  if (pstr_uni_drc_config->drc_coefficients_uni_drc_count > 0) {
171
2.09k
    for (j = 0; j < pstr_drc_coefficients_uni_drc->gain_set_count; j++) {
172
1.65k
      ch_idx = 0;
173
1.65k
      found_ch_idx = 0;
174
1.65k
      ia_drc_gain_set_params_struct *pstr_gain_set_params =
175
1.65k
          &pstr_drc_coefficients_uni_drc->str_gain_set_params[j];
176
177
2.58k
      for (m = 0; m < pstr_uni_drc_config->drc_instructions_uni_drc_count; m++) {
178
958
        if (pstr_uni_drc_config->str_drc_instructions_uni_drc[m].drc_location ==
179
958
            pstr_drc_coefficients_uni_drc->drc_location) {
180
2.81k
          for (ch = 0; ch < MAX_CHANNEL_COUNT; ch++) {
181
2.51k
            if (pstr_uni_drc_config->str_drc_instructions_uni_drc[m].gain_set_index[ch] == j) {
182
33
              ch_idx = ch;
183
33
              found_ch_idx = 1;
184
33
              break;
185
33
            }
186
2.51k
          }
187
339
        }
188
958
        if (found_ch_idx) {
189
33
          break;
190
33
        }
191
958
      }
192
1.65k
      if (ch_idx >= (UWORD32)pstr_gain_enc->base_ch_count) {
193
6
        return IA_EXHEAACE_INIT_FATAL_DRC_INVALID_CHANNEL_INDEX;
194
6
      }
195
1.65k
      if (pstr_gain_set_params->band_count > 1) {
196
51
        impd_drc_util_stft_read_gain_config(pstr_gain_enc->str_drc_stft_gain_handle[0][j],
197
51
                                            pstr_gain_set_params->band_count,
198
51
                                            pstr_gain_set_params);
199
200
155
        for (l = 0; l < pstr_gain_set_params->band_count; l++) {
201
108
          err_code = impd_drc_stft_drc_gain_calc_init(pstr_gain_enc, 0, j, l);
202
108
          if (err_code) {
203
4
            return err_code;
204
4
          }
205
104
          pstr_gain_enc->str_drc_stft_gain_handle[0][j][l].ch_idx = ch_idx;
206
104
          pstr_gain_enc->str_drc_stft_gain_handle[0][j][l].is_valid = 1;
207
104
        }
208
1.60k
      } else if (pstr_gain_set_params->band_count == 1) {
209
526
        impd_drc_util_td_read_gain_config(&pstr_gain_enc->str_drc_compand[0][j],
210
526
                                          pstr_gain_set_params);
211
212
526
        pstr_gain_enc->str_drc_compand[0][j].initial_volume = 0.0f;
213
214
526
        err_code = impd_drc_td_drc_gain_calc_init(pstr_gain_enc, 0, j);
215
526
        if (err_code) {
216
13
          return err_code;
217
13
        }
218
513
        pstr_gain_enc->str_drc_compand[0][j].ch_idx = ch_idx;
219
513
        pstr_gain_enc->str_drc_compand[0][j].is_valid = 1;
220
513
      }
221
222
2.25k
      for (l = 0; l < pstr_gain_set_params->band_count; l++) {
223
615
        pstr_gain_enc->str_drc_gain_seq_buf[k].str_drc_group.n_gain_values = 1;
224
615
        pstr_gain_enc->str_drc_gain_seq_buf[k].str_gain_set_params =
225
615
            pstr_drc_coefficients_uni_drc->str_gain_set_params[j];
226
615
        k++;
227
615
      }
228
1.63k
    }
229
459
  }
230
1.10k
  k = 0;
231
1.49k
  for (i = 0; i < pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count; i++) {
232
411
    pstr_drc_coefficients_uni_drc_v1 =
233
411
        &pstr_uni_drc_config_ext->str_drc_coefficients_uni_drc_v1[i];
234
1.27k
    for (j = 0; j < pstr_drc_coefficients_uni_drc_v1->gain_set_count; j++) {
235
877
      ch_idx = 0;
236
877
      found_ch_idx = 0;
237
877
      ia_drc_gain_set_params_struct *pstr_gain_set_params =
238
877
          &pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[j];
239
240
2.52k
      for (m = 0; m < pstr_uni_drc_config_ext->drc_instructions_uni_drc_v1_count; m++) {
241
1.66k
        if (pstr_uni_drc_config_ext->str_drc_instructions_uni_drc_v1[m].drc_location ==
242
1.66k
            pstr_drc_coefficients_uni_drc_v1->drc_location) {
243
222
          for (ch = 0; ch < MAX_CHANNEL_COUNT; ch++) {
244
201
            if (pstr_uni_drc_config_ext->str_drc_instructions_uni_drc_v1[m].gain_set_index[ch] ==
245
201
                j) {
246
12
              ch_idx = ch;
247
12
              found_ch_idx = 1;
248
12
              break;
249
12
            }
250
201
          }
251
33
        }
252
1.66k
        if (found_ch_idx) {
253
12
          break;
254
12
        }
255
1.66k
      }
256
257
877
      if (ch_idx >= (UWORD32)pstr_gain_enc->base_ch_count) {
258
6
        return IA_EXHEAACE_INIT_FATAL_DRC_INVALID_CHANNEL_INDEX;
259
6
      }
260
261
871
      if (pstr_gain_set_params->band_count > 1) {
262
169
        impd_drc_util_stft_read_gain_config(pstr_gain_enc->str_drc_stft_gain_handle[i][j],
263
169
                                            pstr_gain_set_params->band_count,
264
169
                                            pstr_gain_set_params);
265
266
505
        for (l = 0; l < pstr_gain_set_params->band_count; l++) {
267
339
          err_code = impd_drc_stft_drc_gain_calc_init(pstr_gain_enc, i, j, l);
268
339
          if (err_code) {
269
3
            return err_code;
270
3
          }
271
336
          pstr_gain_enc->str_drc_stft_gain_handle[i][j][l].ch_idx = ch_idx;
272
336
          pstr_gain_enc->str_drc_stft_gain_handle[i][j][l].is_valid = 1;
273
336
        }
274
702
      } else if (pstr_gain_set_params->band_count == 1) {
275
436
        impd_drc_util_td_read_gain_config(&pstr_gain_enc->str_drc_compand[i][j],
276
436
                                          pstr_gain_set_params);
277
278
436
        pstr_gain_enc->str_drc_compand[i][j].initial_volume = 0.0f;
279
280
436
        err_code = impd_drc_td_drc_gain_calc_init(pstr_gain_enc, i, j);
281
436
        if (err_code) {
282
9
          return err_code;
283
9
        }
284
427
        pstr_gain_enc->str_drc_compand[i][j].ch_idx = ch_idx;
285
427
        pstr_gain_enc->str_drc_compand[i][j].is_valid = 1;
286
427
      }
287
288
1.61k
      for (l = 0; l < pstr_gain_set_params->band_count; l++) {
289
760
        pstr_gain_enc->str_drc_gain_seq_buf[k].str_drc_group.n_gain_values = 1;
290
760
        pstr_gain_enc->str_drc_gain_seq_buf[k].str_gain_set_params =
291
760
            pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[j];
292
760
        k++;
293
760
      }
294
859
    }
295
411
  }
296
297
1.08k
  impd_drc_generate_delta_time_code_table(num_gain_values_max,
298
1.08k
                                          pstr_gain_enc->str_delta_time_code_table);
299
300
78.2k
  for (i = num_gain_values_max - 1; i >= 0; i--) {
301
77.1k
    pstr_gain_enc->delta_time_quant_table[i] = pstr_gain_enc->delta_tmin * (i + 1);
302
77.1k
  }
303
304
1.08k
  return err_code;
305
1.10k
}
306
307
IA_ERRORCODE impd_drc_encode_uni_drc_gain(ia_drc_gain_enc_struct *pstr_gain_enc,
308
51.3k
                                          FLOAT32 *ptr_gain_buffer, VOID *pstr_scratch) {
309
51.3k
  LOOPIDX idx;
310
51.3k
  IA_ERRORCODE err_code = IA_NO_ERROR;
311
137k
  for (idx = 0; idx < pstr_gain_enc->n_sequences; idx++) {
312
86.6k
    err_code = impd_drc_quantize_and_encode_drc_gain(
313
86.6k
        pstr_gain_enc, &ptr_gain_buffer[idx * MAX_DRC_FRAME_SIZE],
314
86.6k
        &(pstr_gain_enc->drc_gain_per_sample_with_prev_frame[idx][0]),
315
86.6k
        pstr_gain_enc->str_delta_time_code_table, &(pstr_gain_enc->str_drc_gain_seq_buf[idx]),
316
86.6k
        pstr_scratch);
317
318
86.6k
    if (err_code) {
319
0
      return err_code;
320
0
    }
321
86.6k
  }
322
51.3k
  return err_code;
323
51.3k
}
324
325
4.53k
WORD32 impd_drc_get_delta_t_min(const WORD32 sample_rate) {
326
4.53k
  WORD32 lower_bound;
327
4.53k
  WORD32 result = 1;
328
4.53k
  WORD32 sample_rate_local = sample_rate;
329
330
4.53k
  if (sample_rate_local < 1000) {
331
0
    sample_rate_local = 1000;
332
0
  }
333
4.53k
  lower_bound = (WORD32)((0.0005f * sample_rate_local) + 0.5f);
334
335
26.0k
  while (result <= lower_bound) {
336
21.5k
    result = result << 1;
337
21.5k
  }
338
4.53k
  return result;
339
4.53k
}