194 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			194 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C
		
	
	
	
| /******************************************************************************
 | |
|  *                                                                            *
 | |
|  * Copyright (C) 2018 The Android Open Source Project
 | |
|  *
 | |
|  * Licensed under the Apache License, Version 2.0 (the "License");
 | |
|  * you may not use this file except in compliance with the License.
 | |
|  * You may obtain a copy of the License at:
 | |
|  *
 | |
|  * http://www.apache.org/licenses/LICENSE-2.0
 | |
|  *
 | |
|  * Unless required by applicable law or agreed to in writing, software
 | |
|  * distributed under the License is distributed on an "AS IS" BASIS,
 | |
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
|  * See the License for the specific language governing permissions and
 | |
|  * limitations under the License.
 | |
|  *
 | |
|  *****************************************************************************
 | |
|  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
 | |
| */
 | |
| #include <math.h>
 | |
| #include "ixheaacd_type_def.h"
 | |
| #include "ixheaacd_bitbuffer.h"
 | |
| #include "ixheaacd_config.h"
 | |
| 
 | |
| #include "ixheaacd_mps_polyphase.h"
 | |
| 
 | |
| #include "ixheaacd_mps_dec.h"
 | |
| #include "ixheaacd_mps_interface.h"
 | |
| 
 | |
| #define max(a, b) ((a) > (b) ? (a) : (b))
 | |
| 
 | |
| #define min(a, b) ((a) < (b) ? (a) : (b))
 | |
| 
 | |
| #define DIR_DIFF_IN 0
 | |
| #define DOWNMIX_IN 1
 | |
| 
 | |
| #define LAMDA (4.0f)
 | |
| #define GES_ALPHA (0.99637864f)
 | |
| #define GES_BETA (0.9643691f)
 | |
| 
 | |
| extern const WORD32
 | |
|     ixheaacd_hybrid_band_71_to_processing_band_20_map[MAX_HYBRID_BANDS_MPS];
 | |
| 
 | |
| VOID ixheaacd_mps_env_init(ia_mps_dec_state_struct *self) {
 | |
|   WORD32 i;
 | |
|   for (i = 0; i < 3; i++) {
 | |
|     self->guided_env_shaping.avg_energy_prev[i] = 32768.f * 32768.f;
 | |
|   }
 | |
| }
 | |
| 
 | |
| static VOID ixheaacd_mps_est_normalized_envelope(ia_mps_dec_state_struct *self,
 | |
|                                                  WORD32 inp, WORD32 ch,
 | |
|                                                  FLOAT32 *env) {
 | |
|   FLOAT32 slot_energy[MAX_TIME_SLOTS][MAX_PARAMETER_BANDS] = {{0}};
 | |
|   FLOAT32 pb_energy[MAX_PARAMETER_BANDS] = {0};
 | |
|   FLOAT32 whitening_weight[MAX_PARAMETER_BANDS];
 | |
|   WORD32 ii, jj, param_band;
 | |
| 
 | |
|   WORD32 k_start = 10;
 | |
|   WORD32 k_stop = 18;
 | |
| 
 | |
|   FLOAT32 total_energy = 0, avg_energy = 0;
 | |
| 
 | |
|   WORD32 ch_offset;
 | |
| 
 | |
|   switch (inp) {
 | |
|     case DIR_DIFF_IN:
 | |
|       ch_offset = 0;
 | |
|       for (ii = 0; ii < self->time_slots; ii++) {
 | |
|         for (jj = 0; jj < self->hyb_band_count; jj++) {
 | |
|           slot_energy[ii]
 | |
|                      [ixheaacd_hybrid_band_71_to_processing_band_20_map[jj]] +=
 | |
|               ((self->hyb_dir_out[ch][ii][jj].re +
 | |
|                 self->hyb_diff_out[ch][ii][jj].re) *
 | |
|                (self->hyb_dir_out[ch][ii][jj].re +
 | |
|                 self->hyb_diff_out[ch][ii][jj].re)) +
 | |
|               ((self->hyb_dir_out[ch][ii][jj].im +
 | |
|                 self->hyb_diff_out[ch][ii][jj].im) *
 | |
|                (self->hyb_dir_out[ch][ii][jj].im +
 | |
|                 self->hyb_diff_out[ch][ii][jj].im));
 | |
|         }
 | |
|       }
 | |
|       break;
 | |
|     case DOWNMIX_IN:
 | |
|       ch_offset = self->out_ch_count;
 | |
|       for (ii = 0; ii < self->time_slots; ii++) {
 | |
|         for (jj = 0; jj < self->hyb_band_count; jj++) {
 | |
|           slot_energy[ii]
 | |
|                      [ixheaacd_hybrid_band_71_to_processing_band_20_map[jj]] +=
 | |
|               self->hyb_in[ch][ii][jj].re * self->hyb_in[ch][ii][jj].re +
 | |
|               self->hyb_in[ch][ii][jj].im * self->hyb_in[ch][ii][jj].im;
 | |
|         }
 | |
|       }
 | |
|       break;
 | |
|     default:
 | |
|       ch_offset = 0;
 | |
|       break;
 | |
|   }
 | |
| 
 | |
|   for (param_band = k_start; param_band <= k_stop; param_band++)
 | |
|     pb_energy[param_band] =
 | |
|         self->guided_env_shaping.pb_energy_prev[ch + ch_offset][param_band];
 | |
| 
 | |
|   avg_energy = self->guided_env_shaping.avg_energy_prev[ch + ch_offset];
 | |
| 
 | |
|   for (ii = 0; ii < self->time_slots; ii++) {
 | |
|     total_energy = 0;
 | |
|     for (param_band = k_start; param_band <= k_stop; param_band++) {
 | |
|       pb_energy[param_band] = (1 - GES_ALPHA) * slot_energy[ii][param_band] +
 | |
|                               GES_ALPHA * pb_energy[param_band];
 | |
| 
 | |
|       total_energy += slot_energy[ii][param_band];
 | |
|     }
 | |
|     total_energy /= (k_stop - k_start + 1);
 | |
| 
 | |
|     total_energy =
 | |
|         (1 - GES_ALPHA) * total_energy +
 | |
|         GES_ALPHA * self->guided_env_shaping.frame_energy_prev[ch + ch_offset];
 | |
| 
 | |
|     self->guided_env_shaping.frame_energy_prev[ch + ch_offset] = total_energy;
 | |
| 
 | |
|     for (param_band = k_start; param_band <= k_stop; param_band++) {
 | |
|       whitening_weight[param_band] =
 | |
|           total_energy / (pb_energy[param_band] + ABS_THR);
 | |
|     }
 | |
| 
 | |
|     env[ii] = 0;
 | |
|     for (param_band = k_start; param_band <= k_stop; param_band++) {
 | |
|       env[ii] += slot_energy[ii][param_band] * whitening_weight[param_band];
 | |
|     }
 | |
| 
 | |
|     avg_energy = (1 - GES_BETA) * env[ii] + GES_BETA * avg_energy;
 | |
| 
 | |
|     env[ii] = (FLOAT32)sqrt(env[ii] / (avg_energy + ABS_THR));
 | |
|   }
 | |
| 
 | |
|   for (param_band = k_start; param_band <= k_stop; param_band++)
 | |
|     self->guided_env_shaping.pb_energy_prev[ch + ch_offset][param_band] =
 | |
|         pb_energy[param_band];
 | |
| 
 | |
|   self->guided_env_shaping.avg_energy_prev[ch + ch_offset] = avg_energy;
 | |
| }
 | |
