tns.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Source last modified: $Id: tns.c,v 1.2 2005/05/24 16:01:55 albertofloyd Exp $
  3. *
  4. * Portions Copyright (c) 1995-2005 RealNetworks, Inc. All Rights Reserved.
  5. *
  6. * The contents of this file, and the files included with this file,
  7. * are subject to the current version of the RealNetworks Public
  8. * Source License (the "RPSL") available at
  9. * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10. * the file under the current version of the RealNetworks Community
  11. * Source License (the "RCSL") available at
  12. * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13. * will apply. You may also obtain the license terms directly from
  14. * RealNetworks. You may not use this file except in compliance with
  15. * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16. * to this file, the RCSL. Please see the applicable RPSL or RCSL for
  17. * the rights, obligations and limitations governing use of the
  18. * contents of the file.
  19. *
  20. * This file is part of the Helix DNA Technology. RealNetworks is the
  21. * developer of the Original Code and owns the copyrights in the
  22. * portions it created.
  23. *
  24. * This file, and the files included with this file, is distributed
  25. * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  26. * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  27. * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  28. * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  29. * ENJOYMENT OR NON-INFRINGEMENT.
  30. *
  31. * Technology Compatibility Kit Test Suite(s) Location:
  32. * http://www.helixcommunity.org/content/tck
  33. *
  34. * Contributor(s):
  35. *
  36. * ***** END LICENSE BLOCK ***** */
  37. /**************************************************************************************
  38. * Fixed-point HE-AAC decoder
  39. * Jon Recker (jrecker@real.com)
  40. * February 2005
  41. *
  42. * tns.c - apply TNS to spectrum
  43. **************************************************************************************/
  44. #include "coder.h"
  45. #include "assembly.h"
  46. #define FBITS_LPC_COEFS 20
  47. //fb
  48. #pragma GCC diagnostic push
  49. #pragma GCC diagnostic ignored "-Wnarrowing"
  50. /* inverse quantization tables for TNS filter coefficients, format = Q31
  51. * see bottom of file for table generation
  52. * negative (vs. spec) since we use MADD for filter kernel
  53. */
  54. static const int invQuant3[16] PROGMEM = {
  55. 0x00000000, 0xc8767f65, 0x9becf22c, 0x83358feb, 0x83358feb, 0x9becf22c, 0xc8767f65, 0x00000000,
  56. 0x2bc750e9, 0x5246dd49, 0x6ed9eba1, 0x7e0e2e32, 0x7e0e2e32, 0x6ed9eba1, 0x5246dd49, 0x2bc750e9,
  57. };
  58. static const int invQuant4[16] PROGMEM = {
  59. 0x00000000, 0xe5632654, 0xcbf00dbe, 0xb4c373ee, 0xa0e0a15f, 0x9126145f, 0x8643c7b3, 0x80b381ac,
  60. 0x7f7437ad, 0x7b1d1a49, 0x7294b5f2, 0x66256db2, 0x563ba8aa, 0x4362210e, 0x2e3d2abb, 0x17851aad,
  61. };
  62. #pragma GCC diagnostic pop
  63. /**************************************************************************************
  64. * Function: DecodeLPCCoefs
  65. *
  66. * Description: decode LPC coefficients for TNS
  67. *
  68. * Inputs: order of TNS filter
  69. * resolution of coefficients (3 or 4 bits)
  70. * coefficients unpacked from bitstream
  71. * scratch buffer (b) of size >= order
  72. *
  73. * Outputs: LPC coefficients in Q(FBITS_LPC_COEFS), in 'a'
  74. *
  75. * Return: none
  76. *
  77. * Notes: assumes no guard bits in input transform coefficients
  78. * a[i] = Q(FBITS_LPC_COEFS), don't store a0 = 1.0
  79. * (so a[0] = first delay tap, etc.)
  80. * max abs(a[i]) < log2(order), so for max order = 20 a[i] < 4.4
  81. * (up to 3 bits of gain) so a[i] has at least 31 - FBITS_LPC_COEFS - 3
  82. * guard bits
  83. * to ensure no intermediate overflow in all-pole filter, set
  84. * FBITS_LPC_COEFS such that number of guard bits >= log2(max order)
  85. **************************************************************************************/
  86. static void DecodeLPCCoefs(int order, int res, signed char *filtCoef, int *a, int *b)
  87. {
  88. int i, m, t;
  89. const int *invQuantTab;
  90. if (res == 3) invQuantTab = invQuant3;
  91. else if (res == 4) invQuantTab = invQuant4;
  92. else return;
  93. for (m = 0; m < order; m++) {
  94. t = invQuantTab[filtCoef[m] & 0x0f]; /* t = Q31 */
  95. for (i = 0; i < m; i++)
  96. b[i] = a[i] - (MULSHIFT32(t, a[m-i-1]) << 1);
  97. for (i = 0; i < m; i++)
  98. a[i] = b[i];
  99. a[m] = t >> (31 - FBITS_LPC_COEFS);
  100. }
  101. }
  102. /**************************************************************************************
  103. * Function: FilterRegion
  104. *
  105. * Description: apply LPC filter to one region of coefficients
  106. *
  107. * Inputs: number of transform coefficients in this region
  108. * direction flag (forward = 1, backward = -1)
  109. * order of filter
  110. * 'size' transform coefficients
  111. * 'order' LPC coefficients in Q(FBITS_LPC_COEFS)
  112. * scratch buffer for history (must be >= order samples long)
  113. *
  114. * Outputs: filtered transform coefficients
  115. *
  116. * Return: guard bit mask (OR of abs value of all filtered transform coefs)
  117. *
  118. * Notes: assumes no guard bits in input transform coefficients
  119. * gains 0 int bits
  120. * history buffer does not need to be preserved between regions
  121. **************************************************************************************/
  122. static int FilterRegion(int size, int dir, int order, int *audioCoef, int *a, int *hist)
  123. {
  124. int i, j, y, hi32, inc, gbMask;
  125. U64 sum64;
  126. /* init history to 0 every time */
  127. for (i = 0; i < order; i++)
  128. hist[i] = 0;
  129. sum64.w64 = 0; /* avoid warning */
  130. gbMask = 0;
  131. inc = (dir ? -1 : 1);
  132. do {
  133. /* sum64 = a0*y[n] = 1.0*y[n] */
  134. y = *audioCoef;
  135. sum64.r.hi32 = y >> (32 - FBITS_LPC_COEFS);
  136. sum64.r.lo32 = y << FBITS_LPC_COEFS;
  137. /* sum64 += (a1*y[n-1] + a2*y[n-2] + ... + a[order-1]*y[n-(order-1)]) */
  138. for (j = order - 1; j > 0; j--) {
  139. sum64.w64 = MADD64(sum64.w64, hist[j], a[j]);
  140. hist[j] = hist[j-1];
  141. }
  142. sum64.w64 = MADD64(sum64.w64, hist[0], a[0]);
  143. y = (sum64.r.hi32 << (32 - FBITS_LPC_COEFS)) | (sum64.r.lo32 >> FBITS_LPC_COEFS);
  144. /* clip output (rare) */
  145. hi32 = sum64.r.hi32;
  146. if ((hi32 >> 31) != (hi32 >> (FBITS_LPC_COEFS-1)))
  147. y = (hi32 >> 31) ^ 0x7fffffff;
  148. hist[0] = y;
  149. *audioCoef = y;
  150. audioCoef += inc;
  151. gbMask |= FASTABS(y);
  152. } while (--size);
  153. return gbMask;
  154. }
  155. /**************************************************************************************
  156. * Function: TNSFilter
  157. *
  158. * Description: apply temporal noise shaping, if enabled
  159. *
  160. * Inputs: valid AACDecInfo struct
  161. * index of current channel
  162. *
  163. * Outputs: updated transform coefficients
  164. * updated minimum guard bit count for this channel
  165. *
  166. * Return: 0 if successful, -1 if error
  167. **************************************************************************************/
  168. int TNSFilter(AACDecInfo *aacDecInfo, int ch)
  169. {
  170. int win, winLen, nWindows, nSFB, filt, bottom, top, order, maxOrder, dir;
  171. int start, end, size, tnsMaxBand, numFilt, gbMask;
  172. int *audioCoef;
  173. unsigned char *filtLength, *filtOrder, *filtRes, *filtDir;
  174. signed char *filtCoef;
  175. const unsigned /*char*/ int *tnsMaxBandTab;
  176. const /*short*/ int *sfbTab;
  177. ICSInfo *icsInfo;
  178. TNSInfo *ti;
  179. PSInfoBase *psi;
  180. /* validate pointers */
  181. if (!aacDecInfo || !aacDecInfo->psInfoBase)
  182. return -1;
  183. psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
  184. icsInfo = (ch == 1 && psi->commonWin == 1) ? &(psi->icsInfo[0]) : &(psi->icsInfo[ch]);
  185. ti = &psi->tnsInfo[ch];
  186. if (!ti->tnsDataPresent)
  187. return 0;
  188. if (icsInfo->winSequence == 2) {
  189. nWindows = NWINDOWS_SHORT;
  190. winLen = NSAMPS_SHORT;
  191. nSFB = sfBandTotalShort[psi->sampRateIdx];
  192. maxOrder = tnsMaxOrderShort[aacDecInfo->profile];
  193. sfbTab = sfBandTabShort + sfBandTabShortOffset[psi->sampRateIdx];
  194. tnsMaxBandTab = tnsMaxBandsShort + tnsMaxBandsShortOffset[aacDecInfo->profile];
  195. tnsMaxBand = tnsMaxBandTab[psi->sampRateIdx];
  196. } else {
  197. nWindows = NWINDOWS_LONG;
  198. winLen = NSAMPS_LONG;
  199. nSFB = sfBandTotalLong[psi->sampRateIdx];
  200. maxOrder = tnsMaxOrderLong[aacDecInfo->profile];
  201. sfbTab = sfBandTabLong + sfBandTabLongOffset[psi->sampRateIdx];
  202. tnsMaxBandTab = tnsMaxBandsLong + tnsMaxBandsLongOffset[aacDecInfo->profile];
  203. tnsMaxBand = tnsMaxBandTab[psi->sampRateIdx];
  204. }
  205. if (tnsMaxBand > icsInfo->maxSFB)
  206. tnsMaxBand = icsInfo->maxSFB;
  207. filtRes = ti->coefRes;
  208. filtLength = ti->length;
  209. filtOrder = ti->order;
  210. filtDir = ti->dir;
  211. filtCoef = ti->coef;
  212. gbMask = 0;
  213. audioCoef = psi->coef[ch];
  214. for (win = 0; win < nWindows; win++) {
  215. bottom = nSFB;
  216. numFilt = ti->numFilt[win];
  217. for (filt = 0; filt < numFilt; filt++) {
  218. top = bottom;
  219. bottom = top - *filtLength++;
  220. bottom = MAX(bottom, 0);
  221. order = *filtOrder++;
  222. order = MIN(order, maxOrder);
  223. if (order) {
  224. start = sfbTab[MIN(bottom, tnsMaxBand)];
  225. end = sfbTab[MIN(top, tnsMaxBand)];
  226. size = end - start;
  227. if (size > 0) {
  228. dir = *filtDir++;
  229. if (dir)
  230. start = end - 1;
  231. DecodeLPCCoefs(order, filtRes[win], filtCoef, psi->tnsLPCBuf, psi->tnsWorkBuf);
  232. gbMask |= FilterRegion(size, dir, order, audioCoef + start, psi->tnsLPCBuf, psi->tnsWorkBuf);
  233. }
  234. filtCoef += order;
  235. }
  236. }
  237. audioCoef += winLen;
  238. }
  239. /* update guard bit count if necessary */
  240. size = CLZ(gbMask) - 1;
  241. if (psi->gbCurrent[ch] > size)
  242. psi->gbCurrent[ch] = size;
  243. return 0;
  244. }
  245. /* Code to generate invQuantXXX[] tables
  246. * {
  247. * int res, i, t;
  248. * double powScale, iqfac, iqfac_m, d;
  249. *
  250. * powScale = pow(2.0, 31) * -1.0; / ** make coefficients negative for using MADD in kernel ** /
  251. * for (res = 3; res <= 4; res++) {
  252. * iqfac = ( ((1 << (res-1)) - 0.5) * (2.0 / M_PI) );
  253. * iqfac_m = ( ((1 << (res-1)) + 0.5) * (2.0 / M_PI) );
  254. * printf("static const int invQuant%d[16] = {\n", res);
  255. * for (i = 0; i < 16; i++) {
  256. * / ** extend bottom 4 bits into signed, 2's complement number ** /
  257. * t = (i << 28) >> 28;
  258. *
  259. * if (t >= 0) d = sin(t / iqfac);
  260. * else d = sin(t / iqfac_m);
  261. *
  262. * d *= powScale;
  263. * printf("0x%08x, ", (int)(d > 0 ? d + 0.5 : d - 0.5));
  264. * if ((i & 0x07) == 0x07)
  265. * printf("\n");
  266. * }
  267. * printf("};\n\n");
  268. * }
  269. * }
  270. */