/* -----------------------------------------------------------------------------
|
Software License for The Fraunhofer FDK AAC Codec Library for Android
|
|
© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
|
Forschung e.V. All rights reserved.
|
|
1. INTRODUCTION
|
The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
|
that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
|
scheme for digital audio. This FDK AAC Codec software is intended to be used on
|
a wide variety of Android devices.
|
|
AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
|
general perceptual audio codecs. AAC-ELD is considered the best-performing
|
full-bandwidth communications codec by independent studies and is widely
|
deployed. AAC has been standardized by ISO and IEC as part of the MPEG
|
specifications.
|
|
Patent licenses for necessary patent claims for the FDK AAC Codec (including
|
those of Fraunhofer) may be obtained through Via Licensing
|
(www.vialicensing.com) or through the respective patent owners individually for
|
the purpose of encoding or decoding bit streams in products that are compliant
|
with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
|
Android devices already license these patent claims through Via Licensing or
|
directly from the patent owners, and therefore FDK AAC Codec software may
|
already be covered under those patent licenses when it is used for those
|
licensed purposes only.
|
|
Commercially-licensed AAC software libraries, including floating-point versions
|
with enhanced sound quality, are also available from Fraunhofer. Users are
|
encouraged to check the Fraunhofer website for additional applications
|
information and documentation.
|
|
2. COPYRIGHT LICENSE
|
|
Redistribution and use in source and binary forms, with or without modification,
|
are permitted without payment of copyright license fees provided that you
|
satisfy the following conditions:
|
|
You must retain the complete text of this software license in redistributions of
|
the FDK AAC Codec or your modifications thereto in source code form.
|
|
You must retain the complete text of this software license in the documentation
|
and/or other materials provided with redistributions of the FDK AAC Codec or
|
your modifications thereto in binary form. You must make available free of
|
charge copies of the complete source code of the FDK AAC Codec and your
|
modifications thereto to recipients of copies in binary form.
|
|
The name of Fraunhofer may not be used to endorse or promote products derived
|
from this library without prior written permission.
|
|
You may not charge copyright license fees for anyone to use, copy or distribute
|
the FDK AAC Codec software or your modifications thereto.
|
|
Your modified versions of the FDK AAC Codec must carry prominent notices stating
|
that you changed the software and the date of any change. For modified versions
|
of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
|
must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
|
AAC Codec Library for Android."
|
|
3. NO PATENT LICENSE
|
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
|
limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
|
Fraunhofer provides no warranty of patent non-infringement with respect to this
|
software.
|
|
You may use this FDK AAC Codec software or modifications thereto only for
|
purposes that are authorized by appropriate patent licenses.
|
|
4. DISCLAIMER
|
|
This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
|
holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
|
including but not limited to the implied warranties of merchantability and
|
fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
|
or consequential damages, including but not limited to procurement of substitute
|
goods or services; loss of use, data, or profits, or business interruption,
|
however caused and on any theory of liability, whether in contract, strict
|
liability, or tort (including negligence), arising in any way out of the use of
|
this software, even if advised of the possibility of such damage.
|
|
5. CONTACT INFORMATION
|
|
Fraunhofer Institute for Integrated Circuits IIS
|
Attention: Audio and Multimedia Departments - FDK AAC LL
|
Am Wolfsmantel 33
|
91058 Erlangen, Germany
|
|
www.iis.fraunhofer.de/amm
|
amm-info@iis.fraunhofer.de
|
----------------------------------------------------------------------------- */
|
|
/*********************** MPEG surround decoder library *************************
|
|
Author(s): Matthias Hildenbrand
|
|
Description: USAC MPS212 Transient Steering Decorrelator (TSD)
|
|
*******************************************************************************/
|
|
#include "sac_tsd.h"
|
|
#define TSD_START_BAND (7)
|
#define SIZE_S (4)
|
#define SIZE_C (5)
|
|
/*** Tables ***/
|
RAM_ALIGN
|
LNK_SECTION_CONSTDATA
|
static const UCHAR nBitsTsdCW_32slots[32] = {
|
5, 9, 13, 16, 18, 20, 22, 24, 25, 26, 27, 28, 29, 29, 30, 30,
|
30, 29, 29, 28, 27, 26, 25, 24, 22, 20, 18, 16, 13, 9, 5, 0};
|
|
RAM_ALIGN
|
LNK_SECTION_CONSTDATA
|
static const UCHAR nBitsTsdCW_64slots[64] = {
|
6, 11, 16, 20, 23, 27, 30, 33, 35, 38, 40, 42, 44, 46, 48, 49,
|
51, 52, 53, 55, 56, 57, 58, 58, 59, 60, 60, 60, 61, 61, 61, 61,
|
61, 61, 61, 60, 60, 60, 59, 58, 58, 57, 56, 55, 53, 52, 51, 49,
|
48, 46, 44, 42, 40, 38, 35, 33, 30, 27, 23, 20, 16, 11, 6, 0};
|
|
RAM_ALIGN
|
LNK_SECTION_CONSTDATA
|
static const FIXP_STP phiTsd[8] = {
|
STCP(0x7fffffff, 0x00000000), STCP(0x5a82799a, 0x5a82799a),
|
STCP(0x00000000, 0x7fffffff), STCP(0xa57d8666, 0x5a82799a),
|
STCP(0x80000000, 0x00000000), STCP(0xa57d8666, 0xa57d8666),
|
STCP(0x00000000, 0x80000000), STCP(0x5a82799a, 0xa57d8666),
|
};
|
|
/*** Static Functions ***/
|
static void longmult1(USHORT a[], USHORT b, USHORT d[], int len) {
|
int k;
|
ULONG tmp;
|
ULONG b0 = (ULONG)b;
|
|
tmp = ((ULONG)a[0]) * b0;
|
d[0] = (USHORT)tmp;
|
|
for (k = 1; k < len; k++) {
|
tmp = (tmp >> 16) + ((ULONG)a[k]) * b0;
|
d[k] = (USHORT)tmp;
|
}
|
}
|
|
static void longdiv(USHORT b[], USHORT a, USHORT d[], USHORT *pr, int len) {
|
ULONG r;
|
ULONG tmp;
|
int k;
|
|
FDK_ASSERT(a != 0);
|
|
r = 0;
|
|
for (k = len - 1; k >= 0; k--) {
|
tmp = ((ULONG)b[k]) + (r << 16);
|
|
if (tmp) {
|
d[k] = (USHORT)(tmp / a);
|
r = tmp - d[k] * a;
|
} else {
|
d[k] = 0;
|
}
|
}
|
*pr = (USHORT)r;
|
}
|
|
static void longsub(USHORT a[], USHORT b[], int lena, int lenb) {
|
int h;
|
LONG carry = 0;
|
|
FDK_ASSERT(lena >= lenb);
|
for (h = 0; h < lenb; h++) {
|
carry += ((LONG)a[h]) - ((LONG)b[h]);
|
a[h] = (USHORT)carry;
|
carry = carry >> 16;
|
}
|
|
for (; h < lena; h++) {
|
carry = ((LONG)a[h]) + carry;
|
a[h] = (USHORT)carry;
|
carry = carry >> 16;
|
}
|
|
FDK_ASSERT(carry ==
|
0); /* carry != 0 indicates subtraction underflow, e.g. b > a */
|
return;
|
}
|
|
static int longcompare(USHORT a[], USHORT b[], int len) {
|
int i;
|
|
for (i = len - 1; i > 0; i--) {
|
if (a[i] != b[i]) break;
|
}
|
return (a[i] >= b[i]) ? 1 : 0;
|
}
|
|
FDK_INLINE int isTrSlot(const TSD_DATA *pTsdData, const int ts) {
|
return (pTsdData->bsTsdTrPhaseData[ts] >= 0);
|
}
|
|
/*** Public Functions ***/
|
int TsdRead(HANDLE_FDK_BITSTREAM hBs, const int numSlots, TSD_DATA *pTsdData) {
|
int nBitsTrSlots = 0;
|
int bsTsdNumTrSlots;
|
const UCHAR *nBitsTsdCW_tab = NULL;
|
|
switch (numSlots) {
|
case 32:
|
nBitsTrSlots = 4;
|
nBitsTsdCW_tab = nBitsTsdCW_32slots;
|
break;
|
case 64:
|
nBitsTrSlots = 5;
|
nBitsTsdCW_tab = nBitsTsdCW_64slots;
|
break;
|
default:
|
return 1;
|
}
|
|
/*** Read TempShapeData for bsTempShapeConfig == 3 ***/
|
pTsdData->bsTsdEnable = FDKreadBit(hBs);
|
if (!pTsdData->bsTsdEnable) {
|
return 0;
|
}
|
|
/*** Parse/Decode TsdData() ***/
|
pTsdData->numSlots = numSlots;
|
|
bsTsdNumTrSlots = FDKreadBits(hBs, nBitsTrSlots);
|
|
/* Decode transient slot positions */
|
{
|
int nBitsTsdCW = (int)nBitsTsdCW_tab[bsTsdNumTrSlots];
|
SCHAR *phaseData = pTsdData->bsTsdTrPhaseData;
|
int p = bsTsdNumTrSlots + 1;
|
int k, h;
|
USHORT s[SIZE_S] = {0};
|
USHORT c[SIZE_C] = {0};
|
USHORT r[1];
|
|
/* Init with TsdSepData[k] = 0 */
|
for (k = 0; k < numSlots; k++) {
|
phaseData[k] = -1; /* means TsdSepData[] = 0 */
|
}
|
|
for (h = (SIZE_S - 1); h >= 0; h--) {
|
if (nBitsTsdCW > h * 16) {
|
s[h] = (USHORT)FDKreadBits(hBs, nBitsTsdCW - h * 16);
|
nBitsTsdCW = h * 16;
|
}
|
}
|
|
/* c = prod_{h=1}^{p} (k-p+h)/h */
|
k = numSlots - 1;
|
c[0] = k - p + 1;
|
for (h = 2; h <= p; h++) {
|
longmult1(c, (k - p + h), c, 5); /* c *= k - p + h; */
|
longdiv(c, h, c, r, 5); /* c /= h; */
|
FDK_ASSERT(*r == 0);
|
}
|
|
/* go through all slots */
|
for (; k >= 0; k--) {
|
if (p > k) {
|
for (; k >= 0; k--) {
|
phaseData[k] = 1; /* means TsdSepData[] = 1 */
|
}
|
break;
|
}
|
if (longcompare(s, c, 4)) { /* (s >= c) */
|
longsub(s, c, 4, 4); /* s -= c; */
|
phaseData[k] = 1; /* means TsdSepData[] = 1 */
|
if (p == 1) {
|
break;
|
}
|
/* Update c for next iteration: c_new = c_old * p / k */
|
longmult1(c, p, c, 5);
|
p--;
|
} else {
|
/* Update c for next iteration: c_new = c_old * (k-p) / k */
|
longmult1(c, (k - p), c, 5);
|
}
|
longdiv(c, k, c, r, 5);
|
FDK_ASSERT(*r == 0);
|
}
|
|
/* Read phase data */
|
for (k = 0; k < numSlots; k++) {
|
if (phaseData[k] == 1) {
|
phaseData[k] = FDKreadBits(hBs, 3);
|
}
|
}
|
}
|
|
return 0;
|
}
|
|
void TsdGenerateNonTr(const int numHybridBands, const TSD_DATA *pTsdData,
|
const int ts, FIXP_DBL *pVdirectReal,
|
FIXP_DBL *pVdirectImag, FIXP_DBL *pVnonTrReal,
|
FIXP_DBL *pVnonTrImag, FIXP_DBL **ppDecorrInReal,
|
FIXP_DBL **ppDecorrInImag) {
|
int k = 0;
|
|
if (!isTrSlot(pTsdData, ts)) {
|
/* Let allpass based decorrelator read from direct input. */
|
*ppDecorrInReal = pVdirectReal;
|
*ppDecorrInImag = pVdirectImag;
|
return;
|
}
|
|
/* Generate nonTr input signal for allpass based decorrelator */
|
for (; k < TSD_START_BAND; k++) {
|
pVnonTrReal[k] = pVdirectReal[k];
|
pVnonTrImag[k] = pVdirectImag[k];
|
}
|
for (; k < numHybridBands; k++) {
|
pVnonTrReal[k] = (FIXP_DBL)0;
|
pVnonTrImag[k] = (FIXP_DBL)0;
|
}
|
*ppDecorrInReal = pVnonTrReal;
|
*ppDecorrInImag = pVnonTrImag;
|
}
|
|
void TsdApply(const int numHybridBands, const TSD_DATA *pTsdData, int *pTsdTs,
|
const FIXP_DBL *pVdirectReal, const FIXP_DBL *pVdirectImag,
|
FIXP_DBL *pDnonTrReal, FIXP_DBL *pDnonTrImag) {
|
const int ts = *pTsdTs;
|
|
if (isTrSlot(pTsdData, ts)) {
|
int k;
|
const FIXP_STP *phi = &phiTsd[pTsdData->bsTsdTrPhaseData[ts]];
|
FDK_ASSERT((pTsdData->bsTsdTrPhaseData[ts] >= 0) &&
|
(pTsdData->bsTsdTrPhaseData[ts] < 8));
|
|
/* d = d_nonTr + v_direct * exp(j * bsTsdTrPhaseData[ts]/4 * pi ) */
|
for (k = TSD_START_BAND; k < numHybridBands; k++) {
|
FIXP_DBL tempReal, tempImag;
|
cplxMult(&tempReal, &tempImag, pVdirectReal[k], pVdirectImag[k], *phi);
|
pDnonTrReal[k] += tempReal;
|
pDnonTrImag[k] += tempImag;
|
}
|
}
|
|
/* The modulo MAX_TSD_TIME_SLOTS operation is to avoid illegal memory accesses
|
* in case of errors. */
|
*pTsdTs = (ts + 1) & (MAX_TSD_TIME_SLOTS - 1);
|
return;
|
}
|