diff options
Diffstat (limited to 'media/libstagefright/codecs/aacdec/huffspec_fxp.cpp')
-rw-r--r-- | media/libstagefright/codecs/aacdec/huffspec_fxp.cpp | 671 |
1 files changed, 671 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/aacdec/huffspec_fxp.cpp b/media/libstagefright/codecs/aacdec/huffspec_fxp.cpp new file mode 100644 index 0000000..b18c12d --- /dev/null +++ b/media/libstagefright/codecs/aacdec/huffspec_fxp.cpp @@ -0,0 +1,671 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * 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. + * ------------------------------------------------------------------- + */ +/* + + Pathname: huffspec_fxp.c + Funtions: + huffspec_fxp + +------------------------------------------------------------------------------ + REVISION HISTORY + + Description: Modified from original shareware code + + Description: Modified to pass variables by reference to eliminate use + of global variables. + + Description: (1) Modified to keep in-line with PV standards + (2) Eliminated "continue" in if(sect_cb==ZERO_HCB||...) + + Description: (1) Use SectInfo *pSect + (2) Convert 'Real' to 'Int32', float -> fixed-point + (3) move BITS *pInputStream to second parameter + (4) pass in quantSpec and tmp_spec, scratch shared with hufffac + (5) pass in FrameInfo *pLongFrameInfo, eliminate only_long_info + + Description: (1) Eliminate parameter Hcb *book, because of eliminating + function 'hufftab.c', Hcb hcbbook defined as a + const structure in 'hcbtables.h'. + (2) Replace three nested 'for' loops with a for-while loop in + the rescaling part. + (3) Change esc_iquant-> esc_iquant_fxp, call esc_iquant_fxp() + by sfb + + Description: Cleaned up include files. + + Description: Correct definition of stack variable "scale". + It was defined as Int, but it receives an UInt value, + this present a problem when Int is 16 bits and + the sign bit is not interpreted correctly. This does not + shows for 32-bit implementations. This problem manifest itself + as a flipping sign on some spectral coefficients (the ones + multiplied by 0x8000). + + Description: Typecast b_low and b_high to 32-bits before multiplication, this + assures propoer compilation on a 16-bit platform (TI-C55x) + + Description: Modified to speed up decode_huff_cw + + Description: pass codebook index to decode_huff_cw, delete pointer to Huffman + structure + + Description: keep memset to quantSpec, remove memset to temp_spec + + Description: Modified per review comments + + Description: Use Binary tree search in decode_huff_cw_binary + + Description: Modified per review comments + (1) delete unused codes + + Description: (1) Change the interface to decode huffman codeword. + (2) Move the scaling inside the inverse quantization. + (3) Change scaling factor accuracy to 10 bits. + + Description: + (1) delete unused variable max_fac + + Description: Addresses of huffman tables are now found by means of a + switch statement, this solve linking problem when using the + /ropi option (Read-only position independent) for some + compilers + + Who: Date: MM/DD/YYYY + Description: +------------------------------------------------------------------------------ + INPUT AND OUTPUT DEFINITIONS + + Inputs: + pFrameInfo = ptr to structure that holds Information of current Frame, + type FrameInfo + + pInputStream = ptr to structure of bitstream, type BITS + + nsect = number of sections in current Frame, at fs = 44.1 kHz, + range [0, 49] long block, [0,112] short blocks. type Int + + pSect = ptr to structure that holds section codebook and boundary + type SectInfo + + factors[] = array that contains scalefactors for each sfb, type Int16 + + coef[] = array that holds inverse quantized coefs, Int32 QFormat. + + quantSpec[] = array that holds quantized spectral coefs, type Int + + tmp_spec[] = temporary buffer to hold the de-interleaved coefs. + + pLongFrameInfo = ptr to structure that holds long frame info + + Local Stores/Buffers/Pointers Needed: + exptable = array contains the Q15 format data for 2^0, 2^0.25, 2^0.5, + and 2^0.75, type const Int. + + Global Stores/Buffers/Pointers Needed: + None + + Outputs: + + return 0 if decoding properly. + + Pointers and Buffers Modified: + + pInputStream read codeword index and/or sign bits and/or ESC value + + coef contains the newly inverse quantized 1024 spec coefs, + type Int32 Q-format from esc_iquant() + + quantSpec contains decoded quantized 1024 spec coefs, type Int + + tmp_spec contains the de-interleaved version of quantSpec + + qFormat contains Q-Format for each scalefactor band + + Local Stores Modified: + None + + Global Stores Modified: + None + +------------------------------------------------------------------------------ + FUNCTION DESCRIPTION + + This function first reads the section info (codebook and boundary), then + decode the spectral coefficients if a spectral codebook is used. + If necessary, get the sign bits, ESC value or the NEC_pulse data. In case of + short window sequences, the decoded data is de-interleaved before + multiplied by scalefactors. + +------------------------------------------------------------------------------ + REQUIREMENTS + + This function should set the content of the array 'coef' with the inverse + quantized and rescaled value of spectral coefficients. + +------------------------------------------------------------------------------ + REFERENCES + + (1) MPEG-2 NBC Audio Decoder + "This software module was originally developed by AT&T, Dolby + Laboratories, Fraunhofer Gesellschaft IIS in the course of development + of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and + 3. This software module is an implementation of a part of one or more + MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4 + Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio + standards free license to this software module or modifications thereof + for use in hardware or software products claiming conformance to the + MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software + module in hardware or software products are advised that this use may + infringe existing patents. The original developer of this software + module and his/her company, the subsequent editors and their companies, + and ISO/IEC have no liability for use of this software module or + modifications thereof in an implementation. Copyright is not released + for non MPEG-2 NBC/MPEG-4 Audio conforming products.The original + developer retains full right to use the code for his/her own purpose, + assign or donate the code to a third party and to inhibit third party + from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products. + This copyright notice must be included in all copies or derivative + works." + Copyright(c)1996. + + (2) ISO/IEC 14496-3: 1999(E) + Subpart (4) p56 (spectral_data() parsing and decoding) + p26 (Syntax of spectral_data()) + p74-78 (decoding: unpack_idx, get_sign_bits, + getescape, pulse_nc, deinterleave) + p72 (inverse quantization: esc_iquant) + +------------------------------------------------------------------------------ + PSEUDO-CODE + + +------------------------------------------------------------------------------ + RESOURCES USED + When the code is written for a specific target processor the + the resources used should be documented below. + + STACK USAGE: [stack count for this module] + [variable to represent + stack usage for each subroutine called] + + where: [stack usage variable] = stack usage for [subroutine + name] (see [filename].ext) + + DATA MEMORY USED: x words + + PROGRAM MEMORY USED: x words + + CLOCK CYCLES: [cycle count equation for this module] + [variable + used to represent cycle count for each subroutine + called] + + where: [cycle count variable] = cycle count for [subroutine + name] (see [filename].ext) + +------------------------------------------------------------------------------ +*/ + +/*---------------------------------------------------------------------------- +; INCLUDES +----------------------------------------------------------------------------*/ +#include "pv_audio_type_defs.h" +#include "aac_mem_funcs.h" +#include "esc_iquant_scaling.h" +#include "huffman.h" +#include "unpack_idx.h" +#include "pulse_nc.h" +#include "iquant_table.h" +#include "e_huffmanconst.h" + + +#include "pv_normalize.h" + +/*---------------------------------------------------------------------------- +; MACROS +; Define module specific macros here +----------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------- +; DEFINES +; Include all pre-processor statements here. Include conditional +; compile variables also. +----------------------------------------------------------------------------*/ +#define ORDER (3) + +/* + * Format the table is stored in. + */ +#define QTABLE (27) + +/* + * Number of bits for data in a signed 32 bit integer. + */ +#define SIGNED32BITS (31) + +/* + * Round up value for intermediate values obtained from the table + */ +#define ROUND_UP (( ((UInt32) 1) << (QTABLE) )-1) + +/*---------------------------------------------------------------------------- +; LOCAL FUNCTION DEFINITIONS +; Function Prototype declaration +----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- +; LOCAL STORE/BUFFER/POINTER DEFINITIONS +; Variable declaration - defined here and used outside this module +----------------------------------------------------------------------------*/ +const UInt16 exptable[4] = +{ + 0, /* (2^0.00)<<15 (Q10), use zero to signal no scaling required! */ + 19485, /* (2^0.25)<<15 */ + 23171, /* (2^0.50)<<15 */ + 27555 /* (2^0.75)<<15 */ + +}; + + +/*---------------------------------------------------------------------------- +; EXTERNAL FUNCTION REFERENCES +; Declare functions defined elsewhere and referenced in this module +----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- +; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES +; Declare variables used in this module but defined elsewhere +----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- +; FUNCTION CODE +----------------------------------------------------------------------------*/ + +Int huffspec_fxp( + FrameInfo *pFrameInfo, + BITS *pInputStream, + Int nsect, + SectInfo *pSectInfo, + Int factors[], + Int32 coef[], + Int16 quantSpec[], + Int16 tmp_spec[], + const FrameInfo *pLongFrameInfo, + PulseInfo *pPulseInfo, + Int qFormat[]) +{ + /*---------------------------------------------------------------------------- + ; Define all local variables + ----------------------------------------------------------------------------*/ + const Hcb *pHcb; + Int i; + Int sfb; + Int idx_count; + Int sect_cb; /* section codebook */ + Int dim; + Int idx; + Int stop_idx; /* index of 1st coef in next sfb */ + Int sect_start; /* start index of sfb in one section*/ + Int sect_end; /* index of 1st sfb in next section */ + Int *pSfbStart; + Int *pSfb; + Int16 *pQuantSpec; /* probably could be short */ + Int max = 0; + /* rescaling parameters */ + Int nsfb; + Int tot_sfb; + Int fac; + + Int32 *pCoef; /* ptr to coef[], inverse quantized coefs */ + UInt16 scale; + + Int power_scale_div_4; + Int sfbWidth; + + void (*pUnpack_idx)( + Int16 quant_spec[], + Int codeword_indx, + const Hcb *pHuffCodebook, + BITS *pInputStream, + Int *max); + + Int(*pDec_huff_tab)(BITS *) = NULL; + + UInt32 temp; + Int binaryDigits, QFormat; + + /*---------------------------------------------------------------------------- + ; Function body here + ----------------------------------------------------------------------------*/ + + sect_start = 0; + stop_idx = 0; + + /* pSfb: ptr to array that holds stop index of each sfb */ + pSfbStart = pFrameInfo->frame_sfb_top; + + if (pSfbStart == NULL) + { + return (-1); /* error condition */ + } + + pSfb = pSfbStart; + + /* decoding spectral values section by section */ + for (i = nsect; i > 0; i--) + { + /* read the codebook and section length */ + sect_cb = pSectInfo->sect_cb; /* codebook */ + if ((sect_cb > 15) || (sect_cb < 0)) + { + return (-1); /* error condition */ + } + sect_end = pSectInfo->sect_end; /* # of sfbs */ + + if (sect_end < 0) + { + return (-1); /* error condition */ + } + + pSectInfo++; + + /* sect_cb sect_cb - 1 + * ZERO_HCB 1111b + * 1 0000b + * 2 0001b + * 3 0010b + * 4 0011b + * 5 0100b + * 6 0101b + * 7 0110b + * 8 0111b + * 9 1000b + * 10 1001b + * 11 1010b + * 12 1011b + * NOISE_HCB 1100b + * INTENSITY_HCB2 1101b + * INTENSITY_HCB 1110b + * if ( ((sect_cb - 1) & 0xC) == 0xC ) is identical to + * if !((sect_cb == ZERO_HCB) || (sect_cb == NOISE_HCB) || + * (sec_cb == INTENSITY_HCB) || (sect_cb==INTENSITY_HCB2) ) + * use this compare scheme to speed up the execution + */ + + if (((sect_cb - 1) & 0xC) != 0xC) + { + /* decode spec in one section */ + if (sect_cb > BY4BOOKS) + { + dim = DIMENSION_2; /* set codebook dimension */ + } + else + { + dim = DIMENSION_4; + } + + pHcb = &hcbbook_binary[sect_cb]; + + if (sect_cb == ESCBOOK) + { + pUnpack_idx = &unpack_idx_esc; + } + else if (pHcb->signed_cb == FALSE) + { + pUnpack_idx = &unpack_idx_sgn; + } + else + { + pUnpack_idx = &unpack_idx; + } + + + switch (sect_cb) + { + case 1: + pDec_huff_tab = decode_huff_cw_tab1; + break; + case 2: + pDec_huff_tab = decode_huff_cw_tab2; + break; + case 3: + pDec_huff_tab = decode_huff_cw_tab3; + break; + case 4: + pDec_huff_tab = decode_huff_cw_tab4; + break; + case 5: + pDec_huff_tab = decode_huff_cw_tab5; + break; + case 6: + pDec_huff_tab = decode_huff_cw_tab6; + break; + case 7: + pDec_huff_tab = decode_huff_cw_tab7; + break; + case 8: + pDec_huff_tab = decode_huff_cw_tab8; + break; + case 9: + pDec_huff_tab = decode_huff_cw_tab9; + break; + case 10: + pDec_huff_tab = decode_huff_cw_tab10; + break; + case 11: + pDec_huff_tab = decode_huff_cw_tab11; + break; + default: + return (-1); /* error condition */ + } + + /* move ptr to first sfb of current section */ + pQuantSpec = quantSpec + stop_idx; + + /* step through all sfbs in current section */ + for (sfb = sect_start; sfb < sect_end; sfb++) + { + idx_count = *pSfb - stop_idx; + stop_idx = *pSfb++; + + /* decode all coefs for one sfb */ + while ((idx_count > 0) && (idx_count < 1024)) + { + + idx = (*pDec_huff_tab)(pInputStream); + + (*pUnpack_idx)(pQuantSpec, + idx, + pHcb, + pInputStream, + &max); /* unpack idx -> coefs */ + + pQuantSpec += dim; + idx_count -= dim; + + } /* while(idx_count) */ + + } /* for (sfb=sect_start) */ + } + else + { + + /* current section uses ZERO_HCB, NOISE_HCB, etc */ + + /* move sfb pointer to the start sfb of next section */ + pSfb = pSfbStart + sect_end; + /* number of coefs in current section */ + idx_count = *(pSfb - 1) - stop_idx; + + if ((idx_count > 1024) || (idx_count < 0)) + { + return (-1); /* error condition */ + } + + /* + * This memset is necessary in terms of (1) net savings in total + * MIPS and (2) accurate Q-Formats for fft_rx2 + * In case a scalefactor band uses ZERO_HCB, all coefficients of + * that sfb should be zeros. Without this call to memset, the + * coefficients for a ZERO_HCB sfb are the "leftovers" of the + * previous frame, which may not have all zero values. This leads + * to a drastical increase in the cycles consumed by esc_iquant_fxp + * and fft_rx2, which is the most "expensive" function of the + * library. + * This memset also guarantees the Q_Format for sfbs with all zero + * coefficients will be set properly. + * Profiling data on ARM and TMS320C55x proves that there is a net + * gain in total MIPS if a memset is called here. + */ + pv_memset(&quantSpec[stop_idx], + 0, + idx_count * sizeof(quantSpec[0])); + + /* + * This memset is called because pQuantSpec points to tmp_spec + * after deinterleaving + */ + + pv_memset(&tmp_spec[stop_idx], + 0, + idx_count * sizeof(tmp_spec[0])); + + + /* stop_idx is the index of the 1st coef of next section */ + stop_idx = *(pSfb - 1); + + }/* if (sect_cb) */ + + sect_start = sect_end; + + } /* for (i=nsect) */ + + /* noisless coding reconstruction */ + if (pFrameInfo->islong != FALSE) + { + if (pPulseInfo->pulse_data_present == 1) + { + pulse_nc(quantSpec, + pPulseInfo, + pLongFrameInfo, + &max); /* add pulse data */ + } + + pQuantSpec = quantSpec; + + } + else + { + deinterleave(quantSpec, + tmp_spec, + pFrameInfo); + + pQuantSpec = tmp_spec; + } + + + /* inverse quantization, Q_format: Int32 */ + /* rescaling */ + + /* what we can do here is assuming that we already know maxInput for each band, we have to go + though each one of them for re-quant and scaling, and pick the right qFormat to apply to + all spectral coeffs.*/ + + if ((max < 0) || (max > 8192)) /* (8192>>ORDER) == 1024 is the inverseQuantTable size */ + { + return (-1); /* error condition */ + } + else + { + /* Get (max/SPACING) ^ (1/3), in Q Format */ + temp = inverseQuantTable[(max >> ORDER) + 1]; + } + + + /* Round up before shifting down to Q0 */ + temp += ROUND_UP; + + /* shift down to Q0 and multiply by 2 (FACTOR) in one step */ + temp >>= (QTABLE - 1); + + /* Now get max ^ (4/3) in Q0 */ + temp *= max; + + + binaryDigits = 31 - pv_normalize(temp); + + + /* Prevent negative shifts caused by low maximums. */ + if (binaryDigits < (SIGNED32BITS - QTABLE)) + { + binaryDigits = SIGNED32BITS - QTABLE; + } + + QFormat = SIGNED32BITS - binaryDigits; + + /********************/ + tot_sfb = 0; + nsfb = pFrameInfo->sfb_per_win[0]; + pCoef = coef; + + for (i = pFrameInfo->num_win; i > 0; i--) + { + stop_idx = 0; + + for (sfb = 0; sfb < nsfb; sfb++) + { + sfbWidth = pFrameInfo->win_sfb_top[0][sfb] - stop_idx; + + if ((sfbWidth < 0) || (sfbWidth > 1024)) + { + return (-1); /* error condition */ + } + + stop_idx += sfbWidth; + + fac = factors[tot_sfb] - SF_OFFSET; + scale = exptable[fac & 0x3]; + + power_scale_div_4 = fac >> 2; + + power_scale_div_4++; + + qFormat[tot_sfb] = QFormat; + + esc_iquant_scaling(pQuantSpec, + pCoef, + sfbWidth, + QFormat, + scale, + max); + + pQuantSpec += sfbWidth; + qFormat[tot_sfb] -= power_scale_div_4; + pCoef += sfbWidth; + + tot_sfb++; + + } /* for (sfb) */ + } /* for (i) */ + + + /*---------------------------------------------------------------------------- + ; Return status + ----------------------------------------------------------------------------*/ + return SUCCESS; + +} /* huffspec_fxp */ |