278 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			278 lines
		
	
	
		
			8.3 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 <string.h>
 | |
| #include "ixheaacd_sbr_common.h"
 | |
| #include "ixheaacd_type_def.h"
 | |
| 
 | |
| #include "ixheaacd_constants.h"
 | |
| #include "ixheaacd_basic_ops32.h"
 | |
| #include "ixheaacd_basic_ops16.h"
 | |
| #include "ixheaacd_basic_ops40.h"
 | |
| #include "ixheaacd_basic_ops.h"
 | |
| 
 | |
| #include "ixheaacd_basic_op.h"
 | |
| #include "ixheaacd_intrinsics.h"
 | |
| #include "ixheaacd_bitbuffer.h"
 | |
| #include "ixheaacd_sbrdecsettings.h"
 | |
| #include "ixheaacd_sbr_scale.h"
 | |
| #include "ixheaacd_lpp_tran.h"
 | |
| #include "ixheaacd_env_extr_part.h"
 | |
| #include "ixheaacd_sbr_rom.h"
 | |
| 
 | |
| #include "ixheaacd_hybrid.h"
 | |
| #include "ixheaacd_ps_dec.h"
 | |
| 
 | |
| #include "ixheaacd_env_extr.h"
 | |
| #include "ixheaacd_ps_bitdec.h"
 | |
| 
 | |
| const WORD16 ixheaacd_num_bands[3] = {10, 20, 34};
 | |
| 
 | |
