aboutsummaryrefslogtreecommitdiffstats
path: root/libSACdec/src/sac_tsd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libSACdec/src/sac_tsd.cpp')
-rw-r--r--libSACdec/src/sac_tsd.cpp353
1 files changed, 353 insertions, 0 deletions
diff --git a/libSACdec/src/sac_tsd.cpp b/libSACdec/src/sac_tsd.cpp
new file mode 100644
index 0000000..30acca8
--- /dev/null
+++ b/libSACdec/src/sac_tsd.cpp
@@ -0,0 +1,353 @@
+/* -----------------------------------------------------------------------------
+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;
+}