| /* ----------------------------------------------------------------------------- |
| Software License for The Fraunhofer FDK AAC Codec Library for Android |
| |
| © Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten |
| Forschung e.V. All rights reserved. |
| |
| 1. INTRODUCTION |
| The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software |
| that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding |
| scheme for digital audio. This FDK AAC Codec software is intended to be used on |
| a wide variety of Android devices. |
| |
| AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient |
| general perceptual audio codecs. AAC-ELD is considered the best-performing |
| full-bandwidth communications codec by independent studies and is widely |
| deployed. AAC has been standardized by ISO and IEC as part of the MPEG |
| specifications. |
| |
| Patent licenses for necessary patent claims for the FDK AAC Codec (including |
| those of Fraunhofer) may be obtained through Via Licensing |
| (www.vialicensing.com) or through the respective patent owners individually for |
| the purpose of encoding or decoding bit streams in products that are compliant |
| with the ISO/IEC MPEG audio standards. Please note that most manufacturers of |
| Android devices already license these patent claims through Via Licensing or |
| directly from the patent owners, and therefore FDK AAC Codec software may |
| already be covered under those patent licenses when it is used for those |
| licensed purposes only. |
| |
| Commercially-licensed AAC software libraries, including floating-point versions |
| with enhanced sound quality, are also available from Fraunhofer. Users are |
| encouraged to check the Fraunhofer website for additional applications |
| information and documentation. |
| |
| 2. COPYRIGHT LICENSE |
| |
| Redistribution and use in source and binary forms, with or without modification, |
| are permitted without payment of copyright license fees provided that you |
| satisfy the following conditions: |
| |
| You must retain the complete text of this software license in redistributions of |
| the FDK AAC Codec or your modifications thereto in source code form. |
| |
| You must retain the complete text of this software license in the documentation |
| and/or other materials provided with redistributions of the FDK AAC Codec or |
| your modifications thereto in binary form. You must make available free of |
| charge copies of the complete source code of the FDK AAC Codec and your |
| modifications thereto to recipients of copies in binary form. |
| |
| The name of Fraunhofer may not be used to endorse or promote products derived |
| from this library without prior written permission. |
| |
| You may not charge copyright license fees for anyone to use, copy or distribute |
| the FDK AAC Codec software or your modifications thereto. |
| |
| Your modified versions of the FDK AAC Codec must carry prominent notices stating |
| that you changed the software and the date of any change. For modified versions |
| of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" |
| must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK |
| AAC Codec Library for Android." |
| |
| 3. NO PATENT LICENSE |
| |
| NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without |
| limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. |
| Fraunhofer provides no warranty of patent non-infringement with respect to this |
| software. |
| |
| You may use this FDK AAC Codec software or modifications thereto only for |
| purposes that are authorized by appropriate patent licenses. |
| |
| 4. DISCLAIMER |
| |
| This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright |
| holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, |
| including but not limited to the implied warranties of merchantability and |
| fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR |
| CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, |
| or consequential damages, including but not limited to procurement of substitute |
| goods or services; loss of use, data, or profits, or business interruption, |
| however caused and on any theory of liability, whether in contract, strict |
| liability, or tort (including negligence), arising in any way out of the use of |
| this software, even if advised of the possibility of such damage. |
| |
| 5. CONTACT INFORMATION |
| |
| Fraunhofer Institute for Integrated Circuits IIS |
| Attention: Audio and Multimedia Departments - FDK AAC LL |
| Am Wolfsmantel 33 |
| 91058 Erlangen, Germany |
| |
| www.iis.fraunhofer.de/amm |
| amm-info@iis.fraunhofer.de |
| ----------------------------------------------------------------------------- */ |
| |
| /*********************** MPEG surround encoder library ************************* |
| |
| Author(s): Karsten Linzmeier |
| |
| Description: Noiseless Coding |
| Huffman encoder |
| |
| *******************************************************************************/ |
| |
| /* Includes ******************************************************************/ |
| #include "sacenc_nlc_enc.h" |
| |
| #include "genericStds.h" |
| #include "fixpoint_math.h" |
| |
| #include "sacenc_const.h" |
| #include "sacenc_huff_tab.h" |
| #include "sacenc_paramextract.h" |
| |
| /* Defines *******************************************************************/ |
| #define PAIR_SHIFT 4 |
| #define PAIR_MASK 0xf |
| |
| #define PBC_MIN_BANDS 5 |
| |
| typedef enum { |
| BACKWARDS = 0x0, |
| FORWARDS = 0x1 |
| |
| } DIRECTION; |
| |
| typedef enum { |
| DIFF_FREQ = 0x0, |
| DIFF_TIME = 0x1 |
| |
| } DIFF_TYPE; |
| |
| typedef enum { |
| HUFF_1D = 0x0, |
| HUFF_2D = 0x1 |
| |
| } CODING_SCHEME; |
| |
| typedef enum { |
| FREQ_PAIR = 0x0, |
| TIME_PAIR = 0x1 |
| |
| } PAIRING; |
| |
| /* Data Types ****************************************************************/ |
| |
| /* Constants *****************************************************************/ |
| static const UCHAR lavHuffVal[4] = {0, 2, 6, 7}; |
| static const UCHAR lavHuffLen[4] = {1, 2, 3, 3}; |
| |
| static const UCHAR lav_step_CLD[] = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3}; |
| static const UCHAR lav_step_ICC[] = {0, 0, 1, 1, 2, 2, 3, 3}; |
| |
| /* Function / Class Declarations *********************************************/ |
| |
| /* Function / Class Definition ***********************************************/ |
| static void split_lsb(const SHORT *const in_data, SHORT offset, |
| const INT num_val, SHORT *const out_data_lsb, |
| SHORT *const out_data_msb) { |
| int i; |
| |
| for (i = 0; i < num_val; i++) { |
| SHORT val = in_data[i] + offset; |
| if (out_data_lsb != NULL) out_data_lsb[i] = val & 0x0001; |
| if (out_data_msb != NULL) out_data_msb[i] = val >> 1; |
| } |
| } |
| |
| static void apply_lsb_coding(HANDLE_FDK_BITSTREAM strm, |
| const SHORT *const in_data_lsb, const UINT num_lsb, |
| const INT num_val) { |
| int i; |
| |
| for (i = 0; i < num_val; i++) { |
| FDKwriteBits(strm, in_data_lsb[i], num_lsb); |
| } |
| } |
| |
| static void calc_diff_freq(const SHORT *const in_data, SHORT *const out_data, |
| const INT num_val) { |
| int i; |
| out_data[0] = in_data[0]; |
| |
| for (i = 1; i < num_val; i++) { |
| out_data[i] = in_data[i] - in_data[i - 1]; |
| } |
| } |
| |
| static void calc_diff_time(const SHORT *const in_data, |
| const SHORT *const prev_data, SHORT *const out_data, |
| const INT num_val) { |
| int i; |
| out_data[0] = in_data[0]; |
| out_data[1] = prev_data[0]; |
| |
| for (i = 0; i < num_val; i++) { |
| out_data[i + 2] = in_data[i] - prev_data[i]; |
| } |
| } |
| |
| static INT sym_check(SHORT data[2], const INT lav, SHORT *const pSym_bits) { |
| UCHAR symBits = 0; |
| int sum_val = data[0] + data[1]; |
| int diff_val = data[0] - data[1]; |
| int num_sbits = 0; |
| |
| if (sum_val != 0) { |
| int sum_neg = (sum_val < 0) ? 1 : 0; |
| if (sum_neg) { |
| sum_val = -sum_val; |
| diff_val = -diff_val; |
| } |
| symBits = (symBits << 1) | sum_neg; |
| num_sbits++; |
| } |
| |
| if (diff_val != 0) { |
| int diff_neg = (diff_val < 0) ? 1 : 0; |
| if (diff_neg) { |
| diff_val = -diff_val; |
| } |
| symBits = (symBits << 1) | diff_neg; |
| num_sbits++; |
| } |
| |
| if (pSym_bits != NULL) { |
| *pSym_bits = symBits; |
| } |
| |
| if (sum_val % 2) { |
| data[0] = lav - sum_val / 2; |
| data[1] = lav - diff_val / 2; |
| } else { |
| data[0] = sum_val / 2; |
| data[1] = diff_val / 2; |
| } |
| |
| return num_sbits; |
| } |
| |
| static INT ilog2(UINT i) { |
| int l = 0; |
| |
| if (i) i--; |
| while (i > 0) { |
| i >>= 1; |
| l++; |
| } |
| |
| return l; |
| } |
| |
| static SHORT calc_pcm_bits(const SHORT num_val, const SHORT num_levels) { |
| SHORT num_complete_chunks = 0, rest_chunk_size = 0; |
| SHORT max_grp_len = 0, bits_pcm = 0; |
| int chunk_levels, i; |
| |
| switch (num_levels) { |
| case 3: |
| max_grp_len = 5; |
| break; |
| case 6: |
| max_grp_len = 5; |
| break; |
| case 7: |
| max_grp_len = 6; |
| break; |
| case 11: |
| max_grp_len = 2; |
| break; |
| case 13: |
| max_grp_len = 4; |
| break; |
| case 19: |
| max_grp_len = 4; |
| break; |
| case 25: |
| max_grp_len = 3; |
| break; |
| case 51: |
| max_grp_len = 4; |
| break; |
| default: |
| max_grp_len = 1; |
| } |
| |
| num_complete_chunks = num_val / max_grp_len; |
| rest_chunk_size = num_val % max_grp_len; |
| |
| chunk_levels = 1; |
| for (i = 1; i <= max_grp_len; i++) { |
| chunk_levels *= num_levels; |
| } |
| |
| bits_pcm = (SHORT)(ilog2(chunk_levels) * num_complete_chunks); |
| bits_pcm += (SHORT)(ilog2(num_levels) * rest_chunk_size); |
| |
| return bits_pcm; |
| } |
| |
| static void apply_pcm_coding(HANDLE_FDK_BITSTREAM strm, |
| const SHORT *const in_data_1, |
| const SHORT *const in_data_2, const SHORT offset, |
| const SHORT num_val, const SHORT num_levels) { |
| SHORT i = 0, j = 0, idx = 0; |
| SHORT max_grp_len = 0, grp_len = 0, next_val = 0; |
| int grp_val = 0, chunk_levels = 0; |
| |
| SHORT pcm_chunk_size[7] = {0}; |
| |
| switch (num_levels) { |
| case 3: |
| max_grp_len = 5; |
| break; |
| case 5: |
| max_grp_len = 3; |
| break; |
| case 6: |
| max_grp_len = 5; |
| break; |
| case 7: |
| max_grp_len = 6; |
| break; |
| case 9: |
| max_grp_len = 5; |
| break; |
| case 11: |
| max_grp_len = 2; |
| break; |
| case 13: |
| max_grp_len = 4; |
| break; |
| case 19: |
| max_grp_len = 4; |
| break; |
| case 25: |
| max_grp_len = 3; |
| break; |
| case 51: |
| max_grp_len = 4; |
| break; |
| default: |
| max_grp_len = 1; |
| } |
| |
| chunk_levels = 1; |
| for (i = 1; i <= max_grp_len; i++) { |
| chunk_levels *= num_levels; |
| pcm_chunk_size[i] = ilog2(chunk_levels); |
| } |
| |
| for (i = 0; i < num_val; i += max_grp_len) { |
| grp_len = FDKmin(max_grp_len, num_val - i); |
| grp_val = 0; |
| for (j = 0; j < grp_len; j++) { |
| idx = i + j; |
| if (in_data_2 == NULL) { |
| next_val = in_data_1[idx]; |
| } else if (in_data_1 == NULL) { |
| next_val = in_data_2[idx]; |
| } else { |
| next_val = ((idx % 2) ? in_data_2[idx / 2] : in_data_1[idx / 2]); |
| } |
| next_val += offset; |
| grp_val = grp_val * num_levels + next_val; |
| } |
| |
| FDKwriteBits(strm, grp_val, pcm_chunk_size[grp_len]); |
| } |
| } |
| |
| static UINT huff_enc_1D(HANDLE_FDK_BITSTREAM strm, const DATA_TYPE data_type, |
| const INT dim1, SHORT *const in_data, |
| const SHORT num_val, const SHORT p0_flag) { |
| int i, offset = 0; |
| UINT huffBits = 0; |
| |
| HUFF_ENTRY part0 = {0}; |
| const HUFF_ENTRY *pHuffTab = NULL; |
| |
| switch (data_type) { |
| case t_CLD: |
| pHuffTab = fdk_sacenc_huffCLDTab.h1D[dim1]; |
| break; |
| case t_ICC: |
| pHuffTab = fdk_sacenc_huffICCTab.h1D[dim1]; |
| break; |
| } |
| |
| if (p0_flag) { |
| switch (data_type) { |
| case t_CLD: |
| part0 = fdk_sacenc_huffPart0Tab.cld[in_data[0]]; |
| break; |
| case t_ICC: |
| part0 = fdk_sacenc_huffPart0Tab.icc[in_data[0]]; |
| break; |
| } |
| huffBits += FDKwriteBits(strm, HUFF_VALUE(part0), HUFF_LENGTH(part0)); |
| offset = 1; |
| } |
| |
| for (i = offset; i < num_val; i++) { |
| int id_sign = 0; |
| int id = in_data[i]; |
| |
| if (id != 0) { |
| id_sign = 0; |
| if (id < 0) { |
| id = -id; |
| id_sign = 1; |
| } |
| } |
| |
| huffBits += |
| FDKwriteBits(strm, HUFF_VALUE(pHuffTab[id]), HUFF_LENGTH(pHuffTab[id])); |
| |
| if (id != 0) { |
| huffBits += FDKwriteBits(strm, id_sign, 1); |
| } |
| } /* for i */ |
| |
| return huffBits; |
| } |
| |
| static void getHuffEntry(const INT lav, const DATA_TYPE data_type, const INT i, |
| const SHORT tab_idx_2D[2], const SHORT in_data[][2], |
| HUFF_ENTRY *const pEntry, HUFF_ENTRY *const pEscape) { |
| const HUFF_CLD_TAB_2D *pCLD2dTab = |
| &fdk_sacenc_huffCLDTab.h2D[tab_idx_2D[0]][tab_idx_2D[1]]; |
| const HUFF_ICC_TAB_2D *pICC2dTab = |
| &fdk_sacenc_huffICCTab.h2D[tab_idx_2D[0]][tab_idx_2D[1]]; |
| |
| switch (lav) { |
| case 1: { |
| const LAV1_2D *pLav1 = NULL; |
| switch (data_type) { |
| case t_CLD: |
| pLav1 = NULL; |
| break; |
| case t_ICC: |
| pLav1 = &pICC2dTab->lav1; |
| break; |
| } |
| if (pLav1 != NULL) { |
| *pEntry = pLav1->entry[in_data[i][0]][in_data[i][1]]; |
| *pEscape = pLav1->escape; |
| } |
| } break; |
| case 3: { |
| const LAV3_2D *pLav3 = NULL; |
| switch (data_type) { |
| case t_CLD: |
| pLav3 = &pCLD2dTab->lav3; |
| break; |
| case t_ICC: |
| pLav3 = &pICC2dTab->lav3; |
| break; |
| } |
| if (pLav3 != NULL) { |
| *pEntry = pLav3->entry[in_data[i][0]][in_data[i][1]]; |
| *pEscape = pLav3->escape; |
| } |
| } break; |
| case 5: { |
| const LAV5_2D *pLav5 = NULL; |
| switch (data_type) { |
| case t_CLD: |
| pLav5 = &pCLD2dTab->lav5; |
| break; |
| case t_ICC: |
| pLav5 = &pICC2dTab->lav5; |
| break; |
| } |
| if (pLav5 != NULL) { |
| *pEntry = pLav5->entry[in_data[i][0]][in_data[i][1]]; |
| *pEscape = pLav5->escape; |
| } |
| } break; |
| case 7: { |
| const LAV7_2D *pLav7 = NULL; |
| switch (data_type) { |
| case t_CLD: |
| pLav7 = &pCLD2dTab->lav7; |
| break; |
| case t_ICC: |
| pLav7 = &pICC2dTab->lav7; |
| break; |
| } |
| if (pLav7 != NULL) { |
| *pEntry = pLav7->entry[in_data[i][0]][in_data[i][1]]; |
| *pEscape = pLav7->escape; |
| } |
| } break; |
| case 9: { |
| const LAV9_2D *pLav9 = NULL; |
| switch (data_type) { |
| case t_CLD: |
| pLav9 = &pCLD2dTab->lav9; |
| break; |
| case t_ICC: |
| pLav9 = NULL; |
| break; |
| } |
| if (pLav9 != NULL) { |
| *pEntry = pLav9->entry[in_data[i][0]][in_data[i][1]]; |
| *pEscape = pLav9->escape; |
| } |
| } break; |
| } |
| } |
| |
| static UINT huff_enc_2D(HANDLE_FDK_BITSTREAM strm, const DATA_TYPE data_type, |
| SHORT tab_idx_2D[2], SHORT lav_idx, SHORT in_data[][2], |
| SHORT num_val, SHORT stride, SHORT *p0_data[2]) { |
| SHORT i = 0, lav = 0, num_sbits = 0, sym_bits = 0, escIdx = 0; |
| SHORT esc_data[2][MAXBANDS] = {{0}}; |
| |
| UINT huffBits = 0; |
| |
| const HUFF_ENTRY *pHuffEntry = NULL; |
| |
| switch (data_type) { |
| case t_CLD: |
| lav = 2 * lav_idx + 3; /* LAV */ |
| pHuffEntry = fdk_sacenc_huffPart0Tab.cld; |
| break; |
| case t_ICC: |
| lav = 2 * lav_idx + 1; /* LAV */ |
| pHuffEntry = fdk_sacenc_huffPart0Tab.icc; |
| break; |
| } |
| |
| /* Partition 0 */ |
| if (p0_data[0] != NULL) { |
| HUFF_ENTRY entry = pHuffEntry[*p0_data[0]]; |
| huffBits += FDKwriteBits(strm, HUFF_VALUE(entry), HUFF_LENGTH(entry)); |
| } |
| if (p0_data[1] != NULL) { |
| HUFF_ENTRY entry = pHuffEntry[*p0_data[1]]; |
| huffBits += FDKwriteBits(strm, HUFF_VALUE(entry), HUFF_LENGTH(entry)); |
| } |
| |
| for (i = 0; i < num_val; i += stride) { |
| HUFF_ENTRY entry = {0}; |
| HUFF_ENTRY escape = {0}; |
| |
| esc_data[0][escIdx] = in_data[i][0] + lav; |
| esc_data[1][escIdx] = in_data[i][1] + lav; |
| |
| num_sbits = sym_check(in_data[i], lav, &sym_bits); |
| |
| getHuffEntry(lav, data_type, i, tab_idx_2D, in_data, &entry, &escape); |
| |
| huffBits += FDKwriteBits(strm, HUFF_VALUE(entry), HUFF_LENGTH(entry)); |
| |
| if ((HUFF_VALUE(entry) == HUFF_VALUE(escape)) && |
| (HUFF_LENGTH(entry) == HUFF_LENGTH(escape))) { |
| escIdx++; |
| } else { |
| huffBits += FDKwriteBits(strm, sym_bits, num_sbits); |
| } |
| } /* for i */ |
| |
| if (escIdx > 0) { |
| huffBits += calc_pcm_bits(2 * escIdx, (2 * lav + 1)); |
| if (strm != NULL) { |
| apply_pcm_coding(strm, esc_data[0], esc_data[1], 0 /*offset*/, 2 * escIdx, |
| (2 * lav + 1)); |
| } |
| } |
| |
| return huffBits; |
| } |
| |
| static SCHAR get_next_lav_step(const INT lav, const DATA_TYPE data_type) { |
| SCHAR lav_step = 0; |
| |
| switch (data_type) { |
| case t_CLD: |
| lav_step = (lav > 9) ? -1 : lav_step_CLD[lav]; |
| break; |
| case t_ICC: |
| lav_step = (lav > 7) ? -1 : lav_step_ICC[lav]; |
| break; |
| } |
| |
| return lav_step; |
| } |
| |
| static INT diff_type_offset(const DIFF_TYPE diff_type) { |
| int offset = 0; |
| switch (diff_type) { |
| case DIFF_FREQ: |
| offset = 0; |
| break; |
| case DIFF_TIME: |
| offset = 2; |
| break; |
| } |
| return offset; |
| } |
| |
| static SHORT calc_huff_bits(SHORT *in_data_1, SHORT *in_data_2, |
| const DATA_TYPE data_type, |
| const DIFF_TYPE diff_type_1, |
| const DIFF_TYPE diff_type_2, const SHORT num_val, |
| SHORT *const lav_idx, SHORT *const cdg_scheme) { |
| SHORT tab_idx_2D[2][2] = {{0}}; |
| SHORT tab_idx_1D[2] = {0}; |
| SHORT df_rest_flag[2] = {0}; |
| SHORT p0_flag[2] = {0}; |
| |
| SHORT pair_vec[MAXBANDS][2] = {{0}}; |
| |
| SHORT *p0_data_1[2] = {NULL}; |
| SHORT *p0_data_2[2] = {NULL}; |
| |
| SHORT i = 0; |
| SHORT lav_fp[2] = {0}; |
| |
| SHORT bit_count_1D = 0; |
| SHORT bit_count_2D_freq = 0; |
| SHORT bit_count_min = 0; |
| |
| SHORT num_val_1_short = 0; |
| SHORT num_val_2_short = 0; |
| |
| SHORT *in_data_1_short = NULL; |
| SHORT *in_data_2_short = NULL; |
| |
| /* 1D Huffman coding */ |
| bit_count_1D = 1; /* HUFF_1D */ |
| |
| num_val_1_short = num_val; |
| num_val_2_short = num_val; |
| |
| if (in_data_1 != NULL) { |
| in_data_1_short = in_data_1 + diff_type_offset(diff_type_1); |
| } |
| if (in_data_2 != NULL) { |
| in_data_2_short = in_data_2 + diff_type_offset(diff_type_2); |
| } |
| |
| p0_flag[0] = (diff_type_1 == DIFF_FREQ); |
| p0_flag[1] = (diff_type_2 == DIFF_FREQ); |
| |
| tab_idx_1D[0] = (diff_type_1 == DIFF_FREQ) ? 0 : 1; |
| tab_idx_1D[1] = (diff_type_2 == DIFF_FREQ) ? 0 : 1; |
| |
| if (in_data_1 != NULL) { |
| bit_count_1D += huff_enc_1D(NULL, data_type, tab_idx_1D[0], in_data_1_short, |
| num_val_1_short, p0_flag[0]); |
| } |
| if (in_data_2 != NULL) { |
| bit_count_1D += huff_enc_1D(NULL, data_type, tab_idx_1D[1], in_data_2_short, |
| num_val_2_short, p0_flag[1]); |
| } |
| |
| bit_count_min = bit_count_1D; |
| *cdg_scheme = HUFF_1D << PAIR_SHIFT; |
| lav_idx[0] = lav_idx[1] = -1; |
| |
| /* Huffman 2D frequency pairs */ |
| bit_count_2D_freq = 1; /* HUFF_2D */ |
| |
| num_val_1_short = num_val; |
| num_val_2_short = num_val; |
| |
| if (in_data_1 != NULL) { |
| in_data_1_short = in_data_1 + diff_type_offset(diff_type_1); |
| } |
| if (in_data_2 != NULL) { |
| in_data_2_short = in_data_2 + diff_type_offset(diff_type_2); |
| } |
| |
| lav_fp[0] = lav_fp[1] = 0; |
| |
| p0_data_1[0] = NULL; |
| p0_data_1[1] = NULL; |
| p0_data_2[0] = NULL; |
| p0_data_2[1] = NULL; |
| |
| if (in_data_1 != NULL) { |
| if (diff_type_1 == DIFF_FREQ) { |
| p0_data_1[0] = &in_data_1[0]; |
| p0_data_1[1] = NULL; |
| |
| num_val_1_short -= 1; |
| in_data_1_short += 1; |
| } |
| |
| df_rest_flag[0] = num_val_1_short % 2; |
| |
| if (df_rest_flag[0]) num_val_1_short -= 1; |
| |
| for (i = 0; i < num_val_1_short - 1; i += 2) { |
| pair_vec[i][0] = in_data_1_short[i]; |
| pair_vec[i][1] = in_data_1_short[i + 1]; |
| |
| lav_fp[0] = FDKmax(lav_fp[0], fAbs(pair_vec[i][0])); |
| lav_fp[0] = FDKmax(lav_fp[0], fAbs(pair_vec[i][1])); |
| } |
| |
| tab_idx_2D[0][0] = (diff_type_1 == DIFF_TIME) ? 1 : 0; |
| tab_idx_2D[0][1] = 0; |
| |
| tab_idx_1D[0] = (diff_type_1 == DIFF_FREQ) ? 0 : 1; |
| |
| lav_fp[0] = get_next_lav_step(lav_fp[0], data_type); |
| |
| if (lav_fp[0] != -1) bit_count_2D_freq += lavHuffLen[lav_fp[0]]; |
| } |
| |
| if (in_data_2 != NULL) { |
| if (diff_type_2 == DIFF_FREQ) { |
| p0_data_2[0] = NULL; |
| p0_data_2[1] = &in_data_2[0]; |
| |
| num_val_2_short -= 1; |
| in_data_2_short += 1; |
| } |
| |
| df_rest_flag[1] = num_val_2_short % 2; |
| |
| if (df_rest_flag[1]) num_val_2_short -= 1; |
| |
| for (i = 0; i < num_val_2_short - 1; i += 2) { |
| pair_vec[i + 1][0] = in_data_2_short[i]; |
| pair_vec[i + 1][1] = in_data_2_short[i + 1]; |
| |
| lav_fp[1] = FDKmax(lav_fp[1], fAbs(pair_vec[i + 1][0])); |
| lav_fp[1] = FDKmax(lav_fp[1], fAbs(pair_vec[i + 1][1])); |
| } |
| |
| tab_idx_2D[1][0] = (diff_type_2 == DIFF_TIME) ? 1 : 0; |
| tab_idx_2D[1][1] = 0; |
| |
| tab_idx_1D[1] = (diff_type_2 == DIFF_FREQ) ? 0 : 1; |
| |
| lav_fp[1] = get_next_lav_step(lav_fp[1], data_type); |
| |
| if (lav_fp[1] != -1) bit_count_2D_freq += lavHuffLen[lav_fp[1]]; |
| } |
| |
| if ((lav_fp[0] != -1) && (lav_fp[1] != -1)) { |
| if (in_data_1 != NULL) { |
| bit_count_2D_freq += |
| huff_enc_2D(NULL, data_type, tab_idx_2D[0], lav_fp[0], pair_vec, |
| num_val_1_short, 2, p0_data_1); |
| } |
| if (in_data_2 != NULL) { |
| bit_count_2D_freq += |
| huff_enc_2D(NULL, data_type, tab_idx_2D[1], lav_fp[1], pair_vec + 1, |
| num_val_2_short, 2, p0_data_2); |
| } |
| if (in_data_1 != NULL) { |
| if (df_rest_flag[0]) |
| bit_count_2D_freq += |
| huff_enc_1D(NULL, data_type, tab_idx_1D[0], |
| in_data_1_short + num_val_1_short, 1, 0); |
| } |
| if (in_data_2 != NULL) { |
| if (df_rest_flag[1]) |
| bit_count_2D_freq += |
| huff_enc_1D(NULL, data_type, tab_idx_1D[1], |
| in_data_2_short + num_val_2_short, 1, 0); |
| } |
| |
| if (bit_count_2D_freq < bit_count_min) { |
| bit_count_min = bit_count_2D_freq; |
| *cdg_scheme = HUFF_2D << PAIR_SHIFT | FREQ_PAIR; |
| lav_idx[0] = lav_fp[0]; |
| lav_idx[1] = lav_fp[1]; |
| } |
| } |
| |
| return bit_count_min; |
| } |
| |
| static void apply_huff_coding(HANDLE_FDK_BITSTREAM strm, SHORT *const in_data_1, |
| SHORT *const in_data_2, const DATA_TYPE data_type, |
| const DIFF_TYPE diff_type_1, |
| const DIFF_TYPE diff_type_2, const SHORT num_val, |
| const SHORT *const lav_idx, |
| const SHORT cdg_scheme) { |
| SHORT tab_idx_2D[2][2] = {{0}}; |
| SHORT tab_idx_1D[2] = {0}; |
| SHORT df_rest_flag[2] = {0}; |
| SHORT p0_flag[2] = {0}; |
| |
| SHORT pair_vec[MAXBANDS][2] = {{0}}; |
| |
| SHORT *p0_data_1[2] = {NULL}; |
| SHORT *p0_data_2[2] = {NULL}; |
| |
| SHORT i = 0; |
| |
| SHORT num_val_1_short = num_val; |
| SHORT num_val_2_short = num_val; |
| |
| SHORT *in_data_1_short = NULL; |
| SHORT *in_data_2_short = NULL; |
| |
| /* Offset */ |
| if (in_data_1 != NULL) { |
| in_data_1_short = in_data_1 + diff_type_offset(diff_type_1); |
| } |
| if (in_data_2 != NULL) { |
| in_data_2_short = in_data_2 + diff_type_offset(diff_type_2); |
| } |
| |
| /* Signalize coding scheme */ |
| FDKwriteBits(strm, cdg_scheme >> PAIR_SHIFT, 1); |
| |
| switch (cdg_scheme >> PAIR_SHIFT) { |
| case HUFF_1D: |
| |
| p0_flag[0] = (diff_type_1 == DIFF_FREQ); |
| p0_flag[1] = (diff_type_2 == DIFF_FREQ); |
| |
| tab_idx_1D[0] = (diff_type_1 == DIFF_FREQ) ? 0 : 1; |
| tab_idx_1D[1] = (diff_type_2 == DIFF_FREQ) ? 0 : 1; |
| |
| if (in_data_1 != NULL) { |
| huff_enc_1D(strm, data_type, tab_idx_1D[0], in_data_1_short, |
| num_val_1_short, p0_flag[0]); |
| } |
| if (in_data_2 != NULL) { |
| huff_enc_1D(strm, data_type, tab_idx_1D[1], in_data_2_short, |
| num_val_2_short, p0_flag[1]); |
| } |
| break; /* HUFF_1D */ |
| |
| case HUFF_2D: |
| |
| switch (cdg_scheme & PAIR_MASK) { |
| case FREQ_PAIR: |
| |
| if (in_data_1 != NULL) { |
| if (diff_type_1 == DIFF_FREQ) { |
| p0_data_1[0] = &in_data_1[0]; |
| p0_data_1[1] = NULL; |
| |
| num_val_1_short -= 1; |
| in_data_1_short += 1; |
| } |
| |
| df_rest_flag[0] = num_val_1_short % 2; |
| |
| if (df_rest_flag[0]) num_val_1_short -= 1; |
| |
| for (i = 0; i < num_val_1_short - 1; i += 2) { |
| pair_vec[i][0] = in_data_1_short[i]; |
| pair_vec[i][1] = in_data_1_short[i + 1]; |
| } |
| |
| tab_idx_2D[0][0] = (diff_type_1 == DIFF_TIME) ? 1 : 0; |
| tab_idx_2D[0][1] = 0; |
| |
| tab_idx_1D[0] = (diff_type_1 == DIFF_FREQ) ? 0 : 1; |
| } /* if( in_data_1 != NULL ) */ |
| |
| if (in_data_2 != NULL) { |
| if (diff_type_2 == DIFF_FREQ) { |
| p0_data_2[0] = NULL; |
| p0_data_2[1] = &in_data_2[0]; |
| |
| num_val_2_short -= 1; |
| in_data_2_short += 1; |
| } |
| |
| df_rest_flag[1] = num_val_2_short % 2; |
| |
| if (df_rest_flag[1]) num_val_2_short -= 1; |
| |
| for (i = 0; i < num_val_2_short - 1; i += 2) { |
| pair_vec[i + 1][0] = in_data_2_short[i]; |
| pair_vec[i + 1][1] = in_data_2_short[i + 1]; |
| } |
| |
| tab_idx_2D[1][0] = (diff_type_2 == DIFF_TIME) ? 1 : 0; |
| tab_idx_2D[1][1] = 0; |
| |
| tab_idx_1D[1] = (diff_type_2 == DIFF_FREQ) ? 0 : 1; |
| } /* if( in_data_2 != NULL ) */ |
| |
| if (in_data_1 != NULL) { |
| FDKwriteBits(strm, lavHuffVal[lav_idx[0]], lavHuffLen[lav_idx[0]]); |
| huff_enc_2D(strm, data_type, tab_idx_2D[0], lav_idx[0], pair_vec, |
| num_val_1_short, 2, p0_data_1); |
| if (df_rest_flag[0]) { |
| huff_enc_1D(strm, data_type, tab_idx_1D[0], |
| in_data_1_short + num_val_1_short, 1, 0); |
| } |
| } |
| if (in_data_2 != NULL) { |
| FDKwriteBits(strm, lavHuffVal[lav_idx[1]], lavHuffLen[lav_idx[1]]); |
| huff_enc_2D(strm, data_type, tab_idx_2D[1], lav_idx[1], |
| pair_vec + 1, num_val_2_short, 2, p0_data_2); |
| if (df_rest_flag[1]) { |
| huff_enc_1D(strm, data_type, tab_idx_1D[1], |
| in_data_2_short + num_val_2_short, 1, 0); |
| } |
| } |
| break; /* FREQ_PAIR */ |
| |
| case TIME_PAIR: |
| |
| if ((diff_type_1 == DIFF_FREQ) || (diff_type_2 == DIFF_FREQ)) { |
| p0_data_1[0] = &in_data_1[0]; |
| p0_data_1[1] = &in_data_2[0]; |
| |
| in_data_1_short += 1; |
| in_data_2_short += 1; |
| |
| num_val_1_short -= 1; |
| } |
| |
| for (i = 0; i < num_val_1_short; i++) { |
| pair_vec[i][0] = in_data_1_short[i]; |
| pair_vec[i][1] = in_data_2_short[i]; |
| } |
| |
| tab_idx_2D[0][0] = |
| ((diff_type_1 == DIFF_TIME) || (diff_type_2 == DIFF_TIME)) ? 1 |
| : 0; |
| tab_idx_2D[0][1] = 1; |
| |
| FDKwriteBits(strm, lavHuffVal[lav_idx[0]], lavHuffLen[lav_idx[0]]); |
| |
| huff_enc_2D(strm, data_type, tab_idx_2D[0], lav_idx[0], pair_vec, |
| num_val_1_short, 1, p0_data_1); |
| |
| break; /* TIME_PAIR */ |
| } /* switch( cdg_scheme & PAIR_MASK ) */ |
| |
| break; /* HUFF_2D */ |
| |
| default: |
| break; |
| } /* switch( cdg_scheme >> PAIR_SHIFT ) */ |
| } |
| |
| INT fdk_sacenc_ecDataPairEnc(HANDLE_FDK_BITSTREAM strm, |
| SHORT aaInData[][MAXBANDS], |
| SHORT aHistory[MAXBANDS], |
| const DATA_TYPE data_type, const INT setIdx, |
| const INT startBand, const INT dataBands, |
| const INT coarse_flag, |
| const INT independency_flag) { |
| SHORT reset = 0, pb = 0; |
| SHORT quant_levels = 0, quant_offset = 0, num_pcm_val = 0; |
| |
| SHORT splitLsb_flag = 0; |
| SHORT pcmCoding_flag = 0; |
| |
| SHORT allowDiffTimeBack_flag = !independency_flag || (setIdx > 0); |
| |
| SHORT num_lsb_bits = -1; |
| SHORT num_pcm_bits = -1; |
| |
| SHORT quant_data_lsb[2][MAXBANDS]; |
| SHORT quant_data_msb[2][MAXBANDS]; |
| |
| SHORT quant_data_hist_lsb[MAXBANDS]; |
| SHORT quant_data_hist_msb[MAXBANDS]; |
| |
| SHORT data_diff_freq[2][MAXBANDS]; |
| SHORT data_diff_time[2][MAXBANDS + 2]; |
| |
| SHORT *p_quant_data_msb[2]; |
| SHORT *p_quant_data_hist_msb = NULL; |
| |
| SHORT min_bits_all = 0; |
| SHORT min_found = 0; |
| |
| SHORT min_bits_df_df = -1; |
| SHORT min_bits_df_dt = -1; |
| SHORT min_bits_dtbw_df = -1; |
| SHORT min_bits_dt_dt = -1; |
| |
| SHORT lav_df_df[2] = {-1, -1}; |
| SHORT lav_df_dt[2] = {-1, -1}; |
| SHORT lav_dtbw_df[2] = {-1, -1}; |
| SHORT lav_dt_dt[2] = {-1, -1}; |
| |
| SHORT coding_scheme_df_df = 0; |
| SHORT coding_scheme_df_dt = 0; |
| SHORT coding_scheme_dtbw_df = 0; |
| SHORT coding_scheme_dt_dt = 0; |
| |
| switch (data_type) { |
| case t_CLD: |
| if (coarse_flag) { |
| splitLsb_flag = 0; |
| quant_levels = 15; |
| quant_offset = 7; |
| } else { |
| splitLsb_flag = 0; |
| quant_levels = 31; |
| quant_offset = 15; |
| } |
| break; |
| case t_ICC: |
| if (coarse_flag) { |
| splitLsb_flag = 0; |
| quant_levels = 4; |
| quant_offset = 0; |
| } else { |
| splitLsb_flag = 0; |
| quant_levels = 8; |
| quant_offset = 0; |
| } |
| break; |
| } /* switch( data_type ) */ |
| |
| /* Split off LSB */ |
| if (splitLsb_flag) { |
| split_lsb(aaInData[setIdx] + startBand, quant_offset, dataBands, |
| quant_data_lsb[0], quant_data_msb[0]); |
| |
| split_lsb(aaInData[setIdx + 1] + startBand, quant_offset, dataBands, |
| quant_data_lsb[1], quant_data_msb[1]); |
| |
| p_quant_data_msb[0] = quant_data_msb[0]; |
| p_quant_data_msb[1] = quant_data_msb[1]; |
| |
| num_lsb_bits = 2 * dataBands; |
| } else if (quant_offset != 0) { |
| for (pb = 0; pb < dataBands; pb++) { |
| quant_data_msb[0][pb] = aaInData[setIdx][startBand + pb] + quant_offset; |
| quant_data_msb[1][pb] = |
| aaInData[setIdx + 1][startBand + pb] + quant_offset; |
| } |
| |
| p_quant_data_msb[0] = quant_data_msb[0]; |
| p_quant_data_msb[1] = quant_data_msb[1]; |
| |
| num_lsb_bits = 0; |
| } else { |
| p_quant_data_msb[0] = aaInData[setIdx] + startBand; |
| p_quant_data_msb[1] = aaInData[setIdx + 1] + startBand; |
| |
| num_lsb_bits = 0; |
| } |
| |
| if (allowDiffTimeBack_flag) { |
| if (splitLsb_flag) { |
| split_lsb(aHistory + startBand, quant_offset, dataBands, |
| quant_data_hist_lsb, quant_data_hist_msb); |
| |
| p_quant_data_hist_msb = quant_data_hist_msb; |
| } else if (quant_offset != 0) { |
| for (pb = 0; pb < dataBands; pb++) { |
| quant_data_hist_msb[pb] = aHistory[startBand + pb] + quant_offset; |
| } |
| p_quant_data_hist_msb = quant_data_hist_msb; |
| } else { |
| p_quant_data_hist_msb = aHistory + startBand; |
| } |
| } |
| |
| /* Calculate frequency differences */ |
| calc_diff_freq(p_quant_data_msb[0], data_diff_freq[0], dataBands); |
| |
| calc_diff_freq(p_quant_data_msb[1], data_diff_freq[1], dataBands); |
| |
| /* Calculate time differences */ |
| if (allowDiffTimeBack_flag) { |
| calc_diff_time(p_quant_data_msb[0], p_quant_data_hist_msb, |
| data_diff_time[0], dataBands); |
| } |
| |
| calc_diff_time(p_quant_data_msb[1], p_quant_data_msb[0], data_diff_time[1], |
| dataBands); |
| |
| /* Calculate coding scheme with minumum bit consumption */ |
| |
| /**********************************************************/ |
| num_pcm_bits = calc_pcm_bits(2 * dataBands, quant_levels); |
| num_pcm_val = 2 * dataBands; |
| |
| /**********************************************************/ |
| |
| min_bits_all = num_pcm_bits; |
| |
| /**********************************************************/ |
| /**********************************************************/ |
| |
| /**********************************************************/ |
| min_bits_df_df = |
| calc_huff_bits(data_diff_freq[0], data_diff_freq[1], data_type, DIFF_FREQ, |
| DIFF_FREQ, dataBands, lav_df_df, &coding_scheme_df_df); |
| |
| min_bits_df_df += 2; |
| |
| min_bits_df_df += num_lsb_bits; |
| |
| if (min_bits_df_df < min_bits_all) { |
| min_bits_all = min_bits_df_df; |
| } |
| /**********************************************************/ |
| |
| /**********************************************************/ |
| min_bits_df_dt = |
| calc_huff_bits(data_diff_freq[0], data_diff_time[1], data_type, DIFF_FREQ, |
| DIFF_TIME, dataBands, lav_df_dt, &coding_scheme_df_dt); |
| |
| min_bits_df_dt += 2; |
| |
| min_bits_df_dt += num_lsb_bits; |
| |
| if (min_bits_df_dt < min_bits_all) { |
| min_bits_all = min_bits_df_dt; |
| } |
| /**********************************************************/ |
| |
| /**********************************************************/ |
| /**********************************************************/ |
| |
| if (allowDiffTimeBack_flag) { |
| /**********************************************************/ |
| min_bits_dtbw_df = calc_huff_bits( |
| data_diff_time[0], data_diff_freq[1], data_type, DIFF_TIME, DIFF_FREQ, |
| dataBands, lav_dtbw_df, &coding_scheme_dtbw_df); |
| |
| min_bits_dtbw_df += 2; |
| |
| min_bits_dtbw_df += num_lsb_bits; |
| |
| if (min_bits_dtbw_df < min_bits_all) { |
| min_bits_all = min_bits_dtbw_df; |
| } |
| /**********************************************************/ |
| |
| /**********************************************************/ |
| min_bits_dt_dt = calc_huff_bits(data_diff_time[0], data_diff_time[1], |
| data_type, DIFF_TIME, DIFF_TIME, dataBands, |
| lav_dt_dt, &coding_scheme_dt_dt); |
| |
| min_bits_dt_dt += 2; |
| |
| min_bits_dt_dt += num_lsb_bits; |
| |
| if (min_bits_dt_dt < min_bits_all) { |
| min_bits_all = min_bits_dt_dt; |
| } |
| /**********************************************************/ |
| |
| } /* if( allowDiffTimeBack_flag ) */ |
| |
| /***************************/ |
| /* Start actual coding now */ |
| /***************************/ |
| |
| /* PCM or Diff/Huff Coding? */ |
| pcmCoding_flag = (min_bits_all == num_pcm_bits); |
| |
| FDKwriteBits(strm, pcmCoding_flag, 1); |
| |
| if (pcmCoding_flag) { |
| /* Grouped PCM Coding */ |
| apply_pcm_coding(strm, aaInData[setIdx] + startBand, |
| aaInData[setIdx + 1] + startBand, quant_offset, |
| num_pcm_val, quant_levels); |
| } else { |
| /* Diff/Huff Coding */ |
| |
| min_found = 0; |
| |
| /*******************************************/ |
| if (min_bits_all == min_bits_df_df) { |
| FDKwriteBits(strm, DIFF_FREQ, 1); |
| FDKwriteBits(strm, DIFF_FREQ, 1); |
| |
| apply_huff_coding(strm, data_diff_freq[0], data_diff_freq[1], data_type, |
| DIFF_FREQ, DIFF_FREQ, dataBands, lav_df_df, |
| coding_scheme_df_df); |
| |
| min_found = 1; |
| } |
| /*******************************************/ |
| |
| /*******************************************/ |
| if (!min_found && (min_bits_all == min_bits_df_dt)) { |
| FDKwriteBits(strm, DIFF_FREQ, 1); |
| FDKwriteBits(strm, DIFF_TIME, 1); |
| |
| apply_huff_coding(strm, data_diff_freq[0], data_diff_time[1], data_type, |
| DIFF_FREQ, DIFF_TIME, dataBands, lav_df_dt, |
| coding_scheme_df_dt); |
| |
| min_found = 1; |
| } |
| /*******************************************/ |
| |
| /*******************************************/ |
| /*******************************************/ |
| |
| if (allowDiffTimeBack_flag) { |
| /*******************************************/ |
| if (!min_found && (min_bits_all == min_bits_dtbw_df)) { |
| FDKwriteBits(strm, DIFF_TIME, 1); |
| FDKwriteBits(strm, DIFF_FREQ, 1); |
| |
| apply_huff_coding(strm, data_diff_time[0], data_diff_freq[1], data_type, |
| DIFF_TIME, DIFF_FREQ, dataBands, lav_dtbw_df, |
| coding_scheme_dtbw_df); |
| |
| min_found = 1; |
| } |
| /*******************************************/ |
| |
| /*******************************************/ |
| if (!min_found && (min_bits_all == min_bits_dt_dt)) { |
| FDKwriteBits(strm, DIFF_TIME, 1); |
| FDKwriteBits(strm, DIFF_TIME, 1); |
| |
| apply_huff_coding(strm, data_diff_time[0], data_diff_time[1], data_type, |
| DIFF_TIME, DIFF_TIME, dataBands, lav_dt_dt, |
| coding_scheme_dt_dt); |
| } |
| /*******************************************/ |
| |
| } /* if( allowDiffTimeBack_flag ) */ |
| |
| /* LSB coding */ |
| if (splitLsb_flag) { |
| apply_lsb_coding(strm, quant_data_lsb[0], 1, dataBands); |
| |
| apply_lsb_coding(strm, quant_data_lsb[1], 1, dataBands); |
| } |
| |
| } /* Diff/Huff/LSB coding */ |
| |
| return reset; |
| } |
| |
| INT fdk_sacenc_ecDataSingleEnc(HANDLE_FDK_BITSTREAM strm, |
| SHORT aaInData[][MAXBANDS], |
| SHORT aHistory[MAXBANDS], |
| const DATA_TYPE data_type, const INT setIdx, |
| const INT startBand, const INT dataBands, |
| const INT coarse_flag, |
| const INT independency_flag) { |
| SHORT reset = 0, pb = 0; |
| SHORT quant_levels = 0, quant_offset = 0, num_pcm_val = 0; |
| |
| SHORT splitLsb_flag = 0; |
| SHORT pcmCoding_flag = 0; |
| |
| SHORT allowDiffTimeBack_flag = !independency_flag || (setIdx > 0); |
| |
| SHORT num_lsb_bits = -1; |
| SHORT num_pcm_bits = -1; |
| |
| SHORT quant_data_lsb[MAXBANDS]; |
| SHORT quant_data_msb[MAXBANDS]; |
| |
| SHORT quant_data_hist_lsb[MAXBANDS]; |
| SHORT quant_data_hist_msb[MAXBANDS]; |
| |
| SHORT data_diff_freq[MAXBANDS]; |
| SHORT data_diff_time[MAXBANDS + 2]; |
| |
| SHORT *p_quant_data_msb; |
| SHORT *p_quant_data_hist_msb = NULL; |
| |
| SHORT min_bits_all = 0; |
| SHORT min_found = 0; |
| |
| SHORT min_bits_df = -1; |
| SHORT min_bits_dt = -1; |
| |
| SHORT lav_df[2] = {-1, -1}; |
| SHORT lav_dt[2] = {-1, -1}; |
| |
| SHORT coding_scheme_df = 0; |
| SHORT coding_scheme_dt = 0; |
| |
| switch (data_type) { |
| case t_CLD: |
| if (coarse_flag) { |
| splitLsb_flag = 0; |
| quant_levels = 15; |
| quant_offset = 7; |
| } else { |
| splitLsb_flag = 0; |
| quant_levels = 31; |
| quant_offset = 15; |
| } |
| break; |
| case t_ICC: |
| if (coarse_flag) { |
| splitLsb_flag = 0; |
| quant_levels = 4; |
| quant_offset = 0; |
| } else { |
| splitLsb_flag = 0; |
| quant_levels = 8; |
| quant_offset = 0; |
| } |
| break; |
| } /* switch( data_type ) */ |
| |
| /* Split off LSB */ |
| if (splitLsb_flag) { |
| split_lsb(aaInData[setIdx] + startBand, quant_offset, dataBands, |
| quant_data_lsb, quant_data_msb); |
| |
| p_quant_data_msb = quant_data_msb; |
| num_lsb_bits = dataBands; |
| } else if (quant_offset != 0) { |
| for (pb = 0; pb < dataBands; pb++) { |
| quant_data_msb[pb] = aaInData[setIdx][startBand + pb] + quant_offset; |
| } |
| |
| p_quant_data_msb = quant_data_msb; |
| num_lsb_bits = 0; |
| } else { |
| p_quant_data_msb = aaInData[setIdx] + startBand; |
| num_lsb_bits = 0; |
| } |
| |
| if (allowDiffTimeBack_flag) { |
| if (splitLsb_flag) { |
| split_lsb(aHistory + startBand, quant_offset, dataBands, |
| quant_data_hist_lsb, quant_data_hist_msb); |
| |
| p_quant_data_hist_msb = quant_data_hist_msb; |
| } else if (quant_offset != 0) { |
| for (pb = 0; pb < dataBands; pb++) { |
| quant_data_hist_msb[pb] = aHistory[startBand + pb] + quant_offset; |
| } |
| p_quant_data_hist_msb = quant_data_hist_msb; |
| } else { |
| p_quant_data_hist_msb = aHistory + startBand; |
| } |
| } |
| |
| /* Calculate frequency differences */ |
| calc_diff_freq(p_quant_data_msb, data_diff_freq, dataBands); |
| |
| /* Calculate time differences */ |
| if (allowDiffTimeBack_flag) { |
| calc_diff_time(p_quant_data_msb, p_quant_data_hist_msb, data_diff_time, |
| dataBands); |
| } |
| |
| /* Calculate coding scheme with minumum bit consumption */ |
| |
| /**********************************************************/ |
| num_pcm_bits = calc_pcm_bits(dataBands, quant_levels); |
| num_pcm_val = dataBands; |
| |
| /**********************************************************/ |
| |
| min_bits_all = num_pcm_bits; |
| |
| /**********************************************************/ |
| /**********************************************************/ |
| |
| /**********************************************************/ |
| min_bits_df = calc_huff_bits(data_diff_freq, NULL, data_type, DIFF_FREQ, |
| DIFF_FREQ, dataBands, lav_df, &coding_scheme_df); |
| |
| if (allowDiffTimeBack_flag) min_bits_df += 1; |
| |
| min_bits_df += num_lsb_bits; |
| |
| if (min_bits_df < min_bits_all) { |
| min_bits_all = min_bits_df; |
| } |
| /**********************************************************/ |
| |
| /**********************************************************/ |
| if (allowDiffTimeBack_flag) { |
| min_bits_dt = |
| calc_huff_bits(data_diff_time, NULL, data_type, DIFF_TIME, DIFF_TIME, |
| dataBands, lav_dt, &coding_scheme_dt); |
| |
| min_bits_dt += 1; |
| min_bits_dt += num_lsb_bits; |
| |
| if (min_bits_dt < min_bits_all) { |
| min_bits_all = min_bits_dt; |
| } |
| } /* if( allowDiffTimeBack_flag ) */ |
| |
| /***************************/ |
| /* Start actual coding now */ |
| /***************************/ |
| |
| /* PCM or Diff/Huff Coding? */ |
| pcmCoding_flag = (min_bits_all == num_pcm_bits); |
| |
| FDKwriteBits(strm, pcmCoding_flag, 1); |
| |
| if (pcmCoding_flag) { |
| /* Grouped PCM Coding */ |
| apply_pcm_coding(strm, aaInData[setIdx] + startBand, NULL, quant_offset, |
| num_pcm_val, quant_levels); |
| } else { |
| /* Diff/Huff Coding */ |
| |
| min_found = 0; |
| |
| /*******************************************/ |
| if (min_bits_all == min_bits_df) { |
| if (allowDiffTimeBack_flag) { |
| FDKwriteBits(strm, DIFF_FREQ, 1); |
| } |
| |
| apply_huff_coding(strm, data_diff_freq, NULL, data_type, DIFF_FREQ, |
| DIFF_FREQ, dataBands, lav_df, coding_scheme_df); |
| |
| min_found = 1; |
| } /* if( min_bits_all == min_bits_df ) */ |
| /*******************************************/ |
| |
| /*******************************************/ |
| if (allowDiffTimeBack_flag) { |
| /*******************************************/ |
| if (!min_found && (min_bits_all == min_bits_dt)) { |
| FDKwriteBits(strm, DIFF_TIME, 1); |
| |
| apply_huff_coding(strm, data_diff_time, NULL, data_type, DIFF_TIME, |
| DIFF_TIME, dataBands, lav_dt, coding_scheme_dt); |
| } |
| /*******************************************/ |
| |
| } /* if( allowDiffTimeBack_flag ) */ |
| |
| /* LSB coding */ |
| if (splitLsb_flag) { |
| apply_lsb_coding(strm, quant_data_lsb, 1, dataBands); |
| } |
| |
| } /* Diff/Huff/LSB coding */ |
| |
| return reset; |
| } |