android / platform / external / aac / 48b330d303727e1f2671f844a1d541d596f6d5da / . / libAACenc / src / quantize.cpp

/* ----------------------------------------------------------------------------------------------------------- | |

Software License for The Fraunhofer FDK AAC Codec Library for Android | |

© Copyright 1995 - 2013 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 Audio Encoder ************************** | |

Initial author: M.Werner | |

contents/description: Quantization | |

******************************************************************************/ | |

#include "quantize.h" | |

#include "aacEnc_rom.h" | |

/***************************************************************************** | |

functionname: FDKaacEnc_quantizeLines | |

description: quantizes spectrum lines | |

returns: | |

input: global gain, number of lines to process, spectral data | |

output: quantized spectrum | |

*****************************************************************************/ | |

static void FDKaacEnc_quantizeLines(INT gain, | |

INT noOfLines, | |

FIXP_DBL *mdctSpectrum, | |

SHORT *quaSpectrum) | |

{ | |

int line; | |

FIXP_DBL k = FL2FXCONST_DBL(-0.0946f + 0.5f)>>16; | |

FIXP_QTD quantizer = FDKaacEnc_quantTableQ[(-gain)&3]; | |

INT quantizershift = ((-gain)>>2)+1; | |

for (line = 0; line < noOfLines; line++) | |

{ | |

FIXP_DBL accu = fMultDiv2(mdctSpectrum[line],quantizer); | |

if (accu < FL2FXCONST_DBL(0.0f)) | |

{ | |

accu=-accu; | |

/* normalize */ | |

INT accuShift = CntLeadingZeros(accu) - 1; /* CountLeadingBits() is not necessary here since test value is always > 0 */ | |

accu <<= accuShift; | |

INT tabIndex = (INT)(accu>>(DFRACT_BITS-2-MANT_DIGITS))&(~MANT_SIZE); | |

INT totalShift = quantizershift-accuShift+1; | |

accu = fMultDiv2(FDKaacEnc_mTab_3_4[tabIndex],FDKaacEnc_quantTableE[totalShift&3]); | |

totalShift = (16-4)-(3*(totalShift>>2)); | |

FDK_ASSERT(totalShift >=0); /* MAX_QUANT_VIOLATION */ | |

accu >>= fixMin(totalShift,DFRACT_BITS-1); | |

quaSpectrum[line] = (SHORT)(-((LONG)(k + accu) >> (DFRACT_BITS-1-16))); | |

} | |

else if(accu > FL2FXCONST_DBL(0.0f)) | |

{ | |

/* normalize */ | |

INT accuShift = CntLeadingZeros(accu) - 1; /* CountLeadingBits() is not necessary here since test value is always > 0 */ | |

accu <<= accuShift; | |

INT tabIndex = (INT)(accu>>(DFRACT_BITS-2-MANT_DIGITS))&(~MANT_SIZE); | |

INT totalShift = quantizershift-accuShift+1; | |

accu = fMultDiv2(FDKaacEnc_mTab_3_4[tabIndex],FDKaacEnc_quantTableE[totalShift&3]); | |

totalShift = (16-4)-(3*(totalShift>>2)); | |

FDK_ASSERT(totalShift >=0); /* MAX_QUANT_VIOLATION */ | |

accu >>= fixMin(totalShift,DFRACT_BITS-1); | |

quaSpectrum[line] = (SHORT)((LONG)(k + accu) >> (DFRACT_BITS-1-16)); | |

} | |

else | |

quaSpectrum[line]=0; | |

} | |

} | |

/***************************************************************************** | |

functionname:iFDKaacEnc_quantizeLines | |

description: iquantizes spectrum lines | |

mdctSpectrum = iquaSpectrum^4/3 *2^(0.25*gain) | |

input: global gain, number of lines to process,quantized spectrum | |

output: spectral data | |

*****************************************************************************/ | |

static void FDKaacEnc_invQuantizeLines(INT gain, | |

INT noOfLines, | |

SHORT *quantSpectrum, | |

FIXP_DBL *mdctSpectrum) | |

