diff options
author | Fraunhofer IIS FDK <audio-fdk@iis.fraunhofer.de> | 2018-02-26 20:17:00 +0100 |
---|---|---|
committer | Jean-Michel Trivi <jmtrivi@google.com> | 2018-04-19 11:21:15 -0700 |
commit | 6cfabd35363c3ef5e3b209b867169a500b3ccc3c (patch) | |
tree | 01c0a19f2735e8b5d2407555fe992d4230d089eb /libAACdec/src/usacdec_lpc.cpp | |
parent | 6288a1e34c4dede4c2806beb1736ece6580558c7 (diff) | |
download | fdk-aac-6cfabd35363c3ef5e3b209b867169a500b3ccc3c.tar.gz fdk-aac-6cfabd35363c3ef5e3b209b867169a500b3ccc3c.tar.bz2 fdk-aac-6cfabd35363c3ef5e3b209b867169a500b3ccc3c.zip |
Upgrade to FDKv2
Bug: 71430241
Test: CTS DecoderTest and DecoderTestAacDrc
original-Change-Id: Iaa20f749b8a04d553b20247cfe1a8930ebbabe30
Apply clang-format also on header files.
original-Change-Id: I14de1ef16bbc79ec0283e745f98356a10efeb2e4
Fixes for MPEG-D DRC
original-Change-Id: If1de2d74bbbac84b3f67de3b88b83f6a23b8a15c
Catch unsupported tw_mdct at an early stage
original-Change-Id: Ied9dd00d754162a0e3ca1ae3e6b854315d818afe
Fixing PVC transition frames
original-Change-Id: Ib75725abe39252806c32d71176308f2c03547a4e
Move qmf bands sanity check
original-Change-Id: Iab540c3013c174d9490d2ae100a4576f51d8dbc4
Initialize scaling variable
original-Change-Id: I3c4087101b70e998c71c1689b122b0d7762e0f9e
Add 16 qmf band configuration to getSlotNrgHQ()
original-Change-Id: I49a5d30f703a1b126ff163df9656db2540df21f1
Always apply byte alignment at the end of the AudioMuxElement
original-Change-Id: I42d560287506d65d4c3de8bfe3eb9a4ebeb4efc7
Setup SBR element only if no parse error exists
original-Change-Id: I1915b73704bc80ab882b9173d6bec59cbd073676
Additional array index check in HCR
original-Change-Id: I18cc6e501ea683b5009f1bbee26de8ddd04d8267
Fix fade-in index selection in concealment module
original-Change-Id: Ibf802ed6ed8c05e9257e1f3b6d0ac1162e9b81c1
Enable explicit backward compatible parser for AAC_LD
original-Change-Id: I27e9c678dcb5d40ed760a6d1e06609563d02482d
Skip spatial specific config in explicit backward compatible ASC
original-Change-Id: Iff7cc365561319e886090cedf30533f562ea4d6e
Update flags description in decoder API
original-Change-Id: I9a5b4f8da76bb652f5580cbd3ba9760425c43830
Add QMF domain reset function
original-Change-Id: I4f89a8a2c0277d18103380134e4ed86996e9d8d6
DRC upgrade v2.1.0
original-Change-Id: I5731c0540139dab220094cd978ef42099fc45b74
Fix integer overflow in sqrtFixp_lookup()
original-Change-Id: I429a6f0d19aa2cc957e0f181066f0ca73968c914
Fix integer overflow in invSqrtNorm2()
original-Change-Id: I84de5cbf9fb3adeb611db203fe492fabf4eb6155
Fix integer overflow in GenerateRandomVector()
original-Change-Id: I3118a641008bd9484d479e5b0b1ee2b5d7d44d74
Fix integer overflow in adjustTimeSlot_EldGrid()
original-Change-Id: I29d503c247c5c8282349b79df940416a512fb9d5
Fix integer overflow in FDKsbrEnc_codeEnvelope()
original-Change-Id: I6b34b61ebb9d525b0c651ed08de2befc1f801449
Follow-up on: Fix integer overflow in adjustTimeSlot_EldGrid()
original-Change-Id: I6f8f578cc7089e5eb7c7b93e580b72ca35ad689a
Fix integer overflow in get_pk_v2()
original-Change-Id: I63375bed40d45867f6eeaa72b20b1f33e815938c
Fix integer overflow in Syn_filt_zero()
original-Change-Id: Ie0c02fdfbe03988f9d3b20d10cd9fe4c002d1279
Fix integer overflow in CFac_CalcFacSignal()
original-Change-Id: Id2d767c40066c591b51768e978eb8af3b803f0c5
Fix integer overflow in FDKaacEnc_FDKaacEnc_calcPeNoAH()
original-Change-Id: Idcbd0f4a51ae2550ed106aa6f3d678d1f9724841
Fix integer overflow in sbrDecoder_calculateGainVec()
original-Change-Id: I7081bcbe29c5cede9821b38d93de07c7add2d507
Fix integer overflow in CLpc_SynthesisLattice()
original-Change-Id: I4a95ddc18de150102352d4a1845f06094764c881
Fix integer overflow in Pred_Lt4()
original-Change-Id: I4dbd012b2de7d07c3e70a47b92e3bfae8dbc750a
Fix integer overflow in FDKsbrEnc_InitSbrFastTransientDetector()
original-Change-Id: I788cbec1a4a00f44c2f3a72ad7a4afa219807d04
Fix unsigned integer overflow in FDKaacEnc_WriteBitstream()
original-Change-Id: I68fc75166e7d2cd5cd45b18dbe3d8c2a92f1822a
Fix unsigned integer overflow in FDK_MetadataEnc_Init()
original-Change-Id: Ie8d025f9bcdb2442c704bd196e61065c03c10af4
Fix overflow in pseudo random number generators
original-Change-Id: I3e2551ee01356297ca14e3788436ede80bd5513c
Fix unsigned integer overflow in sbrDecoder_Parse()
original-Change-Id: I3f231b2f437e9c37db4d5b964164686710eee971
Fix unsigned integer overflow in longsub()
original-Change-Id: I73c2bc50415cac26f1f5a29e125bbe75f9180a6e
Fix unsigned integer overflow in CAacDecoder_DecodeFrame()
original-Change-Id: Ifce2db4b1454b46fa5f887e9d383f1cc43b291e4
Fix overflow at CLpdChannelStream_Read()
original-Change-Id: Idb9d822ce3a4272e4794b643644f5434e2d4bf3f
Fix unsigned integer overflow in Hcr_State_BODY_SIGN_ESC__ESC_WORD()
original-Change-Id: I1ccf77c0015684b85534c5eb97162740a870b71c
Fix unsigned integer overflow in UsacConfig_Parse()
original-Change-Id: Ie6d27f84b6ae7eef092ecbff4447941c77864d9f
Fix unsigned integer overflow in aacDecoder_drcParse()
original-Change-Id: I713f28e883eea3d70b6fa56a7b8f8c22bcf66ca0
Fix unsigned integer overflow in aacDecoder_drcReadCompression()
original-Change-Id: Ia34dfeb88c4705c558bce34314f584965cafcf7a
Fix unsigned integer overflow in CDataStreamElement_Read()
original-Change-Id: Iae896cc1d11f0a893d21be6aa90bd3e60a2c25f0
Fix unsigned integer overflow in transportDec_AdjustEndOfAccessUnit()
original-Change-Id: I64cf29a153ee784bb4a16fdc088baabebc0007dc
Fix unsigned integer overflow in transportDec_GetAuBitsRemaining()
original-Change-Id: I975b3420faa9c16a041874ba0db82e92035962e4
Fix unsigned integer overflow in extractExtendedData()
original-Change-Id: I2a59eb09e2053cfb58dfb75fcecfad6b85a80a8f
Fix signed integer overflow in CAacDecoder_ExtPayloadParse()
original-Change-Id: I4ad5ca4e3b83b5d964f1c2f8c5e7b17c477c7929
Fix unsigned integer overflow in CAacDecoder_DecodeFrame()
original-Change-Id: I29a39df77d45c52a0c9c5c83c1ba81f8d0f25090
Follow-up on: Fix integer overflow in CLpc_SynthesisLattice()
original-Change-Id: I8fb194ffc073a3432a380845be71036a272d388f
Fix signed integer overflow in _interpolateDrcGain()
original-Change-Id: I879ec9ab14005069a7c47faf80e8bc6e03d22e60
Fix unsigned integer overflow in FDKreadBits()
original-Change-Id: I1f47a6a8037ff70375aa8844947d5681bb4287ad
Fix unsigned integer overflow in FDKbyteAlign()
original-Change-Id: Id5f3a11a0c9e50fc6f76ed6c572dbd4e9f2af766
Fix unsigned integer overflow in FDK_get32()
original-Change-Id: I9d33b8e97e3d38cbb80629cb859266ca0acdce96
Fix unsigned integer overflow in FDK_pushBack()
original-Change-Id: Ic87f899bc8c6acf7a377a8ca7f3ba74c3a1e1c19
Fix unsigned integer overflow in FDK_pushForward()
original-Change-Id: I3b754382f6776a34be1602e66694ede8e0b8effc
Fix unsigned integer overflow in ReadPsData()
original-Change-Id: I25361664ba8139e32bbbef2ca8c106a606ce9c37
Fix signed integer overflow in E_UTIL_residu()
original-Change-Id: I8c3abd1f437ee869caa8fb5903ce7d3d641b6aad
REVERT: Follow-up on: Integer overflow in CLpc_SynthesisLattice().
original-Change-Id: I3d340099acb0414795c8dfbe6362bc0a8f045f9b
Follow-up on: Fix integer overflow in CLpc_SynthesisLattice()
original-Change-Id: I4aedb8b3a187064e9f4d985175aa55bb99cc7590
Follow-up on: Fix unsigned integer overflow in aacDecoder_drcParse()
original-Change-Id: I2aa2e13916213bf52a67e8b0518e7bf7e57fb37d
Fix integer overflow in acelp
original-Change-Id: Ie6390c136d84055f8b728aefbe4ebef6e029dc77
Fix unsigned integer overflow in aacDecoder_UpdateBitStreamCounters()
original-Change-Id: I391ffd97ddb0b2c184cba76139bfb356a3b4d2e2
Adjust concealment default settings
original-Change-Id: I6a95db935a327c47df348030bcceafcb29f54b21
Saturate estimatedStartPos
original-Change-Id: I27be2085e0ae83ec9501409f65e003f6bcba1ab6
Negative shift exponent in _interpolateDrcGain()
original-Change-Id: I18edb26b26d002aafd5e633d4914960f7a359c29
Negative shift exponent in calculateICC()
original-Change-Id: I3dcd2ae98d2eb70ee0d59750863cbb2a6f4f8aba
Too large shift exponent in FDK_put()
original-Change-Id: Ib7d9aaa434d2d8de4a13b720ca0464b31ca9b671
Too large shift exponent in CalcInvLdData()
original-Change-Id: I43e6e78d4cd12daeb1dcd5d82d1798bdc2550262
Member access within null pointer of type SBR_CHANNEL
original-Change-Id: Idc5e4ea8997810376d2f36bbdf628923b135b097
Member access within null pointer of type CpePersistentData
original-Change-Id: Ib6c91cb0d37882768e5baf63324e429589de0d9d
Member access within null pointer FDKaacEnc_psyMain()
original-Change-Id: I7729b7f4479970531d9dc823abff63ca52e01997
Member access within null pointer FDKaacEnc_GetPnsParam()
original-Change-Id: I9aa3b9f3456ae2e0f7483dbd5b3dde95fc62da39
Member access within null pointer FDKsbrEnc_EnvEncodeFrame()
original-Change-Id: I67936f90ea714e90b3e81bc0dd1472cc713eb23a
Add HCR sanity check
original-Change-Id: I6c1d9732ebcf6af12f50b7641400752f74be39f7
Fix memory issue for HBE edge case with 8:3 SBR
original-Change-Id: I11ea58a61e69fbe8bf75034b640baee3011e63e9
Additional SBR parametrization sanity check for ELD
original-Change-Id: Ie26026fbfe174c2c7b3691f6218b5ce63e322140
Add MPEG-D DRC channel layout check
original-Change-Id: Iea70a74f171b227cce636a9eac4ba662777a2f72
Additional out-of-bounds checks in MPEG-D DRC
original-Change-Id: Ife4a8c3452c6fde8a0a09e941154a39a769777d4
Change-Id: Ic63cb2f628720f54fe9b572b0cb528e2599c624e
Diffstat (limited to 'libAACdec/src/usacdec_lpc.cpp')
-rw-r--r-- | libAACdec/src/usacdec_lpc.cpp | 1194 |
1 files changed, 1194 insertions, 0 deletions
diff --git a/libAACdec/src/usacdec_lpc.cpp b/libAACdec/src/usacdec_lpc.cpp new file mode 100644 index 0000000..271463f --- /dev/null +++ b/libAACdec/src/usacdec_lpc.cpp @@ -0,0 +1,1194 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Matthias Hildenbrand, Manuel Jander + + Description: USAC LPC/AVQ decode + +*******************************************************************************/ + +#include "usacdec_lpc.h" + +#include "usacdec_rom.h" +#include "FDK_trigFcts.h" + +#define NQ_MAX 36 + +/* + * Helper functions. + */ + +/** + * \brief Read unary code. + * \param hBs bitstream handle as data source. + * \return decoded value. + */ +static int get_vlclbf(HANDLE_FDK_BITSTREAM hBs) { + int result = 0; + + while (FDKreadBits(hBs, 1) && result <= NQ_MAX) { + result++; + } + return result; +} + +/** + * \brief Read bit count limited unary code. + * \param hBs bitstream handle as data source + * \param n max amount of bits to be read. + * \return decoded value. + */ +static int get_vlclbf_n(HANDLE_FDK_BITSTREAM hBs, int n) { + int result = 0; + + while (FDKreadBits(hBs, 1)) { + result++; + n--; + if (n <= 0) { + break; + } + } + + return result; +} + +/* + * Algebraic Vector Quantizer + */ + +/* ZF_SCALE must be greater than (number of FIXP_ZF)/2 + because the loss of precision caused by fPow2Div2 in RE8_PPV() */ +//#define ZF_SCALE ((NQ_MAX-3)>>1) +#define ZF_SCALE ((DFRACT_BITS / 2)) +#define FIXP_ZF FIXP_DBL +#define INT2ZF(x, s) (FIXP_ZF)((x) << (ZF_SCALE - (s))) +#define ZF2INT(x) (INT)((x) >> ZF_SCALE) + +/* 1.0 in ZF format format */ +#define ONEZF ((FIXP_ZF)INT2ZF(1, 0)) + +/* static */ +void nearest_neighbor_2D8(FIXP_ZF x[8], int y[8]) { + FIXP_ZF s, em, e[8]; + int i, j, sum; + + /* round x into 2Z^8 i.e. compute y=(y1,...,y8) such that yi = 2[xi/2] + where [.] is the nearest integer operator + in the mean time, compute sum = y1+...+y8 + */ + sum = 0; + for (i = 0; i < 8; i++) { + FIXP_ZF tmp; + /* round to ..., -2, 0, 2, ... ([-1..1[ --> 0) */ + if (x[i] < (FIXP_ZF)0) { + tmp = ONEZF - x[i]; + y[i] = -2 * ((ZF2INT(tmp)) >> 1); + } else { + tmp = ONEZF + x[i]; + y[i] = 2 * ((ZF2INT(tmp)) >> 1); + } + sum += y[i]; + } + /* check if y1+...+y8 is a multiple of 4 + if not, y is not round xj in the wrong way where j is defined by + j = arg max_i | xi -yi| + (this is called the Wagner rule) + */ + if (sum % 4) { + /* find j = arg max_i | xi -yi| */ + em = (FIXP_SGL)0; + j = 0; + for (i = 0; i < 8; i++) { + /* compute ei = xi-yi */ + e[i] = x[i] - INT2ZF(y[i], 0); + } + for (i = 0; i < 8; i++) { + /* compute |ei| = | xi-yi | */ + if (e[i] < (FIXP_ZF)0) { + s = -e[i]; + } else { + s = e[i]; + } + /* check if |ei| is maximal, if so, set j=i */ + if (em < s) { + em = s; + j = i; + } + } + /* round xj in the "wrong way" */ + if (e[j] < (FIXP_ZF)0) { + y[j] -= 2; + } else { + y[j] += 2; + } + } +} + +/*-------------------------------------------------------------- + RE8_PPV(x,y) + NEAREST NEIGHBOR SEARCH IN INFINITE LATTICE RE8 + the algorithm is based on the definition of RE8 as + RE8 = (2D8) U (2D8+[1,1,1,1,1,1,1,1]) + it applies the coset decoding of Sloane and Conway + (i) x: point in R^8 in 32-ZF_SCALE.ZF_SCALE format + (o) y: point in RE8 (8-dimensional integer vector) + -------------------------------------------------------------- +*/ +/* static */ +void RE8_PPV(FIXP_ZF x[], SHORT y[], int r) { + int i, y0[8], y1[8]; + FIXP_ZF x1[8], tmp; + FIXP_DBL e; + + /* find the nearest neighbor y0 of x in 2D8 */ + nearest_neighbor_2D8(x, y0); + /* find the nearest neighbor y1 of x in 2D8+(1,...,1) (by coset decoding) */ + for (i = 0; i < 8; i++) { + x1[i] = x[i] - ONEZF; + } + nearest_neighbor_2D8(x1, y1); + for (i = 0; i < 8; i++) { + y1[i] += 1; + } + + /* compute e0=||x-y0||^2 and e1=||x-y1||^2 */ + e = (FIXP_DBL)0; + for (i = 0; i < 8; i++) { + tmp = x[i] - INT2ZF(y0[i], 0); + e += fPow2Div2( + tmp << r); /* shift left to ensure that no fract part bits get lost. */ + tmp = x[i] - INT2ZF(y1[i], 0); + e -= fPow2Div2(tmp << r); + } + /* select best candidate y0 or y1 to minimize distortion */ + if (e < (FIXP_DBL)0) { + for (i = 0; i < 8; i++) { + y[i] = y0[i]; + } + } else { + for (i = 0; i < 8; i++) { + y[i] = y1[i]; + } + } +} + +/* table look-up of unsigned value: find i where index >= table[i] + Note: range must be >= 2, index must be >= table[0] */ +static int table_lookup(const USHORT *table, unsigned int index, int range) { + int i; + + for (i = 4; i < range; i += 4) { + if (index < table[i]) { + break; + } + } + if (i > range) { + i = range; + } + + if (index < table[i - 2]) { + i -= 2; + } + if (index < table[i - 1]) { + i--; + } + i--; + + return (i); /* index >= table[i] */ +} + +/*-------------------------------------------------------------------------- + re8_decode_rank_of_permutation(rank, xs, x) + DECODING OF THE RANK OF THE PERMUTATION OF xs + (i) rank: index (rank) of a permutation + (i) xs: signed leader in RE8 (8-dimensional integer vector) + (o) x: point in RE8 (8-dimensional integer vector) + -------------------------------------------------------------------------- + */ +static void re8_decode_rank_of_permutation(int rank, int *xs, SHORT x[8]) { + INT a[8], w[8], B, fac, fac_B, target; + int i, j; + + /* --- pre-processing based on the signed leader xs --- + - compute the alphabet a=[a[0] ... a[q-1]] of x (q elements) + such that a[0]!=...!=a[q-1] + it is assumed that xs is sorted in the form of a signed leader + which can be summarized in 2 requirements: + a) |xs[0]| >= |xs[1]| >= |xs[2]| >= ... >= |xs[7]| + b) if |xs[i]|=|xs[i-1]|, xs[i]>=xs[i+1] + where |.| indicates the absolute value operator + - compute q (the number of symbols in the alphabet) + - compute w[0..q-1] where w[j] counts the number of occurences of + the symbol a[j] in xs + - compute B = prod_j=0..q-1 (w[j]!) where .! is the factorial */ + /* xs[i], xs[i-1] and ptr_w/a*/ + j = 0; + w[j] = 1; + a[j] = xs[0]; + B = 1; + for (i = 1; i < 8; i++) { + if (xs[i] != xs[i - 1]) { + j++; + w[j] = 1; + a[j] = xs[i]; + } else { + w[j]++; + B *= w[j]; + } + } + + /* --- actual rank decoding --- + the rank of x (where x is a permutation of xs) is based on + Schalkwijk's formula + it is given by rank=sum_{k=0..7} (A_k * fac_k/B_k) + the decoding of this rank is sequential and reconstructs x[0..7] + element by element from x[0] to x[7] + [the tricky part is the inference of A_k for each k...] + */ + + if (w[0] == 8) { + for (i = 0; i < 8; i++) { + x[i] = a[0]; /* avoid fac of 40320 */ + } + } else { + target = rank * B; + fac_B = 1; + /* decode x element by element */ + for (i = 0; i < 8; i++) { + fac = fac_B * fdk_dec_tab_factorial[i]; /* fac = 1..5040 */ + j = -1; + do { + target -= w[++j] * fac; + } while (target >= 0); /* max of 30 tests / SV */ + x[i] = a[j]; + /* update rank, denominator B (B_k) and counter w[j] */ + target += w[j] * fac; /* target = fac_B*B*rank */ + fac_B *= w[j]; + w[j]--; + } + } +} + +/*-------------------------------------------------------------------------- + re8_decode_base_index(n, I, y) + DECODING OF AN INDEX IN Qn (n=0,2,3 or 4) + (i) n: codebook number (*n is an integer defined in {0,2,3,4}) + (i) I: index of c (pointer to unsigned 16-bit word) + (o) y: point in RE8 (8-dimensional integer vector) + note: the index I is defined as a 32-bit word, but only + 16 bits are required (long can be replaced by unsigned integer) + -------------------------------------------------------------------------- + */ +static void re8_decode_base_index(int *n, UINT index, SHORT y[8]) { + int i, im, t, sign_code, ka, ks, rank, leader[8]; + + if (*n < 2) { + for (i = 0; i < 8; i++) { + y[i] = 0; + } + } else { + // index = (unsigned int)*I; + /* search for the identifier ka of the absolute leader (table-lookup) + Q2 is a subset of Q3 - the two cases are considered in the same branch + */ + switch (*n) { + case 2: + case 3: + i = table_lookup(fdk_dec_I3, index, NB_LDQ3); + ka = fdk_dec_A3[i]; + break; + case 4: + i = table_lookup(fdk_dec_I4, index, NB_LDQ4); + ka = fdk_dec_A4[i]; + break; + default: + FDK_ASSERT(0); + return; + } + /* reconstruct the absolute leader */ + for (i = 0; i < 8; i++) { + leader[i] = fdk_dec_Da[ka][i]; + } + /* search for the identifier ks of the signed leader (table look-up) + (this search is focused based on the identifier ka of the absolute + leader)*/ + t = fdk_dec_Ia[ka]; + im = fdk_dec_Ns[ka]; + ks = table_lookup(fdk_dec_Is + t, index, im); + + /* reconstruct the signed leader from its sign code */ + sign_code = 2 * fdk_dec_Ds[t + ks]; + for (i = 7; i >= 0; i--) { + leader[i] *= (1 - (sign_code & 2)); + sign_code >>= 1; + } + + /* compute and decode the rank of the permutation */ + rank = index - fdk_dec_Is[t + ks]; /* rank = index - cardinality offset */ + + re8_decode_rank_of_permutation(rank, leader, y); + } + return; +} + +/* re8_y2k(y,m,k) + VORONOI INDEXING (INDEX DECODING) k -> y + (i) k: Voronoi index k[0..7] + (i) m: Voronoi modulo (m = 2^r = 1<<r, where r is integer >=2) + (i) r: Voronoi order (m = 2^r = 1<<r, where r is integer >=2) + (o) y: 8-dimensional point y[0..7] in RE8 + */ +static void re8_k2y(int *k, int r, SHORT *y) { + int i, tmp, sum; + SHORT v[8]; + FIXP_ZF zf[8]; + + FDK_ASSERT(r <= ZF_SCALE); + + /* compute y = k M and z=(y-a)/m, where + M = [4 ] + [2 2 ] + [| \ ] + [2 2 ] + [1 1 _ 1 1] + a=(2,0,...,0) + m = 1<<r + */ + for (i = 0; i < 8; i++) { + y[i] = k[7]; + } + zf[7] = INT2ZF(y[7], r); + sum = 0; + for (i = 6; i >= 1; i--) { + tmp = 2 * k[i]; + sum += tmp; + y[i] += tmp; + zf[i] = INT2ZF(y[i], r); + } + y[0] += (4 * k[0] + sum); + zf[0] = INT2ZF(y[0] - 2, r); + /* find nearest neighbor v of z in infinite RE8 */ + RE8_PPV(zf, v, r); + /* compute y -= m v */ + for (i = 0; i < 8; i++) { + y[i] -= (SHORT)(v[i] << r); + } +} + +/*-------------------------------------------------------------------------- + RE8_dec(n, I, k, y) + MULTI-RATE INDEXING OF A POINT y in THE LATTICE RE8 (INDEX DECODING) + (i) n: codebook number (*n is an integer defined in {0,2,3,4,..,n_max}). n_max + = 36 (i) I: index of c (pointer to unsigned 16-bit word) (i) k: index of v + (8-dimensional vector of binary indices) = Voronoi index (o) y: point in RE8 + (8-dimensional integer vector) note: the index I is defined as a 32-bit word, + but only 16 bits are required (long can be replaced by unsigned integer) + + return 0 on success, -1 on error. + -------------------------------------------------------------------------- + */ +static int RE8_dec(int n, int I, int *k, FIXP_DBL *y) { + SHORT v[8]; + SHORT _y[8]; + UINT r; + int i; + + /* Check bound of codebook qn */ + if (n > NQ_MAX) { + return -1; + } + + /* decode the sub-indices I and kv[] according to the codebook number n: + if n=0,2,3,4, decode I (no Voronoi extension) + if n>4, Voronoi extension is used, decode I and kv[] */ + if (n <= 4) { + re8_decode_base_index(&n, I, _y); + for (i = 0; i < 8; i++) { + y[i] = (LONG)_y[i]; + } + } else { + /* compute the Voronoi modulo m = 2^r where r is extension order */ + r = ((n - 3) >> 1); + + while (n > 4) { + n -= 2; + } + /* decode base codebook index I into c (c is an element of Q3 or Q4) + [here c is stored in y to save memory] */ + re8_decode_base_index(&n, I, _y); + /* decode Voronoi index k[] into v */ + re8_k2y(k, r, v); + /* reconstruct y as y = m c + v (with m=2^r, r integer >=1) */ + for (i = 0; i < 8; i++) { + y[i] = (LONG)((_y[i] << r) + v[i]); + } + } + return 0; +} + +/**************************/ +/* start LPC decode stuff */ +/**************************/ +//#define M 16 +#define FREQ_MAX 6400.0f +#define FREQ_DIV 400.0f +#define LSF_GAP 50.0f + +/** + * \brief calculate inverse weighting factor and add non-weighted residual + * LSF vector to first stage LSF approximation + * \param lsfq first stage LSF approximation values. + * \param xq weighted residual LSF vector + * \param nk_mode code book number coding mode. + */ +static void lsf_weight_2st(FIXP_LPC *lsfq, FIXP_DBL *xq, int nk_mode) { + FIXP_LPC d[M_LP_FILTER_ORDER + 1]; + FIXP_SGL factor; + LONG w; /* inverse weight factor */ + int i; + + /* compute lsf distance */ + d[0] = lsfq[0]; + d[M_LP_FILTER_ORDER] = + FL2FXCONST_LPC(FREQ_MAX / (1 << LSF_SCALE)) - lsfq[M_LP_FILTER_ORDER - 1]; + for (i = 1; i < M_LP_FILTER_ORDER; i++) { + d[i] = lsfq[i] - lsfq[i - 1]; + } + + switch (nk_mode) { + case 0: + factor = FL2FXCONST_SGL(2.0f * 60.0f / FREQ_DIV); + break; /* abs */ + case 1: + factor = FL2FXCONST_SGL(2.0f * 65.0f / FREQ_DIV); + break; /* mid */ + case 2: + factor = FL2FXCONST_SGL(2.0f * 64.0f / FREQ_DIV); + break; /* rel1 */ + default: + factor = FL2FXCONST_SGL(2.0f * 63.0f / FREQ_DIV); + break; /* rel2 */ + } + /* add non-weighted residual LSF vector to LSF1st */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + w = (LONG)fMultDiv2(factor, sqrtFixp(fMult(d[i], d[i + 1]))); + lsfq[i] = fAddSaturate(lsfq[i], FX_DBL2FX_LPC((FIXP_DBL)(w * (LONG)xq[i]))); + } + + return; +} + +/** + * \brief decode nqn amount of code book numbers. These values determine the + * amount of following bits for nqn AVQ RE8 vectors. + * \param nk_mode quantization mode. + * \param nqn amount code book number to read. + * \param qn pointer to output buffer to hold decoded code book numbers qn. + */ +static void decode_qn(HANDLE_FDK_BITSTREAM hBs, int nk_mode, int nqn, + int qn[]) { + int n; + + if (nk_mode == 1) { /* nk mode 1 */ + /* Unary code for mid LPC1/LPC3 */ + /* Q0=0, Q2=10, Q3=110, ... */ + for (n = 0; n < nqn; n++) { + qn[n] = get_vlclbf(hBs); + if (qn[n] > 0) { + qn[n]++; + } + } + } else { /* nk_mode 0, 3 and 2 */ + /* 2 bits to specify Q2,Q3,Q4,ext */ + for (n = 0; n < nqn; n++) { + qn[n] = 2 + FDKreadBits(hBs, 2); + } + if (nk_mode == 2) { + /* Unary code for rel LPC1/LPC3 */ + /* Q0 = 0, Q5=10, Q6=110, ... */ + for (n = 0; n < nqn; n++) { + if (qn[n] > 4) { + qn[n] = get_vlclbf(hBs); + if (qn[n] > 0) qn[n] += 4; + } + } + } else { /* nk_mode == (0 and 3) */ + /* Unary code for abs and rel LPC0/LPC2 */ + /* Q5 = 0, Q6=10, Q0=110, Q7=1110, ... */ + for (n = 0; n < nqn; n++) { + if (qn[n] > 4) { + qn[n] = get_vlclbf(hBs); + switch (qn[n]) { + case 0: + qn[n] = 5; + break; + case 1: + qn[n] = 6; + break; + case 2: + qn[n] = 0; + break; + default: + qn[n] += 4; + break; + } + } + } + } + } +} + +/** + * \brief reorder LSF coefficients to minimum distance. + * \param lsf pointer to buffer containing LSF coefficients and where reordered + * LSF coefficients will be stored into, scaled by LSF_SCALE. + * \param min_dist min distance scaled by LSF_SCALE + * \param n number of LSF/LSP coefficients. + */ +static void reorder_lsf(FIXP_LPC *lsf, FIXP_LPC min_dist, int n) { + FIXP_LPC lsf_min; + int i; + + lsf_min = min_dist; + for (i = 0; i < n; i++) { + if (lsf[i] < lsf_min) { + lsf[i] = lsf_min; + } + lsf_min = fAddSaturate(lsf[i], min_dist); + } + + /* reverse */ + lsf_min = FL2FXCONST_LPC(FREQ_MAX / (1 << LSF_SCALE)) - min_dist; + for (i = n - 1; i >= 0; i--) { + if (lsf[i] > lsf_min) { + lsf[i] = lsf_min; + } + + lsf_min = lsf[i] - min_dist; + } +} + +/** + * \brief First stage approximation + * \param hBs bitstream handle as data source + * \param lsfq pointer to output buffer to hold LPC coefficients scaled by + * LSF_SCALE. + */ +static void vlpc_1st_dec( + HANDLE_FDK_BITSTREAM hBs, /* input: codebook index */ + FIXP_LPC *lsfq /* i/o: i:prediction o:quantized lsf */ +) { + const FIXP_LPC *p_dico; + int i, index; + + index = FDKreadBits(hBs, 8); + p_dico = &fdk_dec_dico_lsf_abs_8b[index * M_LP_FILTER_ORDER]; + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsfq[i] = p_dico[i]; + } +} + +/** + * \brief Do first stage approximation weighting and multiply with AVQ + * refinement. + * \param hBs bitstream handle data ssource. + * \param lsfq buffer holding 1st stage approx, 2nd stage approx is added to + * this values. + * \param nk_mode quantization mode. + * \return 0 on success, -1 on error. + */ +static int vlpc_2st_dec( + HANDLE_FDK_BITSTREAM hBs, + FIXP_LPC *lsfq, /* i/o: i:1st stage o:1st+2nd stage */ + int nk_mode /* input: 0=abs, >0=rel */ +) { + int err; + FIXP_DBL xq[M_LP_FILTER_ORDER]; /* weighted residual LSF vector */ + + /* Decode AVQ refinement */ + { err = CLpc_DecodeAVQ(hBs, xq, nk_mode, 2, 8); } + if (err != 0) { + return -1; + } + + /* add non-weighted residual LSF vector to LSF1st */ + lsf_weight_2st(lsfq, xq, nk_mode); + + /* reorder */ + reorder_lsf(lsfq, FL2FXCONST_LPC(LSF_GAP / (1 << LSF_SCALE)), + M_LP_FILTER_ORDER); + + return 0; +} + +/* + * Externally visible functions + */ + +int CLpc_DecodeAVQ(HANDLE_FDK_BITSTREAM hBs, FIXP_DBL *pOutput, int nk_mode, + int no_qn, int length) { + int i, l; + + for (i = 0; i < length; i += 8 * no_qn) { + int qn[2], nk, n, I; + int kv[8] = {0}; + + decode_qn(hBs, nk_mode, no_qn, qn); + + for (l = 0; l < no_qn; l++) { + if (qn[l] == 0) { + FDKmemclear(&pOutput[i + l * 8], 8 * sizeof(FIXP_DBL)); + } + + /* Voronoi extension order ( nk ) */ + nk = 0; + n = qn[l]; + if (qn[l] > 4) { + nk = (qn[l] - 3) >> 1; + n = qn[l] - nk * 2; + } + + /* Base codebook index, in reverse bit group order (!) */ + I = FDKreadBits(hBs, 4 * n); + + if (nk > 0) { + int j; + + for (j = 0; j < 8; j++) { + kv[j] = FDKreadBits(hBs, nk); + } + } + + if (RE8_dec(qn[l], I, kv, &pOutput[i + l * 8]) != 0) { + return -1; + } + } + } + return 0; +} + +int CLpc_Read(HANDLE_FDK_BITSTREAM hBs, FIXP_LPC lsp[][M_LP_FILTER_ORDER], + FIXP_LPC lpc4_lsf[M_LP_FILTER_ORDER], + FIXP_LPC lsf_adaptive_mean_cand[M_LP_FILTER_ORDER], + FIXP_SGL pStability[], UCHAR *mod, int first_lpd_flag, + int last_lpc_lost, int last_frame_ok) { + int i, k, err; + int mode_lpc_bin = 0; /* mode_lpc bitstream representation */ + int lpc_present[5] = {0, 0, 0, 0, 0}; + int lpc0_available = 1; + int s = 0; + int l = 3; + const int nbDiv = NB_DIV; + + lpc_present[4 >> s] = 1; /* LPC4 */ + + /* Decode LPC filters in the following order: LPC 4,0,2,1,3 */ + + /*** Decode LPC4 ***/ + vlpc_1st_dec(hBs, lsp[4 >> s]); + err = vlpc_2st_dec(hBs, lsp[4 >> s], 0); /* nk_mode = 0 */ + if (err != 0) { + return err; + } + + /*** Decode LPC0 and LPC2 ***/ + k = 0; + if (!first_lpd_flag) { + lpc_present[0] = 1; + lpc0_available = !last_lpc_lost; + /* old LPC4 is new LPC0 */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[0][i] = lpc4_lsf[i]; + } + /* skip LPC0 and continue with LPC2 */ + k = 2; + } + + for (; k < l; k += 2) { + int nk_mode = 0; + + if ((k == 2) && (mod[0] == 3)) { + break; /* skip LPC2 */ + } + + lpc_present[k >> s] = 1; + + mode_lpc_bin = FDKreadBit(hBs); + + if (mode_lpc_bin == 0) { + /* LPC0/LPC2: Abs */ + vlpc_1st_dec(hBs, lsp[k >> s]); + } else { + /* LPC0/LPC2: RelR */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[k >> s][i] = lsp[4 >> s][i]; + } + nk_mode = 3; + } + + err = vlpc_2st_dec(hBs, lsp[k >> s], nk_mode); + if (err != 0) { + return err; + } + } + + /*** Decode LPC1 ***/ + if (mod[0] < 2) { /* else: skip LPC1 */ + lpc_present[1] = 1; + mode_lpc_bin = get_vlclbf_n(hBs, 2); + + switch (mode_lpc_bin) { + case 1: + /* LPC1: abs */ + vlpc_1st_dec(hBs, lsp[1]); + err = vlpc_2st_dec(hBs, lsp[1], 0); + if (err != 0) { + return err; + } + break; + case 2: + /* LPC1: mid0 (no second stage AVQ quantizer in this case) */ + if (lpc0_available) { /* LPC0/lsf[0] might be zero some times */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[1][i] = (lsp[0][i] >> 1) + (lsp[2][i] >> 1); + } + } else { + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[1][i] = lsp[2][i]; + } + } + break; + case 0: + /* LPC1: RelR */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[1][i] = lsp[2][i]; + } + err = vlpc_2st_dec(hBs, lsp[1], 2 << s); + if (err != 0) { + return err; + } + break; + } + } + + /*** Decode LPC3 ***/ + if ((mod[2] < 2)) { /* else: skip LPC3 */ + int nk_mode = 0; + lpc_present[3] = 1; + + mode_lpc_bin = get_vlclbf_n(hBs, 3); + + switch (mode_lpc_bin) { + case 1: + /* LPC3: abs */ + vlpc_1st_dec(hBs, lsp[3]); + break; + case 0: + /* LPC3: mid */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[3][i] = (lsp[2][i] >> 1) + (lsp[4][i] >> 1); + } + nk_mode = 1; + break; + case 2: + /* LPC3: relL */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[3][i] = lsp[2][i]; + } + nk_mode = 2; + break; + case 3: + /* LPC3: relR */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[3][i] = lsp[4][i]; + } + nk_mode = 2; + break; + } + err = vlpc_2st_dec(hBs, lsp[3], nk_mode); + if (err != 0) { + return err; + } + } + + if (!lpc0_available && !last_frame_ok) { + /* LPC(0) was lost. Use next available LPC(k) instead */ + for (k = 1; k < (nbDiv + 1); k++) { + if (lpc_present[k]) { + for (i = 0; i < M_LP_FILTER_ORDER; i++) { +#define LSF_INIT_TILT (0.25f) + if (mod[0] > 0) { + lsp[0][i] = FX_DBL2FX_LPC( + fMult(lsp[k][i], FL2FXCONST_SGL(1.0f - LSF_INIT_TILT)) + + fMult(fdk_dec_lsf_init[i], FL2FXCONST_SGL(LSF_INIT_TILT))); + } else { + lsp[0][i] = lsp[k][i]; + } + } + break; + } + } + } + + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lpc4_lsf[i] = lsp[4 >> s][i]; + } + + { + FIXP_DBL divFac; + int last, numLpc = 0; + + i = nbDiv; + do { + numLpc += lpc_present[i--]; + } while (i >= 0 && numLpc < 3); + + last = i; + + switch (numLpc) { + case 3: + divFac = FL2FXCONST_DBL(1.0f / 3.0f); + break; + case 2: + divFac = FL2FXCONST_DBL(1.0f / 2.0f); + break; + default: + divFac = FL2FXCONST_DBL(1.0f); + break; + } + + /* get the adaptive mean for the next (bad) frame */ + for (k = 0; k < M_LP_FILTER_ORDER; k++) { + FIXP_DBL tmp = (FIXP_DBL)0; + for (i = nbDiv; i > last; i--) { + if (lpc_present[i]) { + tmp = fMultAdd(tmp >> 1, lsp[i][k], divFac); + } + } + lsf_adaptive_mean_cand[k] = FX_DBL2FX_LPC(tmp); + } + } + + /* calculate stability factor Theta. Needed for ACELP decoder and concealment + */ + { + FIXP_LPC *lsf_prev, *lsf_curr; + k = 0; + + FDK_ASSERT(lpc_present[0] == 1 && lpc_present[4 >> s] == 1); + lsf_prev = lsp[0]; + for (i = 1; i < (nbDiv + 1); i++) { + if (lpc_present[i]) { + FIXP_DBL tmp = (FIXP_DBL)0; + int j; + lsf_curr = lsp[i]; + + /* sum = tmp * 2^(LSF_SCALE*2 + 4) */ + for (j = 0; j < M_LP_FILTER_ORDER; j++) { + tmp += fPow2Div2((FIXP_SGL)(lsf_curr[j] - lsf_prev[j])) >> 3; + } + + /* tmp = (float)(FL2FXCONST_DBL(1.25f) - fMult(tmp, + * FL2FXCONST_DBL(1/400000.0f))); */ + tmp = FL2FXCONST_DBL(1.25f / (1 << LSF_SCALE)) - + fMult(tmp, FL2FXCONST_DBL((1 << (LSF_SCALE + 4)) / 400000.0f)); + if (tmp >= FL2FXCONST_DBL(1.0f / (1 << LSF_SCALE))) { + pStability[k] = FL2FXCONST_SGL(1.0f / 2.0f); + } else if (tmp < FL2FXCONST_DBL(0.0f)) { + pStability[k] = FL2FXCONST_SGL(0.0f); + } else { + pStability[k] = FX_DBL2FX_SGL(tmp << (LSF_SCALE - 1)); + } + + lsf_prev = lsf_curr; + k = i; + } else { + /* Mark stability value as undefined. */ + pStability[i] = (FIXP_SGL)-1; + } + } + } + + /* convert into LSP domain */ + for (i = 0; i < (nbDiv + 1); i++) { + if (lpc_present[i]) { + for (k = 0; k < M_LP_FILTER_ORDER; k++) { + lsp[i][k] = FX_DBL2FX_LPC( + fixp_cos(fMult(lsp[i][k], + FL2FXCONST_SGL((1 << LSPARG_SCALE) * M_PI / 6400.0)), + LSF_SCALE - LSPARG_SCALE)); + } + } + } + + return 0; +} + +void CLpc_Conceal(FIXP_LPC lsp[][M_LP_FILTER_ORDER], + FIXP_LPC lpc4_lsf[M_LP_FILTER_ORDER], + FIXP_LPC lsf_adaptive_mean[M_LP_FILTER_ORDER], + const int first_lpd_flag) { + int i, j; + +#define BETA (FL2FXCONST_SGL(0.25f)) +#define ONE_BETA (FL2FXCONST_SGL(0.75f)) +#define BFI_FAC (FL2FXCONST_SGL(0.90f)) +#define ONE_BFI_FAC (FL2FXCONST_SGL(0.10f)) + + /* Frame loss concealment (could be improved) */ + + if (first_lpd_flag) { + /* Reset past LSF values */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[0][i] = lpc4_lsf[i] = fdk_dec_lsf_init[i]; + } + } else { + /* old LPC4 is new LPC0 */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[0][i] = lpc4_lsf[i]; + } + } + + /* LPC1 */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + FIXP_LPC lsf_mean = FX_DBL2FX_LPC(fMult(BETA, fdk_dec_lsf_init[i]) + + fMult(ONE_BETA, lsf_adaptive_mean[i])); + + lsp[1][i] = FX_DBL2FX_LPC(fMult(BFI_FAC, lpc4_lsf[i]) + + fMult(ONE_BFI_FAC, lsf_mean)); + } + + /* LPC2 - LPC4 */ + for (j = 2; j <= 4; j++) { + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + /* lsf_mean[i] = FX_DBL2FX_LPC(fMult((FIXP_LPC)(BETA + j * + FL2FXCONST_LPC(0.1f)), fdk_dec_lsf_init[i]) + + fMult((FIXP_LPC)(ONE_BETA - j * + FL2FXCONST_LPC(0.1f)), lsf_adaptive_mean[i])); */ + + FIXP_LPC lsf_mean = FX_DBL2FX_LPC( + fMult((FIXP_SGL)(BETA + (FIXP_SGL)(j * (INT)FL2FXCONST_SGL(0.1f))), + (FIXP_SGL)fdk_dec_lsf_init[i]) + + fMult( + (FIXP_SGL)(ONE_BETA - (FIXP_SGL)(j * (INT)FL2FXCONST_SGL(0.1f))), + lsf_adaptive_mean[i])); + + lsp[j][i] = FX_DBL2FX_LPC(fMult(BFI_FAC, lsp[j - 1][i]) + + fMult(ONE_BFI_FAC, lsf_mean)); + } + } + + /* Update past values for the future */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lpc4_lsf[i] = lsp[4][i]; + } + + /* convert into LSP domain */ + for (j = 0; j < 5; j++) { + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[j][i] = FX_DBL2FX_LPC(fixp_cos( + fMult(lsp[j][i], FL2FXCONST_SGL((1 << LSPARG_SCALE) * M_PI / 6400.0)), + LSF_SCALE - LSPARG_SCALE)); + } + } +} + +void E_LPC_a_weight(FIXP_LPC *wA, const FIXP_LPC *A, int m) { + FIXP_DBL f; + int i; + + f = FL2FXCONST_DBL(0.92f); + for (i = 0; i < m; i++) { + wA[i] = FX_DBL2FX_LPC(fMult(A[i], f)); + f = fMult(f, FL2FXCONST_DBL(0.92f)); + } +} + +void CLpd_DecodeGain(FIXP_DBL *gain, INT *gain_e, int gain_code) { + /* gain * 2^(gain_e) = 10^(gain_code/28) */ + *gain = fLdPow( + FL2FXCONST_DBL(3.3219280948873623478703194294894 / 4.0), /* log2(10)*/ + 2, + fMultDiv2((FIXP_DBL)gain_code << (DFRACT_BITS - 1 - 7), + FL2FXCONST_DBL(2.0f / 28.0f)), + 7, gain_e); +} + + /** + * \brief * Find the polynomial F1(z) or F2(z) from the LSPs. + * This is performed by expanding the product polynomials: + * + * F1(z) = product ( 1 - 2 LSP_i z^-1 + z^-2 ) + * i=0,2,4,6,8 + * F2(z) = product ( 1 - 2 LSP_i z^-1 + z^-2 ) + * i=1,3,5,7,9 + * + * where LSP_i are the LSPs in the cosine domain. + * R.A.Salami October 1990 + * \param lsp input, line spectral freq. (cosine domain) + * \param f output, the coefficients of F1 or F2, scaled by 8 bits + * \param n no of coefficients (m/2) + * \param flag 1 : F1(z) ; 2 : F2(z) + */ + +#define SF_F 8 + +static void get_lsppol(FIXP_LPC lsp[], FIXP_DBL f[], int n, int flag) { + FIXP_DBL b; + FIXP_LPC *plsp; + int i, j; + + plsp = lsp + flag - 1; + f[0] = FL2FXCONST_DBL(1.0f / (1 << SF_F)); + b = -FX_LPC2FX_DBL(*plsp); + f[1] = b >> (SF_F - 1); + for (i = 2; i <= n; i++) { + plsp += 2; + b = -FX_LPC2FX_DBL(*plsp); + f[i] = ((fMultDiv2(b, f[i - 1]) << 1) + (f[i - 2])) << 1; + for (j = i - 1; j > 1; j--) { + f[j] = f[j] + (fMultDiv2(b, f[j - 1]) << 2) + f[j - 2]; + } + f[1] = f[1] + (b >> (SF_F - 1)); + } + return; +} + +#define NC M_LP_FILTER_ORDER / 2 + +/** + * \brief lsp input LSP vector + * \brief a output LP filter coefficient vector scaled by SF_A_COEFFS. + */ +void E_LPC_f_lsp_a_conversion(FIXP_LPC *lsp, FIXP_LPC *a, INT *a_exp) { + FIXP_DBL f1[NC + 1], f2[NC + 1]; + int i, k; + + /*-----------------------------------------------------* + * Find the polynomials F1(z) and F2(z) * + *-----------------------------------------------------*/ + + get_lsppol(lsp, f1, NC, 1); + get_lsppol(lsp, f2, NC, 2); + + /*-----------------------------------------------------* + * Multiply F1(z) by (1+z^-1) and F2(z) by (1-z^-1) * + *-----------------------------------------------------*/ + for (i = NC; i > 0; i--) { + f1[i] += f1[i - 1]; + f2[i] -= f2[i - 1]; + } + + FIXP_DBL aDBL[M_LP_FILTER_ORDER]; + + for (i = 1, k = M_LP_FILTER_ORDER - 1; i <= NC; i++, k--) { + FIXP_DBL tmp1, tmp2; + + tmp1 = f1[i] >> 1; + tmp2 = f2[i] >> 1; + + aDBL[i - 1] = (tmp1 + tmp2); + aDBL[k] = (tmp1 - tmp2); + } + + int headroom_a = getScalefactor(aDBL, M_LP_FILTER_ORDER); + + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + a[i] = FX_DBL2FX_LPC(aDBL[i] << headroom_a); + } + + *a_exp = 8 - headroom_a; +} |