xref: /aosp_15_r20/external/libxaac/encoder/drc_src/impd_drc_gain_enc.c (revision 15dc779a375ca8b5125643b829a8aa4b70d7f451)
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 <stdlib.h>
22 #include <string.h>
23 #include <math.h>
24 #include <float.h>
25 #include "ixheaac_type_def.h"
26 #include "ixheaac_error_standards.h"
27 #include "ixheaace_error_codes.h"
28 
29 #include "iusace_cnst.h"
30 #include "iusace_bitbuffer.h"
31 #include "impd_drc_common_enc.h"
32 #include "impd_drc_uni_drc.h"
33 #include "impd_drc_api.h"
34 #include "impd_drc_uni_drc_eq.h"
35 #include "impd_drc_uni_drc_filter_bank.h"
36 #include "impd_drc_gain_enc.h"
37 #include "impd_drc_struct_def.h"
38 #include "impd_drc_tables.h"
39 #include "impd_drc_enc.h"
40 #include "impd_drc_mux.h"
41 #include "iusace_block_switch_const.h"
42 
43 #include "iusace_tns_usac.h"
44 #include "iusace_psy_mod.h"
45 #include "ixheaace_sbr_header.h"
46 #include "ixheaace_config.h"
47 #include "iusace_config.h"
48 #include "ixheaace_common_utils.h"
49 
impd_drc_limit_drc_gain(const WORD32 gain_coding_profile,const FLOAT32 gain)50 static FLOAT32 impd_drc_limit_drc_gain(const WORD32 gain_coding_profile, const FLOAT32 gain) {
51   FLOAT32 limited_drc_gain;
52 
53   switch (gain_coding_profile) {
54     case GAIN_CODING_PROFILE_CONSTANT:
55       limited_drc_gain = gain;
56       break;
57     case GAIN_CODING_PROFILE_CLIPPING:
58       limited_drc_gain =
59           MAX(MIN(MAX_DRC_GAIN_CODING_PROFILE2, gain), MIN_DRC_GAIN_CODING_PROFILE2);
60       break;
61     case GAIN_CODING_PROFILE_FADING:
62       limited_drc_gain =
63           MAX(MIN(MAX_DRC_GAIN_CODING_PROFILE1, gain), MIN_DRC_GAIN_CODING_PROFILE1);
64       break;
65     case GAIN_CODING_PROFILE_REGULAR:
66       limited_drc_gain =
67           MAX(MIN(MAX_DRC_GAIN_CODING_PROFILE0, gain), MIN_DRC_GAIN_CODING_PROFILE0);
68       break;
69     default:
70       limited_drc_gain = gain;
71       break;
72   }
73 
74   return limited_drc_gain;
75 }
76 
impd_drc_get_quantized_delta_drc_gain(const WORD32 gain_coding_profile,const FLOAT32 delta_gain,FLOAT32 * delta_gain_quant,WORD32 * num_bits,WORD32 * gain_code)77 static VOID impd_drc_get_quantized_delta_drc_gain(const WORD32 gain_coding_profile,
78                                                   const FLOAT32 delta_gain,
79                                                   FLOAT32 *delta_gain_quant, WORD32 *num_bits,
80                                                   WORD32 *gain_code) {
81   LOOPIDX idx;
82   WORD32 num_entries, opt_index;
83   WORD32 min_pos_diff_idx = 0;
84   WORD32 min_neg_diff_idx = 0;
85   FLOAT32 difference;
86   FLOAT32 min_pos_diff = 1000.0f;
87   FLOAT32 min_neg_diff = -1000.0f;
88   ia_drc_delta_gain_code_entry_struct const *pstr_delta_gain_code_table;
89 
90   impd_drc_get_delta_gain_code_table(gain_coding_profile, &pstr_delta_gain_code_table,
91                                      &num_entries);
92   for (idx = 0; idx < num_entries; idx++) {
93     difference = delta_gain - pstr_delta_gain_code_table[idx].value;
94     if (difference <= 0.0f) {
95       if (difference > min_neg_diff) {
96         min_neg_diff = difference;
97         min_neg_diff_idx = idx;
98       }
99     } else {
100       if (difference < min_pos_diff) {
101         min_pos_diff = difference;
102         min_pos_diff_idx = idx;
103       }
104     }
105   }
106   if (min_pos_diff >= -min_neg_diff) {
107     opt_index = min_neg_diff_idx;
108   } else {
109     opt_index = min_pos_diff_idx;
110   }
111 
112   *delta_gain_quant = pstr_delta_gain_code_table[opt_index].value;
113   *num_bits = pstr_delta_gain_code_table[opt_index].size;
114   *gain_code = pstr_delta_gain_code_table[opt_index].code;
115 }
116 
impd_drc_check_overshoot(const WORD32 t_gain_step,const FLOAT32 gain_0,const FLOAT32 gain_1,const FLOAT32 slope_0,const FLOAT32 slope_1,const WORD32 time_delta_min,WORD32 * overshoot_left,WORD32 * overshoot_right)117 static VOID impd_drc_check_overshoot(const WORD32 t_gain_step, const FLOAT32 gain_0,
118                                      const FLOAT32 gain_1, const FLOAT32 slope_0,
119                                      const FLOAT32 slope_1, const WORD32 time_delta_min,
120                                      WORD32 *overshoot_left, WORD32 *overshoot_right) {
121   WORD32 t_connect;
122   FLOAT32 norm_slope_0, norm_slope_1;
123   FLOAT32 gain_left, gain_right;
124   FLOAT32 t_gain_step_inv, t_gain_step_inv_2;
125   FLOAT32 temp_a, temp_b, temp_c, temp_d;
126   FLOAT32 curve_left, curve_right;
127   FLOAT32 max_val, min_val;
128   FLOAT32 tmp, tmp2;
129   FLOAT32 g_extreme, t_extreme;
130   FLOAT32 k1, k2;
131   FLOAT32 slope_norm = 1.0f / (FLOAT32)time_delta_min;
132   FLOAT32 margin = 0.2f;
133   FLOAT32 step_inv_2 = ixheaace_div32(2.0f, (FLOAT32)t_gain_step);
134 
135   *overshoot_left = FALSE;
136   *overshoot_right = FALSE;
137 
138   gain_left = (FLOAT32)pow((FLOAT64)10.0, (FLOAT64)(0.05f * gain_0));
139   gain_right = (FLOAT32)pow((FLOAT64)10.0, (FLOAT64)(0.05f * gain_1));
140 
141   norm_slope_0 = slope_0 * slope_norm * SLOPE_FACTOR_DB_TO_LINEAR * gain_left;
142   norm_slope_1 = slope_1 * slope_norm * SLOPE_FACTOR_DB_TO_LINEAR * gain_right;
143 
144   if ((FLOAT32)fabs((FLOAT64)norm_slope_0) < (FLOAT32)fabs((FLOAT64)norm_slope_1)) {
145     t_connect = (WORD32)(0.5f + 2.0f * (gain_left - gain_right + norm_slope_0 * t_gain_step) /
146                                     (norm_slope_0 - norm_slope_1));
147     t_connect = t_gain_step - t_connect;
148     if ((t_connect >= 0) && (t_connect < t_gain_step)) {
149       return;
150     }
151   } else if ((FLOAT32)fabs((FLOAT64)norm_slope_0) > (FLOAT32)fabs((FLOAT64)norm_slope_1)) {
152     t_connect = (WORD32)(0.5f + 2.0f * (gain_right - gain_left - norm_slope_1 * t_gain_step) /
153                                     (norm_slope_0 - norm_slope_1));
154     if ((t_connect >= 0) && (t_connect < t_gain_step)) {
155       return;
156     }
157   }
158 
159   tmp = 1.5f * step_inv_2 * (gain_right - gain_left) - norm_slope_1 - norm_slope_0;
160   curve_left = step_inv_2 * (tmp - norm_slope_0);
161   curve_right = step_inv_2 * (norm_slope_1 - tmp);
162 
163   tmp = -norm_slope_0 * t_gain_step - gain_left + gain_right;
164   if (curve_left >= 0.0f) {
165     if (tmp + margin < 0.0f) {
166       *overshoot_left = TRUE;
167     }
168   } else {
169     if (tmp - margin > 0.0f) {
170       *overshoot_left = TRUE;
171     }
172   }
173   tmp = norm_slope_1 * t_gain_step - gain_right + gain_left;
174   if (curve_right >= 0.0f) {
175     if (tmp + margin < 0.0f) {
176       *overshoot_right = TRUE;
177     }
178   } else {
179     if (tmp - margin > 0.0f) {
180       *overshoot_right = TRUE;
181     }
182   }
183 
184   if ((!*overshoot_left) && (!*overshoot_right)) {
185     t_gain_step_inv = ixheaace_div32(1.0f, (FLOAT32)t_gain_step);
186     t_gain_step_inv_2 = t_gain_step_inv * t_gain_step_inv;
187     k1 = (gain_right - gain_left) * t_gain_step_inv_2;
188     k2 = norm_slope_1 + norm_slope_0;
189 
190     temp_a = t_gain_step_inv * (t_gain_step_inv * k2 - 2.0f * k1);
191     temp_b = 3.0f * k1 - t_gain_step_inv * (k2 + norm_slope_0);
192     temp_c = norm_slope_0;
193     temp_d = gain_left;
194     tmp = temp_b * temp_b - 3.0f * temp_a * temp_c;
195 
196     if (!((tmp < 0.0f) || (temp_a == 0.0f))) {
197       max_val = MAX(gain_left, gain_right) + margin;
198       min_val = MIN(gain_left, gain_right) - margin;
199       tmp = (FLOAT32)sqrt((FLOAT64)tmp);
200       tmp2 = (1.0f / (3.0f * temp_a));
201 
202       t_extreme = tmp2 * (-temp_b + tmp);
203       if ((t_extreme > 0.0f) && (t_extreme < t_gain_step)) {
204         g_extreme = (((temp_a * t_extreme + temp_b) * t_extreme + temp_c) * t_extreme) + temp_d;
205         if ((g_extreme > max_val) || (g_extreme < min_val)) {
206           *overshoot_left = TRUE;
207         }
208       }
209 
210       t_extreme = tmp2 * (-temp_b - tmp);
211       if ((t_extreme > 0.0f) && (t_extreme < t_gain_step)) {
212         g_extreme = (((temp_a * t_extreme + temp_b) * t_extreme + temp_c) * t_extreme) + temp_d;
213         if ((g_extreme > max_val) || (g_extreme < min_val)) {
214           *overshoot_left = TRUE;
215         }
216       }
217     }
218   }
219 }
220 
impd_drc_quantize_slope(const FLOAT32 slope,FLOAT32 * slope_quant,WORD32 * slope_code_index)221 static VOID impd_drc_quantize_slope(const FLOAT32 slope, FLOAT32 *slope_quant,
222                                     WORD32 *slope_code_index) {
223   LOOPIDX idx = 0;
224   const ia_drc_slope_code_table_entry_struct *pstr_slope_code_table =
225       impd_drc_get_slope_code_table_by_value();
226 
227   while ((idx < 14) && (slope > pstr_slope_code_table[idx].value)) {
228     idx++;
229   }
230   if (idx > 0 && ((pstr_slope_code_table[idx].value - slope) >
231                   (slope - pstr_slope_code_table[idx - 1].value))) {
232     idx--;
233   }
234 
235   *slope_quant = pstr_slope_code_table[idx].value;
236   *slope_code_index = pstr_slope_code_table[idx].index;
237 }
238 
impd_drc_get_preliminary_nodes(const ia_drc_gain_enc_struct * pstr_gain_enc,const FLOAT32 * ptr_drc_gain_per_sample,FLOAT32 * ptr_drc_gain_per_sample_with_prev_frame,ia_drc_group_struct * pstr_drc_group,const WORD32 full_frame,VOID * pstr_scratch)239 static VOID impd_drc_get_preliminary_nodes(const ia_drc_gain_enc_struct *pstr_gain_enc,
240                                            const FLOAT32 *ptr_drc_gain_per_sample,
241                                            FLOAT32 *ptr_drc_gain_per_sample_with_prev_frame,
242                                            ia_drc_group_struct *pstr_drc_group,
243                                            const WORD32 full_frame, VOID *pstr_scratch) {
244   LOOPIDX n, k;
245   WORD32 t, index;
246   WORD32 drc_frame_size = pstr_gain_enc->drc_frame_size;
247   WORD32 time_delta_min = pstr_gain_enc->delta_tmin;
248   WORD32 num_values = drc_frame_size / time_delta_min;
249   WORD32 offset = time_delta_min / 2;
250   WORD32 num_gain_values;
251   WORD32 n_left, n_right;
252 
253   FLOAT32 gain, gain_quant, gain_quant_prev;
254   FLOAT32 quant_error_prev = -1.0f;
255   FLOAT32 quant_error;
256   FLOAT32 slope_prev, slope_next;
257   FLOAT32 f0 = 0.9f;
258   FLOAT32 f1 = 1.0f - f0;
259 
260   WORD32 *ptr_time_at_node = pstr_drc_group->ts_gain;
261   FLOAT32 *ptr_gain_at_node = pstr_drc_group->drc_gain;
262   FLOAT32 *ptr_slope_at_node = pstr_drc_group->slope;
263   FLOAT32 *ptr_gain = ptr_drc_gain_per_sample_with_prev_frame + drc_frame_size;
264   iusace_scratch_mem *ptr_scratch = (iusace_scratch_mem *)(pstr_scratch);
265   FLOAT32 *ptr_slope = (FLOAT32 *)ptr_scratch->ptr_drc_scratch_buf;
266 
267   memcpy(ptr_drc_gain_per_sample_with_prev_frame,
268          &(ptr_drc_gain_per_sample_with_prev_frame[drc_frame_size]),
269          drc_frame_size * sizeof(FLOAT32));
270   memcpy(&(ptr_drc_gain_per_sample_with_prev_frame[drc_frame_size]), ptr_drc_gain_per_sample,
271          drc_frame_size * sizeof(FLOAT32));
272 
273   for (n = 0; n < drc_frame_size; n++) {
274     ptr_gain[n] *= SCALE_APPROXIMATE_DB;
275   }
276   for (n = 0; n < drc_frame_size; n++) {
277     ptr_gain[n] = f0 * ptr_gain[n - 1] + f1 * ptr_gain[n];
278   }
279 
280   if (pstr_drc_group->gain_prev_node < 0.f) {
281     gain_quant_prev =
282         GAIN_QUANT_STEP_SIZE *
283         ((WORD32)(-0.5f + GAIN_QUANT_STEP_SIZE_INV * pstr_drc_group->gain_prev_node));
284   } else {
285     gain_quant_prev =
286         GAIN_QUANT_STEP_SIZE *
287         ((WORD32)(0.5f + GAIN_QUANT_STEP_SIZE_INV * pstr_drc_group->gain_prev_node));
288   }
289 
290   k = -1;
291   for (n = 1; n < num_values + 1; n++) {
292     gain = ptr_gain[n * time_delta_min - 1];
293     if (gain < 0.f) {
294       gain_quant = GAIN_QUANT_STEP_SIZE * ((WORD32)(-0.5f + GAIN_QUANT_STEP_SIZE_INV * gain));
295     } else {
296       gain_quant = GAIN_QUANT_STEP_SIZE * ((WORD32)(0.5f + GAIN_QUANT_STEP_SIZE_INV * gain));
297     }
298     quant_error = (FLOAT32)fabs((FLOAT64)(gain - gain_quant));
299 
300     slope_prev = (gain - ptr_gain[(n - 1) * time_delta_min - 1]);
301     if (n == num_values) {
302       slope_next = 0.2f;
303     } else {
304       slope_next = (ptr_gain[(n + 1) * time_delta_min - 1] - gain);
305     }
306 
307     if (gain_quant_prev != gain_quant) {
308       k++;
309       quant_error_prev = quant_error;
310       gain_quant_prev = gain_quant;
311       ptr_time_at_node[k] = n * time_delta_min - 1;
312       if ((FLOAT32)fabs((FLOAT64)slope_prev) > 0.1f) {
313         gain_quant_prev = 1000.0f;
314       }
315     } else {
316       if ((FLOAT32)fabs((FLOAT64)slope_next) > 0.1f) {
317         if (k < 0) {
318           k = 0;
319         }
320         ptr_time_at_node[k] = n * time_delta_min - 1;
321       } else {
322         if (quant_error_prev > quant_error) {
323           if (k < 0) {
324             k = 0;
325           }
326           quant_error_prev = quant_error;
327           ptr_time_at_node[k] = n * time_delta_min - 1;
328         }
329       }
330     }
331   }
332   if (full_frame == 1) {
333     if (ptr_time_at_node[k] != drc_frame_size - 1) {
334       k++;
335       ptr_time_at_node[k] = drc_frame_size - 1;
336     }
337   }
338 
339   num_gain_values = k + 1;
340   if (num_gain_values <= 0) {
341     if (k < 0) {
342       k = 0;
343     }
344     n = num_values / 2;
345     index = offset + n * time_delta_min - 1;
346     ptr_slope[n] =
347         ptr_drc_gain_per_sample[index + time_delta_min] - ptr_drc_gain_per_sample[index];
348     t = (n + 1) * time_delta_min - 1;
349     ptr_time_at_node[k] = t;
350     ptr_slope_at_node[k] = ptr_slope[n];
351     ptr_gain_at_node[k] = ptr_drc_gain_per_sample[t];
352     num_gain_values++;
353   }
354 
355   for (k = 0; k < num_gain_values; k++) {
356     n_left = MAX(0, ptr_time_at_node[k] - time_delta_min);
357     n_right = n_left + time_delta_min;
358     ptr_slope_at_node[k] = ptr_gain[n_right] - ptr_gain[n_left];
359     ptr_gain_at_node[k] = ptr_gain[ptr_time_at_node[k]];
360   }
361 
362   pstr_drc_group->n_gain_values = num_gain_values;
363 }
364 
impd_drc_advance_nodes(ia_drc_gain_enc_struct * pstr_gain_enc,ia_drc_gain_seq_buf_struct * pstr_drc_gain_seq_buf)365 static VOID impd_drc_advance_nodes(ia_drc_gain_enc_struct *pstr_gain_enc,
366                                    ia_drc_gain_seq_buf_struct *pstr_drc_gain_seq_buf) {
367   LOOPIDX idx;
368   ia_drc_group_struct *pstr_drc_group = &(pstr_drc_gain_seq_buf->str_drc_group);
369   ia_drc_group_for_output_struct *pstr_drc_group_for_output =
370       &(pstr_drc_gain_seq_buf->str_drc_group_for_output);
371 
372   if (pstr_drc_group_for_output->n_gain_values > 0) {
373     pstr_drc_group_for_output->time_quant_prev =
374         pstr_drc_group_for_output->ts_gain_quant[pstr_drc_group_for_output->n_gain_values - 1] -
375         pstr_gain_enc->drc_frame_size;
376     pstr_drc_group_for_output->slope_code_index_prev =
377         pstr_drc_group_for_output->slope_code_index[pstr_drc_group_for_output->n_gain_values - 1];
378     pstr_drc_group_for_output->drc_gain_quant_prev =
379         pstr_drc_group_for_output->drc_gain_quant[pstr_drc_group_for_output->n_gain_values - 1];
380   }
381   for (idx = 0; idx < pstr_drc_group->n_gain_values; idx++) {
382     pstr_drc_group_for_output->ts_gain_quant[idx] = pstr_drc_group->ts_gain_quant[idx];
383     pstr_drc_group_for_output->time_delta_quant[idx] = pstr_drc_group->time_delta_quant[idx];
384     pstr_drc_group_for_output->slope_quant[idx] = pstr_drc_group->slope_quant[idx];
385     pstr_drc_group_for_output->slope_code_index[idx] = pstr_drc_group->slope_code_index[idx];
386     pstr_drc_group_for_output->gain_code[idx] = pstr_drc_group->gain_code[idx];
387     pstr_drc_group_for_output->gain_code_length[idx] = pstr_drc_group->gain_code_length[idx];
388     pstr_drc_group_for_output->drc_gain_quant[idx] = pstr_drc_group->drc_gain_quant[idx];
389   }
390   pstr_drc_group_for_output->n_gain_values = pstr_drc_group->n_gain_values;
391 }
392 
impd_drc_post_process_nodes(ia_drc_gain_enc_struct * pstr_gain_enc,ia_drc_delta_time_code_table_entry_struct * pstr_delta_time_code_table,ia_drc_gain_seq_buf_struct * pstr_drc_gain_seq_buf,VOID * pstr_scratch)393 static IA_ERRORCODE impd_drc_post_process_nodes(
394     ia_drc_gain_enc_struct *pstr_gain_enc,
395     ia_drc_delta_time_code_table_entry_struct *pstr_delta_time_code_table,
396     ia_drc_gain_seq_buf_struct *pstr_drc_gain_seq_buf, VOID *pstr_scratch) {
397   LOOPIDX k, n;
398   WORD32 time_mandatory_node;
399   WORD32 n_removed, move_on;
400   WORD32 idx_left, idx_right;
401   WORD32 idx_0, idx_1, idx_2, idx_3;
402   WORD32 left, mid, right;
403   WORD32 overshoot_right, overshoot_left;
404   WORD32 cod_slope_zero = 0x7;
405   WORD32 slope_changed = TRUE;
406   WORD32 repeat_check = TRUE;
407   WORD32 time_prev = -1;
408   WORD32 time_delta_min = pstr_gain_enc->delta_tmin;
409 
410   FLOAT32 delta_gain;
411   FLOAT32 delta_gain_quant;
412   FLOAT32 gain_value_quant = 0;
413   FLOAT32 slope_average;
414   FLOAT32 slope_of_nodes_left;
415   FLOAT32 slope_of_nodes_right;
416   FLOAT32 thr_low, thr_high;
417   FLOAT32 delta_left, delta_right;
418   FLOAT32 slope_0, slope_1, slope_2;
419   IA_ERRORCODE err_code = IA_NO_ERROR;
420 
421   const ia_drc_slope_code_table_entry_struct *pstr_slope_code_table;
422   ia_drc_group_for_output_struct *pstr_drc_group_for_output =
423       &(pstr_drc_gain_seq_buf->str_drc_group_for_output);
424   WORD32 num_gain_values = pstr_drc_group_for_output->n_gain_values;
425   FLOAT32 drc_gain_quant_prev = pstr_drc_group_for_output->drc_gain_quant_prev;
426 
427   iusace_scratch_mem *ptr_scratch = (iusace_scratch_mem *)(pstr_scratch);
428   FLOAT32 *ptr_gain_buf = (FLOAT32 *)((UWORD8 *)ptr_scratch->ptr_drc_scratch_buf);
429   WORD32 *ptr_time_buf =
430       (WORD32 *)(((UWORD8 *)ptr_gain_buf) + (N_UNIDRC_GAIN_MAX + 2) * sizeof(ptr_gain_buf[0]));
431   WORD32 *ptr_slope_code_index_buf =
432       (WORD32 *)(((UWORD8 *)ptr_time_buf) + (N_UNIDRC_GAIN_MAX + 2) * sizeof(ptr_time_buf[0]));
433   WORD32 *ptr_remove = (WORD32 *)(((UWORD8 *)ptr_slope_code_index_buf) +
434                                   (N_UNIDRC_GAIN_MAX + 2) * sizeof(ptr_slope_code_index_buf[0]));
435 
436   if (pstr_drc_gain_seq_buf->str_gain_set_params.full_frame != 1) {
437     time_mandatory_node = 99999999;
438   } else {
439     time_mandatory_node = pstr_gain_enc->drc_frame_size - 1;
440   }
441 
442   ptr_time_buf[0] = pstr_drc_group_for_output->time_quant_prev;
443   ptr_gain_buf[0] = pstr_drc_group_for_output->drc_gain_quant_prev;
444   for (k = 0; k < num_gain_values; k++) {
445     ptr_time_buf[k + 1] = pstr_drc_group_for_output->ts_gain_quant[k];
446     ptr_gain_buf[k + 1] = pstr_drc_group_for_output->drc_gain_quant[k];
447   }
448   ptr_time_buf[k + 1] = pstr_drc_group_for_output->time_quant_next;
449   ptr_gain_buf[k + 1] = pstr_drc_group_for_output->drc_gain_quant_next;
450 
451   if (num_gain_values > 1) {
452     idx_left = 0;
453     idx_right = 2;
454     n_removed = 0;
455     for (k = 0; k <= num_gain_values + 1; k++) {
456       ptr_remove[k] = FALSE;
457     }
458     while (idx_right <= num_gain_values + 1) {
459       if ((ptr_gain_buf[idx_left] == ptr_gain_buf[idx_right - 1]) &&
460           (ptr_gain_buf[idx_right - 1] == ptr_gain_buf[idx_right]) &&
461           (num_gain_values - n_removed > 1) &&
462           (ptr_time_buf[idx_right - 1] != time_mandatory_node)) {
463         ptr_remove[idx_right - 1] = TRUE;
464         idx_right++;
465         n_removed++;
466       } else {
467         idx_left = idx_right - 1;
468         idx_right++;
469       }
470     }
471 
472     n = 1;
473     for (k = 1; k <= num_gain_values + 1; k++) {
474       if (!ptr_remove[k]) {
475         ptr_time_buf[n] = ptr_time_buf[k];
476         ptr_gain_buf[n] = ptr_gain_buf[k];
477         n++;
478       }
479     }
480 
481     n = 0;
482     for (k = 0; k < num_gain_values; k++) {
483       if (!ptr_remove[k + 1]) {
484         pstr_drc_group_for_output->ts_gain_quant[n] = pstr_drc_group_for_output->ts_gain_quant[k];
485         pstr_drc_group_for_output->time_delta_quant[n] =
486             pstr_drc_group_for_output->time_delta_quant[k];
487         pstr_drc_group_for_output->slope_quant[n] = pstr_drc_group_for_output->slope_quant[k];
488         pstr_drc_group_for_output->slope_code_index[n] =
489             pstr_drc_group_for_output->slope_code_index[k];
490         pstr_drc_group_for_output->gain_code[n] = pstr_drc_group_for_output->gain_code[k];
491         pstr_drc_group_for_output->gain_code_length[n] =
492             pstr_drc_group_for_output->gain_code_length[k];
493         pstr_drc_group_for_output->drc_gain_quant[n] =
494             pstr_drc_group_for_output->drc_gain_quant[k];
495         n++;
496       }
497     }
498     num_gain_values = n;
499   }
500 
501   if (num_gain_values > 2) {
502     move_on = FALSE;
503     idx_0 = 0;
504     idx_1 = 1;
505     idx_2 = 2;
506     idx_3 = 3;
507     n_removed = 0;
508     for (k = 0; k <= num_gain_values + 1; k++) {
509       ptr_remove[k] = FALSE;
510     }
511     while (idx_3 < num_gain_values + 1) {
512       if (move_on) {
513         move_on = FALSE;
514         idx_0 = idx_1;
515         idx_1 = idx_2;
516         idx_2 = idx_3;
517         idx_3++;
518       }
519       if (ptr_gain_buf[idx_1] != ptr_gain_buf[idx_2]) {
520         move_on = TRUE;
521       } else {
522         delta_left = ptr_gain_buf[idx_1] - ptr_gain_buf[idx_0];
523         delta_right = ptr_gain_buf[idx_3] - ptr_gain_buf[idx_2];
524 
525         if (((FLOAT32)fabs((FLOAT64)delta_left) < 0.26f) ||
526             ((FLOAT32)fabs((FLOAT64)delta_right) < 0.26f)) {
527           if ((delta_left > 0.0f) && (delta_right > 0.0f) &&
528               (ptr_time_buf[idx_1] != time_mandatory_node)) {
529             ptr_remove[idx_1] = TRUE;
530             pstr_drc_group_for_output->gain_code[idx_2 - 1] =
531                 pstr_drc_group_for_output->gain_code[idx_1 - 1];
532             pstr_drc_group_for_output->gain_code_length[idx_2 - 1] =
533                 pstr_drc_group_for_output->gain_code_length[idx_1 - 1];
534             idx_1 = idx_2;
535             idx_2 = idx_3;
536             idx_3++;
537             n_removed++;
538           } else if ((delta_left < 0.0f) && (delta_right < 0.0f) &&
539                      (ptr_time_buf[idx_2] != time_mandatory_node)) {
540             ptr_remove[idx_2] = TRUE;
541             idx_2 = idx_3;
542             idx_3++;
543             n_removed++;
544           } else {
545             move_on = TRUE;
546           }
547         } else {
548           move_on = TRUE;
549         }
550       }
551     }
552 
553     n = 1;
554     for (k = 1; k <= num_gain_values + 1; k++) {
555       if (!ptr_remove[k]) {
556         ptr_gain_buf[n] = ptr_gain_buf[k];
557         ptr_time_buf[n] = ptr_time_buf[k];
558         n++;
559       }
560     }
561 
562     n = 0;
563     for (k = 0; k < num_gain_values; k++) {
564       if (!ptr_remove[k + 1]) {
565         pstr_drc_group_for_output->ts_gain_quant[n] = pstr_drc_group_for_output->ts_gain_quant[k];
566         pstr_drc_group_for_output->time_delta_quant[n] =
567             pstr_drc_group_for_output->time_delta_quant[k];
568         pstr_drc_group_for_output->slope_quant[n] = pstr_drc_group_for_output->slope_quant[k];
569         pstr_drc_group_for_output->slope_code_index[n] =
570             pstr_drc_group_for_output->slope_code_index[k];
571         pstr_drc_group_for_output->gain_code[n] = pstr_drc_group_for_output->gain_code[k];
572         pstr_drc_group_for_output->gain_code_length[n] =
573             pstr_drc_group_for_output->gain_code_length[k];
574         pstr_drc_group_for_output->drc_gain_quant[n] =
575             pstr_drc_group_for_output->drc_gain_quant[k];
576         n++;
577       }
578     }
579     num_gain_values = n;
580   }
581 
582   for (k = 1; k <= num_gain_values; k++) {
583     if ((ptr_gain_buf[k - 1] < ptr_gain_buf[k]) && (ptr_gain_buf[k] > ptr_gain_buf[k + 1])) {
584       pstr_drc_group_for_output->slope_code_index[k - 1] = cod_slope_zero;
585       pstr_drc_group_for_output->slope_quant[k - 1] = 0.0f;
586     }
587     if ((ptr_gain_buf[k - 1] > ptr_gain_buf[k]) && (ptr_gain_buf[k] < ptr_gain_buf[k + 1])) {
588       pstr_drc_group_for_output->slope_code_index[k - 1] = cod_slope_zero;
589       pstr_drc_group_for_output->slope_quant[k - 1] = 0.0f;
590     }
591   }
592 
593   if (ptr_gain_buf[0] == ptr_gain_buf[1]) {
594     pstr_drc_group_for_output->slope_code_index[0] = cod_slope_zero;
595     pstr_drc_group_for_output->slope_quant[0] = 0.0f;
596   }
597   for (k = 0; k < num_gain_values - 1; k++) {
598     if (ptr_gain_buf[k + 1] == ptr_gain_buf[k + 2]) {
599       pstr_drc_group_for_output->slope_code_index[k] = cod_slope_zero;
600       pstr_drc_group_for_output->slope_code_index[k + 1] = cod_slope_zero;
601       pstr_drc_group_for_output->slope_quant[k] = 0.0f;
602       pstr_drc_group_for_output->slope_quant[k + 1] = 0.0f;
603     }
604   }
605   if (ptr_gain_buf[k + 1] == ptr_gain_buf[k + 2]) {
606     pstr_drc_group_for_output->slope_code_index[k] = cod_slope_zero;
607     pstr_drc_group_for_output->slope_quant[k] = 0.0f;
608   }
609 
610   ptr_slope_code_index_buf[0] = pstr_drc_group_for_output->slope_code_index_prev;
611   for (k = 0; k < num_gain_values; k++) {
612     ptr_slope_code_index_buf[k + 1] = pstr_drc_group_for_output->slope_code_index[k];
613   }
614   ptr_slope_code_index_buf[k + 1] = pstr_drc_group_for_output->slope_code_index_next;
615 
616   for (k = 0; k <= num_gain_values + 1; k++) {
617     ptr_remove[k] = FALSE;
618   }
619 
620   if (num_gain_values > 1) {
621     left = 0;
622     mid = 1;
623     right = 2;
624     n_removed = 0;
625     while ((right <= num_gain_values + 1) && (num_gain_values - n_removed > 1)) {
626       if (((ptr_time_buf[mid] - ptr_time_buf[left]) > 0) &&
627           (FLOAT32)fabs((FLOAT64)(ptr_gain_buf[left] - ptr_gain_buf[right])) <
628               MAX_DRC_GAIN_DELTA_BEFORE_QUANT) {
629         slope_of_nodes_left =
630             (ptr_gain_buf[mid] - ptr_gain_buf[left]) / (ptr_time_buf[mid] - ptr_time_buf[left]);
631         slope_of_nodes_right =
632             (ptr_gain_buf[right] - ptr_gain_buf[mid]) / (ptr_time_buf[right] - ptr_time_buf[mid]);
633 
634         if (slope_of_nodes_left >= 0.0f) {
635           if ((slope_of_nodes_left < slope_of_nodes_right * SLOPE_CHANGE_THR) &&
636               (slope_of_nodes_left * SLOPE_CHANGE_THR > slope_of_nodes_right)) {
637             slope_average = 0.5f * time_delta_min * (slope_of_nodes_left + slope_of_nodes_right);
638             thr_low = slope_average / SLOPE_QUANT_THR;
639             thr_high = slope_average * SLOPE_QUANT_THR;
640             slope_0 = impd_drc_decode_slope_idx_value(ptr_slope_code_index_buf[left]);
641             slope_1 = impd_drc_decode_slope_idx_value(ptr_slope_code_index_buf[mid]);
642             slope_2 = impd_drc_decode_slope_idx_value(ptr_slope_code_index_buf[right]);
643 
644             if (((slope_0 < thr_high) && (slope_0 > thr_low)) &&
645                 ((slope_1 < thr_high) && (slope_1 > thr_low)) &&
646                 ((slope_2 < thr_high) && (slope_2 > thr_low)) &&
647                 (ptr_time_buf[mid] != time_mandatory_node)) {
648               ptr_remove[mid] = TRUE;
649               n_removed++;
650               mid = right;
651               right++;
652             } else {
653               left = mid;
654               mid = right;
655               right++;
656             }
657           } else {
658             left = mid;
659             mid = right;
660             right++;
661           }
662         } else {
663           if ((-slope_of_nodes_left < -slope_of_nodes_right * SLOPE_CHANGE_THR) &&
664               (-slope_of_nodes_left * SLOPE_CHANGE_THR > -slope_of_nodes_right)) {
665             slope_average = -0.5f * time_delta_min * (slope_of_nodes_left + slope_of_nodes_right);
666             thr_low = slope_average / SLOPE_QUANT_THR;
667             thr_high = slope_average * SLOPE_QUANT_THR;
668             slope_0 = -impd_drc_decode_slope_idx_value(ptr_slope_code_index_buf[left]);
669             slope_1 = -impd_drc_decode_slope_idx_value(ptr_slope_code_index_buf[mid]);
670             slope_2 = -impd_drc_decode_slope_idx_value(ptr_slope_code_index_buf[right]);
671 
672             if (((slope_0 < thr_high) && (slope_0 > thr_low)) &&
673                 ((slope_1 < thr_high) && (slope_1 > thr_low)) &&
674                 ((slope_2 < thr_high) && (slope_2 > thr_low)) &&
675                 (ptr_time_buf[mid] != time_mandatory_node)) {
676               ptr_remove[mid] = TRUE;
677               n_removed++;
678               mid = right;
679               right++;
680             } else {
681               left = mid;
682               mid = right;
683               right++;
684             }
685           } else {
686             left = mid;
687             mid = right;
688             right++;
689           }
690         }
691       } else {
692         left = mid;
693         mid = right;
694         right++;
695       }
696     }
697 
698     n = 1;
699     for (k = 1; k <= num_gain_values + 1; k++) {
700       if (!ptr_remove[k]) {
701         ptr_time_buf[n] = ptr_time_buf[k];
702         ptr_gain_buf[n] = ptr_gain_buf[k];
703         ptr_slope_code_index_buf[n] = ptr_slope_code_index_buf[k];
704         n++;
705       }
706     }
707 
708     n = 0;
709     for (k = 0; k < num_gain_values; k++) {
710       if (!ptr_remove[k + 1]) {
711         pstr_drc_group_for_output->ts_gain_quant[n] = pstr_drc_group_for_output->ts_gain_quant[k];
712         pstr_drc_group_for_output->time_delta_quant[n] =
713             pstr_drc_group_for_output->time_delta_quant[k];
714         pstr_drc_group_for_output->gain_code[n] = pstr_drc_group_for_output->gain_code[k];
715         pstr_drc_group_for_output->gain_code_length[n] =
716             pstr_drc_group_for_output->gain_code_length[k];
717         pstr_drc_group_for_output->slope_quant[n] = pstr_drc_group_for_output->slope_quant[k];
718         pstr_drc_group_for_output->slope_code_index[n] =
719             pstr_drc_group_for_output->slope_code_index[k];
720         pstr_drc_group_for_output->drc_gain_quant[n] =
721             pstr_drc_group_for_output->drc_gain_quant[k];
722         n++;
723       }
724     }
725     num_gain_values = n;
726   }
727   pstr_drc_group_for_output->n_gain_values = num_gain_values;
728 
729   k = 0;
730   while (repeat_check) {
731     repeat_check = FALSE;
732 
733     while (k < num_gain_values) {
734       if (slope_changed) {
735         slope_changed = FALSE;
736       } else {
737         k++;
738       }
739       if ((ptr_slope_code_index_buf[k] != cod_slope_zero) ||
740           (ptr_slope_code_index_buf[k + 1] != cod_slope_zero)) {
741         impd_drc_check_overshoot(ptr_time_buf[k + 1] - ptr_time_buf[k], ptr_gain_buf[k],
742                                  ptr_gain_buf[k + 1],
743                                  impd_drc_decode_slope_idx_value(ptr_slope_code_index_buf[k]),
744                                  impd_drc_decode_slope_idx_value(ptr_slope_code_index_buf[k + 1]),
745                                  time_delta_min, &overshoot_left, &overshoot_right);
746 
747         if (overshoot_right || overshoot_left) {
748           if ((k == 0) ||
749               (impd_drc_decode_slope_idx_magnitude(ptr_slope_code_index_buf[k]) <
750                impd_drc_decode_slope_idx_magnitude(ptr_slope_code_index_buf[k + 1]))) {
751             if (ptr_slope_code_index_buf[k + 1] < cod_slope_zero) {
752               ptr_slope_code_index_buf[k + 1] = ptr_slope_code_index_buf[k + 1] + 1;
753               slope_changed = TRUE;
754             } else if (ptr_slope_code_index_buf[k + 1] > cod_slope_zero) {
755               ptr_slope_code_index_buf[k + 1] = ptr_slope_code_index_buf[k + 1] - 1;
756               slope_changed = TRUE;
757             }
758           } else if ((k == num_gain_values) ||
759                      (impd_drc_decode_slope_idx_magnitude(ptr_slope_code_index_buf[k]) >
760                       impd_drc_decode_slope_idx_magnitude(ptr_slope_code_index_buf[k + 1]))) {
761             if (ptr_slope_code_index_buf[k] < cod_slope_zero) {
762               ptr_slope_code_index_buf[k] = ptr_slope_code_index_buf[k] + 1;
763               slope_changed = TRUE;
764               repeat_check = TRUE;
765             } else if (ptr_slope_code_index_buf[k] > cod_slope_zero) {
766               ptr_slope_code_index_buf[k] = ptr_slope_code_index_buf[k] - 1;
767               slope_changed = TRUE;
768               repeat_check = TRUE;
769             }
770           }
771         }
772       }
773     }
774   }
775   for (k = 0; k < num_gain_values; k++) {
776     pstr_drc_group_for_output->slope_code_index[k] = ptr_slope_code_index_buf[k + 1];
777     pstr_drc_group_for_output->slope_quant[k] =
778         impd_drc_decode_slope_idx_value(ptr_slope_code_index_buf[k + 1]);
779   }
780 
781   for (n = 0; n < num_gain_values; n++) {
782     pstr_drc_group_for_output->time_delta_code_index[n] =
783         MAX((pstr_drc_group_for_output->ts_gain_quant[n] - time_prev) / time_delta_min, 1);
784 
785     time_prev += (pstr_drc_group_for_output->time_delta_code_index[n]) * time_delta_min;
786 
787     if (n != 0) {
788       delta_gain = pstr_drc_group_for_output->drc_gain_quant[n] - drc_gain_quant_prev;
789       impd_drc_get_quantized_delta_drc_gain(
790           pstr_drc_gain_seq_buf->str_gain_set_params.gain_coding_profile, delta_gain,
791           &delta_gain_quant, &(pstr_drc_group_for_output->gain_code_length[n]),
792           &(pstr_drc_group_for_output->gain_code[n]));
793       gain_value_quant = delta_gain_quant + drc_gain_quant_prev;
794     } else {
795       err_code = impd_drc_enc_initial_gain(
796           pstr_drc_gain_seq_buf->str_gain_set_params.gain_coding_profile,
797           pstr_drc_group_for_output->drc_gain_quant[n], &gain_value_quant,
798           &(pstr_drc_group_for_output->gain_code_length[n]),
799           &(pstr_drc_group_for_output->gain_code[n]));
800       if (err_code) {
801         return err_code;
802       }
803     }
804     drc_gain_quant_prev = gain_value_quant;
805     pstr_drc_group_for_output->drc_gain_quant[n] = gain_value_quant;
806   }
807 
808   pstr_drc_group_for_output->coding_mode = 1;
809   if (num_gain_values == 1) {
810     if (pstr_drc_gain_seq_buf->str_gain_set_params.gain_interpolation_type !=
811         GAIN_INTERPOLATION_TYPE_SPLINE) {
812       if (pstr_drc_group_for_output->time_delta_code_index[0] >
813           (pstr_gain_enc->drc_frame_size / pstr_gain_enc->delta_tmin)) {
814         pstr_drc_group_for_output->coding_mode = 0;
815       }
816     } else {
817       if (impd_drc_decode_slope_idx_magnitude(ptr_slope_code_index_buf[1]) == 0.0f) {
818         if ((pstr_drc_group_for_output->time_delta_code_index[0] == 0) ||
819             (pstr_drc_group_for_output->time_delta_code_index[0] > 28)) {
820           pstr_drc_group_for_output->coding_mode = 0;
821         }
822         if ((impd_drc_decode_slope_idx_magnitude(ptr_slope_code_index_buf[0]) == 0.0f) &&
823             (impd_drc_decode_slope_idx_magnitude(ptr_slope_code_index_buf[2]) == 0.0f) &&
824             ((FLOAT32)fabs((FLOAT64)(ptr_gain_buf[1] - ptr_gain_buf[0])) < 0.126f) &&
825             ((FLOAT32)fabs((FLOAT64)(ptr_gain_buf[2] - ptr_gain_buf[1])) < 0.126f)) {
826           pstr_drc_group_for_output->coding_mode = 0;
827         }
828       }
829     }
830   }
831 
832   if (pstr_drc_group_for_output->coding_mode == 1) {
833     pstr_slope_code_table = impd_drc_get_slope_code_table_by_value();
834     for (n = 0; n < num_gain_values; n++) {
835       pstr_drc_group_for_output->slope_code_size[n] =
836           pstr_slope_code_table[ptr_slope_code_index_buf[n + 1]].size;
837       pstr_drc_group_for_output->slope_code[n] =
838           pstr_slope_code_table[ptr_slope_code_index_buf[n + 1]].code;
839     }
840 
841     for (n = 0; n < num_gain_values; n++) {
842       pstr_drc_group_for_output->time_delta_code_size[n] =
843           pstr_delta_time_code_table[pstr_drc_group_for_output->time_delta_code_index[n]].size;
844       pstr_drc_group_for_output->time_delta_code[n] =
845           pstr_delta_time_code_table[pstr_drc_group_for_output->time_delta_code_index[n]].code;
846     }
847   }
848   return err_code;
849 }
850 
impd_drc_quantize_drc_frame(const WORD32 drc_frame_size,const WORD32 time_delta_min,const WORD32 num_gain_values_max,const FLOAT32 * ptr_drc_gain_per_sample_with_prev_frame,const WORD32 * ptr_delta_time_quant_table,const WORD32 gain_coding_profile,ia_drc_group_struct * pstr_drc_group,ia_drc_group_for_output_struct * pstr_drc_group_for_output)851 static IA_ERRORCODE impd_drc_quantize_drc_frame(
852     const WORD32 drc_frame_size, const WORD32 time_delta_min, const WORD32 num_gain_values_max,
853     const FLOAT32 *ptr_drc_gain_per_sample_with_prev_frame,
854     const WORD32 *ptr_delta_time_quant_table, const WORD32 gain_coding_profile,
855     ia_drc_group_struct *pstr_drc_group,
856     ia_drc_group_for_output_struct *pstr_drc_group_for_output) {
857   LOOPIDX i, n;
858   WORD32 t, k = 0;
859   WORD32 num_bits = 0, code = 0, tmp;
860   WORD32 t_left, t_right;
861   WORD32 time_delta_left, time_delta_right;
862   WORD32 restart = TRUE;
863   WORD32 num_drc_gain_values = pstr_drc_group->n_gain_values;
864 
865   FLOAT32 slope;
866   FLOAT32 delta_gain;
867   FLOAT32 gain_value_quant = 0;
868   FLOAT32 delta_gain_quant;
869   FLOAT32 max_time_deviation;
870   FLOAT32 drc_gain_per_sample_limited;
871 
872   WORD32 *ptr_time_at_node = pstr_drc_group->ts_gain;
873   WORD32 *ptr_ts_gain_quant = pstr_drc_group->ts_gain_quant;
874   WORD32 *ptr_slope_code_index = pstr_drc_group->slope_code_index;
875   FLOAT32 *drc_gain_quant_prev = &(pstr_drc_group->drc_gain_quant_prev);
876   FLOAT32 *ptr_gain_at_node = pstr_drc_group->drc_gain;
877   FLOAT32 *ptr_slope_at_node = pstr_drc_group->slope;
878   FLOAT32 *ptr_slope_quant = pstr_drc_group->slope_quant;
879   const FLOAT32 *ptr_drc_gain_per_sample =
880       ptr_drc_gain_per_sample_with_prev_frame + drc_frame_size;
881   IA_ERRORCODE err_code = IA_NO_ERROR;
882 
883   while (restart) {
884     n = 0;
885     restart = FALSE;
886     while ((n < num_drc_gain_values) && (restart == FALSE)) {
887       if (n == 0) {
888         time_delta_left = ptr_time_at_node[n];
889         time_delta_right = ptr_time_at_node[n + 1] - ptr_time_at_node[n];
890       } else if (n < num_drc_gain_values - 1) {
891         time_delta_left = ptr_time_at_node[n] - ptr_time_at_node[n - 1];
892         time_delta_right = ptr_time_at_node[n + 1] - ptr_time_at_node[n];
893       } else {
894         time_delta_left = ptr_time_at_node[n] - ptr_time_at_node[n - 1];
895         time_delta_right = drc_frame_size - ptr_time_at_node[n];
896       }
897       max_time_deviation = MAX_TIME_DEVIATION_FACTOR * MIN(time_delta_left, time_delta_right);
898       max_time_deviation = MAX(time_delta_min, max_time_deviation);
899 
900       i = 0;
901       while ((i < num_gain_values_max - 2) && (ptr_delta_time_quant_table[i] < time_delta_left)) {
902         i++;
903       }
904       if (i > 0) {
905         if (ptr_delta_time_quant_table[i] - time_delta_left >
906             time_delta_left - ptr_delta_time_quant_table[i - 1]) {
907           i--;
908         }
909         if (ptr_delta_time_quant_table[i] >= drc_frame_size) {
910           i--;
911         }
912       }
913       if (abs(ptr_delta_time_quant_table[i] - time_delta_left) > max_time_deviation) {
914         if (ptr_delta_time_quant_table[i] > time_delta_left) {
915           i--;
916         }
917         for (k = num_drc_gain_values; k > n; k--) {
918           ptr_time_at_node[k] = ptr_time_at_node[k - 1];
919           ptr_slope_at_node[k] = ptr_slope_at_node[k - 1];
920           ptr_gain_at_node[k] = ptr_gain_at_node[k - 1];
921         }
922         if (n <= 0) {
923           ptr_time_at_node[n] = ptr_delta_time_quant_table[i];
924         } else {
925           ptr_time_at_node[n] = ptr_time_at_node[n - 1] + ptr_delta_time_quant_table[i];
926         }
927 
928         t = ptr_time_at_node[n];
929         ptr_gain_at_node[n] = ptr_drc_gain_per_sample[t];
930         t_left = MAX(0, t - time_delta_min / 2);
931         t_right = MIN(drc_frame_size, t_left + time_delta_min / 2);
932         ptr_slope_at_node[n] = ptr_drc_gain_per_sample[t_right] - ptr_drc_gain_per_sample[t_left];
933         num_drc_gain_values++;
934         restart = TRUE;
935       }
936       n++;
937     }
938   }
939 
940   ptr_ts_gain_quant[0] =
941       (WORD32)(time_delta_min * (ptr_time_at_node[0] + 0.5f) / (FLOAT32)time_delta_min);
942   k = 1;
943   for (n = 1; n < num_drc_gain_values; n++) {
944     tmp = (WORD32)(time_delta_min * (ptr_time_at_node[n] + 0.5f) / (FLOAT32)time_delta_min);
945     if (tmp > ptr_ts_gain_quant[k - 1]) {
946       ptr_ts_gain_quant[k] = tmp;
947       k++;
948     }
949   }
950 
951   num_drc_gain_values = k;
952   pstr_drc_group->n_gain_values = num_drc_gain_values;
953   for (n = 0; n < num_drc_gain_values; n++) {
954     ptr_gain_at_node[n] = ptr_drc_gain_per_sample[ptr_ts_gain_quant[n]];
955     drc_gain_per_sample_limited =
956         impd_drc_limit_drc_gain(gain_coding_profile, ptr_gain_at_node[n]);
957 
958     if (n != 0) {
959       delta_gain = drc_gain_per_sample_limited - *drc_gain_quant_prev;
960       impd_drc_get_quantized_delta_drc_gain(gain_coding_profile, delta_gain, &delta_gain_quant,
961                                             &num_bits, &code);
962       gain_value_quant = delta_gain_quant + *drc_gain_quant_prev;
963     } else {
964       err_code = impd_drc_enc_initial_gain(gain_coding_profile, drc_gain_per_sample_limited,
965                                            &gain_value_quant, &num_bits, &code);
966       if (err_code) {
967         return err_code;
968       }
969     }
970     pstr_drc_group->gain_code[n] = code;
971     pstr_drc_group->gain_code_length[n] = num_bits;
972     pstr_drc_group->drc_gain_quant[n] = gain_value_quant;
973     *drc_gain_quant_prev = gain_value_quant;
974 
975     t_right = MIN(drc_frame_size - 1, ptr_ts_gain_quant[n] + time_delta_min / 2);
976     t_left = t_right - time_delta_min;
977     slope = ptr_drc_gain_per_sample[t_right] - ptr_drc_gain_per_sample[t_left];
978     ptr_slope_at_node[n] = slope;
979     impd_drc_quantize_slope(slope, &(ptr_slope_quant[n]), &(ptr_slope_code_index[n]));
980   }
981 
982   pstr_drc_group->n_gain_values = num_drc_gain_values;
983   pstr_drc_group->gain_prev_node = ptr_gain_at_node[num_drc_gain_values - 1];
984   pstr_drc_group_for_output->time_quant_next = pstr_drc_group->ts_gain_quant[0] + drc_frame_size;
985   pstr_drc_group_for_output->slope_code_index_next = pstr_drc_group->slope_code_index[0];
986   pstr_drc_group_for_output->drc_gain_quant_next = pstr_drc_group->drc_gain_quant[0];
987   pstr_drc_group_for_output->drc_gain_quant_prev = pstr_drc_group->drc_gain_quant_prev;
988 
989   return err_code;
990 }
991 
impd_drc_quantize_and_encode_drc_gain(ia_drc_gain_enc_struct * pstr_gain_enc,const FLOAT32 * ptr_drc_gain_per_sample,FLOAT32 * ptr_drc_gain_per_sample_with_prev_frame,ia_drc_delta_time_code_table_entry_struct * pstr_delta_time_code_table,ia_drc_gain_seq_buf_struct * pstr_drc_gain_seq_buf,VOID * pstr_scratch)992 IA_ERRORCODE impd_drc_quantize_and_encode_drc_gain(
993     ia_drc_gain_enc_struct *pstr_gain_enc, const FLOAT32 *ptr_drc_gain_per_sample,
994     FLOAT32 *ptr_drc_gain_per_sample_with_prev_frame,
995     ia_drc_delta_time_code_table_entry_struct *pstr_delta_time_code_table,
996     ia_drc_gain_seq_buf_struct *pstr_drc_gain_seq_buf, VOID *pstr_scratch) {
997   WORD32 drc_frame_size = pstr_gain_enc->drc_frame_size;
998   const WORD32 *ptr_delta_time_quant_table = pstr_gain_enc->delta_time_quant_table;
999   ia_drc_group_struct *pstr_drc_group;
1000   ia_drc_group_for_output_struct *pstr_drc_group_for_output;
1001   IA_ERRORCODE err_code = IA_NO_ERROR;
1002   impd_drc_advance_nodes(pstr_gain_enc, pstr_drc_gain_seq_buf);
1003 
1004   pstr_drc_group = &(pstr_drc_gain_seq_buf->str_drc_group);
1005   pstr_drc_group_for_output = &(pstr_drc_gain_seq_buf->str_drc_group_for_output);
1006 
1007   impd_drc_get_preliminary_nodes(
1008       pstr_gain_enc, ptr_drc_gain_per_sample, ptr_drc_gain_per_sample_with_prev_frame,
1009       pstr_drc_group, pstr_drc_gain_seq_buf->str_gain_set_params.full_frame, pstr_scratch);
1010 
1011   err_code = impd_drc_quantize_drc_frame(
1012       drc_frame_size, pstr_gain_enc->delta_tmin,
1013       pstr_gain_enc->drc_frame_size / pstr_gain_enc->delta_tmin,
1014       ptr_drc_gain_per_sample_with_prev_frame, ptr_delta_time_quant_table,
1015       pstr_drc_gain_seq_buf->str_gain_set_params.gain_coding_profile, pstr_drc_group,
1016       pstr_drc_group_for_output);
1017 
1018   if (err_code) {
1019     return err_code;
1020   }
1021 
1022   err_code = impd_drc_post_process_nodes(pstr_gain_enc, pstr_delta_time_code_table,
1023                                          pstr_drc_gain_seq_buf, pstr_scratch);
1024   return err_code;
1025 }
1026