| 
 | |
| VOID ixheaacd_mps_time_env_shaping(ia_mps_dec_state_struct *self) {
 | |
|   FLOAT32 dir_energy[MAX_TIME_SLOTS];
 | |
|   FLOAT32 dmx_energy[MAX_TIME_SLOTS];
 | |
|   WORD32 ch, time_slot, jj;
 | |
| 
 | |
|   WORD32 band_start;
 | |
|   FLOAT32 gain, ratio;
 | |
| 
 | |
|   FLOAT32 amp_direct = 0;
 | |
|   FLOAT32 amp_diff = 0;
 | |
|   FLOAT32 amp_ratio;
 | |
| 
 | |
|   band_start = 6;
 | |
| 
 | |
|   ixheaacd_mps_est_normalized_envelope(self, DOWNMIX_IN, 0, dmx_energy);
 | |
| 
 | |
|   for (ch = 0; ch < self->out_ch_count; ch++) {
 | |
|     ixheaacd_mps_est_normalized_envelope(self, DIR_DIFF_IN, ch, dir_energy);
 | |
| 
 | |
|     if (self->temp_shape_enable_ch_ges[ch]) {
 | |
|       for (time_slot = 0; time_slot < self->time_slots; time_slot++) {
 | |
|         gain = self->env_shape_data[ch][time_slot] * dmx_energy[time_slot] /
 | |
|                (dir_energy[time_slot] + 1e-9f);
 | |
| 
 | |
|         amp_direct = 0;
 | |
|         amp_diff = 0;
 | |
| 
 | |
|         for (jj = band_start; jj < self->hyb_band_count; jj++) {
 | |
|           amp_direct += self->hyb_dir_out[ch][time_slot][jj].re *
 | |
|                             self->hyb_dir_out[ch][time_slot][jj].re +
 | |
|                         self->hyb_dir_out[ch][time_slot][jj].im *
 | |
|                             self->hyb_dir_out[ch][time_slot][jj].im;
 | |
| 
 | |
|           amp_diff += self->hyb_diff_out[ch][time_slot][jj].re *
 | |
|                           self->hyb_diff_out[ch][time_slot][jj].re +
 | |
|                       self->hyb_diff_out[ch][time_slot][jj].im *
 | |
|                           self->hyb_diff_out[ch][time_slot][jj].im;
 | |
|         }
 | |
| 
 | |
|         amp_ratio = (FLOAT32)sqrt(amp_diff / (amp_direct + ABS_THR));
 | |
| 
 | |
|         ratio = min(max((gain + amp_ratio * (gain - 1)), 1 / LAMDA), LAMDA);
 | |
| 
 | |
|         for (jj = band_start; jj < self->hyb_band_count; jj++) {
 | |
|           self->hyb_dir_out[ch][time_slot][jj].re *= ratio;
 | |
|           self->hyb_dir_out[ch][time_slot][jj].im *= ratio;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| } |