1443 lines
41 KiB
C++
1443 lines
41 KiB
C++
/* -----------------------------------------------------------------------------
|
|
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;
|
|
}
|