1197 lines
34 KiB
C++
1197 lines
34 KiB
C++
/* -----------------------------------------------------------------------------
|
|
Software License for The Fraunhofer FDK AAC Codec Library for Android
|
|
|
|
© Copyright 1995 - 2019 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;
|
|
INT64 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 = 0;
|
|
for (i = 0; i < 8; i++) {
|
|
tmp = x[i] - INT2ZF(y0[i], 0);
|
|
e += (INT64)fPow2Div2(
|
|
tmp << r); /* shift left to ensure that no fract part bits get lost. */
|
|
tmp = x[i] - INT2ZF(y1[i], 0);
|
|
e -= (INT64)fPow2Div2(tmp << r);
|
|
}
|
|
/* select best candidate y0 or y1 to minimize distortion */
|
|
if (e < 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)((INT64)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] = SATURATE_LEFT_SHIFT((fMultDiv2(b, f[i - 1]) + (f[i - 2] >> 1)), 2,
|
|
DFRACT_BITS);
|
|
for (j = i - 1; j > 1; j--) {
|
|
f[j] = SATURATE_LEFT_SHIFT(
|
|
((f[j] >> 2) + fMultDiv2(b, f[j - 1]) + (f[j - 2] >> 2)), 2,
|
|
DFRACT_BITS);
|
|
}
|
|
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) *
|
|
*-----------------------------------------------------*/
|
|
scaleValues(f1, NC + 1, -2);
|
|
scaleValues(f2, NC + 1, -2);
|
|
|
|
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--) {
|
|
aDBL[i - 1] = f1[i] + f2[i];
|
|
aDBL[k] = f1[i] - f2[i];
|
|
}
|
|
|
|
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 = SF_F + (2 - 1) - headroom_a;
|
|
}
|