| static WORD32 ixheaacd_clamp(WORD32 i, WORD16 min, WORD16 max) {
 | |
|   WORD32 result = i;
 | |
| 
 | |
|   if (i < min) {
 | |
|     result = min;
 | |
|   } else {
 | |
|     if (i > max) {
 | |
|       result = max;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| WORD16 ixheaacd_divideby2(WORD op) {
 | |
|   FLAG sign = (op < 0);
 | |
| 
 | |
|   if (sign) {
 | |
|     op = -(op);
 | |
|   }
 | |
| 
 | |
|   op = (op >> 1);
 | |
| 
 | |
|   if (sign) {
 | |
|     op = -op;
 | |
|   }
 | |
| 
 | |
|   return (WORD16)op;
 | |
| }
 | |
| 
 | |
| WORD16 ixheaacd_divideby3(WORD op) {
 | |
|   WORD16 temp, ret;
 | |
|   FLAG sign = (op < 0);
 | |
| 
 | |
|   if (sign) {
 | |
|     op = -(op);
 | |
|   }
 | |
| 
 | |
|   temp = (WORD16)(op << 2);
 | |
| 
 | |
|   temp = ixheaacd_mult16_shl(temp, 0x2aab);
 | |
| 
 | |
|   ret = (temp >> 2);
 | |
| 
 | |
|   if (sign) {
 | |
|     ret = -(ret);
 | |
|   }
 | |
| 
 | |
|   return (WORD16)ret;
 | |
| }
 | |
| 
 | |
| VOID ixheaacd_decode_ps_data(ia_ps_dec_struct *ptr_ps_dec) {
 | |
|   WORD e, i, temp;
 | |
|   WORD16 iid_mode = (WORD16)((ptr_ps_dec->iid_mode) ? 1 : 2);
 | |
|   WORD16 icc_mode = (WORD16)((ptr_ps_dec->icc_mode) ? 1 : 2);
 | |
|   WORD16 num_iid_levels =
 | |
|       (WORD16)(ptr_ps_dec->iid_quant ? NUM_IID_LEVELS_FINE : NUM_IID_LEVELS);
 | |
| 
 | |
|   if (!ptr_ps_dec->ps_data_present) {
 | |
|     ptr_ps_dec->num_env = 0;
 | |
|   }
 | |
| 
 | |
|   for (e = 0; e < ptr_ps_dec->num_env; e++) {
 | |
|     WORD16 *p_iid_par_prev;
 | |
|     WORD16 *p_icc_par_prev;
 | |
| 
 | |
|     if (e == 0) {
 | |
|       p_iid_par_prev = ptr_ps_dec->iid_par_prev;
 | |
|       p_icc_par_prev = ptr_ps_dec->icc_par_prev;
 | |
|     } else {
 | |
|       p_iid_par_prev = ptr_ps_dec->iid_par_table[e - 1];
 | |
|       p_icc_par_prev = ptr_ps_dec->icc_par_table[e - 1];
 | |
|     }
 | |
| 
 | |
|     if (ptr_ps_dec->enable_iid) {
 | |
|       if (ptr_ps_dec->iid_dt[e]) {
 | |
|         for (i = 0; i < ixheaacd_num_bands[ptr_ps_dec->iid_mode]; i++) {
 | |
|           temp =
 | |
|               ixheaacd_add16(*p_iid_par_prev, ptr_ps_dec->iid_par_table[e][i]);
 | |
|           ptr_ps_dec->iid_par_table[e][i] = ixheaacd_clamp(
 | |
|               temp, ixheaacd_negate16(num_iid_levels), num_iid_levels);
 | |
|           p_iid_par_prev += iid_mode;
 | |
|         }
 | |
|       } else {
 | |
|         ptr_ps_dec->iid_par_table[e][0] =
 | |
|             ixheaacd_clamp(ptr_ps_dec->iid_par_table[e][0],
 | |
|                            ixheaacd_negate16(num_iid_levels), num_iid_levels);
 | |
|         for (i = 1; i < ixheaacd_num_bands[ptr_ps_dec->iid_mode]; i++) {
 | |
|           temp = ixheaacd_add16(ptr_ps_dec->iid_par_table[e][i - 1],
 | |
|                                 ptr_ps_dec->iid_par_table[e][i]);
 | |
|           ptr_ps_dec->iid_par_table[e][i] = ixheaacd_clamp(
 | |
|               temp, ixheaacd_negate16(num_iid_levels), num_iid_levels);
 | |
|         }
 | |
|       }
 | |
|     } else {
 | |
|       memset(ptr_ps_dec->iid_par_table[e], 0,
 | |
|              sizeof(WORD16) * ixheaacd_num_bands[ptr_ps_dec->iid_mode]);
 | |
|     }
 | |
| 
 | |
|     if (iid_mode == 2) {
 | |
|       for (i = (ixheaacd_num_bands[ptr_ps_dec->iid_mode] * iid_mode - 1);
 | |
|            i != 0; i--) {
 | |
|         ptr_ps_dec->iid_par_table[e][i] =
 | |
|             ptr_ps_dec->iid_par_table[e][ixheaacd_shr32(i, 1)];
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (ptr_ps_dec->enable_icc) {
 | |
|       if (ptr_ps_dec->icc_dt[e]) {
 | |
|         for (i = 0; i < ixheaacd_num_bands[ptr_ps_dec->icc_mode]; i++) {
 | |
|           temp =
 | |
|               ixheaacd_add16(*p_icc_par_prev, ptr_ps_dec->icc_par_table[e][i]);
 | |
|           ptr_ps_dec->icc_par_table[e][i] =
 | |
|               ixheaacd_clamp(temp, 0, (WORD16)(NUM_ICC_LEVELS - 1));
 | |
|           p_icc_par_prev += icc_mode;
 | |
|         }
 | |
|       } else {
 | |
|         ptr_ps_dec->icc_par_table[e][0] = ixheaacd_clamp(
 | |
|             ptr_ps_dec->icc_par_table[e][0], 0, (WORD16)(NUM_ICC_LEVELS - 1));
 | |
|         for (i = 1; i < ixheaacd_num_bands[ptr_ps_dec->icc_mode]; i++) {
 | |
|           temp = ixheaacd_add16(ptr_ps_dec->icc_par_table[e][i - 1],
 | |
|                                 ptr_ps_dec->icc_par_table[e][i]);
 | |
|           ptr_ps_dec->icc_par_table[e][i] =
 | |
|               ixheaacd_clamp(temp, 0, (WORD16)(NUM_ICC_LEVELS - 1));
 | |
|         }
 | |
|       }
 | |
|     } else {
 | |
|       memset(ptr_ps_dec->icc_par_table[e], 0,
 | |
|              sizeof(WORD16) * ixheaacd_num_bands[ptr_ps_dec->icc_mode]);
 | |
|     }
 | |
| 
 | |
|     if (icc_mode == 2) {
 | |
|       for (i = (ixheaacd_num_bands[ptr_ps_dec->icc_mode] * icc_mode - 1);
 | |
|            i != 0; i--) {
 | |
|         ptr_ps_dec->icc_par_table[e][i] =
 | |
|             ptr_ps_dec->icc_par_table[e][ixheaacd_shr32(i, 1)];
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (ptr_ps_dec->num_env == 0) {
 | |
|     ptr_ps_dec->num_env = 1;
 | |
| 
 | |
|     if (ptr_ps_dec->enable_iid) {
 | |
|       memcpy(ptr_ps_dec->iid_par_table[0], ptr_ps_dec->iid_par_prev,
 | |
|              sizeof(WORD16) * NUM_BANDS_FINE);
 | |
|     } else {
 | |
|       memset(ptr_ps_dec->iid_par_table[0], 0, sizeof(WORD16) * NUM_BANDS_FINE);
 | |
|     }
 | |
| 
 | |
|     if (ptr_ps_dec->enable_icc) {
 | |
|       memcpy(ptr_ps_dec->icc_par_table[0], ptr_ps_dec->icc_par_prev,
 | |
|              sizeof(WORD16) * NUM_BANDS_FINE);
 | |
|     } else {
 | |
|       memset(ptr_ps_dec->icc_par_table[0], 0, sizeof(WORD16) * NUM_BANDS_FINE);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   memcpy(ptr_ps_dec->iid_par_prev,
 | |
|          ptr_ps_dec->iid_par_table[ptr_ps_dec->num_env - 1],
 | |
|          sizeof(WORD16) * NUM_BANDS_FINE);
 | |
| 
 | |
|   memcpy(ptr_ps_dec->icc_par_prev,
 | |
|          ptr_ps_dec->icc_par_table[ptr_ps_dec->num_env - 1],
 | |
|          sizeof(WORD16) * NUM_BANDS_FINE);
 | |
| 
 | |
|   ptr_ps_dec->ps_data_present = 0;
 | |
| 
 | |
|   if (ptr_ps_dec->frame_class == 0) {
 | |
|     WORD env_count;
 | |
|     WORD16 shift = 0;
 | |
| 
 | |
|     switch (ptr_ps_dec->num_env) {
 | |
|       case 1:
 | |
|         shift = 0;
 | |
|         break;
 | |
|       case 2:
 | |
|         shift = 1;
 | |
|         break;
 | |
|       case 4:
 | |
|         shift = 2;
 | |
|         break;
 | |
|     }
 | |
|     ptr_ps_dec->border_position[0] = 0;
 | |
|     env_count = 0;
 | |
| 
 | |
|     for (e = 1; e < ptr_ps_dec->num_env; e++) {
 | |
|       env_count = add_d(env_count, MAX_NUM_COLUMNS);
 | |
|       ptr_ps_dec->border_position[e] = (WORD16)(env_count >> shift);
 | |
|     }
 | |
|     ptr_ps_dec->border_position[ptr_ps_dec->num_env] = MAX_NUM_COLUMNS;
 | |
|   } else {
 | |
|     ptr_ps_dec->border_position[0] = 0;
 | |
| 
 | |
|     if (ptr_ps_dec->border_position[ptr_ps_dec->num_env] < MAX_NUM_COLUMNS) {
 | |
|       ptr_ps_dec->num_env++;
 | |
|       add_d(ptr_ps_dec->num_env, 1);
 | |
|       ptr_ps_dec->border_position[ptr_ps_dec->num_env] = MAX_NUM_COLUMNS;
 | |
| 
 | |
|       memcpy(ptr_ps_dec->iid_par_table[ptr_ps_dec->num_env - 1],
 | |
|              ptr_ps_dec->iid_par_table[ptr_ps_dec->num_env - 2],
 | |
|              sizeof(WORD16) * NUM_BANDS_FINE);
 | |
| 
 | |
|       memcpy(ptr_ps_dec->icc_par_table[ptr_ps_dec->num_env - 1],
 | |
|              ptr_ps_dec->icc_par_table[ptr_ps_dec->num_env - 2],
 | |
|              sizeof(WORD16) * NUM_BANDS_FINE);
 | |
|     }
 | |
| 
 | |
|     for (e = 1; e < ptr_ps_dec->num_env; e++) {
 | |
|       WORD threshold;
 | |
|       threshold = sub_d(MAX_NUM_COLUMNS, sub_d(ptr_ps_dec->num_env, e));
 | |
| 
 | |
|       if (ptr_ps_dec->border_position[e] > threshold) {
 | |
|         ptr_ps_dec->border_position[e] = threshold;
 | |
|       } else {
 | |
|         threshold = add_d(ptr_ps_dec->border_position[e - 1], 1);
 | |
| 
 | |
|         if (ptr_ps_dec->border_position[e] < threshold) {
 | |
|           ptr_ps_dec->border_position[e] = threshold;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   for (e = 0; e < ptr_ps_dec->num_env; e++) {
 | |
|     if (ptr_ps_dec->iid_mode == 2)
 | |
|       ixheaacd_map_34_params_to_20(ptr_ps_dec->iid_par_table[e]);
 | |
| 
 | |
|     if (ptr_ps_dec->icc_mode == 2)
 | |
|       ixheaacd_map_34_params_to_20(ptr_ps_dec->icc_par_table[e]);
 | |
|   }
 | |
| } |