/* -----------------------------------------------------------------------------
|
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];
|
FDK_ASSERT((!hQmfTransposer->bSbr41 && hQmfTransposer->startBand <= 32) ||
|
(hQmfTransposer->bSbr41 &&
|
hQmfTransposer->startBand <=
|
16)); /* is checked by resetFreqBandTables() */
|
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;
|
}
|