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 32 IA_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 41 IA_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 64 IA_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 130 IA_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