diff options
Diffstat (limited to 'libSBRdec/src/hbe.cpp')
-rw-r--r-- | libSBRdec/src/hbe.cpp | 2198 |
1 files changed, 2198 insertions, 0 deletions
diff --git a/libSBRdec/src/hbe.cpp b/libSBRdec/src/hbe.cpp new file mode 100644 index 0000000..53b21c9 --- /dev/null +++ b/libSBRdec/src/hbe.cpp @@ -0,0 +1,2198 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Fast FFT routines prototypes + \author Fabian Haussel +*/ + +#include "hbe.h" +#include "qmf.h" +#include "env_extr.h" + +#define HBE_MAX_QMF_BANDS (40) + +#define HBE_MAX_OUT_SLOTS (11) + +#define QMF_WIN_LEN \ + (12 + 6 - 4 - 1) /* 6 subband slots extra delay to align with HQ - 4 slots \ + to compensate for critical sampling delay - 1 slot to \ + align critical sampling exactly (w additional time \ + domain delay)*/ + +#ifndef PI +#define PI 3.14159265358979323846 +#endif + +static const int xProducts[MAX_STRETCH_HBE - 1] = { + 1, 1, 1}; /* Cross products on(1)/off(0) for T=2,3,4. */ +static const int startSubband2kL[33] = { + 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, + 6, 8, 8, 8, 8, 8, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12}; + +static const int pmin = 12; + +static const FIXP_DBL hintReal_F[4][3] = { + {FL2FXCONST_DBL(0.39840335f), FL2FXCONST_DBL(0.39840335f), + FL2FXCONST_DBL(-0.39840335f)}, + {FL2FXCONST_DBL(0.39840335f), FL2FXCONST_DBL(-0.39840335f), + FL2FXCONST_DBL(-0.39840335f)}, + {FL2FXCONST_DBL(-0.39840335f), FL2FXCONST_DBL(-0.39840335f), + FL2FXCONST_DBL(0.39840335f)}, + {FL2FXCONST_DBL(-0.39840335f), FL2FXCONST_DBL(0.39840335f), + FL2FXCONST_DBL(0.39840335f)}}; + +static const FIXP_DBL factors[4] = { + FL2FXCONST_DBL(0.39840335f), FL2FXCONST_DBL(-0.39840335f), + FL2FXCONST_DBL(-0.39840335f), FL2FXCONST_DBL(0.39840335f)}; + +#define PSCALE 32 + +static const FIXP_DBL p_F[128] = {FL2FXCONST_DBL(0.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(1.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(2.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(3.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(4.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(5.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(6.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(7.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(8.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(9.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(10.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(11.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(12.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(13.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(14.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(15.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(16.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(17.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(18.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(19.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(20.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(21.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(22.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(23.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(24.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(25.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(26.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(27.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(28.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(29.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(30.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(31.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(32.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(33.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(34.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(35.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(36.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(37.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(38.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(39.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(40.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(41.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(42.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(43.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(44.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(45.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(46.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(47.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(48.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(49.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(50.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(51.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(52.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(53.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(54.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(55.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(56.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(57.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(58.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(59.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(60.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(61.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(62.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(63.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(64.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(65.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(66.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(67.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(68.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(69.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(70.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(71.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(72.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(73.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(74.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(75.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(76.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(77.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(78.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(79.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(80.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(81.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(82.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(83.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(84.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(85.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(86.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(87.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(88.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(89.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(90.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(91.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(92.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(93.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(94.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(95.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(96.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(97.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(98.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(99.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(100.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(101.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(102.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(103.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(104.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(105.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(106.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(107.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(108.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(109.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(110.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(111.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(112.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(113.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(114.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(115.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(116.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(117.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(118.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(119.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(120.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(121.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(122.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(123.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(124.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(125.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(126.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(127.f / (PSCALE * 12.f))}; + +static const FIXP_DBL band_F[64] = { + FL2FXCONST_DBL((0.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((1.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((2.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((3.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((4.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((5.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((6.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((7.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((8.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((9.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((10.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((11.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((12.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((13.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((14.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((15.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((16.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((17.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((18.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((19.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((20.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((21.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((22.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((23.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((24.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((25.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((26.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((27.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((28.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((29.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((30.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((31.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((32.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((33.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((34.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((35.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((36.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((37.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((38.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((39.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((40.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((41.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((42.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((43.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((44.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((45.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((46.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((47.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((48.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((49.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((50.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((51.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((52.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((53.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((54.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((55.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((56.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((57.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((58.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((59.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((60.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((61.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((62.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((63.f * 2.f + 1) / (PSCALE << 2))}; + +static const FIXP_DBL tr_str[3] = {FL2FXCONST_DBL(1.f / 4.f), + FL2FXCONST_DBL(2.f / 4.f), + FL2FXCONST_DBL(3.f / 4.f)}; + +static const FIXP_DBL stretchfac[3] = {FL2FXCONST_DBL(1.f / 2.f), + FL2FXCONST_DBL(1.f / 3.f), + FL2FXCONST_DBL(1.f / 4.f)}; + +static const FIXP_DBL cos_F[64] = { + 26353028, -79043208, 131685776, -184244944, 236697216, -289006912, + 341142496, -393072608, 444773984, -496191392, 547325824, -598114752, + 648559104, -698597248, 748230016, -797411904, 846083200, -894275136, + 941928192, -989013760, 1035474624, -1081340672, 1126555136, -1171063296, + 1214893696, -1257992192, 1300332544, -1341889408, 1382612736, -1422503808, + 1461586944, -1499741440, 1537039104, -1573364864, 1608743808, -1643196672, + 1676617344, -1709028992, 1740450560, -1770784896, 1800089472, -1828273536, + 1855357440, -1881356288, 1906190080, -1929876608, 1952428928, -1973777664, + 1993962880, -2012922240, 2030670208, -2047216000, 2062508288, -2076559488, + 2089376128, -2100932224, 2111196800, -2120214784, 2127953792, -2134394368, + 2139565056, -2143444864, 2146026624, -2147321856}; + +static const FIXP_DBL twiddle[121] = {1073741824, + 1071442860, + 1064555814, + 1053110176, + 1037154959, + 1016758484, + 992008094, + 963009773, + 929887697, + 892783698, + 851856663, + 807281846, + 759250125, + 707967178, + 653652607, + 596538995, + 536870912, + 474903865, + 410903207, + 345142998, + 277904834, + 209476638, + 140151432, + 70226075, + 0, + -70226075, + -140151432, + -209476638, + -277904834, + -345142998, + -410903207, + -474903865, + -536870912, + -596538995, + -653652607, + -707967178, + -759250125, + -807281846, + -851856663, + -892783698, + -929887697, + -963009773, + -992008094, + -1016758484, + -1037154959, + -1053110176, + -1064555814, + -1071442860, + -1073741824, + -1071442860, + -1064555814, + -1053110176, + -1037154959, + -1016758484, + -992008094, + -963009773, + -929887697, + -892783698, + -851856663, + -807281846, + -759250125, + -707967178, + -653652607, + -596538995, + -536870912, + -474903865, + -410903207, + -345142998, + -277904834, + -209476638, + -140151432, + -70226075, + 0, + 70226075, + 140151432, + 209476638, + 277904834, + 345142998, + 410903207, + 474903865, + 536870912, + 596538995, + 653652607, + 707967178, + 759250125, + 807281846, + 851856663, + 892783698, + 929887697, + 963009773, + 992008094, + 1016758484, + 1037154959, + 1053110176, + 1064555814, + 1071442860, + 1073741824, + 1071442860, + 1064555814, + 1053110176, + 1037154959, + 1016758484, + 992008094, + 963009773, + 929887697, + 892783698, + 851856663, + 807281846, + 759250125, + 707967178, + 653652607, + 596538995, + 536870912, + 474903865, + 410903207, + 345142998, + 277904834, + 209476638, + 140151432, + 70226075, + 0}; + +#if FIXP_QTW == FIXP_SGL +#define HTW(x) (x) +#else +#define HTW(x) FX_DBL2FX_QTW(FX_SGL2FX_DBL((const FIXP_SGL)x)) +#endif + +static const FIXP_QTW post_twiddle_cos_8[8] = { + HTW(-1606), HTW(4756), HTW(-7723), HTW(10394), + HTW(-12665), HTW(14449), HTW(-15679), HTW(16305)}; + +static const FIXP_QTW post_twiddle_cos_16[16] = { + HTW(-804), HTW(2404), HTW(-3981), HTW(5520), HTW(-7005), HTW(8423), + HTW(-9760), HTW(11003), HTW(-12140), HTW(13160), HTW(-14053), HTW(14811), + HTW(-15426), HTW(15893), HTW(-16207), HTW(16364)}; + +static const FIXP_QTW post_twiddle_cos_24[24] = { + HTW(-536), HTW(1606), HTW(-2669), HTW(3720), HTW(-4756), HTW(5771), + HTW(-6762), HTW(7723), HTW(-8652), HTW(9543), HTW(-10394), HTW(11200), + HTW(-11958), HTW(12665), HTW(-13318), HTW(13913), HTW(-14449), HTW(14924), + HTW(-15334), HTW(15679), HTW(-15956), HTW(16165), HTW(-16305), HTW(16375)}; + +static const FIXP_QTW post_twiddle_cos_32[32] = { + HTW(-402), HTW(1205), HTW(-2006), HTW(2801), HTW(-3590), HTW(4370), + HTW(-5139), HTW(5897), HTW(-6639), HTW(7366), HTW(-8076), HTW(8765), + HTW(-9434), HTW(10080), HTW(-10702), HTW(11297), HTW(-11866), HTW(12406), + HTW(-12916), HTW(13395), HTW(-13842), HTW(14256), HTW(-14635), HTW(14978), + HTW(-15286), HTW(15557), HTW(-15791), HTW(15986), HTW(-16143), HTW(16261), + HTW(-16340), HTW(16379)}; + +static const FIXP_QTW post_twiddle_cos_40[40] = { + HTW(-322), HTW(965), HTW(-1606), HTW(2245), HTW(-2880), HTW(3511), + HTW(-4137), HTW(4756), HTW(-5368), HTW(5971), HTW(-6566), HTW(7150), + HTW(-7723), HTW(8285), HTW(-8833), HTW(9368), HTW(-9889), HTW(10394), + HTW(-10883), HTW(11356), HTW(-11810), HTW(12247), HTW(-12665), HTW(13063), + HTW(-13441), HTW(13799), HTW(-14135), HTW(14449), HTW(-14741), HTW(15011), + HTW(-15257), HTW(15480), HTW(-15679), HTW(15853), HTW(-16003), HTW(16129), + HTW(-16229), HTW(16305), HTW(-16356), HTW(16381)}; + +static const FIXP_QTW post_twiddle_sin_8[8] = { + HTW(16305), HTW(-15679), HTW(14449), HTW(-12665), + HTW(10394), HTW(-7723), HTW(4756), HTW(-1606)}; + +static const FIXP_QTW post_twiddle_sin_16[16] = { + HTW(16364), HTW(-16207), HTW(15893), HTW(-15426), HTW(14811), HTW(-14053), + HTW(13160), HTW(-12140), HTW(11003), HTW(-9760), HTW(8423), HTW(-7005), + HTW(5520), HTW(-3981), HTW(2404), HTW(-804)}; + +static const FIXP_QTW post_twiddle_sin_24[24] = { + HTW(16375), HTW(-16305), HTW(16165), HTW(-15956), HTW(15679), HTW(-15334), + HTW(14924), HTW(-14449), HTW(13913), HTW(-13318), HTW(12665), HTW(-11958), + HTW(11200), HTW(-10394), HTW(9543), HTW(-8652), HTW(7723), HTW(-6762), + HTW(5771), HTW(-4756), HTW(3720), HTW(-2669), HTW(1606), HTW(-536)}; + +static const FIXP_QTW post_twiddle_sin_32[32] = { + HTW(16379), HTW(-16340), HTW(16261), HTW(-16143), HTW(15986), HTW(-15791), + HTW(15557), HTW(-15286), HTW(14978), HTW(-14635), HTW(14256), HTW(-13842), + HTW(13395), HTW(-12916), HTW(12406), HTW(-11866), HTW(11297), HTW(-10702), + HTW(10080), HTW(-9434), HTW(8765), HTW(-8076), HTW(7366), HTW(-6639), + HTW(5897), HTW(-5139), HTW(4370), HTW(-3590), HTW(2801), HTW(-2006), + HTW(1205), HTW(-402)}; + +static const FIXP_QTW post_twiddle_sin_40[40] = { + HTW(16381), HTW(-16356), HTW(16305), HTW(-16229), HTW(16129), HTW(-16003), + HTW(15853), HTW(-15679), HTW(15480), HTW(-15257), HTW(15011), HTW(-14741), + HTW(14449), HTW(-14135), HTW(13799), HTW(-13441), HTW(13063), HTW(-12665), + HTW(12247), HTW(-11810), HTW(11356), HTW(-10883), HTW(10394), HTW(-9889), + HTW(9368), HTW(-8833), HTW(8285), HTW(-7723), HTW(7150), HTW(-6566), + HTW(5971), HTW(-5368), HTW(4756), HTW(-4137), HTW(3511), HTW(-2880), + HTW(2245), HTW(-1606), HTW(965), HTW(-322)}; + +static const FIXP_DBL preModCos[32] = { + -749875776, 786681536, 711263552, -821592064, -670937792, 854523392, + 628995648, -885396032, -585538240, 914135680, 540670208, -940673088, + -494499680, 964944384, 447137824, -986891008, -398698816, 1006460096, + 349299264, -1023604544, -299058240, 1038283072, 248096752, -1050460288, + -196537584, 1060106816, 144504928, -1067199488, -92124160, 1071721152, + 39521456, -1073660992}; + +static const FIXP_DBL preModSin[32] = { + 768510144, 730789760, -804379072, -691308864, 838310208, 650162560, + -870221760, -607449920, 900036928, 563273856, -927683776, -517740896, + 953095808, 470960608, -976211712, -423045728, 996975808, 374111712, + -1015338112, -324276416, 1031254400, 273659904, -1044686336, -222384144, + 1055601472, 170572640, -1063973632, -118350192, 1069782528, 65842640, + -1073014208, -13176464}; + +/* The cube root function */ +/***************************************************************************** + + functionname: invCubeRootNorm2 + description: delivers 1/cuberoot(op) in Q1.31 format and modified exponent + +*****************************************************************************/ +#define CUBE_ROOT_BITS 7 +#define CUBE_ROOT_VALUES (128 + 2) +#define CUBE_ROOT_BITS_MASK 0x7f +#define CUBE_ROOT_FRACT_BITS_MASK 0x007FFFFF +/* Inverse cube root table for operands running from 0.5 to 1.0 */ +/* (INT) (1.0/cuberoot((op))); */ +/* Implicit exponent is 1. */ + +LNK_SECTION_CONSTDATA +static const FIXP_DBL invCubeRootTab[CUBE_ROOT_VALUES] = { + (0x50a28be6), (0x506d1172), (0x503823c4), (0x5003c05a), (0x4fcfe4c0), + (0x4f9c8e92), (0x4f69bb7d), (0x4f37693b), (0x4f059594), (0x4ed43e5f), + (0x4ea36181), (0x4e72fcea), (0x4e430e98), (0x4e139495), (0x4de48cf5), + (0x4db5f5db), (0x4d87cd73), (0x4d5a11f2), (0x4d2cc19c), (0x4cffdabb), + (0x4cd35ba4), (0x4ca742b7), (0x4c7b8e5c), (0x4c503d05), (0x4c254d2a), + (0x4bfabd50), (0x4bd08c00), (0x4ba6b7cd), (0x4b7d3f53), (0x4b542134), + (0x4b2b5c18), (0x4b02eeb1), (0x4adad7b8), (0x4ab315ea), (0x4a8ba80d), + (0x4a648cec), (0x4a3dc35b), (0x4a174a30), (0x49f1204a), (0x49cb448d), + (0x49a5b5e2), (0x49807339), (0x495b7b86), (0x4936cdc2), (0x491268ec), + (0x48ee4c08), (0x48ca761f), (0x48a6e63e), (0x48839b76), (0x486094de), + (0x483dd190), (0x481b50ad), (0x47f91156), (0x47d712b3), (0x47b553f0), + (0x4793d43c), (0x477292c9), (0x47518ece), (0x4730c785), (0x47103c2d), + (0x46efec06), (0x46cfd655), (0x46affa61), (0x46905777), (0x4670ece4), + (0x4651b9f9), (0x4632be0b), (0x4613f871), (0x45f56885), (0x45d70da5), + (0x45b8e72f), (0x459af487), (0x457d3511), (0x455fa835), (0x45424d5d), + (0x452523f6), (0x45082b6e), (0x44eb6337), (0x44cecac5), (0x44b2618d), + (0x44962708), (0x447a1ab1), (0x445e3c02), (0x44428a7c), (0x4427059e), + (0x440bacec), (0x43f07fe9), (0x43d57e1c), (0x43baa70e), (0x439ffa48), + (0x43857757), (0x436b1dc8), (0x4350ed2b), (0x4336e511), (0x431d050c), + (0x43034cb2), (0x42e9bb98), (0x42d05156), (0x42b70d85), (0x429defc0), + (0x4284f7a2), (0x426c24cb), (0x425376d8), (0x423aed6a), (0x42228823), + (0x420a46a6), (0x41f22898), (0x41da2d9f), (0x41c25561), (0x41aa9f86), + (0x41930bba), (0x417b99a5), (0x416448f5), (0x414d1956), (0x41360a76), + (0x411f1c06), (0x41084db5), (0x40f19f35), (0x40db1039), (0x40c4a074), + (0x40ae4f9b), (0x40981d64), (0x40820985), (0x406c13b6), (0x40563bb1), + (0x4040812e), (0x402ae3e7), (0x40156399), (0x40000000), (0x3FEAB8D9)}; +/* n.a. */ +static const FIXP_DBL invCubeRootCorrection[3] = {0x40000000, 0x50A28BE6, + 0x6597FA95}; + +/***************************************************************************** + * \brief calculate 1.0/cube_root(op), op contains mantissa and exponent + * \param op_m: (i) mantissa of operand, must not be zero (0x0000.0000) or + * negative + * \param op_e: (i) pointer to the exponent of the operand (must be initialized) + * and .. (o) pointer to the exponent of the result + * \return: (o) mantissa of the result + * \description: + * This routine calculates the cube root of the input operand, that is + * given with its mantissa in Q31 format (FIXP_DBL) and its exponent (INT). + * The resulting mantissa is returned in format Q31. The exponent (*op_e) + * is modified accordingly. It is not assured, that the result is fully + * left-aligned but assumed to have not more than 2 bits headroom. There is one + * macro to activate the use of this algorithm: FUNCTION_invCubeRootNorm2 By + * means of activating the macro INVCUBEROOTNORM2_LINEAR_INTERPOLATE_HQ, a + * slightly higher precision is reachable (by default, not active). For DEBUG + * purpose only: a FDK_ASSERT macro validates, if the input mantissa is greater + * zero. + * + */ +static +#ifdef __arm__ + FIXP_DBL __attribute__((always_inline)) + invCubeRootNorm2(FIXP_DBL op_m, INT* op_e) +#else + FIXP_DBL + invCubeRootNorm2(FIXP_DBL op_m, INT* op_e) +#endif +{ + FDK_ASSERT(op_m > FIXP_DBL(0)); + + /* normalize input, calculate shift value */ + INT exponent = (INT)fNormz(op_m) - 1; + op_m <<= exponent; + + INT index = (INT)(op_m >> (DFRACT_BITS - 1 - (CUBE_ROOT_BITS + 1))) & + CUBE_ROOT_BITS_MASK; + FIXP_DBL fract = (FIXP_DBL)(((INT)op_m & CUBE_ROOT_FRACT_BITS_MASK) + << (CUBE_ROOT_BITS + 1)); + FIXP_DBL diff = invCubeRootTab[index + 1] - invCubeRootTab[index]; + op_m = fMultAddDiv2(invCubeRootTab[index], diff << 1, fract); +#if defined(INVCUBEROOTNORM2_LINEAR_INTERPOLATE_HQ) + /* reg1 = t[i] + (t[i+1]-t[i])*fract ... already computed ... + + * (1-fract)fract*(t[i+2]-t[i+1])/2 */ + if (fract != (FIXP_DBL)0) { + /* fract = fract * (1 - fract) */ + fract = fMultDiv2(fract, (FIXP_DBL)((LONG)0x80000000 - (LONG)fract)) << 1; + diff = diff - (invCubeRootTab[index + 2] - invCubeRootTab[index + 1]); + op_m = fMultAddDiv2(op_m, fract, diff); + } +#endif /* INVCUBEROOTNORM2_LINEAR_INTERPOLATE_HQ */ + + /* calculate the output exponent = input * exp/3 = cubicroot(m)*2^(exp/3) + * where 2^(exp/3) = 2^k'*2 or 2^k'*2^(1/3) or 2^k'*2^(2/3) */ + exponent = exponent - *op_e + 3; + INT shift_tmp = + ((INT)fMultDiv2((FIXP_SGL)fAbs(exponent), (FIXP_SGL)0x5556)) >> 16; + if (exponent < 0) { + shift_tmp = -shift_tmp; + } + INT rem = exponent - 3 * shift_tmp; + if (rem < 0) { + rem += 3; + shift_tmp--; + } + + *op_e = shift_tmp; + op_m = fMultDiv2(op_m, invCubeRootCorrection[rem]) << 2; + + return (op_m); +} + + /***************************************************************************** + + functionname: invFourthRootNorm2 + description: delivers 1/FourthRoot(op) in Q1.31 format and modified + exponent + + *****************************************************************************/ + +#define FOURTHROOT_BITS 7 +#define FOURTHROOT_VALUES (128 + 2) +#define FOURTHROOT_BITS_MASK 0x7f +#define FOURTHROOT_FRACT_BITS_MASK 0x007FFFFF + +LNK_SECTION_CONSTDATA +static const FIXP_DBL invFourthRootTab[FOURTHROOT_VALUES] = { + (0x4c1bf829), (0x4bf61977), (0x4bd09843), (0x4bab72ef), (0x4b86a7eb), + (0x4b6235ac), (0x4b3e1ab6), (0x4b1a5592), (0x4af6e4d4), (0x4ad3c718), + (0x4ab0fb03), (0x4a8e7f42), (0x4a6c5288), (0x4a4a7393), (0x4a28e126), + (0x4a079a0c), (0x49e69d16), (0x49c5e91f), (0x49a57d04), (0x498557ac), + (0x49657802), (0x4945dcf9), (0x49268588), (0x490770ac), (0x48e89d6a), + (0x48ca0ac9), (0x48abb7d6), (0x488da3a6), (0x486fcd4f), (0x485233ed), + (0x4834d6a3), (0x4817b496), (0x47faccf0), (0x47de1ee0), (0x47c1a999), + (0x47a56c51), (0x47896643), (0x476d96af), (0x4751fcd6), (0x473697ff), + (0x471b6773), (0x47006a81), (0x46e5a079), (0x46cb08ae), (0x46b0a279), + (0x46966d34), (0x467c683d), (0x466292f4), (0x4648ecbc), (0x462f74fe), + (0x46162b20), (0x45fd0e91), (0x45e41ebe), (0x45cb5b19), (0x45b2c315), + (0x459a562a), (0x458213cf), (0x4569fb81), (0x45520cbc), (0x453a4701), + (0x4522a9d1), (0x450b34b0), (0x44f3e726), (0x44dcc0ba), (0x44c5c0f7), + (0x44aee768), (0x4498339e), (0x4481a527), (0x446b3b96), (0x4454f67e), + (0x443ed576), (0x4428d815), (0x4412fdf3), (0x43fd46ad), (0x43e7b1de), + (0x43d23f23), (0x43bcee1e), (0x43a7be6f), (0x4392afb8), (0x437dc19d), + (0x4368f3c5), (0x435445d6), (0x433fb779), (0x432b4856), (0x4316f81a), + (0x4302c66f), (0x42eeb305), (0x42dabd8a), (0x42c6e5ad), (0x42b32b21), + (0x429f8d96), (0x428c0cc2), (0x4278a859), (0x42656010), (0x4252339e), + (0x423f22bc), (0x422c2d23), (0x4219528b), (0x420692b2), (0x41f3ed51), + (0x41e16228), (0x41cef0f2), (0x41bc9971), (0x41aa5b62), (0x41983687), + (0x41862aa2), (0x41743775), (0x41625cc3), (0x41509a50), (0x413eefe2), + (0x412d5d3e), (0x411be22b), (0x410a7e70), (0x40f931d5), (0x40e7fc23), + (0x40d6dd24), (0x40c5d4a2), (0x40b4e268), (0x40a40642), (0x40933ffc), + (0x40828f64), (0x4071f447), (0x40616e73), (0x4050fdb9), (0x4040a1e6), + (0x40305acc), (0x4020283c), (0x40100a08), (0x40000000), (0x3ff009f9), +}; + +static const FIXP_DBL invFourthRootCorrection[4] = {0x40000000, 0x4C1BF829, + 0x5A82799A, 0x6BA27E65}; + +/* The fourth root function */ +/***************************************************************************** + * \brief calculate 1.0/fourth_root(op), op contains mantissa and exponent + * \param op_m: (i) mantissa of operand, must not be zero (0x0000.0000) or + * negative + * \param op_e: (i) pointer to the exponent of the operand (must be initialized) + * and .. (o) pointer to the exponent of the result + * \return: (o) mantissa of the result + * \description: + * This routine calculates the cube root of the input operand, that is + * given with its mantissa in Q31 format (FIXP_DBL) and its exponent (INT). + * The resulting mantissa is returned in format Q31. The exponent (*op_e) + * is modified accordingly. It is not assured, that the result is fully + * left-aligned but assumed to have not more than 2 bits headroom. There is one + * macro to activate the use of this algorithm: FUNCTION_invFourthRootNorm2 By + * means of activating the macro INVFOURTHROOTNORM2_LINEAR_INTERPOLATE_HQ, a + * slightly higher precision is reachable (by default, not active). For DEBUG + * purpose only: a FDK_ASSERT macro validates, if the input mantissa is greater + * zero. + * + */ + +/* #define INVFOURTHROOTNORM2_LINEAR_INTERPOLATE_HQ */ + +static +#ifdef __arm__ + FIXP_DBL __attribute__((always_inline)) + invFourthRootNorm2(FIXP_DBL op_m, INT* op_e) +#else + FIXP_DBL + invFourthRootNorm2(FIXP_DBL op_m, INT* op_e) +#endif +{ + FDK_ASSERT(op_m > FL2FXCONST_DBL(0.0)); + + /* normalize input, calculate shift value */ + INT exponent = (INT)fNormz(op_m) - 1; + op_m <<= exponent; + + INT index = (INT)(op_m >> (DFRACT_BITS - 1 - (FOURTHROOT_BITS + 1))) & + FOURTHROOT_BITS_MASK; + FIXP_DBL fract = (FIXP_DBL)(((INT)op_m & FOURTHROOT_FRACT_BITS_MASK) + << (FOURTHROOT_BITS + 1)); + FIXP_DBL diff = invFourthRootTab[index + 1] - invFourthRootTab[index]; + op_m = invFourthRootTab[index] + (fMultDiv2(diff, fract) << 1); + +#if defined(INVFOURTHROOTNORM2_LINEAR_INTERPOLATE_HQ) + /* reg1 = t[i] + (t[i+1]-t[i])*fract ... already computed ... + + * (1-fract)fract*(t[i+2]-t[i+1])/2 */ + if (fract != (FIXP_DBL)0) { + /* fract = fract * (1 - fract) */ + fract = fMultDiv2(fract, (FIXP_DBL)((LONG)0x80000000 - (LONG)fract)) << 1; + diff = diff - (invFourthRootTab[index + 2] - invFourthRootTab[index + 1]); + op_m = fMultAddDiv2(op_m, fract, diff); + } +#endif /* INVFOURTHROOTNORM2_LINEAR_INTERPOLATE_HQ */ + + exponent = exponent - *op_e + 4; + INT rem = exponent & 0x00000003; + INT shift_tmp = (exponent >> 2); + + *op_e = shift_tmp; + op_m = fMultDiv2(op_m, invFourthRootCorrection[rem]) << 2; + + return (op_m); +} + +/***************************************************************************** + + functionname: inv3EigthRootNorm2 + description: delivers 1/cubert(op) normalized to .5...1 and the shift value +of the OUTPUT + +*****************************************************************************/ +#define THREEIGTHROOT_BITS 7 +#define THREEIGTHROOT_VALUES (128 + 2) +#define THREEIGTHROOT_BITS_MASK 0x7f +#define THREEIGTHROOT_FRACT_BITS_MASK 0x007FFFFF + +LNK_SECTION_CONSTDATA +static const FIXP_DBL inv3EigthRootTab[THREEIGTHROOT_VALUES] = { + (0x45cae0f2), (0x45b981bf), (0x45a8492a), (0x45973691), (0x45864959), + (0x457580e6), (0x4564dca4), (0x45545c00), (0x4543fe6b), (0x4533c35a), + (0x4523aa44), (0x4513b2a4), (0x4503dbf7), (0x44f425be), (0x44e48f7b), + (0x44d518b6), (0x44c5c0f7), (0x44b687c8), (0x44a76cb8), (0x44986f58), + (0x44898f38), (0x447acbef), (0x446c2514), (0x445d9a3f), (0x444f2b0d), + (0x4440d71a), (0x44329e07), (0x44247f73), (0x44167b04), (0x4408905e), + (0x43fabf28), (0x43ed070b), (0x43df67b0), (0x43d1e0c5), (0x43c471f7), + (0x43b71af6), (0x43a9db71), (0x439cb31c), (0x438fa1ab), (0x4382a6d2), + (0x4375c248), (0x4368f3c5), (0x435c3b03), (0x434f97bc), (0x434309ac), + (0x43369091), (0x432a2c28), (0x431ddc30), (0x4311a06c), (0x4305789c), + (0x42f96483), (0x42ed63e5), (0x42e17688), (0x42d59c30), (0x42c9d4a6), + (0x42be1fb1), (0x42b27d1a), (0x42a6ecac), (0x429b6e2f), (0x42900172), + (0x4284a63f), (0x42795c64), (0x426e23b0), (0x4262fbf2), (0x4257e4f9), + (0x424cde96), (0x4241e89a), (0x423702d8), (0x422c2d23), (0x4221674d), + (0x4216b12c), (0x420c0a94), (0x4201735b), (0x41f6eb57), (0x41ec725f), + (0x41e2084b), (0x41d7acf3), (0x41cd6030), (0x41c321db), (0x41b8f1ce), + (0x41aecfe5), (0x41a4bbf8), (0x419ab5e6), (0x4190bd89), (0x4186d2bf), + (0x417cf565), (0x41732558), (0x41696277), (0x415faca1), (0x415603b4), + (0x414c6792), (0x4142d818), (0x4139552a), (0x412fdea6), (0x41267470), + (0x411d1668), (0x4113c472), (0x410a7e70), (0x41014445), (0x40f815d4), + (0x40eef302), (0x40e5dbb4), (0x40dccfcd), (0x40d3cf33), (0x40cad9cb), + (0x40c1ef7b), (0x40b9102a), (0x40b03bbd), (0x40a7721c), (0x409eb32e), + (0x4095feda), (0x408d5508), (0x4084b5a0), (0x407c208b), (0x407395b2), + (0x406b14fd), (0x40629e56), (0x405a31a6), (0x4051ced8), (0x404975d5), + (0x40412689), (0x4038e0dd), (0x4030a4bd), (0x40287215), (0x402048cf), + (0x401828d7), (0x4010121a), (0x40080483), (0x40000000), (0x3ff8047d), +}; + +/* The last value is rounded in order to avoid any overflow due to the values + * range of the root table */ +static const FIXP_DBL inv3EigthRootCorrection[8] = { + 0x40000000, 0x45CAE0F2, 0x4C1BF829, 0x52FF6B55, + 0x5A82799A, 0x62B39509, 0x6BA27E65, 0x75606373}; + +/* The 3/8 root function */ +/***************************************************************************** + * \brief calculate 1.0/3Eigth_root(op) = 1.0/(x)^(3/8), op contains mantissa + * and exponent + * \param op_m: (i) mantissa of operand, must not be zero (0x0000.0000) or + * negative + * \param op_e: (i) pointer to the exponent of the operand (must be initialized) + * and .. (o) pointer to the exponent of the result + * \return: (o) mantissa of the result + * \description: + * This routine calculates the cube root of the input operand, that is + * given with its mantissa in Q31 format (FIXP_DBL) and its exponent (INT). + * The resulting mantissa is returned in format Q31. The exponent (*op_e) + * is modified accordingly. It is not assured, that the result is fully + * left-aligned but assumed to have not more than 2 bits headroom. There is one + * macro to activate the use of this algorithm: FUNCTION_inv3EigthRootNorm2 By + * means of activating the macro INVTHREEIGTHROOTNORM2_LINEAR_INTERPOLATE_HQ, a + * slightly higher precision is reachable (by default, not active). For DEBUG + * purpose only: a FDK_ASSERT macro validates, if the input mantissa is greater + * zero. + * + */ + +/* #define INVTHREEIGTHROOTNORM2_LINEAR_INTERPOLATE_HQ */ + +static +#ifdef __arm__ + FIXP_DBL __attribute__((always_inline)) + inv3EigthRootNorm2(FIXP_DBL op_m, INT* op_e) +#else + FIXP_DBL + inv3EigthRootNorm2(FIXP_DBL op_m, INT* op_e) +#endif +{ + FDK_ASSERT(op_m > FL2FXCONST_DBL(0.0)); + + /* normalize input, calculate shift op_mue */ + INT exponent = (INT)fNormz(op_m) - 1; + op_m <<= exponent; + + INT index = (INT)(op_m >> (DFRACT_BITS - 1 - (THREEIGTHROOT_BITS + 1))) & + THREEIGTHROOT_BITS_MASK; + FIXP_DBL fract = (FIXP_DBL)(((INT)op_m & THREEIGTHROOT_FRACT_BITS_MASK) + << (THREEIGTHROOT_BITS + 1)); + FIXP_DBL diff = inv3EigthRootTab[index + 1] - inv3EigthRootTab[index]; + op_m = inv3EigthRootTab[index] + (fMultDiv2(diff, fract) << 1); + +#if defined(INVTHREEIGTHROOTNORM2_LINEAR_INTERPOLATE_HQ) + /* op_m = t[i] + (t[i+1]-t[i])*fract ... already computed ... + + * (1-fract)fract*(t[i+2]-t[i+1])/2 */ + if (fract != (FIXP_DBL)0) { + /* fract = fract * (1 - fract) */ + fract = fMultDiv2(fract, (FIXP_DBL)((LONG)0x80000000 - (LONG)fract)) << 1; + diff = diff - (inv3EigthRootTab[index + 2] - inv3EigthRootTab[index + 1]); + op_m = fMultAddDiv2(op_m, fract, diff); + } +#endif /* INVTHREEIGTHROOTNORM2_LINEAR_INTERPOLATE_HQ */ + + exponent = exponent - *op_e + 8; + INT rem = exponent & 0x00000007; + INT shift_tmp = (exponent >> 3); + + *op_e = shift_tmp * 3; + op_m = fMultDiv2(op_m, inv3EigthRootCorrection[rem]) << 2; + + return (fMult(op_m, fMult(op_m, op_m))); +} + +SBR_ERROR +QmfTransposerCreate(HANDLE_HBE_TRANSPOSER* hQmfTransposer, const int frameSize, + int bDisableCrossProducts, int bSbr41) { + HANDLE_HBE_TRANSPOSER hQmfTran = NULL; + + int i; + + if (hQmfTransposer != NULL) { + /* Memory allocation */ + /*--------------------------------------------------------------------------------------------*/ + hQmfTran = + (HANDLE_HBE_TRANSPOSER)FDKcalloc(1, sizeof(struct hbeTransposer)); + if (hQmfTran == NULL) { + return SBRDEC_MEM_ALLOC_FAILED; + } + + for (i = 0; i < MAX_STRETCH_HBE - 1; i++) { + hQmfTran->bXProducts[i] = (bDisableCrossProducts ? 0 : xProducts[i]); + } + + hQmfTran->timeDomainWinLen = frameSize; + if (frameSize == 768) { + hQmfTran->noCols = + (8 * frameSize / 3) / QMF_SYNTH_CHANNELS; /* 32 for 24:64 */ + } else { + hQmfTran->noCols = + (bSbr41 + 1) * 2 * frameSize / + QMF_SYNTH_CHANNELS; /* 32 for 32:64 and 64 for 16:64 -> identical to + sbrdec->no_cols */ + } + + hQmfTran->noChannels = frameSize / hQmfTran->noCols; + + hQmfTran->qmfInBufSize = QMF_WIN_LEN; + hQmfTran->qmfOutBufSize = 2 * (hQmfTran->noCols / 2 + QMF_WIN_LEN - 1); + + hQmfTran->inBuf_F = + (INT_PCM*)FDKcalloc(QMF_SYNTH_CHANNELS + 20 + 1, sizeof(INT_PCM)); + /* buffered time signal needs to be delayed by synthesis_size; max + * synthesis_size = 20; */ + if (hQmfTran->inBuf_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + + hQmfTran->qmfInBufReal_F = + (FIXP_DBL**)FDKcalloc(hQmfTran->qmfInBufSize, sizeof(FIXP_DBL*)); + hQmfTran->qmfInBufImag_F = + (FIXP_DBL**)FDKcalloc(hQmfTran->qmfInBufSize, sizeof(FIXP_DBL*)); + + if (hQmfTran->qmfInBufReal_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + if (hQmfTran->qmfInBufImag_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + + for (i = 0; i < hQmfTran->qmfInBufSize; i++) { + hQmfTran->qmfInBufReal_F[i] = (FIXP_DBL*)FDKaalloc( + QMF_SYNTH_CHANNELS * sizeof(FIXP_DBL), ALIGNMENT_DEFAULT); + hQmfTran->qmfInBufImag_F[i] = (FIXP_DBL*)FDKaalloc( + QMF_SYNTH_CHANNELS * sizeof(FIXP_DBL), ALIGNMENT_DEFAULT); + if (hQmfTran->qmfInBufReal_F[i] == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + if (hQmfTran->qmfInBufImag_F[i] == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + } + + hQmfTran->qmfHBEBufReal_F = + (FIXP_DBL**)FDKcalloc(HBE_MAX_OUT_SLOTS, sizeof(FIXP_DBL*)); + hQmfTran->qmfHBEBufImag_F = + (FIXP_DBL**)FDKcalloc(HBE_MAX_OUT_SLOTS, sizeof(FIXP_DBL*)); + + if (hQmfTran->qmfHBEBufReal_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + if (hQmfTran->qmfHBEBufImag_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + + for (i = 0; i < HBE_MAX_OUT_SLOTS; i++) { + hQmfTran->qmfHBEBufReal_F[i] = + (FIXP_DBL*)FDKcalloc(QMF_SYNTH_CHANNELS, sizeof(FIXP_DBL)); + hQmfTran->qmfHBEBufImag_F[i] = + (FIXP_DBL*)FDKcalloc(QMF_SYNTH_CHANNELS, sizeof(FIXP_DBL)); + if (hQmfTran->qmfHBEBufReal_F[i] == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + if (hQmfTran->qmfHBEBufImag_F[i] == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + } + + hQmfTran->qmfBufferCodecTempSlot_F = + (FIXP_DBL*)FDKcalloc(QMF_SYNTH_CHANNELS / 2, sizeof(FIXP_DBL)); + if (hQmfTran->qmfBufferCodecTempSlot_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + + hQmfTran->bSbr41 = bSbr41; + + hQmfTran->highband_exp[0] = 0; + hQmfTran->highband_exp[1] = 0; + hQmfTran->target_exp[0] = 0; + hQmfTran->target_exp[1] = 0; + + *hQmfTransposer = hQmfTran; + } + + return SBRDEC_OK; +} + +SBR_ERROR QmfTransposerReInit(HANDLE_HBE_TRANSPOSER hQmfTransposer, + UCHAR* FreqBandTable[2], UCHAR NSfb[2]) +/* removed bSbr41 from parameterlist: + don't know where to get this value from + at call-side */ +{ + int L, sfb, patch, stopPatch, qmfErr; + + if (hQmfTransposer != NULL) { + const FIXP_QTW* tmp_t_cos; + const FIXP_QTW* tmp_t_sin; + + hQmfTransposer->startBand = FreqBandTable[0][0]; + hQmfTransposer->stopBand = FreqBandTable[0][NSfb[0]]; + + hQmfTransposer->synthSize = + 4 * ((hQmfTransposer->startBand + 4) / 8 + 1); /* 8, 12, 16, 20 */ + hQmfTransposer->kstart = startSubband2kL[hQmfTransposer->startBand]; + + /* don't know where to take this information from */ + /* hQmfTransposer->bSbr41 = bSbr41; */ + + if (hQmfTransposer->bSbr41) { + if (hQmfTransposer->kstart + hQmfTransposer->synthSize > 16) + hQmfTransposer->kstart = 16 - hQmfTransposer->synthSize; + } else if (hQmfTransposer->timeDomainWinLen == 768) { + if (hQmfTransposer->kstart + hQmfTransposer->synthSize > 24) + hQmfTransposer->kstart = 24 - hQmfTransposer->synthSize; + } + + hQmfTransposer->synthesisQmfPreModCos_F = + &preModCos[hQmfTransposer->kstart]; + hQmfTransposer->synthesisQmfPreModSin_F = + &preModSin[hQmfTransposer->kstart]; + + L = 2 * hQmfTransposer->synthSize; /* 8, 16, 24, 32, 40 */ + /* Change analysis post twiddles */ + + switch (L) { + case 8: + tmp_t_cos = post_twiddle_cos_8; + tmp_t_sin = post_twiddle_sin_8; + break; + case 16: + tmp_t_cos = post_twiddle_cos_16; + tmp_t_sin = post_twiddle_sin_16; + break; + case 24: + tmp_t_cos = post_twiddle_cos_24; + tmp_t_sin = post_twiddle_sin_24; + break; + case 32: + tmp_t_cos = post_twiddle_cos_32; + tmp_t_sin = post_twiddle_sin_32; + break; + case 40: + tmp_t_cos = post_twiddle_cos_40; + tmp_t_sin = post_twiddle_sin_40; + break; + default: + return SBRDEC_UNSUPPORTED_CONFIG; + } + + qmfErr = qmfInitSynthesisFilterBank( + &hQmfTransposer->HBESynthesisQMF, hQmfTransposer->synQmfStates, + hQmfTransposer->noCols, 0, hQmfTransposer->synthSize, + hQmfTransposer->synthSize, 1); + if (qmfErr != 0) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + qmfErr = qmfInitAnalysisFilterBank( + &hQmfTransposer->HBEAnalysiscQMF, hQmfTransposer->anaQmfStates, + hQmfTransposer->noCols / 2, 0, 2 * hQmfTransposer->synthSize, + 2 * hQmfTransposer->synthSize, 0); + + if (qmfErr != 0) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + hQmfTransposer->HBEAnalysiscQMF.t_cos = tmp_t_cos; + hQmfTransposer->HBEAnalysiscQMF.t_sin = tmp_t_sin; + + FDKmemset(hQmfTransposer->xOverQmf, 0, + MAX_NUM_PATCHES * sizeof(int)); /* global */ + sfb = 0; + if (hQmfTransposer->bSbr41) { + stopPatch = MAX_NUM_PATCHES; + hQmfTransposer->maxStretch = MAX_STRETCH_HBE; + } else { + stopPatch = MAX_STRETCH_HBE; + } + + for (patch = 1; patch <= stopPatch; patch++) { + while (sfb <= NSfb[0] && + FreqBandTable[0][sfb] <= patch * hQmfTransposer->startBand) + sfb++; + if (sfb <= NSfb[0]) { + /* If the distance is larger than three QMF bands - try aligning to high + * resolution frequency bands instead. */ + if ((patch * hQmfTransposer->startBand - FreqBandTable[0][sfb - 1]) <= + 3) { + hQmfTransposer->xOverQmf[patch - 1] = FreqBandTable[0][sfb - 1]; + } else { + int sfb_tmp = 0; + while (sfb_tmp <= NSfb[1] && + FreqBandTable[1][sfb_tmp] <= patch * hQmfTransposer->startBand) + sfb_tmp++; + hQmfTransposer->xOverQmf[patch - 1] = FreqBandTable[1][sfb_tmp - 1]; + } + } else { + hQmfTransposer->xOverQmf[patch - 1] = hQmfTransposer->stopBand; + hQmfTransposer->maxStretch = fMin(patch, MAX_STRETCH_HBE); + break; + } + } + + hQmfTransposer->highband_exp[0] = 0; + hQmfTransposer->highband_exp[1] = 0; + hQmfTransposer->target_exp[0] = 0; + hQmfTransposer->target_exp[1] = 0; + } + + return SBRDEC_OK; +} + +void QmfTransposerClose(HANDLE_HBE_TRANSPOSER hQmfTransposer) { + int i; + + if (hQmfTransposer != NULL) { + if (hQmfTransposer->inBuf_F) FDKfree(hQmfTransposer->inBuf_F); + + if (hQmfTransposer->qmfInBufReal_F) { + for (i = 0; i < hQmfTransposer->qmfInBufSize; i++) { + FDKafree(hQmfTransposer->qmfInBufReal_F[i]); + } + FDKfree(hQmfTransposer->qmfInBufReal_F); + } + + if (hQmfTransposer->qmfInBufImag_F) { + for (i = 0; i < hQmfTransposer->qmfInBufSize; i++) { + FDKafree(hQmfTransposer->qmfInBufImag_F[i]); + } + FDKfree(hQmfTransposer->qmfInBufImag_F); + } + + if (hQmfTransposer->qmfHBEBufReal_F) { + for (i = 0; i < HBE_MAX_OUT_SLOTS; i++) { + FDKfree(hQmfTransposer->qmfHBEBufReal_F[i]); + } + FDKfree(hQmfTransposer->qmfHBEBufReal_F); + } + + if (hQmfTransposer->qmfHBEBufImag_F) { + for (i = 0; i < HBE_MAX_OUT_SLOTS; i++) { + FDKfree(hQmfTransposer->qmfHBEBufImag_F[i]); + } + FDKfree(hQmfTransposer->qmfHBEBufImag_F); + } + + FDKfree(hQmfTransposer->qmfBufferCodecTempSlot_F); + + FDKfree(hQmfTransposer); + } +} + +inline void scaleUp(FIXP_DBL* real_m, FIXP_DBL* imag_m, INT* _e) { + INT reserve; + /* shift gc_r and gc_i up if possible */ + reserve = CntLeadingZeros((INT(*real_m) ^ INT((*real_m >> 31))) | + (INT(*imag_m) ^ INT((*imag_m >> 31)))) - + 1; + reserve = fMax(reserve - 1, + 0); /* Leave one bit headroom such that (real_m^2 + imag_m^2) + does not overflow later if both are 0x80000000. */ + reserve = fMin(reserve, *_e); + FDK_ASSERT(reserve >= 0); + *real_m <<= reserve; + *imag_m <<= reserve; + *_e -= reserve; +} + +static void calculateCenterFIXP(FIXP_DBL gammaVecReal, FIXP_DBL gammaVecImag, + FIXP_DBL* centerReal, FIXP_DBL* centerImag, + INT* exponent, int stretch, int mult) { + scaleUp(&gammaVecReal, &gammaVecImag, exponent); + FIXP_DBL energy = fPow2Div2(gammaVecReal) + fPow2Div2(gammaVecImag); + + if (energy != FL2FXCONST_DBL(0.f)) { + FIXP_DBL gc_r_m, gc_i_m, factor_m = (FIXP_DBL)0; + INT factor_e, gc_e; + factor_e = 2 * (*exponent) + 1; + + switch (stretch) { + case 2: + factor_m = invFourthRootNorm2(energy, &factor_e); + break; + case 3: + factor_m = invCubeRootNorm2(energy, &factor_e); + break; + case 4: + factor_m = inv3EigthRootNorm2(energy, &factor_e); + break; + } + + gc_r_m = fMultDiv2(gammaVecReal, + factor_m); /* exponent = HBE_SCALE + factor_e + 1 */ + gc_i_m = fMultDiv2(gammaVecImag, + factor_m); /* exponent = HBE_SCALE + factor_e + 1*/ + gc_e = *exponent + factor_e + 1; + + scaleUp(&gc_r_m, &gc_i_m, &gc_e); + + switch (mult) { + case 0: + *centerReal = gc_r_m; + *centerImag = gc_i_m; + break; + case 1: + *centerReal = fPow2Div2(gc_r_m) - fPow2Div2(gc_i_m); + *centerImag = fMult(gc_r_m, gc_i_m); + gc_e = 2 * gc_e + 1; + break; + case 2: + FIXP_DBL tmp_r = gc_r_m; + FIXP_DBL tmp_i = gc_i_m; + gc_r_m = fPow2Div2(gc_r_m) - fPow2Div2(gc_i_m); + gc_i_m = fMult(tmp_r, gc_i_m); + gc_e = 3 * gc_e + 1 + 1; + cplxMultDiv2(¢erReal[0], ¢erImag[0], gc_r_m, gc_i_m, tmp_r, + tmp_i); + break; + } + + scaleUp(centerReal, centerImag, &gc_e); + + FDK_ASSERT(gc_e >= 0); + *exponent = gc_e; + } else { + *centerReal = energy; /* energy = 0 */ + *centerImag = energy; /* energy = 0 */ + *exponent = (INT)energy; + } +} + +static int getHBEScaleFactorFrame(const int bSbr41, const int maxStretch, + const int pitchInBins) { + if (pitchInBins >= pmin * (1 + bSbr41)) { + /* crossproducts enabled */ + return 26; + } else { + return (maxStretch == 2) ? 24 : 25; + } +} + +static void addHighBandPart(FIXP_DBL g_r_m, FIXP_DBL g_i_m, INT g_e, + FIXP_DBL mult, FIXP_DBL gammaCenterReal_m, + FIXP_DBL gammaCenterImag_m, INT gammaCenter_e, + INT stretch, INT scale_factor_hbe, + FIXP_DBL* qmfHBEBufReal_F, + FIXP_DBL* qmfHBEBufImag_F) { + if ((g_r_m | g_i_m) != FL2FXCONST_DBL(0.f)) { + FIXP_DBL factor_m = (FIXP_DBL)0; + INT factor_e; + INT add = (stretch == 4) ? 1 : 0; + INT shift = (stretch == 4) ? 1 : 2; + + scaleUp(&g_r_m, &g_i_m, &g_e); + FIXP_DBL energy = fPow2AddDiv2(fPow2Div2(g_r_m), g_i_m); + factor_e = 2 * g_e + 1; + + switch (stretch) { + case 2: + factor_m = invFourthRootNorm2(energy, &factor_e); + break; + case 3: + factor_m = invCubeRootNorm2(energy, &factor_e); + break; + case 4: + factor_m = inv3EigthRootNorm2(energy, &factor_e); + break; + } + + factor_m = fMult(factor_m, mult); + + FIXP_DBL tmp_r, tmp_i; + cplxMultDiv2(&tmp_r, &tmp_i, g_r_m, g_i_m, gammaCenterReal_m, + gammaCenterImag_m); + + g_r_m = fMultDiv2(tmp_r, factor_m) << shift; + g_i_m = fMultDiv2(tmp_i, factor_m) << shift; + g_e = scale_factor_hbe - (g_e + factor_e + gammaCenter_e + add); + fMax((INT)0, g_e); + *qmfHBEBufReal_F += g_r_m >> g_e; + *qmfHBEBufImag_F += g_i_m >> g_e; + } +} + +void QmfTransposerApply(HANDLE_HBE_TRANSPOSER hQmfTransposer, + FIXP_DBL** qmfBufferCodecReal, + FIXP_DBL** qmfBufferCodecImag, int nColsIn, + FIXP_DBL** ppQmfBufferOutReal_F, + FIXP_DBL** ppQmfBufferOutImag_F, + FIXP_DBL lpcFilterStatesReal[2 + (3 * (4))][(64)], + FIXP_DBL lpcFilterStatesImag[2 + (3 * (4))][(64)], + int pitchInBins, int scale_lb, int scale_hbe, + int* scale_hb, int timeStep, int firstSlotOffsset, + int ov_len, + KEEP_STATES_SYNCED_MODE keepStatesSyncedMode) { + int i, j, stretch, band, sourceband, r, s; + int qmfVocoderColsIn = hQmfTransposer->noCols / 2; + int bSbr41 = hQmfTransposer->bSbr41; + + const int winLength[3] = {10, 8, 6}; + const int slotOffset = 6; /* hQmfTransposer->winLen-6; */ + + int qmfOffset = 2 * hQmfTransposer->kstart; + int scale_border = (nColsIn == 64) ? 32 : nColsIn; + + INT slot_stretch4[9] = {0, 0, 0, 0, 2, 4, 6, 8, 10}; + INT slot_stretch2[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + INT slot_stretch3[10] = {0, 0, 0, 1, 3, 4, 6, 7, 9, 10}; + INT filt_stretch3[10] = {0, 0, 0, 1, 0, 1, 0, 1, 0, 1}; + INT filt_dummy[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + INT* pSlotStretch; + INT* pFilt; + + int offset = 0; /* where to take QmfTransposer data */ + + int signPreMod = + (hQmfTransposer->synthesisQmfPreModCos_F[0] < FL2FXCONST_DBL(0.f)) ? 1 + : -1; + + int scale_factor_hbe = + getHBEScaleFactorFrame(bSbr41, hQmfTransposer->maxStretch, pitchInBins); + + if (keepStatesSyncedMode != KEEP_STATES_SYNCED_OFF) { + offset = hQmfTransposer->noCols - ov_len - LPC_ORDER; + } + + hQmfTransposer->highband_exp[0] = hQmfTransposer->highband_exp[1]; + hQmfTransposer->target_exp[0] = hQmfTransposer->target_exp[1]; + + hQmfTransposer->highband_exp[1] = scale_factor_hbe; + hQmfTransposer->target_exp[1] = + fixMax(hQmfTransposer->highband_exp[1], hQmfTransposer->highband_exp[0]); + + scale_factor_hbe = hQmfTransposer->target_exp[1]; + + int shift_ov = hQmfTransposer->target_exp[0] - hQmfTransposer->target_exp[1]; + + if (shift_ov != 0) { + for (i = 0; i < HBE_MAX_OUT_SLOTS; i++) { + for (band = 0; band < QMF_SYNTH_CHANNELS; band++) { + if (shift_ov >= 0) { + hQmfTransposer->qmfHBEBufReal_F[i][band] <<= shift_ov; + hQmfTransposer->qmfHBEBufImag_F[i][band] <<= shift_ov; + } else { + hQmfTransposer->qmfHBEBufReal_F[i][band] >>= (-shift_ov); + hQmfTransposer->qmfHBEBufImag_F[i][band] >>= (-shift_ov); + } + } + } + } + + if ((keepStatesSyncedMode == KEEP_STATES_SYNCED_OFF) && shift_ov != 0) { + for (i = timeStep * firstSlotOffsset; i < ov_len; i++) { + for (band = hQmfTransposer->startBand; band < hQmfTransposer->stopBand; + band++) { + if (shift_ov >= 0) { + ppQmfBufferOutReal_F[i][band] <<= shift_ov; + ppQmfBufferOutImag_F[i][band] <<= shift_ov; + } else { + ppQmfBufferOutReal_F[i][band] >>= (-shift_ov); + ppQmfBufferOutImag_F[i][band] >>= (-shift_ov); + } + } + } + + /* shift lpc filterstates */ + for (i = 0; i < timeStep * firstSlotOffsset + LPC_ORDER; i++) { + for (band = 0; band < (64); band++) { + if (shift_ov >= 0) { + lpcFilterStatesReal[i][band] <<= shift_ov; + lpcFilterStatesImag[i][band] <<= shift_ov; + } else { + lpcFilterStatesReal[i][band] >>= (-shift_ov); + lpcFilterStatesImag[i][band] >>= (-shift_ov); + } + } + } + } + + FIXP_DBL twid_m_new[3][2]; /* [stretch][cos/sin] */ + INT stepsize = 1 + !bSbr41, sine_offset = 24, mod = 96; + INT mult[3] = {1, 2, 3}; + + for (s = 0; s <= MAX_STRETCH_HBE - 2; s++) { + twid_m_new[s][0] = twiddle[(mult[s] * (stepsize * pitchInBins)) % mod]; + twid_m_new[s][1] = + twiddle[((mult[s] * (stepsize * pitchInBins)) + sine_offset) % mod]; + } + + /* Time-stretch */ + for (j = 0; j < qmfVocoderColsIn; j++) { + int sign = -1, k, z, addrshift, codecTemp_e; + /* update inbuf */ + for (i = 0; i < hQmfTransposer->synthSize; i++) { + hQmfTransposer->inBuf_F[i] = + hQmfTransposer->inBuf_F[i + 2 * hQmfTransposer->synthSize]; + } + + /* run synthesis for two sbr slots as transposer uses + half slots double bands representation */ + for (z = 0; z < 2; z++) { + int scale_factor = ((nColsIn == 64) && ((2 * j + z) < scale_border)) + ? scale_lb + : scale_hbe; + codecTemp_e = scale_factor - 1; /* -2 for Div2 and cos/sin scale of 1 */ + + for (k = 0; k < hQmfTransposer->synthSize; k++) { + int ki = hQmfTransposer->kstart + k; + hQmfTransposer->qmfBufferCodecTempSlot_F[k] = + fMultDiv2(signPreMod * hQmfTransposer->synthesisQmfPreModCos_F[k], + qmfBufferCodecReal[2 * j + z][ki]); + hQmfTransposer->qmfBufferCodecTempSlot_F[k] += + fMultDiv2(signPreMod * hQmfTransposer->synthesisQmfPreModSin_F[k], + qmfBufferCodecImag[2 * j + z][ki]); + } + + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, (HBE_MAX_QMF_BANDS << 1)); + + qmfSynthesisFilteringSlot( + &hQmfTransposer->HBESynthesisQMF, + hQmfTransposer->qmfBufferCodecTempSlot_F, NULL, 0, + -7 - hQmfTransposer->HBESynthesisQMF.filterScale - codecTemp_e + 1, + hQmfTransposer->inBuf_F + hQmfTransposer->synthSize * (z + 1), 1, + pWorkBuffer); + + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, (HBE_MAX_QMF_BANDS << 1)); + } + + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, (HBE_MAX_QMF_BANDS << 1)); + + qmfAnalysisFilteringSlot(&hQmfTransposer->HBEAnalysiscQMF, + hQmfTransposer->qmfInBufReal_F[QMF_WIN_LEN - 1], + hQmfTransposer->qmfInBufImag_F[QMF_WIN_LEN - 1], + hQmfTransposer->inBuf_F + 1, 1, pWorkBuffer); + + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, (HBE_MAX_QMF_BANDS << 1)); + + if ((keepStatesSyncedMode == KEEP_STATES_SYNCED_NORMAL) && + j <= qmfVocoderColsIn - ((LPC_ORDER + ov_len + QMF_WIN_LEN - 1) >> 1)) { + /* update in buffer */ + for (i = 0; i < QMF_WIN_LEN - 1; i++) { + FDKmemcpy( + hQmfTransposer->qmfInBufReal_F[i], + hQmfTransposer->qmfInBufReal_F[i + 1], + sizeof(FIXP_DBL) * hQmfTransposer->HBEAnalysiscQMF.no_channels); + FDKmemcpy( + hQmfTransposer->qmfInBufImag_F[i], + hQmfTransposer->qmfInBufImag_F[i + 1], + sizeof(FIXP_DBL) * hQmfTransposer->HBEAnalysiscQMF.no_channels); + } + continue; + } + + for (stretch = 2; stretch <= hQmfTransposer->maxStretch; stretch++) { + int start = slotOffset - winLength[stretch - 2] / 2; + int stop = slotOffset + winLength[stretch - 2] / 2; + + FIXP_DBL factor = FL2FXCONST_DBL(1.f / 3.f); + + for (band = hQmfTransposer->xOverQmf[stretch - 2]; + band < hQmfTransposer->xOverQmf[stretch - 1]; band++) { + FIXP_DBL gammaCenterReal_m[2] = {(FIXP_DBL)0, (FIXP_DBL)0}, + gammaCenterImag_m[2] = {(FIXP_DBL)0, (FIXP_DBL)0}; + INT gammaCenter_e[2] = {0, 0}; + + FIXP_DBL gammaVecReal_m[2] = {(FIXP_DBL)0, (FIXP_DBL)0}, + gammaVecImag_m[2] = {(FIXP_DBL)0, (FIXP_DBL)0}; + INT gammaVec_e[2] = {0, 0}; + + FIXP_DBL wingain = (FIXP_DBL)0; + + gammaCenter_e[0] = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + gammaCenter_e[1] = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + + /* interpolation filters for 3rd order */ + sourceband = 2 * band / stretch - qmfOffset; + FDK_ASSERT(sourceband >= 0); + + /* maximum gammaCenter_e == 20 */ + calculateCenterFIXP( + hQmfTransposer->qmfInBufReal_F[slotOffset][sourceband], + hQmfTransposer->qmfInBufImag_F[slotOffset][sourceband], + &gammaCenterReal_m[0], &gammaCenterImag_m[0], &gammaCenter_e[0], + stretch, stretch - 2); + + if (stretch == 4) { + r = band - 2 * (band / 2); + sourceband += (r == 0) ? -1 : 1; + pSlotStretch = slot_stretch4; + factor = FL2FXCONST_DBL(2.f / 3.f); + pFilt = filt_dummy; + } else if (stretch == 2) { + r = 0; + sourceband = 2 * band / stretch - qmfOffset; + pSlotStretch = slot_stretch2; + factor = FL2FXCONST_DBL(1.f / 3.f); + pFilt = filt_dummy; + } else { + r = 2 * band - 3 * (2 * band / 3); + sourceband = 2 * band / stretch - qmfOffset; + pSlotStretch = slot_stretch3; + factor = FL2FXCONST_DBL(1.4142f / 3.0f); + pFilt = filt_stretch3; + } + + if (r == 2) { + calculateCenterFIXP( + hQmfTransposer->qmfInBufReal_F[slotOffset][sourceband + 1], + hQmfTransposer->qmfInBufImag_F[slotOffset][sourceband + 1], + &gammaCenterReal_m[1], &gammaCenterImag_m[1], &gammaCenter_e[1], + stretch, stretch - 2); + + factor = FL2FXCONST_DBL(1.4142f / 6.0f); + } + + if (r == 2) { + for (k = start; k < stop; k++) { + gammaVecReal_m[0] = + hQmfTransposer->qmfInBufReal_F[pSlotStretch[k]][sourceband]; + gammaVecReal_m[1] = + hQmfTransposer->qmfInBufReal_F[pSlotStretch[k]][sourceband + 1]; + gammaVecImag_m[0] = + hQmfTransposer->qmfInBufImag_F[pSlotStretch[k]][sourceband]; + gammaVecImag_m[1] = + hQmfTransposer->qmfInBufImag_F[pSlotStretch[k]][sourceband + 1]; + gammaVec_e[0] = gammaVec_e[1] = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + + if (pFilt[k] == 1) { + FIXP_DBL tmpRealF = gammaVecReal_m[0], tmpImagF; + gammaVecReal_m[0] = + (fMult(gammaVecReal_m[0], hintReal_F[sourceband % 4][1]) - + fMult(gammaVecImag_m[0], + hintReal_F[(sourceband + 3) % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVecImag_m[0] = + (fMult(tmpRealF, hintReal_F[(sourceband + 3) % 4][1]) + + fMult(gammaVecImag_m[0], hintReal_F[sourceband % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + + tmpRealF = hQmfTransposer + ->qmfInBufReal_F[pSlotStretch[k] + 1][sourceband]; + tmpImagF = hQmfTransposer + ->qmfInBufImag_F[pSlotStretch[k] + 1][sourceband]; + + gammaVecReal_m[0] += + (fMult(tmpRealF, hintReal_F[sourceband % 4][1]) - + fMult(tmpImagF, hintReal_F[(sourceband + 1) % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVecImag_m[0] += + (fMult(tmpRealF, hintReal_F[(sourceband + 1) % 4][1]) + + fMult(tmpImagF, hintReal_F[sourceband % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVec_e[0]++; + + tmpRealF = gammaVecReal_m[1]; + + gammaVecReal_m[1] = + (fMult(gammaVecReal_m[1], hintReal_F[sourceband % 4][2]) - + fMult(gammaVecImag_m[1], + hintReal_F[(sourceband + 3) % 4][2])) >> + 1; + gammaVecImag_m[1] = + (fMult(tmpRealF, hintReal_F[(sourceband + 3) % 4][2]) + + fMult(gammaVecImag_m[1], hintReal_F[sourceband % 4][2])) >> + 1; + + tmpRealF = + hQmfTransposer + ->qmfInBufReal_F[pSlotStretch[k] + 1][sourceband + 1]; + tmpImagF = + hQmfTransposer + ->qmfInBufImag_F[pSlotStretch[k] + 1][sourceband + 1]; + + gammaVecReal_m[1] += + (fMult(tmpRealF, hintReal_F[sourceband % 4][2]) - + fMult(tmpImagF, hintReal_F[(sourceband + 1) % 4][2])) >> + 1; + gammaVecImag_m[1] += + (fMult(tmpRealF, hintReal_F[(sourceband + 1) % 4][2]) + + fMult(tmpImagF, hintReal_F[sourceband % 4][2])) >> + 1; + gammaVec_e[1]++; + } + + addHighBandPart(gammaVecReal_m[1], gammaVecImag_m[1], gammaVec_e[1], + factor, gammaCenterReal_m[0], gammaCenterImag_m[0], + gammaCenter_e[0], stretch, scale_factor_hbe, + &hQmfTransposer->qmfHBEBufReal_F[k][band], + &hQmfTransposer->qmfHBEBufImag_F[k][band]); + + addHighBandPart(gammaVecReal_m[0], gammaVecImag_m[0], gammaVec_e[0], + factor, gammaCenterReal_m[1], gammaCenterImag_m[1], + gammaCenter_e[1], stretch, scale_factor_hbe, + &hQmfTransposer->qmfHBEBufReal_F[k][band], + &hQmfTransposer->qmfHBEBufImag_F[k][band]); + } + } else { + for (k = start; k < stop; k++) { + gammaVecReal_m[0] = + hQmfTransposer->qmfInBufReal_F[pSlotStretch[k]][sourceband]; + gammaVecImag_m[0] = + hQmfTransposer->qmfInBufImag_F[pSlotStretch[k]][sourceband]; + gammaVec_e[0] = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + + if (pFilt[k] == 1) { + FIXP_DBL tmpRealF = gammaVecReal_m[0], tmpImagF; + gammaVecReal_m[0] = + (fMult(gammaVecReal_m[0], hintReal_F[sourceband % 4][1]) - + fMult(gammaVecImag_m[0], + hintReal_F[(sourceband + 3) % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVecImag_m[0] = + (fMult(tmpRealF, hintReal_F[(sourceband + 3) % 4][1]) + + fMult(gammaVecImag_m[0], hintReal_F[sourceband % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + + tmpRealF = hQmfTransposer + ->qmfInBufReal_F[pSlotStretch[k] + 1][sourceband]; + tmpImagF = hQmfTransposer + ->qmfInBufImag_F[pSlotStretch[k] + 1][sourceband]; + + gammaVecReal_m[0] += + (fMult(tmpRealF, hintReal_F[sourceband % 4][1]) - + fMult(tmpImagF, hintReal_F[(sourceband + 1) % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVecImag_m[0] += + (fMult(tmpRealF, hintReal_F[(sourceband + 1) % 4][1]) + + fMult(tmpImagF, hintReal_F[sourceband % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVec_e[0]++; + } + + addHighBandPart(gammaVecReal_m[0], gammaVecImag_m[0], gammaVec_e[0], + factor, gammaCenterReal_m[0], gammaCenterImag_m[0], + gammaCenter_e[0], stretch, scale_factor_hbe, + &hQmfTransposer->qmfHBEBufReal_F[k][band], + &hQmfTransposer->qmfHBEBufImag_F[k][band]); + } + } + + /* pitchInBins is given with the resolution of a 768 bins FFT and we + * need 64 QMF units so factor 768/64 = 12 */ + if (pitchInBins >= pmin * (1 + bSbr41)) { + int tr, ti1, ti2, mTr = 0, ts1 = 0, ts2 = 0, mVal_e = 0, temp_e = 0; + int sqmag0_e = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + + FIXP_DBL mVal_F = FL2FXCONST_DBL(0.f), sqmag0_F, sqmag1_F, sqmag2_F, + temp_F, f1_F; /* all equal exponent */ + sign = -1; + + sourceband = 2 * band / stretch - qmfOffset; /* consistent with the + already computed for + stretch = 3,4. */ + FDK_ASSERT(sourceband >= 0); + + FIXP_DBL sqmag0R_F = + hQmfTransposer->qmfInBufReal_F[slotOffset][sourceband]; + FIXP_DBL sqmag0I_F = + hQmfTransposer->qmfInBufImag_F[slotOffset][sourceband]; + scaleUp(&sqmag0R_F, &sqmag0I_F, &sqmag0_e); + + sqmag0_F = fPow2Div2(sqmag0R_F); + sqmag0_F += fPow2Div2(sqmag0I_F); + sqmag0_e = 2 * sqmag0_e + 1; + + for (tr = 1; tr < stretch; tr++) { + int sqmag1_e = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + int sqmag2_e = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + + FIXP_DBL tmp_band = band_F[band]; + FIXP_DBL tr_p = + fMult(p_F[pitchInBins] >> bSbr41, tr_str[tr - 1]); /* scale 7 */ + f1_F = + fMult(tmp_band - tr_p, stretchfac[stretch - 2]); /* scale 7 */ + ti1 = (INT)(f1_F >> (DFRACT_BITS - 1 - 7)) - qmfOffset; + ti2 = (INT)(((f1_F) + ((p_F[pitchInBins] >> bSbr41) >> 2)) >> + (DFRACT_BITS - 1 - 7)) - + qmfOffset; + + if (ti1 >= 0 && ti2 < 2 * hQmfTransposer->synthSize) { + FIXP_DBL sqmag1R_F = + hQmfTransposer->qmfInBufReal_F[slotOffset][ti1]; + FIXP_DBL sqmag1I_F = + hQmfTransposer->qmfInBufImag_F[slotOffset][ti1]; + scaleUp(&sqmag1R_F, &sqmag1I_F, &sqmag1_e); + sqmag1_F = fPow2Div2(sqmag1R_F); + sqmag1_F += fPow2Div2(sqmag1I_F); + sqmag1_e = 2 * sqmag1_e + 1; + + FIXP_DBL sqmag2R_F = + hQmfTransposer->qmfInBufReal_F[slotOffset][ti2]; + FIXP_DBL sqmag2I_F = + hQmfTransposer->qmfInBufImag_F[slotOffset][ti2]; + scaleUp(&sqmag2R_F, &sqmag2I_F, &sqmag2_e); + sqmag2_F = fPow2Div2(sqmag2R_F); + sqmag2_F += fPow2Div2(sqmag2I_F); + sqmag2_e = 2 * sqmag2_e + 1; + + int shift1 = fMin(fMax(sqmag1_e, sqmag2_e) - sqmag1_e, 31); + int shift2 = fMin(fMax(sqmag1_e, sqmag2_e) - sqmag2_e, 31); + + temp_F = fMin((sqmag1_F >> shift1), (sqmag2_F >> shift2)); + temp_e = fMax(sqmag1_e, sqmag2_e); + + int shift3 = fMin(fMax(temp_e, mVal_e) - temp_e, 31); + int shift4 = fMin(fMax(temp_e, mVal_e) - mVal_e, 31); + + if ((temp_F >> shift3) > (mVal_F >> shift4)) { + mVal_F = temp_F; + mVal_e = temp_e; /* equals sqmag2_e + shift2 */ + mTr = tr; + ts1 = ti1; + ts2 = ti2; + } + } + } + + int shift1 = fMin(fMax(sqmag0_e, mVal_e) - sqmag0_e, 31); + int shift2 = fMin(fMax(sqmag0_e, mVal_e) - mVal_e, 31); + + if ((mVal_F >> shift2) > (sqmag0_F >> shift1) && ts1 >= 0 && + ts2 < 2 * hQmfTransposer->synthSize) { + INT gammaOut_e[2]; + FIXP_DBL gammaOutReal_m[2], gammaOutImag_m[2]; + FIXP_DBL tmpReal_m = (FIXP_DBL)0, tmpImag_m = (FIXP_DBL)0; + + int Tcenter, Tvec; + + Tcenter = stretch - mTr; /* default phase power parameters */ + Tvec = mTr; + switch (stretch) /* 2 tap block creation design depends on stretch + order */ + { + case 2: + wingain = + FL2FXCONST_DBL(5.f / 12.f); /* sum of taps divided by two */ + + if (hQmfTransposer->bXProducts[0]) { + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts1]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts1]; + + for (k = 0; k < 2; k++) { + gammaVecReal_m[k] = + hQmfTransposer->qmfInBufReal_F[slotOffset - 1 + k][ts2]; + gammaVecImag_m[k] = + hQmfTransposer->qmfInBufImag_F[slotOffset - 1 + k][ts2]; + } + + gammaCenter_e[0] = SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + gammaVec_e[0] = gammaVec_e[1] = SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + } + break; + + case 4: + wingain = + FL2FXCONST_DBL(6.f / 12.f); /* sum of taps divided by two */ + if (hQmfTransposer->bXProducts[2]) { + if (mTr == 1) { + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts1]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts1]; + + for (k = 0; k < 2; k++) { + gammaVecReal_m[k] = + hQmfTransposer + ->qmfInBufReal_F[slotOffset + 2 * (k - 1)][ts2]; + gammaVecImag_m[k] = + hQmfTransposer + ->qmfInBufImag_F[slotOffset + 2 * (k - 1)][ts2]; + } + } else if (mTr == 2) { + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts1]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts1]; + + for (k = 0; k < 2; k++) { + gammaVecReal_m[k] = + hQmfTransposer + ->qmfInBufReal_F[slotOffset + (k - 1)][ts2]; + gammaVecImag_m[k] = + hQmfTransposer + ->qmfInBufImag_F[slotOffset + (k - 1)][ts2]; + } + } else /* (mTr == 3) */ + { + sign = 1; + Tcenter = mTr; /* opposite phase power parameters as ts2 is + center */ + Tvec = stretch - mTr; + + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts2]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts2]; + + for (k = 0; k < 2; k++) { + gammaVecReal_m[k] = + hQmfTransposer + ->qmfInBufReal_F[slotOffset + 2 * (k - 1)][ts1]; + gammaVecImag_m[k] = + hQmfTransposer + ->qmfInBufImag_F[slotOffset + 2 * (k - 1)][ts1]; + } + } + + gammaCenter_e[0] = SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + gammaVec_e[0] = gammaVec_e[1] = SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + } + break; + + case 3: + wingain = FL2FXCONST_DBL(5.6568f / + 12.f); /* sum of taps divided by two */ + + if (hQmfTransposer->bXProducts[1]) { + FIXP_DBL tmpReal_F, tmpImag_F; + if (mTr == 1) { + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts1]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts1]; + gammaVecReal_m[1] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts2]; + gammaVecImag_m[1] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts2]; + + addrshift = -2; + tmpReal_F = + hQmfTransposer + ->qmfInBufReal_F[addrshift + slotOffset][ts2]; + tmpImag_F = + hQmfTransposer + ->qmfInBufImag_F[addrshift + slotOffset][ts2]; + + gammaVecReal_m[0] = + (fMult(factors[ts2 % 4], tmpReal_F) - + fMult(factors[(ts2 + 3) % 4], tmpImag_F)) >> + 1; + gammaVecImag_m[0] = + (fMult(factors[(ts2 + 3) % 4], tmpReal_F) + + fMult(factors[ts2 % 4], tmpImag_F)) >> + 1; + + tmpReal_F = + hQmfTransposer + ->qmfInBufReal_F[addrshift + 1 + slotOffset][ts2]; + tmpImag_F = + hQmfTransposer + ->qmfInBufImag_F[addrshift + 1 + slotOffset][ts2]; + + gammaVecReal_m[0] += + (fMult(factors[ts2 % 4], tmpReal_F) - + fMult(factors[(ts2 + 1) % 4], tmpImag_F)) >> + 1; + gammaVecImag_m[0] += + (fMult(factors[(ts2 + 1) % 4], tmpReal_F) + + fMult(factors[ts2 % 4], tmpImag_F)) >> + 1; + + } else /* (mTr == 2) */ + { + sign = 1; + Tcenter = mTr; /* opposite phase power parameters as ts2 is + center */ + Tvec = stretch - mTr; + + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts2]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts2]; + gammaVecReal_m[1] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts1]; + gammaVecImag_m[1] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts1]; + + addrshift = -2; + tmpReal_F = + hQmfTransposer + ->qmfInBufReal_F[addrshift + slotOffset][ts1]; + tmpImag_F = + hQmfTransposer + ->qmfInBufImag_F[addrshift + slotOffset][ts1]; + + gammaVecReal_m[0] = + (fMult(factors[ts1 % 4], tmpReal_F) - + fMult(factors[(ts1 + 3) % 4], tmpImag_F)) >> + 1; + gammaVecImag_m[0] = + (fMult(factors[(ts1 + 3) % 4], tmpReal_F) + + fMult(factors[ts1 % 4], tmpImag_F)) >> + 1; + + tmpReal_F = + hQmfTransposer + ->qmfInBufReal_F[addrshift + 1 + slotOffset][ts1]; + tmpImag_F = + hQmfTransposer + ->qmfInBufImag_F[addrshift + 1 + slotOffset][ts1]; + + gammaVecReal_m[0] += + (fMult(factors[ts1 % 4], tmpReal_F) - + fMult(factors[(ts1 + 1) % 4], tmpImag_F)) >> + 1; + gammaVecImag_m[0] += + (fMult(factors[(ts1 + 1) % 4], tmpReal_F) + + fMult(factors[ts1 % 4], tmpImag_F)) >> + 1; + } + + gammaCenter_e[0] = gammaVec_e[1] = SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + gammaVec_e[0] = + SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor) + + 1; + } + break; + default: + FDK_ASSERT(0); + break; + } /* stretch cases */ + + /* parameter controlled phase modification parts */ + /* maximum *_e == 20 */ + calculateCenterFIXP(gammaCenterReal_m[0], gammaCenterImag_m[0], + &gammaCenterReal_m[0], &gammaCenterImag_m[0], + &gammaCenter_e[0], stretch, Tcenter - 1); + calculateCenterFIXP(gammaVecReal_m[0], gammaVecImag_m[0], + &gammaVecReal_m[0], &gammaVecImag_m[0], + &gammaVec_e[0], stretch, Tvec - 1); + calculateCenterFIXP(gammaVecReal_m[1], gammaVecImag_m[1], + &gammaVecReal_m[1], &gammaVecImag_m[1], + &gammaVec_e[1], stretch, Tvec - 1); + + /* Final multiplication of prepared parts */ + for (k = 0; k < 2; k++) { + gammaOutReal_m[k] = + fMultDiv2(gammaVecReal_m[k], gammaCenterReal_m[0]) - + fMultDiv2(gammaVecImag_m[k], gammaCenterImag_m[0]); + gammaOutImag_m[k] = + fMultDiv2(gammaVecReal_m[k], gammaCenterImag_m[0]) + + fMultDiv2(gammaVecImag_m[k], gammaCenterReal_m[0]); + gammaOut_e[k] = gammaCenter_e[0] + gammaVec_e[k] + 1; + } + + scaleUp(&gammaOutReal_m[0], &gammaOutImag_m[0], &gammaOut_e[0]); + scaleUp(&gammaOutReal_m[1], &gammaOutImag_m[1], &gammaOut_e[1]); + FDK_ASSERT(gammaOut_e[0] >= 0); + FDK_ASSERT(gammaOut_e[0] < 32); + + tmpReal_m = gammaOutReal_m[0]; + tmpImag_m = gammaOutImag_m[0]; + + INT modstretch4 = ((stretch == 4) && (mTr == 2)); + + FIXP_DBL cos_twid = twid_m_new[stretch - 2 - modstretch4][0]; + FIXP_DBL sin_twid = sign * twid_m_new[stretch - 2 - modstretch4][1]; + + gammaOutReal_m[0] = + fMult(tmpReal_m, cos_twid) - + fMult(tmpImag_m, sin_twid); /* sum should be <= 1 because of + sin/cos multiplication */ + gammaOutImag_m[0] = + fMult(tmpImag_m, cos_twid) + + fMult(tmpReal_m, sin_twid); /* sum should be <= 1 because of + sin/cos multiplication */ + + /* wingain */ + for (k = 0; k < 2; k++) { + gammaOutReal_m[k] = (fMult(gammaOutReal_m[k], wingain) << 1); + gammaOutImag_m[k] = (fMult(gammaOutImag_m[k], wingain) << 1); + } + + gammaOutReal_m[1] >>= 1; + gammaOutImag_m[1] >>= 1; + gammaOut_e[0] += 2; + gammaOut_e[1] += 2; + + /* OLA including window scaling by wingain/3 */ + for (k = 0; k < 2; k++) /* need k=1 to correspond to + grainModImag[slotOffset] -> out to + j*2+(slotOffset-offset) */ + { + hQmfTransposer->qmfHBEBufReal_F[(k + slotOffset - 1)][band] += + gammaOutReal_m[k] >> (scale_factor_hbe - gammaOut_e[k]); + hQmfTransposer->qmfHBEBufImag_F[(k + slotOffset - 1)][band] += + gammaOutImag_m[k] >> (scale_factor_hbe - gammaOut_e[k]); + } + } /* mVal > qThrQMF * qThrQMF * sqmag0 && ts1 > 0 && ts2 < 64 */ + } /* p >= pmin */ + } /* for band */ + } /* for stretch */ + + for (i = 0; i < QMF_WIN_LEN - 1; i++) { + FDKmemcpy(hQmfTransposer->qmfInBufReal_F[i], + hQmfTransposer->qmfInBufReal_F[i + 1], + sizeof(FIXP_DBL) * hQmfTransposer->HBEAnalysiscQMF.no_channels); + FDKmemcpy(hQmfTransposer->qmfInBufImag_F[i], + hQmfTransposer->qmfInBufImag_F[i + 1], + sizeof(FIXP_DBL) * hQmfTransposer->HBEAnalysiscQMF.no_channels); + } + + if (keepStatesSyncedMode != KEEP_STATES_SYNCED_NOOUT) { + if (2 * j >= offset) { + /* copy first two slots of internal buffer to output */ + if (keepStatesSyncedMode == KEEP_STATES_SYNCED_OUTDIFF) { + for (i = 0; i < 2; i++) { + FDKmemcpy(&ppQmfBufferOutReal_F[2 * j - offset + i] + [hQmfTransposer->xOverQmf[0]], + &hQmfTransposer + ->qmfHBEBufReal_F[i][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + FDKmemcpy(&ppQmfBufferOutImag_F[2 * j - offset + i] + [hQmfTransposer->xOverQmf[0]], + &hQmfTransposer + ->qmfHBEBufImag_F[i][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + } + } else { + for (i = 0; i < 2; i++) { + FDKmemcpy(&ppQmfBufferOutReal_F[2 * j + i + ov_len] + [hQmfTransposer->xOverQmf[0]], + &hQmfTransposer + ->qmfHBEBufReal_F[i][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + FDKmemcpy(&ppQmfBufferOutImag_F[2 * j + i + ov_len] + [hQmfTransposer->xOverQmf[0]], + &hQmfTransposer + ->qmfHBEBufImag_F[i][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + } + } + } + } + + /* move slots up */ + for (i = 0; i < HBE_MAX_OUT_SLOTS - 2; i++) { + FDKmemcpy( + &hQmfTransposer->qmfHBEBufReal_F[i][hQmfTransposer->xOverQmf[0]], + &hQmfTransposer->qmfHBEBufReal_F[i + 2][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + FDKmemcpy( + &hQmfTransposer->qmfHBEBufImag_F[i][hQmfTransposer->xOverQmf[0]], + &hQmfTransposer->qmfHBEBufImag_F[i + 2][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + } + + /* finally set last two slot to zero */ + for (i = 0; i < 2; i++) { + FDKmemset(&hQmfTransposer->qmfHBEBufReal_F[HBE_MAX_OUT_SLOTS - 1 - i] + [hQmfTransposer->xOverQmf[0]], + 0, + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + FDKmemset(&hQmfTransposer->qmfHBEBufImag_F[HBE_MAX_OUT_SLOTS - 1 - i] + [hQmfTransposer->xOverQmf[0]], + 0, + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + } + } /* qmfVocoderColsIn */ + + if (keepStatesSyncedMode != KEEP_STATES_SYNCED_NOOUT) { + if (keepStatesSyncedMode == KEEP_STATES_SYNCED_OUTDIFF) { + for (i = 0; i < ov_len + LPC_ORDER; i++) { + for (band = hQmfTransposer->startBand; band < hQmfTransposer->stopBand; + band++) { + FIXP_DBL tmpR = ppQmfBufferOutReal_F[i][band]; + FIXP_DBL tmpI = ppQmfBufferOutImag_F[i][band]; + + ppQmfBufferOutReal_F[i][band] = + fMult(tmpR, cos_F[band]) - + fMult(tmpI, (-cos_F[64 - band - 1])); /* sum should be <= 1 + because of sin/cos + multiplication */ + ppQmfBufferOutImag_F[i][band] = + fMult(tmpR, (-cos_F[64 - band - 1])) + + fMult(tmpI, cos_F[band]); /* sum should by <= 1 because of sin/cos + multiplication */ + } + } + } else { + for (i = offset; i < hQmfTransposer->noCols; i++) { + for (band = hQmfTransposer->startBand; band < hQmfTransposer->stopBand; + band++) { + FIXP_DBL tmpR = ppQmfBufferOutReal_F[i + ov_len][band]; + FIXP_DBL tmpI = ppQmfBufferOutImag_F[i + ov_len][band]; + + ppQmfBufferOutReal_F[i + ov_len][band] = + fMult(tmpR, cos_F[band]) - + fMult(tmpI, (-cos_F[64 - band - 1])); /* sum should be <= 1 + because of sin/cos + multiplication */ + ppQmfBufferOutImag_F[i + ov_len][band] = + fMult(tmpR, (-cos_F[64 - band - 1])) + + fMult(tmpI, cos_F[band]); /* sum should by <= 1 because of sin/cos + multiplication */ + } + } + } + } + + *scale_hb = EXP2SCALE(scale_factor_hbe); +} + +int* GetxOverBandQmfTransposer(HANDLE_HBE_TRANSPOSER hQmfTransposer) { + if (hQmfTransposer) + return hQmfTransposer->xOverQmf; + else + return NULL; +} + +int Get41SbrQmfTransposer(HANDLE_HBE_TRANSPOSER hQmfTransposer) { + if (hQmfTransposer != NULL) + return hQmfTransposer->bSbr41; + else + return 0; +} |