xref: /aosp_15_r20/external/aac/libSBRenc/src/sbr_encoder.cpp (revision e54365361535b070c2db7374cec45c159c7d0e7a)
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 - 2020 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 /**************************** SBR encoder library ******************************
96*e5436536SAndroid Build Coastguard Worker 
97*e5436536SAndroid Build Coastguard Worker    Author(s):   Andreas Ehret, Tobias Chalupka
98*e5436536SAndroid Build Coastguard Worker 
99*e5436536SAndroid Build Coastguard Worker    Description: SBR encoder top level processing.
100*e5436536SAndroid Build Coastguard Worker 
101*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
102*e5436536SAndroid Build Coastguard Worker 
103*e5436536SAndroid Build Coastguard Worker #include "sbr_encoder.h"
104*e5436536SAndroid Build Coastguard Worker 
105*e5436536SAndroid Build Coastguard Worker #include "sbrenc_ram.h"
106*e5436536SAndroid Build Coastguard Worker #include "sbrenc_rom.h"
107*e5436536SAndroid Build Coastguard Worker #include "sbrenc_freq_sca.h"
108*e5436536SAndroid Build Coastguard Worker #include "env_bit.h"
109*e5436536SAndroid Build Coastguard Worker #include "cmondata.h"
110*e5436536SAndroid Build Coastguard Worker #include "sbr_misc.h"
111*e5436536SAndroid Build Coastguard Worker #include "sbr.h"
112*e5436536SAndroid Build Coastguard Worker #include "qmf.h"
113*e5436536SAndroid Build Coastguard Worker 
114*e5436536SAndroid Build Coastguard Worker #include "ps_main.h"
115*e5436536SAndroid Build Coastguard Worker 
116*e5436536SAndroid Build Coastguard Worker #define SBRENCODER_LIB_VL0 4
117*e5436536SAndroid Build Coastguard Worker #define SBRENCODER_LIB_VL1 0
118*e5436536SAndroid Build Coastguard Worker #define SBRENCODER_LIB_VL2 0
119*e5436536SAndroid Build Coastguard Worker 
120*e5436536SAndroid Build Coastguard Worker /***************************************************************************/
121*e5436536SAndroid Build Coastguard Worker /*
122*e5436536SAndroid Build Coastguard Worker  * SBR Delay balancing definitions.
123*e5436536SAndroid Build Coastguard Worker  */
124*e5436536SAndroid Build Coastguard Worker 
125*e5436536SAndroid Build Coastguard Worker /*
126*e5436536SAndroid Build Coastguard Worker       input buffer (1ch)
127*e5436536SAndroid Build Coastguard Worker 
128*e5436536SAndroid Build Coastguard Worker       |------------ 1537   -------------|-----|---------- 2048 -------------|
129*e5436536SAndroid Build Coastguard Worker            (core2sbr delay     )          ds     (read, core and ds area)
130*e5436536SAndroid Build Coastguard Worker */
131*e5436536SAndroid Build Coastguard Worker 
132*e5436536SAndroid Build Coastguard Worker #define SFB(dwnsmp) \
133*e5436536SAndroid Build Coastguard Worker   (32 << (dwnsmp -  \
134*e5436536SAndroid Build Coastguard Worker           1)) /* SBR Frequency bands: 64 for dual-rate, 32 for single-rate */
135*e5436536SAndroid Build Coastguard Worker #define STS(fl)                                                              \
136*e5436536SAndroid Build Coastguard Worker   (((fl) == 1024) ? 32                                                       \
137*e5436536SAndroid Build Coastguard Worker                   : 30) /* SBR Time Slots: 32 for core frame length 1024, 30 \
138*e5436536SAndroid Build Coastguard Worker                            for core frame length 960 */
139*e5436536SAndroid Build Coastguard Worker 
140*e5436536SAndroid Build Coastguard Worker #define DELAY_QMF_ANA(dwnsmp) \
141*e5436536SAndroid Build Coastguard Worker   ((320 << ((dwnsmp)-1)) - (32 << ((dwnsmp)-1))) /* Full bandwidth */
142*e5436536SAndroid Build Coastguard Worker #define DELAY_HYB_ANA (10 * 64) /* + 0.5 */      /*  */
143*e5436536SAndroid Build Coastguard Worker #define DELAY_HYB_SYN (6 * 64 - 32)              /*  */
144*e5436536SAndroid Build Coastguard Worker #define DELAY_QMF_POSTPROC(dwnsmp) \
145*e5436536SAndroid Build Coastguard Worker   (32 * (dwnsmp))                               /* QMF postprocessing delay */
146*e5436536SAndroid Build Coastguard Worker #define DELAY_DEC_QMF(dwnsmp) (6 * SFB(dwnsmp)) /* Decoder QMF overlap */
147*e5436536SAndroid Build Coastguard Worker #define DELAY_QMF_SYN(dwnsmp) \
148*e5436536SAndroid Build Coastguard Worker   (1 << (dwnsmp -             \
149*e5436536SAndroid Build Coastguard Worker          1)) /* QMF_NO_POLY/2=2.5, rounded down to 2, half for single-rate */
150*e5436536SAndroid Build Coastguard Worker #define DELAY_QMF_DS (32) /* QMF synthesis for downsampled time signal */
151*e5436536SAndroid Build Coastguard Worker 
152*e5436536SAndroid Build Coastguard Worker /* Delay in QMF paths */
153*e5436536SAndroid Build Coastguard Worker #define DELAY_SBR(fl, dwnsmp) \
154*e5436536SAndroid Build Coastguard Worker   (DELAY_QMF_ANA(dwnsmp) + (SFB(dwnsmp) * STS(fl) - 1) + DELAY_QMF_SYN(dwnsmp))
155*e5436536SAndroid Build Coastguard Worker #define DELAY_PS(fl, dwnsmp)                                       \
156*e5436536SAndroid Build Coastguard Worker   (DELAY_QMF_ANA(dwnsmp) + DELAY_HYB_ANA + DELAY_DEC_QMF(dwnsmp) + \
157*e5436536SAndroid Build Coastguard Worker    (SFB(dwnsmp) * STS(fl) - 1) + DELAY_HYB_SYN + DELAY_QMF_SYN(dwnsmp))
158*e5436536SAndroid Build Coastguard Worker #define DELAY_ELDSBR(fl, dwnsmp) \
159*e5436536SAndroid Build Coastguard Worker   ((((fl) / 2) * (dwnsmp)) - 1 + DELAY_QMF_POSTPROC(dwnsmp))
160*e5436536SAndroid Build Coastguard Worker #define DELAY_ELDv2SBR(fl, dwnsmp)                                        \
161*e5436536SAndroid Build Coastguard Worker   ((((fl) / 2) * (dwnsmp)) - 1 + 80 * (dwnsmp)) /* 80 is the delay caused \
162*e5436536SAndroid Build Coastguard Worker                                                    by the sum of the CLD  \
163*e5436536SAndroid Build Coastguard Worker                                                    analysis and the MPSLD \
164*e5436536SAndroid Build Coastguard Worker                                                    synthesis filterbank */
165*e5436536SAndroid Build Coastguard Worker 
166*e5436536SAndroid Build Coastguard Worker /* Delay in core path (core and downsampler not taken into account) */
167*e5436536SAndroid Build Coastguard Worker #define DELAY_COREPATH_SBR(fl, dwnsmp) \
168*e5436536SAndroid Build Coastguard Worker   ((DELAY_QMF_ANA(dwnsmp) + DELAY_DEC_QMF(dwnsmp) + DELAY_QMF_SYN(dwnsmp)))
169*e5436536SAndroid Build Coastguard Worker #define DELAY_COREPATH_ELDSBR(fl, dwnsmp) ((DELAY_QMF_POSTPROC(dwnsmp)))
170*e5436536SAndroid Build Coastguard Worker #define DELAY_COREPATH_ELDv2SBR(fl, dwnsmp) (128 * (dwnsmp)) /* 4 slots */
171*e5436536SAndroid Build Coastguard Worker #define DELAY_COREPATH_PS(fl, dwnsmp)                                        \
172*e5436536SAndroid Build Coastguard Worker   ((DELAY_QMF_ANA(dwnsmp) + DELAY_QMF_DS +                                   \
173*e5436536SAndroid Build Coastguard Worker     /*(DELAY_AAC(fl)*2) + */ DELAY_QMF_ANA(dwnsmp) + DELAY_DEC_QMF(dwnsmp) + \
174*e5436536SAndroid Build Coastguard Worker     DELAY_HYB_SYN + DELAY_QMF_SYN(dwnsmp))) /* 2048 - 463*2 */
175*e5436536SAndroid Build Coastguard Worker 
176*e5436536SAndroid Build Coastguard Worker /* Delay differences between SBR- and downsampled path for SBR and SBR+PS */
177*e5436536SAndroid Build Coastguard Worker #define DELAY_AAC2SBR(fl, dwnsmp) \
178*e5436536SAndroid Build Coastguard Worker   ((DELAY_COREPATH_SBR(fl, dwnsmp)) - DELAY_SBR((fl), (dwnsmp)))
179*e5436536SAndroid Build Coastguard Worker #define DELAY_ELD2SBR(fl, dwnsmp) \
180*e5436536SAndroid Build Coastguard Worker   ((DELAY_COREPATH_ELDSBR(fl, dwnsmp)) - DELAY_ELDSBR(fl, dwnsmp))
181*e5436536SAndroid Build Coastguard Worker #define DELAY_AAC2PS(fl, dwnsmp) \
182*e5436536SAndroid Build Coastguard Worker   ((DELAY_COREPATH_PS(fl, dwnsmp)) - DELAY_PS(fl, dwnsmp)) /* 2048 - 463*2 */
183*e5436536SAndroid Build Coastguard Worker 
184*e5436536SAndroid Build Coastguard Worker /* Assumption: The sample delay resulting of of DELAY_AAC2PS is always smaller
185*e5436536SAndroid Build Coastguard Worker  * than the sample delay implied by DELAY_AAC2SBR */
186*e5436536SAndroid Build Coastguard Worker #define MAX_DS_FILTER_DELAY \
187*e5436536SAndroid Build Coastguard Worker   (5) /* the additional max downsampler filter delay (source fs) */
188*e5436536SAndroid Build Coastguard Worker #define MAX_SAMPLE_DELAY                                                 \
189*e5436536SAndroid Build Coastguard Worker   (DELAY_AAC2SBR(1024, 2) + MAX_DS_FILTER_DELAY) /* maximum delay: frame \
190*e5436536SAndroid Build Coastguard Worker                                                     length of 1024 and   \
191*e5436536SAndroid Build Coastguard Worker                                                     dual-rate sbr */
192*e5436536SAndroid Build Coastguard Worker 
193*e5436536SAndroid Build Coastguard Worker /***************************************************************************/
194*e5436536SAndroid Build Coastguard Worker 
195*e5436536SAndroid Build Coastguard Worker /*************** Delay parameters for sbrEncoder_Init_delay() **************/
196*e5436536SAndroid Build Coastguard Worker typedef struct {
197*e5436536SAndroid Build Coastguard Worker   int dsDelay;        /* the delay of the (time-domain) downsampler itself */
198*e5436536SAndroid Build Coastguard Worker   int delay;          /* overall delay / samples  */
199*e5436536SAndroid Build Coastguard Worker   int sbrDecDelay;    /* SBR decoder's delay */
200*e5436536SAndroid Build Coastguard Worker   int corePathOffset; /* core path offset / samples; added by
201*e5436536SAndroid Build Coastguard Worker                          sbrEncoder_Init_delay() */
202*e5436536SAndroid Build Coastguard Worker   int sbrPathOffset;  /* SBR path offset / samples; added by
203*e5436536SAndroid Build Coastguard Worker                          sbrEncoder_Init_delay() */
204*e5436536SAndroid Build Coastguard Worker   int bitstrDelay; /* bitstream delay / frames; added by sbrEncoder_Init_delay()
205*e5436536SAndroid Build Coastguard Worker                     */
206*e5436536SAndroid Build Coastguard Worker   int delayInput2Core; /* delay of the input to the core / samples */
207*e5436536SAndroid Build Coastguard Worker } DELAY_PARAM;
208*e5436536SAndroid Build Coastguard Worker /***************************************************************************/
209*e5436536SAndroid Build Coastguard Worker 
210*e5436536SAndroid Build Coastguard Worker #define INVALID_TABLE_IDX -1
211*e5436536SAndroid Build Coastguard Worker 
212*e5436536SAndroid Build Coastguard Worker /***************************************************************************/
213*e5436536SAndroid Build Coastguard Worker /*!
214*e5436536SAndroid Build Coastguard Worker 
215*e5436536SAndroid Build Coastguard Worker   \brief  Selects the SBR tuning settings to use dependent on number of
216*e5436536SAndroid Build Coastguard Worker           channels, bitrate, sample rate and core coder
217*e5436536SAndroid Build Coastguard Worker 
218*e5436536SAndroid Build Coastguard Worker   \return Index to the appropriate table
219*e5436536SAndroid Build Coastguard Worker 
220*e5436536SAndroid Build Coastguard Worker ****************************************************************************/
221*e5436536SAndroid Build Coastguard Worker #define DISTANCE_CEIL_VALUE 5000000
getSbrTuningTableIndex(UINT bitrate,UINT numChannels,UINT sampleRate,AUDIO_OBJECT_TYPE core,UINT * pBitRateClosest)222*e5436536SAndroid Build Coastguard Worker static INT getSbrTuningTableIndex(
223*e5436536SAndroid Build Coastguard Worker     UINT bitrate,     /*! the total bitrate in bits/sec */
224*e5436536SAndroid Build Coastguard Worker     UINT numChannels, /*! the number of channels for the core coder */
225*e5436536SAndroid Build Coastguard Worker     UINT sampleRate,  /*! the sampling rate of the core coder */
226*e5436536SAndroid Build Coastguard Worker     AUDIO_OBJECT_TYPE core, UINT *pBitRateClosest) {
227*e5436536SAndroid Build Coastguard Worker   int i, bitRateClosestLowerIndex = -1, bitRateClosestUpperIndex = -1,
228*e5436536SAndroid Build Coastguard Worker          found = 0;
229*e5436536SAndroid Build Coastguard Worker   UINT bitRateClosestUpper = 0, bitRateClosestLower = DISTANCE_CEIL_VALUE;
230*e5436536SAndroid Build Coastguard Worker 
231*e5436536SAndroid Build Coastguard Worker #define isForThisCore(i)                                                     \
232*e5436536SAndroid Build Coastguard Worker   ((sbrTuningTable[i].coreCoder == CODEC_AACLD && core == AOT_ER_AAC_ELD) || \
233*e5436536SAndroid Build Coastguard Worker    (sbrTuningTable[i].coreCoder == CODEC_AAC && core != AOT_ER_AAC_ELD))
234*e5436536SAndroid Build Coastguard Worker 
235*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < sbrTuningTableSize; i++) {
236*e5436536SAndroid Build Coastguard Worker     if (isForThisCore(i)) /* tuning table is for this core codec */
237*e5436536SAndroid Build Coastguard Worker     {
238*e5436536SAndroid Build Coastguard Worker       if (numChannels == sbrTuningTable[i].numChannels &&
239*e5436536SAndroid Build Coastguard Worker           sampleRate == sbrTuningTable[i].sampleRate) {
240*e5436536SAndroid Build Coastguard Worker         found = 1;
241*e5436536SAndroid Build Coastguard Worker         if ((bitrate >= sbrTuningTable[i].bitrateFrom) &&
242*e5436536SAndroid Build Coastguard Worker             (bitrate < sbrTuningTable[i].bitrateTo)) {
243*e5436536SAndroid Build Coastguard Worker           return i;
244*e5436536SAndroid Build Coastguard Worker         } else {
245*e5436536SAndroid Build Coastguard Worker           if (sbrTuningTable[i].bitrateFrom > bitrate) {
246*e5436536SAndroid Build Coastguard Worker             if (sbrTuningTable[i].bitrateFrom < bitRateClosestLower) {
247*e5436536SAndroid Build Coastguard Worker               bitRateClosestLower = sbrTuningTable[i].bitrateFrom;
248*e5436536SAndroid Build Coastguard Worker               bitRateClosestLowerIndex = i;
249*e5436536SAndroid Build Coastguard Worker             }
250*e5436536SAndroid Build Coastguard Worker           }
251*e5436536SAndroid Build Coastguard Worker           if (sbrTuningTable[i].bitrateTo <= bitrate) {
252*e5436536SAndroid Build Coastguard Worker             if (sbrTuningTable[i].bitrateTo > bitRateClosestUpper) {
253*e5436536SAndroid Build Coastguard Worker               bitRateClosestUpper = sbrTuningTable[i].bitrateTo - 1;
254*e5436536SAndroid Build Coastguard Worker               bitRateClosestUpperIndex = i;
255*e5436536SAndroid Build Coastguard Worker             }
256*e5436536SAndroid Build Coastguard Worker           }
257*e5436536SAndroid Build Coastguard Worker         }
258*e5436536SAndroid Build Coastguard Worker       }
259*e5436536SAndroid Build Coastguard Worker     }
260*e5436536SAndroid Build Coastguard Worker   }
261*e5436536SAndroid Build Coastguard Worker 
262*e5436536SAndroid Build Coastguard Worker   if (bitRateClosestUpperIndex >= 0) {
263*e5436536SAndroid Build Coastguard Worker     return bitRateClosestUpperIndex;
264*e5436536SAndroid Build Coastguard Worker   }
265*e5436536SAndroid Build Coastguard Worker 
266*e5436536SAndroid Build Coastguard Worker   if (pBitRateClosest != NULL) {
267*e5436536SAndroid Build Coastguard Worker     /* If there was at least one matching tuning entry pick the least distance
268*e5436536SAndroid Build Coastguard Worker      * bit rate */
269*e5436536SAndroid Build Coastguard Worker     if (found) {
270*e5436536SAndroid Build Coastguard Worker       int distanceUpper = DISTANCE_CEIL_VALUE,
271*e5436536SAndroid Build Coastguard Worker           distanceLower = DISTANCE_CEIL_VALUE;
272*e5436536SAndroid Build Coastguard Worker       if (bitRateClosestLowerIndex >= 0) {
273*e5436536SAndroid Build Coastguard Worker         distanceLower =
274*e5436536SAndroid Build Coastguard Worker             sbrTuningTable[bitRateClosestLowerIndex].bitrateFrom - bitrate;
275*e5436536SAndroid Build Coastguard Worker       }
276*e5436536SAndroid Build Coastguard Worker       if (bitRateClosestUpperIndex >= 0) {
277*e5436536SAndroid Build Coastguard Worker         distanceUpper =
278*e5436536SAndroid Build Coastguard Worker             bitrate - sbrTuningTable[bitRateClosestUpperIndex].bitrateTo;
279*e5436536SAndroid Build Coastguard Worker       }
280*e5436536SAndroid Build Coastguard Worker       if (distanceUpper < distanceLower) {
281*e5436536SAndroid Build Coastguard Worker         *pBitRateClosest = bitRateClosestUpper;
282*e5436536SAndroid Build Coastguard Worker       } else {
283*e5436536SAndroid Build Coastguard Worker         *pBitRateClosest = bitRateClosestLower;
284*e5436536SAndroid Build Coastguard Worker       }
285*e5436536SAndroid Build Coastguard Worker     } else {
286*e5436536SAndroid Build Coastguard Worker       *pBitRateClosest = 0;
287*e5436536SAndroid Build Coastguard Worker     }
288*e5436536SAndroid Build Coastguard Worker   }
289*e5436536SAndroid Build Coastguard Worker 
290*e5436536SAndroid Build Coastguard Worker   return INVALID_TABLE_IDX;
291*e5436536SAndroid Build Coastguard Worker }
292*e5436536SAndroid Build Coastguard Worker 
293*e5436536SAndroid Build Coastguard Worker /***************************************************************************/
294*e5436536SAndroid Build Coastguard Worker /*!
295*e5436536SAndroid Build Coastguard Worker 
296*e5436536SAndroid Build Coastguard Worker   \brief  Selects the PS tuning settings to use dependent on bitrate
297*e5436536SAndroid Build Coastguard Worker   and core coder
298*e5436536SAndroid Build Coastguard Worker 
299*e5436536SAndroid Build Coastguard Worker   \return Index to the appropriate table
300*e5436536SAndroid Build Coastguard Worker 
301*e5436536SAndroid Build Coastguard Worker ****************************************************************************/
getPsTuningTableIndex(UINT bitrate,UINT * pBitRateClosest)302*e5436536SAndroid Build Coastguard Worker static INT getPsTuningTableIndex(UINT bitrate, UINT *pBitRateClosest) {
303*e5436536SAndroid Build Coastguard Worker   INT i, paramSets = sizeof(psTuningTable) / sizeof(psTuningTable[0]);
304*e5436536SAndroid Build Coastguard Worker   int bitRateClosestLowerIndex = -1, bitRateClosestUpperIndex = -1;
305*e5436536SAndroid Build Coastguard Worker   UINT bitRateClosestUpper = 0, bitRateClosestLower = DISTANCE_CEIL_VALUE;
306*e5436536SAndroid Build Coastguard Worker 
307*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < paramSets; i++) {
308*e5436536SAndroid Build Coastguard Worker     if ((bitrate >= psTuningTable[i].bitrateFrom) &&
309*e5436536SAndroid Build Coastguard Worker         (bitrate < psTuningTable[i].bitrateTo)) {
310*e5436536SAndroid Build Coastguard Worker       return i;
311*e5436536SAndroid Build Coastguard Worker     } else {
312*e5436536SAndroid Build Coastguard Worker       if (psTuningTable[i].bitrateFrom > bitrate) {
313*e5436536SAndroid Build Coastguard Worker         if (psTuningTable[i].bitrateFrom < bitRateClosestLower) {
314*e5436536SAndroid Build Coastguard Worker           bitRateClosestLower = psTuningTable[i].bitrateFrom;
315*e5436536SAndroid Build Coastguard Worker           bitRateClosestLowerIndex = i;
316*e5436536SAndroid Build Coastguard Worker         }
317*e5436536SAndroid Build Coastguard Worker       }
318*e5436536SAndroid Build Coastguard Worker       if (psTuningTable[i].bitrateTo <= bitrate) {
319*e5436536SAndroid Build Coastguard Worker         if (psTuningTable[i].bitrateTo > bitRateClosestUpper) {
320*e5436536SAndroid Build Coastguard Worker           bitRateClosestUpper = psTuningTable[i].bitrateTo - 1;
321*e5436536SAndroid Build Coastguard Worker           bitRateClosestUpperIndex = i;
322*e5436536SAndroid Build Coastguard Worker         }
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   if (bitRateClosestUpperIndex >= 0) {
328*e5436536SAndroid Build Coastguard Worker     return bitRateClosestUpperIndex;
329*e5436536SAndroid Build Coastguard Worker   }
330*e5436536SAndroid Build Coastguard Worker 
331*e5436536SAndroid Build Coastguard Worker   if (pBitRateClosest != NULL) {
332*e5436536SAndroid Build Coastguard Worker     int distanceUpper = DISTANCE_CEIL_VALUE,
333*e5436536SAndroid Build Coastguard Worker         distanceLower = DISTANCE_CEIL_VALUE;
334*e5436536SAndroid Build Coastguard Worker     if (bitRateClosestLowerIndex >= 0) {
335*e5436536SAndroid Build Coastguard Worker       distanceLower =
336*e5436536SAndroid Build Coastguard Worker           sbrTuningTable[bitRateClosestLowerIndex].bitrateFrom - bitrate;
337*e5436536SAndroid Build Coastguard Worker     }
338*e5436536SAndroid Build Coastguard Worker     if (bitRateClosestUpperIndex >= 0) {
339*e5436536SAndroid Build Coastguard Worker       distanceUpper =
340*e5436536SAndroid Build Coastguard Worker           bitrate - sbrTuningTable[bitRateClosestUpperIndex].bitrateTo;
341*e5436536SAndroid Build Coastguard Worker     }
342*e5436536SAndroid Build Coastguard Worker     if (distanceUpper < distanceLower) {
343*e5436536SAndroid Build Coastguard Worker       *pBitRateClosest = bitRateClosestUpper;
344*e5436536SAndroid Build Coastguard Worker     } else {
345*e5436536SAndroid Build Coastguard Worker       *pBitRateClosest = bitRateClosestLower;
346*e5436536SAndroid Build Coastguard Worker     }
347*e5436536SAndroid Build Coastguard Worker   }
348*e5436536SAndroid Build Coastguard Worker 
349*e5436536SAndroid Build Coastguard Worker   return INVALID_TABLE_IDX;
350*e5436536SAndroid Build Coastguard Worker }
351*e5436536SAndroid Build Coastguard Worker 
352*e5436536SAndroid Build Coastguard Worker /***************************************************************************/
353*e5436536SAndroid Build Coastguard Worker /*!
354*e5436536SAndroid Build Coastguard Worker 
355*e5436536SAndroid Build Coastguard Worker   \brief  In case of downsampled SBR we may need to lower the stop freq
356*e5436536SAndroid Build Coastguard Worker           of a tuning setting to fit into the lower half of the
357*e5436536SAndroid Build Coastguard Worker           spectrum ( which is sampleRate/4 )
358*e5436536SAndroid Build Coastguard Worker 
359*e5436536SAndroid Build Coastguard Worker   \return the adapted stop frequency index (-1 -> error)
360*e5436536SAndroid Build Coastguard Worker 
361*e5436536SAndroid Build Coastguard Worker   \ingroup SbrEncCfg
362*e5436536SAndroid Build Coastguard Worker 
363*e5436536SAndroid Build Coastguard Worker ****************************************************************************/
FDKsbrEnc_GetDownsampledStopFreq(const INT sampleRateCore,const INT startFreq,INT stopFreq,const INT downSampleFactor)364*e5436536SAndroid Build Coastguard Worker static INT FDKsbrEnc_GetDownsampledStopFreq(const INT sampleRateCore,
365*e5436536SAndroid Build Coastguard Worker                                             const INT startFreq, INT stopFreq,
366*e5436536SAndroid Build Coastguard Worker                                             const INT downSampleFactor) {
367*e5436536SAndroid Build Coastguard Worker   INT maxStopFreqRaw = sampleRateCore / 2;
368*e5436536SAndroid Build Coastguard Worker   INT startBand, stopBand;
369*e5436536SAndroid Build Coastguard Worker   HANDLE_ERROR_INFO err;
370*e5436536SAndroid Build Coastguard Worker 
371*e5436536SAndroid Build Coastguard Worker   while (stopFreq > 0 && FDKsbrEnc_getSbrStopFreqRAW(stopFreq, sampleRateCore) >
372*e5436536SAndroid Build Coastguard Worker                              maxStopFreqRaw) {
373*e5436536SAndroid Build Coastguard Worker     stopFreq--;
374*e5436536SAndroid Build Coastguard Worker   }
375*e5436536SAndroid Build Coastguard Worker 
376*e5436536SAndroid Build Coastguard Worker   if (FDKsbrEnc_getSbrStopFreqRAW(stopFreq, sampleRateCore) > maxStopFreqRaw)
377*e5436536SAndroid Build Coastguard Worker     return -1;
378*e5436536SAndroid Build Coastguard Worker 
379*e5436536SAndroid Build Coastguard Worker   err = FDKsbrEnc_FindStartAndStopBand(
380*e5436536SAndroid Build Coastguard Worker       sampleRateCore << (downSampleFactor - 1), sampleRateCore,
381*e5436536SAndroid Build Coastguard Worker       32 << (downSampleFactor - 1), startFreq, stopFreq, &startBand, &stopBand);
382*e5436536SAndroid Build Coastguard Worker   if (err) return -1;
383*e5436536SAndroid Build Coastguard Worker 
384*e5436536SAndroid Build Coastguard Worker   return stopFreq;
385*e5436536SAndroid Build Coastguard Worker }
386*e5436536SAndroid Build Coastguard Worker 
387*e5436536SAndroid Build Coastguard Worker /***************************************************************************/
388*e5436536SAndroid Build Coastguard Worker /*!
389*e5436536SAndroid Build Coastguard Worker 
390*e5436536SAndroid Build Coastguard Worker   \brief  tells us, if for the given coreCoder, bitrate, number of channels
391*e5436536SAndroid Build Coastguard Worker           and input sampling rate an SBR setting is available. If yes, it
392*e5436536SAndroid Build Coastguard Worker           tells us also the core sampling rate we would need to run with
393*e5436536SAndroid Build Coastguard Worker 
394*e5436536SAndroid Build Coastguard Worker   \return a flag indicating success: yes (1) or no (0)
395*e5436536SAndroid Build Coastguard Worker 
396*e5436536SAndroid Build Coastguard Worker ****************************************************************************/
FDKsbrEnc_IsSbrSettingAvail(UINT bitrate,UINT vbrMode,UINT numOutputChannels,UINT sampleRateInput,UINT sampleRateCore,AUDIO_OBJECT_TYPE core)397*e5436536SAndroid Build Coastguard Worker static UINT FDKsbrEnc_IsSbrSettingAvail(
398*e5436536SAndroid Build Coastguard Worker     UINT bitrate,           /*! the total bitrate in bits/sec */
399*e5436536SAndroid Build Coastguard Worker     UINT vbrMode,           /*! the vbr paramter, 0 means constant bitrate */
400*e5436536SAndroid Build Coastguard Worker     UINT numOutputChannels, /*! the number of channels for the core coder */
401*e5436536SAndroid Build Coastguard Worker     UINT sampleRateInput,   /*! the input sample rate [in Hz] */
402*e5436536SAndroid Build Coastguard Worker     UINT sampleRateCore,    /*! the core's sampling rate */
403*e5436536SAndroid Build Coastguard Worker     AUDIO_OBJECT_TYPE core) {
404*e5436536SAndroid Build Coastguard Worker   INT idx = INVALID_TABLE_IDX;
405*e5436536SAndroid Build Coastguard Worker 
406*e5436536SAndroid Build Coastguard Worker   if (sampleRateInput < 16000) return 0;
407*e5436536SAndroid Build Coastguard Worker 
408*e5436536SAndroid Build Coastguard Worker   if (bitrate == 0) {
409*e5436536SAndroid Build Coastguard Worker     /* map vbr quality to bitrate */
410*e5436536SAndroid Build Coastguard Worker     if (vbrMode < 30)
411*e5436536SAndroid Build Coastguard Worker       bitrate = 24000;
412*e5436536SAndroid Build Coastguard Worker     else if (vbrMode < 40)
413*e5436536SAndroid Build Coastguard Worker       bitrate = 28000;
414*e5436536SAndroid Build Coastguard Worker     else if (vbrMode < 60)
415*e5436536SAndroid Build Coastguard Worker       bitrate = 32000;
416*e5436536SAndroid Build Coastguard Worker     else if (vbrMode < 75)
417*e5436536SAndroid Build Coastguard Worker       bitrate = 40000;
418*e5436536SAndroid Build Coastguard Worker     else
419*e5436536SAndroid Build Coastguard Worker       bitrate = 48000;
420*e5436536SAndroid Build Coastguard Worker     bitrate *= numOutputChannels;
421*e5436536SAndroid Build Coastguard Worker   }
422*e5436536SAndroid Build Coastguard Worker 
423*e5436536SAndroid Build Coastguard Worker   idx = getSbrTuningTableIndex(bitrate, numOutputChannels, sampleRateCore, core,
424*e5436536SAndroid Build Coastguard Worker                                NULL);
425*e5436536SAndroid Build Coastguard Worker 
426*e5436536SAndroid Build Coastguard Worker   return (idx == INVALID_TABLE_IDX ? 0 : 1);
427*e5436536SAndroid Build Coastguard Worker }
428*e5436536SAndroid Build Coastguard Worker 
429*e5436536SAndroid Build Coastguard Worker /***************************************************************************/
430*e5436536SAndroid Build Coastguard Worker /*!
431*e5436536SAndroid Build Coastguard Worker 
432*e5436536SAndroid Build Coastguard Worker   \brief  Adjusts the SBR settings according to the chosen core coder
433*e5436536SAndroid Build Coastguard Worker           settings which are accessible via config->codecSettings
434*e5436536SAndroid Build Coastguard Worker 
435*e5436536SAndroid Build Coastguard Worker   \return A flag indicating success: yes (1) or no (0)
436*e5436536SAndroid Build Coastguard Worker 
437*e5436536SAndroid Build Coastguard Worker ****************************************************************************/
FDKsbrEnc_AdjustSbrSettings(const sbrConfigurationPtr config,UINT bitRate,UINT numChannels,UINT sampleRateCore,UINT sampleRateSbr,UINT transFac,UINT standardBitrate,UINT vbrMode,UINT useSpeechConfig,UINT lcsMode,UINT bParametricStereo,AUDIO_OBJECT_TYPE core)438*e5436536SAndroid Build Coastguard Worker static UINT FDKsbrEnc_AdjustSbrSettings(
439*e5436536SAndroid Build Coastguard Worker     const sbrConfigurationPtr config, /*! output, modified */
440*e5436536SAndroid Build Coastguard Worker     UINT bitRate,                     /*! the total bitrate in bits/sec */
441*e5436536SAndroid Build Coastguard Worker     UINT numChannels,                 /*! the core coder number of channels */
442*e5436536SAndroid Build Coastguard Worker     UINT sampleRateCore,              /*! the core coder sampling rate in Hz */
443*e5436536SAndroid Build Coastguard Worker     UINT sampleRateSbr,               /*! the sbr coder sampling rate in Hz */
444*e5436536SAndroid Build Coastguard Worker     UINT transFac,                    /*! the short block to long block ratio */
445*e5436536SAndroid Build Coastguard Worker     UINT standardBitrate, /*! the standard bitrate per channel in bits/sec */
446*e5436536SAndroid Build Coastguard Worker     UINT vbrMode, /*! the vbr paramter, 0 poor quality .. 100 high quality*/
447*e5436536SAndroid Build Coastguard Worker     UINT useSpeechConfig,   /*!< adapt tuning parameters for speech ? */
448*e5436536SAndroid Build Coastguard Worker     UINT lcsMode,           /*! the low complexity stereo mode */
449*e5436536SAndroid Build Coastguard Worker     UINT bParametricStereo, /*!< use parametric stereo */
450*e5436536SAndroid Build Coastguard Worker     AUDIO_OBJECT_TYPE core) /* Core audio codec object type */
451*e5436536SAndroid Build Coastguard Worker {
452*e5436536SAndroid Build Coastguard Worker   INT idx = INVALID_TABLE_IDX;
453*e5436536SAndroid Build Coastguard Worker   /* set the core codec settings */
454*e5436536SAndroid Build Coastguard Worker   config->codecSettings.bitRate = bitRate;
455*e5436536SAndroid Build Coastguard Worker   config->codecSettings.nChannels = numChannels;
456*e5436536SAndroid Build Coastguard Worker   config->codecSettings.sampleFreq = sampleRateCore;
457*e5436536SAndroid Build Coastguard Worker   config->codecSettings.transFac = transFac;
458*e5436536SAndroid Build Coastguard Worker   config->codecSettings.standardBitrate = standardBitrate;
459*e5436536SAndroid Build Coastguard Worker 
460*e5436536SAndroid Build Coastguard Worker   if (bitRate < 28000) {
461*e5436536SAndroid Build Coastguard Worker     config->threshold_AmpRes_FF_m = (FIXP_DBL)MAXVAL_DBL;
462*e5436536SAndroid Build Coastguard Worker     config->threshold_AmpRes_FF_e = 7;
463*e5436536SAndroid Build Coastguard Worker   } else if (bitRate >= 28000 && bitRate <= 48000) {
464*e5436536SAndroid Build Coastguard Worker     /* The float threshold is 75
465*e5436536SAndroid Build Coastguard Worker        0.524288f is fractional part of RELAXATION, the quotaMatrix and therefore
466*e5436536SAndroid Build Coastguard Worker        tonality are scaled by this 2/3 is because the original implementation
467*e5436536SAndroid Build Coastguard Worker        divides the tonality values by 3, here it's divided by 2 128 compensates
468*e5436536SAndroid Build Coastguard Worker        the necessary shiftfactor of 7 */
469*e5436536SAndroid Build Coastguard Worker     config->threshold_AmpRes_FF_m =
470*e5436536SAndroid Build Coastguard Worker         FL2FXCONST_DBL(75.0f * 0.524288f / (2.0f / 3.0f) / 128.0f);
471*e5436536SAndroid Build Coastguard Worker     config->threshold_AmpRes_FF_e = 7;
472*e5436536SAndroid Build Coastguard Worker   } else if (bitRate > 48000) {
473*e5436536SAndroid Build Coastguard Worker     config->threshold_AmpRes_FF_m = FL2FXCONST_DBL(0);
474*e5436536SAndroid Build Coastguard Worker     config->threshold_AmpRes_FF_e = 0;
475*e5436536SAndroid Build Coastguard Worker   }
476*e5436536SAndroid Build Coastguard Worker 
477*e5436536SAndroid Build Coastguard Worker   if (bitRate == 0) {
478*e5436536SAndroid Build Coastguard Worker     /* map vbr quality to bitrate */
479*e5436536SAndroid Build Coastguard Worker     if (vbrMode < 30)
480*e5436536SAndroid Build Coastguard Worker       bitRate = 24000;
481*e5436536SAndroid Build Coastguard Worker     else if (vbrMode < 40)
482*e5436536SAndroid Build Coastguard Worker       bitRate = 28000;
483*e5436536SAndroid Build Coastguard Worker     else if (vbrMode < 60)
484*e5436536SAndroid Build Coastguard Worker       bitRate = 32000;
485*e5436536SAndroid Build Coastguard Worker     else if (vbrMode < 75)
486*e5436536SAndroid Build Coastguard Worker       bitRate = 40000;
487*e5436536SAndroid Build Coastguard Worker     else
488*e5436536SAndroid Build Coastguard Worker       bitRate = 48000;
489*e5436536SAndroid Build Coastguard Worker     bitRate *= numChannels;
490*e5436536SAndroid Build Coastguard Worker     /* fix to enable mono vbrMode<40 @ 44.1 of 48kHz */
491*e5436536SAndroid Build Coastguard Worker     if (numChannels == 1) {
492*e5436536SAndroid Build Coastguard Worker       if (sampleRateSbr == 44100 || sampleRateSbr == 48000) {
493*e5436536SAndroid Build Coastguard Worker         if (vbrMode < 40) bitRate = 32000;
494*e5436536SAndroid Build Coastguard Worker       }
495*e5436536SAndroid Build Coastguard Worker     }
496*e5436536SAndroid Build Coastguard Worker   }
497*e5436536SAndroid Build Coastguard Worker 
498*e5436536SAndroid Build Coastguard Worker   idx =
499*e5436536SAndroid Build Coastguard Worker       getSbrTuningTableIndex(bitRate, numChannels, sampleRateCore, core, NULL);
500*e5436536SAndroid Build Coastguard Worker 
501*e5436536SAndroid Build Coastguard Worker   if (idx != INVALID_TABLE_IDX) {
502*e5436536SAndroid Build Coastguard Worker     config->startFreq = sbrTuningTable[idx].startFreq;
503*e5436536SAndroid Build Coastguard Worker     config->stopFreq = sbrTuningTable[idx].stopFreq;
504*e5436536SAndroid Build Coastguard Worker     if (useSpeechConfig) {
505*e5436536SAndroid Build Coastguard Worker       config->startFreq = sbrTuningTable[idx].startFreqSpeech;
506*e5436536SAndroid Build Coastguard Worker       config->stopFreq = sbrTuningTable[idx].stopFreqSpeech;
507*e5436536SAndroid Build Coastguard Worker     }
508*e5436536SAndroid Build Coastguard Worker 
509*e5436536SAndroid Build Coastguard Worker     /* Adapt stop frequency in case of downsampled SBR - only 32 bands then */
510*e5436536SAndroid Build Coastguard Worker     if (1 == config->downSampleFactor) {
511*e5436536SAndroid Build Coastguard Worker       INT dsStopFreq = FDKsbrEnc_GetDownsampledStopFreq(
512*e5436536SAndroid Build Coastguard Worker           sampleRateCore, config->startFreq, config->stopFreq,
513*e5436536SAndroid Build Coastguard Worker           config->downSampleFactor);
514*e5436536SAndroid Build Coastguard Worker       if (dsStopFreq < 0) {
515*e5436536SAndroid Build Coastguard Worker         return 0;
516*e5436536SAndroid Build Coastguard Worker       }
517*e5436536SAndroid Build Coastguard Worker 
518*e5436536SAndroid Build Coastguard Worker       config->stopFreq = dsStopFreq;
519*e5436536SAndroid Build Coastguard Worker     }
520*e5436536SAndroid Build Coastguard Worker 
521*e5436536SAndroid Build Coastguard Worker     config->sbr_noise_bands = sbrTuningTable[idx].numNoiseBands;
522*e5436536SAndroid Build Coastguard Worker     if (core == AOT_ER_AAC_ELD) config->init_amp_res_FF = SBR_AMP_RES_1_5;
523*e5436536SAndroid Build Coastguard Worker     config->noiseFloorOffset = sbrTuningTable[idx].noiseFloorOffset;
524*e5436536SAndroid Build Coastguard Worker 
525*e5436536SAndroid Build Coastguard Worker     config->ana_max_level = sbrTuningTable[idx].noiseMaxLevel;
526*e5436536SAndroid Build Coastguard Worker     config->stereoMode = sbrTuningTable[idx].stereoMode;
527*e5436536SAndroid Build Coastguard Worker     config->freqScale = sbrTuningTable[idx].freqScale;
528*e5436536SAndroid Build Coastguard Worker 
529*e5436536SAndroid Build Coastguard Worker     if (numChannels == 1) {
530*e5436536SAndroid Build Coastguard Worker       /* stereo case */
531*e5436536SAndroid Build Coastguard Worker       switch (core) {
532*e5436536SAndroid Build Coastguard Worker         case AOT_AAC_LC:
533*e5436536SAndroid Build Coastguard Worker           if (bitRate <= (useSpeechConfig ? 24000U : 20000U)) {
534*e5436536SAndroid Build Coastguard Worker             config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency
535*e5436536SAndroid Build Coastguard Worker                                                           resolution for
536*e5436536SAndroid Build Coastguard Worker                                                           non-split frames */
537*e5436536SAndroid Build Coastguard Worker             config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency
538*e5436536SAndroid Build Coastguard Worker                                                           resolution for split
539*e5436536SAndroid Build Coastguard Worker                                                           frames */
540*e5436536SAndroid Build Coastguard Worker           }
541*e5436536SAndroid Build Coastguard Worker           break;
542*e5436536SAndroid Build Coastguard Worker         case AOT_ER_AAC_ELD:
543*e5436536SAndroid Build Coastguard Worker           if (bitRate < 36000)
544*e5436536SAndroid Build Coastguard Worker             config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency
545*e5436536SAndroid Build Coastguard Worker                                                           resolution for split
546*e5436536SAndroid Build Coastguard Worker                                                           frames */
547*e5436536SAndroid Build Coastguard Worker           if (bitRate < 26000) {
548*e5436536SAndroid Build Coastguard Worker             config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency
549*e5436536SAndroid Build Coastguard Worker                                                           resolution for
550*e5436536SAndroid Build Coastguard Worker                                                           non-split frames */
551*e5436536SAndroid Build Coastguard Worker             config->fResTransIsLow =
552*e5436536SAndroid Build Coastguard Worker                 1; /* for transient frames, set low frequency resolution */
553*e5436536SAndroid Build Coastguard Worker           }
554*e5436536SAndroid Build Coastguard Worker           break;
555*e5436536SAndroid Build Coastguard Worker         default:
556*e5436536SAndroid Build Coastguard Worker           break;
557*e5436536SAndroid Build Coastguard Worker       }
558*e5436536SAndroid Build Coastguard Worker     } else {
559*e5436536SAndroid Build Coastguard Worker       /* stereo case */
560*e5436536SAndroid Build Coastguard Worker       switch (core) {
561*e5436536SAndroid Build Coastguard Worker         case AOT_AAC_LC:
562*e5436536SAndroid Build Coastguard Worker           if (bitRate <= 28000) {
563*e5436536SAndroid Build Coastguard Worker             config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency
564*e5436536SAndroid Build Coastguard Worker                                                           resolution for
565*e5436536SAndroid Build Coastguard Worker                                                           non-split frames */
566*e5436536SAndroid Build Coastguard Worker             config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency
567*e5436536SAndroid Build Coastguard Worker                                                           resolution for split
568*e5436536SAndroid Build Coastguard Worker                                                           frames */
569*e5436536SAndroid Build Coastguard Worker           }
570*e5436536SAndroid Build Coastguard Worker           break;
571*e5436536SAndroid Build Coastguard Worker         case AOT_ER_AAC_ELD:
572*e5436536SAndroid Build Coastguard Worker           if (bitRate < 72000) {
573*e5436536SAndroid Build Coastguard Worker             config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency
574*e5436536SAndroid Build Coastguard Worker                                                           resolution for split
575*e5436536SAndroid Build Coastguard Worker                                                           frames */
576*e5436536SAndroid Build Coastguard Worker           }
577*e5436536SAndroid Build Coastguard Worker           if (bitRate < 52000) {
578*e5436536SAndroid Build Coastguard Worker             config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency
579*e5436536SAndroid Build Coastguard Worker                                                           resolution for
580*e5436536SAndroid Build Coastguard Worker                                                           non-split frames */
581*e5436536SAndroid Build Coastguard Worker             config->fResTransIsLow =
582*e5436536SAndroid Build Coastguard Worker                 1; /* for transient frames, set low frequency resolution */
583*e5436536SAndroid Build Coastguard Worker           }
584*e5436536SAndroid Build Coastguard Worker           break;
585*e5436536SAndroid Build Coastguard Worker         default:
586*e5436536SAndroid Build Coastguard Worker           break;
587*e5436536SAndroid Build Coastguard Worker       }
588*e5436536SAndroid Build Coastguard Worker       if (bitRate <= 28000) {
589*e5436536SAndroid Build Coastguard Worker         /*
590*e5436536SAndroid Build Coastguard Worker           additionally restrict frequency resolution in FIXFIX frames
591*e5436536SAndroid Build Coastguard Worker           to further reduce SBR payload size */
592*e5436536SAndroid Build Coastguard Worker         config->freq_res_fixfix[0] = FREQ_RES_LOW;
593*e5436536SAndroid Build Coastguard Worker         config->freq_res_fixfix[1] = FREQ_RES_LOW;
594*e5436536SAndroid Build Coastguard Worker       }
595*e5436536SAndroid Build Coastguard Worker     }
596*e5436536SAndroid Build Coastguard Worker 
597*e5436536SAndroid Build Coastguard Worker     /* adjust usage of parametric coding dependent on bitrate and speech config
598*e5436536SAndroid Build Coastguard Worker      * flag */
599*e5436536SAndroid Build Coastguard Worker     if (useSpeechConfig) config->parametricCoding = 0;
600*e5436536SAndroid Build Coastguard Worker 
601*e5436536SAndroid Build Coastguard Worker     if (core == AOT_ER_AAC_ELD) {
602*e5436536SAndroid Build Coastguard Worker       if (bitRate < 28000) config->init_amp_res_FF = SBR_AMP_RES_3_0;
603*e5436536SAndroid Build Coastguard Worker       config->SendHeaderDataTime = -1;
604*e5436536SAndroid Build Coastguard Worker     }
605*e5436536SAndroid Build Coastguard Worker 
606*e5436536SAndroid Build Coastguard Worker     if (numChannels == 1) {
607*e5436536SAndroid Build Coastguard Worker       if (bitRate < 16000) {
608*e5436536SAndroid Build Coastguard Worker         config->parametricCoding = 0;
609*e5436536SAndroid Build Coastguard Worker       }
610*e5436536SAndroid Build Coastguard Worker     } else {
611*e5436536SAndroid Build Coastguard Worker       if (bitRate < 20000) {
612*e5436536SAndroid Build Coastguard Worker         config->parametricCoding = 0;
613*e5436536SAndroid Build Coastguard Worker       }
614*e5436536SAndroid Build Coastguard Worker     }
615*e5436536SAndroid Build Coastguard Worker 
616*e5436536SAndroid Build Coastguard Worker     config->useSpeechConfig = useSpeechConfig;
617*e5436536SAndroid Build Coastguard Worker 
618*e5436536SAndroid Build Coastguard Worker     /* PS settings */
619*e5436536SAndroid Build Coastguard Worker     config->bParametricStereo = bParametricStereo;
620*e5436536SAndroid Build Coastguard Worker 
621*e5436536SAndroid Build Coastguard Worker     return 1;
622*e5436536SAndroid Build Coastguard Worker   } else {
623*e5436536SAndroid Build Coastguard Worker     return 0;
624*e5436536SAndroid Build Coastguard Worker   }
625*e5436536SAndroid Build Coastguard Worker }
626*e5436536SAndroid Build Coastguard Worker 
627*e5436536SAndroid Build Coastguard Worker /*****************************************************************************
628*e5436536SAndroid Build Coastguard Worker 
629*e5436536SAndroid Build Coastguard Worker  functionname: FDKsbrEnc_InitializeSbrDefaults
630*e5436536SAndroid Build Coastguard Worker  description:  initializes the SBR configuration
631*e5436536SAndroid Build Coastguard Worker  returns:      error status
632*e5436536SAndroid Build Coastguard Worker  input:        - core codec type,
633*e5436536SAndroid Build Coastguard Worker                - factor of SBR to core frame length,
634*e5436536SAndroid Build Coastguard Worker                - core frame length
635*e5436536SAndroid Build Coastguard Worker  output:       initialized SBR configuration
636*e5436536SAndroid Build Coastguard Worker 
637*e5436536SAndroid Build Coastguard Worker *****************************************************************************/
FDKsbrEnc_InitializeSbrDefaults(sbrConfigurationPtr config,INT downSampleFactor,UINT codecGranuleLen,const INT isLowDelay)638*e5436536SAndroid Build Coastguard Worker static UINT FDKsbrEnc_InitializeSbrDefaults(sbrConfigurationPtr config,
639*e5436536SAndroid Build Coastguard Worker                                             INT downSampleFactor,
640*e5436536SAndroid Build Coastguard Worker                                             UINT codecGranuleLen,
641*e5436536SAndroid Build Coastguard Worker                                             const INT isLowDelay) {
642*e5436536SAndroid Build Coastguard Worker   if ((downSampleFactor < 1 || downSampleFactor > 2) ||
643*e5436536SAndroid Build Coastguard Worker       (codecGranuleLen * downSampleFactor > 64 * 32))
644*e5436536SAndroid Build Coastguard Worker     return (0); /* error */
645*e5436536SAndroid Build Coastguard Worker 
646*e5436536SAndroid Build Coastguard Worker   config->SendHeaderDataTime = 1000;
647*e5436536SAndroid Build Coastguard Worker   config->useWaveCoding = 0;
648*e5436536SAndroid Build Coastguard Worker   config->crcSbr = 0;
649*e5436536SAndroid Build Coastguard Worker   config->dynBwSupported = 1;
650*e5436536SAndroid Build Coastguard Worker   if (isLowDelay)
651*e5436536SAndroid Build Coastguard Worker     config->tran_thr = 6000;
652*e5436536SAndroid Build Coastguard Worker   else
653*e5436536SAndroid Build Coastguard Worker     config->tran_thr = 13000;
654*e5436536SAndroid Build Coastguard Worker 
655*e5436536SAndroid Build Coastguard Worker   config->parametricCoding = 1;
656*e5436536SAndroid Build Coastguard Worker 
657*e5436536SAndroid Build Coastguard Worker   config->sbrFrameSize = codecGranuleLen * downSampleFactor;
658*e5436536SAndroid Build Coastguard Worker   config->downSampleFactor = downSampleFactor;
659*e5436536SAndroid Build Coastguard Worker 
660*e5436536SAndroid Build Coastguard Worker   /* sbr default parameters */
661*e5436536SAndroid Build Coastguard Worker   config->sbr_data_extra = 0;
662*e5436536SAndroid Build Coastguard Worker   config->amp_res = SBR_AMP_RES_3_0;
663*e5436536SAndroid Build Coastguard Worker   config->tran_fc = 0;
664*e5436536SAndroid Build Coastguard Worker   config->tran_det_mode = 1;
665*e5436536SAndroid Build Coastguard Worker   config->spread = 1;
666*e5436536SAndroid Build Coastguard Worker   config->stat = 0;
667*e5436536SAndroid Build Coastguard Worker   config->e = 1;
668*e5436536SAndroid Build Coastguard Worker   config->deltaTAcrossFrames = 1;
669*e5436536SAndroid Build Coastguard Worker   config->dF_edge_1stEnv = FL2FXCONST_DBL(0.3f);
670*e5436536SAndroid Build Coastguard Worker   config->dF_edge_incr = FL2FXCONST_DBL(0.3f);
671*e5436536SAndroid Build Coastguard Worker 
672*e5436536SAndroid Build Coastguard Worker   config->sbr_invf_mode = INVF_SWITCHED;
673*e5436536SAndroid Build Coastguard Worker   config->sbr_xpos_mode = XPOS_LC;
674*e5436536SAndroid Build Coastguard Worker   config->sbr_xpos_ctrl = SBR_XPOS_CTRL_DEFAULT;
675*e5436536SAndroid Build Coastguard Worker   config->sbr_xpos_level = 0;
676*e5436536SAndroid Build Coastguard Worker   config->useSaPan = 0;
677*e5436536SAndroid Build Coastguard Worker   config->dynBwEnabled = 0;
678*e5436536SAndroid Build Coastguard Worker 
679*e5436536SAndroid Build Coastguard Worker   /* the following parameters are overwritten by the
680*e5436536SAndroid Build Coastguard Worker      FDKsbrEnc_AdjustSbrSettings() function since they are included in the
681*e5436536SAndroid Build Coastguard Worker      tuning table */
682*e5436536SAndroid Build Coastguard Worker   config->stereoMode = SBR_SWITCH_LRC;
683*e5436536SAndroid Build Coastguard Worker   config->ana_max_level = 6;
684*e5436536SAndroid Build Coastguard Worker   config->noiseFloorOffset = 0;
685*e5436536SAndroid Build Coastguard Worker   config->startFreq = 5; /*  5.9 respectively  6.0 kHz at fs = 44.1/48 kHz */
686*e5436536SAndroid Build Coastguard Worker   config->stopFreq = 9;  /* 16.2 respectively 16.8 kHz at fs = 44.1/48 kHz */
687*e5436536SAndroid Build Coastguard Worker   config->freq_res_fixfix[0] = FREQ_RES_HIGH; /* non-split case */
688*e5436536SAndroid Build Coastguard Worker   config->freq_res_fixfix[1] = FREQ_RES_HIGH; /* split case */
689*e5436536SAndroid Build Coastguard Worker   config->fResTransIsLow = 0; /* for transient frames, set variable frequency
690*e5436536SAndroid Build Coastguard Worker                                  resolution according to freqResTable */
691*e5436536SAndroid Build Coastguard Worker 
692*e5436536SAndroid Build Coastguard Worker   /* header_extra_1 */
693*e5436536SAndroid Build Coastguard Worker   config->freqScale = SBR_FREQ_SCALE_DEFAULT;
694*e5436536SAndroid Build Coastguard Worker   config->alterScale = SBR_ALTER_SCALE_DEFAULT;
695*e5436536SAndroid Build Coastguard Worker   config->sbr_noise_bands = SBR_NOISE_BANDS_DEFAULT;
696*e5436536SAndroid Build Coastguard Worker 
697*e5436536SAndroid Build Coastguard Worker   /* header_extra_2 */
698*e5436536SAndroid Build Coastguard Worker   config->sbr_limiter_bands = SBR_LIMITER_BANDS_DEFAULT;
699*e5436536SAndroid Build Coastguard Worker   config->sbr_limiter_gains = SBR_LIMITER_GAINS_DEFAULT;
700*e5436536SAndroid Build Coastguard Worker   config->sbr_interpol_freq = SBR_INTERPOL_FREQ_DEFAULT;
701*e5436536SAndroid Build Coastguard Worker   config->sbr_smoothing_length = SBR_SMOOTHING_LENGTH_DEFAULT;
702*e5436536SAndroid Build Coastguard Worker 
703*e5436536SAndroid Build Coastguard Worker   return 1;
704*e5436536SAndroid Build Coastguard Worker }
705*e5436536SAndroid Build Coastguard Worker 
706*e5436536SAndroid Build Coastguard Worker /*****************************************************************************
707*e5436536SAndroid Build Coastguard Worker 
708*e5436536SAndroid Build Coastguard Worker  functionname: DeleteEnvChannel
709*e5436536SAndroid Build Coastguard Worker  description:  frees memory of one SBR channel
710*e5436536SAndroid Build Coastguard Worker  returns:      -
711*e5436536SAndroid Build Coastguard Worker  input:        handle of channel
712*e5436536SAndroid Build Coastguard Worker  output:       released handle
713*e5436536SAndroid Build Coastguard Worker 
714*e5436536SAndroid Build Coastguard Worker *****************************************************************************/
deleteEnvChannel(HANDLE_ENV_CHANNEL hEnvCut)715*e5436536SAndroid Build Coastguard Worker static void deleteEnvChannel(HANDLE_ENV_CHANNEL hEnvCut) {
716*e5436536SAndroid Build Coastguard Worker   if (hEnvCut) {
717*e5436536SAndroid Build Coastguard Worker     FDKsbrEnc_DeleteTonCorrParamExtr(&hEnvCut->TonCorr);
718*e5436536SAndroid Build Coastguard Worker 
719*e5436536SAndroid Build Coastguard Worker     FDKsbrEnc_deleteExtractSbrEnvelope(&hEnvCut->sbrExtractEnvelope);
720*e5436536SAndroid Build Coastguard Worker   }
721*e5436536SAndroid Build Coastguard Worker }
722*e5436536SAndroid Build Coastguard Worker 
723*e5436536SAndroid Build Coastguard Worker /*****************************************************************************
724*e5436536SAndroid Build Coastguard Worker 
725*e5436536SAndroid Build Coastguard Worker  functionname: sbrEncoder_ChannelClose
726*e5436536SAndroid Build Coastguard Worker  description:  close the channel coding handle
727*e5436536SAndroid Build Coastguard Worker  returns:
728*e5436536SAndroid Build Coastguard Worker  input:        phSbrChannel
729*e5436536SAndroid Build Coastguard Worker  output:
730*e5436536SAndroid Build Coastguard Worker 
731*e5436536SAndroid Build Coastguard Worker *****************************************************************************/
sbrEncoder_ChannelClose(HANDLE_SBR_CHANNEL hSbrChannel)732*e5436536SAndroid Build Coastguard Worker static void sbrEncoder_ChannelClose(HANDLE_SBR_CHANNEL hSbrChannel) {
733*e5436536SAndroid Build Coastguard Worker   if (hSbrChannel != NULL) {
734*e5436536SAndroid Build Coastguard Worker     deleteEnvChannel(&hSbrChannel->hEnvChannel);
735*e5436536SAndroid Build Coastguard Worker   }
736*e5436536SAndroid Build Coastguard Worker }
737*e5436536SAndroid Build Coastguard Worker 
738*e5436536SAndroid Build Coastguard Worker /*****************************************************************************
739*e5436536SAndroid Build Coastguard Worker 
740*e5436536SAndroid Build Coastguard Worker  functionname: sbrEncoder_ElementClose
741*e5436536SAndroid Build Coastguard Worker  description:  close the channel coding handle
742*e5436536SAndroid Build Coastguard Worker  returns:
743*e5436536SAndroid Build Coastguard Worker  input:        phSbrChannel
744*e5436536SAndroid Build Coastguard Worker  output:
745*e5436536SAndroid Build Coastguard Worker 
746*e5436536SAndroid Build Coastguard Worker *****************************************************************************/
sbrEncoder_ElementClose(HANDLE_SBR_ELEMENT * phSbrElement)747*e5436536SAndroid Build Coastguard Worker static void sbrEncoder_ElementClose(HANDLE_SBR_ELEMENT *phSbrElement) {
748*e5436536SAndroid Build Coastguard Worker   HANDLE_SBR_ELEMENT hSbrElement = *phSbrElement;
749*e5436536SAndroid Build Coastguard Worker 
750*e5436536SAndroid Build Coastguard Worker   if (hSbrElement != NULL) {
751*e5436536SAndroid Build Coastguard Worker     if (hSbrElement->sbrConfigData.v_k_master)
752*e5436536SAndroid Build Coastguard Worker       FreeRam_Sbr_v_k_master(&hSbrElement->sbrConfigData.v_k_master);
753*e5436536SAndroid Build Coastguard Worker     if (hSbrElement->sbrConfigData.freqBandTable[LO])
754*e5436536SAndroid Build Coastguard Worker       FreeRam_Sbr_freqBandTableLO(
755*e5436536SAndroid Build Coastguard Worker           &hSbrElement->sbrConfigData.freqBandTable[LO]);
756*e5436536SAndroid Build Coastguard Worker     if (hSbrElement->sbrConfigData.freqBandTable[HI])
757*e5436536SAndroid Build Coastguard Worker       FreeRam_Sbr_freqBandTableHI(
758*e5436536SAndroid Build Coastguard Worker           &hSbrElement->sbrConfigData.freqBandTable[HI]);
759*e5436536SAndroid Build Coastguard Worker 
760*e5436536SAndroid Build Coastguard Worker     FreeRam_SbrElement(phSbrElement);
761*e5436536SAndroid Build Coastguard Worker   }
762*e5436536SAndroid Build Coastguard Worker   return;
763*e5436536SAndroid Build Coastguard Worker }
764*e5436536SAndroid Build Coastguard Worker 
sbrEncoder_Close(HANDLE_SBR_ENCODER * phSbrEncoder)765*e5436536SAndroid Build Coastguard Worker void sbrEncoder_Close(HANDLE_SBR_ENCODER *phSbrEncoder) {
766*e5436536SAndroid Build Coastguard Worker   HANDLE_SBR_ENCODER hSbrEncoder = *phSbrEncoder;
767*e5436536SAndroid Build Coastguard Worker 
768*e5436536SAndroid Build Coastguard Worker   if (hSbrEncoder != NULL) {
769*e5436536SAndroid Build Coastguard Worker     int el, ch;
770*e5436536SAndroid Build Coastguard Worker 
771*e5436536SAndroid Build Coastguard Worker     for (el = 0; el < (8); el++) {
772*e5436536SAndroid Build Coastguard Worker       if (hSbrEncoder->sbrElement[el] != NULL) {
773*e5436536SAndroid Build Coastguard Worker         sbrEncoder_ElementClose(&hSbrEncoder->sbrElement[el]);
774*e5436536SAndroid Build Coastguard Worker       }
775*e5436536SAndroid Build Coastguard Worker     }
776*e5436536SAndroid Build Coastguard Worker 
777*e5436536SAndroid Build Coastguard Worker     /* Close sbr Channels */
778*e5436536SAndroid Build Coastguard Worker     for (ch = 0; ch < (8); ch++) {
779*e5436536SAndroid Build Coastguard Worker       if (hSbrEncoder->pSbrChannel[ch]) {
780*e5436536SAndroid Build Coastguard Worker         sbrEncoder_ChannelClose(hSbrEncoder->pSbrChannel[ch]);
781*e5436536SAndroid Build Coastguard Worker         FreeRam_SbrChannel(&hSbrEncoder->pSbrChannel[ch]);
782*e5436536SAndroid Build Coastguard Worker       }
783*e5436536SAndroid Build Coastguard Worker 
784*e5436536SAndroid Build Coastguard Worker       if (hSbrEncoder->QmfAnalysis[ch].FilterStates)
785*e5436536SAndroid Build Coastguard Worker         FreeRam_Sbr_QmfStatesAnalysis(
786*e5436536SAndroid Build Coastguard Worker             (FIXP_QAS **)&hSbrEncoder->QmfAnalysis[ch].FilterStates);
787*e5436536SAndroid Build Coastguard Worker     }
788*e5436536SAndroid Build Coastguard Worker 
789*e5436536SAndroid Build Coastguard Worker     if (hSbrEncoder->hParametricStereo)
790*e5436536SAndroid Build Coastguard Worker       PSEnc_Destroy(&hSbrEncoder->hParametricStereo);
791*e5436536SAndroid Build Coastguard Worker     if (hSbrEncoder->qmfSynthesisPS.FilterStates)
792*e5436536SAndroid Build Coastguard Worker       FreeRam_PsQmfStatesSynthesis(
793*e5436536SAndroid Build Coastguard Worker           (FIXP_DBL **)&hSbrEncoder->qmfSynthesisPS.FilterStates);
794*e5436536SAndroid Build Coastguard Worker 
795*e5436536SAndroid Build Coastguard Worker     /* Release Overlay */
796*e5436536SAndroid Build Coastguard Worker     if (hSbrEncoder->pSBRdynamic_RAM)
797*e5436536SAndroid Build Coastguard Worker       FreeRam_SbrDynamic_RAM((FIXP_DBL **)&hSbrEncoder->pSBRdynamic_RAM);
798*e5436536SAndroid Build Coastguard Worker 
799*e5436536SAndroid Build Coastguard Worker     FreeRam_SbrEncoder(phSbrEncoder);
800*e5436536SAndroid Build Coastguard Worker   }
801*e5436536SAndroid Build Coastguard Worker }
802*e5436536SAndroid Build Coastguard Worker 
803*e5436536SAndroid Build Coastguard Worker /*****************************************************************************
804*e5436536SAndroid Build Coastguard Worker 
805*e5436536SAndroid Build Coastguard Worker  functionname: updateFreqBandTable
806*e5436536SAndroid Build Coastguard Worker  description:  updates vk_master
807*e5436536SAndroid Build Coastguard Worker  returns:      -
808*e5436536SAndroid Build Coastguard Worker  input:        config handle
809*e5436536SAndroid Build Coastguard Worker  output:       error info
810*e5436536SAndroid Build Coastguard Worker 
811*e5436536SAndroid Build Coastguard Worker *****************************************************************************/
updateFreqBandTable(HANDLE_SBR_CONFIG_DATA sbrConfigData,HANDLE_SBR_HEADER_DATA sbrHeaderData,const INT downSampleFactor)812*e5436536SAndroid Build Coastguard Worker static INT updateFreqBandTable(HANDLE_SBR_CONFIG_DATA sbrConfigData,
813*e5436536SAndroid Build Coastguard Worker                                HANDLE_SBR_HEADER_DATA sbrHeaderData,
814*e5436536SAndroid Build Coastguard Worker                                const INT downSampleFactor) {
815*e5436536SAndroid Build Coastguard Worker   INT k0, k2;
816*e5436536SAndroid Build Coastguard Worker 
817*e5436536SAndroid Build Coastguard Worker   if (FDKsbrEnc_FindStartAndStopBand(
818*e5436536SAndroid Build Coastguard Worker           sbrConfigData->sampleFreq,
819*e5436536SAndroid Build Coastguard Worker           sbrConfigData->sampleFreq >> (downSampleFactor - 1),
820*e5436536SAndroid Build Coastguard Worker           sbrConfigData->noQmfBands, sbrHeaderData->sbr_start_frequency,
821*e5436536SAndroid Build Coastguard Worker           sbrHeaderData->sbr_stop_frequency, &k0, &k2))
822*e5436536SAndroid Build Coastguard Worker     return (1);
823*e5436536SAndroid Build Coastguard Worker 
824*e5436536SAndroid Build Coastguard Worker   if (FDKsbrEnc_UpdateFreqScale(
825*e5436536SAndroid Build Coastguard Worker           sbrConfigData->v_k_master, &sbrConfigData->num_Master, k0, k2,
826*e5436536SAndroid Build Coastguard Worker           sbrHeaderData->freqScale, sbrHeaderData->alterScale))
827*e5436536SAndroid Build Coastguard Worker     return (1);
828*e5436536SAndroid Build Coastguard Worker 
829*e5436536SAndroid Build Coastguard Worker   sbrHeaderData->sbr_xover_band = 0;
830*e5436536SAndroid Build Coastguard Worker 
831*e5436536SAndroid Build Coastguard Worker   if (FDKsbrEnc_UpdateHiRes(sbrConfigData->freqBandTable[HI],
832*e5436536SAndroid Build Coastguard Worker                             &sbrConfigData->nSfb[HI], sbrConfigData->v_k_master,
833*e5436536SAndroid Build Coastguard Worker                             sbrConfigData->num_Master,
834*e5436536SAndroid Build Coastguard Worker                             &sbrHeaderData->sbr_xover_band))
835*e5436536SAndroid Build Coastguard Worker     return (1);
836*e5436536SAndroid Build Coastguard Worker 
837*e5436536SAndroid Build Coastguard Worker   FDKsbrEnc_UpdateLoRes(
838*e5436536SAndroid Build Coastguard Worker       sbrConfigData->freqBandTable[LO], &sbrConfigData->nSfb[LO],
839*e5436536SAndroid Build Coastguard Worker       sbrConfigData->freqBandTable[HI], sbrConfigData->nSfb[HI]);
840*e5436536SAndroid Build Coastguard Worker 
841*e5436536SAndroid Build Coastguard Worker   sbrConfigData->xOverFreq =
842*e5436536SAndroid Build Coastguard Worker       (sbrConfigData->freqBandTable[LOW_RES][0] * sbrConfigData->sampleFreq /
843*e5436536SAndroid Build Coastguard Worker            sbrConfigData->noQmfBands +
844*e5436536SAndroid Build Coastguard Worker        1) >>
845*e5436536SAndroid Build Coastguard Worker       1;
846*e5436536SAndroid Build Coastguard Worker 
847*e5436536SAndroid Build Coastguard Worker   return (0);
848*e5436536SAndroid Build Coastguard Worker }
849*e5436536SAndroid Build Coastguard Worker 
850*e5436536SAndroid Build Coastguard Worker /*****************************************************************************
851*e5436536SAndroid Build Coastguard Worker 
852*e5436536SAndroid Build Coastguard Worker  functionname: resetEnvChannel
853*e5436536SAndroid Build Coastguard Worker  description:  resets parameters and allocates memory
854*e5436536SAndroid Build Coastguard Worker  returns:      error status
855*e5436536SAndroid Build Coastguard Worker  input:
856*e5436536SAndroid Build Coastguard Worker  output:       hEnv
857*e5436536SAndroid Build Coastguard Worker 
858*e5436536SAndroid Build Coastguard Worker *****************************************************************************/
resetEnvChannel(HANDLE_SBR_CONFIG_DATA sbrConfigData,HANDLE_SBR_HEADER_DATA sbrHeaderData,HANDLE_ENV_CHANNEL hEnv)859*e5436536SAndroid Build Coastguard Worker static INT resetEnvChannel(HANDLE_SBR_CONFIG_DATA sbrConfigData,
860*e5436536SAndroid Build Coastguard Worker                            HANDLE_SBR_HEADER_DATA sbrHeaderData,
861*e5436536SAndroid Build Coastguard Worker                            HANDLE_ENV_CHANNEL hEnv) {
862*e5436536SAndroid Build Coastguard Worker   /* note !!! hEnv->encEnvData.noOfnoisebands will be updated later in function
863*e5436536SAndroid Build Coastguard Worker    * FDKsbrEnc_extractSbrEnvelope !!!*/
864*e5436536SAndroid Build Coastguard Worker   hEnv->TonCorr.sbrNoiseFloorEstimate.noiseBands =
865*e5436536SAndroid Build Coastguard Worker       sbrHeaderData->sbr_noise_bands;
866*e5436536SAndroid Build Coastguard Worker 
867*e5436536SAndroid Build Coastguard Worker   if (FDKsbrEnc_ResetTonCorrParamExtr(
868*e5436536SAndroid Build Coastguard Worker           &hEnv->TonCorr, sbrConfigData->xposCtrlSwitch,
869*e5436536SAndroid Build Coastguard Worker           sbrConfigData->freqBandTable[HI][0], sbrConfigData->v_k_master,
870*e5436536SAndroid Build Coastguard Worker           sbrConfigData->num_Master, sbrConfigData->sampleFreq,
871*e5436536SAndroid Build Coastguard Worker           sbrConfigData->freqBandTable, sbrConfigData->nSfb,
872*e5436536SAndroid Build Coastguard Worker           sbrConfigData->noQmfBands))
873*e5436536SAndroid Build Coastguard Worker     return (1);
874*e5436536SAndroid Build Coastguard Worker 
875*e5436536SAndroid Build Coastguard Worker   hEnv->sbrCodeNoiseFloor.nSfb[LO] =
876*e5436536SAndroid Build Coastguard Worker       hEnv->TonCorr.sbrNoiseFloorEstimate.noNoiseBands;
877*e5436536SAndroid Build Coastguard Worker   hEnv->sbrCodeNoiseFloor.nSfb[HI] =
878*e5436536SAndroid Build Coastguard Worker       hEnv->TonCorr.sbrNoiseFloorEstimate.noNoiseBands;
879*e5436536SAndroid Build Coastguard Worker 
880*e5436536SAndroid Build Coastguard Worker   hEnv->sbrCodeEnvelope.nSfb[LO] = sbrConfigData->nSfb[LO];
881*e5436536SAndroid Build Coastguard Worker   hEnv->sbrCodeEnvelope.nSfb[HI] = sbrConfigData->nSfb[HI];
882*e5436536SAndroid Build Coastguard Worker 
883*e5436536SAndroid Build Coastguard Worker   hEnv->encEnvData.noHarmonics = sbrConfigData->nSfb[HI];
884*e5436536SAndroid Build Coastguard Worker 
885*e5436536SAndroid Build Coastguard Worker   hEnv->sbrCodeEnvelope.upDate = 0;
886*e5436536SAndroid Build Coastguard Worker   hEnv->sbrCodeNoiseFloor.upDate = 0;
887*e5436536SAndroid Build Coastguard Worker 
888*e5436536SAndroid Build Coastguard Worker   return (0);
889*e5436536SAndroid Build Coastguard Worker }
890*e5436536SAndroid Build Coastguard Worker 
891*e5436536SAndroid Build Coastguard Worker /* ****************************** FDKsbrEnc_SbrGetXOverFreq
892*e5436536SAndroid Build Coastguard Worker  * ******************************/
893*e5436536SAndroid Build Coastguard Worker /**
894*e5436536SAndroid Build Coastguard Worker  * @fn
895*e5436536SAndroid Build Coastguard Worker  * @brief       calculates the closest possible crossover frequency
896*e5436536SAndroid Build Coastguard Worker  * @return      the crossover frequency SBR accepts
897*e5436536SAndroid Build Coastguard Worker  *
898*e5436536SAndroid Build Coastguard Worker  */
FDKsbrEnc_SbrGetXOverFreq(HANDLE_SBR_ELEMENT hEnv,INT xoverFreq)899*e5436536SAndroid Build Coastguard Worker static INT FDKsbrEnc_SbrGetXOverFreq(
900*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_ELEMENT hEnv, /*!< handle to SBR encoder instance */
901*e5436536SAndroid Build Coastguard Worker     INT xoverFreq) /*!< from core coder suggested crossover frequency */
902*e5436536SAndroid Build Coastguard Worker {
903*e5436536SAndroid Build Coastguard Worker   INT band;
904*e5436536SAndroid Build Coastguard Worker   INT lastDiff, newDiff;
905*e5436536SAndroid Build Coastguard Worker   INT cutoffSb;
906*e5436536SAndroid Build Coastguard Worker 
907*e5436536SAndroid Build Coastguard Worker   UCHAR *RESTRICT pVKMaster = hEnv->sbrConfigData.v_k_master;
908*e5436536SAndroid Build Coastguard Worker 
909*e5436536SAndroid Build Coastguard Worker   /* Check if there is a matching cutoff frequency in the master table */
910*e5436536SAndroid Build Coastguard Worker   cutoffSb = (4 * xoverFreq * hEnv->sbrConfigData.noQmfBands /
911*e5436536SAndroid Build Coastguard Worker                   hEnv->sbrConfigData.sampleFreq +
912*e5436536SAndroid Build Coastguard Worker               1) >>
913*e5436536SAndroid Build Coastguard Worker              1;
914*e5436536SAndroid Build Coastguard Worker   lastDiff = cutoffSb;
915*e5436536SAndroid Build Coastguard Worker   for (band = 0; band < hEnv->sbrConfigData.num_Master; band++) {
916*e5436536SAndroid Build Coastguard Worker     newDiff = fixp_abs((INT)pVKMaster[band] - cutoffSb);
917*e5436536SAndroid Build Coastguard Worker 
918*e5436536SAndroid Build Coastguard Worker     if (newDiff >= lastDiff) {
919*e5436536SAndroid Build Coastguard Worker       band--;
920*e5436536SAndroid Build Coastguard Worker       break;
921*e5436536SAndroid Build Coastguard Worker     }
922*e5436536SAndroid Build Coastguard Worker 
923*e5436536SAndroid Build Coastguard Worker     lastDiff = newDiff;
924*e5436536SAndroid Build Coastguard Worker   }
925*e5436536SAndroid Build Coastguard Worker 
926*e5436536SAndroid Build Coastguard Worker   return ((pVKMaster[band] * hEnv->sbrConfigData.sampleFreq /
927*e5436536SAndroid Build Coastguard Worker                hEnv->sbrConfigData.noQmfBands +
928*e5436536SAndroid Build Coastguard Worker            1) >>
929*e5436536SAndroid Build Coastguard Worker           1);
930*e5436536SAndroid Build Coastguard Worker }
931*e5436536SAndroid Build Coastguard Worker 
932*e5436536SAndroid Build Coastguard Worker /*****************************************************************************
933*e5436536SAndroid Build Coastguard Worker 
934*e5436536SAndroid Build Coastguard Worker  functionname: FDKsbrEnc_EnvEncodeFrame
935*e5436536SAndroid Build Coastguard Worker  description: performs the sbr envelope calculation for one element
936*e5436536SAndroid Build Coastguard Worker  returns:
937*e5436536SAndroid Build Coastguard Worker  input:
938*e5436536SAndroid Build Coastguard Worker  output:
939*e5436536SAndroid Build Coastguard Worker 
940*e5436536SAndroid Build Coastguard Worker *****************************************************************************/
FDKsbrEnc_EnvEncodeFrame(HANDLE_SBR_ENCODER hEnvEncoder,int iElement,INT_PCM * samples,UINT samplesBufSize,UINT * sbrDataBits,UCHAR * sbrData,int clearOutput)941*e5436536SAndroid Build Coastguard Worker INT FDKsbrEnc_EnvEncodeFrame(
942*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_ENCODER hEnvEncoder, int iElement,
943*e5436536SAndroid Build Coastguard Worker     INT_PCM *samples,    /*!< time samples, always deinterleaved */
944*e5436536SAndroid Build Coastguard Worker     UINT samplesBufSize, /*!< time buffer channel stride */
945*e5436536SAndroid Build Coastguard Worker     UINT *sbrDataBits,   /*!< Size of SBR payload  */
946*e5436536SAndroid Build Coastguard Worker     UCHAR *sbrData,      /*!< SBR payload  */
947*e5436536SAndroid Build Coastguard Worker     int clearOutput      /*!< Do not consider any input signal */
948*e5436536SAndroid Build Coastguard Worker ) {
949*e5436536SAndroid Build Coastguard Worker   HANDLE_SBR_ELEMENT hSbrElement = NULL;
950*e5436536SAndroid Build Coastguard Worker   FDK_CRCINFO crcInfo;
951*e5436536SAndroid Build Coastguard Worker   INT crcReg;
952*e5436536SAndroid Build Coastguard Worker   INT ch;
953*e5436536SAndroid Build Coastguard Worker   INT band;
954*e5436536SAndroid Build Coastguard Worker   INT cutoffSb;
955*e5436536SAndroid Build Coastguard Worker   INT newXOver;
956*e5436536SAndroid Build Coastguard Worker 
957*e5436536SAndroid Build Coastguard Worker   if (hEnvEncoder == NULL) return -1;
958*e5436536SAndroid Build Coastguard Worker 
959*e5436536SAndroid Build Coastguard Worker   hSbrElement = hEnvEncoder->sbrElement[iElement];
960*e5436536SAndroid Build Coastguard Worker 
961*e5436536SAndroid Build Coastguard Worker   if (hSbrElement == NULL) return -1;
962*e5436536SAndroid Build Coastguard Worker 
963*e5436536SAndroid Build Coastguard Worker   /* header bitstream handling */
964*e5436536SAndroid Build Coastguard Worker   HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData = &hSbrElement->sbrBitstreamData;
965*e5436536SAndroid Build Coastguard Worker 
966*e5436536SAndroid Build Coastguard Worker   INT psHeaderActive = 0;
967*e5436536SAndroid Build Coastguard Worker   sbrBitstreamData->HeaderActive = 0;
968*e5436536SAndroid Build Coastguard Worker 
969*e5436536SAndroid Build Coastguard Worker   /* Anticipate PS header because of internal PS bitstream delay in order to be
970*e5436536SAndroid Build Coastguard Worker    * in sync with SBR header. */
971*e5436536SAndroid Build Coastguard Worker   if (sbrBitstreamData->CountSendHeaderData ==
972*e5436536SAndroid Build Coastguard Worker       (sbrBitstreamData->NrSendHeaderData - 1)) {
973*e5436536SAndroid Build Coastguard Worker     psHeaderActive = 1;
974*e5436536SAndroid Build Coastguard Worker   }
975*e5436536SAndroid Build Coastguard Worker 
976*e5436536SAndroid Build Coastguard Worker   /* Signal SBR header to be written into bitstream */
977*e5436536SAndroid Build Coastguard Worker   if (sbrBitstreamData->CountSendHeaderData == 0) {
978*e5436536SAndroid Build Coastguard Worker     sbrBitstreamData->HeaderActive = 1;
979*e5436536SAndroid Build Coastguard Worker   }
980*e5436536SAndroid Build Coastguard Worker 
981*e5436536SAndroid Build Coastguard Worker   /* Increment header interval counter */
982*e5436536SAndroid Build Coastguard Worker   if (sbrBitstreamData->NrSendHeaderData == 0) {
983*e5436536SAndroid Build Coastguard Worker     sbrBitstreamData->CountSendHeaderData = 1;
984*e5436536SAndroid Build Coastguard Worker   } else {
985*e5436536SAndroid Build Coastguard Worker     if (sbrBitstreamData->CountSendHeaderData >= 0) {
986*e5436536SAndroid Build Coastguard Worker       sbrBitstreamData->CountSendHeaderData++;
987*e5436536SAndroid Build Coastguard Worker       sbrBitstreamData->CountSendHeaderData %=
988*e5436536SAndroid Build Coastguard Worker           sbrBitstreamData->NrSendHeaderData;
989*e5436536SAndroid Build Coastguard Worker     }
990*e5436536SAndroid Build Coastguard Worker   }
991*e5436536SAndroid Build Coastguard Worker 
992*e5436536SAndroid Build Coastguard Worker   if (hSbrElement->CmonData.dynBwEnabled) {
993*e5436536SAndroid Build Coastguard Worker     INT i;
994*e5436536SAndroid Build Coastguard Worker     for (i = 4; i > 0; i--)
995*e5436536SAndroid Build Coastguard Worker       hSbrElement->dynXOverFreqDelay[i] = hSbrElement->dynXOverFreqDelay[i - 1];
996*e5436536SAndroid Build Coastguard Worker 
997*e5436536SAndroid Build Coastguard Worker     hSbrElement->dynXOverFreqDelay[0] = hSbrElement->CmonData.dynXOverFreqEnc;
998*e5436536SAndroid Build Coastguard Worker     if (hSbrElement->dynXOverFreqDelay[1] > hSbrElement->dynXOverFreqDelay[2])
999*e5436536SAndroid Build Coastguard Worker       newXOver = hSbrElement->dynXOverFreqDelay[2];
1000*e5436536SAndroid Build Coastguard Worker     else
1001*e5436536SAndroid Build Coastguard Worker       newXOver = hSbrElement->dynXOverFreqDelay[1];
1002*e5436536SAndroid Build Coastguard Worker 
1003*e5436536SAndroid Build Coastguard Worker     /* has the crossover frequency changed? */
1004*e5436536SAndroid Build Coastguard Worker     if (hSbrElement->sbrConfigData.dynXOverFreq != newXOver) {
1005*e5436536SAndroid Build Coastguard Worker       /* get corresponding master band */
1006*e5436536SAndroid Build Coastguard Worker       cutoffSb = ((4 * newXOver * hSbrElement->sbrConfigData.noQmfBands /
1007*e5436536SAndroid Build Coastguard Worker                    hSbrElement->sbrConfigData.sampleFreq) +
1008*e5436536SAndroid Build Coastguard Worker                   1) >>
1009*e5436536SAndroid Build Coastguard Worker                  1;
1010*e5436536SAndroid Build Coastguard Worker 
1011*e5436536SAndroid Build Coastguard Worker       for (band = 0; band < hSbrElement->sbrConfigData.num_Master; band++) {
1012*e5436536SAndroid Build Coastguard Worker         if (cutoffSb == hSbrElement->sbrConfigData.v_k_master[band]) break;
1013*e5436536SAndroid Build Coastguard Worker       }
1014*e5436536SAndroid Build Coastguard Worker       FDK_ASSERT(band < hSbrElement->sbrConfigData.num_Master);
1015*e5436536SAndroid Build Coastguard Worker 
1016*e5436536SAndroid Build Coastguard Worker       hSbrElement->sbrConfigData.dynXOverFreq = newXOver;
1017*e5436536SAndroid Build Coastguard Worker       hSbrElement->sbrHeaderData.sbr_xover_band = band;
1018*e5436536SAndroid Build Coastguard Worker       hSbrElement->sbrBitstreamData.HeaderActive = 1;
1019*e5436536SAndroid Build Coastguard Worker       psHeaderActive = 1; /* ps header is one frame delayed */
1020*e5436536SAndroid Build Coastguard Worker 
1021*e5436536SAndroid Build Coastguard Worker       /*
1022*e5436536SAndroid Build Coastguard Worker         update vk_master table
1023*e5436536SAndroid Build Coastguard Worker       */
1024*e5436536SAndroid Build Coastguard Worker       if (updateFreqBandTable(&hSbrElement->sbrConfigData,
1025*e5436536SAndroid Build Coastguard Worker                               &hSbrElement->sbrHeaderData,
1026*e5436536SAndroid Build Coastguard Worker                               hEnvEncoder->downSampleFactor))
1027*e5436536SAndroid Build Coastguard Worker         return (1);
1028*e5436536SAndroid Build Coastguard Worker 
1029*e5436536SAndroid Build Coastguard Worker       /* reset SBR channels */
1030*e5436536SAndroid Build Coastguard Worker       INT nEnvCh = hSbrElement->sbrConfigData.nChannels;
1031*e5436536SAndroid Build Coastguard Worker       for (ch = 0; ch < nEnvCh; ch++) {
1032*e5436536SAndroid Build Coastguard Worker         if (resetEnvChannel(&hSbrElement->sbrConfigData,
1033*e5436536SAndroid Build Coastguard Worker                             &hSbrElement->sbrHeaderData,
1034*e5436536SAndroid Build Coastguard Worker                             &hSbrElement->sbrChannel[ch]->hEnvChannel))
1035*e5436536SAndroid Build Coastguard Worker           return (1);
1036*e5436536SAndroid Build Coastguard Worker       }
1037*e5436536SAndroid Build Coastguard Worker     }
1038*e5436536SAndroid Build Coastguard Worker   }
1039*e5436536SAndroid Build Coastguard Worker 
1040*e5436536SAndroid Build Coastguard Worker   /*
1041*e5436536SAndroid Build Coastguard Worker     allocate space for dummy header and crc
1042*e5436536SAndroid Build Coastguard Worker   */
1043*e5436536SAndroid Build Coastguard Worker   crcReg = FDKsbrEnc_InitSbrBitstream(
1044*e5436536SAndroid Build Coastguard Worker       &hSbrElement->CmonData,
1045*e5436536SAndroid Build Coastguard Worker       hSbrElement->payloadDelayLine[hEnvEncoder->nBitstrDelay],
1046*e5436536SAndroid Build Coastguard Worker       MAX_PAYLOAD_SIZE * sizeof(UCHAR), &crcInfo,
1047*e5436536SAndroid Build Coastguard Worker       hSbrElement->sbrConfigData.sbrSyntaxFlags);
1048*e5436536SAndroid Build Coastguard Worker 
1049*e5436536SAndroid Build Coastguard Worker   /* Temporal Envelope Data */
1050*e5436536SAndroid Build Coastguard Worker   SBR_FRAME_TEMP_DATA _fData;
1051*e5436536SAndroid Build Coastguard Worker   SBR_FRAME_TEMP_DATA *fData = &_fData;
1052*e5436536SAndroid Build Coastguard Worker   SBR_ENV_TEMP_DATA eData[MAX_NUM_CHANNELS];
1053*e5436536SAndroid Build Coastguard Worker 
1054*e5436536SAndroid Build Coastguard Worker   /* Init Temporal Envelope Data */
1055*e5436536SAndroid Build Coastguard Worker   {
1056*e5436536SAndroid Build Coastguard Worker     int i;
1057*e5436536SAndroid Build Coastguard Worker 
1058*e5436536SAndroid Build Coastguard Worker     FDKmemclear(&eData[0], sizeof(SBR_ENV_TEMP_DATA));
1059*e5436536SAndroid Build Coastguard Worker     FDKmemclear(&eData[1], sizeof(SBR_ENV_TEMP_DATA));
1060*e5436536SAndroid Build Coastguard Worker     FDKmemclear(fData, sizeof(SBR_FRAME_TEMP_DATA));
1061*e5436536SAndroid Build Coastguard Worker 
1062*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) fData->res[i] = FREQ_RES_HIGH;
1063*e5436536SAndroid Build Coastguard Worker   }
1064*e5436536SAndroid Build Coastguard Worker 
1065*e5436536SAndroid Build Coastguard Worker   if (!clearOutput) {
1066*e5436536SAndroid Build Coastguard Worker     /*
1067*e5436536SAndroid Build Coastguard Worker      * Transform audio data into QMF domain
1068*e5436536SAndroid Build Coastguard Worker      */
1069*e5436536SAndroid Build Coastguard Worker     for (ch = 0; ch < hSbrElement->sbrConfigData.nChannels; ch++) {
1070*e5436536SAndroid Build Coastguard Worker       HANDLE_ENV_CHANNEL h_envChan = &hSbrElement->sbrChannel[ch]->hEnvChannel;
1071*e5436536SAndroid Build Coastguard Worker       HANDLE_SBR_EXTRACT_ENVELOPE sbrExtrEnv = &h_envChan->sbrExtractEnvelope;
1072*e5436536SAndroid Build Coastguard Worker 
1073*e5436536SAndroid Build Coastguard Worker       if (hSbrElement->elInfo.fParametricStereo == 0) {
1074*e5436536SAndroid Build Coastguard Worker         QMF_SCALE_FACTOR tmpScale;
1075*e5436536SAndroid Build Coastguard Worker         FIXP_DBL **pQmfReal, **pQmfImag;
1076*e5436536SAndroid Build Coastguard Worker         C_AALLOC_SCRATCH_START(qmfWorkBuffer, FIXP_DBL, 64 * 2)
1077*e5436536SAndroid Build Coastguard Worker 
1078*e5436536SAndroid Build Coastguard Worker         /* Obtain pointers to QMF buffers. */
1079*e5436536SAndroid Build Coastguard Worker         pQmfReal = sbrExtrEnv->rBuffer;
1080*e5436536SAndroid Build Coastguard Worker         pQmfImag = sbrExtrEnv->iBuffer;
1081*e5436536SAndroid Build Coastguard Worker 
1082*e5436536SAndroid Build Coastguard Worker         qmfAnalysisFiltering(
1083*e5436536SAndroid Build Coastguard Worker             hSbrElement->hQmfAnalysis[ch], pQmfReal, pQmfImag, &tmpScale,
1084*e5436536SAndroid Build Coastguard Worker             samples + hSbrElement->elInfo.ChannelIndex[ch] * samplesBufSize, 0,
1085*e5436536SAndroid Build Coastguard Worker             1, qmfWorkBuffer);
1086*e5436536SAndroid Build Coastguard Worker 
1087*e5436536SAndroid Build Coastguard Worker         h_envChan->qmfScale = tmpScale.lb_scale + 7;
1088*e5436536SAndroid Build Coastguard Worker 
1089*e5436536SAndroid Build Coastguard Worker         C_AALLOC_SCRATCH_END(qmfWorkBuffer, FIXP_DBL, 64 * 2)
1090*e5436536SAndroid Build Coastguard Worker 
1091*e5436536SAndroid Build Coastguard Worker       } /* fParametricStereo == 0 */
1092*e5436536SAndroid Build Coastguard Worker 
1093*e5436536SAndroid Build Coastguard Worker       /*
1094*e5436536SAndroid Build Coastguard Worker         Parametric Stereo processing
1095*e5436536SAndroid Build Coastguard Worker       */
1096*e5436536SAndroid Build Coastguard Worker       if (hSbrElement->elInfo.fParametricStereo) {
1097*e5436536SAndroid Build Coastguard Worker         INT error = noError;
1098*e5436536SAndroid Build Coastguard Worker 
1099*e5436536SAndroid Build Coastguard Worker         /* Limit Parametric Stereo to one instance */
1100*e5436536SAndroid Build Coastguard Worker         FDK_ASSERT(ch == 0);
1101*e5436536SAndroid Build Coastguard Worker 
1102*e5436536SAndroid Build Coastguard Worker         if (error == noError) {
1103*e5436536SAndroid Build Coastguard Worker           /* parametric stereo processing:
1104*e5436536SAndroid Build Coastguard Worker              - input:
1105*e5436536SAndroid Build Coastguard Worker                o left and right time domain samples
1106*e5436536SAndroid Build Coastguard Worker              - processing:
1107*e5436536SAndroid Build Coastguard Worker                o stereo qmf analysis
1108*e5436536SAndroid Build Coastguard Worker                o stereo hybrid analysis
1109*e5436536SAndroid Build Coastguard Worker                o ps parameter extraction
1110*e5436536SAndroid Build Coastguard Worker                o downmix + hybrid synthesis
1111*e5436536SAndroid Build Coastguard Worker              - output:
1112*e5436536SAndroid Build Coastguard Worker                o downmixed qmf data is written to sbrExtrEnv->rBuffer and
1113*e5436536SAndroid Build Coastguard Worker              sbrExtrEnv->iBuffer
1114*e5436536SAndroid Build Coastguard Worker           */
1115*e5436536SAndroid Build Coastguard Worker           SCHAR qmfScale;
1116*e5436536SAndroid Build Coastguard Worker           INT_PCM *pSamples[2] = {
1117*e5436536SAndroid Build Coastguard Worker               samples + hSbrElement->elInfo.ChannelIndex[0] * samplesBufSize,
1118*e5436536SAndroid Build Coastguard Worker               samples + hSbrElement->elInfo.ChannelIndex[1] * samplesBufSize};
1119*e5436536SAndroid Build Coastguard Worker           error = FDKsbrEnc_PSEnc_ParametricStereoProcessing(
1120*e5436536SAndroid Build Coastguard Worker               hEnvEncoder->hParametricStereo, pSamples, samplesBufSize,
1121*e5436536SAndroid Build Coastguard Worker               hSbrElement->hQmfAnalysis, sbrExtrEnv->rBuffer,
1122*e5436536SAndroid Build Coastguard Worker               sbrExtrEnv->iBuffer,
1123*e5436536SAndroid Build Coastguard Worker               samples + hSbrElement->elInfo.ChannelIndex[ch] * samplesBufSize,
1124*e5436536SAndroid Build Coastguard Worker               &hEnvEncoder->qmfSynthesisPS, &qmfScale, psHeaderActive);
1125*e5436536SAndroid Build Coastguard Worker           h_envChan->qmfScale = (int)qmfScale;
1126*e5436536SAndroid Build Coastguard Worker         }
1127*e5436536SAndroid Build Coastguard Worker 
1128*e5436536SAndroid Build Coastguard Worker       } /* if (hEnvEncoder->hParametricStereo) */
1129*e5436536SAndroid Build Coastguard Worker 
1130*e5436536SAndroid Build Coastguard Worker       /*
1131*e5436536SAndroid Build Coastguard Worker 
1132*e5436536SAndroid Build Coastguard Worker          Extract Envelope relevant things from QMF data
1133*e5436536SAndroid Build Coastguard Worker 
1134*e5436536SAndroid Build Coastguard Worker       */
1135*e5436536SAndroid Build Coastguard Worker       FDKsbrEnc_extractSbrEnvelope1(&hSbrElement->sbrConfigData,
1136*e5436536SAndroid Build Coastguard Worker                                     &hSbrElement->sbrHeaderData,
1137*e5436536SAndroid Build Coastguard Worker                                     &hSbrElement->sbrBitstreamData, h_envChan,
1138*e5436536SAndroid Build Coastguard Worker                                     &hSbrElement->CmonData, &eData[ch], fData);
1139*e5436536SAndroid Build Coastguard Worker 
1140*e5436536SAndroid Build Coastguard Worker     } /* hEnvEncoder->sbrConfigData.nChannels */
1141*e5436536SAndroid Build Coastguard Worker   }
1142*e5436536SAndroid Build Coastguard Worker 
1143*e5436536SAndroid Build Coastguard Worker   /*
1144*e5436536SAndroid Build Coastguard Worker      Process Envelope relevant things and calculate envelope data and write
1145*e5436536SAndroid Build Coastguard Worker      payload
1146*e5436536SAndroid Build Coastguard Worker   */
1147*e5436536SAndroid Build Coastguard Worker   FDKsbrEnc_extractSbrEnvelope2(
1148*e5436536SAndroid Build Coastguard Worker       &hSbrElement->sbrConfigData, &hSbrElement->sbrHeaderData,
1149*e5436536SAndroid Build Coastguard Worker       (hSbrElement->elInfo.fParametricStereo) ? hEnvEncoder->hParametricStereo
1150*e5436536SAndroid Build Coastguard Worker                                               : NULL,
1151*e5436536SAndroid Build Coastguard Worker       &hSbrElement->sbrBitstreamData, &hSbrElement->sbrChannel[0]->hEnvChannel,
1152*e5436536SAndroid Build Coastguard Worker       (hSbrElement->sbrConfigData.stereoMode != SBR_MONO)
1153*e5436536SAndroid Build Coastguard Worker           ? &hSbrElement->sbrChannel[1]->hEnvChannel
1154*e5436536SAndroid Build Coastguard Worker           : NULL,
1155*e5436536SAndroid Build Coastguard Worker       &hSbrElement->CmonData, eData, fData, clearOutput);
1156*e5436536SAndroid Build Coastguard Worker 
1157*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrBitstreamData.rightBorderFIX = 0;
1158*e5436536SAndroid Build Coastguard Worker 
1159*e5436536SAndroid Build Coastguard Worker   /*
1160*e5436536SAndroid Build Coastguard Worker     format payload, calculate crc
1161*e5436536SAndroid Build Coastguard Worker   */
1162*e5436536SAndroid Build Coastguard Worker   FDKsbrEnc_AssembleSbrBitstream(&hSbrElement->CmonData, &crcInfo, crcReg,
1163*e5436536SAndroid Build Coastguard Worker                                  hSbrElement->sbrConfigData.sbrSyntaxFlags);
1164*e5436536SAndroid Build Coastguard Worker 
1165*e5436536SAndroid Build Coastguard Worker   /*
1166*e5436536SAndroid Build Coastguard Worker     save new payload, set to zero length if greater than MAX_PAYLOAD_SIZE
1167*e5436536SAndroid Build Coastguard Worker   */
1168*e5436536SAndroid Build Coastguard Worker   hSbrElement->payloadDelayLineSize[hEnvEncoder->nBitstrDelay] =
1169*e5436536SAndroid Build Coastguard Worker       FDKgetValidBits(&hSbrElement->CmonData.sbrBitbuf);
1170*e5436536SAndroid Build Coastguard Worker 
1171*e5436536SAndroid Build Coastguard Worker   if (hSbrElement->payloadDelayLineSize[hEnvEncoder->nBitstrDelay] >
1172*e5436536SAndroid Build Coastguard Worker       (MAX_PAYLOAD_SIZE << 3))
1173*e5436536SAndroid Build Coastguard Worker     hSbrElement->payloadDelayLineSize[hEnvEncoder->nBitstrDelay] = 0;
1174*e5436536SAndroid Build Coastguard Worker 
1175*e5436536SAndroid Build Coastguard Worker   /* While filling the Delay lines, sbrData is NULL */
1176*e5436536SAndroid Build Coastguard Worker   if (sbrData) {
1177*e5436536SAndroid Build Coastguard Worker     *sbrDataBits = hSbrElement->payloadDelayLineSize[0];
1178*e5436536SAndroid Build Coastguard Worker     FDKmemcpy(sbrData, hSbrElement->payloadDelayLine[0],
1179*e5436536SAndroid Build Coastguard Worker               (hSbrElement->payloadDelayLineSize[0] + 7) >> 3);
1180*e5436536SAndroid Build Coastguard Worker   }
1181*e5436536SAndroid Build Coastguard Worker 
1182*e5436536SAndroid Build Coastguard Worker   /* delay header active flag */
1183*e5436536SAndroid Build Coastguard Worker   if (hSbrElement->sbrBitstreamData.HeaderActive == 1) {
1184*e5436536SAndroid Build Coastguard Worker     hSbrElement->sbrBitstreamData.HeaderActiveDelay =
1185*e5436536SAndroid Build Coastguard Worker         1 + hEnvEncoder->nBitstrDelay;
1186*e5436536SAndroid Build Coastguard Worker   } else {
1187*e5436536SAndroid Build Coastguard Worker     if (hSbrElement->sbrBitstreamData.HeaderActiveDelay > 0) {
1188*e5436536SAndroid Build Coastguard Worker       hSbrElement->sbrBitstreamData.HeaderActiveDelay--;
1189*e5436536SAndroid Build Coastguard Worker     }
1190*e5436536SAndroid Build Coastguard Worker   }
1191*e5436536SAndroid Build Coastguard Worker 
1192*e5436536SAndroid Build Coastguard Worker   return (0);
1193*e5436536SAndroid Build Coastguard Worker }
1194*e5436536SAndroid Build Coastguard Worker 
1195*e5436536SAndroid Build Coastguard Worker /*****************************************************************************
1196*e5436536SAndroid Build Coastguard Worker 
1197*e5436536SAndroid Build Coastguard Worker  functionname: FDKsbrEnc_Downsample
1198*e5436536SAndroid Build Coastguard Worker  description: performs downsampling and delay compensation of the core path
1199*e5436536SAndroid Build Coastguard Worker  returns:
1200*e5436536SAndroid Build Coastguard Worker  input:
1201*e5436536SAndroid Build Coastguard Worker  output:
1202*e5436536SAndroid Build Coastguard Worker 
1203*e5436536SAndroid Build Coastguard Worker *****************************************************************************/
FDKsbrEnc_Downsample(HANDLE_SBR_ENCODER hSbrEncoder,INT_PCM * samples,UINT samplesBufSize,UINT numChannels,UINT * sbrDataBits,UCHAR * sbrData,int clearOutput)1204*e5436536SAndroid Build Coastguard Worker INT FDKsbrEnc_Downsample(
1205*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_ENCODER hSbrEncoder,
1206*e5436536SAndroid Build Coastguard Worker     INT_PCM *samples,    /*!< time samples, always deinterleaved */
1207*e5436536SAndroid Build Coastguard Worker     UINT samplesBufSize, /*!< time buffer size per channel */
1208*e5436536SAndroid Build Coastguard Worker     UINT numChannels,    /*!< number of channels */
1209*e5436536SAndroid Build Coastguard Worker     UINT *sbrDataBits,   /*!< Size of SBR payload  */
1210*e5436536SAndroid Build Coastguard Worker     UCHAR *sbrData,      /*!< SBR payload  */
1211*e5436536SAndroid Build Coastguard Worker     int clearOutput      /*!< Do not consider any input signal */
1212*e5436536SAndroid Build Coastguard Worker ) {
1213*e5436536SAndroid Build Coastguard Worker   HANDLE_SBR_ELEMENT hSbrElement = NULL;
1214*e5436536SAndroid Build Coastguard Worker   INT nOutSamples;
1215*e5436536SAndroid Build Coastguard Worker   int el;
1216*e5436536SAndroid Build Coastguard Worker   if (hSbrEncoder->downSampleFactor > 1) {
1217*e5436536SAndroid Build Coastguard Worker     /* Do downsampling */
1218*e5436536SAndroid Build Coastguard Worker 
1219*e5436536SAndroid Build Coastguard Worker     /* Loop over elements (LFE is handled later) */
1220*e5436536SAndroid Build Coastguard Worker     for (el = 0; el < hSbrEncoder->noElements; el++) {
1221*e5436536SAndroid Build Coastguard Worker       hSbrElement = hSbrEncoder->sbrElement[el];
1222*e5436536SAndroid Build Coastguard Worker       if (hSbrEncoder->sbrElement[el] != NULL) {
1223*e5436536SAndroid Build Coastguard Worker         if (hSbrEncoder->downsamplingMethod == SBRENC_DS_TIME) {
1224*e5436536SAndroid Build Coastguard Worker           int ch;
1225*e5436536SAndroid Build Coastguard Worker           int nChannels = hSbrElement->sbrConfigData.nChannels;
1226*e5436536SAndroid Build Coastguard Worker 
1227*e5436536SAndroid Build Coastguard Worker           for (ch = 0; ch < nChannels; ch++) {
1228*e5436536SAndroid Build Coastguard Worker             FDKaacEnc_Downsample(
1229*e5436536SAndroid Build Coastguard Worker                 &hSbrElement->sbrChannel[ch]->downSampler,
1230*e5436536SAndroid Build Coastguard Worker                 samples +
1231*e5436536SAndroid Build Coastguard Worker                     hSbrElement->elInfo.ChannelIndex[ch] * samplesBufSize +
1232*e5436536SAndroid Build Coastguard Worker                     hSbrEncoder->bufferOffset / numChannels,
1233*e5436536SAndroid Build Coastguard Worker                 hSbrElement->sbrConfigData.frameSize,
1234*e5436536SAndroid Build Coastguard Worker                 samples + hSbrElement->elInfo.ChannelIndex[ch] * samplesBufSize,
1235*e5436536SAndroid Build Coastguard Worker                 &nOutSamples);
1236*e5436536SAndroid Build Coastguard Worker           }
1237*e5436536SAndroid Build Coastguard Worker         }
1238*e5436536SAndroid Build Coastguard Worker       }
1239*e5436536SAndroid Build Coastguard Worker     }
1240*e5436536SAndroid Build Coastguard Worker 
1241*e5436536SAndroid Build Coastguard Worker     /* Handle LFE (if existing) */
1242*e5436536SAndroid Build Coastguard Worker     if (hSbrEncoder->lfeChIdx != -1) { /* lfe downsampler */
1243*e5436536SAndroid Build Coastguard Worker       FDKaacEnc_Downsample(&hSbrEncoder->lfeDownSampler,
1244*e5436536SAndroid Build Coastguard Worker                            samples + hSbrEncoder->lfeChIdx * samplesBufSize +
1245*e5436536SAndroid Build Coastguard Worker                                hSbrEncoder->bufferOffset / numChannels,
1246*e5436536SAndroid Build Coastguard Worker                            hSbrEncoder->frameSize,
1247*e5436536SAndroid Build Coastguard Worker                            samples + hSbrEncoder->lfeChIdx * samplesBufSize,
1248*e5436536SAndroid Build Coastguard Worker                            &nOutSamples);
1249*e5436536SAndroid Build Coastguard Worker     }
1250*e5436536SAndroid Build Coastguard Worker   } else {
1251*e5436536SAndroid Build Coastguard Worker     /* No downsampling. Still, some buffer shifting for correct delay */
1252*e5436536SAndroid Build Coastguard Worker     int samples2Copy = hSbrEncoder->frameSize;
1253*e5436536SAndroid Build Coastguard Worker     if (hSbrEncoder->bufferOffset / (int)numChannels < samples2Copy) {
1254*e5436536SAndroid Build Coastguard Worker       for (int c = 0; c < (int)numChannels; c++) {
1255*e5436536SAndroid Build Coastguard Worker         /* Do memmove while taking care of overlapping memory areas. (memcpy
1256*e5436536SAndroid Build Coastguard Worker            does not necessarily take care) Distinguish between oeverlapping and
1257*e5436536SAndroid Build Coastguard Worker            non overlapping version due to reasons of complexity. */
1258*e5436536SAndroid Build Coastguard Worker         FDKmemmove(samples + c * samplesBufSize,
1259*e5436536SAndroid Build Coastguard Worker                    samples + c * samplesBufSize +
1260*e5436536SAndroid Build Coastguard Worker                        hSbrEncoder->bufferOffset / numChannels,
1261*e5436536SAndroid Build Coastguard Worker                    samples2Copy * sizeof(INT_PCM));
1262*e5436536SAndroid Build Coastguard Worker       }
1263*e5436536SAndroid Build Coastguard Worker     } else {
1264*e5436536SAndroid Build Coastguard Worker       for (int c = 0; c < (int)numChannels; c++) {
1265*e5436536SAndroid Build Coastguard Worker         /* Simple memcpy since the memory areas are not overlapping */
1266*e5436536SAndroid Build Coastguard Worker         FDKmemcpy(samples + c * samplesBufSize,
1267*e5436536SAndroid Build Coastguard Worker                   samples + c * samplesBufSize +
1268*e5436536SAndroid Build Coastguard Worker                       hSbrEncoder->bufferOffset / numChannels,
1269*e5436536SAndroid Build Coastguard Worker                   samples2Copy * sizeof(INT_PCM));
1270*e5436536SAndroid Build Coastguard Worker       }
1271*e5436536SAndroid Build Coastguard Worker     }
1272*e5436536SAndroid Build Coastguard Worker   }
1273*e5436536SAndroid Build Coastguard Worker 
1274*e5436536SAndroid Build Coastguard Worker   return 0;
1275*e5436536SAndroid Build Coastguard Worker }
1276*e5436536SAndroid Build Coastguard Worker 
1277*e5436536SAndroid Build Coastguard Worker /*****************************************************************************
1278*e5436536SAndroid Build Coastguard Worker 
1279*e5436536SAndroid Build Coastguard Worker  functionname: createEnvChannel
1280*e5436536SAndroid Build Coastguard Worker  description:  initializes parameters and allocates memory
1281*e5436536SAndroid Build Coastguard Worker  returns:      error status
1282*e5436536SAndroid Build Coastguard Worker  input:
1283*e5436536SAndroid Build Coastguard Worker  output:       hEnv
1284*e5436536SAndroid Build Coastguard Worker 
1285*e5436536SAndroid Build Coastguard Worker *****************************************************************************/
1286*e5436536SAndroid Build Coastguard Worker 
createEnvChannel(HANDLE_ENV_CHANNEL hEnv,INT channel,UCHAR * dynamic_RAM)1287*e5436536SAndroid Build Coastguard Worker static INT createEnvChannel(HANDLE_ENV_CHANNEL hEnv, INT channel,
1288*e5436536SAndroid Build Coastguard Worker                             UCHAR *dynamic_RAM) {
1289*e5436536SAndroid Build Coastguard Worker   FDKmemclear(hEnv, sizeof(struct ENV_CHANNEL));
1290*e5436536SAndroid Build Coastguard Worker 
1291*e5436536SAndroid Build Coastguard Worker   if (FDKsbrEnc_CreateTonCorrParamExtr(&hEnv->TonCorr, channel)) {
1292*e5436536SAndroid Build Coastguard Worker     return (1);
1293*e5436536SAndroid Build Coastguard Worker   }
1294*e5436536SAndroid Build Coastguard Worker 
1295*e5436536SAndroid Build Coastguard Worker   if (FDKsbrEnc_CreateExtractSbrEnvelope(&hEnv->sbrExtractEnvelope, channel,
1296*e5436536SAndroid Build Coastguard Worker                                          /*chan*/ 0, dynamic_RAM)) {
1297*e5436536SAndroid Build Coastguard Worker     return (1);
1298*e5436536SAndroid Build Coastguard Worker   }
1299*e5436536SAndroid Build Coastguard Worker 
1300*e5436536SAndroid Build Coastguard Worker   return 0;
1301*e5436536SAndroid Build Coastguard Worker }
1302*e5436536SAndroid Build Coastguard Worker 
1303*e5436536SAndroid Build Coastguard Worker /*****************************************************************************
1304*e5436536SAndroid Build Coastguard Worker 
1305*e5436536SAndroid Build Coastguard Worker  functionname: initEnvChannel
1306*e5436536SAndroid Build Coastguard Worker  description:  initializes parameters
1307*e5436536SAndroid Build Coastguard Worker  returns:      error status
1308*e5436536SAndroid Build Coastguard Worker  input:
1309*e5436536SAndroid Build Coastguard Worker  output:
1310*e5436536SAndroid Build Coastguard Worker 
1311*e5436536SAndroid Build Coastguard Worker *****************************************************************************/
initEnvChannel(HANDLE_SBR_CONFIG_DATA sbrConfigData,HANDLE_SBR_HEADER_DATA sbrHeaderData,HANDLE_ENV_CHANNEL hEnv,sbrConfigurationPtr params,ULONG statesInitFlag,INT chanInEl,UCHAR * dynamic_RAM)1312*e5436536SAndroid Build Coastguard Worker static INT initEnvChannel(HANDLE_SBR_CONFIG_DATA sbrConfigData,
1313*e5436536SAndroid Build Coastguard Worker                           HANDLE_SBR_HEADER_DATA sbrHeaderData,
1314*e5436536SAndroid Build Coastguard Worker                           HANDLE_ENV_CHANNEL hEnv, sbrConfigurationPtr params,
1315*e5436536SAndroid Build Coastguard Worker                           ULONG statesInitFlag, INT chanInEl,
1316*e5436536SAndroid Build Coastguard Worker                           UCHAR *dynamic_RAM) {
1317*e5436536SAndroid Build Coastguard Worker   int frameShift, tran_off = 0;
1318*e5436536SAndroid Build Coastguard Worker   INT e;
1319*e5436536SAndroid Build Coastguard Worker   INT tran_fc;
1320*e5436536SAndroid Build Coastguard Worker   INT timeSlots, timeStep, startIndex;
1321*e5436536SAndroid Build Coastguard Worker   INT noiseBands[2] = {3, 3};
1322*e5436536SAndroid Build Coastguard Worker 
1323*e5436536SAndroid Build Coastguard Worker   e = 1 << params->e;
1324*e5436536SAndroid Build Coastguard Worker 
1325*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(params->e >= 0);
1326*e5436536SAndroid Build Coastguard Worker 
1327*e5436536SAndroid Build Coastguard Worker   hEnv->encEnvData.freq_res_fixfix[0] = params->freq_res_fixfix[0];
1328*e5436536SAndroid Build Coastguard Worker   hEnv->encEnvData.freq_res_fixfix[1] = params->freq_res_fixfix[1];
1329*e5436536SAndroid Build Coastguard Worker   hEnv->encEnvData.fResTransIsLow = params->fResTransIsLow;
1330*e5436536SAndroid Build Coastguard Worker 
1331*e5436536SAndroid Build Coastguard Worker   hEnv->fLevelProtect = 0;
1332*e5436536SAndroid Build Coastguard Worker 
1333*e5436536SAndroid Build Coastguard Worker   hEnv->encEnvData.ldGrid =
1334*e5436536SAndroid Build Coastguard Worker       (sbrConfigData->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) ? 1 : 0;
1335*e5436536SAndroid Build Coastguard Worker 
1336*e5436536SAndroid Build Coastguard Worker   hEnv->encEnvData.sbr_xpos_mode = (XPOS_MODE)params->sbr_xpos_mode;
1337*e5436536SAndroid Build Coastguard Worker 
1338*e5436536SAndroid Build Coastguard Worker   if (hEnv->encEnvData.sbr_xpos_mode == XPOS_SWITCHED) {
1339*e5436536SAndroid Build Coastguard Worker     /*
1340*e5436536SAndroid Build Coastguard Worker        no other type than XPOS_MDCT or XPOS_SPEECH allowed,
1341*e5436536SAndroid Build Coastguard Worker        but enable switching
1342*e5436536SAndroid Build Coastguard Worker     */
1343*e5436536SAndroid Build Coastguard Worker     sbrConfigData->switchTransposers = TRUE;
1344*e5436536SAndroid Build Coastguard Worker     hEnv->encEnvData.sbr_xpos_mode = XPOS_MDCT;
1345*e5436536SAndroid Build Coastguard Worker   } else {
1346*e5436536SAndroid Build Coastguard Worker     sbrConfigData->switchTransposers = FALSE;
1347*e5436536SAndroid Build Coastguard Worker   }
1348*e5436536SAndroid Build Coastguard Worker 
1349*e5436536SAndroid Build Coastguard Worker   hEnv->encEnvData.sbr_xpos_ctrl = params->sbr_xpos_ctrl;
1350*e5436536SAndroid Build Coastguard Worker 
1351*e5436536SAndroid Build Coastguard Worker   /* extended data */
1352*e5436536SAndroid Build Coastguard Worker   if (params->parametricCoding) {
1353*e5436536SAndroid Build Coastguard Worker     hEnv->encEnvData.extended_data = 1;
1354*e5436536SAndroid Build Coastguard Worker   } else {
1355*e5436536SAndroid Build Coastguard Worker     hEnv->encEnvData.extended_data = 0;
1356*e5436536SAndroid Build Coastguard Worker   }
1357*e5436536SAndroid Build Coastguard Worker 
1358*e5436536SAndroid Build Coastguard Worker   hEnv->encEnvData.extension_size = 0;
1359*e5436536SAndroid Build Coastguard Worker 
1360*e5436536SAndroid Build Coastguard Worker   startIndex = QMF_FILTER_PROTOTYPE_SIZE - sbrConfigData->noQmfBands;
1361*e5436536SAndroid Build Coastguard Worker 
1362*e5436536SAndroid Build Coastguard Worker   switch (params->sbrFrameSize) {
1363*e5436536SAndroid Build Coastguard Worker     case 2304:
1364*e5436536SAndroid Build Coastguard Worker       timeSlots = 18;
1365*e5436536SAndroid Build Coastguard Worker       break;
1366*e5436536SAndroid Build Coastguard Worker     case 2048:
1367*e5436536SAndroid Build Coastguard Worker     case 1024:
1368*e5436536SAndroid Build Coastguard Worker     case 512:
1369*e5436536SAndroid Build Coastguard Worker       timeSlots = 16;
1370*e5436536SAndroid Build Coastguard Worker       break;
1371*e5436536SAndroid Build Coastguard Worker     case 1920:
1372*e5436536SAndroid Build Coastguard Worker     case 960:
1373*e5436536SAndroid Build Coastguard Worker     case 480:
1374*e5436536SAndroid Build Coastguard Worker       timeSlots = 15;
1375*e5436536SAndroid Build Coastguard Worker       break;
1376*e5436536SAndroid Build Coastguard Worker     case 1152:
1377*e5436536SAndroid Build Coastguard Worker       timeSlots = 9;
1378*e5436536SAndroid Build Coastguard Worker       break;
1379*e5436536SAndroid Build Coastguard Worker     default:
1380*e5436536SAndroid Build Coastguard Worker       return (1); /* Illegal frame size */
1381*e5436536SAndroid Build Coastguard Worker   }
1382*e5436536SAndroid Build Coastguard Worker 
1383*e5436536SAndroid Build Coastguard Worker   timeStep = sbrConfigData->noQmfSlots / timeSlots;
1384*e5436536SAndroid Build Coastguard Worker 
1385*e5436536SAndroid Build Coastguard Worker   if (FDKsbrEnc_InitTonCorrParamExtr(
1386*e5436536SAndroid Build Coastguard Worker           params->sbrFrameSize, &hEnv->TonCorr, sbrConfigData, timeSlots,
1387*e5436536SAndroid Build Coastguard Worker           params->sbr_xpos_ctrl, params->ana_max_level,
1388*e5436536SAndroid Build Coastguard Worker           sbrHeaderData->sbr_noise_bands, params->noiseFloorOffset,
1389*e5436536SAndroid Build Coastguard Worker           params->useSpeechConfig))
1390*e5436536SAndroid Build Coastguard Worker     return (1);
1391*e5436536SAndroid Build Coastguard Worker 
1392*e5436536SAndroid Build Coastguard Worker   hEnv->encEnvData.noOfnoisebands =
1393*e5436536SAndroid Build Coastguard Worker       hEnv->TonCorr.sbrNoiseFloorEstimate.noNoiseBands;
1394*e5436536SAndroid Build Coastguard Worker 
1395*e5436536SAndroid Build Coastguard Worker   noiseBands[0] = hEnv->encEnvData.noOfnoisebands;
1396*e5436536SAndroid Build Coastguard Worker   noiseBands[1] = hEnv->encEnvData.noOfnoisebands;
1397*e5436536SAndroid Build Coastguard Worker 
1398*e5436536SAndroid Build Coastguard Worker   hEnv->encEnvData.sbr_invf_mode = (INVF_MODE)params->sbr_invf_mode;
1399*e5436536SAndroid Build Coastguard Worker 
1400*e5436536SAndroid Build Coastguard Worker   if (hEnv->encEnvData.sbr_invf_mode == INVF_SWITCHED) {
1401*e5436536SAndroid Build Coastguard Worker     hEnv->encEnvData.sbr_invf_mode = INVF_MID_LEVEL;
1402*e5436536SAndroid Build Coastguard Worker     hEnv->TonCorr.switchInverseFilt = TRUE;
1403*e5436536SAndroid Build Coastguard Worker   } else {
1404*e5436536SAndroid Build Coastguard Worker     hEnv->TonCorr.switchInverseFilt = FALSE;
1405*e5436536SAndroid Build Coastguard Worker   }
1406*e5436536SAndroid Build Coastguard Worker 
1407*e5436536SAndroid Build Coastguard Worker   tran_fc = params->tran_fc;
1408*e5436536SAndroid Build Coastguard Worker 
1409*e5436536SAndroid Build Coastguard Worker   if (tran_fc == 0) {
1410*e5436536SAndroid Build Coastguard Worker     tran_fc = fixMin(
1411*e5436536SAndroid Build Coastguard Worker         5000, FDKsbrEnc_getSbrStartFreqRAW(sbrHeaderData->sbr_start_frequency,
1412*e5436536SAndroid Build Coastguard Worker                                            params->codecSettings.sampleFreq));
1413*e5436536SAndroid Build Coastguard Worker   }
1414*e5436536SAndroid Build Coastguard Worker 
1415*e5436536SAndroid Build Coastguard Worker   tran_fc =
1416*e5436536SAndroid Build Coastguard Worker       (tran_fc * 4 * sbrConfigData->noQmfBands / sbrConfigData->sampleFreq +
1417*e5436536SAndroid Build Coastguard Worker        1) >>
1418*e5436536SAndroid Build Coastguard Worker       1;
1419*e5436536SAndroid Build Coastguard Worker 
1420*e5436536SAndroid Build Coastguard Worker   if (sbrConfigData->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) {
1421*e5436536SAndroid Build Coastguard Worker     frameShift = LD_PRETRAN_OFF;
1422*e5436536SAndroid Build Coastguard Worker     tran_off = LD_PRETRAN_OFF + FRAME_MIDDLE_SLOT_512LD * timeStep;
1423*e5436536SAndroid Build Coastguard Worker   } else {
1424*e5436536SAndroid Build Coastguard Worker     frameShift = 0;
1425*e5436536SAndroid Build Coastguard Worker     switch (timeSlots) {
1426*e5436536SAndroid Build Coastguard Worker       /* The factor of 2 is by definition. */
1427*e5436536SAndroid Build Coastguard Worker       case NUMBER_TIME_SLOTS_2048:
1428*e5436536SAndroid Build Coastguard Worker         tran_off = 8 + FRAME_MIDDLE_SLOT_2048 * timeStep;
1429*e5436536SAndroid Build Coastguard Worker         break;
1430*e5436536SAndroid Build Coastguard Worker       case NUMBER_TIME_SLOTS_1920:
1431*e5436536SAndroid Build Coastguard Worker         tran_off = 7 + FRAME_MIDDLE_SLOT_1920 * timeStep;
1432*e5436536SAndroid Build Coastguard Worker         break;
1433*e5436536SAndroid Build Coastguard Worker       default:
1434*e5436536SAndroid Build Coastguard Worker         return 1;
1435*e5436536SAndroid Build Coastguard Worker     }
1436*e5436536SAndroid Build Coastguard Worker   }
1437*e5436536SAndroid Build Coastguard Worker   if (FDKsbrEnc_InitExtractSbrEnvelope(
1438*e5436536SAndroid Build Coastguard Worker           &hEnv->sbrExtractEnvelope, sbrConfigData->noQmfSlots,
1439*e5436536SAndroid Build Coastguard Worker           sbrConfigData->noQmfBands, startIndex, timeSlots, timeStep, tran_off,
1440*e5436536SAndroid Build Coastguard Worker           statesInitFlag, chanInEl, dynamic_RAM, sbrConfigData->sbrSyntaxFlags))
1441*e5436536SAndroid Build Coastguard Worker     return (1);
1442*e5436536SAndroid Build Coastguard Worker 
1443*e5436536SAndroid Build Coastguard Worker   if (FDKsbrEnc_InitSbrCodeEnvelope(&hEnv->sbrCodeEnvelope, sbrConfigData->nSfb,
1444*e5436536SAndroid Build Coastguard Worker                                     params->deltaTAcrossFrames,
1445*e5436536SAndroid Build Coastguard Worker                                     params->dF_edge_1stEnv,
1446*e5436536SAndroid Build Coastguard Worker                                     params->dF_edge_incr))
1447*e5436536SAndroid Build Coastguard Worker     return (1);
1448*e5436536SAndroid Build Coastguard Worker 
1449*e5436536SAndroid Build Coastguard Worker   if (FDKsbrEnc_InitSbrCodeEnvelope(&hEnv->sbrCodeNoiseFloor, noiseBands,
1450*e5436536SAndroid Build Coastguard Worker                                     params->deltaTAcrossFrames, 0, 0))
1451*e5436536SAndroid Build Coastguard Worker     return (1);
1452*e5436536SAndroid Build Coastguard Worker 
1453*e5436536SAndroid Build Coastguard Worker   if (FDKsbrEnc_InitSbrHuffmanTables(&hEnv->encEnvData, &hEnv->sbrCodeEnvelope,
1454*e5436536SAndroid Build Coastguard Worker                                      &hEnv->sbrCodeNoiseFloor,
1455*e5436536SAndroid Build Coastguard Worker                                      sbrHeaderData->sbr_amp_res))
1456*e5436536SAndroid Build Coastguard Worker     return (1);
1457*e5436536SAndroid Build Coastguard Worker 
1458*e5436536SAndroid Build Coastguard Worker   FDKsbrEnc_initFrameInfoGenerator(
1459*e5436536SAndroid Build Coastguard Worker       &hEnv->SbrEnvFrame, params->spread, e, params->stat, timeSlots,
1460*e5436536SAndroid Build Coastguard Worker       hEnv->encEnvData.freq_res_fixfix, hEnv->encEnvData.fResTransIsLow,
1461*e5436536SAndroid Build Coastguard Worker       hEnv->encEnvData.ldGrid);
1462*e5436536SAndroid Build Coastguard Worker 
1463*e5436536SAndroid Build Coastguard Worker   if (sbrConfigData->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY)
1464*e5436536SAndroid Build Coastguard Worker 
1465*e5436536SAndroid Build Coastguard Worker   {
1466*e5436536SAndroid Build Coastguard Worker     INT bandwidth_qmf_slot =
1467*e5436536SAndroid Build Coastguard Worker         (sbrConfigData->sampleFreq >> 1) / (sbrConfigData->noQmfBands);
1468*e5436536SAndroid Build Coastguard Worker     if (FDKsbrEnc_InitSbrFastTransientDetector(
1469*e5436536SAndroid Build Coastguard Worker             &hEnv->sbrFastTransientDetector, sbrConfigData->noQmfSlots,
1470*e5436536SAndroid Build Coastguard Worker             bandwidth_qmf_slot, sbrConfigData->noQmfBands,
1471*e5436536SAndroid Build Coastguard Worker             sbrConfigData->freqBandTable[0][0]))
1472*e5436536SAndroid Build Coastguard Worker       return (1);
1473*e5436536SAndroid Build Coastguard Worker   }
1474*e5436536SAndroid Build Coastguard Worker 
1475*e5436536SAndroid Build Coastguard Worker   /* The transient detector has to be initialized also if the fast transient
1476*e5436536SAndroid Build Coastguard Worker      detector was active, because the values from the transient detector
1477*e5436536SAndroid Build Coastguard Worker      structure are used. */
1478*e5436536SAndroid Build Coastguard Worker   if (FDKsbrEnc_InitSbrTransientDetector(
1479*e5436536SAndroid Build Coastguard Worker           &hEnv->sbrTransientDetector, sbrConfigData->sbrSyntaxFlags,
1480*e5436536SAndroid Build Coastguard Worker           sbrConfigData->frameSize, sbrConfigData->sampleFreq, params, tran_fc,
1481*e5436536SAndroid Build Coastguard Worker           sbrConfigData->noQmfSlots, sbrConfigData->noQmfBands,
1482*e5436536SAndroid Build Coastguard Worker           hEnv->sbrExtractEnvelope.YBufferWriteOffset,
1483*e5436536SAndroid Build Coastguard Worker           hEnv->sbrExtractEnvelope.YBufferSzShift, frameShift, tran_off))
1484*e5436536SAndroid Build Coastguard Worker     return (1);
1485*e5436536SAndroid Build Coastguard Worker 
1486*e5436536SAndroid Build Coastguard Worker   sbrConfigData->xposCtrlSwitch = params->sbr_xpos_ctrl;
1487*e5436536SAndroid Build Coastguard Worker 
1488*e5436536SAndroid Build Coastguard Worker   hEnv->encEnvData.noHarmonics = sbrConfigData->nSfb[HI];
1489*e5436536SAndroid Build Coastguard Worker   hEnv->encEnvData.addHarmonicFlag = 0;
1490*e5436536SAndroid Build Coastguard Worker 
1491*e5436536SAndroid Build Coastguard Worker   return (0);
1492*e5436536SAndroid Build Coastguard Worker }
1493*e5436536SAndroid Build Coastguard Worker 
sbrEncoder_Open(HANDLE_SBR_ENCODER * phSbrEncoder,INT nElements,INT nChannels,INT supportPS)1494*e5436536SAndroid Build Coastguard Worker INT sbrEncoder_Open(HANDLE_SBR_ENCODER *phSbrEncoder, INT nElements,
1495*e5436536SAndroid Build Coastguard Worker                     INT nChannels, INT supportPS) {
1496*e5436536SAndroid Build Coastguard Worker   INT i;
1497*e5436536SAndroid Build Coastguard Worker   INT errorStatus = 1;
1498*e5436536SAndroid Build Coastguard Worker   HANDLE_SBR_ENCODER hSbrEncoder = NULL;
1499*e5436536SAndroid Build Coastguard Worker 
1500*e5436536SAndroid Build Coastguard Worker   if (phSbrEncoder == NULL) {
1501*e5436536SAndroid Build Coastguard Worker     goto bail;
1502*e5436536SAndroid Build Coastguard Worker   }
1503*e5436536SAndroid Build Coastguard Worker 
1504*e5436536SAndroid Build Coastguard Worker   hSbrEncoder = GetRam_SbrEncoder();
1505*e5436536SAndroid Build Coastguard Worker   if (hSbrEncoder == NULL) {
1506*e5436536SAndroid Build Coastguard Worker     goto bail;
1507*e5436536SAndroid Build Coastguard Worker   }
1508*e5436536SAndroid Build Coastguard Worker   FDKmemclear(hSbrEncoder, sizeof(SBR_ENCODER));
1509*e5436536SAndroid Build Coastguard Worker 
1510*e5436536SAndroid Build Coastguard Worker   if (NULL ==
1511*e5436536SAndroid Build Coastguard Worker       (hSbrEncoder->pSBRdynamic_RAM = (UCHAR *)GetRam_SbrDynamic_RAM())) {
1512*e5436536SAndroid Build Coastguard Worker     goto bail;
1513*e5436536SAndroid Build Coastguard Worker   }
1514*e5436536SAndroid Build Coastguard Worker   hSbrEncoder->dynamicRam = hSbrEncoder->pSBRdynamic_RAM;
1515*e5436536SAndroid Build Coastguard Worker 
1516*e5436536SAndroid Build Coastguard Worker   /* Create SBR elements */
1517*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < nElements; i++) {
1518*e5436536SAndroid Build Coastguard Worker     hSbrEncoder->sbrElement[i] = GetRam_SbrElement(i);
1519*e5436536SAndroid Build Coastguard Worker     if (hSbrEncoder->sbrElement[i] == NULL) {
1520*e5436536SAndroid Build Coastguard Worker       goto bail;
1521*e5436536SAndroid Build Coastguard Worker     }
1522*e5436536SAndroid Build Coastguard Worker     FDKmemclear(hSbrEncoder->sbrElement[i], sizeof(SBR_ELEMENT));
1523*e5436536SAndroid Build Coastguard Worker     hSbrEncoder->sbrElement[i]->sbrConfigData.freqBandTable[LO] =
1524*e5436536SAndroid Build Coastguard Worker         GetRam_Sbr_freqBandTableLO(i);
1525*e5436536SAndroid Build Coastguard Worker     hSbrEncoder->sbrElement[i]->sbrConfigData.freqBandTable[HI] =
1526*e5436536SAndroid Build Coastguard Worker         GetRam_Sbr_freqBandTableHI(i);
1527*e5436536SAndroid Build Coastguard Worker     hSbrEncoder->sbrElement[i]->sbrConfigData.v_k_master =
1528*e5436536SAndroid Build Coastguard Worker         GetRam_Sbr_v_k_master(i);
1529*e5436536SAndroid Build Coastguard Worker     if ((hSbrEncoder->sbrElement[i]->sbrConfigData.freqBandTable[LO] == NULL) ||
1530*e5436536SAndroid Build Coastguard Worker         (hSbrEncoder->sbrElement[i]->sbrConfigData.freqBandTable[HI] == NULL) ||
1531*e5436536SAndroid Build Coastguard Worker         (hSbrEncoder->sbrElement[i]->sbrConfigData.v_k_master == NULL)) {
1532*e5436536SAndroid Build Coastguard Worker       goto bail;
1533*e5436536SAndroid Build Coastguard Worker     }
1534*e5436536SAndroid Build Coastguard Worker   }
1535*e5436536SAndroid Build Coastguard Worker 
1536*e5436536SAndroid Build Coastguard Worker   /* Create SBR channels */
1537*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < nChannels; i++) {
1538*e5436536SAndroid Build Coastguard Worker     hSbrEncoder->pSbrChannel[i] = GetRam_SbrChannel(i);
1539*e5436536SAndroid Build Coastguard Worker     if (hSbrEncoder->pSbrChannel[i] == NULL) {
1540*e5436536SAndroid Build Coastguard Worker       goto bail;
1541*e5436536SAndroid Build Coastguard Worker     }
1542*e5436536SAndroid Build Coastguard Worker 
1543*e5436536SAndroid Build Coastguard Worker     if (createEnvChannel(&hSbrEncoder->pSbrChannel[i]->hEnvChannel, i,
1544*e5436536SAndroid Build Coastguard Worker                          hSbrEncoder->dynamicRam)) {
1545*e5436536SAndroid Build Coastguard Worker       goto bail;
1546*e5436536SAndroid Build Coastguard Worker     }
1547*e5436536SAndroid Build Coastguard Worker   }
1548*e5436536SAndroid Build Coastguard Worker 
1549*e5436536SAndroid Build Coastguard Worker   /* Create QMF States */
1550*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < fixMax(nChannels, (supportPS) ? 2 : 0); i++) {
1551*e5436536SAndroid Build Coastguard Worker     hSbrEncoder->QmfAnalysis[i].FilterStates = GetRam_Sbr_QmfStatesAnalysis(i);
1552*e5436536SAndroid Build Coastguard Worker     if (hSbrEncoder->QmfAnalysis[i].FilterStates == NULL) {
1553*e5436536SAndroid Build Coastguard Worker       goto bail;
1554*e5436536SAndroid Build Coastguard Worker     }
1555*e5436536SAndroid Build Coastguard Worker   }
1556*e5436536SAndroid Build Coastguard Worker 
1557*e5436536SAndroid Build Coastguard Worker   /* Create Parametric Stereo handle */
1558*e5436536SAndroid Build Coastguard Worker   if (supportPS) {
1559*e5436536SAndroid Build Coastguard Worker     if (PSEnc_Create(&hSbrEncoder->hParametricStereo)) {
1560*e5436536SAndroid Build Coastguard Worker       goto bail;
1561*e5436536SAndroid Build Coastguard Worker     }
1562*e5436536SAndroid Build Coastguard Worker 
1563*e5436536SAndroid Build Coastguard Worker     hSbrEncoder->qmfSynthesisPS.FilterStates = GetRam_PsQmfStatesSynthesis();
1564*e5436536SAndroid Build Coastguard Worker     if (hSbrEncoder->qmfSynthesisPS.FilterStates == NULL) {
1565*e5436536SAndroid Build Coastguard Worker       goto bail;
1566*e5436536SAndroid Build Coastguard Worker     }
1567*e5436536SAndroid Build Coastguard Worker   } /* supportPS */
1568*e5436536SAndroid Build Coastguard Worker 
1569*e5436536SAndroid Build Coastguard Worker   *phSbrEncoder = hSbrEncoder;
1570*e5436536SAndroid Build Coastguard Worker 
1571*e5436536SAndroid Build Coastguard Worker   errorStatus = 0;
1572*e5436536SAndroid Build Coastguard Worker   return errorStatus;
1573*e5436536SAndroid Build Coastguard Worker 
1574*e5436536SAndroid Build Coastguard Worker bail:
1575*e5436536SAndroid Build Coastguard Worker   /* Close SBR encoder instance */
1576*e5436536SAndroid Build Coastguard Worker   sbrEncoder_Close(&hSbrEncoder);
1577*e5436536SAndroid Build Coastguard Worker   return errorStatus;
1578*e5436536SAndroid Build Coastguard Worker }
1579*e5436536SAndroid Build Coastguard Worker 
FDKsbrEnc_Reallocate(HANDLE_SBR_ENCODER hSbrEncoder,SBR_ELEMENT_INFO elInfo[(8)],const INT noElements)1580*e5436536SAndroid Build Coastguard Worker static INT FDKsbrEnc_Reallocate(HANDLE_SBR_ENCODER hSbrEncoder,
1581*e5436536SAndroid Build Coastguard Worker                                 SBR_ELEMENT_INFO elInfo[(8)],
1582*e5436536SAndroid Build Coastguard Worker                                 const INT noElements) {
1583*e5436536SAndroid Build Coastguard Worker   INT totalCh = 0;
1584*e5436536SAndroid Build Coastguard Worker   INT totalQmf = 0;
1585*e5436536SAndroid Build Coastguard Worker   INT coreEl;
1586*e5436536SAndroid Build Coastguard Worker   INT el = -1;
1587*e5436536SAndroid Build Coastguard Worker 
1588*e5436536SAndroid Build Coastguard Worker   hSbrEncoder->lfeChIdx = -1; /* default value, until lfe found */
1589*e5436536SAndroid Build Coastguard Worker 
1590*e5436536SAndroid Build Coastguard Worker   for (coreEl = 0; coreEl < noElements; coreEl++) {
1591*e5436536SAndroid Build Coastguard Worker     /* SBR only handles SCE and CPE's */
1592*e5436536SAndroid Build Coastguard Worker     if (elInfo[coreEl].elType == ID_SCE || elInfo[coreEl].elType == ID_CPE) {
1593*e5436536SAndroid Build Coastguard Worker       el++;
1594*e5436536SAndroid Build Coastguard Worker     } else {
1595*e5436536SAndroid Build Coastguard Worker       if (elInfo[coreEl].elType == ID_LFE) {
1596*e5436536SAndroid Build Coastguard Worker         hSbrEncoder->lfeChIdx = elInfo[coreEl].ChannelIndex[0];
1597*e5436536SAndroid Build Coastguard Worker       }
1598*e5436536SAndroid Build Coastguard Worker       continue;
1599*e5436536SAndroid Build Coastguard Worker     }
1600*e5436536SAndroid Build Coastguard Worker 
1601*e5436536SAndroid Build Coastguard Worker     SBR_ELEMENT_INFO *pelInfo = &elInfo[coreEl];
1602*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_ELEMENT hSbrElement = hSbrEncoder->sbrElement[el];
1603*e5436536SAndroid Build Coastguard Worker 
1604*e5436536SAndroid Build Coastguard Worker     int ch;
1605*e5436536SAndroid Build Coastguard Worker     for (ch = 0; ch < pelInfo->nChannelsInEl; ch++) {
1606*e5436536SAndroid Build Coastguard Worker       hSbrElement->sbrChannel[ch] = hSbrEncoder->pSbrChannel[totalCh];
1607*e5436536SAndroid Build Coastguard Worker       totalCh++;
1608*e5436536SAndroid Build Coastguard Worker     }
1609*e5436536SAndroid Build Coastguard Worker     /* analysis QMF */
1610*e5436536SAndroid Build Coastguard Worker     for (ch = 0;
1611*e5436536SAndroid Build Coastguard Worker          ch < ((pelInfo->fParametricStereo) ? 2 : pelInfo->nChannelsInEl);
1612*e5436536SAndroid Build Coastguard Worker          ch++) {
1613*e5436536SAndroid Build Coastguard Worker       hSbrElement->elInfo.ChannelIndex[ch] = pelInfo->ChannelIndex[ch];
1614*e5436536SAndroid Build Coastguard Worker       hSbrElement->hQmfAnalysis[ch] = &hSbrEncoder->QmfAnalysis[totalQmf++];
1615*e5436536SAndroid Build Coastguard Worker     }
1616*e5436536SAndroid Build Coastguard Worker 
1617*e5436536SAndroid Build Coastguard Worker     /* Copy Element info */
1618*e5436536SAndroid Build Coastguard Worker     hSbrElement->elInfo.elType = pelInfo->elType;
1619*e5436536SAndroid Build Coastguard Worker     hSbrElement->elInfo.instanceTag = pelInfo->instanceTag;
1620*e5436536SAndroid Build Coastguard Worker     hSbrElement->elInfo.nChannelsInEl = pelInfo->nChannelsInEl;
1621*e5436536SAndroid Build Coastguard Worker     hSbrElement->elInfo.fParametricStereo = pelInfo->fParametricStereo;
1622*e5436536SAndroid Build Coastguard Worker     hSbrElement->elInfo.fDualMono = pelInfo->fDualMono;
1623*e5436536SAndroid Build Coastguard Worker   } /* coreEl */
1624*e5436536SAndroid Build Coastguard Worker 
1625*e5436536SAndroid Build Coastguard Worker   return 0;
1626*e5436536SAndroid Build Coastguard Worker }
1627*e5436536SAndroid Build Coastguard Worker 
1628*e5436536SAndroid Build Coastguard Worker /*****************************************************************************
1629*e5436536SAndroid Build Coastguard Worker 
1630*e5436536SAndroid Build Coastguard Worker  functionname: FDKsbrEnc_bsBufInit
1631*e5436536SAndroid Build Coastguard Worker  description:  initializes bitstream buffer
1632*e5436536SAndroid Build Coastguard Worker  returns:      initialized bitstream buffer in env encoder
1633*e5436536SAndroid Build Coastguard Worker  input:
1634*e5436536SAndroid Build Coastguard Worker  output:       hEnv
1635*e5436536SAndroid Build Coastguard Worker 
1636*e5436536SAndroid Build Coastguard Worker *****************************************************************************/
FDKsbrEnc_bsBufInit(HANDLE_SBR_ELEMENT hSbrElement,int nBitstrDelay)1637*e5436536SAndroid Build Coastguard Worker static INT FDKsbrEnc_bsBufInit(HANDLE_SBR_ELEMENT hSbrElement,
1638*e5436536SAndroid Build Coastguard Worker                                int nBitstrDelay) {
1639*e5436536SAndroid Build Coastguard Worker   UCHAR *bitstreamBuffer;
1640*e5436536SAndroid Build Coastguard Worker 
1641*e5436536SAndroid Build Coastguard Worker   /* initialize the bitstream buffer */
1642*e5436536SAndroid Build Coastguard Worker   bitstreamBuffer = hSbrElement->payloadDelayLine[nBitstrDelay];
1643*e5436536SAndroid Build Coastguard Worker   FDKinitBitStream(&hSbrElement->CmonData.sbrBitbuf, bitstreamBuffer,
1644*e5436536SAndroid Build Coastguard Worker                    MAX_PAYLOAD_SIZE * sizeof(UCHAR), 0, BS_WRITER);
1645*e5436536SAndroid Build Coastguard Worker 
1646*e5436536SAndroid Build Coastguard Worker   return (0);
1647*e5436536SAndroid Build Coastguard Worker }
1648*e5436536SAndroid Build Coastguard Worker 
1649*e5436536SAndroid Build Coastguard Worker /*****************************************************************************
1650*e5436536SAndroid Build Coastguard Worker 
1651*e5436536SAndroid Build Coastguard Worker  functionname: FDKsbrEnc_EnvInit
1652*e5436536SAndroid Build Coastguard Worker  description:  initializes parameters
1653*e5436536SAndroid Build Coastguard Worker  returns:      error status
1654*e5436536SAndroid Build Coastguard Worker  input:
1655*e5436536SAndroid Build Coastguard Worker  output:       hEnv
1656*e5436536SAndroid Build Coastguard Worker 
1657*e5436536SAndroid Build Coastguard Worker *****************************************************************************/
FDKsbrEnc_EnvInit(HANDLE_SBR_ELEMENT hSbrElement,sbrConfigurationPtr params,INT * coreBandWith,AUDIO_OBJECT_TYPE aot,int nElement,const int headerPeriod,ULONG statesInitFlag,const SBRENC_DS_TYPE downsamplingMethod,UCHAR * dynamic_RAM)1658*e5436536SAndroid Build Coastguard Worker static INT FDKsbrEnc_EnvInit(HANDLE_SBR_ELEMENT hSbrElement,
1659*e5436536SAndroid Build Coastguard Worker                              sbrConfigurationPtr params, INT *coreBandWith,
1660*e5436536SAndroid Build Coastguard Worker                              AUDIO_OBJECT_TYPE aot, int nElement,
1661*e5436536SAndroid Build Coastguard Worker                              const int headerPeriod, ULONG statesInitFlag,
1662*e5436536SAndroid Build Coastguard Worker                              const SBRENC_DS_TYPE downsamplingMethod,
1663*e5436536SAndroid Build Coastguard Worker                              UCHAR *dynamic_RAM) {
1664*e5436536SAndroid Build Coastguard Worker   int ch, i;
1665*e5436536SAndroid Build Coastguard Worker 
1666*e5436536SAndroid Build Coastguard Worker   if ((params->codecSettings.nChannels < 1) ||
1667*e5436536SAndroid Build Coastguard Worker       (params->codecSettings.nChannels > MAX_NUM_CHANNELS)) {
1668*e5436536SAndroid Build Coastguard Worker     return (1);
1669*e5436536SAndroid Build Coastguard Worker   }
1670*e5436536SAndroid Build Coastguard Worker 
1671*e5436536SAndroid Build Coastguard Worker   /* init and set syntax flags */
1672*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrConfigData.sbrSyntaxFlags = 0;
1673*e5436536SAndroid Build Coastguard Worker 
1674*e5436536SAndroid Build Coastguard Worker   switch (aot) {
1675*e5436536SAndroid Build Coastguard Worker     case AOT_ER_AAC_ELD:
1676*e5436536SAndroid Build Coastguard Worker       hSbrElement->sbrConfigData.sbrSyntaxFlags |= SBR_SYNTAX_LOW_DELAY;
1677*e5436536SAndroid Build Coastguard Worker       break;
1678*e5436536SAndroid Build Coastguard Worker     default:
1679*e5436536SAndroid Build Coastguard Worker       break;
1680*e5436536SAndroid Build Coastguard Worker   }
1681*e5436536SAndroid Build Coastguard Worker   if (params->crcSbr) {
1682*e5436536SAndroid Build Coastguard Worker     hSbrElement->sbrConfigData.sbrSyntaxFlags |= SBR_SYNTAX_CRC;
1683*e5436536SAndroid Build Coastguard Worker   }
1684*e5436536SAndroid Build Coastguard Worker 
1685*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrConfigData.noQmfBands = 64 >> (2 - params->downSampleFactor);
1686*e5436536SAndroid Build Coastguard Worker   switch (hSbrElement->sbrConfigData.noQmfBands) {
1687*e5436536SAndroid Build Coastguard Worker     case 64:
1688*e5436536SAndroid Build Coastguard Worker       hSbrElement->sbrConfigData.noQmfSlots = params->sbrFrameSize >> 6;
1689*e5436536SAndroid Build Coastguard Worker       break;
1690*e5436536SAndroid Build Coastguard Worker     case 32:
1691*e5436536SAndroid Build Coastguard Worker       hSbrElement->sbrConfigData.noQmfSlots = params->sbrFrameSize >> 5;
1692*e5436536SAndroid Build Coastguard Worker       break;
1693*e5436536SAndroid Build Coastguard Worker     default:
1694*e5436536SAndroid Build Coastguard Worker       hSbrElement->sbrConfigData.noQmfSlots = params->sbrFrameSize >> 6;
1695*e5436536SAndroid Build Coastguard Worker       return (2);
1696*e5436536SAndroid Build Coastguard Worker   }
1697*e5436536SAndroid Build Coastguard Worker 
1698*e5436536SAndroid Build Coastguard Worker   /*
1699*e5436536SAndroid Build Coastguard Worker     now initialize sbrConfigData, sbrHeaderData and sbrBitstreamData,
1700*e5436536SAndroid Build Coastguard Worker   */
1701*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrConfigData.nChannels = params->codecSettings.nChannels;
1702*e5436536SAndroid Build Coastguard Worker 
1703*e5436536SAndroid Build Coastguard Worker   if (params->codecSettings.nChannels == 2) {
1704*e5436536SAndroid Build Coastguard Worker     if ((hSbrElement->elInfo.elType == ID_CPE) &&
1705*e5436536SAndroid Build Coastguard Worker         ((hSbrElement->elInfo.fDualMono == 1))) {
1706*e5436536SAndroid Build Coastguard Worker       hSbrElement->sbrConfigData.stereoMode = SBR_LEFT_RIGHT;
1707*e5436536SAndroid Build Coastguard Worker     } else {
1708*e5436536SAndroid Build Coastguard Worker       hSbrElement->sbrConfigData.stereoMode = params->stereoMode;
1709*e5436536SAndroid Build Coastguard Worker     }
1710*e5436536SAndroid Build Coastguard Worker   } else {
1711*e5436536SAndroid Build Coastguard Worker     hSbrElement->sbrConfigData.stereoMode = SBR_MONO;
1712*e5436536SAndroid Build Coastguard Worker   }
1713*e5436536SAndroid Build Coastguard Worker 
1714*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrConfigData.frameSize = params->sbrFrameSize;
1715*e5436536SAndroid Build Coastguard Worker 
1716*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrConfigData.sampleFreq =
1717*e5436536SAndroid Build Coastguard Worker       params->downSampleFactor * params->codecSettings.sampleFreq;
1718*e5436536SAndroid Build Coastguard Worker 
1719*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrBitstreamData.CountSendHeaderData = 0;
1720*e5436536SAndroid Build Coastguard Worker   if (params->SendHeaderDataTime > 0) {
1721*e5436536SAndroid Build Coastguard Worker     if (headerPeriod == -1) {
1722*e5436536SAndroid Build Coastguard Worker       hSbrElement->sbrBitstreamData.NrSendHeaderData = (INT)(
1723*e5436536SAndroid Build Coastguard Worker           params->SendHeaderDataTime * hSbrElement->sbrConfigData.sampleFreq /
1724*e5436536SAndroid Build Coastguard Worker           (1000 * hSbrElement->sbrConfigData.frameSize));
1725*e5436536SAndroid Build Coastguard Worker       hSbrElement->sbrBitstreamData.NrSendHeaderData =
1726*e5436536SAndroid Build Coastguard Worker           fixMax(hSbrElement->sbrBitstreamData.NrSendHeaderData, 1);
1727*e5436536SAndroid Build Coastguard Worker     } else {
1728*e5436536SAndroid Build Coastguard Worker       /* assure header period at least once per second */
1729*e5436536SAndroid Build Coastguard Worker       hSbrElement->sbrBitstreamData.NrSendHeaderData = fixMin(
1730*e5436536SAndroid Build Coastguard Worker           fixMax(headerPeriod, 1), (hSbrElement->sbrConfigData.sampleFreq /
1731*e5436536SAndroid Build Coastguard Worker                                     hSbrElement->sbrConfigData.frameSize));
1732*e5436536SAndroid Build Coastguard Worker     }
1733*e5436536SAndroid Build Coastguard Worker   } else {
1734*e5436536SAndroid Build Coastguard Worker     hSbrElement->sbrBitstreamData.NrSendHeaderData = 0;
1735*e5436536SAndroid Build Coastguard Worker   }
1736*e5436536SAndroid Build Coastguard Worker 
1737*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrHeaderData.sbr_data_extra = params->sbr_data_extra;
1738*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrBitstreamData.HeaderActive = 0;
1739*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrBitstreamData.rightBorderFIX = 0;
1740*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrHeaderData.sbr_start_frequency = params->startFreq;
1741*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrHeaderData.sbr_stop_frequency = params->stopFreq;
1742*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrHeaderData.sbr_xover_band = 0;
1743*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrHeaderData.sbr_lc_stereo_mode = 0;
1744*e5436536SAndroid Build Coastguard Worker 
1745*e5436536SAndroid Build Coastguard Worker   /* data_extra */
1746*e5436536SAndroid Build Coastguard Worker   if (params->sbr_xpos_ctrl != SBR_XPOS_CTRL_DEFAULT)
1747*e5436536SAndroid Build Coastguard Worker     hSbrElement->sbrHeaderData.sbr_data_extra = 1;
1748*e5436536SAndroid Build Coastguard Worker 
1749*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrHeaderData.sbr_amp_res = (AMP_RES)params->amp_res;
1750*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrConfigData.initAmpResFF = params->init_amp_res_FF;
1751*e5436536SAndroid Build Coastguard Worker 
1752*e5436536SAndroid Build Coastguard Worker   /* header_extra_1 */
1753*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrHeaderData.freqScale = params->freqScale;
1754*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrHeaderData.alterScale = params->alterScale;
1755*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrHeaderData.sbr_noise_bands = params->sbr_noise_bands;
1756*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrHeaderData.header_extra_1 = 0;
1757*e5436536SAndroid Build Coastguard Worker 
1758*e5436536SAndroid Build Coastguard Worker   if ((params->freqScale != SBR_FREQ_SCALE_DEFAULT) ||
1759*e5436536SAndroid Build Coastguard Worker       (params->alterScale != SBR_ALTER_SCALE_DEFAULT) ||
1760*e5436536SAndroid Build Coastguard Worker       (params->sbr_noise_bands != SBR_NOISE_BANDS_DEFAULT)) {
1761*e5436536SAndroid Build Coastguard Worker     hSbrElement->sbrHeaderData.header_extra_1 = 1;
1762*e5436536SAndroid Build Coastguard Worker   }
1763*e5436536SAndroid Build Coastguard Worker 
1764*e5436536SAndroid Build Coastguard Worker   /* header_extra_2 */
1765*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrHeaderData.sbr_limiter_bands = params->sbr_limiter_bands;
1766*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrHeaderData.sbr_limiter_gains = params->sbr_limiter_gains;
1767*e5436536SAndroid Build Coastguard Worker 
1768*e5436536SAndroid Build Coastguard Worker   if ((hSbrElement->sbrConfigData.sampleFreq > 48000) &&
1769*e5436536SAndroid Build Coastguard Worker       (hSbrElement->sbrHeaderData.sbr_start_frequency >= 9)) {
1770*e5436536SAndroid Build Coastguard Worker     hSbrElement->sbrHeaderData.sbr_limiter_gains = SBR_LIMITER_GAINS_INFINITE;
1771*e5436536SAndroid Build Coastguard Worker   }
1772*e5436536SAndroid Build Coastguard Worker 
1773*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrHeaderData.sbr_interpol_freq = params->sbr_interpol_freq;
1774*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrHeaderData.sbr_smoothing_length =
1775*e5436536SAndroid Build Coastguard Worker       params->sbr_smoothing_length;
1776*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrHeaderData.header_extra_2 = 0;
1777*e5436536SAndroid Build Coastguard Worker 
1778*e5436536SAndroid Build Coastguard Worker   if ((params->sbr_limiter_bands != SBR_LIMITER_BANDS_DEFAULT) ||
1779*e5436536SAndroid Build Coastguard Worker       (params->sbr_limiter_gains != SBR_LIMITER_GAINS_DEFAULT) ||
1780*e5436536SAndroid Build Coastguard Worker       (params->sbr_interpol_freq != SBR_INTERPOL_FREQ_DEFAULT) ||
1781*e5436536SAndroid Build Coastguard Worker       (params->sbr_smoothing_length != SBR_SMOOTHING_LENGTH_DEFAULT)) {
1782*e5436536SAndroid Build Coastguard Worker     hSbrElement->sbrHeaderData.header_extra_2 = 1;
1783*e5436536SAndroid Build Coastguard Worker   }
1784*e5436536SAndroid Build Coastguard Worker 
1785*e5436536SAndroid Build Coastguard Worker   /* other switches */
1786*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrConfigData.useWaveCoding = params->useWaveCoding;
1787*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrConfigData.useParametricCoding = params->parametricCoding;
1788*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrConfigData.thresholdAmpResFF_m =
1789*e5436536SAndroid Build Coastguard Worker       params->threshold_AmpRes_FF_m;
1790*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrConfigData.thresholdAmpResFF_e =
1791*e5436536SAndroid Build Coastguard Worker       params->threshold_AmpRes_FF_e;
1792*e5436536SAndroid Build Coastguard Worker 
1793*e5436536SAndroid Build Coastguard Worker   /* init freq band table */
1794*e5436536SAndroid Build Coastguard Worker   if (updateFreqBandTable(&hSbrElement->sbrConfigData,
1795*e5436536SAndroid Build Coastguard Worker                           &hSbrElement->sbrHeaderData,
1796*e5436536SAndroid Build Coastguard Worker                           params->downSampleFactor)) {
1797*e5436536SAndroid Build Coastguard Worker     return (1);
1798*e5436536SAndroid Build Coastguard Worker   }
1799*e5436536SAndroid Build Coastguard Worker 
1800*e5436536SAndroid Build Coastguard Worker   /* now create envelope ext and QMF for each available channel */
1801*e5436536SAndroid Build Coastguard Worker   for (ch = 0; ch < hSbrElement->sbrConfigData.nChannels; ch++) {
1802*e5436536SAndroid Build Coastguard Worker     if (initEnvChannel(&hSbrElement->sbrConfigData, &hSbrElement->sbrHeaderData,
1803*e5436536SAndroid Build Coastguard Worker                        &hSbrElement->sbrChannel[ch]->hEnvChannel, params,
1804*e5436536SAndroid Build Coastguard Worker                        statesInitFlag, ch, dynamic_RAM)) {
1805*e5436536SAndroid Build Coastguard Worker       return (1);
1806*e5436536SAndroid Build Coastguard Worker     }
1807*e5436536SAndroid Build Coastguard Worker 
1808*e5436536SAndroid Build Coastguard Worker   } /* nChannels */
1809*e5436536SAndroid Build Coastguard Worker 
1810*e5436536SAndroid Build Coastguard Worker   /* reset and intialize analysis qmf */
1811*e5436536SAndroid Build Coastguard Worker   for (ch = 0; ch < ((hSbrElement->elInfo.fParametricStereo)
1812*e5436536SAndroid Build Coastguard Worker                          ? 2
1813*e5436536SAndroid Build Coastguard Worker                          : hSbrElement->sbrConfigData.nChannels);
1814*e5436536SAndroid Build Coastguard Worker        ch++) {
1815*e5436536SAndroid Build Coastguard Worker     int err;
1816*e5436536SAndroid Build Coastguard Worker     UINT qmfFlags =
1817*e5436536SAndroid Build Coastguard Worker         (hSbrElement->sbrConfigData.sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY)
1818*e5436536SAndroid Build Coastguard Worker             ? QMF_FLAG_CLDFB
1819*e5436536SAndroid Build Coastguard Worker             : 0;
1820*e5436536SAndroid Build Coastguard Worker     if (statesInitFlag)
1821*e5436536SAndroid Build Coastguard Worker       qmfFlags &= ~QMF_FLAG_KEEP_STATES;
1822*e5436536SAndroid Build Coastguard Worker     else
1823*e5436536SAndroid Build Coastguard Worker       qmfFlags |= QMF_FLAG_KEEP_STATES;
1824*e5436536SAndroid Build Coastguard Worker 
1825*e5436536SAndroid Build Coastguard Worker     err = qmfInitAnalysisFilterBank(
1826*e5436536SAndroid Build Coastguard Worker         hSbrElement->hQmfAnalysis[ch],
1827*e5436536SAndroid Build Coastguard Worker         (FIXP_QAS *)hSbrElement->hQmfAnalysis[ch]->FilterStates,
1828*e5436536SAndroid Build Coastguard Worker         hSbrElement->sbrConfigData.noQmfSlots,
1829*e5436536SAndroid Build Coastguard Worker         hSbrElement->sbrConfigData.noQmfBands,
1830*e5436536SAndroid Build Coastguard Worker         hSbrElement->sbrConfigData.noQmfBands,
1831*e5436536SAndroid Build Coastguard Worker         hSbrElement->sbrConfigData.noQmfBands, qmfFlags);
1832*e5436536SAndroid Build Coastguard Worker     if (0 != err) {
1833*e5436536SAndroid Build Coastguard Worker       return err;
1834*e5436536SAndroid Build Coastguard Worker     }
1835*e5436536SAndroid Build Coastguard Worker   }
1836*e5436536SAndroid Build Coastguard Worker 
1837*e5436536SAndroid Build Coastguard Worker   /*  */
1838*e5436536SAndroid Build Coastguard Worker   hSbrElement->CmonData.xOverFreq = hSbrElement->sbrConfigData.xOverFreq;
1839*e5436536SAndroid Build Coastguard Worker   hSbrElement->CmonData.dynBwEnabled =
1840*e5436536SAndroid Build Coastguard Worker       (params->dynBwSupported && params->dynBwEnabled);
1841*e5436536SAndroid Build Coastguard Worker   hSbrElement->CmonData.dynXOverFreqEnc =
1842*e5436536SAndroid Build Coastguard Worker       FDKsbrEnc_SbrGetXOverFreq(hSbrElement, hSbrElement->CmonData.xOverFreq);
1843*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < 5; i++)
1844*e5436536SAndroid Build Coastguard Worker     hSbrElement->dynXOverFreqDelay[i] = hSbrElement->CmonData.dynXOverFreqEnc;
1845*e5436536SAndroid Build Coastguard Worker   hSbrElement->CmonData.sbrNumChannels = hSbrElement->sbrConfigData.nChannels;
1846*e5436536SAndroid Build Coastguard Worker   hSbrElement->sbrConfigData.dynXOverFreq = hSbrElement->CmonData.xOverFreq;
1847*e5436536SAndroid Build Coastguard Worker 
1848*e5436536SAndroid Build Coastguard Worker   /* Update Bandwith to be passed to the core encoder */
1849*e5436536SAndroid Build Coastguard Worker   *coreBandWith = hSbrElement->CmonData.xOverFreq;
1850*e5436536SAndroid Build Coastguard Worker 
1851*e5436536SAndroid Build Coastguard Worker   return (0);
1852*e5436536SAndroid Build Coastguard Worker }
1853*e5436536SAndroid Build Coastguard Worker 
sbrEncoder_GetInBufferSize(int noChannels)1854*e5436536SAndroid Build Coastguard Worker INT sbrEncoder_GetInBufferSize(int noChannels) {
1855*e5436536SAndroid Build Coastguard Worker   INT temp;
1856*e5436536SAndroid Build Coastguard Worker 
1857*e5436536SAndroid Build Coastguard Worker   temp = (2048);
1858*e5436536SAndroid Build Coastguard Worker   temp += 1024 + MAX_SAMPLE_DELAY;
1859*e5436536SAndroid Build Coastguard Worker   temp *= noChannels;
1860*e5436536SAndroid Build Coastguard Worker   temp *= sizeof(INT_PCM);
1861*e5436536SAndroid Build Coastguard Worker   return temp;
1862*e5436536SAndroid Build Coastguard Worker }
1863*e5436536SAndroid Build Coastguard Worker 
1864*e5436536SAndroid Build Coastguard Worker /*
1865*e5436536SAndroid Build Coastguard Worker  * Encode Dummy SBR payload frames to fill the delay lines.
1866*e5436536SAndroid Build Coastguard Worker  */
FDKsbrEnc_DelayCompensation(HANDLE_SBR_ENCODER hEnvEnc,INT_PCM * timeBuffer,UINT timeBufferBufSize)1867*e5436536SAndroid Build Coastguard Worker static INT FDKsbrEnc_DelayCompensation(HANDLE_SBR_ENCODER hEnvEnc,
1868*e5436536SAndroid Build Coastguard Worker                                        INT_PCM *timeBuffer,
1869*e5436536SAndroid Build Coastguard Worker                                        UINT timeBufferBufSize) {
1870*e5436536SAndroid Build Coastguard Worker   int n, el;
1871*e5436536SAndroid Build Coastguard Worker 
1872*e5436536SAndroid Build Coastguard Worker   for (n = hEnvEnc->nBitstrDelay; n > 0; n--) {
1873*e5436536SAndroid Build Coastguard Worker     for (el = 0; el < hEnvEnc->noElements; el++) {
1874*e5436536SAndroid Build Coastguard Worker       if (FDKsbrEnc_EnvEncodeFrame(
1875*e5436536SAndroid Build Coastguard Worker               hEnvEnc, el,
1876*e5436536SAndroid Build Coastguard Worker               timeBuffer + hEnvEnc->downsampledOffset / hEnvEnc->nChannels,
1877*e5436536SAndroid Build Coastguard Worker               timeBufferBufSize, NULL, NULL, 1))
1878*e5436536SAndroid Build Coastguard Worker         return -1;
1879*e5436536SAndroid Build Coastguard Worker     }
1880*e5436536SAndroid Build Coastguard Worker     sbrEncoder_UpdateBuffers(hEnvEnc, timeBuffer, timeBufferBufSize);
1881*e5436536SAndroid Build Coastguard Worker   }
1882*e5436536SAndroid Build Coastguard Worker   return 0;
1883*e5436536SAndroid Build Coastguard Worker }
1884*e5436536SAndroid Build Coastguard Worker 
sbrEncoder_LimitBitRate(UINT bitRate,UINT numChannels,UINT coreSampleRate,AUDIO_OBJECT_TYPE aot)1885*e5436536SAndroid Build Coastguard Worker UINT sbrEncoder_LimitBitRate(UINT bitRate, UINT numChannels,
1886*e5436536SAndroid Build Coastguard Worker                              UINT coreSampleRate, AUDIO_OBJECT_TYPE aot) {
1887*e5436536SAndroid Build Coastguard Worker   UINT newBitRate = bitRate;
1888*e5436536SAndroid Build Coastguard Worker   INT index;
1889*e5436536SAndroid Build Coastguard Worker 
1890*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(numChannels > 0 && numChannels <= 2);
1891*e5436536SAndroid Build Coastguard Worker   if (aot == AOT_PS) {
1892*e5436536SAndroid Build Coastguard Worker     if (numChannels == 1) {
1893*e5436536SAndroid Build Coastguard Worker       index = getPsTuningTableIndex(bitRate, &newBitRate);
1894*e5436536SAndroid Build Coastguard Worker       if (index == INVALID_TABLE_IDX) {
1895*e5436536SAndroid Build Coastguard Worker         bitRate = newBitRate;
1896*e5436536SAndroid Build Coastguard Worker       }
1897*e5436536SAndroid Build Coastguard Worker     } else {
1898*e5436536SAndroid Build Coastguard Worker       return 0;
1899*e5436536SAndroid Build Coastguard Worker     }
1900*e5436536SAndroid Build Coastguard Worker   }
1901*e5436536SAndroid Build Coastguard Worker   index = getSbrTuningTableIndex(bitRate, numChannels, coreSampleRate, aot,
1902*e5436536SAndroid Build Coastguard Worker                                  &newBitRate);
1903*e5436536SAndroid Build Coastguard Worker   if (index != INVALID_TABLE_IDX) {
1904*e5436536SAndroid Build Coastguard Worker     newBitRate = bitRate;
1905*e5436536SAndroid Build Coastguard Worker   }
1906*e5436536SAndroid Build Coastguard Worker 
1907*e5436536SAndroid Build Coastguard Worker   return newBitRate;
1908*e5436536SAndroid Build Coastguard Worker }
1909*e5436536SAndroid Build Coastguard Worker 
sbrEncoder_IsSingleRatePossible(AUDIO_OBJECT_TYPE aot)1910*e5436536SAndroid Build Coastguard Worker UINT sbrEncoder_IsSingleRatePossible(AUDIO_OBJECT_TYPE aot) {
1911*e5436536SAndroid Build Coastguard Worker   UINT isPossible = (AOT_PS == aot) ? 0 : 1;
1912*e5436536SAndroid Build Coastguard Worker   return isPossible;
1913*e5436536SAndroid Build Coastguard Worker }
1914*e5436536SAndroid Build Coastguard Worker 
1915*e5436536SAndroid Build Coastguard Worker /*****************************************************************************/
1916*e5436536SAndroid Build Coastguard Worker /*                                                                           */
1917*e5436536SAndroid Build Coastguard Worker /*functionname: sbrEncoder_Init_delay                                        */
1918*e5436536SAndroid Build Coastguard Worker /*description:  Determine Delay balancing and new encoder delay              */
1919*e5436536SAndroid Build Coastguard Worker /*                                                                           */
1920*e5436536SAndroid Build Coastguard Worker /*returns:      - error status                                               */
1921*e5436536SAndroid Build Coastguard Worker /*input:        - frame length of the core (i.e. e.g. AAC)                   */
1922*e5436536SAndroid Build Coastguard Worker /*              - number of channels                                         */
1923*e5436536SAndroid Build Coastguard Worker /*              - downsample factor (1 for downsampled, 2 for dual-rate SBR) */
1924*e5436536SAndroid Build Coastguard Worker /*              - low delay presence                                         */
1925*e5436536SAndroid Build Coastguard Worker /*              - ps presence                                                */
1926*e5436536SAndroid Build Coastguard Worker /*              - downsampling method: QMF-, time domain or no downsampling  */
1927*e5436536SAndroid Build Coastguard Worker /*              - various delay values (see DELAY_PARAM struct description)  */
1928*e5436536SAndroid Build Coastguard Worker /*                                                                           */
1929*e5436536SAndroid Build Coastguard Worker /*Example: Delay balancing for a HE-AACv1 encoder (time-domain downsampling) */
1930*e5436536SAndroid Build Coastguard Worker /*========================================================================== */
1931*e5436536SAndroid Build Coastguard Worker /*                                                                           */
1932*e5436536SAndroid Build Coastguard Worker /*    +--------+            +--------+ +--------+ +--------+ +--------+      */
1933*e5436536SAndroid Build Coastguard Worker /*    |core    |            |ds 2:1  | |AAC     | |QMF     | |QMF     |      */
1934*e5436536SAndroid Build Coastguard Worker /*  +-+path    +------------+        +-+core    +-+analysis+-+overlap +-+    */
1935*e5436536SAndroid Build Coastguard Worker /*  | |offset  |            |        | |        | |32 bands| |        | |    */
1936*e5436536SAndroid Build Coastguard Worker /*  | +--------+            +--------+ +--------+ +--------+ +--------+ |    */
1937*e5436536SAndroid Build Coastguard Worker /*  |                              core path                    +-------++   */
1938*e5436536SAndroid Build Coastguard Worker /*  |                                                           |QMF     |   */
1939*e5436536SAndroid Build Coastguard Worker /*->+                                                           +synth.  +-> */
1940*e5436536SAndroid Build Coastguard Worker /*  |                                                           |64 bands|   */
1941*e5436536SAndroid Build Coastguard Worker /*  |                                                           +-------++   */
1942*e5436536SAndroid Build Coastguard Worker /*  | +--------+ +--------+ +--------+ +--------+                       |    */
1943*e5436536SAndroid Build Coastguard Worker /*  | |SBR path| |QMF     | |subband | |bs delay|                       |    */
1944*e5436536SAndroid Build Coastguard Worker /*  +-+offset  +-+analysis+-+sample  +-+(full   +-----------------------+    */
1945*e5436536SAndroid Build Coastguard Worker /*    |        | |64 bands| |buffer  | | frames)|                            */
1946*e5436536SAndroid Build Coastguard Worker /*    +--------+ +--------+ +--------+ +--------+                            */
1947*e5436536SAndroid Build Coastguard Worker /*                                 SBR path                                  */
1948*e5436536SAndroid Build Coastguard Worker /*                                                                           */
1949*e5436536SAndroid Build Coastguard Worker /*****************************************************************************/
sbrEncoder_Init_delay(const int coreFrameLength,const int numChannels,const int downSampleFactor,const int lowDelay,const int usePs,const int is212,const SBRENC_DS_TYPE downsamplingMethod,DELAY_PARAM * hDelayParam)1950*e5436536SAndroid Build Coastguard Worker static INT sbrEncoder_Init_delay(
1951*e5436536SAndroid Build Coastguard Worker     const int coreFrameLength,               /* input */
1952*e5436536SAndroid Build Coastguard Worker     const int numChannels,                   /* input */
1953*e5436536SAndroid Build Coastguard Worker     const int downSampleFactor,              /* input */
1954*e5436536SAndroid Build Coastguard Worker     const int lowDelay,                      /* input */
1955*e5436536SAndroid Build Coastguard Worker     const int usePs,                         /* input */
1956*e5436536SAndroid Build Coastguard Worker     const int is212,                         /* input */
1957*e5436536SAndroid Build Coastguard Worker     const SBRENC_DS_TYPE downsamplingMethod, /* input */
1958*e5436536SAndroid Build Coastguard Worker     DELAY_PARAM *hDelayParam                 /* input/output */
1959*e5436536SAndroid Build Coastguard Worker ) {
1960*e5436536SAndroid Build Coastguard Worker   int delayCorePath = 0;   /* delay in core path */
1961*e5436536SAndroid Build Coastguard Worker   int delaySbrPath = 0;    /* delay difference in QMF aka SBR path */
1962*e5436536SAndroid Build Coastguard Worker   int delayInput2Core = 0; /* delay from the input to the core */
1963*e5436536SAndroid Build Coastguard Worker   int delaySbrDec = 0;     /* delay of the decoder's SBR module */
1964*e5436536SAndroid Build Coastguard Worker 
1965*e5436536SAndroid Build Coastguard Worker   int delayCore = hDelayParam->delay; /* delay of the core */
1966*e5436536SAndroid Build Coastguard Worker 
1967*e5436536SAndroid Build Coastguard Worker   /* Added delay by the SBR delay initialization */
1968*e5436536SAndroid Build Coastguard Worker   int corePathOffset = 0; /* core path */
1969*e5436536SAndroid Build Coastguard Worker   int sbrPathOffset = 0;  /* sbr path */
1970*e5436536SAndroid Build Coastguard Worker   int bitstreamDelay = 0; /* sbr path, framewise */
1971*e5436536SAndroid Build Coastguard Worker 
1972*e5436536SAndroid Build Coastguard Worker   int flCore = coreFrameLength; /* core frame length */
1973*e5436536SAndroid Build Coastguard Worker 
1974*e5436536SAndroid Build Coastguard Worker   int returnValue = 0; /* return value - 0 means: no error */
1975*e5436536SAndroid Build Coastguard Worker 
1976*e5436536SAndroid Build Coastguard Worker   /* 1) Calculate actual delay  for core and SBR path */
1977*e5436536SAndroid Build Coastguard Worker   if (is212) {
1978*e5436536SAndroid Build Coastguard Worker     delayCorePath = DELAY_COREPATH_ELDv2SBR(flCore, downSampleFactor);
1979*e5436536SAndroid Build Coastguard Worker     delaySbrPath = DELAY_ELDv2SBR(flCore, downSampleFactor);
1980*e5436536SAndroid Build Coastguard Worker     delaySbrDec = ((flCore) / 2) * (downSampleFactor);
1981*e5436536SAndroid Build Coastguard Worker   } else if (lowDelay) {
1982*e5436536SAndroid Build Coastguard Worker     delayCorePath = DELAY_COREPATH_ELDSBR(flCore, downSampleFactor);
1983*e5436536SAndroid Build Coastguard Worker     delaySbrPath = DELAY_ELDSBR(flCore, downSampleFactor);
1984*e5436536SAndroid Build Coastguard Worker     delaySbrDec = DELAY_QMF_POSTPROC(downSampleFactor);
1985*e5436536SAndroid Build Coastguard Worker   } else if (usePs) {
1986*e5436536SAndroid Build Coastguard Worker     delayCorePath = DELAY_COREPATH_PS(flCore, downSampleFactor);
1987*e5436536SAndroid Build Coastguard Worker     delaySbrPath = DELAY_PS(flCore, downSampleFactor);
1988*e5436536SAndroid Build Coastguard Worker     delaySbrDec = DELAY_COREPATH_SBR(flCore, downSampleFactor);
1989*e5436536SAndroid Build Coastguard Worker   } else {
1990*e5436536SAndroid Build Coastguard Worker     delayCorePath = DELAY_COREPATH_SBR(flCore, downSampleFactor);
1991*e5436536SAndroid Build Coastguard Worker     delaySbrPath = DELAY_SBR(flCore, downSampleFactor);
1992*e5436536SAndroid Build Coastguard Worker     delaySbrDec = DELAY_COREPATH_SBR(flCore, downSampleFactor);
1993*e5436536SAndroid Build Coastguard Worker   }
1994*e5436536SAndroid Build Coastguard Worker   delayCorePath += delayCore * downSampleFactor;
1995*e5436536SAndroid Build Coastguard Worker   delayCorePath +=
1996*e5436536SAndroid Build Coastguard Worker       (downsamplingMethod == SBRENC_DS_TIME) ? hDelayParam->dsDelay : 0;
1997*e5436536SAndroid Build Coastguard Worker 
1998*e5436536SAndroid Build Coastguard Worker   /* 2) Manage coupling of paths */
1999*e5436536SAndroid Build Coastguard Worker   if (downsamplingMethod == SBRENC_DS_QMF && delayCorePath > delaySbrPath) {
2000*e5436536SAndroid Build Coastguard Worker     /* In case of QMF downsampling, both paths are coupled, i.e. the SBR path
2001*e5436536SAndroid Build Coastguard Worker        offset would be added to both the SBR path and to the core path
2002*e5436536SAndroid Build Coastguard Worker        as well, thus making it impossible to achieve delay balancing.
2003*e5436536SAndroid Build Coastguard Worker        To overcome that problem, a framewise delay is added to the SBR path
2004*e5436536SAndroid Build Coastguard Worker        first, until the overall delay of the core path is shorter than
2005*e5436536SAndroid Build Coastguard Worker        the delay of the SBR path. When this is achieved, the missing delay
2006*e5436536SAndroid Build Coastguard Worker        difference can be added as downsampled offset to the core path.
2007*e5436536SAndroid Build Coastguard Worker     */
2008*e5436536SAndroid Build Coastguard Worker     while (delayCorePath > delaySbrPath) {
2009*e5436536SAndroid Build Coastguard Worker       /* Add one frame delay to SBR path */
2010*e5436536SAndroid Build Coastguard Worker       delaySbrPath += flCore * downSampleFactor;
2011*e5436536SAndroid Build Coastguard Worker       bitstreamDelay += 1;
2012*e5436536SAndroid Build Coastguard Worker     }
2013*e5436536SAndroid Build Coastguard Worker   }
2014*e5436536SAndroid Build Coastguard Worker 
2015*e5436536SAndroid Build Coastguard Worker   /* 3) Calculate necessary additional delay to balance the paths */
2016*e5436536SAndroid Build Coastguard Worker   if (delayCorePath > delaySbrPath) {
2017*e5436536SAndroid Build Coastguard Worker     /* Delay QMF input */
2018*e5436536SAndroid Build Coastguard Worker     while (delayCorePath > delaySbrPath + (int)flCore * (int)downSampleFactor) {
2019*e5436536SAndroid Build Coastguard Worker       /* Do bitstream frame-wise delay balancing if there are
2020*e5436536SAndroid Build Coastguard Worker          more than SBR framelength samples delay difference */
2021*e5436536SAndroid Build Coastguard Worker       delaySbrPath += flCore * downSampleFactor;
2022*e5436536SAndroid Build Coastguard Worker       bitstreamDelay += 1;
2023*e5436536SAndroid Build Coastguard Worker     }
2024*e5436536SAndroid Build Coastguard Worker     /* Multiply input offset by input channels */
2025*e5436536SAndroid Build Coastguard Worker     corePathOffset = 0;
2026*e5436536SAndroid Build Coastguard Worker     sbrPathOffset = (delayCorePath - delaySbrPath) * numChannels;
2027*e5436536SAndroid Build Coastguard Worker   } else {
2028*e5436536SAndroid Build Coastguard Worker     /* Delay AAC data */
2029*e5436536SAndroid Build Coastguard Worker     /* Multiply downsampled offset by AAC core channels. Divide by 2 because of
2030*e5436536SAndroid Build Coastguard Worker        half samplerate of downsampled data. */
2031*e5436536SAndroid Build Coastguard Worker     corePathOffset = ((delaySbrPath - delayCorePath) * numChannels) >>
2032*e5436536SAndroid Build Coastguard Worker                      (downSampleFactor - 1);
2033*e5436536SAndroid Build Coastguard Worker     sbrPathOffset = 0;
2034*e5436536SAndroid Build Coastguard Worker   }
2035*e5436536SAndroid Build Coastguard Worker 
2036*e5436536SAndroid Build Coastguard Worker   /* 4) Calculate delay from input to core */
2037*e5436536SAndroid Build Coastguard Worker   if (usePs) {
2038*e5436536SAndroid Build Coastguard Worker     delayInput2Core =
2039*e5436536SAndroid Build Coastguard Worker         (DELAY_QMF_ANA(downSampleFactor) + DELAY_QMF_DS + DELAY_HYB_SYN) +
2040*e5436536SAndroid Build Coastguard Worker         (downSampleFactor * corePathOffset) + 1;
2041*e5436536SAndroid Build Coastguard Worker   } else if (downsamplingMethod == SBRENC_DS_TIME) {
2042*e5436536SAndroid Build Coastguard Worker     delayInput2Core = corePathOffset + hDelayParam->dsDelay;
2043*e5436536SAndroid Build Coastguard Worker   } else {
2044*e5436536SAndroid Build Coastguard Worker     delayInput2Core = corePathOffset;
2045*e5436536SAndroid Build Coastguard Worker   }
2046*e5436536SAndroid Build Coastguard Worker 
2047*e5436536SAndroid Build Coastguard Worker   /* 6) Set output parameters */
2048*e5436536SAndroid Build Coastguard Worker   hDelayParam->delay = FDKmax(delayCorePath, delaySbrPath); /* overall delay */
2049*e5436536SAndroid Build Coastguard Worker   hDelayParam->sbrDecDelay = delaySbrDec;         /* SBR decoder delay */
2050*e5436536SAndroid Build Coastguard Worker   hDelayParam->delayInput2Core = delayInput2Core; /* delay input - core */
2051*e5436536SAndroid Build Coastguard Worker   hDelayParam->bitstrDelay = bitstreamDelay;    /* bitstream delay, in frames */
2052*e5436536SAndroid Build Coastguard Worker   hDelayParam->corePathOffset = corePathOffset; /* offset added to core path */
2053*e5436536SAndroid Build Coastguard Worker   hDelayParam->sbrPathOffset = sbrPathOffset;   /* offset added to SBR path */
2054*e5436536SAndroid Build Coastguard Worker 
2055*e5436536SAndroid Build Coastguard Worker   return returnValue;
2056*e5436536SAndroid Build Coastguard Worker }
2057*e5436536SAndroid Build Coastguard Worker 
2058*e5436536SAndroid Build Coastguard Worker /*****************************************************************************
2059*e5436536SAndroid Build Coastguard Worker 
2060*e5436536SAndroid Build Coastguard Worker  functionname: sbrEncoder_Init
2061*e5436536SAndroid Build Coastguard Worker  description:  initializes the SBR encoder
2062*e5436536SAndroid Build Coastguard Worker  returns:      error status
2063*e5436536SAndroid Build Coastguard Worker 
2064*e5436536SAndroid Build Coastguard Worker *****************************************************************************/
sbrEncoder_Init(HANDLE_SBR_ENCODER hSbrEncoder,SBR_ELEMENT_INFO elInfo[(8)],int noElements,INT_PCM * inputBuffer,UINT inputBufferBufSize,INT * coreBandwidth,INT * inputBufferOffset,INT * numChannels,const UINT syntaxFlags,INT * coreSampleRate,UINT * downSampleFactor,INT * frameLength,AUDIO_OBJECT_TYPE aot,int * delay,int transformFactor,const int headerPeriod,ULONG statesInitFlag)2065*e5436536SAndroid Build Coastguard Worker INT sbrEncoder_Init(HANDLE_SBR_ENCODER hSbrEncoder,
2066*e5436536SAndroid Build Coastguard Worker                     SBR_ELEMENT_INFO elInfo[(8)], int noElements,
2067*e5436536SAndroid Build Coastguard Worker                     INT_PCM *inputBuffer, UINT inputBufferBufSize,
2068*e5436536SAndroid Build Coastguard Worker                     INT *coreBandwidth, INT *inputBufferOffset,
2069*e5436536SAndroid Build Coastguard Worker                     INT *numChannels, const UINT syntaxFlags,
2070*e5436536SAndroid Build Coastguard Worker                     INT *coreSampleRate, UINT *downSampleFactor,
2071*e5436536SAndroid Build Coastguard Worker                     INT *frameLength, AUDIO_OBJECT_TYPE aot, int *delay,
2072*e5436536SAndroid Build Coastguard Worker                     int transformFactor, const int headerPeriod,
2073*e5436536SAndroid Build Coastguard Worker                     ULONG statesInitFlag) {
2074*e5436536SAndroid Build Coastguard Worker   HANDLE_ERROR_INFO errorInfo = noError;
2075*e5436536SAndroid Build Coastguard Worker   sbrConfiguration sbrConfig[(8)];
2076*e5436536SAndroid Build Coastguard Worker   INT error = 0;
2077*e5436536SAndroid Build Coastguard Worker   INT lowestBandwidth;
2078*e5436536SAndroid Build Coastguard Worker   /* Save input parameters */
2079*e5436536SAndroid Build Coastguard Worker   INT inputSampleRate = *coreSampleRate;
2080*e5436536SAndroid Build Coastguard Worker   int coreFrameLength = *frameLength;
2081*e5436536SAndroid Build Coastguard Worker   int inputBandWidth = *coreBandwidth;
2082*e5436536SAndroid Build Coastguard Worker   int inputChannels = *numChannels;
2083*e5436536SAndroid Build Coastguard Worker 
2084*e5436536SAndroid Build Coastguard Worker   SBRENC_DS_TYPE downsamplingMethod = SBRENC_DS_NONE;
2085*e5436536SAndroid Build Coastguard Worker   int highestSbrStartFreq, highestSbrStopFreq;
2086*e5436536SAndroid Build Coastguard Worker   int lowDelay = 0;
2087*e5436536SAndroid Build Coastguard Worker   int usePs = 0;
2088*e5436536SAndroid Build Coastguard Worker   int is212 = 0;
2089*e5436536SAndroid Build Coastguard Worker 
2090*e5436536SAndroid Build Coastguard Worker   DELAY_PARAM delayParam;
2091*e5436536SAndroid Build Coastguard Worker 
2092*e5436536SAndroid Build Coastguard Worker   /* check whether SBR setting is available for the current encoder
2093*e5436536SAndroid Build Coastguard Worker    * configuration (bitrate, samplerate) */
2094*e5436536SAndroid Build Coastguard Worker   if (!sbrEncoder_IsSingleRatePossible(aot)) {
2095*e5436536SAndroid Build Coastguard Worker     *downSampleFactor = 2;
2096*e5436536SAndroid Build Coastguard Worker   }
2097*e5436536SAndroid Build Coastguard Worker 
2098*e5436536SAndroid Build Coastguard Worker   if (aot == AOT_PS) {
2099*e5436536SAndroid Build Coastguard Worker     usePs = 1;
2100*e5436536SAndroid Build Coastguard Worker   }
2101*e5436536SAndroid Build Coastguard Worker   if (aot == AOT_ER_AAC_ELD) {
2102*e5436536SAndroid Build Coastguard Worker     lowDelay = 1;
2103*e5436536SAndroid Build Coastguard Worker   } else if (aot == AOT_ER_AAC_LD) {
2104*e5436536SAndroid Build Coastguard Worker     error = 1;
2105*e5436536SAndroid Build Coastguard Worker     goto bail;
2106*e5436536SAndroid Build Coastguard Worker   }
2107*e5436536SAndroid Build Coastguard Worker 
2108*e5436536SAndroid Build Coastguard Worker   /* Parametric Stereo */
2109*e5436536SAndroid Build Coastguard Worker   if (usePs) {
2110*e5436536SAndroid Build Coastguard Worker     if (*numChannels == 2 && noElements == 1) {
2111*e5436536SAndroid Build Coastguard Worker       /* Override Element type in case of Parametric stereo */
2112*e5436536SAndroid Build Coastguard Worker       elInfo[0].elType = ID_SCE;
2113*e5436536SAndroid Build Coastguard Worker       elInfo[0].fParametricStereo = 1;
2114*e5436536SAndroid Build Coastguard Worker       elInfo[0].nChannelsInEl = 1;
2115*e5436536SAndroid Build Coastguard Worker       /* core encoder gets downmixed mono signal */
2116*e5436536SAndroid Build Coastguard Worker       *numChannels = 1;
2117*e5436536SAndroid Build Coastguard Worker     } else {
2118*e5436536SAndroid Build Coastguard Worker       error = 1;
2119*e5436536SAndroid Build Coastguard Worker       goto bail;
2120*e5436536SAndroid Build Coastguard Worker     }
2121*e5436536SAndroid Build Coastguard Worker   } /* usePs */
2122*e5436536SAndroid Build Coastguard Worker 
2123*e5436536SAndroid Build Coastguard Worker   /* set the core's sample rate */
2124*e5436536SAndroid Build Coastguard Worker   switch (*downSampleFactor) {
2125*e5436536SAndroid Build Coastguard Worker     case 1:
2126*e5436536SAndroid Build Coastguard Worker       *coreSampleRate = inputSampleRate;
2127*e5436536SAndroid Build Coastguard Worker       downsamplingMethod = SBRENC_DS_NONE;
2128*e5436536SAndroid Build Coastguard Worker       break;
2129*e5436536SAndroid Build Coastguard Worker     case 2:
2130*e5436536SAndroid Build Coastguard Worker       *coreSampleRate = inputSampleRate >> 1;
2131*e5436536SAndroid Build Coastguard Worker       downsamplingMethod = usePs ? SBRENC_DS_QMF : SBRENC_DS_TIME;
2132*e5436536SAndroid Build Coastguard Worker       break;
2133*e5436536SAndroid Build Coastguard Worker     default:
2134*e5436536SAndroid Build Coastguard Worker       *coreSampleRate = inputSampleRate >> 1;
2135*e5436536SAndroid Build Coastguard Worker       return 0; /* return error */
2136*e5436536SAndroid Build Coastguard Worker   }
2137*e5436536SAndroid Build Coastguard Worker 
2138*e5436536SAndroid Build Coastguard Worker   /* check whether SBR setting is available for the current encoder
2139*e5436536SAndroid Build Coastguard Worker    * configuration (bitrate, coreSampleRate) */
2140*e5436536SAndroid Build Coastguard Worker   {
2141*e5436536SAndroid Build Coastguard Worker     int el, coreEl;
2142*e5436536SAndroid Build Coastguard Worker 
2143*e5436536SAndroid Build Coastguard Worker     /* Check if every element config is feasible */
2144*e5436536SAndroid Build Coastguard Worker     for (coreEl = 0; coreEl < noElements; coreEl++) {
2145*e5436536SAndroid Build Coastguard Worker       /* SBR only handles SCE and CPE's */
2146*e5436536SAndroid Build Coastguard Worker       if (elInfo[coreEl].elType != ID_SCE && elInfo[coreEl].elType != ID_CPE) {
2147*e5436536SAndroid Build Coastguard Worker         continue;
2148*e5436536SAndroid Build Coastguard Worker       }
2149*e5436536SAndroid Build Coastguard Worker       /* check if desired configuration is available */
2150*e5436536SAndroid Build Coastguard Worker       if (!FDKsbrEnc_IsSbrSettingAvail(elInfo[coreEl].bitRate, 0,
2151*e5436536SAndroid Build Coastguard Worker                                        elInfo[coreEl].nChannelsInEl,
2152*e5436536SAndroid Build Coastguard Worker                                        inputSampleRate, *coreSampleRate, aot)) {
2153*e5436536SAndroid Build Coastguard Worker         error = 1;
2154*e5436536SAndroid Build Coastguard Worker         goto bail;
2155*e5436536SAndroid Build Coastguard Worker       }
2156*e5436536SAndroid Build Coastguard Worker     }
2157*e5436536SAndroid Build Coastguard Worker 
2158*e5436536SAndroid Build Coastguard Worker     hSbrEncoder->nChannels = *numChannels;
2159*e5436536SAndroid Build Coastguard Worker     hSbrEncoder->frameSize = coreFrameLength * *downSampleFactor;
2160*e5436536SAndroid Build Coastguard Worker     hSbrEncoder->downsamplingMethod = downsamplingMethod;
2161*e5436536SAndroid Build Coastguard Worker     hSbrEncoder->downSampleFactor = *downSampleFactor;
2162*e5436536SAndroid Build Coastguard Worker     hSbrEncoder->estimateBitrate = 0;
2163*e5436536SAndroid Build Coastguard Worker     hSbrEncoder->inputDataDelay = 0;
2164*e5436536SAndroid Build Coastguard Worker     is212 = ((aot == AOT_ER_AAC_ELD) && (syntaxFlags & AC_LD_MPS)) ? 1 : 0;
2165*e5436536SAndroid Build Coastguard Worker 
2166*e5436536SAndroid Build Coastguard Worker     /* Open SBR elements */
2167*e5436536SAndroid Build Coastguard Worker     el = -1;
2168*e5436536SAndroid Build Coastguard Worker     highestSbrStartFreq = highestSbrStopFreq = 0;
2169*e5436536SAndroid Build Coastguard Worker     lowestBandwidth = 99999;
2170*e5436536SAndroid Build Coastguard Worker 
2171*e5436536SAndroid Build Coastguard Worker     /* Loop through each core encoder element and get a matching SBR element
2172*e5436536SAndroid Build Coastguard Worker      * config */
2173*e5436536SAndroid Build Coastguard Worker     for (coreEl = 0; coreEl < noElements; coreEl++) {
2174*e5436536SAndroid Build Coastguard Worker       /* SBR only handles SCE and CPE's */
2175*e5436536SAndroid Build Coastguard Worker       if (elInfo[coreEl].elType == ID_SCE || elInfo[coreEl].elType == ID_CPE) {
2176*e5436536SAndroid Build Coastguard Worker         el++;
2177*e5436536SAndroid Build Coastguard Worker       } else {
2178*e5436536SAndroid Build Coastguard Worker         continue;
2179*e5436536SAndroid Build Coastguard Worker       }
2180*e5436536SAndroid Build Coastguard Worker 
2181*e5436536SAndroid Build Coastguard Worker       /* Set parametric Stereo Flag. */
2182*e5436536SAndroid Build Coastguard Worker       if (usePs) {
2183*e5436536SAndroid Build Coastguard Worker         elInfo[coreEl].fParametricStereo = 1;
2184*e5436536SAndroid Build Coastguard Worker       } else {
2185*e5436536SAndroid Build Coastguard Worker         elInfo[coreEl].fParametricStereo = 0;
2186*e5436536SAndroid Build Coastguard Worker       }
2187*e5436536SAndroid Build Coastguard Worker 
2188*e5436536SAndroid Build Coastguard Worker       /*
2189*e5436536SAndroid Build Coastguard Worker        * Init sbrConfig structure
2190*e5436536SAndroid Build Coastguard Worker        */
2191*e5436536SAndroid Build Coastguard Worker       if (!FDKsbrEnc_InitializeSbrDefaults(&sbrConfig[el], *downSampleFactor,
2192*e5436536SAndroid Build Coastguard Worker                                            coreFrameLength, IS_LOWDELAY(aot))) {
2193*e5436536SAndroid Build Coastguard Worker         error = 1;
2194*e5436536SAndroid Build Coastguard Worker         goto bail;
2195*e5436536SAndroid Build Coastguard Worker       }
2196*e5436536SAndroid Build Coastguard Worker 
2197*e5436536SAndroid Build Coastguard Worker       /*
2198*e5436536SAndroid Build Coastguard Worker        * Modify sbrConfig structure according to Element parameters
2199*e5436536SAndroid Build Coastguard Worker        */
2200*e5436536SAndroid Build Coastguard Worker       if (!FDKsbrEnc_AdjustSbrSettings(
2201*e5436536SAndroid Build Coastguard Worker               &sbrConfig[el], elInfo[coreEl].bitRate,
2202*e5436536SAndroid Build Coastguard Worker               elInfo[coreEl].nChannelsInEl, *coreSampleRate, inputSampleRate,
2203*e5436536SAndroid Build Coastguard Worker               transformFactor, 24000, 0, 0, /* useSpeechConfig */
2204*e5436536SAndroid Build Coastguard Worker               0,                            /* lcsMode */
2205*e5436536SAndroid Build Coastguard Worker               usePs,                        /* bParametricStereo */
2206*e5436536SAndroid Build Coastguard Worker               aot)) {
2207*e5436536SAndroid Build Coastguard Worker         error = 1;
2208*e5436536SAndroid Build Coastguard Worker         goto bail;
2209*e5436536SAndroid Build Coastguard Worker       }
2210*e5436536SAndroid Build Coastguard Worker 
2211*e5436536SAndroid Build Coastguard Worker       /* Find common frequency border for all SBR elements */
2212*e5436536SAndroid Build Coastguard Worker       highestSbrStartFreq =
2213*e5436536SAndroid Build Coastguard Worker           fixMax(highestSbrStartFreq, sbrConfig[el].startFreq);
2214*e5436536SAndroid Build Coastguard Worker       highestSbrStopFreq = fixMax(highestSbrStopFreq, sbrConfig[el].stopFreq);
2215*e5436536SAndroid Build Coastguard Worker 
2216*e5436536SAndroid Build Coastguard Worker     } /* first element loop */
2217*e5436536SAndroid Build Coastguard Worker 
2218*e5436536SAndroid Build Coastguard Worker     /* Set element count (can be less than core encoder element count) */
2219*e5436536SAndroid Build Coastguard Worker     hSbrEncoder->noElements = el + 1;
2220*e5436536SAndroid Build Coastguard Worker 
2221*e5436536SAndroid Build Coastguard Worker     FDKsbrEnc_Reallocate(hSbrEncoder, elInfo, noElements);
2222*e5436536SAndroid Build Coastguard Worker 
2223*e5436536SAndroid Build Coastguard Worker     for (el = 0; el < hSbrEncoder->noElements; el++) {
2224*e5436536SAndroid Build Coastguard Worker       int bandwidth = *coreBandwidth;
2225*e5436536SAndroid Build Coastguard Worker 
2226*e5436536SAndroid Build Coastguard Worker       /* Use lowest common bandwidth */
2227*e5436536SAndroid Build Coastguard Worker       sbrConfig[el].startFreq = highestSbrStartFreq;
2228*e5436536SAndroid Build Coastguard Worker       sbrConfig[el].stopFreq = highestSbrStopFreq;
2229*e5436536SAndroid Build Coastguard Worker 
2230*e5436536SAndroid Build Coastguard Worker       /* initialize SBR element, and get core bandwidth */
2231*e5436536SAndroid Build Coastguard Worker       error = FDKsbrEnc_EnvInit(hSbrEncoder->sbrElement[el], &sbrConfig[el],
2232*e5436536SAndroid Build Coastguard Worker                                 &bandwidth, aot, el, headerPeriod,
2233*e5436536SAndroid Build Coastguard Worker                                 statesInitFlag, hSbrEncoder->downsamplingMethod,
2234*e5436536SAndroid Build Coastguard Worker                                 hSbrEncoder->dynamicRam);
2235*e5436536SAndroid Build Coastguard Worker 
2236*e5436536SAndroid Build Coastguard Worker       if (error != 0) {
2237*e5436536SAndroid Build Coastguard Worker         error = 2;
2238*e5436536SAndroid Build Coastguard Worker         goto bail;
2239*e5436536SAndroid Build Coastguard Worker       }
2240*e5436536SAndroid Build Coastguard Worker 
2241*e5436536SAndroid Build Coastguard Worker       /* Get lowest core encoder bandwidth to be returned later. */
2242*e5436536SAndroid Build Coastguard Worker       lowestBandwidth = fixMin(lowestBandwidth, bandwidth);
2243*e5436536SAndroid Build Coastguard Worker 
2244*e5436536SAndroid Build Coastguard Worker     } /* second element loop */
2245*e5436536SAndroid Build Coastguard Worker 
2246*e5436536SAndroid Build Coastguard Worker     /* Initialize a downsampler for each channel in each SBR element */
2247*e5436536SAndroid Build Coastguard Worker     if (hSbrEncoder->downsamplingMethod == SBRENC_DS_TIME) {
2248*e5436536SAndroid Build Coastguard Worker       for (el = 0; el < hSbrEncoder->noElements; el++) {
2249*e5436536SAndroid Build Coastguard Worker         HANDLE_SBR_ELEMENT hSbrEl = hSbrEncoder->sbrElement[el];
2250*e5436536SAndroid Build Coastguard Worker         INT Wc, ch;
2251*e5436536SAndroid Build Coastguard Worker 
2252*e5436536SAndroid Build Coastguard Worker         Wc = 500; /* Cutoff frequency with full bandwidth */
2253*e5436536SAndroid Build Coastguard Worker 
2254*e5436536SAndroid Build Coastguard Worker         for (ch = 0; ch < hSbrEl->elInfo.nChannelsInEl; ch++) {
2255*e5436536SAndroid Build Coastguard Worker           FDKaacEnc_InitDownsampler(&hSbrEl->sbrChannel[ch]->downSampler, Wc,
2256*e5436536SAndroid Build Coastguard Worker                                     *downSampleFactor);
2257*e5436536SAndroid Build Coastguard Worker           FDK_ASSERT(hSbrEl->sbrChannel[ch]->downSampler.delay <=
2258*e5436536SAndroid Build Coastguard Worker                      MAX_DS_FILTER_DELAY);
2259*e5436536SAndroid Build Coastguard Worker         }
2260*e5436536SAndroid Build Coastguard Worker       } /* third element loop */
2261*e5436536SAndroid Build Coastguard Worker 
2262*e5436536SAndroid Build Coastguard Worker       /* lfe */
2263*e5436536SAndroid Build Coastguard Worker       FDKaacEnc_InitDownsampler(&hSbrEncoder->lfeDownSampler, 0,
2264*e5436536SAndroid Build Coastguard Worker                                 *downSampleFactor);
2265*e5436536SAndroid Build Coastguard Worker     }
2266*e5436536SAndroid Build Coastguard Worker 
2267*e5436536SAndroid Build Coastguard Worker     /* Get delay information */
2268*e5436536SAndroid Build Coastguard Worker     delayParam.dsDelay =
2269*e5436536SAndroid Build Coastguard Worker         hSbrEncoder->sbrElement[0]->sbrChannel[0]->downSampler.delay;
2270*e5436536SAndroid Build Coastguard Worker     delayParam.delay = *delay;
2271*e5436536SAndroid Build Coastguard Worker 
2272*e5436536SAndroid Build Coastguard Worker     error = sbrEncoder_Init_delay(coreFrameLength, *numChannels,
2273*e5436536SAndroid Build Coastguard Worker                                   *downSampleFactor, lowDelay, usePs, is212,
2274*e5436536SAndroid Build Coastguard Worker                                   downsamplingMethod, &delayParam);
2275*e5436536SAndroid Build Coastguard Worker 
2276*e5436536SAndroid Build Coastguard Worker     if (error != 0) {
2277*e5436536SAndroid Build Coastguard Worker       error = 3;
2278*e5436536SAndroid Build Coastguard Worker       goto bail;
2279*e5436536SAndroid Build Coastguard Worker     }
2280*e5436536SAndroid Build Coastguard Worker 
2281*e5436536SAndroid Build Coastguard Worker     hSbrEncoder->nBitstrDelay = delayParam.bitstrDelay;
2282*e5436536SAndroid Build Coastguard Worker     hSbrEncoder->sbrDecDelay = delayParam.sbrDecDelay;
2283*e5436536SAndroid Build Coastguard Worker     hSbrEncoder->inputDataDelay = delayParam.delayInput2Core;
2284*e5436536SAndroid Build Coastguard Worker 
2285*e5436536SAndroid Build Coastguard Worker     /* Assign core encoder Bandwidth */
2286*e5436536SAndroid Build Coastguard Worker     *coreBandwidth = lowestBandwidth;
2287*e5436536SAndroid Build Coastguard Worker 
2288*e5436536SAndroid Build Coastguard Worker     /* Estimate sbr bitrate, 2.5 kBit/s per sbr channel */
2289*e5436536SAndroid Build Coastguard Worker     hSbrEncoder->estimateBitrate += 2500 * (*numChannels);
2290*e5436536SAndroid Build Coastguard Worker 
2291*e5436536SAndroid Build Coastguard Worker     /* Initialize bitstream buffer for each element */
2292*e5436536SAndroid Build Coastguard Worker     for (el = 0; el < hSbrEncoder->noElements; el++) {
2293*e5436536SAndroid Build Coastguard Worker       FDKsbrEnc_bsBufInit(hSbrEncoder->sbrElement[el], delayParam.bitstrDelay);
2294*e5436536SAndroid Build Coastguard Worker     }
2295*e5436536SAndroid Build Coastguard Worker 
2296*e5436536SAndroid Build Coastguard Worker     /* initialize parametric stereo */
2297*e5436536SAndroid Build Coastguard Worker     if (usePs) {
2298*e5436536SAndroid Build Coastguard Worker       PSENC_CONFIG psEncConfig;
2299*e5436536SAndroid Build Coastguard Worker       FDK_ASSERT(hSbrEncoder->noElements == 1);
2300*e5436536SAndroid Build Coastguard Worker       INT psTuningTableIdx = getPsTuningTableIndex(elInfo[0].bitRate, NULL);
2301*e5436536SAndroid Build Coastguard Worker 
2302*e5436536SAndroid Build Coastguard Worker       psEncConfig.frameSize = coreFrameLength;  // sbrConfig.sbrFrameSize;
2303*e5436536SAndroid Build Coastguard Worker       psEncConfig.qmfFilterMode = 0;
2304*e5436536SAndroid Build Coastguard Worker       psEncConfig.sbrPsDelay = 0;
2305*e5436536SAndroid Build Coastguard Worker 
2306*e5436536SAndroid Build Coastguard Worker       /* tuning parameters */
2307*e5436536SAndroid Build Coastguard Worker       if (psTuningTableIdx != INVALID_TABLE_IDX) {
2308*e5436536SAndroid Build Coastguard Worker         psEncConfig.nStereoBands = psTuningTable[psTuningTableIdx].nStereoBands;
2309*e5436536SAndroid Build Coastguard Worker         psEncConfig.maxEnvelopes = psTuningTable[psTuningTableIdx].nEnvelopes;
2310*e5436536SAndroid Build Coastguard Worker         psEncConfig.iidQuantErrorThreshold =
2311*e5436536SAndroid Build Coastguard Worker             (FIXP_DBL)psTuningTable[psTuningTableIdx].iidQuantErrorThreshold;
2312*e5436536SAndroid Build Coastguard Worker 
2313*e5436536SAndroid Build Coastguard Worker         /* calculation is not quite linear, increased number of envelopes causes
2314*e5436536SAndroid Build Coastguard Worker          * more bits */
2315*e5436536SAndroid Build Coastguard Worker         /* assume avg. 50 bits per frame for 10 stereo bands / 1 envelope
2316*e5436536SAndroid Build Coastguard Worker          * configuration */
2317*e5436536SAndroid Build Coastguard Worker         hSbrEncoder->estimateBitrate +=
2318*e5436536SAndroid Build Coastguard Worker             ((((*coreSampleRate) * 5 * psEncConfig.nStereoBands *
2319*e5436536SAndroid Build Coastguard Worker                psEncConfig.maxEnvelopes) /
2320*e5436536SAndroid Build Coastguard Worker               hSbrEncoder->frameSize));
2321*e5436536SAndroid Build Coastguard Worker 
2322*e5436536SAndroid Build Coastguard Worker       } else {
2323*e5436536SAndroid Build Coastguard Worker         error = ERROR(CDI, "Invalid ps tuning table index.");
2324*e5436536SAndroid Build Coastguard Worker         goto bail;
2325*e5436536SAndroid Build Coastguard Worker       }
2326*e5436536SAndroid Build Coastguard Worker 
2327*e5436536SAndroid Build Coastguard Worker       qmfInitSynthesisFilterBank(
2328*e5436536SAndroid Build Coastguard Worker           &hSbrEncoder->qmfSynthesisPS,
2329*e5436536SAndroid Build Coastguard Worker           (FIXP_DBL *)hSbrEncoder->qmfSynthesisPS.FilterStates,
2330*e5436536SAndroid Build Coastguard Worker           hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfSlots,
2331*e5436536SAndroid Build Coastguard Worker           hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfBands >> 1,
2332*e5436536SAndroid Build Coastguard Worker           hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfBands >> 1,
2333*e5436536SAndroid Build Coastguard Worker           hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfBands >> 1,
2334*e5436536SAndroid Build Coastguard Worker           (statesInitFlag) ? 0 : QMF_FLAG_KEEP_STATES);
2335*e5436536SAndroid Build Coastguard Worker 
2336*e5436536SAndroid Build Coastguard Worker       if (errorInfo == noError) {
2337*e5436536SAndroid Build Coastguard Worker         /* update delay */
2338*e5436536SAndroid Build Coastguard Worker         psEncConfig.sbrPsDelay =
2339*e5436536SAndroid Build Coastguard Worker             FDKsbrEnc_GetEnvEstDelay(&hSbrEncoder->sbrElement[0]
2340*e5436536SAndroid Build Coastguard Worker                                           ->sbrChannel[0]
2341*e5436536SAndroid Build Coastguard Worker                                           ->hEnvChannel.sbrExtractEnvelope);
2342*e5436536SAndroid Build Coastguard Worker 
2343*e5436536SAndroid Build Coastguard Worker         errorInfo =
2344*e5436536SAndroid Build Coastguard Worker             PSEnc_Init(hSbrEncoder->hParametricStereo, &psEncConfig,
2345*e5436536SAndroid Build Coastguard Worker                        hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfSlots,
2346*e5436536SAndroid Build Coastguard Worker                        hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfBands,
2347*e5436536SAndroid Build Coastguard Worker                        hSbrEncoder->dynamicRam);
2348*e5436536SAndroid Build Coastguard Worker       }
2349*e5436536SAndroid Build Coastguard Worker     }
2350*e5436536SAndroid Build Coastguard Worker 
2351*e5436536SAndroid Build Coastguard Worker     hSbrEncoder->downsampledOffset = delayParam.corePathOffset;
2352*e5436536SAndroid Build Coastguard Worker     hSbrEncoder->bufferOffset = delayParam.sbrPathOffset;
2353*e5436536SAndroid Build Coastguard Worker     *delay = delayParam.delay;
2354*e5436536SAndroid Build Coastguard Worker 
2355*e5436536SAndroid Build Coastguard Worker     { hSbrEncoder->downmixSize = coreFrameLength * (*numChannels); }
2356*e5436536SAndroid Build Coastguard Worker 
2357*e5436536SAndroid Build Coastguard Worker     /* Delay Compensation: fill bitstream delay buffer with zero input signal */
2358*e5436536SAndroid Build Coastguard Worker     if (hSbrEncoder->nBitstrDelay > 0) {
2359*e5436536SAndroid Build Coastguard Worker       error = FDKsbrEnc_DelayCompensation(hSbrEncoder, inputBuffer,
2360*e5436536SAndroid Build Coastguard Worker                                           inputBufferBufSize);
2361*e5436536SAndroid Build Coastguard Worker       if (error != 0) goto bail;
2362*e5436536SAndroid Build Coastguard Worker     }
2363*e5436536SAndroid Build Coastguard Worker 
2364*e5436536SAndroid Build Coastguard Worker     /* Set Output frame length */
2365*e5436536SAndroid Build Coastguard Worker     *frameLength = coreFrameLength * *downSampleFactor;
2366*e5436536SAndroid Build Coastguard Worker     /* Input buffer offset */
2367*e5436536SAndroid Build Coastguard Worker     *inputBufferOffset =
2368*e5436536SAndroid Build Coastguard Worker         fixMax(delayParam.sbrPathOffset, delayParam.corePathOffset);
2369*e5436536SAndroid Build Coastguard Worker   }
2370*e5436536SAndroid Build Coastguard Worker 
2371*e5436536SAndroid Build Coastguard Worker   return error;
2372*e5436536SAndroid Build Coastguard Worker 
2373*e5436536SAndroid Build Coastguard Worker bail:
2374*e5436536SAndroid Build Coastguard Worker   /* Restore input settings */
2375*e5436536SAndroid Build Coastguard Worker   *coreSampleRate = inputSampleRate;
2376*e5436536SAndroid Build Coastguard Worker   *frameLength = coreFrameLength;
2377*e5436536SAndroid Build Coastguard Worker   *numChannels = inputChannels;
2378*e5436536SAndroid Build Coastguard Worker   *coreBandwidth = inputBandWidth;
2379*e5436536SAndroid Build Coastguard Worker 
2380*e5436536SAndroid Build Coastguard Worker   return error;
2381*e5436536SAndroid Build Coastguard Worker }
2382*e5436536SAndroid Build Coastguard Worker 
sbrEncoder_EncodeFrame(HANDLE_SBR_ENCODER hSbrEncoder,INT_PCM * samples,UINT samplesBufSize,UINT sbrDataBits[(8)],UCHAR sbrData[(8)][MAX_PAYLOAD_SIZE])2383*e5436536SAndroid Build Coastguard Worker INT sbrEncoder_EncodeFrame(HANDLE_SBR_ENCODER hSbrEncoder, INT_PCM *samples,
2384*e5436536SAndroid Build Coastguard Worker                            UINT samplesBufSize, UINT sbrDataBits[(8)],
2385*e5436536SAndroid Build Coastguard Worker                            UCHAR sbrData[(8)][MAX_PAYLOAD_SIZE]) {
2386*e5436536SAndroid Build Coastguard Worker   INT error;
2387*e5436536SAndroid Build Coastguard Worker   int el;
2388*e5436536SAndroid Build Coastguard Worker 
2389*e5436536SAndroid Build Coastguard Worker   for (el = 0; el < hSbrEncoder->noElements; el++) {
2390*e5436536SAndroid Build Coastguard Worker     if (hSbrEncoder->sbrElement[el] != NULL) {
2391*e5436536SAndroid Build Coastguard Worker       error = FDKsbrEnc_EnvEncodeFrame(
2392*e5436536SAndroid Build Coastguard Worker           hSbrEncoder, el,
2393*e5436536SAndroid Build Coastguard Worker           samples + hSbrEncoder->downsampledOffset / hSbrEncoder->nChannels,
2394*e5436536SAndroid Build Coastguard Worker           samplesBufSize, &sbrDataBits[el], sbrData[el], 0);
2395*e5436536SAndroid Build Coastguard Worker       if (error) return error;
2396*e5436536SAndroid Build Coastguard Worker     }
2397*e5436536SAndroid Build Coastguard Worker   }
2398*e5436536SAndroid Build Coastguard Worker 
2399*e5436536SAndroid Build Coastguard Worker   error = FDKsbrEnc_Downsample(
2400*e5436536SAndroid Build Coastguard Worker       hSbrEncoder,
2401*e5436536SAndroid Build Coastguard Worker       samples + hSbrEncoder->downsampledOffset / hSbrEncoder->nChannels,
2402*e5436536SAndroid Build Coastguard Worker       samplesBufSize, hSbrEncoder->nChannels, &sbrDataBits[el], sbrData[el], 0);
2403*e5436536SAndroid Build Coastguard Worker   if (error) return error;
2404*e5436536SAndroid Build Coastguard Worker 
2405*e5436536SAndroid Build Coastguard Worker   return 0;
2406*e5436536SAndroid Build Coastguard Worker }
2407*e5436536SAndroid Build Coastguard Worker 
sbrEncoder_UpdateBuffers(HANDLE_SBR_ENCODER hSbrEncoder,INT_PCM * timeBuffer,UINT timeBufferBufSize)2408*e5436536SAndroid Build Coastguard Worker INT sbrEncoder_UpdateBuffers(HANDLE_SBR_ENCODER hSbrEncoder,
2409*e5436536SAndroid Build Coastguard Worker                              INT_PCM *timeBuffer, UINT timeBufferBufSize) {
2410*e5436536SAndroid Build Coastguard Worker   if (hSbrEncoder->downsampledOffset > 0) {
2411*e5436536SAndroid Build Coastguard Worker     int c;
2412*e5436536SAndroid Build Coastguard Worker     int nd = hSbrEncoder->downmixSize / hSbrEncoder->nChannels;
2413*e5436536SAndroid Build Coastguard Worker 
2414*e5436536SAndroid Build Coastguard Worker     for (c = 0; c < hSbrEncoder->nChannels; c++) {
2415*e5436536SAndroid Build Coastguard Worker       /* Move delayed downsampled data */
2416*e5436536SAndroid Build Coastguard Worker       FDKmemcpy(timeBuffer + timeBufferBufSize * c,
2417*e5436536SAndroid Build Coastguard Worker                 timeBuffer + timeBufferBufSize * c + nd,
2418*e5436536SAndroid Build Coastguard Worker                 sizeof(INT_PCM) *
2419*e5436536SAndroid Build Coastguard Worker                     (hSbrEncoder->downsampledOffset / hSbrEncoder->nChannels));
2420*e5436536SAndroid Build Coastguard Worker     }
2421*e5436536SAndroid Build Coastguard Worker   } else {
2422*e5436536SAndroid Build Coastguard Worker     int c;
2423*e5436536SAndroid Build Coastguard Worker 
2424*e5436536SAndroid Build Coastguard Worker     for (c = 0; c < hSbrEncoder->nChannels; c++) {
2425*e5436536SAndroid Build Coastguard Worker       /* Move delayed input data */
2426*e5436536SAndroid Build Coastguard Worker       FDKmemcpy(
2427*e5436536SAndroid Build Coastguard Worker           timeBuffer + timeBufferBufSize * c,
2428*e5436536SAndroid Build Coastguard Worker           timeBuffer + timeBufferBufSize * c + hSbrEncoder->frameSize,
2429*e5436536SAndroid Build Coastguard Worker           sizeof(INT_PCM) * hSbrEncoder->bufferOffset / hSbrEncoder->nChannels);
2430*e5436536SAndroid Build Coastguard Worker     }
2431*e5436536SAndroid Build Coastguard Worker   }
2432*e5436536SAndroid Build Coastguard Worker   if (hSbrEncoder->nBitstrDelay > 0) {
2433*e5436536SAndroid Build Coastguard Worker     int el;
2434*e5436536SAndroid Build Coastguard Worker 
2435*e5436536SAndroid Build Coastguard Worker     for (el = 0; el < hSbrEncoder->noElements; el++) {
2436*e5436536SAndroid Build Coastguard Worker       FDKmemmove(
2437*e5436536SAndroid Build Coastguard Worker           hSbrEncoder->sbrElement[el]->payloadDelayLine[0],
2438*e5436536SAndroid Build Coastguard Worker           hSbrEncoder->sbrElement[el]->payloadDelayLine[1],
2439*e5436536SAndroid Build Coastguard Worker           sizeof(UCHAR) * (hSbrEncoder->nBitstrDelay * MAX_PAYLOAD_SIZE));
2440*e5436536SAndroid Build Coastguard Worker 
2441*e5436536SAndroid Build Coastguard Worker       FDKmemmove(&hSbrEncoder->sbrElement[el]->payloadDelayLineSize[0],
2442*e5436536SAndroid Build Coastguard Worker                  &hSbrEncoder->sbrElement[el]->payloadDelayLineSize[1],
2443*e5436536SAndroid Build Coastguard Worker                  sizeof(UINT) * (hSbrEncoder->nBitstrDelay));
2444*e5436536SAndroid Build Coastguard Worker     }
2445*e5436536SAndroid Build Coastguard Worker   }
2446*e5436536SAndroid Build Coastguard Worker   return 0;
2447*e5436536SAndroid Build Coastguard Worker }
2448*e5436536SAndroid Build Coastguard Worker 
sbrEncoder_SendHeader(HANDLE_SBR_ENCODER hSbrEncoder)2449*e5436536SAndroid Build Coastguard Worker INT sbrEncoder_SendHeader(HANDLE_SBR_ENCODER hSbrEncoder) {
2450*e5436536SAndroid Build Coastguard Worker   INT error = -1;
2451*e5436536SAndroid Build Coastguard Worker   if (hSbrEncoder) {
2452*e5436536SAndroid Build Coastguard Worker     int el;
2453*e5436536SAndroid Build Coastguard Worker     for (el = 0; el < hSbrEncoder->noElements; el++) {
2454*e5436536SAndroid Build Coastguard Worker       if ((hSbrEncoder->noElements == 1) &&
2455*e5436536SAndroid Build Coastguard Worker           (hSbrEncoder->sbrElement[0]->elInfo.fParametricStereo == 1)) {
2456*e5436536SAndroid Build Coastguard Worker         hSbrEncoder->sbrElement[el]->sbrBitstreamData.CountSendHeaderData =
2457*e5436536SAndroid Build Coastguard Worker             hSbrEncoder->sbrElement[el]->sbrBitstreamData.NrSendHeaderData - 1;
2458*e5436536SAndroid Build Coastguard Worker       } else {
2459*e5436536SAndroid Build Coastguard Worker         hSbrEncoder->sbrElement[el]->sbrBitstreamData.CountSendHeaderData = 0;
2460*e5436536SAndroid Build Coastguard Worker       }
2461*e5436536SAndroid Build Coastguard Worker     }
2462*e5436536SAndroid Build Coastguard Worker     error = 0;
2463*e5436536SAndroid Build Coastguard Worker   }
2464*e5436536SAndroid Build Coastguard Worker   return error;
2465*e5436536SAndroid Build Coastguard Worker }
2466*e5436536SAndroid Build Coastguard Worker 
sbrEncoder_ContainsHeader(HANDLE_SBR_ENCODER hSbrEncoder)2467*e5436536SAndroid Build Coastguard Worker INT sbrEncoder_ContainsHeader(HANDLE_SBR_ENCODER hSbrEncoder) {
2468*e5436536SAndroid Build Coastguard Worker   INT sbrHeader = 1;
2469*e5436536SAndroid Build Coastguard Worker   if (hSbrEncoder) {
2470*e5436536SAndroid Build Coastguard Worker     int el;
2471*e5436536SAndroid Build Coastguard Worker     for (el = 0; el < hSbrEncoder->noElements; el++) {
2472*e5436536SAndroid Build Coastguard Worker       sbrHeader &=
2473*e5436536SAndroid Build Coastguard Worker           (hSbrEncoder->sbrElement[el]->sbrBitstreamData.HeaderActiveDelay == 1)
2474*e5436536SAndroid Build Coastguard Worker               ? 1
2475*e5436536SAndroid Build Coastguard Worker               : 0;
2476*e5436536SAndroid Build Coastguard Worker     }
2477*e5436536SAndroid Build Coastguard Worker   }
2478*e5436536SAndroid Build Coastguard Worker   return sbrHeader;
2479*e5436536SAndroid Build Coastguard Worker }
2480*e5436536SAndroid Build Coastguard Worker 
sbrEncoder_GetHeaderDelay(HANDLE_SBR_ENCODER hSbrEncoder)2481*e5436536SAndroid Build Coastguard Worker INT sbrEncoder_GetHeaderDelay(HANDLE_SBR_ENCODER hSbrEncoder) {
2482*e5436536SAndroid Build Coastguard Worker   INT delay = -1;
2483*e5436536SAndroid Build Coastguard Worker 
2484*e5436536SAndroid Build Coastguard Worker   if (hSbrEncoder) {
2485*e5436536SAndroid Build Coastguard Worker     if ((hSbrEncoder->noElements == 1) &&
2486*e5436536SAndroid Build Coastguard Worker         (hSbrEncoder->sbrElement[0]->elInfo.fParametricStereo == 1)) {
2487*e5436536SAndroid Build Coastguard Worker       delay = hSbrEncoder->nBitstrDelay + 1;
2488*e5436536SAndroid Build Coastguard Worker     } else {
2489*e5436536SAndroid Build Coastguard Worker       delay = hSbrEncoder->nBitstrDelay;
2490*e5436536SAndroid Build Coastguard Worker     }
2491*e5436536SAndroid Build Coastguard Worker   }
2492*e5436536SAndroid Build Coastguard Worker   return delay;
2493*e5436536SAndroid Build Coastguard Worker }
sbrEncoder_GetBsDelay(HANDLE_SBR_ENCODER hSbrEncoder)2494*e5436536SAndroid Build Coastguard Worker INT sbrEncoder_GetBsDelay(HANDLE_SBR_ENCODER hSbrEncoder) {
2495*e5436536SAndroid Build Coastguard Worker   INT delay = -1;
2496*e5436536SAndroid Build Coastguard Worker 
2497*e5436536SAndroid Build Coastguard Worker   if (hSbrEncoder) {
2498*e5436536SAndroid Build Coastguard Worker     delay = hSbrEncoder->nBitstrDelay;
2499*e5436536SAndroid Build Coastguard Worker   }
2500*e5436536SAndroid Build Coastguard Worker   return delay;
2501*e5436536SAndroid Build Coastguard Worker }
2502*e5436536SAndroid Build Coastguard Worker 
sbrEncoder_SAPPrepare(HANDLE_SBR_ENCODER hSbrEncoder)2503*e5436536SAndroid Build Coastguard Worker INT sbrEncoder_SAPPrepare(HANDLE_SBR_ENCODER hSbrEncoder) {
2504*e5436536SAndroid Build Coastguard Worker   INT error = -1;
2505*e5436536SAndroid Build Coastguard Worker   if (hSbrEncoder) {
2506*e5436536SAndroid Build Coastguard Worker     int el;
2507*e5436536SAndroid Build Coastguard Worker     for (el = 0; el < hSbrEncoder->noElements; el++) {
2508*e5436536SAndroid Build Coastguard Worker       hSbrEncoder->sbrElement[el]->sbrBitstreamData.rightBorderFIX = 1;
2509*e5436536SAndroid Build Coastguard Worker     }
2510*e5436536SAndroid Build Coastguard Worker     error = 0;
2511*e5436536SAndroid Build Coastguard Worker   }
2512*e5436536SAndroid Build Coastguard Worker   return error;
2513*e5436536SAndroid Build Coastguard Worker }
2514*e5436536SAndroid Build Coastguard Worker 
sbrEncoder_GetEstimateBitrate(HANDLE_SBR_ENCODER hSbrEncoder)2515*e5436536SAndroid Build Coastguard Worker INT sbrEncoder_GetEstimateBitrate(HANDLE_SBR_ENCODER hSbrEncoder) {
2516*e5436536SAndroid Build Coastguard Worker   INT estimateBitrate = 0;
2517*e5436536SAndroid Build Coastguard Worker 
2518*e5436536SAndroid Build Coastguard Worker   if (hSbrEncoder) {
2519*e5436536SAndroid Build Coastguard Worker     estimateBitrate += hSbrEncoder->estimateBitrate;
2520*e5436536SAndroid Build Coastguard Worker   }
2521*e5436536SAndroid Build Coastguard Worker 
2522*e5436536SAndroid Build Coastguard Worker   return estimateBitrate;
2523*e5436536SAndroid Build Coastguard Worker }
2524*e5436536SAndroid Build Coastguard Worker 
sbrEncoder_GetInputDataDelay(HANDLE_SBR_ENCODER hSbrEncoder)2525*e5436536SAndroid Build Coastguard Worker INT sbrEncoder_GetInputDataDelay(HANDLE_SBR_ENCODER hSbrEncoder) {
2526*e5436536SAndroid Build Coastguard Worker   INT delay = -1;
2527*e5436536SAndroid Build Coastguard Worker 
2528*e5436536SAndroid Build Coastguard Worker   if (hSbrEncoder) {
2529*e5436536SAndroid Build Coastguard Worker     delay = hSbrEncoder->inputDataDelay;
2530*e5436536SAndroid Build Coastguard Worker   }
2531*e5436536SAndroid Build Coastguard Worker   return delay;
2532*e5436536SAndroid Build Coastguard Worker }
2533*e5436536SAndroid Build Coastguard Worker 
sbrEncoder_GetSbrDecDelay(HANDLE_SBR_ENCODER hSbrEncoder)2534*e5436536SAndroid Build Coastguard Worker INT sbrEncoder_GetSbrDecDelay(HANDLE_SBR_ENCODER hSbrEncoder) {
2535*e5436536SAndroid Build Coastguard Worker   INT delay = -1;
2536*e5436536SAndroid Build Coastguard Worker 
2537*e5436536SAndroid Build Coastguard Worker   if (hSbrEncoder) {
2538*e5436536SAndroid Build Coastguard Worker     delay = hSbrEncoder->sbrDecDelay;
2539*e5436536SAndroid Build Coastguard Worker   }
2540*e5436536SAndroid Build Coastguard Worker   return delay;
2541*e5436536SAndroid Build Coastguard Worker }
2542*e5436536SAndroid Build Coastguard Worker 
sbrEncoder_GetLibInfo(LIB_INFO * info)2543*e5436536SAndroid Build Coastguard Worker INT sbrEncoder_GetLibInfo(LIB_INFO *info) {
2544*e5436536SAndroid Build Coastguard Worker   int i;
2545*e5436536SAndroid Build Coastguard Worker 
2546*e5436536SAndroid Build Coastguard Worker   if (info == NULL) {
2547*e5436536SAndroid Build Coastguard Worker     return -1;
2548*e5436536SAndroid Build Coastguard Worker   }
2549*e5436536SAndroid Build Coastguard Worker   /* search for next free tab */
2550*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < FDK_MODULE_LAST; i++) {
2551*e5436536SAndroid Build Coastguard Worker     if (info[i].module_id == FDK_NONE) break;
2552*e5436536SAndroid Build Coastguard Worker   }
2553*e5436536SAndroid Build Coastguard Worker   if (i == FDK_MODULE_LAST) {
2554*e5436536SAndroid Build Coastguard Worker     return -1;
2555*e5436536SAndroid Build Coastguard Worker   }
2556*e5436536SAndroid Build Coastguard Worker   info += i;
2557*e5436536SAndroid Build Coastguard Worker 
2558*e5436536SAndroid Build Coastguard Worker   info->module_id = FDK_SBRENC;
2559*e5436536SAndroid Build Coastguard Worker   info->version =
2560*e5436536SAndroid Build Coastguard Worker       LIB_VERSION(SBRENCODER_LIB_VL0, SBRENCODER_LIB_VL1, SBRENCODER_LIB_VL2);
2561*e5436536SAndroid Build Coastguard Worker   LIB_VERSION_STRING(info);
2562*e5436536SAndroid Build Coastguard Worker #ifdef SUPPRESS_BUILD_DATE_INFO
2563*e5436536SAndroid Build Coastguard Worker   info->build_date = "";
2564*e5436536SAndroid Build Coastguard Worker   info->build_time = "";
2565*e5436536SAndroid Build Coastguard Worker #else
2566*e5436536SAndroid Build Coastguard Worker   info->build_date = __DATE__;
2567*e5436536SAndroid Build Coastguard Worker   info->build_time = __TIME__;
2568*e5436536SAndroid Build Coastguard Worker #endif
2569*e5436536SAndroid Build Coastguard Worker   info->title = "SBR Encoder";
2570*e5436536SAndroid Build Coastguard Worker 
2571*e5436536SAndroid Build Coastguard Worker   /* Set flags */
2572*e5436536SAndroid Build Coastguard Worker   info->flags = 0 | CAPF_SBR_HQ | CAPF_SBR_PS_MPEG;
2573*e5436536SAndroid Build Coastguard Worker   /* End of flags */
2574*e5436536SAndroid Build Coastguard Worker 
2575*e5436536SAndroid Build Coastguard Worker   return 0;
2576*e5436536SAndroid Build Coastguard Worker }
2577