Coverage Report

Created: 2025-07-01 06:21

/src/aac/libSACenc/src/sacenc_bitstream.cpp
Line
Count
Source (jump to first uncovered line)
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):
98
99
   Description: Encoder Library Interface
100
                Bitstream Writer
101
102
*******************************************************************************/
103
104
/* Includes ******************************************************************/
105
#include "sacenc_bitstream.h"
106
#include "sacenc_const.h"
107
108
#include "genericStds.h"
109
#include "common_fix.h"
110
111
#include "FDK_matrixCalloc.h"
112
#include "sacenc_nlc_enc.h"
113
114
/* Defines *******************************************************************/
115
0
#define MAX_FREQ_RES_INDEX 8
116
0
#define MAX_SAMPLING_FREQUENCY_INDEX 13
117
0
#define SAMPLING_FREQUENCY_INDEX_ESCAPE 15
118
119
/* Data Types ****************************************************************/
120
typedef struct {
121
  SCHAR cld_old[SACENC_MAX_NUM_BOXES][MAX_NUM_BINS];
122
  SCHAR icc_old[SACENC_MAX_NUM_BOXES][MAX_NUM_BINS];
123
  UCHAR quantCoarseCldPrev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS];
124
  UCHAR quantCoarseIccPrev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS];
125
126
} PREV_OTTDATA;
127
128
typedef struct {
129
  PREV_OTTDATA prevOttData;
130
131
} STATIC_SPATIALFRAME;
132
133
typedef struct BSF_INSTANCE {
134
  SPATIALSPECIFICCONFIG spatialSpecificConfig;
135
  SPATIALFRAME frame;
136
  STATIC_SPATIALFRAME prevFrameData;
137
138
} BSF_INSTANCE;
139
140
/* Constants *****************************************************************/
141
static const INT SampleRateTable[MAX_SAMPLING_FREQUENCY_INDEX] = {
142
    96000, 88200, 64000, 48000, 44100, 32000, 24000,
143
    22050, 16000, 12000, 11025, 8000,  7350};
144
145
static const UCHAR FreqResBinTable_LD[MAX_FREQ_RES_INDEX] = {0, 23, 15, 12,
146
                                                             9, 7,  5,  4};
147
static const UCHAR FreqResStrideTable_LD[] = {1, 2, 5, 23};
148
149
/* Function / Class Declarations *********************************************/
150
151
/* Function / Class Definition ***********************************************/
152
static FDK_SACENC_ERROR DuplicateLosslessData(
153
    const INT startBox, const INT stopBox,
154
    const LOSSLESSDATA *const hLosslessDataFrom, const INT setFrom,
155
0
    LOSSLESSDATA *const hLosslessDataTo, const INT setTo) {
156
0
  FDK_SACENC_ERROR error = SACENC_OK;
157
158
0
  if ((NULL == hLosslessDataFrom) || (NULL == hLosslessDataTo)) {
159
0
    error = SACENC_INVALID_HANDLE;
160
0
  } else {
161
0
    int i;
162
163
0
    for (i = startBox; i < stopBox; i++) {
164
0
      hLosslessDataTo->bsXXXDataMode[i][setTo] =
165
0
          hLosslessDataFrom->bsXXXDataMode[i][setFrom];
166
0
      hLosslessDataTo->bsDataPair[i][setTo] =
167
0
          hLosslessDataFrom->bsDataPair[i][setFrom];
168
0
      hLosslessDataTo->bsQuantCoarseXXX[i][setTo] =
169
0
          hLosslessDataFrom->bsQuantCoarseXXX[i][setFrom];
170
0
      hLosslessDataTo->bsFreqResStrideXXX[i][setTo] =
171
0
          hLosslessDataFrom->bsFreqResStrideXXX[i][setFrom];
172
0
    }
173
0
  }
174
0
  return error;
175
0
}
176
177
FDK_SACENC_ERROR fdk_sacenc_duplicateParameterSet(
178
    const SPATIALFRAME *const hFrom, const INT setFrom, SPATIALFRAME *const hTo,
179
0
    const INT setTo) {
180
0
  FDK_SACENC_ERROR error = SACENC_OK;
181
182
0
  if ((NULL == hFrom) || (NULL == hTo)) {
183
0
    error = SACENC_INVALID_HANDLE;
184
0
  } else {
185
0
    int box;
186
    /* Only Copy Parameter Set selective stuff */
187
188
    /* OTT-Data */
189
0
    for (box = 0; box < SACENC_MAX_NUM_BOXES; box++) {
190
0
      FDKmemcpy(hTo->ottData.cld[box][setTo], hFrom->ottData.cld[box][setFrom],
191
0
                sizeof(hFrom->ottData.cld[0][0]));
192
0
      FDKmemcpy(hTo->ottData.icc[box][setTo], hFrom->ottData.icc[box][setFrom],
193
0
                sizeof(hFrom->ottData.icc[0][0]));
194
0
    }
195
196
    /* LOSSLESSDATA */
197
0
    DuplicateLosslessData(0, SACENC_MAX_NUM_BOXES, &hFrom->CLDLosslessData,
198
0
                          setFrom, &hTo->CLDLosslessData, setTo);
199
0
    DuplicateLosslessData(0, SACENC_MAX_NUM_BOXES, &hFrom->ICCLosslessData,
200
0
                          setFrom, &hTo->ICCLosslessData, setTo);
201
202
0
  } /* valid handle */
203
204
0
  return error;
205
0
}
206
207
/* set frame defaults */
208
0
static void clearFrame(SPATIALFRAME *const pFrame) {
209
0
  FDKmemclear(pFrame, sizeof(SPATIALFRAME));
210
211
0
  pFrame->bsIndependencyFlag = 1;
212
0
  pFrame->framingInfo.numParamSets = 1;
213
0
}
214
215
static void fine2coarse(SCHAR *const data, const DATA_TYPE dataType,
216
0
                        const INT startBand, const INT numBands) {
217
0
  int i;
218
0
  if (dataType == t_CLD) {
219
0
    for (i = startBand; i < startBand + numBands; i++) {
220
0
      data[i] /= 2;
221
0
    }
222
0
  } else {
223
0
    for (i = startBand; i < startBand + numBands; i++) {
224
0
      data[i] >>= 1;
225
0
    }
226
0
  }
227
0
}
228
229
static void coarse2fine(SCHAR *const data, const DATA_TYPE dataType,
230
0
                        const INT startBand, const INT numBands) {
231
0
  int i;
232
233
0
  for (i = startBand; i < startBand + numBands; i++) {
234
0
    data[i] <<= 1;
235
0
  }
236
237
0
  if (dataType == t_CLD) {
238
0
    for (i = startBand; i < startBand + numBands; i++) {
239
0
      if (data[i] == -14) {
240
0
        data[i] = -15;
241
0
      } else if (data[i] == 14) {
242
0
        data[i] = 15;
243
0
      }
244
0
    }
245
0
  } /* (dataType == t_CLD) */
246
0
}
247
248
0
static UCHAR getBsFreqResStride(const INT index) {
249
0
  const UCHAR *pFreqResStrideTable = NULL;
250
0
  int freqResStrideTableSize = 0;
251
252
0
  pFreqResStrideTable = FreqResStrideTable_LD;
253
0
  freqResStrideTableSize =
254
0
      sizeof(FreqResStrideTable_LD) / sizeof(*FreqResStrideTable_LD);
255
256
0
  return (((NULL != pFreqResStrideTable) && (index >= 0) &&
257
0
           (index < freqResStrideTableSize))
258
0
              ? pFreqResStrideTable[index]
259
0
              : 1);
260
0
}
261
262
/* write data to bitstream */
263
static void ecData(HANDLE_FDK_BITSTREAM bitstream,
264
                   SCHAR data[MAX_NUM_PARAMS][MAX_NUM_BINS],
265
                   SCHAR oldData[MAX_NUM_BINS],
266
                   UCHAR quantCoarseXXXprev[MAX_NUM_PARAMS],
267
                   LOSSLESSDATA *const losslessData, const DATA_TYPE dataType,
268
                   const INT paramIdx, const INT numParamSets,
269
                   const INT independencyFlag, const INT startBand,
270
0
                   const INT stopBand, const INT defaultValue) {
271
0
  int ps, pb, strOffset, pbStride, dataBands, i;
272
0
  int aStrides[MAX_NUM_BINS + 1] = {0};
273
0
  SHORT cmpIdxData[2][MAX_NUM_BINS] = {{0}};
274
0
  SHORT cmpOldData[MAX_NUM_BINS] = {0};
275
276
  /* bsXXXDataMode */
277
0
  if (independencyFlag || (losslessData->bsQuantCoarseXXX[paramIdx][0] !=
278
0
                           quantCoarseXXXprev[paramIdx])) {
279
0
    losslessData->bsXXXDataMode[paramIdx][0] = FINECOARSE;
280
0
  } else {
281
0
    losslessData->bsXXXDataMode[paramIdx][0] = KEEP;
282
0
    for (i = startBand; i < stopBand; i++) {
283
0
      if (data[0][i] != oldData[i]) {
284
0
        losslessData->bsXXXDataMode[paramIdx][0] = FINECOARSE;
285
0
        break;
286
0
      }
287
0
    }
288
0
  }
289
290
0
  FDKwriteBits(bitstream, losslessData->bsXXXDataMode[paramIdx][0], 2);
291
292
0
  for (ps = 1; ps < numParamSets; ps++) {
293
0
    if (losslessData->bsQuantCoarseXXX[paramIdx][ps] !=
294
0
        losslessData->bsQuantCoarseXXX[paramIdx][ps - 1]) {
295
0
      losslessData->bsXXXDataMode[paramIdx][ps] = FINECOARSE;
296
0
    } else {
297
0
      losslessData->bsXXXDataMode[paramIdx][ps] = KEEP;
298
0
      for (i = startBand; i < stopBand; i++) {
299
0
        if (data[ps][i] != data[ps - 1][i]) {
300
0
          losslessData->bsXXXDataMode[paramIdx][ps] = FINECOARSE;
301
0
          break;
302
0
        }
303
0
      }
304
0
    }
305
306
0
    FDKwriteBits(bitstream, losslessData->bsXXXDataMode[paramIdx][ps], 2);
307
0
  } /* for ps */
308
309
  /* Create data pairs if possible */
310
0
  for (ps = 0; ps < (numParamSets - 1); ps++) {
311
0
    if (losslessData->bsXXXDataMode[paramIdx][ps] == FINECOARSE) {
312
      /* Check if next parameter set is FINCOARSE */
313
0
      if (losslessData->bsXXXDataMode[paramIdx][ps + 1] == FINECOARSE) {
314
        /* We have to check if ps and ps+1 use the same bsXXXQuantMode */
315
        /* and also have the same stride */
316
0
        if ((losslessData->bsQuantCoarseXXX[paramIdx][ps + 1] ==
317
0
             losslessData->bsQuantCoarseXXX[paramIdx][ps]) &&
318
0
            (losslessData->bsFreqResStrideXXX[paramIdx][ps + 1] ==
319
0
             losslessData->bsFreqResStrideXXX[paramIdx][ps])) {
320
0
          losslessData->bsDataPair[paramIdx][ps] = 1;
321
0
          losslessData->bsDataPair[paramIdx][ps + 1] = 1;
322
323
          /* We have a data pair -> Jump to the ps after next ps*/
324
0
          ps++;
325
0
          continue;
326
0
        }
327
0
      }
328
      /* dataMode of next ps is not FINECOARSE or does not use the same
329
       * bsXXXQuantMode/stride */
330
      /* -> no dataPair possible */
331
0
      losslessData->bsDataPair[paramIdx][ps] = 0;
332
333
      /* Initialize ps after next ps to Zero (only important for the last
334
       * parameter set) */
335
0
      losslessData->bsDataPair[paramIdx][ps + 1] = 0;
336
0
    } else {
337
      /* No FINECOARSE -> no data pair possible */
338
0
      losslessData->bsDataPair[paramIdx][ps] = 0;
339
340
      /* Initialize ps after next ps to Zero (only important for the last
341
       * parameter set) */
342
0
      losslessData->bsDataPair[paramIdx][ps + 1] = 0;
343
0
    }
344
0
  } /* for ps */
345
346
0
  for (ps = 0; ps < numParamSets; ps++) {
347
0
    if (losslessData->bsXXXDataMode[paramIdx][ps] == DEFAULT) {
348
      /* Prepare old data */
349
0
      for (i = startBand; i < stopBand; i++) {
350
0
        oldData[i] = defaultValue;
351
0
      }
352
0
      quantCoarseXXXprev[paramIdx] = 0; /* Default data are always fine */
353
0
    }
354
355
0
    if (losslessData->bsXXXDataMode[paramIdx][ps] == FINECOARSE) {
356
0
      FDKwriteBits(bitstream, losslessData->bsDataPair[paramIdx][ps], 1);
357
0
      FDKwriteBits(bitstream, losslessData->bsQuantCoarseXXX[paramIdx][ps], 1);
358
0
      FDKwriteBits(bitstream, losslessData->bsFreqResStrideXXX[paramIdx][ps],
359
0
                   2);
360
361
0
      if (losslessData->bsQuantCoarseXXX[paramIdx][ps] !=
362
0
          quantCoarseXXXprev[paramIdx]) {
363
0
        if (quantCoarseXXXprev[paramIdx]) {
364
0
          coarse2fine(oldData, dataType, startBand, stopBand - startBand);
365
0
        } else {
366
0
          fine2coarse(oldData, dataType, startBand, stopBand - startBand);
367
0
        }
368
0
      }
369
370
      /* Handle strides */
371
0
      pbStride =
372
0
          getBsFreqResStride(losslessData->bsFreqResStrideXXX[paramIdx][ps]);
373
0
      dataBands = (stopBand - startBand - 1) / pbStride + 1;
374
375
0
      aStrides[0] = startBand;
376
0
      for (pb = 1; pb <= dataBands; pb++) {
377
0
        aStrides[pb] = aStrides[pb - 1] + pbStride;
378
0
      }
379
380
0
      strOffset = 0;
381
0
      while (aStrides[dataBands] > stopBand) {
382
0
        if (strOffset < dataBands) {
383
0
          strOffset++;
384
0
        }
385
0
        for (i = strOffset; i <= dataBands; i++) {
386
0
          aStrides[i]--;
387
0
        }
388
0
      } /* while */
389
390
0
      for (pb = 0; pb < dataBands; pb++) {
391
0
        cmpOldData[startBand + pb] = oldData[aStrides[pb]];
392
0
        cmpIdxData[0][startBand + pb] = data[ps][aStrides[pb]];
393
394
0
        if (losslessData->bsDataPair[paramIdx][ps]) {
395
0
          cmpIdxData[1][startBand + pb] = data[ps + 1][aStrides[pb]];
396
0
        }
397
0
      } /* for pb*/
398
399
      /* Finally encode */
400
0
      if (losslessData->bsDataPair[paramIdx][ps]) {
401
0
        fdk_sacenc_ecDataPairEnc(bitstream, cmpIdxData, cmpOldData, dataType, 0,
402
0
                                 startBand, dataBands,
403
0
                                 losslessData->bsQuantCoarseXXX[paramIdx][ps],
404
0
                                 independencyFlag && (ps == 0));
405
0
      } else {
406
0
        fdk_sacenc_ecDataSingleEnc(bitstream, cmpIdxData, cmpOldData, dataType,
407
0
                                   0, startBand, dataBands,
408
0
                                   losslessData->bsQuantCoarseXXX[paramIdx][ps],
409
0
                                   independencyFlag && (ps == 0));
410
0
      }
411
412
      /* Overwrite old data */
413
0
      for (i = startBand; i < stopBand; i++) {
414
0
        if (losslessData->bsDataPair[paramIdx][ps]) {
415
0
          oldData[i] = data[ps + 1][i];
416
0
        } else {
417
0
          oldData[i] = data[ps][i];
418
0
        }
419
0
      }
420
421
0
      quantCoarseXXXprev[paramIdx] =
422
0
          losslessData->bsQuantCoarseXXX[paramIdx][ps];
423
424
      /* Jump forward if we have encoded a data pair */
425
0
      if (losslessData->bsDataPair[paramIdx][ps]) {
426
0
        ps++;
427
0
      }
428
429
0
    } /* if (losslessData->bsXXXDataMode[paramIdx][ps] == FINECOARSE ) */
430
0
  }   /* for ps */
431
0
}
432
433
/****************************************************************************/
434
/* Bitstream formatter interface functions                                  */
435
/****************************************************************************/
436
static FDK_SACENC_ERROR getBsFreqResIndex(const INT numBands,
437
0
                                          INT *const pbsFreqResIndex) {
438
0
  FDK_SACENC_ERROR error = SACENC_OK;
439
440
0
  if (NULL == pbsFreqResIndex) {
441
0
    error = SACENC_INVALID_HANDLE;
442
0
  } else {
443
0
    const UCHAR *pFreqResBinTable = FreqResBinTable_LD;
444
0
    int i;
445
0
    *pbsFreqResIndex = -1;
446
447
0
    for (i = 0; i < MAX_FREQ_RES_INDEX; i++) {
448
0
      if (numBands == pFreqResBinTable[i]) {
449
0
        *pbsFreqResIndex = i;
450
0
        break;
451
0
      }
452
0
    }
453
0
    if (*pbsFreqResIndex < 0 || *pbsFreqResIndex >= MAX_FREQ_RES_INDEX) {
454
0
      error = SACENC_INVALID_CONFIG;
455
0
    }
456
0
  }
457
0
  return error;
458
0
}
459
460
static FDK_SACENC_ERROR getSamplingFrequencyIndex(
461
0
    const INT bsSamplingFrequency, INT *const pbsSamplingFrequencyIndex) {
462
0
  FDK_SACENC_ERROR error = SACENC_OK;
463
464
0
  if (NULL == pbsSamplingFrequencyIndex) {
465
0
    error = SACENC_INVALID_HANDLE;
466
0
  } else {
467
0
    int i;
468
0
    *pbsSamplingFrequencyIndex = SAMPLING_FREQUENCY_INDEX_ESCAPE;
469
470
0
    for (i = 0; i < MAX_SAMPLING_FREQUENCY_INDEX; i++) {
471
0
      if (bsSamplingFrequency == SampleRateTable[i]) { /*spatial sampling rate*/
472
0
        *pbsSamplingFrequencyIndex = i;
473
0
        break;
474
0
      }
475
0
    }
476
0
  }
477
0
  return error;
478
0
}
479
480
/* destroy encoder instance */
481
FDK_SACENC_ERROR fdk_sacenc_destroySpatialBitstreamEncoder(
482
0
    HANDLE_BSF_INSTANCE *selfPtr) {
483
0
  FDK_SACENC_ERROR error = SACENC_OK;
484
485
0
  if ((selfPtr == NULL) || (*selfPtr == NULL)) {
486
0
    error = SACENC_INVALID_HANDLE;
487
0
  } else {
488
0
    if (*selfPtr != NULL) {
489
0
      FDK_FREE_MEMORY_1D(*selfPtr);
490
0
    }
491
0
  }
492
0
  return error;
493
0
}
494
495
/* create encoder instance */
496
FDK_SACENC_ERROR fdk_sacenc_createSpatialBitstreamEncoder(
497
0
    HANDLE_BSF_INSTANCE *selfPtr) {
498
0
  FDK_SACENC_ERROR error = SACENC_OK;
499
500
0
  if (NULL == selfPtr) {
501
0
    error = SACENC_INVALID_HANDLE;
502
0
  } else {
503
    /* allocate encoder struct */
504
0
    FDK_ALLOCATE_MEMORY_1D(*selfPtr, 1, BSF_INSTANCE);
505
0
  }
506
0
  return error;
507
508
0
bail:
509
0
  fdk_sacenc_destroySpatialBitstreamEncoder(selfPtr);
510
0
  return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error);
