1 /* -----------------------------------------------------------------------------
2 Software License for The Fraunhofer FDK AAC Codec Library for Android
3
4 © Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
5 Forschung e.V. All rights reserved.
6
7 1. INTRODUCTION
8 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9 that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10 scheme for digital audio. This FDK AAC Codec software is intended to be used on
11 a wide variety of Android devices.
12
13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14 general perceptual audio codecs. AAC-ELD is considered the best-performing
15 full-bandwidth communications codec by independent studies and is widely
16 deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17 specifications.
18
19 Patent licenses for necessary patent claims for the FDK AAC Codec (including
20 those of Fraunhofer) may be obtained through Via Licensing
21 (www.vialicensing.com) or through the respective patent owners individually for
22 the purpose of encoding or decoding bit streams in products that are compliant
23 with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24 Android devices already license these patent claims through Via Licensing or
25 directly from the patent owners, and therefore FDK AAC Codec software may
26 already be covered under those patent licenses when it is used for those
27 licensed purposes only.
28
29 Commercially-licensed AAC software libraries, including floating-point versions
30 with enhanced sound quality, are also available from Fraunhofer. Users are
31 encouraged to check the Fraunhofer website for additional applications
32 information and documentation.
33
34 2. COPYRIGHT LICENSE
35
36 Redistribution and use in source and binary forms, with or without modification,
37 are permitted without payment of copyright license fees provided that you
38 satisfy the following conditions:
39
40 You must retain the complete text of this software license in redistributions of
41 the FDK AAC Codec or your modifications thereto in source code form.
42
43 You must retain the complete text of this software license in the documentation
44 and/or other materials provided with redistributions of the FDK AAC Codec or
45 your modifications thereto in binary form. You must make available free of
46 charge copies of the complete source code of the FDK AAC Codec and your
47 modifications thereto to recipients of copies in binary form.
48
49 The name of Fraunhofer may not be used to endorse or promote products derived
50 from this library without prior written permission.
51
52 You may not charge copyright license fees for anyone to use, copy or distribute
53 the FDK AAC Codec software or your modifications thereto.
54
55 Your modified versions of the FDK AAC Codec must carry prominent notices stating
56 that you changed the software and the date of any change. For modified versions
57 of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58 must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59 AAC Codec Library for Android."
60
61 3. NO PATENT LICENSE
62
63 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64 limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65 Fraunhofer provides no warranty of patent non-infringement with respect to this
66 software.
67
68 You may use this FDK AAC Codec software or modifications thereto only for
69 purposes that are authorized by appropriate patent licenses.
70
71 4. DISCLAIMER
72
73 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74 holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75 including but not limited to the implied warranties of merchantability and
76 fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78 or consequential damages, including but not limited to procurement of substitute
79 goods or services; loss of use, data, or profits, or business interruption,
80 however caused and on any theory of liability, whether in contract, strict
81 liability, or tort (including negligence), arising in any way out of the use of
82 this software, even if advised of the possibility of such damage.
83
84 5. CONTACT INFORMATION
85
86 Fraunhofer Institute for Integrated Circuits IIS
87 Attention: Audio and Multimedia Departments - FDK AAC LL
88 Am Wolfsmantel 33
89 91058 Erlangen, Germany
90
91 www.iis.fraunhofer.de/amm
92 amm-info@iis.fraunhofer.de
93 ----------------------------------------------------------------------------- */
94
95 /*********************** MPEG surround encoder library *************************
96
97 Author(s): Max Neuendorf
98
99 Description: Encoder Library Interface
100 Interface to Spacial Audio Coding Encoder lib
101
102 *******************************************************************************/
103
104 /****************************************************************************
105 \file
106 Description of file contents
107 ******************************************************************************/
108
109 /* Includes ******************************************************************/
110 #include "sacenc_lib.h"
111 #include "sacenc_const.h"
112 #include "genericStds.h"
113 #include "FDK_core.h"
114 #include "sacenc_tree.h"
115 #include "sacenc_bitstream.h"
116 #include "sacenc_onsetdetect.h"
117 #include "sacenc_framewindowing.h"
118 #include "sacenc_filter.h"
119 #include "sacenc_paramextract.h"
120 #include "sacenc_staticgain.h"
121 #include "sacenc_delay.h"
122 #include "sacenc_dmx_tdom_enh.h"
123 #include "sacenc_vectorfunctions.h"
124 #include "qmf.h"
125
126 /* Defines *******************************************************************/
127
128 /* Encoder library info */
129 #define SACENC_LIB_VL0 2
130 #define SACENC_LIB_VL1 0
131 #define SACENC_LIB_VL2 0
132 #define SACENC_LIB_TITLE "MPEG Surround Encoder"
133 #ifdef SUPPRESS_BUILD_DATE_INFO
134 #define SACENC_LIB_BUILD_DATE ""
135 #define SACENC_LIB_BUILD_TIME ""
136 #else
137 #define SACENC_LIB_BUILD_DATE __DATE__
138 #define SACENC_LIB_BUILD_TIME __TIME__
139 #endif
140
141 #define MAX_MPEGS_BYTES (1 << 14)
142 #define MAX_SSC_BYTES (1 << 6)
143
144 #define MAX_SPACE_TREE_CHANNELS 2
145 #define NUM_KEEP_WINDOWS 3
146
147 /* Data Types ****************************************************************/
148 typedef struct {
149 MP4SPACEENC_MODE encMode;
150 MP4SPACEENC_BANDS_CONFIG nParamBands;
151 MP4SPACEENC_QUANTMODE quantMode;
152 UCHAR bUseCoarseQuant;
153 UCHAR bLdMode;
154 UCHAR bTimeDomainDmx;
155 UINT sampleRate;
156 UINT frameTimeSlots; /* e.g. 32 when used with HE-AAC */
157 UINT independencyFactor; /* how often should we set the independency flag */
158 INT timeAlignment; /* additional delay for downmix */
159
160 } MP4SPACEENC_SETUP, *HANDLE_MP4SPACEENC_SETUP;
161
162 struct ENC_CONFIG_SETUP {
163 UCHAR bEncMode_212;
164 UCHAR maxHybridInStaticSlots;
165 LONG maxSamplingrate;
166 INT maxAnalysisLengthTimeSlots;
167 INT maxHybridBands;
168 INT maxQmfBands;
169 INT maxChIn;
170 INT maxFrameTimeSlots;
171 INT maxFrameLength;
172 INT maxChOut;
173 INT maxChTotOut;
174 };
175
176 struct MP4SPACE_ENCODER {
177 MP4SPACEENC_SETUP user;
178
179 ENC_CONFIG_SETUP setup; /* describe allocated instance */
180
181 HANDLE_FRAMEWINDOW
182 hFrameWindow; /* Windowing, only created+updated, but not used */
183 INT nSamplesValid; /* Input Buffer Handling */
184
185 /* Routing Sensible Switches/Variables */
186 MP4SPACEENC_BANDS_CONFIG nParamBands;
187 UCHAR useTimeDomDownmix;
188
189 /* not Routing Sensible Switches/Varibles - must be contained in Check */
190 MP4SPACEENC_MODE encMode;
191 UCHAR bEncMode_212_only;
192
193 /* not Routing Sensible Switches/Varibles + lower Classes */
194 UCHAR useFrameKeep;
195 UINT independencyFactor;
196 UINT nSampleRate;
197 UCHAR nInputChannels;
198 UCHAR nOutputChannels;
199 UCHAR nFrameTimeSlots; /* e.g. 32 when used with HE-AAC */
200 UCHAR nQmfBands;
201 UCHAR nHybridBands;
202 UINT nFrameLength; /* number of output waveform samples/channel/frame */
203
204 /* not Routing Sensible Switches/Varibles + lower Classes, secondary computed
205 */
206 INT nSamplesNext;
207 INT nAnalysisLengthTimeSlots;
208 INT nAnalysisLookaheadTimeSlots;
209 INT nUpdateHybridPositionTimeSlots;
210 INT *pnOutputBits;
211 INT nInputDelay;
212 INT nOutputBufferDelay;
213 INT nSurroundAnalysisBufferDelay;
214 INT nBitstreamDelayBuffer;
215 INT nBitstreamBufferRead;
216 INT nBitstreamBufferWrite;
217 INT nDiscardOutFrames;
218 INT avoid_keep;
219
220 /* not Routing Sensible Switches/Varibles -> moved to lower Classes */
221 UCHAR useCoarseQuantCld; /* Only Used in SpaceTreeSetup */
222 UCHAR useCoarseQuantIcc; /* Only Used in SpaceTreeSetup */
223 UCHAR useCoarseQuantCpc; /* Only Used in SpaceTreeSetup */
224 UCHAR useCoarseQuantArbDmx; /* ArbitraryDmx,... not available yet */
225 MP4SPACEENC_QUANTMODE
226 quantMode; /* Used for quanitzation and in bitstream writer */
227 INT coreCoderDelay; /* Used in delay compensation */
228 INT timeAlignment; /* Used in delay compensation */
229
230 /* Local Processing Variables */
231 INT independencyCount;
232 INT independencyFlag;
233 INT **ppTrCurrPos; /* belongs somehow to Onset Detection */
234 INT trPrevPos[2 * MAX_NUM_TRANS]; /* belongs somehow to Onset Detection */
235
236 FRAMEWIN_LIST frameWinList;
237 SPATIALFRAME saveFrame;
238
239 /* Module-Handles */
240 SPACE_TREE_SETUP spaceTreeSetup;
241 MPEG4SPACEENC_SSCBUF sscBuf;
242 FIXP_WIN *pFrameWindowAna__FDK[MAX_NUM_PARAMS];
243 HANDLE_QMF_FILTER_BANK *phQmfFiltIn__FDK;
244 HANDLE_DC_FILTER phDCFilterSigIn[SACENC_MAX_INPUT_CHANNELS];
245 HANDLE_ONSET_DETECT phOnset[SACENC_MAX_INPUT_CHANNELS];
246 HANDLE_SPACE_TREE hSpaceTree;
247 HANDLE_BSF_INSTANCE hBitstreamFormatter;
248 HANDLE_STATIC_GAIN_CONFIG hStaticGainConfig;
249 HANDLE_STATIC_GAIN hStaticGain;
250 HANDLE_DELAY hDelay;
251
252 /* enhanced time domain downmix (for stereo input) */
253 HANDLE_ENHANCED_TIME_DOMAIN_DMX hEnhancedTimeDmx;
254
255 /* Data Buffers */
256 INT_PCM **ppTimeSigIn__FDK;
257 INT_PCM **ppTimeSigDelayIn__FDK;
258 INT_PCM **ppTimeSigOut__FDK;
259 FIXP_DPK ***pppHybridIn__FDK;
260 FIXP_DPK ***pppHybridInStatic__FDK;
261 FIXP_DPK ***pppProcDataIn__FDK;
262 INT_PCM *pOutputDelayBuffer__FDK;
263
264 UCHAR **ppBitstreamDelayBuffer;
265
266 UCHAR *pParameterBand2HybridBandOffset;
267 INT staticGainScale;
268
269 INT *pEncoderInputChScale;
270 INT *staticTimeDomainDmxInScale;
271 };
272
273 /* Constants *****************************************************************/
274 static const UCHAR pValidBands_Ld[8] = {4, 5, 7, 9, 12, 15, 23, 40};
275
276 static const UCHAR qmf2qmf[] = /* Bypass the HybridAnylyis/Synthesis*/
277 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
278 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
279 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
280 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
281 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
282 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
283 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
284 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
285 120, 121, 122, 123, 124, 125, 126, 127};
286
287 /* Function / Class Declarations *********************************************/
288 static FDK_SACENC_ERROR mp4SpaceEnc_create(
289 HANDLE_MP4SPACE_ENCODER *phMp4SpaceEnc);
290
291 static FDK_SACENC_ERROR FillSpatialSpecificConfig(
292 const HANDLE_MP4SPACE_ENCODER hEnc, SPATIALSPECIFICCONFIG *const hSsc);
293
294 static FDK_SACENC_ERROR mp4SpaceEnc_FillSpaceTreeSetup(
295 const HANDLE_MP4SPACE_ENCODER hEnc,
296 SPACE_TREE_SETUP *const hSpaceTreeSetup);
297
298 static FDK_SACENC_ERROR mp4SpaceEnc_InitDelayCompensation(
299 HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, const INT coreCoderDelay);
300
301 static FDK_SACENC_ERROR mp4SpaceEnc_InitDefault(
302 HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc);
303
304 static DECORRCONFIG mp4SpaceEnc_GetDecorrConfig(const MP4SPACEENC_MODE encMode);
305
306 static FDK_SACENC_ERROR mp4SpaceEnc_InitNumParamBands(
307 HANDLE_MP4SPACE_ENCODER hEnc, const MP4SPACEENC_BANDS_CONFIG nParamBands);
308
309 /* Function / Class Definition ***********************************************/
mp4SpaceEnc_GetNumQmfBands(const UINT nSampleRate)310 static UINT mp4SpaceEnc_GetNumQmfBands(const UINT nSampleRate) {
311 UINT nQmfBands = 0;
312
313 if (nSampleRate < 27713)
314 nQmfBands = 32;
315 else if (nSampleRate < 55426)
316 nQmfBands = 64;
317
318 return nQmfBands;
319 }
320
updateQmfFlags(const UINT flags,const INT keepStates)321 static UINT updateQmfFlags(const UINT flags, const INT keepStates) {
322 UINT qmfFlags = flags;
323
324 qmfFlags = (qmfFlags & (~(UINT)QMF_FLAG_LP));
325 qmfFlags = (qmfFlags | QMF_FLAG_MPSLDFB);
326 qmfFlags = (keepStates) ? (qmfFlags | QMF_FLAG_KEEP_STATES)
327 : (qmfFlags & (~(UINT)QMF_FLAG_KEEP_STATES));
328
329 return qmfFlags;
330 }
331
freq2HybridBand(const UINT nFrequency,const UINT nSampleRate,const UINT nQmfBands)332 static INT freq2HybridBand(const UINT nFrequency, const UINT nSampleRate,
333 const UINT nQmfBands) {
334 /*
335 nQmfSlotWidth = (nSampleRate/2) / nQmfBands;
336 nQmfBand = nFrequency / nQmfSlotWidth;
337 */
338 int nHybridBand = -1;
339 int scale = 0;
340 const FIXP_DBL temp = fDivNorm((FIXP_DBL)(2 * nFrequency * nQmfBands),
341 (FIXP_DBL)nSampleRate, &scale);
342 const int nQmfBand = scaleValue(temp, scale - (DFRACT_BITS - 1));
343
344 if ((nQmfBand > -1) && (nQmfBand < (int)nQmfBands)) {
345 nHybridBand = qmf2qmf[nQmfBand];
346 }
347
348 return nHybridBand;
349 }
350
351 /*
352 * Examine buffer descriptor regarding choosen type.
353 *
354 * \param pBufDesc Pointer to buffer descriptor
355 * \param type Buffer type to look for.
356
357 * \return - Buffer descriptor index.
358 * -1, if there is no entry available.
359 */
getBufDescIdx(const FDK_bufDescr * pBufDesc,const UINT type)360 static INT getBufDescIdx(const FDK_bufDescr *pBufDesc, const UINT type) {
361 INT i, idx = -1;
362
363 for (i = 0; i < (int)pBufDesc->numBufs; i++) {
364 if (pBufDesc->pBufType[i] == type) {
365 idx = i;
366 break;
367 }
368 }
369 return idx;
370 }
371
FDK_sacenc_open(HANDLE_MP4SPACE_ENCODER * phMp4SpaceEnc)372 FDK_SACENC_ERROR FDK_sacenc_open(HANDLE_MP4SPACE_ENCODER *phMp4SpaceEnc) {
373 return mp4SpaceEnc_create(phMp4SpaceEnc);
374 }
375
mp4SpaceEnc_create(HANDLE_MP4SPACE_ENCODER * phMp4SpaceEnc)376 static FDK_SACENC_ERROR mp4SpaceEnc_create(
377 HANDLE_MP4SPACE_ENCODER *phMp4SpaceEnc) {
378 FDK_SACENC_ERROR error = SACENC_OK;
379 HANDLE_MP4SPACE_ENCODER hEnc = NULL;
380 ENC_CONFIG_SETUP setup;
381
382 if (NULL == phMp4SpaceEnc) {
383 error = SACENC_INVALID_HANDLE;
384 } else {
385 int i, ch;
386 FDKmemclear(&setup, sizeof(ENC_CONFIG_SETUP));
387
388 /* Allocate Encoder Instance */
389 FDK_ALLOCATE_MEMORY_1D(hEnc, 1, struct MP4SPACE_ENCODER);
390
391 /* Clear everything, also pointers. */
392 if (NULL != hEnc) {
393 FDKmemclear(hEnc, sizeof(struct MP4SPACE_ENCODER));
394 }
395
396 setup.maxSamplingrate = 48000;
397 setup.maxFrameTimeSlots = 16;
398
399 setup.maxAnalysisLengthTimeSlots = 3 * setup.maxFrameTimeSlots;
400 setup.maxQmfBands = mp4SpaceEnc_GetNumQmfBands(setup.maxSamplingrate);
401 ;
402 setup.maxHybridBands = setup.maxQmfBands;
403 setup.maxFrameLength = setup.maxQmfBands * setup.maxFrameTimeSlots;
404
405 setup.maxChIn = 2;
406 setup.maxChOut = 1;
407 setup.maxChTotOut = setup.maxChOut;
408 setup.bEncMode_212 = 1;
409 setup.maxHybridInStaticSlots = 24;
410
411 /* Open Static Gain*/
412 if (SACENC_OK !=
413 (error = fdk_sacenc_staticGain_OpenConfig(&hEnc->hStaticGainConfig))) {
414 goto bail;
415 }
416
417 /* enhanced time domain downmix (for stereo input) */
418 if (SACENC_OK != (error = fdk_sacenc_open_enhancedTimeDomainDmx(
419 &hEnc->hEnhancedTimeDmx, setup.maxFrameLength))) {
420 goto bail;
421 }
422
423 FDK_ALLOCATE_MEMORY_1D(hEnc->pParameterBand2HybridBandOffset,
424 MAX_NUM_PARAM_BANDS, UCHAR);
425
426 /* Create Space Tree first, to get number of in-/output channels */
427 if (SACENC_OK != (error = fdk_sacenc_spaceTree_Open(&hEnc->hSpaceTree))) {
428 goto bail;
429 }
430
431 FDK_ALLOCATE_MEMORY_1D(hEnc->pEncoderInputChScale, setup.maxChIn, INT);
432 FDK_ALLOCATE_MEMORY_1D(hEnc->staticTimeDomainDmxInScale, setup.maxChIn,
433 INT);
434
435 FDK_ALLOCATE_MEMORY_1D(hEnc->phQmfFiltIn__FDK, setup.maxChIn,
436 HANDLE_QMF_FILTER_BANK);
437
438 /* Allocate Analysis Filterbank Structs */
439 for (ch = 0; ch < setup.maxChIn; ch++) {
440 FDK_ALLOCATE_MEMORY_1D_INT(hEnc->phQmfFiltIn__FDK[ch], 1,
441 struct QMF_FILTER_BANK, SECT_DATA_L2)
442 FDK_ALLOCATE_MEMORY_1D_INT(hEnc->phQmfFiltIn__FDK[ch]->FilterStates,
443 2 * 5 * setup.maxQmfBands, FIXP_QAS,
444 SECT_DATA_L2)
445 }
446
447 /* Allocate Synthesis Filterbank Structs for arbitrary downmix */
448
449 /* Allocate DC Filter Struct for normal signal input */
450 for (ch = 0; ch < setup.maxChIn; ch++) {
451 if (SACENC_OK !=
452 (error = fdk_sacenc_createDCFilter(&hEnc->phDCFilterSigIn[ch]))) {
453 goto bail;
454 }
455 }
456
457 /* Open Onset Detection */
458 for (ch = 0; ch < setup.maxChIn; ch++) {
459 if (SACENC_OK != (error = fdk_sacenc_onsetDetect_Open(
460 &hEnc->phOnset[ch], setup.maxFrameTimeSlots))) {
461 goto bail;
462 }
463 }
464
465 FDK_ALLOCATE_MEMORY_2D(hEnc->ppTrCurrPos, setup.maxChIn, MAX_NUM_TRANS,
466 INT);
467
468 /* Create Windowing */
469 if (SACENC_OK !=
470 (error = fdk_sacenc_frameWindow_Create(&hEnc->hFrameWindow))) {
471 goto bail;
472 }
473
474 /* Open static gain */
475 if (SACENC_OK != (error = fdk_sacenc_staticGain_Open(&hEnc->hStaticGain))) {
476 goto bail;
477 }
478
479 /* create bitstream encoder */
480 if (SACENC_OK != (error = fdk_sacenc_createSpatialBitstreamEncoder(
481 &hEnc->hBitstreamFormatter))) {
482 goto bail;
483 }
484
485 FDK_ALLOCATE_MEMORY_1D(hEnc->sscBuf.pSsc, MAX_SSC_BYTES, UCHAR);
486
487 {
488 FDK_ALLOCATE_MEMORY_2D(hEnc->ppTimeSigIn__FDK, setup.maxChIn,
489 setup.maxFrameLength + MAX_DELAY_SURROUND_ANALYSIS,
490 INT_PCM);
491 }
492 FDK_ALLOCATE_MEMORY_2D(hEnc->ppTimeSigDelayIn__FDK, setup.maxChIn,
493 MAX_DELAY_SURROUND_ANALYSIS, INT_PCM);
494
495 /* Create new buffers for several signals (including arbitrary downmix) */
496 if (setup.bEncMode_212 == 0) {
497 /* pOutputDelayBuffer__FDK buffer is not needed for SACENC_212 mode */
498 FDK_ALLOCATE_MEMORY_1D(
499 hEnc->pOutputDelayBuffer__FDK,
500 (setup.maxFrameLength + MAX_DELAY_OUTPUT) * setup.maxChOut, INT_PCM);
501 }
502
503 /* allocate buffers */
504 if (setup.bEncMode_212 == 0) {
505 /* ppTimeSigOut__FDK buffer is not needed for SACENC_212 mode */
506 FDK_ALLOCATE_MEMORY_2D(hEnc->ppTimeSigOut__FDK, setup.maxChTotOut,
507 setup.maxFrameLength, INT_PCM);
508 }
509
510 if (setup.bEncMode_212 == 1) {
511 /* pppHybridIn__FDK buffer can be reduced by maxFrameTimeSlots/2 slots for
512 * SACENC_212 mode */
513 FDK_ALLOCATE_MEMORY_3D(
514 hEnc->pppHybridIn__FDK, setup.maxChIn,
515 setup.maxAnalysisLengthTimeSlots - (setup.maxFrameTimeSlots >> 1),
516 setup.maxHybridBands, FIXP_DPK);
517 FDK_ALLOCATE_MEMORY_3D(hEnc->pppHybridInStatic__FDK, setup.maxChIn,
518 setup.maxHybridInStaticSlots, setup.maxHybridBands,
519 FIXP_DPK);
520 } else {
521 FDK_ALLOCATE_MEMORY_3D(hEnc->pppHybridIn__FDK, setup.maxChIn,
522 setup.maxAnalysisLengthTimeSlots,
523 setup.maxHybridBands, FIXP_DPK);
524 }
525
526 if (setup.bEncMode_212 == 0) {
527 /* pppProcDataIn__FDK buffer is not needed for SACENC_212 mode */
528 FDK_ALLOCATE_MEMORY_3D(hEnc->pppProcDataIn__FDK, MAX_SPACE_TREE_CHANNELS,
529 setup.maxAnalysisLengthTimeSlots,
530 setup.maxHybridBands, FIXP_DPK);
531 }
532 for (i = 0; i < MAX_NUM_PARAMS; i++) {
533 FDK_ALLOCATE_MEMORY_1D(hEnc->pFrameWindowAna__FDK[i],
534 setup.maxAnalysisLengthTimeSlots, FIXP_WIN);
535 } /* for i */
536
537 if (SACENC_OK != (error = fdk_sacenc_delay_Open(&hEnc->hDelay))) {
538 goto bail;
539 }
540
541 if (setup.bEncMode_212 == 0) {
542 /* ppBitstreamDelayBuffer buffer is not needed for SACENC_212 mode */
543 FDK_ALLOCATE_MEMORY_2D(hEnc->ppBitstreamDelayBuffer, MAX_BITSTREAM_DELAY,
544 MAX_MPEGS_BYTES, UCHAR);
545 }
546 FDK_ALLOCATE_MEMORY_1D(hEnc->pnOutputBits, MAX_BITSTREAM_DELAY, INT);
547
548 hEnc->setup = setup; /* save configuration used while encoder allocation. */
549 mp4SpaceEnc_InitDefault(hEnc);
550
551 if (NULL != phMp4SpaceEnc) {
552 *phMp4SpaceEnc = hEnc; /* return encoder handle */
553 }
554
555 } /* valid handle */
556
557 return error;
558
559 bail:
560 if (NULL != hEnc) {
561 hEnc->setup = setup;
562 FDK_sacenc_close(&hEnc);
563 }
564 return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error);
565 }
566
mp4SpaceEnc_InitDefault(HANDLE_MP4SPACE_ENCODER hEnc)567 static FDK_SACENC_ERROR mp4SpaceEnc_InitDefault(HANDLE_MP4SPACE_ENCODER hEnc) {
568 FDK_SACENC_ERROR err = SACENC_OK;
569
570 /* Get default static gain configuration. */
571 if (SACENC_OK != (err = fdk_sacenc_staticGain_InitDefaultConfig(
572 hEnc->hStaticGainConfig))) {
573 goto bail;
574 }
575
576 bail:
577 return err;
578 }
579
FDK_sacenc_configure(HANDLE_MP4SPACE_ENCODER hEnc,const HANDLE_MP4SPACEENC_SETUP hSetup)580 static FDK_SACENC_ERROR FDK_sacenc_configure(
581 HANDLE_MP4SPACE_ENCODER hEnc, const HANDLE_MP4SPACEENC_SETUP hSetup) {
582 FDK_SACENC_ERROR error = SACENC_OK;
583
584 hEnc->nSampleRate = hSetup->sampleRate;
585 hEnc->encMode = hSetup->encMode;
586 hEnc->nQmfBands = mp4SpaceEnc_GetNumQmfBands(hEnc->nSampleRate);
587
588 /* Make sure that we have set time domain downmix for 212 */
589 if (hSetup->encMode == SACENC_212 && hSetup->bTimeDomainDmx == 0) {
590 error = SACENC_INVALID_CONFIG;
591 } else {
592 hEnc->useTimeDomDownmix = hSetup->bTimeDomainDmx;
593 }
594
595 hEnc->timeAlignment = hSetup->timeAlignment;
596 hEnc->quantMode = hSetup->quantMode;
597
598 hEnc->useCoarseQuantCld = hSetup->bUseCoarseQuant;
599 hEnc->useCoarseQuantCpc = hSetup->bUseCoarseQuant;
600 hEnc->useFrameKeep = (hSetup->bLdMode == 2);
601 hEnc->useCoarseQuantIcc = 0; /* not available */
602 hEnc->useCoarseQuantArbDmx = 0; /* not available for user right now */
603 hEnc->independencyFactor = hSetup->independencyFactor;
604 hEnc->independencyCount = 0;
605 hEnc->independencyFlag = 1;
606
607 /* set number of Hybrid bands */
608 hEnc->nHybridBands = hEnc->nQmfBands;
609 hEnc->nFrameTimeSlots = hSetup->frameTimeSlots;
610 mp4SpaceEnc_InitNumParamBands(hEnc, hSetup->nParamBands);
611
612 return error;
613 }
614
FDK_sacenc_init(HANDLE_MP4SPACE_ENCODER hEnc,const INT dmxDelay)615 FDK_SACENC_ERROR FDK_sacenc_init(HANDLE_MP4SPACE_ENCODER hEnc,
616 const INT dmxDelay) {
617 FDK_SACENC_ERROR error = SACENC_OK;
618
619 /* Sanity Checks */
620 if (NULL == hEnc) {
621 error = SACENC_INVALID_HANDLE;
622 } else {
623 const int initStatesFlag = 1;
624
625 int ch; /* loop counter */
626 int nChInArbDmx;
627
628 if (SACENC_OK != (error = FDK_sacenc_configure(hEnc, &hEnc->user))) {
629 goto bail;
630 }
631
632 hEnc->bEncMode_212_only = hEnc->setup.bEncMode_212;
633
634 /* Slots per Frame and Frame Length */
635 if (hEnc->nFrameTimeSlots < 1) {
636 error = SACENC_INVALID_CONFIG;
637 goto bail;
638 }
639 hEnc->nFrameLength = hEnc->nQmfBands * hEnc->nFrameTimeSlots;
640
641 if (hEnc->useFrameKeep == 1) {
642 hEnc->nAnalysisLengthTimeSlots = 3 * hEnc->nFrameTimeSlots;
643 hEnc->nUpdateHybridPositionTimeSlots = hEnc->nFrameTimeSlots;
644 } else {
645 hEnc->nAnalysisLengthTimeSlots = 2 * hEnc->nFrameTimeSlots;
646 hEnc->nUpdateHybridPositionTimeSlots = 0;
647 }
648
649 {
650 hEnc->nAnalysisLookaheadTimeSlots =
651 hEnc->nAnalysisLengthTimeSlots - 3 * hEnc->nFrameTimeSlots / 2;
652 }
653
654 /* init parameterBand2hybridBandOffset table */
655 fdk_sacenc_calcParameterBand2HybridBandOffset(
656 (BOX_SUBBAND_CONFIG)hEnc->nParamBands, hEnc->nHybridBands,
657 hEnc->pParameterBand2HybridBandOffset);
658
659 /* Fill Setup structure for Space Tree */
660 if (SACENC_OK !=
661 (error = mp4SpaceEnc_FillSpaceTreeSetup(hEnc, &hEnc->spaceTreeSetup))) {
662 goto bail;
663 }
664
665 /* Init space tree configuration */
666 if (SACENC_OK !=
667 (error = fdk_sacenc_spaceTree_Init(
668 hEnc->hSpaceTree, &hEnc->spaceTreeSetup,
669 hEnc->pParameterBand2HybridBandOffset, hEnc->useFrameKeep))) {
670 goto bail;
671 }
672
673 /* Get space tree description and resulting number of input/output channels
674 */
675 {
676 SPACE_TREE_DESCRIPTION spaceTreeDescription;
677
678 if (SACENC_OK != (error = fdk_sacenc_spaceTree_GetDescription(
679 hEnc->hSpaceTree, &spaceTreeDescription))) {
680 goto bail;
681 }
682
683 hEnc->nInputChannels =
684 spaceTreeDescription.nOutChannels; /* space tree description
685 describes decoder
686 configuration */
687 hEnc->nOutputChannels =
688 spaceTreeDescription.nInChannels; /* space tree description
689 describes decoder
690 configuration */
691 }
692
693 nChInArbDmx = 0;
694
695 /* INITIALIZATION */
696 for (ch = 0; ch < hEnc->nInputChannels; ch++) {
697 /* scaling in analysis qmf filterbank (7) */
698 hEnc->pEncoderInputChScale[ch] = 7;
699
700 {
701 /* additional scaling in qmf prototype filter for low delay */
702 hEnc->pEncoderInputChScale[ch] += 1;
703 }
704
705 { hEnc->pEncoderInputChScale[ch] += DC_FILTER_SF; }
706 } /* nInputChannels */
707
708 /* Init analysis filterbank */
709 for (ch = 0; ch < hEnc->nInputChannels; ch++) {
710 hEnc->phQmfFiltIn__FDK[ch]->flags =
711 updateQmfFlags(hEnc->phQmfFiltIn__FDK[ch]->flags, !initStatesFlag);
712
713 if (0 != qmfInitAnalysisFilterBank(
714 hEnc->phQmfFiltIn__FDK[ch],
715 (FIXP_QAS *)hEnc->phQmfFiltIn__FDK[ch]->FilterStates, 1,
716 hEnc->nQmfBands, hEnc->nQmfBands, hEnc->nQmfBands,
717 hEnc->phQmfFiltIn__FDK[ch]->flags)) {
718 error = SACENC_INIT_ERROR;
719 goto bail;
720 }
721 }
722
723 /* Initialize DC Filter. */
724 {
725 for (ch = 0; ch < hEnc->nInputChannels; ch++) {
726 if (SACENC_OK != (error = fdk_sacenc_initDCFilter(
727 hEnc->phDCFilterSigIn[ch], hEnc->nSampleRate))) {
728 goto bail;
729 }
730 }
731 }
732
733 /* Init onset detect. */
734 {
735 /* init onset detect configuration struct */
736 ONSET_DETECT_CONFIG onsetDetectConfig;
737 onsetDetectConfig.maxTimeSlots = hEnc->nFrameTimeSlots;
738 onsetDetectConfig.lowerBoundOnsetDetection =
739 freq2HybridBand(1725, hEnc->nSampleRate, hEnc->nQmfBands);
740 onsetDetectConfig.upperBoundOnsetDetection = hEnc->nHybridBands;
741
742 for (ch = 0; ch < hEnc->nInputChannels; ch++) {
743 if (SACENC_OK != (error = fdk_sacenc_onsetDetect_Init(
744 hEnc->phOnset[ch], &onsetDetectConfig, 1))) {
745 goto bail;
746 }
747 }
748 }
749
750 {
751 /* init windowing */
752 FRAMEWINDOW_CONFIG framewindowConfig;
753 framewindowConfig.nTimeSlotsMax = hEnc->nFrameTimeSlots;
754 framewindowConfig.bFrameKeep = hEnc->useFrameKeep;
755
756 if (SACENC_OK != (error = fdk_sacenc_frameWindow_Init(
757 hEnc->hFrameWindow, &framewindowConfig))) {
758 goto bail;
759 }
760 }
761
762 /* Set encoder mode for static gain initialization. */
763 if (SACENC_OK != (error = fdk_sacenc_staticGain_SetEncMode(
764 hEnc->hStaticGainConfig, hEnc->encMode))) {
765 goto bail;
766 }
767
768 /* Init static gain. */
769 if (SACENC_OK != (error = fdk_sacenc_staticGain_Init(
770 hEnc->hStaticGain, hEnc->hStaticGainConfig,
771 &(hEnc->staticGainScale)))) {
772 goto bail;
773 }
774
775 for (ch = 0; ch < hEnc->nInputChannels; ch++) {
776 hEnc->pEncoderInputChScale[ch] += hEnc->staticGainScale;
777 }
778
779 /* enhanced downmix for stereo input*/
780 if (hEnc->useTimeDomDownmix != 0) {
781 if (SACENC_OK != (error = fdk_sacenc_init_enhancedTimeDomainDmx(
782 hEnc->hEnhancedTimeDmx,
783 fdk_sacenc_getPreGainPtrFDK(hEnc->hStaticGain),
784 hEnc->staticGainScale,
785 fdk_sacenc_getPostGainFDK(hEnc->hStaticGain),
786 hEnc->staticGainScale, hEnc->nFrameLength))) {
787 goto bail;
788 }
789 }
790
791 /* Create config structure for bitstream formatter including arbitrary
792 * downmix residual */
793 if (SACENC_OK != (error = fdk_sacenc_initSpatialBitstreamEncoder(
794 hEnc->hBitstreamFormatter))) {
795 goto bail;
796 }
797
798 if (SACENC_OK != (error = FillSpatialSpecificConfig(
799 hEnc, fdk_sacenc_getSpatialSpecificConfig(
800 hEnc->hBitstreamFormatter)))) {
801 goto bail;
802 }
803
804 if (SACENC_OK !=
805 (error = fdk_sacenc_writeSpatialSpecificConfig(
806 fdk_sacenc_getSpatialSpecificConfig(hEnc->hBitstreamFormatter),
807 hEnc->sscBuf.pSsc, MAX_SSC_BYTES, &hEnc->sscBuf.nSscSizeBits))) {
808 goto bail;
809 }
810
811 /* init delay compensation with dmx core coder delay; if no core coder is
812 * used, many other buffers are initialized nevertheless */
813 if (SACENC_OK !=
814 (error = mp4SpaceEnc_InitDelayCompensation(hEnc, dmxDelay))) {
815 goto bail;
816 }
817
818 /* How much input do we need? */
819 hEnc->nSamplesNext =
820 hEnc->nFrameLength * (hEnc->nInputChannels + nChInArbDmx);
821 hEnc->nSamplesValid = 0;
822 } /* valid handle */
823
824 bail:
825 return error;
826 }
827
getAnalysisLengthTimeSlots(FIXP_WIN * pFrameWindowAna,INT nTimeSlots)828 static INT getAnalysisLengthTimeSlots(FIXP_WIN *pFrameWindowAna,
829 INT nTimeSlots) {
830 int i;
831 for (i = nTimeSlots - 1; i >= 0; i--) {
832 if (pFrameWindowAna[i] != (FIXP_WIN)0) {
833 break;
834 }
835 }
836 nTimeSlots = i + 1;
837 return nTimeSlots;
838 }
839
getAnalysisStartTimeSlot(FIXP_WIN * pFrameWindowAna,INT nTimeSlots)840 static INT getAnalysisStartTimeSlot(FIXP_WIN *pFrameWindowAna, INT nTimeSlots) {
841 int startTimeSlot = 0;
842 int i;
843 for (i = 0; i < nTimeSlots; i++) {
844 if (pFrameWindowAna[i] != (FIXP_WIN)0) {
845 break;
846 }
847 }
848 startTimeSlot = i;
849 return startTimeSlot;
850 }
851
__FeedDeinterPreScale(HANDLE_MP4SPACE_ENCODER hEnc,INT_PCM const * const pSamples,INT_PCM * const pOutputSamples,INT const nSamples,UINT const isInputInterleaved,UINT const inputBufferSizePerChannel,UINT * const pnSamplesFed)852 static FDK_SACENC_ERROR __FeedDeinterPreScale(
853 HANDLE_MP4SPACE_ENCODER hEnc, INT_PCM const *const pSamples,
854 INT_PCM *const pOutputSamples, INT const nSamples,
855 UINT const isInputInterleaved, UINT const inputBufferSizePerChannel,
856 UINT *const pnSamplesFed) {
857 FDK_SACENC_ERROR error = SACENC_OK;
858
859 if ((hEnc == NULL) || (pSamples == NULL) || (pnSamplesFed == NULL)) {
860 error = SACENC_INVALID_HANDLE;
861 } else if (nSamples == 0) {
862 error = SACENC_INVALID_CONFIG; /* Flushing not implemented */
863 } else {
864 int ch;
865 const INT nChIn = hEnc->nInputChannels;
866 const INT nChInWithDmx = nChIn;
867 const INT samplesToFeed =
868 FDKmin(nSamples, hEnc->nSamplesNext - hEnc->nSamplesValid);
869 const INT nSamplesPerChannel = samplesToFeed / nChInWithDmx;
870
871 if ((samplesToFeed < 0) || (samplesToFeed % nChInWithDmx != 0) ||
872 (samplesToFeed > nChInWithDmx * (INT)hEnc->nFrameLength)) {
873 error = SACENC_INVALID_CONFIG;
874 goto bail;
875 }
876 int i;
877
878 const INT_PCM *pInput__FDK;
879 const INT_PCM *pInput2__FDK;
880
881 { /* no dmx align = default*/
882 pInput__FDK = pSamples;
883 pInput2__FDK = pSamples + (hEnc->nInputDelay * nChInWithDmx);
884 }
885
886 for (i = 0; i < hEnc->nInputChannels; i++) {
887 hEnc->staticTimeDomainDmxInScale[i] = hEnc->staticGainScale;
888 }
889
890 /***** N-channel-input *****/
891 for (ch = 0; ch < nChIn; ch++) {
892 /* Write delayed time signal into time signal buffer */
893 FDKmemcpy(&(hEnc->ppTimeSigIn__FDK[ch][0]),
894 &(hEnc->ppTimeSigDelayIn__FDK[ch][0]),
895 hEnc->nSurroundAnalysisBufferDelay * sizeof(INT_PCM));
896
897 if (isInputInterleaved) {
898 /* Add the new frame de-interleaved. Apply nSurroundAnalysisBufferDelay.
899 */
900 FDKmemcpy_flex(
901 &(hEnc->ppTimeSigIn__FDK[ch][hEnc->nSurroundAnalysisBufferDelay]),
902 1, pInput__FDK + ch, nChInWithDmx, hEnc->nInputDelay);
903 FDKmemcpy_flex(
904 &(hEnc->ppTimeSigIn__FDK[ch][hEnc->nSurroundAnalysisBufferDelay +
905 hEnc->nInputDelay]),
906 1, pInput2__FDK + ch, nChInWithDmx,
907 nSamplesPerChannel - hEnc->nInputDelay);
908 } else {
909 /* Input is already deinterleaved, just copy */
910 FDKmemcpy(
911 &(hEnc->ppTimeSigIn__FDK[ch][hEnc->nSurroundAnalysisBufferDelay]),
912 pInput__FDK + ch * inputBufferSizePerChannel,
913 hEnc->nInputDelay * sizeof(INT_PCM));
914 FDKmemcpy(
915 &(hEnc->ppTimeSigIn__FDK[ch][hEnc->nSurroundAnalysisBufferDelay +
916 hEnc->nInputDelay]),
917 pInput2__FDK + ch * inputBufferSizePerChannel,
918 (nSamplesPerChannel - hEnc->nInputDelay) * sizeof(INT_PCM));
919 }
920
921 /* Update time signal delay buffer */
922 FDKmemcpy(&(hEnc->ppTimeSigDelayIn__FDK[ch][0]),
923 &(hEnc->ppTimeSigIn__FDK[ch][hEnc->nFrameLength]),
924 hEnc->nSurroundAnalysisBufferDelay * sizeof(INT_PCM));
925 } /* for ch */
926
927 /***** No Arbitrary Downmix *****/
928 /* "Crude TD Dmx": Time DomainDownmix + NO Arbitrary Downmix, Delay Added at
929 * pOutputBuffer */
930 if ((hEnc->useTimeDomDownmix > 0)) {
931 if ((hEnc->useTimeDomDownmix == 1) || (hEnc->nInputChannels != 2)) {
932 error = SACENC_INVALID_CONFIG;
933 goto bail;
934 } else {
935 /* enhanced time domain downmix (for stereo input) */
936 if (hEnc->encMode == SACENC_212) {
937 if (pOutputSamples == NULL) {
938 error = SACENC_INVALID_HANDLE;
939 goto bail;
940 }
941
942 fdk_sacenc_apply_enhancedTimeDomainDmx(
943 hEnc->hEnhancedTimeDmx, hEnc->ppTimeSigIn__FDK, pOutputSamples,
944 hEnc->nSurroundAnalysisBufferDelay);
945 } else {
946 if (&hEnc->ppTimeSigOut__FDK[0][0] == NULL) {
947 error = SACENC_INVALID_HANDLE;
948 goto bail;
949 }
950
951 fdk_sacenc_apply_enhancedTimeDomainDmx(
952 hEnc->hEnhancedTimeDmx, hEnc->ppTimeSigIn__FDK,
953 &hEnc->ppTimeSigOut__FDK[0][0],
954 hEnc->nSurroundAnalysisBufferDelay);
955 }
956 }
957 }
958
959 /* update number of samples still to process */
960 hEnc->nSamplesValid += samplesToFeed;
961
962 /*return number of fed samples */
963 *pnSamplesFed = samplesToFeed;
964 }
965 bail:
966 return error;
967 }
968
FDK_sacenc_encode(const HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc,const FDK_bufDescr * inBufDesc,const FDK_bufDescr * outBufDesc,const SACENC_InArgs * inargs,SACENC_OutArgs * outargs)969 FDK_SACENC_ERROR FDK_sacenc_encode(const HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc,
970 const FDK_bufDescr *inBufDesc,
971 const FDK_bufDescr *outBufDesc,
972 const SACENC_InArgs *inargs,
973 SACENC_OutArgs *outargs) {
974 FDK_SACENC_ERROR error = SACENC_OK;
975
976 const INT_PCM *pInputSamples =
977 (const INT_PCM *)inBufDesc->ppBase[getBufDescIdx(
978 inBufDesc, (FDK_BUF_TYPE_INPUT | FDK_BUF_TYPE_PCM_DATA))];
979
980 INT_PCM *const pOutputSamples = (INT_PCM *)outBufDesc->ppBase[getBufDescIdx(
981 outBufDesc, (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_PCM_DATA))];
982
983 const int nOutputSamplesBufferSize =
984 outBufDesc->pBufSize[getBufDescIdx(
985 outBufDesc, (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_PCM_DATA))] /
986 outBufDesc->pEleSize[getBufDescIdx(
987 outBufDesc, (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_PCM_DATA))];
988
989 if ((hMp4SpaceEnc == NULL) || (pInputSamples == NULL)) {
990 error = SACENC_INVALID_HANDLE;
991 } else {
992 int nOutputSamples;
993 int i, ch, ps, winCnt, ts, slot;
994 INT currTransPos = -1;
995 SPATIALFRAME *pFrameData = NULL;
996
997 /* Improve Code Readability */
998 const int nChIn = hMp4SpaceEnc->nInputChannels;
999 const int nChInWithDmx = nChIn;
1000 const int nChOut = hMp4SpaceEnc->nOutputChannels;
1001 const int nSamplesPerChannel = inargs->nInputSamples / nChInWithDmx;
1002 const int nOutputSamplesMax = nSamplesPerChannel * nChOut;
1003 const int nFrameTimeSlots = hMp4SpaceEnc->nFrameTimeSlots;
1004
1005 INT encoderInputChScale[SACENC_MAX_INPUT_CHANNELS];
1006 INT nFrameTimeSlotsReduction = 0;
1007
1008 if (hMp4SpaceEnc->encMode == SACENC_212) {
1009 nFrameTimeSlotsReduction = hMp4SpaceEnc->nFrameTimeSlots >> 1;
1010 }
1011
1012 for (i = 0; i < nChIn; i++)
1013 encoderInputChScale[i] = hMp4SpaceEnc->pEncoderInputChScale[i];
1014
1015 /* Sanity Check */
1016 if ((0 != inargs->nInputSamples % nChInWithDmx)) {
1017 error = SACENC_INVALID_CONFIG;
1018 goto bail;
1019 }
1020
1021 /*
1022 * Get Frame Data Handle.
1023 */
1024
1025 /* get bitstream handle (for storage of cld's, icc's and so on)
1026 * get spatialframe 2 frames in the future; NOTE: this is necessary to
1027 * synchronise spatial data and audio data */
1028 if (NULL == (pFrameData = fdk_sacenc_getSpatialFrame(
1029 hMp4SpaceEnc->hBitstreamFormatter, WRITE_SPATIALFRAME))) {
1030 error = SACENC_INVALID_HANDLE;
1031 goto bail;
1032 }
1033
1034 /* Independent Frames Counters*/
1035 if (hMp4SpaceEnc->nDiscardOutFrames >
1036 0) { /* Independent Frames if they should be discarded, Reset Counter*/
1037 hMp4SpaceEnc->independencyCount =
1038 0; /* Reset the counter, first valid frame is an independent one*/
1039 hMp4SpaceEnc->independencyFlag = 1;
1040 } else { /*hMp4SpaceEnc->nDiscardOutFrames == 0*/
1041 hMp4SpaceEnc->independencyFlag =
1042 (hMp4SpaceEnc->independencyCount == 0) ? 1 : 0;
1043 if (hMp4SpaceEnc->independencyFactor > 0) {
1044 hMp4SpaceEnc->independencyCount++;
1045 hMp4SpaceEnc->independencyCount =
1046 hMp4SpaceEnc->independencyCount %
1047 ((int)hMp4SpaceEnc->independencyFactor);
1048 } else { /* independencyFactor == 0 */
1049 hMp4SpaceEnc->independencyCount = -1;
1050 }
1051 }
1052
1053 /*
1054 * Time signal preprocessing:
1055 * - Feed input buffer
1056 * - Prescale time signal
1057 * - Apply DC filter on input signal
1058 */
1059
1060 /* Feed, Deinterleave, Pre-Scale the input time signals */
1061 if (SACENC_OK !=
1062 (error = __FeedDeinterPreScale(
1063 hMp4SpaceEnc, pInputSamples, pOutputSamples, inargs->nInputSamples,
1064 inargs->isInputInterleaved, inargs->inputBufferSizePerChannel,
1065 &outargs->nSamplesConsumed))) {
1066 goto bail;
1067 }
1068
1069 if (hMp4SpaceEnc->nSamplesNext != hMp4SpaceEnc->nSamplesValid) {
1070 error = SACENC_INVALID_CONFIG;
1071 goto bail;
1072 }
1073
1074 if (hMp4SpaceEnc->encMode == SACENC_212 &&
1075 hMp4SpaceEnc->bEncMode_212_only) {
1076 for (ch = 0; ch < nChIn; ch++) {
1077 for (slot = 0; slot < nFrameTimeSlots; slot++) {
1078 setCplxVec(
1079 hMp4SpaceEnc->pppHybridIn__FDK
1080 [ch][hMp4SpaceEnc->nUpdateHybridPositionTimeSlots +
1081 nFrameTimeSlots - nFrameTimeSlotsReduction + slot],
1082 (FIXP_DBL)0, hMp4SpaceEnc->nHybridBands);
1083 }
1084 }
1085 }
1086
1087 /*
1088 * Time / Frequency:
1089 * - T/F audio input channels
1090 * - T/F arbitrary downmix input channels
1091 */
1092 for (ch = 0; ch < nChIn; ch++) {
1093 C_AALLOC_SCRATCH_START(pQmfInReal, FIXP_DBL, MAX_QMF_BANDS)
1094 C_AALLOC_SCRATCH_START(pQmfInImag, FIXP_DBL, MAX_QMF_BANDS)
1095 FIXP_GAIN *pPreGain =
1096 fdk_sacenc_getPreGainPtrFDK(hMp4SpaceEnc->hStaticGain);
1097
1098 for (ts = 0; ts < nFrameTimeSlots; ts++) {
1099 FIXP_DBL *pSpecReal;
1100 FIXP_DBL *pSpecImag;
1101
1102 INT_PCM *pTimeIn =
1103 &hMp4SpaceEnc->ppTimeSigIn__FDK[ch][(ts * hMp4SpaceEnc->nQmfBands)];
1104
1105 {
1106 /* Apply DC filter on input channels */
1107 if (SACENC_OK != (error = fdk_sacenc_applyDCFilter(
1108 hMp4SpaceEnc->phDCFilterSigIn[ch], pTimeIn,
1109 pTimeIn, hMp4SpaceEnc->nQmfBands))) {
1110 goto bail;
1111 }
1112 }
1113
1114 /* QMF filterbank */
1115 C_ALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, (MAX_QMF_BANDS << 1));
1116
1117 qmfAnalysisFilteringSlot(hMp4SpaceEnc->phQmfFiltIn__FDK[ch], pQmfInReal,
1118 pQmfInImag, pTimeIn, 1, pWorkBuffer);
1119
1120 C_ALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, (MAX_QMF_BANDS << 1));
1121
1122 pSpecReal = pQmfInReal;
1123 pSpecImag = pQmfInImag;
1124
1125 /* Apply pre-scale after filterbank */
1126 if (MAXVAL_GAIN != pPreGain[ch]) {
1127 for (i = 0; i < hMp4SpaceEnc->nHybridBands; i++) {
1128 hMp4SpaceEnc
1129 ->pppHybridIn__FDK[ch]
1130 [hMp4SpaceEnc->nAnalysisLookaheadTimeSlots +
1131 ts][i]
1132 .v.re = fMult(pSpecReal[i], pPreGain[ch]);
1133 hMp4SpaceEnc
1134 ->pppHybridIn__FDK[ch]
1135 [hMp4SpaceEnc->nAnalysisLookaheadTimeSlots +
1136 ts][i]
1137 .v.im = fMult(pSpecImag[i], pPreGain[ch]);
1138 }
1139 } else {
1140 for (i = 0; i < hMp4SpaceEnc->nHybridBands; i++) {
1141 hMp4SpaceEnc
1142 ->pppHybridIn__FDK[ch]
1143 [hMp4SpaceEnc->nAnalysisLookaheadTimeSlots +
1144 ts][i]
1145 .v.re = pSpecReal[i];
1146 hMp4SpaceEnc
1147 ->pppHybridIn__FDK[ch]
1148 [hMp4SpaceEnc->nAnalysisLookaheadTimeSlots +
1149 ts][i]
1150 .v.im = pSpecImag[i];
1151 }
1152 }
1153 } /* ts */
1154 C_AALLOC_SCRATCH_END(pQmfInImag, FIXP_DBL, MAX_QMF_BANDS)
1155 C_AALLOC_SCRATCH_END(pQmfInReal, FIXP_DBL, MAX_QMF_BANDS)
1156
1157 if (SACENC_OK != error) {
1158 goto bail;
1159 }
1160 } /* ch */
1161
1162 if (hMp4SpaceEnc->encMode == SACENC_212 &&
1163 hMp4SpaceEnc->bEncMode_212_only) {
1164 for (ch = 0; ch < nChIn; ch++) {
1165 for (slot = 0;
1166 slot < (int)(hMp4SpaceEnc->nUpdateHybridPositionTimeSlots +
1167 nFrameTimeSlots - nFrameTimeSlotsReduction);
1168 slot++) {
1169 copyCplxVec(hMp4SpaceEnc->pppHybridIn__FDK[ch][slot],
1170 hMp4SpaceEnc->pppHybridInStatic__FDK[ch][slot],
1171 hMp4SpaceEnc->nHybridBands);
1172 }
1173 }
1174 for (ch = 0; ch < nChIn; ch++) {
1175 for (slot = 0;
1176 slot < (int)(hMp4SpaceEnc->nUpdateHybridPositionTimeSlots +
1177 nFrameTimeSlots - nFrameTimeSlotsReduction);
1178 slot++) {
1179 copyCplxVec(
1180 hMp4SpaceEnc->pppHybridInStatic__FDK[ch][slot],
1181 hMp4SpaceEnc->pppHybridIn__FDK[ch][nFrameTimeSlots + slot],
1182 hMp4SpaceEnc->nHybridBands);
1183 }
1184 }
1185 }
1186
1187 /*
1188 * Onset Detection:
1189 * - detection of transients
1190 * - build framing
1191 */
1192 for (ch = 0; ch < nChIn; ch++) {
1193 if (ch != 3) { /* !LFE */
1194 if (SACENC_OK !=
1195 (error = fdk_sacenc_onsetDetect_Apply(
1196 hMp4SpaceEnc->phOnset[ch], nFrameTimeSlots,
1197 hMp4SpaceEnc->nHybridBands,
1198 &hMp4SpaceEnc->pppHybridIn__FDK
1199 [ch][hMp4SpaceEnc->nAnalysisLookaheadTimeSlots],
1200 encoderInputChScale[ch],
1201 hMp4SpaceEnc->trPrevPos[1], /* contains previous Transient */
1202 hMp4SpaceEnc->ppTrCurrPos[ch]))) {
1203 goto bail;
1204 }
1205
1206 if ((1) && (hMp4SpaceEnc->useFrameKeep == 0)) {
1207 hMp4SpaceEnc->ppTrCurrPos[ch][0] = -1;
1208 }
1209
1210 /* Find first Transient Position */
1211 if ((hMp4SpaceEnc->ppTrCurrPos[ch][0] >= 0) &&
1212 ((currTransPos < 0) ||
1213 (hMp4SpaceEnc->ppTrCurrPos[ch][0] < currTransPos))) {
1214 currTransPos = hMp4SpaceEnc->ppTrCurrPos[ch][0];
1215 }
1216 } /* !LFE */
1217 } /* ch */
1218
1219 if (hMp4SpaceEnc->useFrameKeep == 1) {
1220 if ((currTransPos != -1) || (hMp4SpaceEnc->independencyFlag == 1)) {
1221 hMp4SpaceEnc->avoid_keep = NUM_KEEP_WINDOWS;
1222 currTransPos = -1;
1223 }
1224 }
1225
1226 /* Save previous Transient Position */
1227 hMp4SpaceEnc->trPrevPos[0] =
1228 FDKmax(-1, hMp4SpaceEnc->trPrevPos[1] - (INT)nFrameTimeSlots);
1229 hMp4SpaceEnc->trPrevPos[1] = currTransPos;
1230
1231 /* Update Onset Detection Energy Buffer */
1232 for (ch = 0; ch < nChIn; ch++) {
1233 if (SACENC_OK != (error = fdk_sacenc_onsetDetect_Update(
1234 hMp4SpaceEnc->phOnset[ch], nFrameTimeSlots))) {
1235 goto bail;
1236 }
1237 }
1238
1239 /* Framing */
1240 if (SACENC_OK !=
1241 (error = fdk_sacenc_frameWindow_GetWindow(
1242 hMp4SpaceEnc->hFrameWindow, hMp4SpaceEnc->trPrevPos,
1243 nFrameTimeSlots, &pFrameData->framingInfo,
1244 hMp4SpaceEnc->pFrameWindowAna__FDK, &hMp4SpaceEnc->frameWinList,
1245 hMp4SpaceEnc->avoid_keep))) {
1246 goto bail;
1247 }
1248
1249 /*
1250 * MPS Processing:
1251 */
1252 for (ps = 0, winCnt = 0; ps < hMp4SpaceEnc->frameWinList.n; ++ps) {
1253 /* Analysis Windowing */
1254 if (hMp4SpaceEnc->frameWinList.dat[ps].hold == FW_HOLD) {
1255 /* ************************************** */
1256 /* ONLY COPY AND HOLD PREVIOUS PARAMETERS */
1257 if (SACENC_OK != (error = fdk_sacenc_duplicateParameterSet(
1258 &hMp4SpaceEnc->saveFrame, 0, pFrameData, ps))) {
1259 goto bail;
1260 }
1261
1262 } else { /* !FW_HOLD */
1263 /* ************************************** */
1264 /* NEW WINDOW */
1265
1266 INT nAnalysisLengthTimeSlots, analysisStartTimeSlot;
1267
1268 nAnalysisLengthTimeSlots = getAnalysisLengthTimeSlots(
1269 hMp4SpaceEnc->pFrameWindowAna__FDK[winCnt],
1270 hMp4SpaceEnc->nAnalysisLengthTimeSlots);
1271
1272 analysisStartTimeSlot =
1273 getAnalysisStartTimeSlot(hMp4SpaceEnc->pFrameWindowAna__FDK[winCnt],
1274 hMp4SpaceEnc->nAnalysisLengthTimeSlots);
1275
1276 /* perform main signal analysis windowing in
1277 * fdk_sacenc_spaceTree_Apply() */
1278 FIXP_WIN *pFrameWindowAna__FDK =
1279 hMp4SpaceEnc->pFrameWindowAna__FDK[winCnt];
1280 FIXP_DPK ***pppHybridIn__FDK = hMp4SpaceEnc->pppHybridIn__FDK;
1281 FIXP_DPK ***pppProcDataIn__FDK = hMp4SpaceEnc->pppProcDataIn__FDK;
1282
1283 if (hMp4SpaceEnc->encMode == SACENC_212 &&
1284 hMp4SpaceEnc->bEncMode_212_only) {
1285 pppProcDataIn__FDK = pppHybridIn__FDK;
1286 }
1287
1288 if (SACENC_OK !=
1289 (error = fdk_sacenc_spaceTree_Apply(
1290 hMp4SpaceEnc->hSpaceTree, ps, nChIn, nAnalysisLengthTimeSlots,
1291 analysisStartTimeSlot, hMp4SpaceEnc->nHybridBands,
1292 pFrameWindowAna__FDK, pppHybridIn__FDK,
1293 pppProcDataIn__FDK, /* multi-channel input */
1294 pFrameData, hMp4SpaceEnc->avoid_keep, encoderInputChScale))) {
1295 goto bail;
1296 }
1297
1298 /* Save spatial frame for potential hold parameter set */
1299 if (SACENC_OK != (error = fdk_sacenc_duplicateParameterSet(
1300 pFrameData, ps, &hMp4SpaceEnc->saveFrame, 0))) {
1301 goto bail;
1302 }
1303
1304 ++winCnt;
1305 }
1306 if (hMp4SpaceEnc->avoid_keep > 0) {
1307 hMp4SpaceEnc->avoid_keep--;
1308 }
1309 } /* Loop over Parameter Sets */
1310 /* ---- End of Processing Loop ---- */
1311
1312 /*
1313 * Update hybridInReal/Imag buffer and do the same for arbDmx
1314 * this means to move the hybrid data of the current frame to the beginning
1315 * of the 2*nFrameLength-long buffer
1316 */
1317 if (!(hMp4SpaceEnc->encMode == SACENC_212 &&
1318 hMp4SpaceEnc->bEncMode_212_only)) {
1319 for (ch = 0; ch < nChIn; ch++) { /* for automatic downmix */
1320 for (slot = 0;
1321 slot < (int)(hMp4SpaceEnc->nUpdateHybridPositionTimeSlots +
1322 nFrameTimeSlots - nFrameTimeSlotsReduction);
1323 slot++) {
1324 copyCplxVec(
1325 hMp4SpaceEnc->pppHybridIn__FDK[ch][slot],
1326 hMp4SpaceEnc->pppHybridIn__FDK[ch][nFrameTimeSlots + slot],
1327 hMp4SpaceEnc->nHybridBands);
1328 }
1329 for (slot = 0; slot < nFrameTimeSlots; slot++) {
1330 setCplxVec(
1331 hMp4SpaceEnc->pppHybridIn__FDK
1332 [ch][hMp4SpaceEnc->nUpdateHybridPositionTimeSlots +
1333 nFrameTimeSlots - nFrameTimeSlotsReduction + slot],
1334 (FIXP_DBL)0, hMp4SpaceEnc->nHybridBands);
1335 }
1336 }
1337 }
1338 /*
1339 * Spatial Tonality:
1340 */
1341 {
1342 /* Smooth config off. */
1343 FDKmemclear(&pFrameData->smgData, sizeof(pFrameData->smgData));
1344 }
1345
1346 /*
1347 * Create bitstream
1348 * - control independecy flag
1349 * - write spatial frame
1350 * - return bitstream
1351 */
1352 UCHAR *pBitstreamDelayBuffer;
1353
1354 if (hMp4SpaceEnc->encMode == SACENC_212) {
1355 /* no bitstream delay buffer for SACENC_212 mode, write bitstream directly
1356 * into the sacOutBuffer buffer which is provided by the core routine */
1357 pBitstreamDelayBuffer = (UCHAR *)outBufDesc->ppBase[1];
1358 } else {
1359 /* bitstream delay is handled in ppBitstreamDelayBuffer buffer */
1360 pBitstreamDelayBuffer =
1361 hMp4SpaceEnc
1362 ->ppBitstreamDelayBuffer[hMp4SpaceEnc->nBitstreamBufferWrite];
1363 }
1364 if (pBitstreamDelayBuffer == NULL) {
1365 error = SACENC_INVALID_HANDLE;
1366 goto bail;
1367 }
1368
1369 pFrameData->bsIndependencyFlag = hMp4SpaceEnc->independencyFlag;
1370
1371 if (SACENC_OK !=
1372 (error = fdk_sacenc_writeSpatialFrame(
1373 pBitstreamDelayBuffer, MAX_MPEGS_BYTES,
1374 &hMp4SpaceEnc->pnOutputBits[hMp4SpaceEnc->nBitstreamBufferWrite],
1375 hMp4SpaceEnc->hBitstreamFormatter))) {
1376 goto bail;
1377 }
1378
1379 /* return bitstream info */
1380 if ((hMp4SpaceEnc->nDiscardOutFrames == 0) &&
1381 (getBufDescIdx(outBufDesc,
1382 (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_BS_DATA)) != -1)) {
1383 const INT idx = getBufDescIdx(
1384 outBufDesc, (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_BS_DATA));
1385 const INT outBits =
1386 hMp4SpaceEnc->pnOutputBits[hMp4SpaceEnc->nBitstreamBufferRead];
1387
1388 if (((outBits + 7) / 8) >
1389 (INT)(outBufDesc->pBufSize[idx] / outBufDesc->pEleSize[idx])) {
1390 outargs->nOutputBits = 0;
1391 error = SACENC_ENCODE_ERROR;
1392 goto bail;
1393 }
1394
1395 /* return bitstream buffer, copy delayed bitstream for all configurations
1396 * except for the SACENC_212 mode */
1397 if (hMp4SpaceEnc->encMode != SACENC_212) {
1398 FDKmemcpy(
1399 outBufDesc->ppBase[idx],
1400 hMp4SpaceEnc
1401 ->ppBitstreamDelayBuffer[hMp4SpaceEnc->nBitstreamBufferRead],
1402 (outBits + 7) / 8);
1403 }
1404
1405 /* return number of valid bits */
1406 outargs->nOutputBits = outBits;
1407 } else { /* No spatial data should be returned if the current frame is to be
1408 discarded. */
1409 outargs->nOutputBits = 0;
1410 }
1411
1412 /* update pointers */
1413 hMp4SpaceEnc->nBitstreamBufferRead =
1414 (hMp4SpaceEnc->nBitstreamBufferRead + 1) %
1415 hMp4SpaceEnc->nBitstreamDelayBuffer;
1416 hMp4SpaceEnc->nBitstreamBufferWrite =
1417 (hMp4SpaceEnc->nBitstreamBufferWrite + 1) %
1418 hMp4SpaceEnc->nBitstreamDelayBuffer;
1419
1420 /* Set Output Parameters */
1421 nOutputSamples =
1422 (hMp4SpaceEnc->nDiscardOutFrames == 0)
1423 ? (nOutputSamplesMax)
1424 : 0; /* don't output samples in case frames to be discarded */
1425 if (nOutputSamples > nOutputSamplesBufferSize) {
1426 error = SACENC_INVALID_CONFIG;
1427 goto bail;
1428 }
1429 outargs->nOutputSamples = nOutputSamples;
1430
1431 { /* !bQmfOutput */
1432
1433 if (hMp4SpaceEnc->encMode != SACENC_212) {
1434 /* delay output samples and interleave them */
1435 /* note: in case of arbitrary downmix this will always be processed,
1436 * because nOutputSamples != 0, even if bDMXAlign is switched on */
1437 /* always run copy-func, so nOutputSamplesMax instead of nOutputSamples
1438 */
1439 for (ch = 0; ch < nChOut; ch++) {
1440 FDKmemcpy_flex(
1441 &hMp4SpaceEnc->pOutputDelayBuffer__FDK
1442 [ch + (hMp4SpaceEnc->nOutputBufferDelay) * nChOut],
1443 nChOut, hMp4SpaceEnc->ppTimeSigOut__FDK[ch], 1,
1444 nOutputSamplesMax / nChOut);
1445 }
1446
1447 /* write delayed data in output pcm stream */
1448 /* always calculate, limiter must have a lookahead!!! */
1449 FDKmemcpy(pOutputSamples, hMp4SpaceEnc->pOutputDelayBuffer__FDK,
1450 nOutputSamplesMax * sizeof(INT_PCM));
1451
1452 /* update delay buffer (move back end to the beginning of the buffer) */
1453 FDKmemmove(
1454 hMp4SpaceEnc->pOutputDelayBuffer__FDK,
1455 &hMp4SpaceEnc->pOutputDelayBuffer__FDK[nOutputSamplesMax],
1456 nChOut * (hMp4SpaceEnc->nOutputBufferDelay) * sizeof(INT_PCM));
1457 }
1458
1459 if (hMp4SpaceEnc->useTimeDomDownmix <= 0) {
1460 if (SACENC_OK != (error = fdk_sacenc_staticPostGain_ApplyFDK(
1461 hMp4SpaceEnc->hStaticGain, pOutputSamples,
1462 nOutputSamplesMax, 0))) {
1463 goto bail;
1464 }
1465 }
1466
1467 } /* !bQmfOutput */
1468
1469 if (hMp4SpaceEnc->nDiscardOutFrames > 0) {
1470 hMp4SpaceEnc->nDiscardOutFrames--;
1471 }
1472
1473 /* Invalidate Input Buffer */
1474 hMp4SpaceEnc->nSamplesValid = 0;
1475
1476 } /* valid handle */
1477 bail:
1478 return error;
1479 }
1480
FDK_sacenc_close(HANDLE_MP4SPACE_ENCODER * phMp4SpaceEnc)1481 FDK_SACENC_ERROR FDK_sacenc_close(HANDLE_MP4SPACE_ENCODER *phMp4SpaceEnc) {
1482 FDK_SACENC_ERROR error = SACENC_OK;
1483
1484 if (NULL != phMp4SpaceEnc) {
1485 if (NULL != *phMp4SpaceEnc) {
1486 int ch, i;
1487 HANDLE_MP4SPACE_ENCODER const hEnc = *phMp4SpaceEnc;
1488
1489 if (hEnc->pParameterBand2HybridBandOffset != NULL) {
1490 FDK_FREE_MEMORY_1D(hEnc->pParameterBand2HybridBandOffset);
1491 }
1492 /* Free Analysis Filterbank Structs */
1493 if (hEnc->pEncoderInputChScale != NULL) {
1494 FDK_FREE_MEMORY_1D(hEnc->pEncoderInputChScale);
1495 }
1496 if (hEnc->staticTimeDomainDmxInScale != NULL) {
1497 FDK_FREE_MEMORY_1D(hEnc->staticTimeDomainDmxInScale);
1498 }
1499 if (hEnc->phQmfFiltIn__FDK != NULL) {
1500 for (ch = 0; ch < hEnc->setup.maxChIn; ch++) {
1501 if (hEnc->phQmfFiltIn__FDK[ch] != NULL) {
1502 if (hEnc->phQmfFiltIn__FDK[ch]->FilterStates != NULL) {
1503 FDK_FREE_MEMORY_1D(hEnc->phQmfFiltIn__FDK[ch]->FilterStates);
1504 }
1505 FDK_FREE_MEMORY_1D(hEnc->phQmfFiltIn__FDK[ch]);
1506 }
1507 }
1508 FDK_FREE_MEMORY_1D(hEnc->phQmfFiltIn__FDK);
1509 }
1510 for (ch = 0; ch < hEnc->setup.maxChIn; ch++) {
1511 if (NULL != hEnc->phDCFilterSigIn[ch]) {
1512 fdk_sacenc_destroyDCFilter(&hEnc->phDCFilterSigIn[ch]);
1513 }
1514 }
1515 /* Close Onset Detection */
1516 for (ch = 0; ch < hEnc->setup.maxChIn; ch++) {
1517 if (NULL != hEnc->phOnset[ch]) {
1518 fdk_sacenc_onsetDetect_Close(&hEnc->phOnset[ch]);
1519 }
1520 }
1521 if (hEnc->ppTrCurrPos) {
1522 FDK_FREE_MEMORY_2D(hEnc->ppTrCurrPos);
1523 }
1524 if (hEnc->hFrameWindow) {
1525 fdk_sacenc_frameWindow_Destroy(&hEnc->hFrameWindow);
1526 }
1527 /* Close Space Tree */
1528 if (NULL != hEnc->hSpaceTree) {
1529 fdk_sacenc_spaceTree_Close(&hEnc->hSpaceTree);
1530 }
1531 if (NULL != hEnc->hEnhancedTimeDmx) {
1532 fdk_sacenc_close_enhancedTimeDomainDmx(&hEnc->hEnhancedTimeDmx);
1533 }
1534 /* Close Static Gain */
1535 if (NULL != hEnc->hStaticGain) {
1536 fdk_sacenc_staticGain_Close(&hEnc->hStaticGain);
1537 }
1538 if (NULL != hEnc->hStaticGainConfig) {
1539 fdk_sacenc_staticGain_CloseConfig(&hEnc->hStaticGainConfig);
1540 }
1541 /* Close Delay*/
1542 if (NULL != hEnc->hDelay) {
1543 fdk_sacenc_delay_Close(&hEnc->hDelay);
1544 }
1545 /* Delete Bitstream Stuff */
1546 if (NULL != hEnc->hBitstreamFormatter) {
1547 fdk_sacenc_destroySpatialBitstreamEncoder(&(hEnc->hBitstreamFormatter));
1548 }
1549 if (hEnc->pppHybridIn__FDK != NULL) {
1550 if (hEnc->setup.bEncMode_212 == 1) {
1551 FDK_FREE_MEMORY_3D(hEnc->pppHybridIn__FDK);
1552 FDK_FREE_MEMORY_3D(hEnc->pppHybridInStatic__FDK);
1553 } else {
1554 FDK_FREE_MEMORY_3D(hEnc->pppHybridIn__FDK);
1555 }
1556 }
1557 if (hEnc->pppProcDataIn__FDK != NULL) {
1558 FDK_FREE_MEMORY_3D(hEnc->pppProcDataIn__FDK);
1559 }
1560 if (hEnc->pOutputDelayBuffer__FDK != NULL) {
1561 FDK_FREE_MEMORY_1D(hEnc->pOutputDelayBuffer__FDK);
1562 }
1563 if (hEnc->ppTimeSigIn__FDK != NULL) {
1564 { FDK_FREE_MEMORY_2D(hEnc->ppTimeSigIn__FDK); }
1565 }
1566 if (hEnc->ppTimeSigDelayIn__FDK != NULL) {
1567 FDK_FREE_MEMORY_2D(hEnc->ppTimeSigDelayIn__FDK);
1568 }
1569 if (hEnc->ppTimeSigOut__FDK != NULL) {
1570 FDK_FREE_MEMORY_2D(hEnc->ppTimeSigOut__FDK);
1571 }
1572 for (i = 0; i < MAX_NUM_PARAMS; i++) {
1573 if (hEnc->pFrameWindowAna__FDK[i] != NULL) {
1574 FDK_FREE_MEMORY_1D(hEnc->pFrameWindowAna__FDK[i]);
1575 }
1576 }
1577 if (hEnc->pnOutputBits != NULL) {
1578 FDK_FREE_MEMORY_1D(hEnc->pnOutputBits);
1579 }
1580 if (hEnc->ppBitstreamDelayBuffer != NULL) {
1581 FDK_FREE_MEMORY_2D(hEnc->ppBitstreamDelayBuffer);
1582 }
1583 if (hEnc->sscBuf.pSsc != NULL) {
1584 FDK_FREE_MEMORY_1D(hEnc->sscBuf.pSsc);
1585 }
1586 FDK_FREE_MEMORY_1D(*phMp4SpaceEnc);
1587 }
1588 }
1589
1590 return error;
1591 }
1592
1593 /*-----------------------------------------------------------------------------
1594 functionname: mp4SpaceEnc_InitDelayCompensation()
1595 description: initialzes delay compensation
1596 returns: noError on success, an apropriate error code else
1597 -----------------------------------------------------------------------------*/
mp4SpaceEnc_InitDelayCompensation(HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc,const INT coreCoderDelay)1598 static FDK_SACENC_ERROR mp4SpaceEnc_InitDelayCompensation(
1599 HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, const INT coreCoderDelay) {
1600 FDK_SACENC_ERROR error = SACENC_OK;
1601
1602 /* Sanity Check */
1603 if (hMp4SpaceEnc == NULL) {
1604 error = SACENC_INVALID_HANDLE;
1605 } else {
1606 hMp4SpaceEnc->coreCoderDelay = coreCoderDelay;
1607
1608 if (SACENC_OK != (error = fdk_sacenc_delay_Init(
1609 hMp4SpaceEnc->hDelay, hMp4SpaceEnc->nQmfBands,
1610 hMp4SpaceEnc->nFrameLength, coreCoderDelay,
1611 hMp4SpaceEnc->timeAlignment))) {
1612 goto bail;
1613 }
1614
1615 fdk_sacenc_delay_SetDmxAlign(hMp4SpaceEnc->hDelay, 0);
1616 fdk_sacenc_delay_SetTimeDomDmx(
1617 hMp4SpaceEnc->hDelay, (hMp4SpaceEnc->useTimeDomDownmix >= 1) ? 1 : 0);
1618 fdk_sacenc_delay_SetMinimizeDelay(hMp4SpaceEnc->hDelay, 1);
1619
1620 if (SACENC_OK != (error = fdk_sacenc_delay_SubCalulateBufferDelays(
1621 hMp4SpaceEnc->hDelay))) {
1622 goto bail;
1623 }
1624
1625 /* init output delay compensation */
1626 hMp4SpaceEnc->nBitstreamDelayBuffer =
1627 fdk_sacenc_delay_GetBitstreamFrameBufferSize(hMp4SpaceEnc->hDelay);
1628 hMp4SpaceEnc->nOutputBufferDelay =
1629 fdk_sacenc_delay_GetOutputAudioBufferDelay(hMp4SpaceEnc->hDelay);
1630 hMp4SpaceEnc->nSurroundAnalysisBufferDelay =
1631 fdk_sacenc_delay_GetSurroundAnalysisBufferDelay(hMp4SpaceEnc->hDelay);
1632 hMp4SpaceEnc->nBitstreamBufferRead = 0;
1633 hMp4SpaceEnc->nBitstreamBufferWrite =
1634 hMp4SpaceEnc->nBitstreamDelayBuffer - 1;
1635
1636 if (hMp4SpaceEnc->encMode == SACENC_212) {
1637 /* mode 212 expects no bitstream delay */
1638 if (hMp4SpaceEnc->nBitstreamBufferWrite !=
1639 hMp4SpaceEnc->nBitstreamBufferRead) {
1640 error = SACENC_PARAM_ERROR;
1641 goto bail;
1642 }
1643
1644 /* mode 212 expects no output buffer delay */
1645 if (hMp4SpaceEnc->nOutputBufferDelay != 0) {
1646 error = SACENC_PARAM_ERROR;
1647 goto bail;
1648 }
1649 }
1650
1651 /*** Input delay to obtain a net encoder delay that is a multiple
1652 of the used framelength to ensure synchronization of framing
1653 in artistic down-mix with the corresponding spatial data. ***/
1654 hMp4SpaceEnc->nDiscardOutFrames =
1655 fdk_sacenc_delay_GetDiscardOutFrames(hMp4SpaceEnc->hDelay);
1656 hMp4SpaceEnc->nInputDelay =
1657 fdk_sacenc_delay_GetDmxAlignBufferDelay(hMp4SpaceEnc->hDelay);
1658
1659 /* reset independency Flag counter */
1660 hMp4SpaceEnc->independencyCount = 0;
1661 hMp4SpaceEnc->independencyFlag = 1;
1662
1663 int i;
1664
1665 /* write some parameters to bitstream */
1666 for (i = 0; i < hMp4SpaceEnc->nBitstreamDelayBuffer - 1; i++) {
1667 SPATIALFRAME *pFrameData = NULL;
1668
1669 if (NULL == (pFrameData = fdk_sacenc_getSpatialFrame(
1670 hMp4SpaceEnc->hBitstreamFormatter, READ_SPATIALFRAME))) {
1671 error = SACENC_INVALID_HANDLE;
1672 goto bail;
1673 }
1674
1675 pFrameData->bsIndependencyFlag = 1;
1676 pFrameData->framingInfo.numParamSets = 1;
1677 pFrameData->framingInfo.bsFramingType = 0;
1678
1679 fdk_sacenc_writeSpatialFrame(
1680 hMp4SpaceEnc->ppBitstreamDelayBuffer[i], MAX_MPEGS_BYTES,
1681 &hMp4SpaceEnc->pnOutputBits[i], hMp4SpaceEnc->hBitstreamFormatter);
1682 }
1683
1684 if ((hMp4SpaceEnc->nInputDelay > MAX_DELAY_INPUT) ||
1685 (hMp4SpaceEnc->nOutputBufferDelay > MAX_DELAY_OUTPUT) ||
1686 (hMp4SpaceEnc->nSurroundAnalysisBufferDelay >
1687 MAX_DELAY_SURROUND_ANALYSIS) ||
1688 (hMp4SpaceEnc->nBitstreamDelayBuffer > MAX_BITSTREAM_DELAY)) {
1689 error = SACENC_INIT_ERROR;
1690 goto bail;
1691 }
1692 }
1693
1694 bail:
1695
1696 return error;
1697 }
1698
__mapQuantMode(const MP4SPACEENC_QUANTMODE quantMode)1699 static QUANTMODE __mapQuantMode(const MP4SPACEENC_QUANTMODE quantMode) {
1700 QUANTMODE bsQuantMode = QUANTMODE_INVALID;
1701
1702 switch (quantMode) {
1703 case SACENC_QUANTMODE_FINE:
1704 bsQuantMode = QUANTMODE_FINE;
1705 break;
1706 case SACENC_QUANTMODE_EBQ1:
1707 bsQuantMode = QUANTMODE_EBQ1;
1708 break;
1709 case SACENC_QUANTMODE_EBQ2:
1710 bsQuantMode = QUANTMODE_EBQ2;
1711 break;
1712 case SACENC_QUANTMODE_RSVD3:
1713 case SACENC_QUANTMODE_INVALID:
1714 default:
1715 bsQuantMode = QUANTMODE_INVALID;
1716 } /* switch hEnc->quantMode */
1717
1718 return bsQuantMode;
1719 }
1720
FillSpatialSpecificConfig(const HANDLE_MP4SPACE_ENCODER hEnc,SPATIALSPECIFICCONFIG * const hSsc)1721 static FDK_SACENC_ERROR FillSpatialSpecificConfig(
1722 const HANDLE_MP4SPACE_ENCODER hEnc, SPATIALSPECIFICCONFIG *const hSsc) {
1723 FDK_SACENC_ERROR error = SACENC_OK;
1724
1725 if ((NULL == hEnc) || (NULL == hSsc)) {
1726 error = SACENC_INVALID_HANDLE;
1727 } else {
1728 SPACE_TREE_DESCRIPTION spaceTreeDescription;
1729 int i;
1730
1731 /* Get tree description */
1732 if (SACENC_OK != (error = fdk_sacenc_spaceTree_GetDescription(
1733 hEnc->hSpaceTree, &spaceTreeDescription))) {
1734 goto bail;
1735 }
1736
1737 /* Fill SSC */
1738 FDKmemclear(hSsc, sizeof(SPATIALSPECIFICCONFIG)); /* reset */
1739
1740 hSsc->numBands = hEnc->spaceTreeSetup.nParamBands; /* for bsFreqRes */
1741
1742 /* Fill tree configuration */
1743 hSsc->treeDescription.numOttBoxes = spaceTreeDescription.nOttBoxes;
1744 hSsc->treeDescription.numInChan = spaceTreeDescription.nInChannels;
1745 hSsc->treeDescription.numOutChan = spaceTreeDescription.nOutChannels;
1746
1747 for (i = 0; i < SACENC_MAX_NUM_BOXES; i++) {
1748 hSsc->ottConfig[i].bsOttBands = hSsc->numBands;
1749 }
1750
1751 switch (hEnc->encMode) {
1752 case SACENC_212:
1753 hSsc->bsTreeConfig = TREE_212;
1754 break;
1755 case SACENC_INVALID_MODE:
1756 default:
1757 error = SACENC_INVALID_CONFIG;
1758 goto bail;
1759 }
1760
1761 hSsc->bsSamplingFrequency =
1762 hEnc->nSampleRate; /* for bsSamplingFrequencyIndex */
1763 hSsc->bsFrameLength = hEnc->nFrameTimeSlots - 1;
1764
1765 /* map decorr type */
1766 if (DECORR_INVALID ==
1767 (hSsc->bsDecorrConfig = mp4SpaceEnc_GetDecorrConfig(hEnc->encMode))) {
1768 error = SACENC_INVALID_CONFIG;
1769 goto bail;
1770 }
1771
1772 /* map quantMode */
1773 if (QUANTMODE_INVALID ==
1774 (hSsc->bsQuantMode = __mapQuantMode(hEnc->quantMode))) {
1775 error = SACENC_INVALID_CONFIG;
1776 goto bail;
1777 }
1778
1779 /* Configure Gains*/
1780 hSsc->bsFixedGainDMX = fdk_sacenc_staticGain_GetDmxGain(hEnc->hStaticGain);
1781 hSsc->bsEnvQuantMode = 0;
1782
1783 } /* valid handle */
1784
1785 bail:
1786 return error;
1787 }
1788
mp4SpaceEnc_FillSpaceTreeSetup(const HANDLE_MP4SPACE_ENCODER hEnc,SPACE_TREE_SETUP * const hSpaceTreeSetup)1789 static FDK_SACENC_ERROR mp4SpaceEnc_FillSpaceTreeSetup(
1790 const HANDLE_MP4SPACE_ENCODER hEnc,
1791 SPACE_TREE_SETUP *const hSpaceTreeSetup) {
1792 FDK_SACENC_ERROR error = SACENC_OK;
1793
1794 /* Sanity Check */
1795 if (NULL == hEnc || NULL == hSpaceTreeSetup) {
1796 error = SACENC_INVALID_HANDLE;
1797 } else {
1798 QUANTMODE tmpQuantmode = QUANTMODE_INVALID;
1799
1800 /* map quantMode */
1801 if (QUANTMODE_INVALID == (tmpQuantmode = __mapQuantMode(hEnc->quantMode))) {
1802 error = SACENC_INVALID_CONFIG;
1803 goto bail;
1804 }
1805
1806 hSpaceTreeSetup->nParamBands = hEnc->nParamBands;
1807 hSpaceTreeSetup->bUseCoarseQuantTtoCld = hEnc->useCoarseQuantCld;
1808 hSpaceTreeSetup->bUseCoarseQuantTtoIcc = hEnc->useCoarseQuantIcc;
1809 hSpaceTreeSetup->quantMode = tmpQuantmode;
1810 hSpaceTreeSetup->nHybridBandsMax = hEnc->nHybridBands;
1811
1812 switch (hEnc->encMode) {
1813 case SACENC_212:
1814 hSpaceTreeSetup->mode = SPACETREE_212;
1815 hSpaceTreeSetup->nChannelsInMax = 2;
1816 break;
1817 case SACENC_INVALID_MODE:
1818 default:
1819 error = SACENC_INVALID_CONFIG;
1820 goto bail;
1821 } /* switch hEnc->encMode */
1822
1823 } /* valid handle */
1824 bail:
1825 return error;
1826 }
1827
FDK_sacenc_getInfo(const HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc,MP4SPACEENC_INFO * const pInfo)1828 FDK_SACENC_ERROR FDK_sacenc_getInfo(const HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc,
1829 MP4SPACEENC_INFO *const pInfo) {
1830 FDK_SACENC_ERROR error = SACENC_OK;
1831
1832 if ((NULL == hMp4SpaceEnc) || (NULL == pInfo)) {
1833 error = SACENC_INVALID_HANDLE;
1834 } else {
1835 pInfo->nSampleRate = hMp4SpaceEnc->nSampleRate;
1836 pInfo->nSamplesFrame = hMp4SpaceEnc->nFrameLength;
1837 pInfo->nTotalInputChannels = hMp4SpaceEnc->nInputChannels;
1838 pInfo->nDmxDelay = fdk_sacenc_delay_GetInfoDmxDelay(hMp4SpaceEnc->hDelay);
1839 pInfo->nCodecDelay =
1840 fdk_sacenc_delay_GetInfoCodecDelay(hMp4SpaceEnc->hDelay);
1841 pInfo->nDecoderDelay =
1842 fdk_sacenc_delay_GetInfoDecoderDelay(hMp4SpaceEnc->hDelay);
1843 pInfo->nPayloadDelay =
1844 fdk_sacenc_delay_GetBitstreamFrameBufferSize(hMp4SpaceEnc->hDelay) - 1;
1845 pInfo->nDiscardOutFrames = hMp4SpaceEnc->nDiscardOutFrames;
1846
1847 pInfo->pSscBuf = &hMp4SpaceEnc->sscBuf;
1848 }
1849 return error;
1850 }
1851
FDK_sacenc_setParam(HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc,const SPACEENC_PARAM param,const UINT value)1852 FDK_SACENC_ERROR FDK_sacenc_setParam(HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc,
1853 const SPACEENC_PARAM param,
1854 const UINT value) {
1855 FDK_SACENC_ERROR error = SACENC_OK;
1856
1857 /* check encoder handle */
1858 if (hMp4SpaceEnc == NULL) {
1859 error = SACENC_INVALID_HANDLE;
1860 goto bail;
1861 }
1862
1863 /* apply param value */
1864 switch (param) {
1865 case SACENC_LOWDELAY:
1866 if (!((value == 0) || (value == 1) || (value == 2))) {
1867 error = SACENC_INVALID_CONFIG;
1868 break;
1869 }
1870 hMp4SpaceEnc->user.bLdMode = value;
1871 break;
1872
1873 case SACENC_ENC_MODE:
1874 switch ((MP4SPACEENC_MODE)value) {
1875 case SACENC_212:
1876 hMp4SpaceEnc->user.encMode = (MP4SPACEENC_MODE)value;
1877 break;
1878 default:
1879 error = SACENC_INVALID_CONFIG;
1880 }
1881 break;
1882
1883 case SACENC_SAMPLERATE:
1884 if (((int)value < 0) ||
1885 ((int)value > hMp4SpaceEnc->setup.maxSamplingrate)) {
1886 error = SACENC_INVALID_CONFIG;
1887 break;
1888 }
1889 hMp4SpaceEnc->user.sampleRate = value;
1890 break;
1891
1892 case SACENC_FRAME_TIME_SLOTS:
1893 if (((int)value < 0) ||
1894 ((int)value > hMp4SpaceEnc->setup.maxFrameTimeSlots)) {
1895 error = SACENC_INVALID_CONFIG;
1896 break;
1897 }
1898 hMp4SpaceEnc->user.frameTimeSlots = value;
1899 break;
1900
1901 case SACENC_PARAM_BANDS:
1902 switch ((MP4SPACEENC_BANDS_CONFIG)value) {
1903 case SACENC_BANDS_4:
1904 case SACENC_BANDS_5:
1905 case SACENC_BANDS_7:
1906 case SACENC_BANDS_9:
1907 case SACENC_BANDS_12:
1908 case SACENC_BANDS_15:
1909 case SACENC_BANDS_23:
1910 hMp4SpaceEnc->user.nParamBands = (MP4SPACEENC_BANDS_CONFIG)value;
1911 break;
1912 default:
1913 error = SACENC_INVALID_CONFIG;
1914 }
1915 break;
1916
1917 case SACENC_TIME_DOM_DMX:
1918 if (!((value == 0) || (value == 2))) {
1919 error = SACENC_INVALID_CONFIG;
1920 break;
1921 }
1922 hMp4SpaceEnc->user.bTimeDomainDmx = value;
1923 break;
1924
1925 case SACENC_DMX_GAIN:
1926 if (!((value == 0) || (value == 1) || (value == 2) || (value == 3) ||
1927 (value == 4) || (value == 5) || (value == 6) || (value == 7))) {
1928 error = SACENC_INVALID_CONFIG;
1929 break;
1930 }
1931 error = fdk_sacenc_staticGain_SetDmxGain(hMp4SpaceEnc->hStaticGainConfig,
1932 (MP4SPACEENC_DMX_GAIN)value);
1933 break;
1934
1935 case SACENC_COARSE_QUANT:
1936 if (!((value == 0) || (value == 1))) {
1937 error = SACENC_INVALID_CONFIG;
1938 break;
1939 }
1940 hMp4SpaceEnc->user.bUseCoarseQuant = value;
1941 break;
1942
1943 case SACENC_QUANT_MODE:
1944 switch ((MP4SPACEENC_QUANTMODE)value) {
1945 case SACENC_QUANTMODE_FINE:
1946 case SACENC_QUANTMODE_EBQ1:
1947 case SACENC_QUANTMODE_EBQ2:
1948 hMp4SpaceEnc->user.quantMode = (MP4SPACEENC_QUANTMODE)value;
1949 break;
1950 default:
1951 error = SACENC_INVALID_CONFIG;
1952 }
1953 break;
1954
1955 case SACENC_TIME_ALIGNMENT:
1956 if ((INT)value < -32768 || (INT)value > 32767) {
1957 error = SACENC_INVALID_CONFIG;
1958 break;
1959 }
1960 hMp4SpaceEnc->user.timeAlignment = value;
1961 break;
1962
1963 case SACENC_INDEPENDENCY_COUNT:
1964 hMp4SpaceEnc->independencyCount = value;
1965 break;
1966
1967 case SACENC_INDEPENDENCY_FACTOR:
1968 hMp4SpaceEnc->user.independencyFactor = value;
1969 break;
1970
1971 default:
1972 error = SACENC_UNSUPPORTED_PARAMETER;
1973 break;
1974 } /* switch(param) */
1975 bail:
1976 return error;
1977 }
1978
FDK_sacenc_getLibInfo(LIB_INFO * info)1979 FDK_SACENC_ERROR FDK_sacenc_getLibInfo(LIB_INFO *info) {
1980 int i = 0;
1981
1982 if (info == NULL) {
1983 return SACENC_INVALID_HANDLE;
1984 }
1985
1986 FDK_toolsGetLibInfo(info);
1987
1988 /* search for next free tab */
1989 for (i = 0; i < FDK_MODULE_LAST; i++) {
1990 if (info[i].module_id == FDK_NONE) break;
1991 }
1992 if (i == FDK_MODULE_LAST) {
1993 return SACENC_INIT_ERROR;
1994 }
1995
1996 info[i].module_id = FDK_MPSENC;
1997 info[i].build_date = SACENC_LIB_BUILD_DATE;
1998 info[i].build_time = SACENC_LIB_BUILD_TIME;
1999 info[i].title = SACENC_LIB_TITLE;
2000 info[i].version = LIB_VERSION(SACENC_LIB_VL0, SACENC_LIB_VL1, SACENC_LIB_VL2);
2001 LIB_VERSION_STRING(&info[i]);
2002
2003 /* Capability flags */
2004 info[i].flags = 0;
2005 /* End of flags */
2006
2007 return SACENC_OK;
2008 }
2009
mp4SpaceEnc_GetDecorrConfig(const MP4SPACEENC_MODE encMode)2010 static DECORRCONFIG mp4SpaceEnc_GetDecorrConfig(
2011 const MP4SPACEENC_MODE encMode) {
2012 DECORRCONFIG decorrConfig = DECORR_INVALID;
2013
2014 /* set decorrConfig dependent on tree mode */
2015 switch (encMode) {
2016 case SACENC_212:
2017 decorrConfig = DECORR_QMFSPLIT0;
2018 break;
2019 case SACENC_INVALID_MODE:
2020 default:
2021 decorrConfig = DECORR_INVALID;
2022 }
2023 return decorrConfig;
2024 }
2025
mp4SpaceEnc_InitNumParamBands(HANDLE_MP4SPACE_ENCODER hEnc,const MP4SPACEENC_BANDS_CONFIG nParamBands)2026 static FDK_SACENC_ERROR mp4SpaceEnc_InitNumParamBands(
2027 HANDLE_MP4SPACE_ENCODER hEnc, const MP4SPACEENC_BANDS_CONFIG nParamBands) {
2028 FDK_SACENC_ERROR error = SACENC_OK;
2029
2030 /* Set/Check nParamBands */
2031 int k = 0;
2032 const int n = sizeof(pValidBands_Ld) / sizeof(UCHAR);
2033 const UCHAR *pBands = pValidBands_Ld;
2034
2035 while (k < n && pBands[k] != (UCHAR)nParamBands) ++k;
2036 if (k == n) {
2037 hEnc->nParamBands = SACENC_BANDS_INVALID;
2038 } else {
2039 hEnc->nParamBands = nParamBands;
2040 }
2041 return error;
2042 }
2043