Home | History | Annotate | Download | only in src
      1 
      2 /* -----------------------------------------------------------------------------------------------------------
      3 Software License for The Fraunhofer FDK AAC Codec Library for Android
      4 
      5  Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur Frderung der angewandten Forschung e.V.
      6   All rights reserved.
      7 
      8  1.    INTRODUCTION
      9 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
     10 the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
     11 This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
     12 
     13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
     14 audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
     15 independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
     16 of the MPEG specifications.
     17 
     18 Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
     19 may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
     20 individually for the purpose of encoding or decoding bit streams in products that are compliant with
     21 the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
     22 these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
     23 software may already be covered under those patent licenses when it is used for those licensed purposes only.
     24 
     25 Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
     26 are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
     27 applications information and documentation.
     28 
     29 2.    COPYRIGHT LICENSE
     30 
     31 Redistribution and use in source and binary forms, with or without modification, are permitted without
     32 payment of copyright license fees provided that you satisfy the following conditions:
     33 
     34 You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
     35 your modifications thereto in source code form.
     36 
     37 You must retain the complete text of this software license in the documentation and/or other materials
     38 provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
     39 You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
     40 modifications thereto to recipients of copies in binary form.
     41 
     42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
     43 prior written permission.
     44 
     45 You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
     46 software or your modifications thereto.
     47 
     48 Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
     49 and the date of any change. For modified versions of the FDK AAC Codec, the term
     50 "Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
     51 "Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
     52 
     53 3.    NO PATENT LICENSE
     54 
     55 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
     56 ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
     57 respect to this software.
     58 
     59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
     60 by appropriate patent licenses.
     61 
     62 4.    DISCLAIMER
     63 
     64 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
     65 "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
     66 of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     67 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
     68 including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
     69 or business interruption, however caused and on any theory of liability, whether in contract, strict
     70 liability, or tort (including negligence), arising in any way out of the use of this software, even if
     71 advised of the possibility of such damage.
     72 
     73 5.    CONTACT INFORMATION
     74 
     75 Fraunhofer Institute for Integrated Circuits IIS
     76 Attention: Audio and Multimedia Departments - FDK AAC LL
     77 Am Wolfsmantel 33
     78 91058 Erlangen, Germany
     79 
     80 www.iis.fraunhofer.de/amm
     81 amm-info (at) iis.fraunhofer.de
     82 ----------------------------------------------------------------------------------------------------------- */
     83 
     84 /*****************************  MPEG-4 AAC Encoder  **************************
     85 
     86    Author(s):
     87    Description:
     88 
     89 ******************************************************************************/
     90 
     91 #include "tp_data.h"
     92 
     93 #include "tpenc_lib.h"
     94 #include "tpenc_asc.h"
     95 #include "FDK_bitstream.h"
     96 #include "genericStds.h"
     97 
     98 #define PCE_MAX_ELEMENTS 8
     99 
    100 /**
    101  *  Describe a PCE based on placed channel elements and element type sequence.
    102  */
    103 typedef struct {
    104 
    105     UCHAR    num_front_channel_elements;     /*!< Number of front channel elements. */
    106     UCHAR    num_side_channel_elements;      /*!< Number of side channel elements. */
    107     UCHAR    num_back_channel_elements;      /*!< Number of back channel elements. */
    108     UCHAR    num_lfe_channel_elements;       /*!< Number of lfe channel elements. */
    109     MP4_ELEMENT_ID el_list[PCE_MAX_ELEMENTS];/*!< List contains sequence describing the elements
    110                                                   in present channel mode. (MPEG order) */
    111 } PCE_CONFIGURATION;
    112 
    113 
    114 /**
    115  *  Map an incoming channel mode to a existing PCE configuration entry.
    116  */
    117 typedef struct {
    118 
    119     CHANNEL_MODE        channel_mode;        /*!< Present channel mode. */
    120     PCE_CONFIGURATION   pce_configuration;   /*!< Program config element description. */
    121 
    122 } CHANNEL_CONFIGURATION;
    123 
    124 
    125 /**
    126  * \brief Table contains all supported channel modes and according PCE configuration description.
    127  *
    128  * The number of channel element parameter describes the kind of consecutively elements.
    129  * E.g. MODE_1_2_2_2_1 means:
    130  *                          - First 3 elements (SCE,CPE,CPE) are front channel elements.
    131  *                          - Next element (CPE) is a back channel element.
    132  *                          - Last element (LFE) is a lfe channel element.
    133  */
    134 static const CHANNEL_CONFIGURATION pceConfigTab[] =
    135 {
    136   { MODE_1,                        {  1, 0, 0, 0, { ID_SCE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
    137   { MODE_2,                        {  1, 0, 0, 0, { ID_CPE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
    138   { MODE_1_2,                      {  2, 0, 0, 0, { ID_SCE,  ID_CPE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
    139   { MODE_1_2_1,                    {  2, 0, 1, 0, { ID_SCE,  ID_CPE,  ID_SCE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
    140   { MODE_1_2_2,                    {  2, 0, 1, 0, { ID_SCE,  ID_CPE,  ID_CPE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
    141   { MODE_1_2_2_1,                  {  2, 0, 1, 1, { ID_SCE,  ID_CPE,  ID_CPE,  ID_LFE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
    142   { MODE_1_2_2_2_1,                {  3, 0, 1, 1, { ID_SCE,  ID_CPE,  ID_CPE,  ID_CPE,  ID_LFE,  ID_NONE, ID_NONE, ID_NONE } } },
    143 
    144 
    145   { MODE_1_1,                      {  2, 0, 0, 0, { ID_SCE,  ID_SCE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
    146   { MODE_1_1_1_1,                  {  2, 2, 0, 0, { ID_SCE,  ID_SCE,  ID_SCE,  ID_SCE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
    147   { MODE_1_1_1_1_1_1,              {  2, 2, 2, 0, { ID_SCE,  ID_SCE,  ID_SCE,  ID_SCE,  ID_SCE,  ID_SCE,  ID_NONE, ID_NONE } } },
    148   { MODE_1_1_1_1_1_1_1_1,          {  3, 2, 3, 0, { ID_SCE,  ID_SCE,  ID_SCE,  ID_SCE,  ID_SCE,  ID_SCE,  ID_SCE,  ID_SCE } } },
    149 
    150   { MODE_2_2,                      {  1, 0, 1, 0, { ID_CPE,  ID_CPE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
    151   { MODE_2_2_2,                    {  1, 1, 1, 0, { ID_CPE,  ID_CPE,  ID_CPE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
    152   { MODE_2_2_2_2,                  {  4, 0, 0, 0, { ID_CPE,  ID_CPE,  ID_CPE,  ID_CPE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
    153 
    154   { MODE_2_1,                      {  1, 0, 1, 0, { ID_CPE,  ID_SCE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
    155 
    156   { MODE_7_1_REAR_SURROUND,        {  2, 0, 2, 1, { ID_SCE,  ID_CPE,  ID_CPE,  ID_CPE,  ID_LFE,  ID_NONE, ID_NONE, ID_NONE } } },
    157   { MODE_7_1_FRONT_CENTER,         {  3, 0, 1, 1, { ID_SCE,  ID_CPE,  ID_CPE,  ID_CPE,  ID_LFE,  ID_NONE, ID_NONE, ID_NONE } } },
    158 
    159 };
    160 
    161 
    162 /**
    163  * \brief  Get program config element description for existing channel mode.
    164  *
    165  * \param channel_mode          Current channel mode.
    166  *
    167  * \return
    168  *          - Pointer to PCE_CONFIGURATION entry, on success.
    169  *          - NULL, on failure.
    170  */
    171 static const PCE_CONFIGURATION* getPceEntry(
    172         const CHANNEL_MODE channel_mode
    173         )
    174 {
    175   UINT i;
    176   const PCE_CONFIGURATION *pce_config = NULL;
    177 
    178   for (i=0; i < (sizeof(pceConfigTab)/sizeof(CHANNEL_CONFIGURATION)); i++) {
    179     if (pceConfigTab[i].channel_mode == channel_mode) {
    180       pce_config = &pceConfigTab[i].pce_configuration;
    181     }
    182   }
    183 
    184   return pce_config;
    185 }
    186 
    187 int getChannelConfig( CHANNEL_MODE channel_mode )
    188 {
    189   INT chan_config = 0;
    190 
    191   switch(channel_mode) {
    192     case MODE_1:         chan_config = 1; break;
    193     case MODE_2:         chan_config = 2; break;
    194     case MODE_1_2:       chan_config = 3; break;
    195     case MODE_1_2_1:     chan_config = 4; break;
    196     case MODE_1_2_2:     chan_config = 5; break;
    197     case MODE_1_2_2_1:   chan_config = 6; break;
    198     case MODE_1_2_2_2_1: chan_config = 7; break;
    199 
    200     default:             chan_config = 0;
    201   }
    202 
    203   return chan_config;
    204 }
    205 
    206 CHANNEL_MODE transportEnc_GetChannelMode( int noChannels )
    207 {
    208   CHANNEL_MODE chMode;
    209 
    210   if (noChannels <= 8 && noChannels > 0)
    211     chMode = (CHANNEL_MODE)((noChannels == 8) ? 7 : noChannels); /* see : iso/mpeg4 v1 audio subpart1*/
    212   else
    213     chMode = MODE_UNKNOWN;
    214 
    215   return chMode;
    216 }
    217 
    218 #ifdef TP_PCE_ENABLE
    219 int transportEnc_writePCE(HANDLE_FDK_BITSTREAM hBs,
    220                           CHANNEL_MODE channelMode,
    221                           INT sampleRate,
    222                           int instanceTagPCE,
    223                           int profile,
    224                           int matrixMixdownA,
    225                           int pseudoSurroundEnable,
    226                           UINT alignAnchor)
    227 {
    228   int sampleRateIndex, i;
    229   const PCE_CONFIGURATION* config = NULL;
    230   const MP4_ELEMENT_ID* pEl_list = NULL;
    231   UCHAR cpeCnt=0, sceCnt=0, lfeCnt=0;
    232 
    233   sampleRateIndex = getSamplingRateIndex(sampleRate);
    234   if (sampleRateIndex == 15) {
    235     return -1;
    236   }
    237 
    238   if ((config=getPceEntry(channelMode))==NULL) {
    239     return -1;
    240   }
    241 
    242   /* Pointer to first element in element list. */
    243   pEl_list = &config->el_list[0];
    244 
    245   FDKwriteBits(hBs, instanceTagPCE,  4);                        /* Element instance tag */
    246   FDKwriteBits(hBs, profile,         2);                        /* Object type */
    247   FDKwriteBits(hBs, sampleRateIndex, 4);                        /* Sample rate index*/
    248 
    249   FDKwriteBits(hBs, config->num_front_channel_elements, 4);     /* Front channel Elements */
    250   FDKwriteBits(hBs, config->num_side_channel_elements , 4);     /* No Side Channel Elements */
    251   FDKwriteBits(hBs, config->num_back_channel_elements , 4);     /* No Back channel Elements */
    252   FDKwriteBits(hBs, config->num_lfe_channel_elements  , 2);     /* No Lfe channel elements */
    253 
    254   FDKwriteBits(hBs, 0, 3);                                      /* No assoc data elements */
    255   FDKwriteBits(hBs, 0, 4);                                      /* No valid cc elements */
    256   FDKwriteBits(hBs, 0, 1);                                      /* Mono mixdown present */
    257   FDKwriteBits(hBs, 0, 1);                                      /* Stereo mixdown present */
    258 
    259   if ( matrixMixdownA!=0 && ((channelMode==MODE_1_2_2)||(channelMode==MODE_1_2_2_1)) ) {
    260       FDKwriteBits(hBs, 1, 1);                                  /* Matrix mixdown present */
    261       FDKwriteBits(hBs, (matrixMixdownA-1)&0x3, 2);             /* matrix_mixdown_idx */
    262       FDKwriteBits(hBs, (pseudoSurroundEnable)?1:0, 1);         /* pseudo_surround_enable */
    263   }
    264   else {
    265       FDKwriteBits(hBs, 0, 1);                                  /* Matrix mixdown not present */
    266   }
    267 
    268   for(i=0; i<config->num_front_channel_elements; i++) {
    269       UCHAR isCpe = (*pEl_list++==ID_CPE) ? 1 : 0;
    270       UCHAR tag   = (isCpe) ? cpeCnt++ : sceCnt++;
    271       FDKwriteBits(hBs, isCpe, 1);                              /* Front channel Elements is CPE? */
    272       FDKwriteBits(hBs, tag, 4);                                /* Front channel Instance Tag.*/
    273   }
    274   for(i=0; i<config->num_side_channel_elements; i++) {
    275       UCHAR isCpe = (*pEl_list++==ID_CPE) ? 1 : 0;
    276       UCHAR tag   = (isCpe) ? cpeCnt++ : sceCnt++;
    277       FDKwriteBits(hBs, isCpe, 1);                              /* Front channel Elements is CPE? */
    278       FDKwriteBits(hBs, tag, 4);                                /* Front channel Instance Tag.*/
    279   }
    280   for(i=0; i<config->num_back_channel_elements; i++) {
    281       UCHAR isCpe = (*pEl_list++==ID_CPE) ? 1 : 0;
    282       UCHAR tag   = (isCpe) ? cpeCnt++ : sceCnt++;
    283       FDKwriteBits(hBs, isCpe, 1);                              /* Front channel Elements is CPE? */
    284       FDKwriteBits(hBs, tag, 4);                                /* Front channel Instance Tag.*/
    285   }
    286   for(i=0; i<config->num_lfe_channel_elements; i++) {
    287       FDKwriteBits(hBs, lfeCnt++, 4);                           /* LFE channel Instance Tag. */
    288   }
    289 
    290   /* - num_valid_cc_elements always 0.
    291      - num_assoc_data_elements always 0. */
    292 
    293   /* Byte alignment: relative to alignAnchor
    294        ADTS: align with respect to the first bit of the raw_data_block()
    295        ADIF: align with respect to the first bit of the header
    296        LATM: align with respect to the first bit of the ASC */
    297   FDKbyteAlign(hBs, alignAnchor);                               /* Alignment */
    298 
    299   FDKwriteBits(hBs, 0 ,8);                                      /* Do no write any comment. */
    300 
    301   /* - comment_field_bytes always 0. */
    302 
    303   return 0;
    304 }
    305 
    306 int transportEnc_GetPCEBits(CHANNEL_MODE channelMode,
    307                             int matrixMixdownA,
    308                             int bits)
    309 {
    310   const PCE_CONFIGURATION* config = NULL;
    311 
    312   if ((config=getPceEntry(channelMode))==NULL) {
    313     return -1;  /* unsupported channelmapping */
    314   }
    315 
    316   bits += 4 + 2 + 4;        /* Element instance tag  + Object type + Sample rate index */
    317   bits += 4 + 4 + 4 + 2;    /* No (front + side + back + lfe channel) elements */
    318   bits += 3 + 4;            /* No (assoc data + valid cc) elements */
    319   bits += 1 + 1 + 1 ;       /* Mono + Stereo + Matrix mixdown present */
    320 
    321   if ( matrixMixdownA!=0 && ((channelMode==MODE_1_2_2)||(channelMode==MODE_1_2_2_1)) ) {
    322     bits +=3;               /* matrix_mixdown_idx + pseudo_surround_enable */
    323   }
    324 
    325   bits += (1+4) * (INT)config->num_front_channel_elements;
    326   bits += (1+4) * (INT)config->num_side_channel_elements;
    327   bits += (1+4) * (INT)config->num_back_channel_elements;
    328   bits +=   (4) * (INT)config->num_lfe_channel_elements;
    329 
    330   /* - num_valid_cc_elements always 0.
    331      - num_assoc_data_elements always 0. */
    332 
    333   if ((bits%8) != 0) {
    334     bits += (8 - (bits%8)); /* Alignment */
    335   }
    336 
    337   bits += 8;                /* Comment field  bytes */
    338 
    339   /* - comment_field_bytes alwys 0. */
    340 
    341   return bits;
    342 }
    343 #endif /* TP_PCE_ENABLE */
    344 
    345 static void writeAot(HANDLE_FDK_BITSTREAM hBitstreamBuffer, AUDIO_OBJECT_TYPE aot)
    346 {
    347     int tmp = (int) aot;
    348 
    349     if (tmp > 31) {
    350         FDKwriteBits( hBitstreamBuffer, AOT_ESCAPE, 5 );
    351         FDKwriteBits( hBitstreamBuffer, tmp-32, 6 );   /* AudioObjectType */
    352     } else {
    353         FDKwriteBits( hBitstreamBuffer, tmp, 5 );
    354     }
    355 }
    356 
    357 static void writeSampleRate(HANDLE_FDK_BITSTREAM hBitstreamBuffer, int sampleRate)
    358 {
    359   int sampleRateIndex = getSamplingRateIndex(sampleRate);
    360 
    361   FDKwriteBits( hBitstreamBuffer, sampleRateIndex, 4 );
    362   if( sampleRateIndex == 15 ) {
    363     FDKwriteBits( hBitstreamBuffer, sampleRate, 24 );
    364   }
    365 }
    366 
    367 #ifdef TP_GA_ENABLE
    368 static
    369 int transportEnc_writeGASpecificConfig(
    370                                         HANDLE_FDK_BITSTREAM asc,
    371                                         CODER_CONFIG *config,
    372                                         int          extFlg,
    373                                         UINT         alignAnchor
    374                                        )
    375 {
    376   int aot = config->aot;
    377   int samplesPerFrame = config->samplesPerFrame;
    378 
    379   /* start of GASpecificConfig according to ISO/IEC 14496-3 Subpart 4, 4.4.1 */
    380   FDKwriteBits( asc, ((samplesPerFrame==960 || samplesPerFrame==480)?1:0), 1);  /* frameLengthFlag: 1 for a 960/480 (I)MDCT, 0 for a 1024/512 (I)MDCT*/
    381   FDKwriteBits( asc, 0, 1);  /* dependsOnCoreCoder: Sampling Rate Coder Specific, see in ISO/IEC 14496-3 Subpart 4, 4.4.1 */
    382   FDKwriteBits( asc, extFlg, 1 ); /* Extension Flag: Shall be 1 for aot = 17,19,20,21,22,23 */
    383 
    384   /* Write PCE if channel config is not 1-7 */
    385   if (getChannelConfig(config->channelMode) == 0) {
    386       transportEnc_writePCE(asc, config->channelMode, config->samplingRate, 0, 1, config->matrixMixdownA, (config->flags&CC_PSEUDO_SURROUND)?1:0, alignAnchor);
    387   }
    388   if (extFlg) {
    389     if (aot == AOT_ER_BSAC) {
    390       FDKwriteBits( asc, config->BSACnumOfSubFrame, 5 ); /* numOfSubFrame */
    391       FDKwriteBits( asc, config->BSAClayerLength, 11 );  /* layer_length */
    392     }
    393     if ((aot == AOT_ER_AAC_LC)   || (aot == AOT_ER_AAC_LTP)  ||
    394         (aot == AOT_ER_AAC_SCAL) || (aot == AOT_ER_AAC_LD))
    395     {
    396       FDKwriteBits( asc, (config->flags & CC_VCB11) ? 1 : 0, 1 ); /* aacSectionDataResillienceFlag */
    397       FDKwriteBits( asc, (config->flags & CC_RVLC) ? 1 : 0,  1 ); /* aacScaleFactorDataResillienceFlag */
    398       FDKwriteBits( asc, (config->flags & CC_HCR) ? 1 : 0,   1 ); /* aacSpectralDataResillienceFlag */
    399     }
    400     FDKwriteBits( asc, 0, 1 ); /* extensionFlag3: reserved. Shall be '0' */
    401   }
    402   return 0;
    403 }
    404 #endif /* TP_GA_ENABLE */
    405 
    406 #ifdef TP_ELD_ENABLE
    407 
    408 static
    409 int transportEnc_writeELDSpecificConfig(
    410                                          HANDLE_FDK_BITSTREAM hBs,
    411                                          CODER_CONFIG *config,
    412                                          int        epConfig,
    413                                          CSTpCallBacks *cb
    414                                         )
    415 {
    416   /* ELD specific config */
    417   if (config->channelMode == MODE_1_1) {
    418     return -1;
    419   }
    420   FDKwriteBits(hBs, (config->samplesPerFrame == 480) ? 1 : 0, 1);
    421 
    422   FDKwriteBits(hBs, (config->flags & CC_VCB11 ) ? 1:0, 1);
    423   FDKwriteBits(hBs, (config->flags & CC_RVLC ) ? 1:0, 1);
    424   FDKwriteBits(hBs, (config->flags & CC_HCR  ) ? 1:0, 1);
    425 
    426   FDKwriteBits(hBs, (config->flags & CC_SBR) ? 1:0, 1); /* SBR header flag */
    427   if ( (config->flags & CC_SBR) ) {
    428     FDKwriteBits(hBs, (config->samplingRate == config->extSamplingRate) ? 0:1, 1); /* Samplerate Flag */
    429     FDKwriteBits(hBs, (config->flags & CC_SBRCRC) ? 1:0, 1); /* SBR CRC flag*/
    430 
    431     if (cb->cbSbr != NULL) {
    432       const PCE_CONFIGURATION *pPce;
    433       int e;
    434 
    435       pPce = getPceEntry(config->channelMode);
    436 
    437       for (e=0; e<PCE_MAX_ELEMENTS && pPce->el_list[e] != ID_NONE; e++  ) {
    438         if ( (pPce->el_list[e] == ID_SCE) || (pPce->el_list[e] == ID_CPE) ) {
    439           cb->cbSbr(cb->cbSbrData, hBs, 0, 0, 0, config->aot, pPce->el_list[e], e);
    440         }
    441       }
    442     }
    443   }
    444 
    445   FDKwriteBits(hBs, 0, 4); /* ELDEXT_TERM */
    446 
    447   return 0;
    448 }
    449 #endif /* TP_ELD_ENABLE */
    450 
    451 
    452 int transportEnc_writeASC (
    453                             HANDLE_FDK_BITSTREAM asc,
    454                             CODER_CONFIG *config,
    455                             CSTpCallBacks *cb
    456                            )
    457 {
    458   UINT extFlag = 0;
    459   int err;
    460   int epConfig = 0;
    461 
    462   /* Required for the PCE. */
    463   UINT alignAnchor = FDKgetValidBits(asc);
    464 
    465   /* Extension Flag: Shall be 1 for aot = 17,19,20,21,22,23,39 */
    466   switch (config->aot) {
    467     case AOT_ER_AAC_LC:
    468     case AOT_ER_AAC_LTP:
    469     case AOT_ER_AAC_SCAL:
    470     case AOT_ER_TWIN_VQ:
    471     case AOT_ER_BSAC:
    472     case AOT_ER_AAC_LD:
    473     case AOT_ER_AAC_ELD:
    474     case AOT_USAC:
    475         extFlag = 1;
    476         break;
    477     default:
    478         break;
    479   }
    480 
    481   if (config->sbrSignaling==SIG_EXPLICIT_HIERARCHICAL && config->sbrPresent)
    482     writeAot(asc, config->extAOT);
    483   else
    484     writeAot(asc, config->aot);
    485 
    486   {
    487     writeSampleRate(asc, config->samplingRate);
    488   }
    489 
    490   /* Try to guess a reasonable channel mode if not given */
    491   if (config->channelMode == MODE_INVALID) {
    492     config->channelMode = transportEnc_GetChannelMode(config->noChannels);
    493     if (config->channelMode == MODE_INVALID)
    494       return -1;
    495   }
    496 
    497   FDKwriteBits( asc, getChannelConfig(config->channelMode), 4 );
    498 
    499   if (config->sbrSignaling==SIG_EXPLICIT_HIERARCHICAL && config->sbrPresent) {
    500     writeSampleRate(asc, config->extSamplingRate);
    501     writeAot(asc, config->aot);
    502   }
    503 
    504   switch (config->aot) {
    505 #ifdef TP_GA_ENABLE
    506     case AOT_AAC_MAIN:
    507     case AOT_AAC_LC:
    508     case AOT_AAC_SSR:
    509     case AOT_AAC_LTP:
    510     case AOT_AAC_SCAL:
    511     case AOT_TWIN_VQ:
    512     case AOT_ER_AAC_LC:
    513     case AOT_ER_AAC_LTP:
    514     case AOT_ER_AAC_SCAL:
    515     case AOT_ER_TWIN_VQ:
    516     case AOT_ER_BSAC:
    517     case AOT_ER_AAC_LD:
    518       err = transportEnc_writeGASpecificConfig(asc, config, extFlag, alignAnchor);
    519       if (err)
    520         return err;
    521       break;
    522 #endif /* TP_GA_ENABLE */
    523 #ifdef TP_ELD_ENABLE
    524     case AOT_ER_AAC_ELD:
    525       err = transportEnc_writeELDSpecificConfig(asc, config, epConfig, cb);
    526       if (err)
    527         return err;
    528       break;
    529 #endif /* TP_ELD_ENABLE */
    530     default:
    531       return -1;
    532   }
    533 
    534   switch (config->aot) {
    535     case AOT_ER_AAC_LC:
    536     case AOT_ER_AAC_LTP:
    537     case AOT_ER_AAC_SCAL:
    538     case AOT_ER_TWIN_VQ:
    539     case AOT_ER_BSAC:
    540     case AOT_ER_AAC_LD:
    541     case AOT_ER_CELP:
    542     case AOT_ER_HVXC:
    543     case AOT_ER_HILN:
    544     case AOT_ER_PARA:
    545     case AOT_ER_AAC_ELD:
    546       FDKwriteBits( asc, 0, 2 ); /* epconfig 0 */
    547       break;
    548     default:
    549       break;
    550   }
    551 
    552   /* backward compatible explicit signaling of extension AOT */
    553   if (config->sbrSignaling==SIG_EXPLICIT_BW_COMPATIBLE)
    554   {
    555     TP_ASC_EXTENSION_ID ascExtId = ASCEXT_UNKOWN;
    556 
    557     if (config->sbrPresent) {
    558       ascExtId=ASCEXT_SBR;
    559       FDKwriteBits( asc, ascExtId, 11 );
    560       writeAot(asc, config->extAOT);
    561       FDKwriteBits( asc, 1, 1 ); /* sbrPresentFlag=1 */
    562       writeSampleRate(asc, config->extSamplingRate);
    563       if (config->psPresent) {
    564         ascExtId=ASCEXT_PS;
    565         FDKwriteBits( asc, ascExtId, 11 );
    566         FDKwriteBits( asc, 1, 1 ); /* psPresentFlag=1 */
    567       }
    568     }
    569 
    570   }
    571 
    572   /* Make sure all bits are sync'ed */
    573   FDKsyncCache( asc );
    574 
    575   return 0;
    576 }
    577