511
0
}
512
513
/* init encoder instance */
514
FDK_SACENC_ERROR fdk_sacenc_initSpatialBitstreamEncoder(
515
0
    HANDLE_BSF_INSTANCE selfPtr) {
516
0
  FDK_SACENC_ERROR error = SACENC_OK;
517
518
0
  if (selfPtr == NULL) {
519
0
    error = SACENC_INVALID_HANDLE;
520
0
  } else {
521
    /* init/clear */
522
0
    clearFrame(&selfPtr->frame);
523
524
0
  } /* valid handle */
525
0
  return error;
526
0
}
527
528
/* get SpatialSpecificConfig struct */
529
SPATIALSPECIFICCONFIG *fdk_sacenc_getSpatialSpecificConfig(
530
0
    HANDLE_BSF_INSTANCE selfPtr) {
531
0
  return ((selfPtr == NULL) ? NULL : &(selfPtr->spatialSpecificConfig));
532
0
}
533
534
/* write SpatialSpecificConfig to stream */
535
FDK_SACENC_ERROR fdk_sacenc_writeSpatialSpecificConfig(
536
    SPATIALSPECIFICCONFIG *const spatialSpecificConfig,
537
    UCHAR *const pOutputBuffer, const INT outputBufferSize,
538
0
    INT *const pnOutputBits) {
539
0
  FDK_SACENC_ERROR error = SACENC_OK;
540
0
  INT bsSamplingFrequencyIndex = 0;
541
0
  INT bsFreqRes = 0;
542
543
0
  if ((spatialSpecificConfig == NULL) || (pOutputBuffer == NULL) ||
544
0
      (pnOutputBits == NULL)) {
545
0
    error = SACENC_INVALID_HANDLE;
546
0
  } else {
547
0
    FDK_BITSTREAM bitstream;
548
549
    /* Find FreqRes */
550
0
    if (SACENC_OK != (error = getBsFreqResIndex(spatialSpecificConfig->numBands,
551
0
                                                &bsFreqRes)))
552
0
      goto bail;
553
554
    /* Find SamplingFrequencyIndex */
555
0
    if (SACENC_OK != (error = getSamplingFrequencyIndex(
556
0
                          spatialSpecificConfig->bsSamplingFrequency,
557
0
                          &bsSamplingFrequencyIndex)))
558
0
      goto bail;
559
560
    /* bind extern buffer to bitstream handle */
561
0
    FDKinitBitStream(&bitstream, pOutputBuffer, outputBufferSize, 0, BS_WRITER);
562
563
    /****************************************************************************/
564
    /* write to bitstream */
565
566
0
    FDKwriteBits(&bitstream, bsSamplingFrequencyIndex, 4);
567
568
0
    if (bsSamplingFrequencyIndex == 15) {
569
0
      FDKwriteBits(&bitstream, spatialSpecificConfig->bsSamplingFrequency, 24);
570
0
    }
571
572
0
    FDKwriteBits(&bitstream, spatialSpecificConfig->bsFrameLength, 5);
573
574
0
    FDKwriteBits(&bitstream, bsFreqRes, 3);
575
0
    FDKwriteBits(&bitstream, spatialSpecificConfig->bsTreeConfig, 4);
576
0
    FDKwriteBits(&bitstream, spatialSpecificConfig->bsQuantMode, 2);
577
578
0
    FDKwriteBits(&bitstream, 0, 1); /* bsArbitraryDownmix */
579
580
0
    FDKwriteBits(&bitstream, spatialSpecificConfig->bsFixedGainDMX, 3);
581
582
0
    FDKwriteBits(&bitstream, TEMPSHAPE_OFF, 2);
583
0
    FDKwriteBits(&bitstream, spatialSpecificConfig->bsDecorrConfig, 2);
584
585
0
    FDKbyteAlign(&bitstream, 0); /* byte alignment */
586
587
    /* return number of valid bits in bitstream */
588
0
    if ((*pnOutputBits = FDKgetValidBits(&bitstream)) >
589
0
        (outputBufferSize * 8)) {
590
0
      error = SACENC_INVALID_CONFIG;
591
0
      goto bail;
592
0
    }
593
594
    /* terminate buffer with alignment */
595
0
    FDKbyteAlign(&bitstream, 0);
596
597
0
  } /* valid handle */
598
599
0
bail:
600
0
  return error;
601
0
}
602
603
/* get SpatialFrame struct */
604
SPATIALFRAME *fdk_sacenc_getSpatialFrame(HANDLE_BSF_INSTANCE selfPtr,
605
0
                                         const SPATIALFRAME_TYPE frameType) {
606
0
  int idx = -1;
607
608
0
  switch (frameType) {
609
0
    case READ_SPATIALFRAME:
610
0
    case WRITE_SPATIALFRAME:
611
0
      idx = 0;
612
0
      break;
613
0
    default:
614
0
      idx = -1; /* invalid configuration */
615
0
  }             /* switch frameType */
616
617
0
  return (((selfPtr == NULL) || (idx == -1)) ? NULL : &selfPtr->frame);
618
0
}
619
620
static FDK_SACENC_ERROR writeFramingInfo(HANDLE_FDK_BITSTREAM hBitstream,
621
                                         const FRAMINGINFO *const pFramingInfo,
622
0
                                         const INT frameLength) {
623
0
  FDK_SACENC_ERROR error = SACENC_OK;
624
625
0
  if ((hBitstream == NULL) || (pFramingInfo == NULL)) {
626
0
    error = SACENC_INVALID_HANDLE;
627
0
  } else {
628
0
    FDKwriteBits(hBitstream, pFramingInfo->bsFramingType, 1);
629
0
    FDKwriteBits(hBitstream, pFramingInfo->numParamSets - 1, 1);
630
631
0
    if (pFramingInfo->bsFramingType) {
632
0
      int ps = 0;
633
0
      int numParamSets = pFramingInfo->numParamSets;
634
635
0
      {
636
0
        for (ps = 0; ps < numParamSets; ps++) {
637
0
          int bitsParamSlot = 0;
638
0
          while ((1 << bitsParamSlot) < (frameLength + 1)) bitsParamSlot++;
639
0
          if (bitsParamSlot > 0)
640
0
            FDKwriteBits(hBitstream, pFramingInfo->bsParamSlots[ps],
641
0
                         bitsParamSlot);
642
0
        }
643
0
      }
644
0
    } /* pFramingInfo->bsFramingType */
645
0
  }   /* valid handle */
646
647
0
  return error;
648
0
}
649
650
static FDK_SACENC_ERROR writeSmgData(HANDLE_FDK_BITSTREAM hBitstream,
651
                                     const SMGDATA *const pSmgData,
652
                                     const INT numParamSets,
653
0
                                     const INT dataBands) {
654
0
  FDK_SACENC_ERROR error = SACENC_OK;
655
656
0
  if ((hBitstream == NULL) || (pSmgData == NULL)) {
657
0
    error = SACENC_INVALID_HANDLE;
658
0
  } else {
659
0
    int i, j;
660
661
0
    for (i = 0; i < numParamSets; i++) {
662
0
      FDKwriteBits(hBitstream, pSmgData->bsSmoothMode[i], 2);
663
664
0
      if (pSmgData->bsSmoothMode[i] >= 2) {
665
0
        FDKwriteBits(hBitstream, pSmgData->bsSmoothTime[i], 2);
666
0
      }
667
0
      if (pSmgData->bsSmoothMode[i] == 3) {
668
0
        const int stride = getBsFreqResStride(pSmgData->bsFreqResStride[i]);
669
0
        FDKwriteBits(hBitstream, pSmgData->bsFreqResStride[i], 2);
670
0
        for (j = 0; j < dataBands; j += stride) {
671
0
          FDKwriteBits(hBitstream, pSmgData->bsSmgData[i][j], 1);
672
0
        }
673
0
      }
674
0
    } /* for i */
675
0
  }   /* valid handle */
676
677
0
  return error;
678
0
}
679
680
static FDK_SACENC_ERROR writeOttData(
681
    HANDLE_FDK_BITSTREAM hBitstream, PREV_OTTDATA *const pPrevOttData,
682
    OTTDATA *const pOttData, const OTTCONFIG ottConfig[SACENC_MAX_NUM_BOXES],
683
    LOSSLESSDATA *const pCLDLosslessData, LOSSLESSDATA *const pICCLosslessData,
684
    const INT numOttBoxes, const INT numBands, const INT numParamSets,
685
0
    const INT bsIndependencyFlag) {
686
0
  FDK_SACENC_ERROR error = SACENC_OK;
687
688
0
  if ((hBitstream == NULL) || (pPrevOttData == NULL) || (pOttData == NULL) ||
689
0
      (ottConfig == NULL) || (pCLDLosslessData == NULL) ||
690
0
      (pICCLosslessData == NULL)) {
691
0
    error = SACENC_INVALID_HANDLE;
692
0
  } else {
693
0
    int i;
694
0
    for (i = 0; i < numOttBoxes; i++) {
695
0
      ecData(hBitstream, pOttData->cld[i], pPrevOttData->cld_old[i],
696
0
             pPrevOttData->quantCoarseCldPrev[i], pCLDLosslessData, t_CLD, i,
697
0
             numParamSets, bsIndependencyFlag, 0, ottConfig[i].bsOttBands, 15);
698
0
    }
699
0
    {
700
0
      for (i = 0; i < numOttBoxes; i++) {
701
0
        {
702
0
          ecData(hBitstream, pOttData->icc[i], pPrevOttData->icc_old[i],
703
0
                 pPrevOttData->quantCoarseIccPrev[i], pICCLosslessData, t_ICC,
704
0
                 i, numParamSets, bsIndependencyFlag, 0, numBands, 0);
705
0
        }
706
0
      } /* for i */
707
0
    }
708
0
  } /* valid handle */
709
710
0
  return error;
711
0
}
712
713
/* write extension frame data to stream */
714
static FDK_SACENC_ERROR WriteSpatialExtensionFrame(
715
0
    HANDLE_FDK_BITSTREAM bitstream, HANDLE_BSF_INSTANCE self) {
716
0
  FDK_SACENC_ERROR error = SACENC_OK;
717
718
0
  if ((bitstream == NULL) || (self == NULL)) {
719
0
    error = SACENC_INVALID_HANDLE;
720
0
  } else {
721
0
    FDKbyteAlign(bitstream, 0);
722
0
  } /* valid handle */
723
724
0
  return error;
725
0
}
726
727
/* write frame data to stream */
728
FDK_SACENC_ERROR fdk_sacenc_writeSpatialFrame(UCHAR *const pOutputBuffer,
729
                                              const INT outputBufferSize,
730
                                              INT *const pnOutputBits,
731
0
                                              HANDLE_BSF_INSTANCE selfPtr) {
732
0
  FDK_SACENC_ERROR error = SACENC_OK;
733
734
0
  if ((pOutputBuffer == NULL) || (pnOutputBits == NULL) || (selfPtr == NULL)) {
735
0
    error = SACENC_INVALID_HANDLE;
736
0
  } else {
737
0
    SPATIALFRAME *frame = NULL;
738
0
    SPATIALSPECIFICCONFIG *config = NULL;
739
0
    FDK_BITSTREAM bitstream;
740
741
0
    int i, j, numParamSets, numOttBoxes;
742
743
0
    if ((NULL ==
744
0
         (frame = fdk_sacenc_getSpatialFrame(selfPtr, READ_SPATIALFRAME))) ||
745
0
        (NULL == (config = &(selfPtr->spatialSpecificConfig)))) {
746
0
      error = SACENC_INVALID_HANDLE;
747
0
      goto bail;
748
0
    }
749
750
0
    numOttBoxes = selfPtr->spatialSpecificConfig.treeDescription.numOttBoxes;
751
752
0
    numParamSets = frame->framingInfo.numParamSets;
753
754
0
    if (frame->bUseBBCues) {
755
0
      for (i = 0; i < SACENC_MAX_NUM_BOXES; i++) {
756
        /* If a transient was detected, force only the second ps broad band */
757
0
        if (numParamSets == 1) {
758
0
          frame->CLDLosslessData.bsFreqResStrideXXX[i][0] = 3;
759
0
          frame->ICCLosslessData.bsFreqResStrideXXX[i][0] = 3;
760
0
        } else {
761
0
          for (j = 1; j < MAX_NUM_PARAMS; j++) {
762
0
            frame->CLDLosslessData.bsFreqResStrideXXX[i][j] = 3;
763
0
            frame->ICCLosslessData.bsFreqResStrideXXX[i][j] = 3;
764
0
          }
765
0
        }
766
0
      }
767
0
    } /* frame->bUseBBCues */
768
769
    /* bind extern buffer to bitstream handle */
770
0
    FDKinitBitStream(&bitstream, pOutputBuffer, outputBufferSize, 0, BS_WRITER);
771
772
0
    if (SACENC_OK != (error = writeFramingInfo(
773
0
                          &bitstream, &(frame->framingInfo),
774
0
                          selfPtr->spatialSpecificConfig.bsFrameLength))) {
775
0
      goto bail;
776
0
    }
777
778
    /* write bsIndependencyFlag */
779
0
    FDKwriteBits(&bitstream, frame->bsIndependencyFlag, 1);
780
781
    /* write spatial data to bitstream */
782
0
    if (SACENC_OK !=
783
0
        (error = writeOttData(&bitstream, &selfPtr->prevFrameData.prevOttData,
784
0
                              &frame->ottData, config->ottConfig,
785
0
                              &frame->CLDLosslessData, &frame->ICCLosslessData,
786
0
                              numOttBoxes, config->numBands, numParamSets,
787
0
                              frame->bsIndependencyFlag))) {
788
0
      goto bail;
789
0
    }
790
0
    if (SACENC_OK != (error = writeSmgData(&bitstream, &frame->smgData,
791
0
                                           numParamSets, config->numBands))) {
792
0
      goto bail;
793
0
    }
794
795
    /* byte alignment */
796
0
    FDKbyteAlign(&bitstream, 0);
797
798
    /* Write SpatialExtensionFrame */
799
0
    if (SACENC_OK !=
800
0
        (error = WriteSpatialExtensionFrame(&bitstream, selfPtr))) {
801
0
      goto bail;
802
0
    }
803
804
0
    if (NULL ==
805
0
        (frame = fdk_sacenc_getSpatialFrame(selfPtr, WRITE_SPATIALFRAME))) {
806
0
      error = SACENC_INVALID_HANDLE;
807
0
      goto bail;
808
0
    }
809
810
0
    clearFrame(frame);
811
812
    /* return number of valid bits in bitstream */
813
0
    if ((*pnOutputBits = FDKgetValidBits(&bitstream)) >
814
0
        (outputBufferSize * 8)) {
815
0
      error = SACENC_INVALID_CONFIG;
816
0
      goto bail;
817
0
    }
818
819
    /* terminate buffer with alignment */
820
0
    FDKbyteAlign(&bitstream, 0);
821
822
0
  } /* valid handle */
823
824
0
bail:
825
0
  return error;
826
0
}