📄 sbrhfgen.c
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: sbrhfgen.c,v 1.1.2.2 2005/05/19 21:00:01 jrecker Exp $ * * Portions Copyright (c) 1995-2005 RealNetworks, Inc. All Rights Reserved. * * The contents of this file, and the files included with this file, * are subject to the current version of the RealNetworks Public * Source License (the "RPSL") available at * http://www.helixcommunity.org/content/rpsl unless you have licensed * the file under the current version of the RealNetworks Community * Source License (the "RCSL") available at * http://www.helixcommunity.org/content/rcsl, in which case the RCSL * will apply. You may also obtain the license terms directly from * RealNetworks. You may not use this file except in compliance with * the RPSL or, if you have a valid RCSL with RealNetworks applicable * to this file, the RCSL. Please see the applicable RPSL or RCSL for * the rights, obligations and limitations governing use of the * contents of the file. * * This file is part of the Helix DNA Technology. RealNetworks is the * developer of the Original Code and owns the copyrights in the * portions it created. * * This file, and the files included with this file, is distributed * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET * ENJOYMENT OR NON-INFRINGEMENT. * * Technology Compatibility Kit Test Suite(s) Location: * http://www.helixcommunity.org/content/tck * * Contributor(s): * * ***** END LICENSE BLOCK ***** */ /************************************************************************************** * Fixed-point HE-AAC decoder * Jon Recker (jrecker@real.com) * February 2005 * * sbrhfgen.c - high frequency generation for SBR **************************************************************************************/#include "sbr.h"#include "assembly.h"#define FBITS_LPCOEFS 29 /* Q29 for range of (-4, 4) */#define MAG_16 (16 * (1 << (32 - (2*(32-FBITS_LPCOEFS))))) /* i.e. 16 in Q26 format */#define RELAX_COEF 0x7ffff79c /* 1.0 / (1.0 + 1e-6), Q31 *//* newBWTab[prev invfMode][curr invfMode], format = Q31 (table 4.158) * sample file which uses all of these: al_sbr_sr_64_2_fsaac32.aac */static const int newBWTab[4][4] = { {0x00000000, 0x4ccccccd, 0x73333333, 0x7d70a3d7}, {0x4ccccccd, 0x60000000, 0x73333333, 0x7d70a3d7}, {0x00000000, 0x60000000, 0x73333333, 0x7d70a3d7}, {0x00000000, 0x60000000, 0x73333333, 0x7d70a3d7},};/************************************************************************************** * Function: CVKernel1 * * Description: kernel of covariance matrix calculation for p01, p11, p12, p22 * * Inputs: buffer of low-freq samples, starting at time index = 0, * freq index = patch subband * * Outputs: 64-bit accumulators for p01re, p01im, p12re, p12im, p11re, p22re * stored in accBuf * * Return: none * * Notes: this is carefully written to be efficient on ARM * use the assembly code version in sbrcov.s when building for ARM! **************************************************************************************/#if (defined (__arm) && defined (__ARMCC_VERSION)) || (defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM)) || (defined(__GNUC__) && defined(__arm__))#ifdef __cplusplusextern "C"#endifvoid CVKernel1(int *XBuf, int *accBuf);#elsevoid CVKernel1(int *XBuf, int *accBuf){ U64 p01re, p01im, p12re, p12im, p11re, p22re; int n, x0re, x0im, x1re, x1im; x0re = XBuf[0]; x0im = XBuf[1]; XBuf += (2*64); x1re = XBuf[0]; x1im = XBuf[1]; XBuf += (2*64); p01re.w64 = p01im.w64 = 0; p12re.w64 = p12im.w64 = 0; p11re.w64 = 0; p22re.w64 = 0; p12re.w64 = MADD64(p12re.w64, x1re, x0re); p12re.w64 = MADD64(p12re.w64, x1im, x0im); p12im.w64 = MADD64(p12im.w64, x0re, x1im); p12im.w64 = MADD64(p12im.w64, -x0im, x1re); p22re.w64 = MADD64(p22re.w64, x0re, x0re); p22re.w64 = MADD64(p22re.w64, x0im, x0im); for (n = (NUM_TIME_SLOTS*SAMPLES_PER_SLOT + 6); n != 0; n--) { /* 4 input, 3*2 acc, 1 ptr, 1 loop counter = 12 registers (use same for x0im, -x0im) */ x0re = x1re; x0im = x1im; x1re = XBuf[0]; x1im = XBuf[1]; p01re.w64 = MADD64(p01re.w64, x1re, x0re); p01re.w64 = MADD64(p01re.w64, x1im, x0im); p01im.w64 = MADD64(p01im.w64, x0re, x1im); p01im.w64 = MADD64(p01im.w64, -x0im, x1re); p11re.w64 = MADD64(p11re.w64, x0re, x0re); p11re.w64 = MADD64(p11re.w64, x0im, x0im); XBuf += (2*64); } /* these can be derived by slight changes to account for boundary conditions */ p12re.w64 += p01re.w64; p12re.w64 = MADD64(p12re.w64, x1re, -x0re); p12re.w64 = MADD64(p12re.w64, x1im, -x0im); p12im.w64 += p01im.w64; p12im.w64 = MADD64(p12im.w64, x0re, -x1im); p12im.w64 = MADD64(p12im.w64, x0im, x1re); p22re.w64 += p11re.w64; p22re.w64 = MADD64(p22re.w64, x0re, -x0re); p22re.w64 = MADD64(p22re.w64, x0im, -x0im); accBuf[0] = p01re.r.lo32; accBuf[1] = p01re.r.hi32; accBuf[2] = p01im.r.lo32; accBuf[3] = p01im.r.hi32; accBuf[4] = p11re.r.lo32; accBuf[5] = p11re.r.hi32; accBuf[6] = p12re.r.lo32; accBuf[7] = p12re.r.hi32; accBuf[8] = p12im.r.lo32; accBuf[9] = p12im.r.hi32; accBuf[10] = p22re.r.lo32; accBuf[11] = p22re.r.hi32;}#endif/************************************************************************************** * Function: CalcCovariance1 * * Description: calculate covariance matrix for p01, p12, p11, p22 (4.6.18.6.2) * * Inputs: buffer of low-freq samples, starting at time index 0, * freq index = patch subband * * Outputs: complex covariance elements p01re, p01im, p12re, p12im, p11re, p22re * (p11im = p22im = 0) * format = integer (Q0) * 2^N, with scalefactor N >= 0 * * Return: scalefactor N * * Notes: outputs are normalized to have 1 GB (sign in at least top 2 bits) **************************************************************************************/static int CalcCovariance1(int *XBuf, int *p01reN, int *p01imN, int *p12reN, int *p12imN, int *p11reN, int *p22reN){ int accBuf[2*6]; int n, z, s, loShift, hiShift, gbMask; U64 p01re, p01im, p12re, p12im, p11re, p22re; CVKernel1(XBuf, accBuf); p01re.r.lo32 = accBuf[0]; p01re.r.hi32 = accBuf[1]; p01im.r.lo32 = accBuf[2]; p01im.r.hi32 = accBuf[3]; p11re.r.lo32 = accBuf[4]; p11re.r.hi32 = accBuf[5]; p12re.r.lo32 = accBuf[6]; p12re.r.hi32 = accBuf[7]; p12im.r.lo32 = accBuf[8]; p12im.r.hi32 = accBuf[9]; p22re.r.lo32 = accBuf[10]; p22re.r.hi32 = accBuf[11]; /* 64-bit accumulators now have 2*FBITS_OUT_QMFA fraction bits * want to scale them down to integers (32-bit signed, Q0) * with scale factor of 2^n, n >= 0 * leave 2 GB's for calculating determinant, so take top 30 non-zero bits */ gbMask = ((p01re.r.hi32) ^ (p01re.r.hi32 >> 31)) | ((p01im.r.hi32) ^ (p01im.r.hi32 >> 31)); gbMask |= ((p12re.r.hi32) ^ (p12re.r.hi32 >> 31)) | ((p12im.r.hi32) ^ (p12im.r.hi32 >> 31)); gbMask |= ((p11re.r.hi32) ^ (p11re.r.hi32 >> 31)) | ((p22re.r.hi32) ^ (p22re.r.hi32 >> 31)); if (gbMask == 0) { s = p01re.r.hi32 >> 31; gbMask = (p01re.r.lo32 ^ s) - s; s = p01im.r.hi32 >> 31; gbMask |= (p01im.r.lo32 ^ s) - s; s = p12re.r.hi32 >> 31; gbMask |= (p12re.r.lo32 ^ s) - s; s = p12im.r.hi32 >> 31; gbMask |= (p12im.r.lo32 ^ s) - s; s = p11re.r.hi32 >> 31; gbMask |= (p11re.r.lo32 ^ s) - s; s = p22re.r.hi32 >> 31; gbMask |= (p22re.r.lo32 ^ s) - s; z = 32 + CLZ(gbMask); } else { gbMask = FASTABS(p01re.r.hi32) | FASTABS(p01im.r.hi32); gbMask |= FASTABS(p12re.r.hi32) | FASTABS(p12im.r.hi32); gbMask |= FASTABS(p11re.r.hi32) | FASTABS(p22re.r.hi32); z = CLZ(gbMask); } n = 64 - z; /* number of non-zero bits in bottom of 64-bit word */ if (n <= 30) { loShift = (30 - n); *p01reN = p01re.r.lo32 << loShift; *p01imN = p01im.r.lo32 << loShift; *p12reN = p12re.r.lo32 << loShift; *p12imN = p12im.r.lo32 << loShift; *p11reN = p11re.r.lo32 << loShift; *p22reN = p22re.r.lo32 << loShift; return -(loShift + 2*FBITS_OUT_QMFA); } else if (n < 32 + 30) { loShift = (n - 30); hiShift = 32 - loShift; *p01reN = (p01re.r.hi32 << hiShift) | (p01re.r.lo32 >> loShift); *p01imN = (p01im.r.hi32 << hiShift) | (p01im.r.lo32 >> loShift); *p12reN = (p12re.r.hi32 << hiShift) | (p12re.r.lo32 >> loShift); *p12imN = (p12im.r.hi32 << hiShift) | (p12im.r.lo32 >> loShift); *p11reN = (p11re.r.hi32 << hiShift) | (p11re.r.lo32 >> loShift); *p22reN = (p22re.r.hi32 << hiShift) | (p22re.r.lo32 >> loShift); return (loShift - 2*FBITS_OUT_QMFA); } else { hiShift = n - (32 + 30); *p01reN = p01re.r.hi32 >> hiShift; *p01imN = p01im.r.hi32 >> hiShift; *p12reN = p12re.r.hi32 >> hiShift; *p12imN = p12im.r.hi32 >> hiShift; *p11reN = p11re.r.hi32 >> hiShift; *p22reN = p22re.r.hi32 >> hiShift; return (32 - 2*FBITS_OUT_QMFA - hiShift); } return 0;}/************************************************************************************** * Function: CVKernel2 * * Description: kernel of covariance matrix calculation for p02 * * Inputs: buffer of low-freq samples, starting at time index = 0, * freq index = patch subband * * Outputs: 64-bit accumulators for p02re, p02im stored in accBuf * * Return: none * * Notes: this is carefully written to be efficient on ARM * use the assembly code version in sbrcov.s when building for ARM! **************************************************************************************/#if (defined (__arm) && defined (__ARMCC_VERSION)) || (defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM)) || (defined(__GNUC__) && defined(__arm__))#ifdef __cplusplusextern "C"#endifvoid CVKernel2(int *XBuf, int *accBuf);#elsevoid CVKernel2(int *XBuf, int *accBuf){ U64 p02re, p02im; int n, x0re, x0im, x1re, x1im, x2re, x2im; p02re.w64 = p02im.w64 = 0; x0re = XBuf[0]; x0im = XBuf[1]; XBuf += (2*64); x1re = XBuf[0]; x1im = XBuf[1]; XBuf += (2*64); for (n = (NUM_TIME_SLOTS*SAMPLES_PER_SLOT + 6); n != 0; n--) { /* 6 input, 2*2 acc, 1 ptr, 1 loop counter = 12 registers (use same for x0im, -x0im) */ x2re = XBuf[0]; x2im = XBuf[1]; p02re.w64 = MADD64(p02re.w64, x2re, x0re); p02re.w64 = MADD64(p02re.w64, x2im, x0im); p02im.w64 = MADD64(p02im.w64, x0re, x2im); p02im.w64 = MADD64(p02im.w64, -x0im, x2re); x0re = x1re; x0im = x1im; x1re = x2re; x1im = x2im; XBuf += (2*64); } accBuf[0] = p02re.r.lo32; accBuf[1] = p02re.r.hi32; accBuf[2] = p02im.r.lo32; accBuf[3] = p02im.r.hi32;}#endif/************************************************************************************** * Function: CalcCovariance2 * * Description: calculate covariance matrix for p02 (4.6.18.6.2) * * Inputs: buffer of low-freq samples, starting at time index = 0, * freq index = patch subband * * Outputs: complex covariance element p02re, p02im * format = integer (Q0) * 2^N, with scalefactor N >= 0 * * Return: scalefactor N * * Notes: outputs are normalized to have 1 GB (sign in at least top 2 bits) **************************************************************************************/static int CalcCovariance2(int *XBuf, int *p02reN, int *p02imN){ U64 p02re, p02im; int n, z, s, loShift, hiShift, gbMask; int accBuf[2*2]; CVKernel2(XBuf, accBuf); p02re.r.lo32 = accBuf[0]; p02re.r.hi32 = accBuf[1]; p02im.r.lo32 = accBuf[2];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -