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