{ | |

INT iquantizermod; | |

INT iquantizershift; | |

INT line; | |

iquantizermod = gain&3; | |

iquantizershift = gain>>2; | |

for (line = 0; line < noOfLines; line++) { | |

if(quantSpectrum[line] < 0) { | |

FIXP_DBL accu; | |

INT ex,specExp,tabIndex; | |

FIXP_DBL s,t; | |

accu = (FIXP_DBL) -quantSpectrum[line]; | |

ex = CountLeadingBits(accu); | |

accu <<= ex; | |

specExp = (DFRACT_BITS-1) - ex; | |

FDK_ASSERT(specExp < 14); /* this fails if abs(value) > 8191 */ | |

tabIndex = (INT)(accu>>(DFRACT_BITS-2-MANT_DIGITS))&(~MANT_SIZE); | |

/* calculate "mantissa" ^4/3 */ | |

s = FDKaacEnc_mTab_4_3Elc[tabIndex]; | |

/* get approperiate exponent multiplier for specExp^3/4 combined with scfMod */ | |

t = FDKaacEnc_specExpMantTableCombElc[iquantizermod][specExp]; | |

/* multiply "mantissa" ^4/3 with exponent multiplier */ | |

accu = fMult(s,t); | |

/* get approperiate exponent shifter */ | |

specExp = FDKaacEnc_specExpTableComb[iquantizermod][specExp]-1; /* -1 to avoid overflows in accu */ | |

if ((-iquantizershift-specExp) < 0) | |

accu <<= -(-iquantizershift-specExp); | |

else | |

accu >>= -iquantizershift-specExp; | |

mdctSpectrum[line] = -accu; | |

} | |

else if (quantSpectrum[line] > 0) { | |

FIXP_DBL accu; | |

INT ex,specExp,tabIndex; | |

FIXP_DBL s,t; | |

accu = (FIXP_DBL)(INT)quantSpectrum[line]; | |

ex = CountLeadingBits(accu); | |

accu <<= ex; | |

specExp = (DFRACT_BITS-1) - ex; | |

FDK_ASSERT(specExp < 14); /* this fails if abs(value) > 8191 */ | |

tabIndex = (INT)(accu>>(DFRACT_BITS-2-MANT_DIGITS))&(~MANT_SIZE); | |

/* calculate "mantissa" ^4/3 */ | |

s = FDKaacEnc_mTab_4_3Elc[tabIndex]; | |

/* get approperiate exponent multiplier for specExp^3/4 combined with scfMod */ | |

t = FDKaacEnc_specExpMantTableCombElc[iquantizermod][specExp]; | |

/* multiply "mantissa" ^4/3 with exponent multiplier */ | |

accu = fMult(s,t); | |

/* get approperiate exponent shifter */ | |

specExp = FDKaacEnc_specExpTableComb[iquantizermod][specExp]-1; /* -1 to avoid overflows in accu */ | |

if (( -iquantizershift-specExp) < 0) | |

accu <<= -(-iquantizershift-specExp); | |

else | |

accu >>= -iquantizershift-specExp; | |

mdctSpectrum[line] = accu; | |

} | |

else { | |

mdctSpectrum[line] = FL2FXCONST_DBL(0.0f); | |

} | |

} | |

} | |

/***************************************************************************** | |

functionname: FDKaacEnc_QuantizeSpectrum | |

description: quantizes the entire spectrum | |

returns: | |

input: number of scalefactor bands to be quantized, ... | |

output: quantized spectrum | |

*****************************************************************************/ | |

void FDKaacEnc_QuantizeSpectrum(INT sfbCnt, | |

INT maxSfbPerGroup, | |

INT sfbPerGroup, | |

INT *sfbOffset, | |

FIXP_DBL *mdctSpectrum, | |

INT globalGain, | |

INT *scalefactors, | |

SHORT *quantizedSpectrum) | |

