1/******************************************************************************
2 *
3 * Copyright (C) 2018 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#include <stdio.h>
21#include <stdlib.h>
22#include <math.h>
23#include "impd_type_def.h"
24#include "impd_error_standards.h"
25#include "impd_drc_extr_delta_coded_info.h"
26#include "impd_drc_common.h"
27#include "impd_drc_struct.h"
28#include "impd_drc_filter_bank.h"
29#include "impd_drc_multi_band.h"
30#include "impd_drc_rom.h"
31
32IA_ERRORCODE impd_fcenter_norm_sb_init(WORD32 num_subbands,
33                                       FLOAT32* fcenter_norm_subband) {
34  WORD32 s;
35  for (s = 0; s < num_subbands; s++) {
36    fcenter_norm_subband[s] = (s + 0.5f) / (2.0f * num_subbands);
37  }
38  return (0);
39}
40
41IA_ERRORCODE impd_generate_slope(WORD32 num_sub_bands,
42                                 FLOAT32* fcenter_norm_subband,
43                                 FLOAT32 fcross_norm_lo, FLOAT32 fcross_norm_hi,
44                                 FLOAT32* response) {
45  WORD32 i;
46  FLOAT32 filter_slope = -24.0f;
47  FLOAT32 inv_log10_2 = 3.32192809f;
48  FLOAT32 norm = 0.05f * filter_slope * inv_log10_2;
49
50  for (i = 0; i < num_sub_bands; i++) {
51    if (fcenter_norm_subband[i] < fcross_norm_lo) {
52      response[i] = (FLOAT32)pow(
53          10.0, norm * log10(fcross_norm_lo / fcenter_norm_subband[i]));
54    } else if (fcenter_norm_subband[i] < fcross_norm_hi) {
55      response[i] = 1.0f;
56    } else {
57      response[i] = (FLOAT32)pow(
58          10.0, norm * log10(fcenter_norm_subband[i] / fcross_norm_hi));
59    }
60  }
61  return (0);
62}
63
64IA_ERRORCODE impd_generate_overlap_weights(
65    WORD32 num_drc_bands, WORD32 drc_band_type,
66    ia_gain_params_struct* gain_params, WORD32 dec_subband_count,
67    ia_group_overlap_params_struct* pstr_group_overlap_params) {
68  FLOAT32 fcenter_norm_subband[AUDIO_CODEC_SUBBAND_COUNT_MAX];
69  FLOAT32 w_norm[AUDIO_CODEC_SUBBAND_COUNT_MAX];
70  FLOAT32 fcross_norm_lo, fcross_norm_hi;
71  WORD32 err, b, s, start_subband_index = 0, stop_sub_band_index = 0;
72  err = impd_fcenter_norm_sb_init(dec_subband_count, fcenter_norm_subband);
73
74  if (drc_band_type == 1) {
75    fcross_norm_lo = 0.0f;
76    for (b = 0; b < num_drc_bands; b++) {
77      if (b < num_drc_bands - 1) {
78        fcross_norm_hi =
79            normal_cross_freq[gain_params[b + 1].crossover_freq_idx]
80                .f_cross_norm;
81      } else {
82        fcross_norm_hi = 0.5f;
83      }
84      impd_generate_slope(
85          dec_subband_count, fcenter_norm_subband, fcross_norm_lo,
86          fcross_norm_hi,
87          pstr_group_overlap_params->str_band_overlap_params[b].overlap_weight);
88
89      fcross_norm_lo = fcross_norm_hi;
90    }
91    for (s = 0; s < dec_subband_count; s++) {
92      w_norm[s] = pstr_group_overlap_params->str_band_overlap_params[0]
93                      .overlap_weight[s];
94      for (b = 1; b < num_drc_bands; b++) {
95        w_norm[s] += pstr_group_overlap_params->str_band_overlap_params[b]
96                         .overlap_weight[s];
97      }
98    }
99
100    for (s = 0; s < dec_subband_count; s++) {
101      for (b = 0; b < num_drc_bands; b++) {
102        pstr_group_overlap_params->str_band_overlap_params[b]
103            .overlap_weight[s] /= w_norm[s];
104      }
105    }
106  } else {
107    start_subband_index = 0;
108    for (b = 0; b < num_drc_bands; b++) {
109      if (b < num_drc_bands - 1) {
110        stop_sub_band_index = gain_params[b + 1].start_subband_index - 1;
111      } else {
112        stop_sub_band_index = dec_subband_count - 1;
113      }
114      for (s = 0; s < dec_subband_count; s++) {
115        if (s >= start_subband_index && s <= stop_sub_band_index) {
116          pstr_group_overlap_params->str_band_overlap_params[b]
117              .overlap_weight[s] = 1.0;
118        } else {
119          pstr_group_overlap_params->str_band_overlap_params[b]
120              .overlap_weight[s] = 0.0;
121        }
122      }
123      start_subband_index = stop_sub_band_index + 1;
124    }
125  }
126
127  return (0);
128}
129
130IA_ERRORCODE impd_init_overlap_weight(
131    ia_uni_drc_coeffs_struct* str_p_loc_drc_coefficients_uni_drc,
132    ia_drc_instructions_struct* str_drc_instruction_str,
133    WORD32 sub_band_domain_mode,
134    ia_overlap_params_struct* pstr_overlap_params) {
135  WORD32 err = 0, g;
136  WORD32 dec_subband_count = 0;
137  switch (sub_band_domain_mode) {
138    case SUBBAND_DOMAIN_MODE_QMF64:
139      dec_subband_count = AUDIO_CODEC_SUBBAND_COUNT_QMF64;
140      break;
141    case SUBBAND_DOMAIN_MODE_QMF71:
142      dec_subband_count = AUDIO_CODEC_SUBBAND_COUNT_QMF71;
143      break;
144    case SUBBAND_DOMAIN_MODE_STFT256:
145      dec_subband_count = AUDIO_CODEC_SUBBAND_COUNT_STFT256;
146      break;
147  }
148
149  for (g = 0; g < str_drc_instruction_str->num_drc_ch_groups; g++) {
150    if (str_drc_instruction_str->band_count_of_ch_group[g] > 1) {
151      err = impd_generate_overlap_weights(
152          str_drc_instruction_str->band_count_of_ch_group[g],
153          str_p_loc_drc_coefficients_uni_drc
154              ->gain_set_params[str_drc_instruction_str
155                                    ->gain_set_index_for_channel_group[g]]
156              .drc_band_type,
157          str_p_loc_drc_coefficients_uni_drc
158              ->gain_set_params[str_drc_instruction_str
159                                    ->gain_set_index_for_channel_group[g]]
160              .gain_params,
161          dec_subband_count,
162          &(pstr_overlap_params->str_group_overlap_params[g]));
163      if (err) return (err);
164    }
165  }
166
167  return (0);
168}
169