1*e5436536SAndroid Build Coastguard Worker /* -----------------------------------------------------------------------------
2*e5436536SAndroid Build Coastguard Worker Software License for The Fraunhofer FDK AAC Codec Library for Android
3*e5436536SAndroid Build Coastguard Worker
4*e5436536SAndroid Build Coastguard Worker © Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
5*e5436536SAndroid Build Coastguard Worker Forschung e.V. All rights reserved.
6*e5436536SAndroid Build Coastguard Worker
7*e5436536SAndroid Build Coastguard Worker 1. INTRODUCTION
8*e5436536SAndroid Build Coastguard Worker The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9*e5436536SAndroid Build Coastguard Worker that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10*e5436536SAndroid Build Coastguard Worker scheme for digital audio. This FDK AAC Codec software is intended to be used on
11*e5436536SAndroid Build Coastguard Worker a wide variety of Android devices.
12*e5436536SAndroid Build Coastguard Worker
13*e5436536SAndroid Build Coastguard Worker AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14*e5436536SAndroid Build Coastguard Worker general perceptual audio codecs. AAC-ELD is considered the best-performing
15*e5436536SAndroid Build Coastguard Worker full-bandwidth communications codec by independent studies and is widely
16*e5436536SAndroid Build Coastguard Worker deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17*e5436536SAndroid Build Coastguard Worker specifications.
18*e5436536SAndroid Build Coastguard Worker
19*e5436536SAndroid Build Coastguard Worker Patent licenses for necessary patent claims for the FDK AAC Codec (including
20*e5436536SAndroid Build Coastguard Worker those of Fraunhofer) may be obtained through Via Licensing
21*e5436536SAndroid Build Coastguard Worker (www.vialicensing.com) or through the respective patent owners individually for
22*e5436536SAndroid Build Coastguard Worker the purpose of encoding or decoding bit streams in products that are compliant
23*e5436536SAndroid Build Coastguard Worker with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24*e5436536SAndroid Build Coastguard Worker Android devices already license these patent claims through Via Licensing or
25*e5436536SAndroid Build Coastguard Worker directly from the patent owners, and therefore FDK AAC Codec software may
26*e5436536SAndroid Build Coastguard Worker already be covered under those patent licenses when it is used for those
27*e5436536SAndroid Build Coastguard Worker licensed purposes only.
28*e5436536SAndroid Build Coastguard Worker
29*e5436536SAndroid Build Coastguard Worker Commercially-licensed AAC software libraries, including floating-point versions
30*e5436536SAndroid Build Coastguard Worker with enhanced sound quality, are also available from Fraunhofer. Users are
31*e5436536SAndroid Build Coastguard Worker encouraged to check the Fraunhofer website for additional applications
32*e5436536SAndroid Build Coastguard Worker information and documentation.
33*e5436536SAndroid Build Coastguard Worker
34*e5436536SAndroid Build Coastguard Worker 2. COPYRIGHT LICENSE
35*e5436536SAndroid Build Coastguard Worker
36*e5436536SAndroid Build Coastguard Worker Redistribution and use in source and binary forms, with or without modification,
37*e5436536SAndroid Build Coastguard Worker are permitted without payment of copyright license fees provided that you
38*e5436536SAndroid Build Coastguard Worker satisfy the following conditions:
39*e5436536SAndroid Build Coastguard Worker
40*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in redistributions of
41*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec or your modifications thereto in source code form.
42*e5436536SAndroid Build Coastguard Worker
43*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in the documentation
44*e5436536SAndroid Build Coastguard Worker and/or other materials provided with redistributions of the FDK AAC Codec or
45*e5436536SAndroid Build Coastguard Worker your modifications thereto in binary form. You must make available free of
46*e5436536SAndroid Build Coastguard Worker charge copies of the complete source code of the FDK AAC Codec and your
47*e5436536SAndroid Build Coastguard Worker modifications thereto to recipients of copies in binary form.
48*e5436536SAndroid Build Coastguard Worker
49*e5436536SAndroid Build Coastguard Worker The name of Fraunhofer may not be used to endorse or promote products derived
50*e5436536SAndroid Build Coastguard Worker from this library without prior written permission.
51*e5436536SAndroid Build Coastguard Worker
52*e5436536SAndroid Build Coastguard Worker You may not charge copyright license fees for anyone to use, copy or distribute
53*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec software or your modifications thereto.
54*e5436536SAndroid Build Coastguard Worker
55*e5436536SAndroid Build Coastguard Worker Your modified versions of the FDK AAC Codec must carry prominent notices stating
56*e5436536SAndroid Build Coastguard Worker that you changed the software and the date of any change. For modified versions
57*e5436536SAndroid Build Coastguard Worker of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58*e5436536SAndroid Build Coastguard Worker must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59*e5436536SAndroid Build Coastguard Worker AAC Codec Library for Android."
60*e5436536SAndroid Build Coastguard Worker
61*e5436536SAndroid Build Coastguard Worker 3. NO PATENT LICENSE
62*e5436536SAndroid Build Coastguard Worker
63*e5436536SAndroid Build Coastguard Worker NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64*e5436536SAndroid Build Coastguard Worker limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65*e5436536SAndroid Build Coastguard Worker Fraunhofer provides no warranty of patent non-infringement with respect to this
66*e5436536SAndroid Build Coastguard Worker software.
67*e5436536SAndroid Build Coastguard Worker
68*e5436536SAndroid Build Coastguard Worker You may use this FDK AAC Codec software or modifications thereto only for
69*e5436536SAndroid Build Coastguard Worker purposes that are authorized by appropriate patent licenses.
70*e5436536SAndroid Build Coastguard Worker
71*e5436536SAndroid Build Coastguard Worker 4. DISCLAIMER
72*e5436536SAndroid Build Coastguard Worker
73*e5436536SAndroid Build Coastguard Worker This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74*e5436536SAndroid Build Coastguard Worker holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75*e5436536SAndroid Build Coastguard Worker including but not limited to the implied warranties of merchantability and
76*e5436536SAndroid Build Coastguard Worker fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77*e5436536SAndroid Build Coastguard Worker CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78*e5436536SAndroid Build Coastguard Worker or consequential damages, including but not limited to procurement of substitute
79*e5436536SAndroid Build Coastguard Worker goods or services; loss of use, data, or profits, or business interruption,
80*e5436536SAndroid Build Coastguard Worker however caused and on any theory of liability, whether in contract, strict
81*e5436536SAndroid Build Coastguard Worker liability, or tort (including negligence), arising in any way out of the use of
82*e5436536SAndroid Build Coastguard Worker this software, even if advised of the possibility of such damage.
83*e5436536SAndroid Build Coastguard Worker
84*e5436536SAndroid Build Coastguard Worker 5. CONTACT INFORMATION
85*e5436536SAndroid Build Coastguard Worker
86*e5436536SAndroid Build Coastguard Worker Fraunhofer Institute for Integrated Circuits IIS
87*e5436536SAndroid Build Coastguard Worker Attention: Audio and Multimedia Departments - FDK AAC LL
88*e5436536SAndroid Build Coastguard Worker Am Wolfsmantel 33
89*e5436536SAndroid Build Coastguard Worker 91058 Erlangen, Germany
90*e5436536SAndroid Build Coastguard Worker
91*e5436536SAndroid Build Coastguard Worker www.iis.fraunhofer.de/amm
92*e5436536SAndroid Build Coastguard Worker [email protected]
93*e5436536SAndroid Build Coastguard Worker ----------------------------------------------------------------------------- */
94*e5436536SAndroid Build Coastguard Worker
95*e5436536SAndroid Build Coastguard Worker /**************************** AAC encoder library ******************************
96*e5436536SAndroid Build Coastguard Worker
97*e5436536SAndroid Build Coastguard Worker Author(s): Alex Groeschel, Tobias Chalupka
98*e5436536SAndroid Build Coastguard Worker
99*e5436536SAndroid Build Coastguard Worker Description: Temporal noise shaping
100*e5436536SAndroid Build Coastguard Worker
101*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
102*e5436536SAndroid Build Coastguard Worker
103*e5436536SAndroid Build Coastguard Worker #include "aacenc_tns.h"
104*e5436536SAndroid Build Coastguard Worker #include "psy_const.h"
105*e5436536SAndroid Build Coastguard Worker #include "psy_configuration.h"
106*e5436536SAndroid Build Coastguard Worker #include "tns_func.h"
107*e5436536SAndroid Build Coastguard Worker #include "aacEnc_rom.h"
108*e5436536SAndroid Build Coastguard Worker #include "aacenc_tns.h"
109*e5436536SAndroid Build Coastguard Worker #include "FDK_lpc.h"
110*e5436536SAndroid Build Coastguard Worker
111*e5436536SAndroid Build Coastguard Worker #define FILTER_DIRECTION 0 /* 0 = up, 1 = down */
112*e5436536SAndroid Build Coastguard Worker
113*e5436536SAndroid Build Coastguard Worker static const FIXP_DBL acfWindowLong[12 + 3 + 1] = {
114*e5436536SAndroid Build Coastguard Worker 0x7fffffff, 0x7fb80000, 0x7ee00000, 0x7d780000, 0x7b800000, 0x78f80000,
115*e5436536SAndroid Build Coastguard Worker 0x75e00000, 0x72380000, 0x6e000000, 0x69380000, 0x63e00000, 0x5df80000,
116*e5436536SAndroid Build Coastguard Worker 0x57800000, 0x50780000, 0x48e00000, 0x40b80000};
117*e5436536SAndroid Build Coastguard Worker
118*e5436536SAndroid Build Coastguard Worker static const FIXP_DBL acfWindowShort[4 + 3 + 1] = {
119*e5436536SAndroid Build Coastguard Worker 0x7fffffff, 0x7e000000, 0x78000000, 0x6e000000,
120*e5436536SAndroid Build Coastguard Worker 0x60000000, 0x4e000000, 0x38000000, 0x1e000000};
121*e5436536SAndroid Build Coastguard Worker
122*e5436536SAndroid Build Coastguard Worker typedef struct {
123*e5436536SAndroid Build Coastguard Worker INT bitRateFrom[2]; /* noneSbr=0, useSbr=1 */
124*e5436536SAndroid Build Coastguard Worker INT bitRateTo[2]; /* noneSbr=0, useSbr=1 */
125*e5436536SAndroid Build Coastguard Worker TNS_PARAMETER_TABULATED paramTab[2]; /* mono=0, stereo=1 */
126*e5436536SAndroid Build Coastguard Worker
127*e5436536SAndroid Build Coastguard Worker } TNS_INFO_TAB;
128*e5436536SAndroid Build Coastguard Worker
129*e5436536SAndroid Build Coastguard Worker #define TNS_TIMERES_SCALE (1)
130*e5436536SAndroid Build Coastguard Worker #define FL2_TIMERES_FIX(a) (FL2FXCONST_DBL(a / (float)(1 << TNS_TIMERES_SCALE)))
131*e5436536SAndroid Build Coastguard Worker
132*e5436536SAndroid Build Coastguard Worker static const TNS_INFO_TAB tnsInfoTab[] = {
133*e5436536SAndroid Build Coastguard Worker {{16000, 13500},
134*e5436536SAndroid Build Coastguard Worker {32000, 28000},
135*e5436536SAndroid Build Coastguard Worker {{{1, 1},
136*e5436536SAndroid Build Coastguard Worker {1437, 1500},
137*e5436536SAndroid Build Coastguard Worker {1400, 600},
138*e5436536SAndroid Build Coastguard Worker {12, 12},
139*e5436536SAndroid Build Coastguard Worker {FILTER_DIRECTION, FILTER_DIRECTION},
140*e5436536SAndroid Build Coastguard Worker {3, 1},
141*e5436536SAndroid Build Coastguard Worker {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.2f)},
142*e5436536SAndroid Build Coastguard Worker 1},
143*e5436536SAndroid Build Coastguard Worker {{1, 1},
144*e5436536SAndroid Build Coastguard Worker {1437, 1500},
145*e5436536SAndroid Build Coastguard Worker {1400, 600},
146*e5436536SAndroid Build Coastguard Worker {12, 12},
147*e5436536SAndroid Build Coastguard Worker {FILTER_DIRECTION, FILTER_DIRECTION},
148*e5436536SAndroid Build Coastguard Worker {3, 1},
149*e5436536SAndroid Build Coastguard Worker {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.2f)},
150*e5436536SAndroid Build Coastguard Worker 1}}},
151*e5436536SAndroid Build Coastguard Worker {{32001, 28001},
152*e5436536SAndroid Build Coastguard Worker {60000, 52000},
153*e5436536SAndroid Build Coastguard Worker {{{1, 1},
154*e5436536SAndroid Build Coastguard Worker {1437, 1500},
155*e5436536SAndroid Build Coastguard Worker {1400, 600},
156*e5436536SAndroid Build Coastguard Worker {12, 10},
157*e5436536SAndroid Build Coastguard Worker {FILTER_DIRECTION, FILTER_DIRECTION},
158*e5436536SAndroid Build Coastguard Worker {3, 1},
159*e5436536SAndroid Build Coastguard Worker {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)},
160*e5436536SAndroid Build Coastguard Worker 1},
161*e5436536SAndroid Build Coastguard Worker {{1, 1},
162*e5436536SAndroid Build Coastguard Worker {1437, 1500},
163*e5436536SAndroid Build Coastguard Worker {1400, 600},
164*e5436536SAndroid Build Coastguard Worker {12, 10},
165*e5436536SAndroid Build Coastguard Worker {FILTER_DIRECTION, FILTER_DIRECTION},
166*e5436536SAndroid Build Coastguard Worker {3, 1},
167*e5436536SAndroid Build Coastguard Worker {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)},
168*e5436536SAndroid Build Coastguard Worker 1}}},
169*e5436536SAndroid Build Coastguard Worker {{60001, 52001},
170*e5436536SAndroid Build Coastguard Worker {384000, 384000},
171*e5436536SAndroid Build Coastguard Worker {{{1, 1},
172*e5436536SAndroid Build Coastguard Worker {1437, 1500},
173*e5436536SAndroid Build Coastguard Worker {1400, 600},
174*e5436536SAndroid Build Coastguard Worker {12, 8},
175*e5436536SAndroid Build Coastguard Worker {FILTER_DIRECTION, FILTER_DIRECTION},
176*e5436536SAndroid Build Coastguard Worker {3, 1},
177*e5436536SAndroid Build Coastguard Worker {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)},
178*e5436536SAndroid Build Coastguard Worker 1},
179*e5436536SAndroid Build Coastguard Worker {{1, 1},
180*e5436536SAndroid Build Coastguard Worker {1437, 1500},
181*e5436536SAndroid Build Coastguard Worker {1400, 600},
182*e5436536SAndroid Build Coastguard Worker {12, 8},
183*e5436536SAndroid Build Coastguard Worker {FILTER_DIRECTION, FILTER_DIRECTION},
184*e5436536SAndroid Build Coastguard Worker {3, 1},
185*e5436536SAndroid Build Coastguard Worker {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)},
186*e5436536SAndroid Build Coastguard Worker 1}}}};
187*e5436536SAndroid Build Coastguard Worker
188*e5436536SAndroid Build Coastguard Worker typedef struct {
189*e5436536SAndroid Build Coastguard Worker INT samplingRate;
190*e5436536SAndroid Build Coastguard Worker SCHAR maxBands[2]; /* long=0; short=1 */
191*e5436536SAndroid Build Coastguard Worker
192*e5436536SAndroid Build Coastguard Worker } TNS_MAX_TAB_ENTRY;
193*e5436536SAndroid Build Coastguard Worker
194*e5436536SAndroid Build Coastguard Worker static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab1024[] = {
195*e5436536SAndroid Build Coastguard Worker {96000, {31, 9}}, {88200, {31, 9}}, {64000, {34, 10}}, {48000, {40, 14}},
196*e5436536SAndroid Build Coastguard Worker {44100, {42, 14}}, {32000, {51, 14}}, {24000, {46, 14}}, {22050, {46, 14}},
197*e5436536SAndroid Build Coastguard Worker {16000, {42, 14}}, {12000, {42, 14}}, {11025, {42, 14}}, {8000, {39, 14}}};
198*e5436536SAndroid Build Coastguard Worker
199*e5436536SAndroid Build Coastguard Worker static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab120[] = {
200*e5436536SAndroid Build Coastguard Worker {48000, {12, -1}}, /* 48000 */
201*e5436536SAndroid Build Coastguard Worker {44100, {12, -1}}, /* 44100 */
202*e5436536SAndroid Build Coastguard Worker {32000, {15, -1}}, /* 32000 */
203*e5436536SAndroid Build Coastguard Worker {24000, {15, -1}}, /* 24000 */
204*e5436536SAndroid Build Coastguard Worker {22050, {15, -1}} /* 22050 */
205*e5436536SAndroid Build Coastguard Worker };
206*e5436536SAndroid Build Coastguard Worker
207*e5436536SAndroid Build Coastguard Worker static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab128[] = {
208*e5436536SAndroid Build Coastguard Worker {48000, {12, -1}}, /* 48000 */
209*e5436536SAndroid Build Coastguard Worker {44100, {12, -1}}, /* 44100 */
210*e5436536SAndroid Build Coastguard Worker {32000, {15, -1}}, /* 32000 */
211*e5436536SAndroid Build Coastguard Worker {24000, {15, -1}}, /* 24000 */
212*e5436536SAndroid Build Coastguard Worker {22050, {15, -1}} /* 22050 */
213*e5436536SAndroid Build Coastguard Worker };
214*e5436536SAndroid Build Coastguard Worker
215*e5436536SAndroid Build Coastguard Worker static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab240[] = {
216*e5436536SAndroid Build Coastguard Worker {96000, {22, -1}}, /* 96000 */
217*e5436536SAndroid Build Coastguard Worker {48000, {22, -1}}, /* 48000 */
218*e5436536SAndroid Build Coastguard Worker {44100, {22, -1}}, /* 44100 */
219*e5436536SAndroid Build Coastguard Worker {32000, {21, -1}}, /* 32000 */
220*e5436536SAndroid Build Coastguard Worker {24000, {21, -1}}, /* 24000 */
221*e5436536SAndroid Build Coastguard Worker {22050, {21, -1}} /* 22050 */
222*e5436536SAndroid Build Coastguard Worker };
223*e5436536SAndroid Build Coastguard Worker
224*e5436536SAndroid Build Coastguard Worker static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab256[] = {
225*e5436536SAndroid Build Coastguard Worker {96000, {25, -1}}, /* 96000 */
226*e5436536SAndroid Build Coastguard Worker {48000, {25, -1}}, /* 48000 */
227*e5436536SAndroid Build Coastguard Worker {44100, {25, -1}}, /* 44100 */
228*e5436536SAndroid Build Coastguard Worker {32000, {24, -1}}, /* 32000 */
229*e5436536SAndroid Build Coastguard Worker {24000, {24, -1}}, /* 24000 */
230*e5436536SAndroid Build Coastguard Worker {22050, {24, -1}} /* 22050 */
231*e5436536SAndroid Build Coastguard Worker };
232*e5436536SAndroid Build Coastguard Worker static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab480[] = {{48000, {31, -1}},
233*e5436536SAndroid Build Coastguard Worker {44100, {32, -1}},
234*e5436536SAndroid Build Coastguard Worker {32000, {37, -1}},
235*e5436536SAndroid Build Coastguard Worker {24000, {30, -1}},
236*e5436536SAndroid Build Coastguard Worker {22050, {30, -1}}};
237*e5436536SAndroid Build Coastguard Worker
238*e5436536SAndroid Build Coastguard Worker static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab512[] = {{48000, {31, -1}},
239*e5436536SAndroid Build Coastguard Worker {44100, {32, -1}},
240*e5436536SAndroid Build Coastguard Worker {32000, {37, -1}},
241*e5436536SAndroid Build Coastguard Worker {24000, {31, -1}},
242*e5436536SAndroid Build Coastguard Worker {22050, {31, -1}}};
243*e5436536SAndroid Build Coastguard Worker
244*e5436536SAndroid Build Coastguard Worker static void FDKaacEnc_Parcor2Index(const FIXP_LPC *parcor, INT *RESTRICT index,
245*e5436536SAndroid Build Coastguard Worker const INT order, const INT bitsPerCoeff);
246*e5436536SAndroid Build Coastguard Worker
247*e5436536SAndroid Build Coastguard Worker static void FDKaacEnc_Index2Parcor(const INT *index, FIXP_LPC *RESTRICT parcor,
248*e5436536SAndroid Build Coastguard Worker const INT order, const INT bitsPerCoeff);
249*e5436536SAndroid Build Coastguard Worker
250*e5436536SAndroid Build Coastguard Worker static void FDKaacEnc_CalcGaussWindow(FIXP_DBL *win, const int winSize,
251*e5436536SAndroid Build Coastguard Worker const INT samplingRate,
252*e5436536SAndroid Build Coastguard Worker const INT transformResolution,
253*e5436536SAndroid Build Coastguard Worker const FIXP_DBL timeResolution,
254*e5436536SAndroid Build Coastguard Worker const INT timeResolution_e);
255*e5436536SAndroid Build Coastguard Worker
FDKaacEnc_GetTnsParam(const INT bitRate,const INT channels,const INT sbrLd)256*e5436536SAndroid Build Coastguard Worker static const TNS_PARAMETER_TABULATED *FDKaacEnc_GetTnsParam(const INT bitRate,
257*e5436536SAndroid Build Coastguard Worker const INT channels,
258*e5436536SAndroid Build Coastguard Worker const INT sbrLd) {
259*e5436536SAndroid Build Coastguard Worker int i;
260*e5436536SAndroid Build Coastguard Worker const TNS_PARAMETER_TABULATED *tnsConfigTab = NULL;
261*e5436536SAndroid Build Coastguard Worker
262*e5436536SAndroid Build Coastguard Worker for (i = 0; i < (int)(sizeof(tnsInfoTab) / sizeof(TNS_INFO_TAB)); i++) {
263*e5436536SAndroid Build Coastguard Worker if ((bitRate >= tnsInfoTab[i].bitRateFrom[sbrLd ? 1 : 0]) &&
264*e5436536SAndroid Build Coastguard Worker bitRate <= tnsInfoTab[i].bitRateTo[sbrLd ? 1 : 0]) {
265*e5436536SAndroid Build Coastguard Worker tnsConfigTab = &tnsInfoTab[i].paramTab[(channels == 1) ? 0 : 1];
266*e5436536SAndroid Build Coastguard Worker }
267*e5436536SAndroid Build Coastguard Worker }
268*e5436536SAndroid Build Coastguard Worker
269*e5436536SAndroid Build Coastguard Worker return tnsConfigTab;
270*e5436536SAndroid Build Coastguard Worker }
271*e5436536SAndroid Build Coastguard Worker
getTnsMaxBands(const INT sampleRate,const INT granuleLength,const INT isShortBlock)272*e5436536SAndroid Build Coastguard Worker static INT getTnsMaxBands(const INT sampleRate, const INT granuleLength,
273*e5436536SAndroid Build Coastguard Worker const INT isShortBlock) {
274*e5436536SAndroid Build Coastguard Worker int i;
275*e5436536SAndroid Build Coastguard Worker INT numBands = -1;
276*e5436536SAndroid Build Coastguard Worker const TNS_MAX_TAB_ENTRY *pMaxBandsTab = NULL;
277*e5436536SAndroid Build Coastguard Worker int maxBandsTabSize = 0;
278*e5436536SAndroid Build Coastguard Worker
279*e5436536SAndroid Build Coastguard Worker switch (granuleLength) {
280*e5436536SAndroid Build Coastguard Worker case 960:
281*e5436536SAndroid Build Coastguard Worker case 1024:
282*e5436536SAndroid Build Coastguard Worker pMaxBandsTab = tnsMaxBandsTab1024;
283*e5436536SAndroid Build Coastguard Worker maxBandsTabSize = sizeof(tnsMaxBandsTab1024) / sizeof(TNS_MAX_TAB_ENTRY);
284*e5436536SAndroid Build Coastguard Worker break;
285*e5436536SAndroid Build Coastguard Worker case 120:
286*e5436536SAndroid Build Coastguard Worker pMaxBandsTab = tnsMaxBandsTab120;
287*e5436536SAndroid Build Coastguard Worker maxBandsTabSize = sizeof(tnsMaxBandsTab120) / sizeof(TNS_MAX_TAB_ENTRY);
288*e5436536SAndroid Build Coastguard Worker break;
289*e5436536SAndroid Build Coastguard Worker case 128:
290*e5436536SAndroid Build Coastguard Worker pMaxBandsTab = tnsMaxBandsTab128;
291*e5436536SAndroid Build Coastguard Worker maxBandsTabSize = sizeof(tnsMaxBandsTab128) / sizeof(TNS_MAX_TAB_ENTRY);
292*e5436536SAndroid Build Coastguard Worker break;
293*e5436536SAndroid Build Coastguard Worker case 240:
294*e5436536SAndroid Build Coastguard Worker pMaxBandsTab = tnsMaxBandsTab240;
295*e5436536SAndroid Build Coastguard Worker maxBandsTabSize = sizeof(tnsMaxBandsTab240) / sizeof(TNS_MAX_TAB_ENTRY);
296*e5436536SAndroid Build Coastguard Worker break;
297*e5436536SAndroid Build Coastguard Worker case 256:
298*e5436536SAndroid Build Coastguard Worker pMaxBandsTab = tnsMaxBandsTab256;
299*e5436536SAndroid Build Coastguard Worker maxBandsTabSize = sizeof(tnsMaxBandsTab256) / sizeof(TNS_MAX_TAB_ENTRY);
300*e5436536SAndroid Build Coastguard Worker break;
301*e5436536SAndroid Build Coastguard Worker case 480:
302*e5436536SAndroid Build Coastguard Worker pMaxBandsTab = tnsMaxBandsTab480;
303*e5436536SAndroid Build Coastguard Worker maxBandsTabSize = sizeof(tnsMaxBandsTab480) / sizeof(TNS_MAX_TAB_ENTRY);
304*e5436536SAndroid Build Coastguard Worker break;
305*e5436536SAndroid Build Coastguard Worker case 512:
306*e5436536SAndroid Build Coastguard Worker pMaxBandsTab = tnsMaxBandsTab512;
307*e5436536SAndroid Build Coastguard Worker maxBandsTabSize = sizeof(tnsMaxBandsTab512) / sizeof(TNS_MAX_TAB_ENTRY);
308*e5436536SAndroid Build Coastguard Worker break;
309*e5436536SAndroid Build Coastguard Worker default:
310*e5436536SAndroid Build Coastguard Worker numBands = -1;
311*e5436536SAndroid Build Coastguard Worker }
312*e5436536SAndroid Build Coastguard Worker
313*e5436536SAndroid Build Coastguard Worker if (pMaxBandsTab != NULL) {
314*e5436536SAndroid Build Coastguard Worker for (i = 0; i < maxBandsTabSize; i++) {
315*e5436536SAndroid Build Coastguard Worker numBands = pMaxBandsTab[i].maxBands[(!isShortBlock) ? 0 : 1];
316*e5436536SAndroid Build Coastguard Worker if (sampleRate >= pMaxBandsTab[i].samplingRate) {
317*e5436536SAndroid Build Coastguard Worker break;
318*e5436536SAndroid Build Coastguard Worker }
319*e5436536SAndroid Build Coastguard Worker }
320*e5436536SAndroid Build Coastguard Worker }
321*e5436536SAndroid Build Coastguard Worker
322*e5436536SAndroid Build Coastguard Worker return numBands;
323*e5436536SAndroid Build Coastguard Worker }
324*e5436536SAndroid Build Coastguard Worker
325*e5436536SAndroid Build Coastguard Worker /***************************************************************************/
326*e5436536SAndroid Build Coastguard Worker /*!
327*e5436536SAndroid Build Coastguard Worker \brief FDKaacEnc_FreqToBandWidthRounding
328*e5436536SAndroid Build Coastguard Worker
329*e5436536SAndroid Build Coastguard Worker Returns index of nearest band border
330*e5436536SAndroid Build Coastguard Worker
331*e5436536SAndroid Build Coastguard Worker \param frequency
332*e5436536SAndroid Build Coastguard Worker \param sampling frequency
333*e5436536SAndroid Build Coastguard Worker \param total number of bands
334*e5436536SAndroid Build Coastguard Worker \param pointer to table of band borders
335*e5436536SAndroid Build Coastguard Worker
336*e5436536SAndroid Build Coastguard Worker \return band border
337*e5436536SAndroid Build Coastguard Worker ****************************************************************************/
338*e5436536SAndroid Build Coastguard Worker
FDKaacEnc_FreqToBandWidthRounding(const INT freq,const INT fs,const INT numOfBands,const INT * bandStartOffset)339*e5436536SAndroid Build Coastguard Worker INT FDKaacEnc_FreqToBandWidthRounding(const INT freq, const INT fs,
340*e5436536SAndroid Build Coastguard Worker const INT numOfBands,
341*e5436536SAndroid Build Coastguard Worker const INT *bandStartOffset) {
342*e5436536SAndroid Build Coastguard Worker INT lineNumber, band;
343*e5436536SAndroid Build Coastguard Worker
344*e5436536SAndroid Build Coastguard Worker /* assert(freq >= 0); */
345*e5436536SAndroid Build Coastguard Worker lineNumber = (freq * bandStartOffset[numOfBands] * 4 / fs + 1) / 2;
346*e5436536SAndroid Build Coastguard Worker
347*e5436536SAndroid Build Coastguard Worker /* freq > fs/2 */
348*e5436536SAndroid Build Coastguard Worker if (lineNumber >= bandStartOffset[numOfBands]) return numOfBands;
349*e5436536SAndroid Build Coastguard Worker
350*e5436536SAndroid Build Coastguard Worker /* find band the line number lies in */
351*e5436536SAndroid Build Coastguard Worker for (band = 0; band < numOfBands; band++) {
352*e5436536SAndroid Build Coastguard Worker if (bandStartOffset[band + 1] > lineNumber) break;
353*e5436536SAndroid Build Coastguard Worker }
354*e5436536SAndroid Build Coastguard Worker
355*e5436536SAndroid Build Coastguard Worker /* round to nearest band border */
356*e5436536SAndroid Build Coastguard Worker if (lineNumber - bandStartOffset[band] >
357*e5436536SAndroid Build Coastguard Worker bandStartOffset[band + 1] - lineNumber) {
358*e5436536SAndroid Build Coastguard Worker band++;
359*e5436536SAndroid Build Coastguard Worker }
360*e5436536SAndroid Build Coastguard Worker
361*e5436536SAndroid Build Coastguard Worker return (band);
362*e5436536SAndroid Build Coastguard Worker }
363*e5436536SAndroid Build Coastguard Worker
364*e5436536SAndroid Build Coastguard Worker /*****************************************************************************
365*e5436536SAndroid Build Coastguard Worker
366*e5436536SAndroid Build Coastguard Worker functionname: FDKaacEnc_InitTnsConfiguration
367*e5436536SAndroid Build Coastguard Worker description: fill TNS_CONFIG structure with sensible content
368*e5436536SAndroid Build Coastguard Worker returns:
369*e5436536SAndroid Build Coastguard Worker input: bitrate, samplerate, number of channels,
370*e5436536SAndroid Build Coastguard Worker blocktype (long or short),
371*e5436536SAndroid Build Coastguard Worker TNS Config struct (modified),
372*e5436536SAndroid Build Coastguard Worker psy config struct,
373*e5436536SAndroid Build Coastguard Worker tns active flag
374*e5436536SAndroid Build Coastguard Worker output:
375*e5436536SAndroid Build Coastguard Worker
376*e5436536SAndroid Build Coastguard Worker *****************************************************************************/
FDKaacEnc_InitTnsConfiguration(INT bitRate,INT sampleRate,INT channels,INT blockType,INT granuleLength,INT isLowDelay,INT ldSbrPresent,TNS_CONFIG * tC,PSY_CONFIGURATION * pC,INT active,INT useTnsPeak)377*e5436536SAndroid Build Coastguard Worker AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration(
378*e5436536SAndroid Build Coastguard Worker INT bitRate, INT sampleRate, INT channels, INT blockType, INT granuleLength,
379*e5436536SAndroid Build Coastguard Worker INT isLowDelay, INT ldSbrPresent, TNS_CONFIG *tC, PSY_CONFIGURATION *pC,
380*e5436536SAndroid Build Coastguard Worker INT active, INT useTnsPeak) {
381*e5436536SAndroid Build Coastguard Worker int i;
382*e5436536SAndroid Build Coastguard Worker // float acfTimeRes = (blockType == SHORT_WINDOW) ? 0.125f : 0.046875f;
383*e5436536SAndroid Build Coastguard Worker
384*e5436536SAndroid Build Coastguard Worker if (channels <= 0) return (AAC_ENCODER_ERROR)1;
385*e5436536SAndroid Build Coastguard Worker
386*e5436536SAndroid Build Coastguard Worker tC->isLowDelay = isLowDelay;
387*e5436536SAndroid Build Coastguard Worker
388*e5436536SAndroid Build Coastguard Worker /* initialize TNS filter flag, order, and coefficient resolution (in bits per
389*e5436536SAndroid Build Coastguard Worker * coeff) */
390*e5436536SAndroid Build Coastguard Worker tC->tnsActive = (active) ? TRUE : FALSE;
391*e5436536SAndroid Build Coastguard Worker tC->maxOrder = (blockType == SHORT_WINDOW) ? 5 : 12; /* maximum: 7, 20 */
392*e5436536SAndroid Build Coastguard Worker if (bitRate < 16000) tC->maxOrder -= 2;
393*e5436536SAndroid Build Coastguard Worker tC->coefRes = (blockType == SHORT_WINDOW) ? 3 : 4;
394*e5436536SAndroid Build Coastguard Worker
395*e5436536SAndroid Build Coastguard Worker /* LPC stop line: highest MDCT line to be coded, but do not go beyond
396*e5436536SAndroid Build Coastguard Worker * TNS_MAX_BANDS! */
397*e5436536SAndroid Build Coastguard Worker tC->lpcStopBand = getTnsMaxBands(sampleRate, granuleLength,
398*e5436536SAndroid Build Coastguard Worker (blockType == SHORT_WINDOW) ? 1 : 0);
399*e5436536SAndroid Build Coastguard Worker
400*e5436536SAndroid Build Coastguard Worker if (tC->lpcStopBand < 0) {
401*e5436536SAndroid Build Coastguard Worker return (AAC_ENCODER_ERROR)1;
402*e5436536SAndroid Build Coastguard Worker }
403*e5436536SAndroid Build Coastguard Worker
404*e5436536SAndroid Build Coastguard Worker tC->lpcStopBand = fMin(tC->lpcStopBand, pC->sfbActive);
405*e5436536SAndroid Build Coastguard Worker tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand];
406*e5436536SAndroid Build Coastguard Worker
407*e5436536SAndroid Build Coastguard Worker switch (granuleLength) {
408*e5436536SAndroid Build Coastguard Worker case 960:
409*e5436536SAndroid Build Coastguard Worker case 1024:
410*e5436536SAndroid Build Coastguard Worker /* TNS start line: skip lower MDCT lines to prevent artifacts due to
411*e5436536SAndroid Build Coastguard Worker * filter mismatch */
412*e5436536SAndroid Build Coastguard Worker if (blockType == SHORT_WINDOW) {
413*e5436536SAndroid Build Coastguard Worker tC->lpcStartBand[LOFILT] = 0;
414*e5436536SAndroid Build Coastguard Worker } else {
415*e5436536SAndroid Build Coastguard Worker tC->lpcStartBand[LOFILT] =
416*e5436536SAndroid Build Coastguard Worker (sampleRate < 9391) ? 2 : ((sampleRate < 18783) ? 4 : 8);
417*e5436536SAndroid Build Coastguard Worker }
418*e5436536SAndroid Build Coastguard Worker tC->lpcStartLine[LOFILT] = pC->sfbOffset[tC->lpcStartBand[LOFILT]];
419*e5436536SAndroid Build Coastguard Worker
420*e5436536SAndroid Build Coastguard Worker i = tC->lpcStopBand;
421*e5436536SAndroid Build Coastguard Worker while (pC->sfbOffset[i] >
422*e5436536SAndroid Build Coastguard Worker (tC->lpcStartLine[LOFILT] +
423*e5436536SAndroid Build Coastguard Worker (tC->lpcStopLine - tC->lpcStartLine[LOFILT]) / 4))
424*e5436536SAndroid Build Coastguard Worker i--;
425*e5436536SAndroid Build Coastguard Worker tC->lpcStartBand[HIFILT] = i;
426*e5436536SAndroid Build Coastguard Worker tC->lpcStartLine[HIFILT] = pC->sfbOffset[i];
427*e5436536SAndroid Build Coastguard Worker
428*e5436536SAndroid Build Coastguard Worker tC->confTab.threshOn[HIFILT] = 1437;
429*e5436536SAndroid Build Coastguard Worker tC->confTab.threshOn[LOFILT] = 1500;
430*e5436536SAndroid Build Coastguard Worker
431*e5436536SAndroid Build Coastguard Worker tC->confTab.tnsLimitOrder[HIFILT] = tC->maxOrder;
432*e5436536SAndroid Build Coastguard Worker tC->confTab.tnsLimitOrder[LOFILT] = fMax(0, tC->maxOrder - 7);
433*e5436536SAndroid Build Coastguard Worker
434*e5436536SAndroid Build Coastguard Worker tC->confTab.tnsFilterDirection[HIFILT] = FILTER_DIRECTION;
435*e5436536SAndroid Build Coastguard Worker tC->confTab.tnsFilterDirection[LOFILT] = FILTER_DIRECTION;
436*e5436536SAndroid Build Coastguard Worker
437*e5436536SAndroid Build Coastguard Worker tC->confTab.acfSplit[HIFILT] =
438*e5436536SAndroid Build Coastguard Worker -1; /* signal Merged4to2QuartersAutoCorrelation in
439*e5436536SAndroid Build Coastguard Worker FDKaacEnc_MergedAutoCorrelation*/
440*e5436536SAndroid Build Coastguard Worker tC->confTab.acfSplit[LOFILT] =
441*e5436536SAndroid Build Coastguard Worker -1; /* signal Merged4to2QuartersAutoCorrelation in
442*e5436536SAndroid Build Coastguard Worker FDKaacEnc_MergedAutoCorrelation */
443*e5436536SAndroid Build Coastguard Worker
444*e5436536SAndroid Build Coastguard Worker tC->confTab.filterEnabled[HIFILT] = 1;
445*e5436536SAndroid Build Coastguard Worker tC->confTab.filterEnabled[LOFILT] = 1;
446*e5436536SAndroid Build Coastguard Worker tC->confTab.seperateFiltersAllowed = 1;
447*e5436536SAndroid Build Coastguard Worker
448*e5436536SAndroid Build Coastguard Worker /* compute autocorrelation window based on maximum filter order for given
449*e5436536SAndroid Build Coastguard Worker * block type */
450*e5436536SAndroid Build Coastguard Worker /* for (i = 0; i <= tC->maxOrder + 3; i++) {
451*e5436536SAndroid Build Coastguard Worker float acfWinTemp = acfTimeRes * i;
452*e5436536SAndroid Build Coastguard Worker acfWindow[i] = FL2FXCONST_DBL(1.0f - acfWinTemp * acfWinTemp);
453*e5436536SAndroid Build Coastguard Worker }
454*e5436536SAndroid Build Coastguard Worker */
455*e5436536SAndroid Build Coastguard Worker if (blockType == SHORT_WINDOW) {
456*e5436536SAndroid Build Coastguard Worker FDKmemcpy(tC->acfWindow[HIFILT], acfWindowShort,
457*e5436536SAndroid Build Coastguard Worker fMin((LONG)sizeof(acfWindowShort),
458*e5436536SAndroid Build Coastguard Worker (LONG)sizeof(tC->acfWindow[HIFILT])));
459*e5436536SAndroid Build Coastguard Worker FDKmemcpy(tC->acfWindow[LOFILT], acfWindowShort,
460*e5436536SAndroid Build Coastguard Worker fMin((LONG)sizeof(acfWindowShort),
461*e5436536SAndroid Build Coastguard Worker (LONG)sizeof(tC->acfWindow[HIFILT])));
462*e5436536SAndroid Build Coastguard Worker } else {
463*e5436536SAndroid Build Coastguard Worker FDKmemcpy(tC->acfWindow[HIFILT], acfWindowLong,
464*e5436536SAndroid Build Coastguard Worker fMin((LONG)sizeof(acfWindowLong),
465*e5436536SAndroid Build Coastguard Worker (LONG)sizeof(tC->acfWindow[HIFILT])));
466*e5436536SAndroid Build Coastguard Worker FDKmemcpy(tC->acfWindow[LOFILT], acfWindowLong,
467*e5436536SAndroid Build Coastguard Worker fMin((LONG)sizeof(acfWindowLong),
468*e5436536SAndroid Build Coastguard Worker (LONG)sizeof(tC->acfWindow[HIFILT])));
469*e5436536SAndroid Build Coastguard Worker }
470*e5436536SAndroid Build Coastguard Worker break;
471*e5436536SAndroid Build Coastguard Worker case 480:
472*e5436536SAndroid Build Coastguard Worker case 512: {
473*e5436536SAndroid Build Coastguard Worker const TNS_PARAMETER_TABULATED *pCfg =
474*e5436536SAndroid Build Coastguard Worker FDKaacEnc_GetTnsParam(bitRate, channels, ldSbrPresent);
475*e5436536SAndroid Build Coastguard Worker if (pCfg != NULL) {
476*e5436536SAndroid Build Coastguard Worker FDKmemcpy(&(tC->confTab), pCfg, sizeof(tC->confTab));
477*e5436536SAndroid Build Coastguard Worker
478*e5436536SAndroid Build Coastguard Worker tC->lpcStartBand[HIFILT] = FDKaacEnc_FreqToBandWidthRounding(
479*e5436536SAndroid Build Coastguard Worker pCfg->filterStartFreq[HIFILT], sampleRate, pC->sfbCnt,
480*e5436536SAndroid Build Coastguard Worker pC->sfbOffset);
481*e5436536SAndroid Build Coastguard Worker tC->lpcStartLine[HIFILT] = pC->sfbOffset[tC->lpcStartBand[HIFILT]];
482*e5436536SAndroid Build Coastguard Worker tC->lpcStartBand[LOFILT] = FDKaacEnc_FreqToBandWidthRounding(
483*e5436536SAndroid Build Coastguard Worker pCfg->filterStartFreq[LOFILT], sampleRate, pC->sfbCnt,
484*e5436536SAndroid Build Coastguard Worker pC->sfbOffset);
485*e5436536SAndroid Build Coastguard Worker tC->lpcStartLine[LOFILT] = pC->sfbOffset[tC->lpcStartBand[LOFILT]];
486*e5436536SAndroid Build Coastguard Worker
487*e5436536SAndroid Build Coastguard Worker FDKaacEnc_CalcGaussWindow(
488*e5436536SAndroid Build Coastguard Worker tC->acfWindow[HIFILT], tC->maxOrder + 1, sampleRate, granuleLength,
489*e5436536SAndroid Build Coastguard Worker pCfg->tnsTimeResolution[HIFILT], TNS_TIMERES_SCALE);
490*e5436536SAndroid Build Coastguard Worker FDKaacEnc_CalcGaussWindow(
491*e5436536SAndroid Build Coastguard Worker tC->acfWindow[LOFILT], tC->maxOrder + 1, sampleRate, granuleLength,
492*e5436536SAndroid Build Coastguard Worker pCfg->tnsTimeResolution[LOFILT], TNS_TIMERES_SCALE);
493*e5436536SAndroid Build Coastguard Worker } else {
494*e5436536SAndroid Build Coastguard Worker tC->tnsActive =
495*e5436536SAndroid Build Coastguard Worker FALSE; /* no configuration available, disable tns tool */
496*e5436536SAndroid Build Coastguard Worker }
497*e5436536SAndroid Build Coastguard Worker } break;
498*e5436536SAndroid Build Coastguard Worker default:
499*e5436536SAndroid Build Coastguard Worker tC->tnsActive = FALSE; /* no configuration available, disable tns tool */
500*e5436536SAndroid Build Coastguard Worker }
501*e5436536SAndroid Build Coastguard Worker
502*e5436536SAndroid Build Coastguard Worker return AAC_ENC_OK;
503*e5436536SAndroid Build Coastguard Worker }
504*e5436536SAndroid Build Coastguard Worker
505*e5436536SAndroid Build Coastguard Worker /***************************************************************************/
506*e5436536SAndroid Build Coastguard Worker /*!
507*e5436536SAndroid Build Coastguard Worker \brief FDKaacEnc_ScaleUpSpectrum
508*e5436536SAndroid Build Coastguard Worker
509*e5436536SAndroid Build Coastguard Worker Scales up spectrum lines in a given frequency section
510*e5436536SAndroid Build Coastguard Worker
511*e5436536SAndroid Build Coastguard Worker \param scaled spectrum
512*e5436536SAndroid Build Coastguard Worker \param original spectrum
513*e5436536SAndroid Build Coastguard Worker \param frequency line to start scaling
514*e5436536SAndroid Build Coastguard Worker \param frequency line to enc scaling
515*e5436536SAndroid Build Coastguard Worker
516*e5436536SAndroid Build Coastguard Worker \return scale factor
517*e5436536SAndroid Build Coastguard Worker
518*e5436536SAndroid Build Coastguard Worker ****************************************************************************/
FDKaacEnc_ScaleUpSpectrum(FIXP_DBL * dest,const FIXP_DBL * src,const INT startLine,const INT stopLine)519*e5436536SAndroid Build Coastguard Worker static inline INT FDKaacEnc_ScaleUpSpectrum(FIXP_DBL *dest, const FIXP_DBL *src,
520*e5436536SAndroid Build Coastguard Worker const INT startLine,
521*e5436536SAndroid Build Coastguard Worker const INT stopLine) {
522*e5436536SAndroid Build Coastguard Worker INT i, scale;
523*e5436536SAndroid Build Coastguard Worker
524*e5436536SAndroid Build Coastguard Worker FIXP_DBL maxVal = FL2FXCONST_DBL(0.f);
525*e5436536SAndroid Build Coastguard Worker
526*e5436536SAndroid Build Coastguard Worker /* Get highest value in given spectrum */
527*e5436536SAndroid Build Coastguard Worker for (i = startLine; i < stopLine; i++) {
528*e5436536SAndroid Build Coastguard Worker maxVal = fixMax(maxVal, fixp_abs(src[i]));
529*e5436536SAndroid Build Coastguard Worker }
530*e5436536SAndroid Build Coastguard Worker scale = CountLeadingBits(maxVal);
531*e5436536SAndroid Build Coastguard Worker
532*e5436536SAndroid Build Coastguard Worker /* Scale spectrum according to highest value */
533*e5436536SAndroid Build Coastguard Worker for (i = startLine; i < stopLine; i++) {
534*e5436536SAndroid Build Coastguard Worker dest[i] = src[i] << scale;
535*e5436536SAndroid Build Coastguard Worker }
536*e5436536SAndroid Build Coastguard Worker
537*e5436536SAndroid Build Coastguard Worker return scale;
538*e5436536SAndroid Build Coastguard Worker }
539*e5436536SAndroid Build Coastguard Worker
540*e5436536SAndroid Build Coastguard Worker /***************************************************************************/
541*e5436536SAndroid Build Coastguard Worker /*!
542*e5436536SAndroid Build Coastguard Worker \brief FDKaacEnc_CalcAutoCorrValue
543*e5436536SAndroid Build Coastguard Worker
544*e5436536SAndroid Build Coastguard Worker Calculate autocorellation value for one lag
545*e5436536SAndroid Build Coastguard Worker
546*e5436536SAndroid Build Coastguard Worker \param pointer to spectrum
547*e5436536SAndroid Build Coastguard Worker \param start line
548*e5436536SAndroid Build Coastguard Worker \param stop line
549*e5436536SAndroid Build Coastguard Worker \param lag to be calculated
550*e5436536SAndroid Build Coastguard Worker \param scaling of the lag
551*e5436536SAndroid Build Coastguard Worker
552*e5436536SAndroid Build Coastguard Worker ****************************************************************************/
FDKaacEnc_CalcAutoCorrValue(const FIXP_DBL * spectrum,const INT startLine,const INT stopLine,const INT lag,const INT scale)553*e5436536SAndroid Build Coastguard Worker static inline FIXP_DBL FDKaacEnc_CalcAutoCorrValue(const FIXP_DBL *spectrum,
554*e5436536SAndroid Build Coastguard Worker const INT startLine,
555*e5436536SAndroid Build Coastguard Worker const INT stopLine,
556*e5436536SAndroid Build Coastguard Worker const INT lag,
557*e5436536SAndroid Build Coastguard Worker const INT scale) {
558*e5436536SAndroid Build Coastguard Worker int i;
559*e5436536SAndroid Build Coastguard Worker FIXP_DBL result = FL2FXCONST_DBL(0.f);
560*e5436536SAndroid Build Coastguard Worker
561*e5436536SAndroid Build Coastguard Worker /* This versions allows to save memory accesses, when computing pow2 */
562*e5436536SAndroid Build Coastguard Worker /* It is of interest for ARM, XTENSA without parallel memory access */
563*e5436536SAndroid Build Coastguard Worker if (lag == 0) {
564*e5436536SAndroid Build Coastguard Worker for (i = startLine; i < stopLine; i++) {
565*e5436536SAndroid Build Coastguard Worker result += (fPow2(spectrum[i]) >> scale);
566*e5436536SAndroid Build Coastguard Worker }
567*e5436536SAndroid Build Coastguard Worker } else {
568*e5436536SAndroid Build Coastguard Worker for (i = startLine; i < (stopLine - lag); i++) {
569*e5436536SAndroid Build Coastguard Worker result += (fMult(spectrum[i], spectrum[i + lag]) >> scale);
570*e5436536SAndroid Build Coastguard Worker }
571*e5436536SAndroid Build Coastguard Worker }
572*e5436536SAndroid Build Coastguard Worker
573*e5436536SAndroid Build Coastguard Worker return result;
574*e5436536SAndroid Build Coastguard Worker }
575*e5436536SAndroid Build Coastguard Worker
576*e5436536SAndroid Build Coastguard Worker /***************************************************************************/
577*e5436536SAndroid Build Coastguard Worker /*!
578*e5436536SAndroid Build Coastguard Worker \brief FDKaacEnc_AutoCorrNormFac
579*e5436536SAndroid Build Coastguard Worker
580*e5436536SAndroid Build Coastguard Worker Autocorrelation function for 1st and 2nd half of the spectrum
581*e5436536SAndroid Build Coastguard Worker
582*e5436536SAndroid Build Coastguard Worker \param pointer to spectrum
583*e5436536SAndroid Build Coastguard Worker \param pointer to autocorrelation window
584*e5436536SAndroid Build Coastguard Worker \param filter start line
585*e5436536SAndroid Build Coastguard Worker
586*e5436536SAndroid Build Coastguard Worker ****************************************************************************/
FDKaacEnc_AutoCorrNormFac(const FIXP_DBL value,const INT scale,INT * sc)587*e5436536SAndroid Build Coastguard Worker static inline FIXP_DBL FDKaacEnc_AutoCorrNormFac(const FIXP_DBL value,
588*e5436536SAndroid Build Coastguard Worker const INT scale, INT *sc) {
589*e5436536SAndroid Build Coastguard Worker #define HLM_MIN_NRG 0.0000000037252902984619140625f /* 2^-28 */
590*e5436536SAndroid Build Coastguard Worker #define MAX_INV_NRGFAC (1.f / HLM_MIN_NRG)
591*e5436536SAndroid Build Coastguard Worker
592*e5436536SAndroid Build Coastguard Worker FIXP_DBL retValue;
593*e5436536SAndroid Build Coastguard Worker FIXP_DBL A, B;
594*e5436536SAndroid Build Coastguard Worker
595*e5436536SAndroid Build Coastguard Worker if (scale >= 0) {
596*e5436536SAndroid Build Coastguard Worker A = value;
597*e5436536SAndroid Build Coastguard Worker B = FL2FXCONST_DBL(HLM_MIN_NRG) >> fixMin(DFRACT_BITS - 1, scale);
598*e5436536SAndroid Build Coastguard Worker } else {
599*e5436536SAndroid Build Coastguard Worker A = value >> fixMin(DFRACT_BITS - 1, (-scale));
600*e5436536SAndroid Build Coastguard Worker B = FL2FXCONST_DBL(HLM_MIN_NRG);
601*e5436536SAndroid Build Coastguard Worker }
602*e5436536SAndroid Build Coastguard Worker
603*e5436536SAndroid Build Coastguard Worker if (A > B) {
604*e5436536SAndroid Build Coastguard Worker int shift = 0;
605*e5436536SAndroid Build Coastguard Worker FIXP_DBL tmp = invSqrtNorm2(value, &shift);
606*e5436536SAndroid Build Coastguard Worker
607*e5436536SAndroid Build Coastguard Worker retValue = fMult(tmp, tmp);
608*e5436536SAndroid Build Coastguard Worker *sc += (2 * shift);
609*e5436536SAndroid Build Coastguard Worker } else {
610*e5436536SAndroid Build Coastguard Worker /* MAX_INV_NRGFAC*FDKpow(2,-28) = 1/2^-28 * 2^-28 = 1.0 */
611*e5436536SAndroid Build Coastguard Worker retValue =
612*e5436536SAndroid Build Coastguard Worker /*FL2FXCONST_DBL(MAX_INV_NRGFAC*FDKpow(2,-28))*/ (FIXP_DBL)MAXVAL_DBL;
613*e5436536SAndroid Build Coastguard Worker *sc += scale + 28;
614*e5436536SAndroid Build Coastguard Worker }
615*e5436536SAndroid Build Coastguard Worker
616*e5436536SAndroid Build Coastguard Worker return retValue;
617*e5436536SAndroid Build Coastguard Worker }
618*e5436536SAndroid Build Coastguard Worker
FDKaacEnc_MergedAutoCorrelation(const FIXP_DBL * spectrum,const INT isLowDelay,const FIXP_DBL acfWindow[MAX_NUM_OF_FILTERS][TNS_MAX_ORDER+3+1],const INT lpcStartLine[MAX_NUM_OF_FILTERS],const INT lpcStopLine,const INT maxOrder,const INT acfSplit[MAX_NUM_OF_FILTERS],FIXP_DBL * _rxx1,FIXP_DBL * _rxx2)619*e5436536SAndroid Build Coastguard Worker static void FDKaacEnc_MergedAutoCorrelation(
620*e5436536SAndroid Build Coastguard Worker const FIXP_DBL *spectrum, const INT isLowDelay,
621*e5436536SAndroid Build Coastguard Worker const FIXP_DBL acfWindow[MAX_NUM_OF_FILTERS][TNS_MAX_ORDER + 3 + 1],
622*e5436536SAndroid Build Coastguard Worker const INT lpcStartLine[MAX_NUM_OF_FILTERS], const INT lpcStopLine,
623*e5436536SAndroid Build Coastguard Worker const INT maxOrder, const INT acfSplit[MAX_NUM_OF_FILTERS], FIXP_DBL *_rxx1,
624*e5436536SAndroid Build Coastguard Worker FIXP_DBL *_rxx2) {
625*e5436536SAndroid Build Coastguard Worker int i, idx0, idx1, idx2, idx3, idx4, lag;
626*e5436536SAndroid Build Coastguard Worker FIXP_DBL rxx1_0, rxx2_0, rxx3_0, rxx4_0;
627*e5436536SAndroid Build Coastguard Worker
628*e5436536SAndroid Build Coastguard Worker /* buffer for temporal spectrum */
629*e5436536SAndroid Build Coastguard Worker C_ALLOC_SCRATCH_START(pSpectrum, FIXP_DBL, (1024))
630*e5436536SAndroid Build Coastguard Worker
631*e5436536SAndroid Build Coastguard Worker /* MDCT line indices separating the 1st, 2nd, 3rd, and 4th analysis quarters
632*e5436536SAndroid Build Coastguard Worker */
633*e5436536SAndroid Build Coastguard Worker if ((acfSplit[LOFILT] == -1) || (acfSplit[HIFILT] == -1)) {
634*e5436536SAndroid Build Coastguard Worker /* autocorrelation function for 1st, 2nd, 3rd, and 4th quarter of the
635*e5436536SAndroid Build Coastguard Worker * spectrum */
636*e5436536SAndroid Build Coastguard Worker idx0 = lpcStartLine[LOFILT];
637*e5436536SAndroid Build Coastguard Worker i = lpcStopLine - lpcStartLine[LOFILT];
638*e5436536SAndroid Build Coastguard Worker idx1 = idx0 + i / 4;
639*e5436536SAndroid Build Coastguard Worker idx2 = idx0 + i / 2;
640*e5436536SAndroid Build Coastguard Worker idx3 = idx0 + i * 3 / 4;
641*e5436536SAndroid Build Coastguard Worker idx4 = lpcStopLine;
642*e5436536SAndroid Build Coastguard Worker } else {
643*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(acfSplit[LOFILT] == 1);
644*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(acfSplit[HIFILT] == 3);
645*e5436536SAndroid Build Coastguard Worker i = (lpcStopLine - lpcStartLine[HIFILT]) / 3;
646*e5436536SAndroid Build Coastguard Worker idx0 = lpcStartLine[LOFILT];
647*e5436536SAndroid Build Coastguard Worker idx1 = lpcStartLine[HIFILT];
648*e5436536SAndroid Build Coastguard Worker idx2 = idx1 + i;
649*e5436536SAndroid Build Coastguard Worker idx3 = idx2 + i;
650*e5436536SAndroid Build Coastguard Worker idx4 = lpcStopLine;
651*e5436536SAndroid Build Coastguard Worker }
652*e5436536SAndroid Build Coastguard Worker
653*e5436536SAndroid Build Coastguard Worker /* copy spectrum to temporal buffer and scale up as much as possible */
654*e5436536SAndroid Build Coastguard Worker INT sc1 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx0, idx1);
655*e5436536SAndroid Build Coastguard Worker INT sc2 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx1, idx2);
656*e5436536SAndroid Build Coastguard Worker INT sc3 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx2, idx3);
657*e5436536SAndroid Build Coastguard Worker INT sc4 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx3, idx4);
658*e5436536SAndroid Build Coastguard Worker
659*e5436536SAndroid Build Coastguard Worker /* get scaling values for summation */
660*e5436536SAndroid Build Coastguard Worker INT nsc1, nsc2, nsc3, nsc4;
661*e5436536SAndroid Build Coastguard Worker for (nsc1 = 1; (1 << nsc1) < (idx1 - idx0); nsc1++)
662*e5436536SAndroid Build Coastguard Worker ;
663*e5436536SAndroid Build Coastguard Worker for (nsc2 = 1; (1 << nsc2) < (idx2 - idx1); nsc2++)
664*e5436536SAndroid Build Coastguard Worker ;
665*e5436536SAndroid Build Coastguard Worker for (nsc3 = 1; (1 << nsc3) < (idx3 - idx2); nsc3++)
666*e5436536SAndroid Build Coastguard Worker ;
667*e5436536SAndroid Build Coastguard Worker for (nsc4 = 1; (1 << nsc4) < (idx4 - idx3); nsc4++)
668*e5436536SAndroid Build Coastguard Worker ;
669*e5436536SAndroid Build Coastguard Worker
670*e5436536SAndroid Build Coastguard Worker /* compute autocorrelation value at lag zero, i. e. energy, for each quarter
671*e5436536SAndroid Build Coastguard Worker */
672*e5436536SAndroid Build Coastguard Worker rxx1_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, 0, nsc1);
673*e5436536SAndroid Build Coastguard Worker rxx2_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx1, idx2, 0, nsc2);
674*e5436536SAndroid Build Coastguard Worker rxx3_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx2, idx3, 0, nsc3);
675*e5436536SAndroid Build Coastguard Worker rxx4_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx3, idx4, 0, nsc4);
676*e5436536SAndroid Build Coastguard Worker
677*e5436536SAndroid Build Coastguard Worker /* compute energy normalization factors, i. e. 1/energy (saves some divisions)
678*e5436536SAndroid Build Coastguard Worker */
679*e5436536SAndroid Build Coastguard Worker if (rxx1_0 != FL2FXCONST_DBL(0.f)) {
680*e5436536SAndroid Build Coastguard Worker INT sc_fac1 = -1;
681*e5436536SAndroid Build Coastguard Worker FIXP_DBL fac1 =
682*e5436536SAndroid Build Coastguard Worker FDKaacEnc_AutoCorrNormFac(rxx1_0, ((-2 * sc1) + nsc1), &sc_fac1);
683*e5436536SAndroid Build Coastguard Worker _rxx1[0] = scaleValue(fMult(rxx1_0, fac1), sc_fac1);
684*e5436536SAndroid Build Coastguard Worker
685*e5436536SAndroid Build Coastguard Worker if (isLowDelay) {
686*e5436536SAndroid Build Coastguard Worker for (lag = 1; lag <= maxOrder; lag++) {
687*e5436536SAndroid Build Coastguard Worker /* compute energy-normalized and windowed autocorrelation values at this
688*e5436536SAndroid Build Coastguard Worker * lag */
689*e5436536SAndroid Build Coastguard Worker FIXP_DBL x1 =
690*e5436536SAndroid Build Coastguard Worker FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, lag, nsc1);
691*e5436536SAndroid Build Coastguard Worker _rxx1[lag] =
692*e5436536SAndroid Build Coastguard Worker fMult(scaleValue(fMult(x1, fac1), sc_fac1), acfWindow[LOFILT][lag]);
693*e5436536SAndroid Build Coastguard Worker }
694*e5436536SAndroid Build Coastguard Worker } else {
695*e5436536SAndroid Build Coastguard Worker for (lag = 1; lag <= maxOrder; lag++) {
696*e5436536SAndroid Build Coastguard Worker if ((3 * lag) <= maxOrder + 3) {
697*e5436536SAndroid Build Coastguard Worker FIXP_DBL x1 =
698*e5436536SAndroid Build Coastguard Worker FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, lag, nsc1);
699*e5436536SAndroid Build Coastguard Worker _rxx1[lag] = fMult(scaleValue(fMult(x1, fac1), sc_fac1),
700*e5436536SAndroid Build Coastguard Worker acfWindow[LOFILT][3 * lag]);
701*e5436536SAndroid Build Coastguard Worker }
702*e5436536SAndroid Build Coastguard Worker }
703*e5436536SAndroid Build Coastguard Worker }
704*e5436536SAndroid Build Coastguard Worker }
705*e5436536SAndroid Build Coastguard Worker
706*e5436536SAndroid Build Coastguard Worker /* auto corr over upper 3/4 of spectrum */
707*e5436536SAndroid Build Coastguard Worker if (!((rxx2_0 == FL2FXCONST_DBL(0.f)) && (rxx3_0 == FL2FXCONST_DBL(0.f)) &&
708*e5436536SAndroid Build Coastguard Worker (rxx4_0 == FL2FXCONST_DBL(0.f)))) {
709*e5436536SAndroid Build Coastguard Worker FIXP_DBL fac2, fac3, fac4;
710*e5436536SAndroid Build Coastguard Worker fac2 = fac3 = fac4 = FL2FXCONST_DBL(0.f);
711*e5436536SAndroid Build Coastguard Worker INT sc_fac2, sc_fac3, sc_fac4;
712*e5436536SAndroid Build Coastguard Worker sc_fac2 = sc_fac3 = sc_fac4 = 0;
713*e5436536SAndroid Build Coastguard Worker
714*e5436536SAndroid Build Coastguard Worker if (rxx2_0 != FL2FXCONST_DBL(0.f)) {
715*e5436536SAndroid Build Coastguard Worker fac2 = FDKaacEnc_AutoCorrNormFac(rxx2_0, ((-2 * sc2) + nsc2), &sc_fac2);
716*e5436536SAndroid Build Coastguard Worker sc_fac2 -= 2;
717*e5436536SAndroid Build Coastguard Worker }
718*e5436536SAndroid Build Coastguard Worker if (rxx3_0 != FL2FXCONST_DBL(0.f)) {
719*e5436536SAndroid Build Coastguard Worker fac3 = FDKaacEnc_AutoCorrNormFac(rxx3_0, ((-2 * sc3) + nsc3), &sc_fac3);
720*e5436536SAndroid Build Coastguard Worker sc_fac3 -= 2;
721*e5436536SAndroid Build Coastguard Worker }
722*e5436536SAndroid Build Coastguard Worker if (rxx4_0 != FL2FXCONST_DBL(0.f)) {
723*e5436536SAndroid Build Coastguard Worker fac4 = FDKaacEnc_AutoCorrNormFac(rxx4_0, ((-2 * sc4) + nsc4), &sc_fac4);
724*e5436536SAndroid Build Coastguard Worker sc_fac4 -= 2;
725*e5436536SAndroid Build Coastguard Worker }
726*e5436536SAndroid Build Coastguard Worker
727*e5436536SAndroid Build Coastguard Worker _rxx2[0] = scaleValue(fMult(rxx2_0, fac2), sc_fac2) +
728*e5436536SAndroid Build Coastguard Worker scaleValue(fMult(rxx3_0, fac3), sc_fac3) +
729*e5436536SAndroid Build Coastguard Worker scaleValue(fMult(rxx4_0, fac4), sc_fac4);
730*e5436536SAndroid Build Coastguard Worker
731*e5436536SAndroid Build Coastguard Worker for (lag = 1; lag <= maxOrder; lag++) {
732*e5436536SAndroid Build Coastguard Worker /* merge quarters 2, 3, 4 into one autocorrelation; quarter 1 stays
733*e5436536SAndroid Build Coastguard Worker * separate */
734*e5436536SAndroid Build Coastguard Worker FIXP_DBL x2 = scaleValue(fMult(FDKaacEnc_CalcAutoCorrValue(
735*e5436536SAndroid Build Coastguard Worker pSpectrum, idx1, idx2, lag, nsc2),
736*e5436536SAndroid Build Coastguard Worker fac2),
737*e5436536SAndroid Build Coastguard Worker sc_fac2) +
738*e5436536SAndroid Build Coastguard Worker scaleValue(fMult(FDKaacEnc_CalcAutoCorrValue(
739*e5436536SAndroid Build Coastguard Worker pSpectrum, idx2, idx3, lag, nsc3),
740*e5436536SAndroid Build Coastguard Worker fac3),
741*e5436536SAndroid Build Coastguard Worker sc_fac3) +
742*e5436536SAndroid Build Coastguard Worker scaleValue(fMult(FDKaacEnc_CalcAutoCorrValue(
743*e5436536SAndroid Build Coastguard Worker pSpectrum, idx3, idx4, lag, nsc4),
744*e5436536SAndroid Build Coastguard Worker fac4),
745*e5436536SAndroid Build Coastguard Worker sc_fac4);
746*e5436536SAndroid Build Coastguard Worker
747*e5436536SAndroid Build Coastguard Worker _rxx2[lag] = fMult(x2, acfWindow[HIFILT][lag]);
748*e5436536SAndroid Build Coastguard Worker }
749*e5436536SAndroid Build Coastguard Worker }
750*e5436536SAndroid Build Coastguard Worker
751*e5436536SAndroid Build Coastguard Worker C_ALLOC_SCRATCH_END(pSpectrum, FIXP_DBL, (1024))
752*e5436536SAndroid Build Coastguard Worker }
753*e5436536SAndroid Build Coastguard Worker
754*e5436536SAndroid Build Coastguard Worker /*****************************************************************************
755*e5436536SAndroid Build Coastguard Worker functionname: FDKaacEnc_TnsDetect
756*e5436536SAndroid Build Coastguard Worker description: do decision, if TNS shall be used or not
757*e5436536SAndroid Build Coastguard Worker returns:
758*e5436536SAndroid Build Coastguard Worker input: tns data structure (modified),
759*e5436536SAndroid Build Coastguard Worker tns config structure,
760*e5436536SAndroid Build Coastguard Worker scalefactor size and table,
761*e5436536SAndroid Build Coastguard Worker spectrum,
762*e5436536SAndroid Build Coastguard Worker subblock num, blocktype,
763*e5436536SAndroid Build Coastguard Worker sfb-wise energy.
764*e5436536SAndroid Build Coastguard Worker
765*e5436536SAndroid Build Coastguard Worker *****************************************************************************/
FDKaacEnc_TnsDetect(TNS_DATA * tnsData,const TNS_CONFIG * tC,TNS_INFO * tnsInfo,INT sfbCnt,const FIXP_DBL * spectrum,INT subBlockNumber,INT blockType)766*e5436536SAndroid Build Coastguard Worker INT FDKaacEnc_TnsDetect(TNS_DATA *tnsData, const TNS_CONFIG *tC,
767*e5436536SAndroid Build Coastguard Worker TNS_INFO *tnsInfo, INT sfbCnt, const FIXP_DBL *spectrum,
768*e5436536SAndroid Build Coastguard Worker INT subBlockNumber, INT blockType) {
769*e5436536SAndroid Build Coastguard Worker /* autocorrelation function for 1st, 2nd, 3rd, and 4th quarter of the
770*e5436536SAndroid Build Coastguard Worker * spectrum. */
771*e5436536SAndroid Build Coastguard Worker FIXP_DBL rxx1[TNS_MAX_ORDER + 1]; /* higher part */
772*e5436536SAndroid Build Coastguard Worker FIXP_DBL rxx2[TNS_MAX_ORDER + 1]; /* lower part */
773*e5436536SAndroid Build Coastguard Worker FIXP_LPC parcor_tmp[TNS_MAX_ORDER];
774*e5436536SAndroid Build Coastguard Worker
775*e5436536SAndroid Build Coastguard Worker int i;
776*e5436536SAndroid Build Coastguard Worker
777*e5436536SAndroid Build Coastguard Worker FDKmemclear(rxx1, sizeof(rxx1));
778*e5436536SAndroid Build Coastguard Worker FDKmemclear(rxx2, sizeof(rxx2));
779*e5436536SAndroid Build Coastguard Worker
780*e5436536SAndroid Build Coastguard Worker TNS_SUBBLOCK_INFO *tsbi =
781*e5436536SAndroid Build Coastguard Worker (blockType == SHORT_WINDOW)
782*e5436536SAndroid Build Coastguard Worker ? &tnsData->dataRaw.Short.subBlockInfo[subBlockNumber]
783*e5436536SAndroid Build Coastguard Worker : &tnsData->dataRaw.Long.subBlockInfo;
784*e5436536SAndroid Build Coastguard Worker
785*e5436536SAndroid Build Coastguard Worker tnsData->filtersMerged = FALSE;
786*e5436536SAndroid Build Coastguard Worker
787*e5436536SAndroid Build Coastguard Worker tsbi->tnsActive[HIFILT] = FALSE;
788*e5436536SAndroid Build Coastguard Worker tsbi->predictionGain[HIFILT] = 1000;
789*e5436536SAndroid Build Coastguard Worker tsbi->tnsActive[LOFILT] = FALSE;
790*e5436536SAndroid Build Coastguard Worker tsbi->predictionGain[LOFILT] = 1000;
791*e5436536SAndroid Build Coastguard Worker
792*e5436536SAndroid Build Coastguard Worker tnsInfo->numOfFilters[subBlockNumber] = 0;
793*e5436536SAndroid Build Coastguard Worker tnsInfo->coefRes[subBlockNumber] = tC->coefRes;
794*e5436536SAndroid Build Coastguard Worker for (i = 0; i < tC->maxOrder; i++) {
795*e5436536SAndroid Build Coastguard Worker tnsInfo->coef[subBlockNumber][HIFILT][i] =
796*e5436536SAndroid Build Coastguard Worker tnsInfo->coef[subBlockNumber][LOFILT][i] = 0;
797*e5436536SAndroid Build Coastguard Worker }
798*e5436536SAndroid Build Coastguard Worker
799*e5436536SAndroid Build Coastguard Worker tnsInfo->length[subBlockNumber][HIFILT] =
800*e5436536SAndroid Build Coastguard Worker tnsInfo->length[subBlockNumber][LOFILT] = 0;
801*e5436536SAndroid Build Coastguard Worker tnsInfo->order[subBlockNumber][HIFILT] =
802*e5436536SAndroid Build Coastguard Worker tnsInfo->order[subBlockNumber][LOFILT] = 0;
803*e5436536SAndroid Build Coastguard Worker
804*e5436536SAndroid Build Coastguard Worker if ((tC->tnsActive) && (tC->maxOrder > 0)) {
805*e5436536SAndroid Build Coastguard Worker int sumSqrCoef;
806*e5436536SAndroid Build Coastguard Worker
807*e5436536SAndroid Build Coastguard Worker FDKaacEnc_MergedAutoCorrelation(
808*e5436536SAndroid Build Coastguard Worker spectrum, tC->isLowDelay, tC->acfWindow, tC->lpcStartLine,
809*e5436536SAndroid Build Coastguard Worker tC->lpcStopLine, tC->maxOrder, tC->confTab.acfSplit, rxx1, rxx2);
810*e5436536SAndroid Build Coastguard Worker
811*e5436536SAndroid Build Coastguard Worker /* compute higher TNS filter coefficients in lattice form (ParCor) with
812*e5436536SAndroid Build Coastguard Worker * LeRoux-Gueguen/Schur algorithm */
813*e5436536SAndroid Build Coastguard Worker {
814*e5436536SAndroid Build Coastguard Worker FIXP_DBL predictionGain_m;
815*e5436536SAndroid Build Coastguard Worker INT predictionGain_e;
816*e5436536SAndroid Build Coastguard Worker
817*e5436536SAndroid Build Coastguard Worker CLpc_AutoToParcor(rxx2, 0, parcor_tmp, tC->confTab.tnsLimitOrder[HIFILT],
818*e5436536SAndroid Build Coastguard Worker &predictionGain_m, &predictionGain_e);
819*e5436536SAndroid Build Coastguard Worker tsbi->predictionGain[HIFILT] =
820*e5436536SAndroid Build Coastguard Worker (INT)fMultNorm(predictionGain_m, predictionGain_e, 1000, 31, 31);
821*e5436536SAndroid Build Coastguard Worker }
822*e5436536SAndroid Build Coastguard Worker
823*e5436536SAndroid Build Coastguard Worker /* non-linear quantization of TNS lattice coefficients with given resolution
824*e5436536SAndroid Build Coastguard Worker */
825*e5436536SAndroid Build Coastguard Worker FDKaacEnc_Parcor2Index(parcor_tmp, tnsInfo->coef[subBlockNumber][HIFILT],
826*e5436536SAndroid Build Coastguard Worker tC->confTab.tnsLimitOrder[HIFILT], tC->coefRes);
827*e5436536SAndroid Build Coastguard Worker
828*e5436536SAndroid Build Coastguard Worker /* reduce filter order by truncating trailing zeros, compute sum(abs(coefs))
829*e5436536SAndroid Build Coastguard Worker */
830*e5436536SAndroid Build Coastguard Worker for (i = tC->confTab.tnsLimitOrder[HIFILT] - 1; i >= 0; i--) {
831*e5436536SAndroid Build Coastguard Worker if (tnsInfo->coef[subBlockNumber][HIFILT][i] != 0) {
832*e5436536SAndroid Build Coastguard Worker break;
833*e5436536SAndroid Build Coastguard Worker }
834*e5436536SAndroid Build Coastguard Worker }
835*e5436536SAndroid Build Coastguard Worker
836*e5436536SAndroid Build Coastguard Worker tnsInfo->order[subBlockNumber][HIFILT] = i + 1;
837*e5436536SAndroid Build Coastguard Worker
838*e5436536SAndroid Build Coastguard Worker sumSqrCoef = 0;
839*e5436536SAndroid Build Coastguard Worker for (; i >= 0; i--) {
840*e5436536SAndroid Build Coastguard Worker sumSqrCoef += tnsInfo->coef[subBlockNumber][HIFILT][i] *
841*e5436536SAndroid Build Coastguard Worker tnsInfo->coef[subBlockNumber][HIFILT][i];
842*e5436536SAndroid Build Coastguard Worker }
843*e5436536SAndroid Build Coastguard Worker
844*e5436536SAndroid Build Coastguard Worker tnsInfo->direction[subBlockNumber][HIFILT] =
845*e5436536SAndroid Build Coastguard Worker tC->confTab.tnsFilterDirection[HIFILT];
846*e5436536SAndroid Build Coastguard Worker tnsInfo->length[subBlockNumber][HIFILT] = sfbCnt - tC->lpcStartBand[HIFILT];
847*e5436536SAndroid Build Coastguard Worker
848*e5436536SAndroid Build Coastguard Worker /* disable TNS if predictionGain is less than 3dB or sumSqrCoef is too small
849*e5436536SAndroid Build Coastguard Worker */
850*e5436536SAndroid Build Coastguard Worker if ((tsbi->predictionGain[HIFILT] > tC->confTab.threshOn[HIFILT]) ||
851*e5436536SAndroid Build Coastguard Worker (sumSqrCoef > (tC->confTab.tnsLimitOrder[HIFILT] / 2 + 2))) {
852*e5436536SAndroid Build Coastguard Worker tsbi->tnsActive[HIFILT] = TRUE;
853*e5436536SAndroid Build Coastguard Worker tnsInfo->numOfFilters[subBlockNumber]++;
854*e5436536SAndroid Build Coastguard Worker
855*e5436536SAndroid Build Coastguard Worker /* compute second filter for lower quarter; only allowed for long windows!
856*e5436536SAndroid Build Coastguard Worker */
857*e5436536SAndroid Build Coastguard Worker if ((blockType != SHORT_WINDOW) && (tC->confTab.filterEnabled[LOFILT]) &&
858*e5436536SAndroid Build Coastguard Worker (tC->confTab.seperateFiltersAllowed)) {
859*e5436536SAndroid Build Coastguard Worker /* compute second filter for lower frequencies */
860*e5436536SAndroid Build Coastguard Worker
861*e5436536SAndroid Build Coastguard Worker /* compute TNS filter in lattice (ParCor) form with LeRoux-Gueguen
862*e5436536SAndroid Build Coastguard Worker * algorithm */
863*e5436536SAndroid Build Coastguard Worker INT predGain;
864*e5436536SAndroid Build Coastguard Worker {
865*e5436536SAndroid Build Coastguard Worker FIXP_DBL predictionGain_m;
866*e5436536SAndroid Build Coastguard Worker INT predictionGain_e;
867*e5436536SAndroid Build Coastguard Worker
868*e5436536SAndroid Build Coastguard Worker CLpc_AutoToParcor(rxx1, 0, parcor_tmp,
869*e5436536SAndroid Build Coastguard Worker tC->confTab.tnsLimitOrder[LOFILT],
870*e5436536SAndroid Build Coastguard Worker &predictionGain_m, &predictionGain_e);
871*e5436536SAndroid Build Coastguard Worker predGain =
872*e5436536SAndroid Build Coastguard Worker (INT)fMultNorm(predictionGain_m, predictionGain_e, 1000, 31, 31);
873*e5436536SAndroid Build Coastguard Worker }
874*e5436536SAndroid Build Coastguard Worker
875*e5436536SAndroid Build Coastguard Worker /* non-linear quantization of TNS lattice coefficients with given
876*e5436536SAndroid Build Coastguard Worker * resolution */
877*e5436536SAndroid Build Coastguard Worker FDKaacEnc_Parcor2Index(parcor_tmp,
878*e5436536SAndroid Build Coastguard Worker tnsInfo->coef[subBlockNumber][LOFILT],
879*e5436536SAndroid Build Coastguard Worker tC->confTab.tnsLimitOrder[LOFILT], tC->coefRes);
880*e5436536SAndroid Build Coastguard Worker
881*e5436536SAndroid Build Coastguard Worker /* reduce filter order by truncating trailing zeros, compute
882*e5436536SAndroid Build Coastguard Worker * sum(abs(coefs)) */
883*e5436536SAndroid Build Coastguard Worker for (i = tC->confTab.tnsLimitOrder[LOFILT] - 1; i >= 0; i--) {
884*e5436536SAndroid Build Coastguard Worker if (tnsInfo->coef[subBlockNumber][LOFILT][i] != 0) {
885*e5436536SAndroid Build Coastguard Worker break;
886*e5436536SAndroid Build Coastguard Worker }
887*e5436536SAndroid Build Coastguard Worker }
888*e5436536SAndroid Build Coastguard Worker tnsInfo->order[subBlockNumber][LOFILT] = i + 1;
889*e5436536SAndroid Build Coastguard Worker
890*e5436536SAndroid Build Coastguard Worker sumSqrCoef = 0;
891*e5436536SAndroid Build Coastguard Worker for (; i >= 0; i--) {
892*e5436536SAndroid Build Coastguard Worker sumSqrCoef += tnsInfo->coef[subBlockNumber][LOFILT][i] *
893*e5436536SAndroid Build Coastguard Worker tnsInfo->coef[subBlockNumber][LOFILT][i];
894*e5436536SAndroid Build Coastguard Worker }
895*e5436536SAndroid Build Coastguard Worker
896*e5436536SAndroid Build Coastguard Worker tnsInfo->direction[subBlockNumber][LOFILT] =
897*e5436536SAndroid Build Coastguard Worker tC->confTab.tnsFilterDirection[LOFILT];
898*e5436536SAndroid Build Coastguard Worker tnsInfo->length[subBlockNumber][LOFILT] =
899*e5436536SAndroid Build Coastguard Worker tC->lpcStartBand[HIFILT] - tC->lpcStartBand[LOFILT];
900*e5436536SAndroid Build Coastguard Worker
901*e5436536SAndroid Build Coastguard Worker /* filter lower quarter if gain is high enough, but not if it's too high
902*e5436536SAndroid Build Coastguard Worker */
903*e5436536SAndroid Build Coastguard Worker if (((predGain > tC->confTab.threshOn[LOFILT]) &&
904*e5436536SAndroid Build Coastguard Worker (predGain < (16000 * tC->confTab.tnsLimitOrder[LOFILT]))) ||
905*e5436536SAndroid Build Coastguard Worker ((sumSqrCoef > 9) &&
906*e5436536SAndroid Build Coastguard Worker (sumSqrCoef < 22 * tC->confTab.tnsLimitOrder[LOFILT]))) {
907*e5436536SAndroid Build Coastguard Worker /* compare lower to upper filter; if they are very similar, merge them
908*e5436536SAndroid Build Coastguard Worker */
909*e5436536SAndroid Build Coastguard Worker tsbi->tnsActive[LOFILT] = TRUE;
910*e5436536SAndroid Build Coastguard Worker sumSqrCoef = 0;
911*e5436536SAndroid Build Coastguard Worker for (i = 0; i < tC->confTab.tnsLimitOrder[LOFILT]; i++) {
912*e5436536SAndroid Build Coastguard Worker sumSqrCoef += fAbs(tnsInfo->coef[subBlockNumber][HIFILT][i] -
913*e5436536SAndroid Build Coastguard Worker tnsInfo->coef[subBlockNumber][LOFILT][i]);
914*e5436536SAndroid Build Coastguard Worker }
915*e5436536SAndroid Build Coastguard Worker if ((sumSqrCoef < 2) &&
916*e5436536SAndroid Build Coastguard Worker (tnsInfo->direction[subBlockNumber][LOFILT] ==
917*e5436536SAndroid Build Coastguard Worker tnsInfo->direction[subBlockNumber][HIFILT])) {
918*e5436536SAndroid Build Coastguard Worker tnsData->filtersMerged = TRUE;
919*e5436536SAndroid Build Coastguard Worker tnsInfo->length[subBlockNumber][HIFILT] =
920*e5436536SAndroid Build Coastguard Worker sfbCnt - tC->lpcStartBand[LOFILT];
921*e5436536SAndroid Build Coastguard Worker for (; i < tnsInfo->order[subBlockNumber][HIFILT]; i++) {
922*e5436536SAndroid Build Coastguard Worker if (fAbs(tnsInfo->coef[subBlockNumber][HIFILT][i]) > 1) {
923*e5436536SAndroid Build Coastguard Worker break;
924*e5436536SAndroid Build Coastguard Worker }
925*e5436536SAndroid Build Coastguard Worker }
926*e5436536SAndroid Build Coastguard Worker for (i--; i >= 0; i--) {
927*e5436536SAndroid Build Coastguard Worker if (tnsInfo->coef[subBlockNumber][HIFILT][i] != 0) {
928*e5436536SAndroid Build Coastguard Worker break;
929*e5436536SAndroid Build Coastguard Worker }
930*e5436536SAndroid Build Coastguard Worker }
931*e5436536SAndroid Build Coastguard Worker if (i < tnsInfo->order[subBlockNumber][HIFILT]) {
932*e5436536SAndroid Build Coastguard Worker tnsInfo->order[subBlockNumber][HIFILT] = i + 1;
933*e5436536SAndroid Build Coastguard Worker }
934*e5436536SAndroid Build Coastguard Worker } else {
935*e5436536SAndroid Build Coastguard Worker tnsInfo->numOfFilters[subBlockNumber]++;
936*e5436536SAndroid Build Coastguard Worker }
937*e5436536SAndroid Build Coastguard Worker } /* filter lower part */
938*e5436536SAndroid Build Coastguard Worker tsbi->predictionGain[LOFILT] = predGain;
939*e5436536SAndroid Build Coastguard Worker
940*e5436536SAndroid Build Coastguard Worker } /* second filter allowed */
941*e5436536SAndroid Build Coastguard Worker } /* if predictionGain > 1437 ... */
942*e5436536SAndroid Build Coastguard Worker } /* maxOrder > 0 && tnsActive */
943*e5436536SAndroid Build Coastguard Worker
944*e5436536SAndroid Build Coastguard Worker return 0;
945*e5436536SAndroid Build Coastguard Worker }
946*e5436536SAndroid Build Coastguard Worker
947*e5436536SAndroid Build Coastguard Worker /***************************************************************************/
948*e5436536SAndroid Build Coastguard Worker /*!
949*e5436536SAndroid Build Coastguard Worker \brief FDKaacLdEnc_TnsSync
950*e5436536SAndroid Build Coastguard Worker
951*e5436536SAndroid Build Coastguard Worker synchronize TNS parameters when TNS gain difference small (relative)
952*e5436536SAndroid Build Coastguard Worker
953*e5436536SAndroid Build Coastguard Worker \param pointer to TNS data structure (destination)
954*e5436536SAndroid Build Coastguard Worker \param pointer to TNS data structure (source)
955*e5436536SAndroid Build Coastguard Worker \param pointer to TNS config structure
956*e5436536SAndroid Build Coastguard Worker \param number of sub-block
957*e5436536SAndroid Build Coastguard Worker \param block type
958*e5436536SAndroid Build Coastguard Worker
959*e5436536SAndroid Build Coastguard Worker \return void
960*e5436536SAndroid Build Coastguard Worker ****************************************************************************/
FDKaacEnc_TnsSync(TNS_DATA * tnsDataDest,const TNS_DATA * tnsDataSrc,TNS_INFO * tnsInfoDest,TNS_INFO * tnsInfoSrc,const INT blockTypeDest,const INT blockTypeSrc,const TNS_CONFIG * tC)961*e5436536SAndroid Build Coastguard Worker void FDKaacEnc_TnsSync(TNS_DATA *tnsDataDest, const TNS_DATA *tnsDataSrc,
962*e5436536SAndroid Build Coastguard Worker TNS_INFO *tnsInfoDest, TNS_INFO *tnsInfoSrc,
963*e5436536SAndroid Build Coastguard Worker const INT blockTypeDest, const INT blockTypeSrc,
964*e5436536SAndroid Build Coastguard Worker const TNS_CONFIG *tC) {
965*e5436536SAndroid Build Coastguard Worker int i, w, absDiff, nWindows;
966*e5436536SAndroid Build Coastguard Worker TNS_SUBBLOCK_INFO *sbInfoDest;
967*e5436536SAndroid Build Coastguard Worker const TNS_SUBBLOCK_INFO *sbInfoSrc;
968*e5436536SAndroid Build Coastguard Worker
969*e5436536SAndroid Build Coastguard Worker /* if one channel contains short blocks and the other not, do not synchronize
970*e5436536SAndroid Build Coastguard Worker */
971*e5436536SAndroid Build Coastguard Worker if ((blockTypeSrc == SHORT_WINDOW && blockTypeDest != SHORT_WINDOW) ||
972*e5436536SAndroid Build Coastguard Worker (blockTypeDest == SHORT_WINDOW && blockTypeSrc != SHORT_WINDOW)) {
973*e5436536SAndroid Build Coastguard Worker return;
974*e5436536SAndroid Build Coastguard Worker }
975*e5436536SAndroid Build Coastguard Worker
976*e5436536SAndroid Build Coastguard Worker if (blockTypeDest != SHORT_WINDOW) {
977*e5436536SAndroid Build Coastguard Worker sbInfoDest = &tnsDataDest->dataRaw.Long.subBlockInfo;
978*e5436536SAndroid Build Coastguard Worker sbInfoSrc = &tnsDataSrc->dataRaw.Long.subBlockInfo;
979*e5436536SAndroid Build Coastguard Worker nWindows = 1;
980*e5436536SAndroid Build Coastguard Worker } else {
981*e5436536SAndroid Build Coastguard Worker sbInfoDest = &tnsDataDest->dataRaw.Short.subBlockInfo[0];
982*e5436536SAndroid Build Coastguard Worker sbInfoSrc = &tnsDataSrc->dataRaw.Short.subBlockInfo[0];
983*e5436536SAndroid Build Coastguard Worker nWindows = 8;
984*e5436536SAndroid Build Coastguard Worker }
985*e5436536SAndroid Build Coastguard Worker
986*e5436536SAndroid Build Coastguard Worker for (w = 0; w < nWindows; w++) {
987*e5436536SAndroid Build Coastguard Worker const TNS_SUBBLOCK_INFO *pSbInfoSrcW = sbInfoSrc + w;
988*e5436536SAndroid Build Coastguard Worker TNS_SUBBLOCK_INFO *pSbInfoDestW = sbInfoDest + w;
989*e5436536SAndroid Build Coastguard Worker INT doSync = 1, absDiffSum = 0;
990*e5436536SAndroid Build Coastguard Worker
991*e5436536SAndroid Build Coastguard Worker /* if TNS is active in at least one channel, check if ParCor coefficients of
992*e5436536SAndroid Build Coastguard Worker * higher filter are similar */
993*e5436536SAndroid Build Coastguard Worker if (pSbInfoDestW->tnsActive[HIFILT] || pSbInfoSrcW->tnsActive[HIFILT]) {
994*e5436536SAndroid Build Coastguard Worker for (i = 0; i < tC->maxOrder; i++) {
995*e5436536SAndroid Build Coastguard Worker absDiff = fAbs(tnsInfoDest->coef[w][HIFILT][i] -
996*e5436536SAndroid Build Coastguard Worker tnsInfoSrc->coef[w][HIFILT][i]);
997*e5436536SAndroid Build Coastguard Worker absDiffSum += absDiff;
998*e5436536SAndroid Build Coastguard Worker /* if coefficients diverge too much between channels, do not synchronize
999*e5436536SAndroid Build Coastguard Worker */
1000*e5436536SAndroid Build Coastguard Worker if ((absDiff > 1) || (absDiffSum > 2)) {
1001*e5436536SAndroid Build Coastguard Worker doSync = 0;
1002*e5436536SAndroid Build Coastguard Worker break;
1003*e5436536SAndroid Build Coastguard Worker }
1004*e5436536SAndroid Build Coastguard Worker }
1005*e5436536SAndroid Build Coastguard Worker
1006*e5436536SAndroid Build Coastguard Worker if (doSync) {
1007*e5436536SAndroid Build Coastguard Worker /* if no significant difference was detected, synchronize coefficient
1008*e5436536SAndroid Build Coastguard Worker * sets */
1009*e5436536SAndroid Build Coastguard Worker if (pSbInfoSrcW->tnsActive[HIFILT]) {
1010*e5436536SAndroid Build Coastguard Worker /* no dest filter, or more dest than source filters: use one dest
1011*e5436536SAndroid Build Coastguard Worker * filter */
1012*e5436536SAndroid Build Coastguard Worker if ((!pSbInfoDestW->tnsActive[HIFILT]) ||
1013*e5436536SAndroid Build Coastguard Worker ((pSbInfoDestW->tnsActive[HIFILT]) &&
1014*e5436536SAndroid Build Coastguard Worker (tnsInfoDest->numOfFilters[w] > tnsInfoSrc->numOfFilters[w]))) {
1015*e5436536SAndroid Build Coastguard Worker pSbInfoDestW->tnsActive[HIFILT] = tnsInfoDest->numOfFilters[w] = 1;
1016*e5436536SAndroid Build Coastguard Worker }
1017*e5436536SAndroid Build Coastguard Worker tnsDataDest->filtersMerged = tnsDataSrc->filtersMerged;
1018*e5436536SAndroid Build Coastguard Worker tnsInfoDest->order[w][HIFILT] = tnsInfoSrc->order[w][HIFILT];
1019*e5436536SAndroid Build Coastguard Worker tnsInfoDest->length[w][HIFILT] = tnsInfoSrc->length[w][HIFILT];
1020*e5436536SAndroid Build Coastguard Worker tnsInfoDest->direction[w][HIFILT] = tnsInfoSrc->direction[w][HIFILT];
1021*e5436536SAndroid Build Coastguard Worker tnsInfoDest->coefCompress[w][HIFILT] =
1022*e5436536SAndroid Build Coastguard Worker tnsInfoSrc->coefCompress[w][HIFILT];
1023*e5436536SAndroid Build Coastguard Worker
1024*e5436536SAndroid Build Coastguard Worker for (i = 0; i < tC->maxOrder; i++) {
1025*e5436536SAndroid Build Coastguard Worker tnsInfoDest->coef[w][HIFILT][i] = tnsInfoSrc->coef[w][HIFILT][i];
1026*e5436536SAndroid Build Coastguard Worker }
1027*e5436536SAndroid Build Coastguard Worker } else
1028*e5436536SAndroid Build Coastguard Worker pSbInfoDestW->tnsActive[HIFILT] = tnsInfoDest->numOfFilters[w] = 0;
1029*e5436536SAndroid Build Coastguard Worker }
1030*e5436536SAndroid Build Coastguard Worker }
1031*e5436536SAndroid Build Coastguard Worker }
1032*e5436536SAndroid Build Coastguard Worker }
1033*e5436536SAndroid Build Coastguard Worker
1034*e5436536SAndroid Build Coastguard Worker /***************************************************************************/
1035*e5436536SAndroid Build Coastguard Worker /*!
1036*e5436536SAndroid Build Coastguard Worker \brief FDKaacEnc_TnsEncode
1037*e5436536SAndroid Build Coastguard Worker
1038*e5436536SAndroid Build Coastguard Worker perform TNS encoding
1039*e5436536SAndroid Build Coastguard Worker
1040*e5436536SAndroid Build Coastguard Worker \param pointer to TNS info structure
1041*e5436536SAndroid Build Coastguard Worker \param pointer to TNS data structure
1042*e5436536SAndroid Build Coastguard Worker \param number of sfbs
1043*e5436536SAndroid Build Coastguard Worker \param pointer to TNS config structure
1044*e5436536SAndroid Build Coastguard Worker \param low-pass line
1045*e5436536SAndroid Build Coastguard Worker \param pointer to spectrum
1046*e5436536SAndroid Build Coastguard Worker \param number of sub-block
1047*e5436536SAndroid Build Coastguard Worker \param block type
1048*e5436536SAndroid Build Coastguard Worker
1049*e5436536SAndroid Build Coastguard Worker \return ERROR STATUS
1050*e5436536SAndroid Build Coastguard Worker ****************************************************************************/
FDKaacEnc_TnsEncode(TNS_INFO * tnsInfo,TNS_DATA * tnsData,const INT numOfSfb,const TNS_CONFIG * tC,const INT lowPassLine,FIXP_DBL * spectrum,const INT subBlockNumber,const INT blockType)1051*e5436536SAndroid Build Coastguard Worker INT FDKaacEnc_TnsEncode(TNS_INFO *tnsInfo, TNS_DATA *tnsData,
1052*e5436536SAndroid Build Coastguard Worker const INT numOfSfb, const TNS_CONFIG *tC,
1053*e5436536SAndroid Build Coastguard Worker const INT lowPassLine, FIXP_DBL *spectrum,
1054*e5436536SAndroid Build Coastguard Worker const INT subBlockNumber, const INT blockType) {
1055*e5436536SAndroid Build Coastguard Worker INT i, startLine, stopLine;
1056*e5436536SAndroid Build Coastguard Worker
1057*e5436536SAndroid Build Coastguard Worker if (((blockType == SHORT_WINDOW) &&
1058*e5436536SAndroid Build Coastguard Worker (!tnsData->dataRaw.Short.subBlockInfo[subBlockNumber]
1059*e5436536SAndroid Build Coastguard Worker .tnsActive[HIFILT])) ||
1060*e5436536SAndroid Build Coastguard Worker ((blockType != SHORT_WINDOW) &&
1061*e5436536SAndroid Build Coastguard Worker (!tnsData->dataRaw.Long.subBlockInfo.tnsActive[HIFILT]))) {
1062*e5436536SAndroid Build Coastguard Worker return 1;
1063*e5436536SAndroid Build Coastguard Worker }
1064*e5436536SAndroid Build Coastguard Worker
1065*e5436536SAndroid Build Coastguard Worker startLine = (tnsData->filtersMerged) ? tC->lpcStartLine[LOFILT]
1066*e5436536SAndroid Build Coastguard Worker : tC->lpcStartLine[HIFILT];
1067*e5436536SAndroid Build Coastguard Worker stopLine = tC->lpcStopLine;
1068*e5436536SAndroid Build Coastguard Worker
1069*e5436536SAndroid Build Coastguard Worker for (i = 0; i < tnsInfo->numOfFilters[subBlockNumber]; i++) {
1070*e5436536SAndroid Build Coastguard Worker INT lpcGainFactor;
1071*e5436536SAndroid Build Coastguard Worker FIXP_LPC LpcCoeff[TNS_MAX_ORDER];
1072*e5436536SAndroid Build Coastguard Worker FIXP_DBL workBuffer[TNS_MAX_ORDER];
1073*e5436536SAndroid Build Coastguard Worker FIXP_LPC parcor_tmp[TNS_MAX_ORDER];
1074*e5436536SAndroid Build Coastguard Worker
1075*e5436536SAndroid Build Coastguard Worker FDKaacEnc_Index2Parcor(tnsInfo->coef[subBlockNumber][i], parcor_tmp,
1076*e5436536SAndroid Build Coastguard Worker tnsInfo->order[subBlockNumber][i], tC->coefRes);
1077*e5436536SAndroid Build Coastguard Worker
1078*e5436536SAndroid Build Coastguard Worker lpcGainFactor = CLpc_ParcorToLpc(
1079*e5436536SAndroid Build Coastguard Worker parcor_tmp, LpcCoeff, tnsInfo->order[subBlockNumber][i], workBuffer);
1080*e5436536SAndroid Build Coastguard Worker
1081*e5436536SAndroid Build Coastguard Worker FDKmemclear(workBuffer, TNS_MAX_ORDER * sizeof(FIXP_DBL));
1082*e5436536SAndroid Build Coastguard Worker CLpc_Analysis(&spectrum[startLine], stopLine - startLine, LpcCoeff,
1083*e5436536SAndroid Build Coastguard Worker lpcGainFactor, tnsInfo->order[subBlockNumber][i], workBuffer,
1084*e5436536SAndroid Build Coastguard Worker NULL);
1085*e5436536SAndroid Build Coastguard Worker
1086*e5436536SAndroid Build Coastguard Worker /* update for second filter */
1087*e5436536SAndroid Build Coastguard Worker startLine = tC->lpcStartLine[LOFILT];
1088*e5436536SAndroid Build Coastguard Worker stopLine = tC->lpcStartLine[HIFILT];
1089*e5436536SAndroid Build Coastguard Worker }
1090*e5436536SAndroid Build Coastguard Worker
1091*e5436536SAndroid Build Coastguard Worker return (0);
1092*e5436536SAndroid Build Coastguard Worker }
1093*e5436536SAndroid Build Coastguard Worker
FDKaacEnc_CalcGaussWindow(FIXP_DBL * win,const int winSize,const INT samplingRate,const INT transformResolution,const FIXP_DBL timeResolution,const INT timeResolution_e)1094*e5436536SAndroid Build Coastguard Worker static void FDKaacEnc_CalcGaussWindow(FIXP_DBL *win, const int winSize,
1095*e5436536SAndroid Build Coastguard Worker const INT samplingRate,
1096*e5436536SAndroid Build Coastguard Worker const INT transformResolution,
1097*e5436536SAndroid Build Coastguard Worker const FIXP_DBL timeResolution,
1098*e5436536SAndroid Build Coastguard Worker const INT timeResolution_e) {
1099*e5436536SAndroid Build Coastguard Worker #define PI_E (2)
1100*e5436536SAndroid Build Coastguard Worker #define PI_M FL2FXCONST_DBL(3.1416f / (float)(1 << PI_E))
1101*e5436536SAndroid Build Coastguard Worker
1102*e5436536SAndroid Build Coastguard Worker #define EULER_E (2)
1103*e5436536SAndroid Build Coastguard Worker #define EULER_M FL2FXCONST_DBL(2.7183 / (float)(1 << EULER_E))
1104*e5436536SAndroid Build Coastguard Worker
1105*e5436536SAndroid Build Coastguard Worker #define COEFF_LOOP_SCALE (4)
1106*e5436536SAndroid Build Coastguard Worker
1107*e5436536SAndroid Build Coastguard Worker INT i, e1, e2, gaussExp_e;
1108*e5436536SAndroid Build Coastguard Worker FIXP_DBL gaussExp_m;
1109*e5436536SAndroid Build Coastguard Worker
1110*e5436536SAndroid Build Coastguard Worker /* calc. window exponent from time resolution:
1111*e5436536SAndroid Build Coastguard Worker *
1112*e5436536SAndroid Build Coastguard Worker * gaussExp = PI * samplingRate * 0.001f * timeResolution /
1113*e5436536SAndroid Build Coastguard Worker * transformResolution; gaussExp = -0.5f * gaussExp * gaussExp;
1114*e5436536SAndroid Build Coastguard Worker */
1115*e5436536SAndroid Build Coastguard Worker gaussExp_m = fMultNorm(
1116*e5436536SAndroid Build Coastguard Worker timeResolution,
1117*e5436536SAndroid Build Coastguard Worker fMult(PI_M,
1118*e5436536SAndroid Build Coastguard Worker fDivNorm((FIXP_DBL)(samplingRate),
1119*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)(LONG)(transformResolution * 1000.f), &e1)),
1120*e5436536SAndroid Build Coastguard Worker &e2);
1121*e5436536SAndroid Build Coastguard Worker gaussExp_m = -fPow2Div2(gaussExp_m);
1122*e5436536SAndroid Build Coastguard Worker gaussExp_e = 2 * (e1 + e2 + timeResolution_e + PI_E);
1123*e5436536SAndroid Build Coastguard Worker
1124*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(winSize < (1 << COEFF_LOOP_SCALE));
1125*e5436536SAndroid Build Coastguard Worker
1126*e5436536SAndroid Build Coastguard Worker /* calc. window coefficients
1127*e5436536SAndroid Build Coastguard Worker * win[i] = (float)exp( gaussExp * (i+0.5) * (i+0.5) );
1128*e5436536SAndroid Build Coastguard Worker */
1129*e5436536SAndroid Build Coastguard Worker for (i = 0; i < winSize; i++) {
1130*e5436536SAndroid Build Coastguard Worker win[i] = fPow(
1131*e5436536SAndroid Build Coastguard Worker EULER_M, EULER_E,
1132*e5436536SAndroid Build Coastguard Worker fMult(gaussExp_m,
1133*e5436536SAndroid Build Coastguard Worker fPow2((i * FL2FXCONST_DBL(1.f / (float)(1 << COEFF_LOOP_SCALE)) +
1134*e5436536SAndroid Build Coastguard Worker FL2FXCONST_DBL(.5f / (float)(1 << COEFF_LOOP_SCALE))))),
1135*e5436536SAndroid Build Coastguard Worker gaussExp_e + 2 * COEFF_LOOP_SCALE, &e1);
1136*e5436536SAndroid Build Coastguard Worker
1137*e5436536SAndroid Build Coastguard Worker win[i] = scaleValueSaturate(win[i], e1);
1138*e5436536SAndroid Build Coastguard Worker }
1139*e5436536SAndroid Build Coastguard Worker }
1140*e5436536SAndroid Build Coastguard Worker
FDKaacEnc_Search3(FIXP_LPC parcor)1141*e5436536SAndroid Build Coastguard Worker static INT FDKaacEnc_Search3(FIXP_LPC parcor) {
1142*e5436536SAndroid Build Coastguard Worker INT i, index = 0;
1143*e5436536SAndroid Build Coastguard Worker
1144*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
1145*e5436536SAndroid Build Coastguard Worker if (parcor > FDKaacEnc_tnsCoeff3Borders[i]) index = i;
1146*e5436536SAndroid Build Coastguard Worker }
1147*e5436536SAndroid Build Coastguard Worker return (index - 4);
1148*e5436536SAndroid Build Coastguard Worker }
1149*e5436536SAndroid Build Coastguard Worker
FDKaacEnc_Search4(FIXP_LPC parcor)1150*e5436536SAndroid Build Coastguard Worker static INT FDKaacEnc_Search4(FIXP_LPC parcor) {
1151*e5436536SAndroid Build Coastguard Worker INT i, index = 0;
1152*e5436536SAndroid Build Coastguard Worker
1153*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 16; i++) {
1154*e5436536SAndroid Build Coastguard Worker if (parcor > FDKaacEnc_tnsCoeff4Borders[i]) index = i;
1155*e5436536SAndroid Build Coastguard Worker }
1156*e5436536SAndroid Build Coastguard Worker return (index - 8);
1157*e5436536SAndroid Build Coastguard Worker }
1158*e5436536SAndroid Build Coastguard Worker
1159*e5436536SAndroid Build Coastguard Worker /*****************************************************************************
1160*e5436536SAndroid Build Coastguard Worker
1161*e5436536SAndroid Build Coastguard Worker functionname: FDKaacEnc_Parcor2Index
1162*e5436536SAndroid Build Coastguard Worker
1163*e5436536SAndroid Build Coastguard Worker *****************************************************************************/
FDKaacEnc_Parcor2Index(const FIXP_LPC * parcor,INT * RESTRICT index,const INT order,const INT bitsPerCoeff)1164*e5436536SAndroid Build Coastguard Worker static void FDKaacEnc_Parcor2Index(const FIXP_LPC *parcor, INT *RESTRICT index,
1165*e5436536SAndroid Build Coastguard Worker const INT order, const INT bitsPerCoeff) {
1166*e5436536SAndroid Build Coastguard Worker INT i;
1167*e5436536SAndroid Build Coastguard Worker for (i = 0; i < order; i++) {
1168*e5436536SAndroid Build Coastguard Worker if (bitsPerCoeff == 3)
1169*e5436536SAndroid Build Coastguard Worker index[i] = FDKaacEnc_Search3(parcor[i]);
1170*e5436536SAndroid Build Coastguard Worker else
1171*e5436536SAndroid Build Coastguard Worker index[i] = FDKaacEnc_Search4(parcor[i]);
1172*e5436536SAndroid Build Coastguard Worker }
1173*e5436536SAndroid Build Coastguard Worker }
1174*e5436536SAndroid Build Coastguard Worker
1175*e5436536SAndroid Build Coastguard Worker /*****************************************************************************
1176*e5436536SAndroid Build Coastguard Worker
1177*e5436536SAndroid Build Coastguard Worker functionname: FDKaacEnc_Index2Parcor
1178*e5436536SAndroid Build Coastguard Worker description: inverse quantization for reflection coefficients
1179*e5436536SAndroid Build Coastguard Worker returns: -
1180*e5436536SAndroid Build Coastguard Worker input: quantized values, ptr. to reflection coefficients,
1181*e5436536SAndroid Build Coastguard Worker no. of coefficients, resolution
1182*e5436536SAndroid Build Coastguard Worker output: reflection coefficients
1183*e5436536SAndroid Build Coastguard Worker
1184*e5436536SAndroid Build Coastguard Worker *****************************************************************************/
FDKaacEnc_Index2Parcor(const INT * index,FIXP_LPC * RESTRICT parcor,const INT order,const INT bitsPerCoeff)1185*e5436536SAndroid Build Coastguard Worker static void FDKaacEnc_Index2Parcor(const INT *index, FIXP_LPC *RESTRICT parcor,
1186*e5436536SAndroid Build Coastguard Worker const INT order, const INT bitsPerCoeff) {
1187*e5436536SAndroid Build Coastguard Worker INT i;
1188*e5436536SAndroid Build Coastguard Worker for (i = 0; i < order; i++)
1189*e5436536SAndroid Build Coastguard Worker parcor[i] = bitsPerCoeff == 4 ? FDKaacEnc_tnsEncCoeff4[index[i] + 8]
1190*e5436536SAndroid Build Coastguard Worker : FDKaacEnc_tnsEncCoeff3[index[i] + 4];
1191*e5436536SAndroid Build Coastguard Worker }
1192