{ | |

INT sfbOffs,sfb; | |

/* in FDKaacEnc_quantizeLines quaSpectrum is calculated with: | |

spec^(3/4) * 2^(-3/16*QSS) * 2^(3/4*scale) + k | |

simplify scaling calculation and reduce QSS before: | |

spec^(3/4) * 2^(-3/16*(QSS - 4*scale)) */ | |

for(sfbOffs=0;sfbOffs<sfbCnt;sfbOffs+=sfbPerGroup) | |

for (sfb = 0; sfb < maxSfbPerGroup; sfb++) | |

{ | |

INT scalefactor = scalefactors[sfbOffs+sfb] ; | |

FDKaacEnc_quantizeLines(globalGain - scalefactor, /* QSS */ | |

sfbOffset[sfbOffs+sfb+1] - sfbOffset[sfbOffs+sfb], | |

mdctSpectrum + sfbOffset[sfbOffs+sfb], | |

quantizedSpectrum + sfbOffset[sfbOffs+sfb]); | |

} | |

} | |

/***************************************************************************** | |

functionname: FDKaacEnc_calcSfbDist | |

description: calculates distortion of quantized values | |

returns: distortion | |

input: gain, number of lines to process, spectral data | |

output: | |

*****************************************************************************/ | |

FIXP_DBL FDKaacEnc_calcSfbDist(FIXP_DBL *mdctSpectrum, | |

SHORT *quantSpectrum, | |

INT noOfLines, | |

INT gain | |

) | |

{ | |

INT i,scale; | |

FIXP_DBL xfsf; | |

FIXP_DBL diff; | |

FIXP_DBL invQuantSpec; | |

xfsf = FL2FXCONST_DBL(0.0f); | |

for (i=0; i<noOfLines; i++) { | |

/* quantization */ | |

FDKaacEnc_quantizeLines(gain, | |

1, | |

&mdctSpectrum[i], | |

&quantSpectrum[i]); | |

if (fAbs(quantSpectrum[i])>MAX_QUANT) { | |

return FL2FXCONST_DBL(0.0f); | |

} | |

/* inverse quantization */ | |

FDKaacEnc_invQuantizeLines(gain,1,&quantSpectrum[i],&invQuantSpec); | |

/* dist */ | |

diff = fixp_abs(fixp_abs(invQuantSpec) - fixp_abs(mdctSpectrum[i]>>1)); | |

scale = CountLeadingBits(diff); | |

diff = scaleValue(diff, scale); | |

diff = fPow2(diff); | |

scale = fixMin(2*(scale-1), DFRACT_BITS-1); | |

diff = scaleValue(diff, -scale); | |

xfsf = xfsf + diff; | |

} | |

xfsf = CalcLdData(xfsf); | |

return xfsf; | |

} | |

/***************************************************************************** | |

functionname: FDKaacEnc_calcSfbQuantEnergyAndDist | |

description: calculates energy and distortion of quantized values | |

returns: | |

input: gain, number of lines to process, quantized spectral data, | |

spectral data | |

output: energy, distortion | |

*****************************************************************************/ | |

void FDKaacEnc_calcSfbQuantEnergyAndDist(FIXP_DBL *mdctSpectrum, | |

SHORT *quantSpectrum, | |

INT noOfLines, | |

INT gain, | |

FIXP_DBL *en, | |

FIXP_DBL *dist) | |

{ | |

INT i,scale; | |

FIXP_DBL invQuantSpec; | |

FIXP_DBL diff; | |

FIXP_DBL energy = FL2FXCONST_DBL(0.0f); | |

FIXP_DBL distortion = FL2FXCONST_DBL(0.0f); | |

for (i=0; i<noOfLines; i++) { | |

if (fAbs(quantSpectrum[i])>MAX_QUANT) { | |

*en = FL2FXCONST_DBL(0.0f); | |

*dist = FL2FXCONST_DBL(0.0f); | |

return; | |

} | |

/* inverse quantization */ | |

FDKaacEnc_invQuantizeLines(gain,1,&quantSpectrum[i],&invQuantSpec); | |

/* energy */ | |

energy += fPow2(invQuantSpec); | |

/* dist */ | |

diff = fixp_abs(fixp_abs(invQuantSpec) - fixp_abs(mdctSpectrum[i]>>1)); | |

scale = CountLeadingBits(diff); | |

diff = scaleValue(diff, scale); | |

diff = fPow2(diff); | |

scale = fixMin(2*(scale-1), DFRACT_BITS-1); | |

diff = scaleValue(diff, -scale); | |

distortion += diff; | |

} | |

*en = CalcLdData(energy)+FL2FXCONST_DBL(0.03125f); | |

*dist = CalcLdData(distortion); | |

} | |