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 Decoder  **************************
     85 
     86    Author(s):   Christian Griebel
     87    Description: Dynamic range control (DRC) decoder tool for AAC
     88 
     89 ******************************************************************************/
     90 
     91 #include "aacdec_drc.h"
     92 
     93 
     94 #include "channelinfo.h"
     95 #include "aac_rom.h"
     96 
     97  #include "sbrdecoder.h"
     98 
     99 /*
    100  * Dynamic Range Control
    101  */
    102 
    103 /* For parameter conversion */
    104 #define DRC_PARAMETER_BITS        ( 7 )
    105 #define DRC_MAX_QUANT_STEPS       ( 1<<DRC_PARAMETER_BITS )
    106 #define DRC_MAX_QUANT_FACTOR      ( DRC_MAX_QUANT_STEPS-1 )
    107 #define DRC_PARAM_QUANT_STEP      ( FL2FXCONST_DBL(1.0f/(float)DRC_MAX_QUANT_FACTOR) )
    108 #define DRC_PARAM_SCALE           ( 1 )
    109 
    110 #define MAX_REFERENCE_LEVEL       ( 127 )
    111 
    112  #define DVB_ANC_DATA_SYNC_BYTE   ( 0xBC )    /* DVB ancillary data sync byte. */
    113 
    114 /*!
    115   \brief Initialize DRC information
    116 
    117   \self Handle of DRC info
    118 
    119   \return none
    120 */
    121 void aacDecoder_drcInit (
    122     HANDLE_AAC_DRC self )
    123 {
    124   CDrcParams *pParams;
    125 
    126   if (self == NULL) {
    127     return;
    128   }
    129 
    130   /* init control fields */
    131   self->enable = 0;
    132   self->numThreads = 0;
    133 
    134   /* init params */
    135   pParams = &self->params;
    136   pParams->bsDelayEnable = 0;
    137   pParams->cut      = FL2FXCONST_DBL(0.0f);
    138   pParams->usrCut   = FL2FXCONST_DBL(0.0f);
    139   pParams->boost    = FL2FXCONST_DBL(0.0f);
    140   pParams->usrBoost = FL2FXCONST_DBL(0.0f);
    141   pParams->targetRefLevel = -1;
    142   pParams->expiryFrame = AACDEC_DRC_DFLT_EXPIRY_FRAMES;
    143   pParams->applyDigitalNorm = 0;
    144   pParams->applyHeavyCompression = 0;
    145 
    146   /* initial program ref level = target ref level */
    147   self->progRefLevel = pParams->targetRefLevel;
    148   self->progRefLevelPresent = 0;
    149   self->presMode = -1;
    150 }
    151 
    152 
    153 /*!
    154   \brief Initialize DRC control data for one channel
    155 
    156   \self Handle of DRC info
    157 
    158   \return none
    159 */
    160 void aacDecoder_drcInitChannelData (
    161     CDrcChannelData *pDrcChData )
    162 {
    163   if (pDrcChData != NULL) {
    164     pDrcChData->expiryCount = 0;
    165     pDrcChData->numBands    = 1;
    166     pDrcChData->bandTop[0]  = (1024 >> 2) - 1;
    167     pDrcChData->drcValue[0] = 0;
    168     pDrcChData->drcInterpolationScheme = 0;
    169     pDrcChData->drcDataType = UNKNOWN_PAYLOAD;
    170   }
    171 }
    172 
    173 
    174 /*!
    175   \brief  Set one single DRC parameter
    176 
    177   \self   Handle of DRC info.
    178   \param  Parameter to be set.
    179   \value  Value to be set.
    180 
    181   \return an error code.
    182 */
    183 AAC_DECODER_ERROR aacDecoder_drcSetParam (
    184     HANDLE_AAC_DRC    self,
    185     AACDEC_DRC_PARAM  param,
    186     INT               value )
    187 {
    188   AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK;
    189 
    190   switch (param)
    191   {
    192   case DRC_CUT_SCALE:
    193     /* set attenuation scale factor */
    194     if ( (value < 0)
    195       || (value > DRC_MAX_QUANT_FACTOR) ) {
    196       return AAC_DEC_SET_PARAM_FAIL;
    197     }
    198     if (self == NULL) {
    199       return AAC_DEC_INVALID_HANDLE;
    200     }
    201     self->params.usrCut = (FIXP_DBL)((INT)(DRC_PARAM_QUANT_STEP>>DRC_PARAM_SCALE) * (INT)value);
    202     if (self->params.applyHeavyCompression == 0)
    203       self->params.cut = self->params.usrCut;
    204     break;
    205   case DRC_BOOST_SCALE:
    206     /* set boost factor */
    207     if ( (value < 0)
    208       || (value > DRC_MAX_QUANT_FACTOR) ) {
    209       return AAC_DEC_SET_PARAM_FAIL;
    210     }
    211     if (self == NULL) {
    212       return AAC_DEC_INVALID_HANDLE;
    213     }
    214     self->params.usrBoost = (FIXP_DBL)((INT)(DRC_PARAM_QUANT_STEP>>DRC_PARAM_SCALE) * (INT)value);
    215     if (self->params.applyHeavyCompression == 0)
    216       self->params.boost = self->params.usrBoost;
    217     break;
    218   case TARGET_REF_LEVEL:
    219     if ( value >  MAX_REFERENCE_LEVEL
    220       || value < -MAX_REFERENCE_LEVEL ) {
    221       return AAC_DEC_SET_PARAM_FAIL;
    222     }
    223     if (self == NULL) {
    224       return AAC_DEC_INVALID_HANDLE;
    225     }
    226     if (value < 0) {
    227       self->params.applyDigitalNorm = 0;
    228       self->params.targetRefLevel = -1;
    229     }
    230     else {
    231       /* ref_level must be between 0 and MAX_REFERENCE_LEVEL, inclusive */
    232       self->params.applyDigitalNorm = 1;
    233       if (self->params.targetRefLevel != (SCHAR)value) {
    234         self->params.targetRefLevel = (SCHAR)value;
    235         self->progRefLevel = (SCHAR)value;  /* Always set the program reference level equal to the
    236                                                target level according to 4.5.2.7.3 of ISO/IEC 14496-3. */
    237       }
    238     }
    239     break;
    240   case APPLY_NORMALIZATION:
    241     if (value < 0 || value > 1) {
    242       return AAC_DEC_SET_PARAM_FAIL;
    243     }
    244     if (self == NULL) {
    245       return AAC_DEC_INVALID_HANDLE;
    246     }
    247     /* Store new parameter value */
    248     self->params.applyDigitalNorm = (UCHAR)value;
    249     break;
    250   case APPLY_HEAVY_COMPRESSION:
    251     if (value < 0 || value > 1) {
    252       return AAC_DEC_SET_PARAM_FAIL;
    253     }
    254     if (self == NULL) {
    255       return AAC_DEC_INVALID_HANDLE;
    256     }
    257     if (self->params.applyHeavyCompression != (UCHAR)value) {
    258       if (value == 1) {
    259         /* Disable scaling of DRC values by setting the max values */
    260         self->params.boost = FL2FXCONST_DBL(1.0f/(float)(1<<DRC_PARAM_SCALE));
    261         self->params.cut   = FL2FXCONST_DBL(1.0f/(float)(1<<DRC_PARAM_SCALE));
    262       } else {
    263         /* Restore the user params */
    264         self->params.boost = self->params.usrBoost;
    265         self->params.cut   = self->params.usrCut;
    266       }
    267       /* Store new parameter value */
    268       self->params.applyHeavyCompression = (UCHAR)value;
    269     }
    270     break;
    271   case DRC_BS_DELAY:
    272     if (value < 0 || value > 1) {
    273       return AAC_DEC_SET_PARAM_FAIL;
    274     }
    275     if (self == NULL) {
    276       return AAC_DEC_INVALID_HANDLE;
    277     }
    278     self->params.bsDelayEnable = value;
    279     break;
    280   case DRC_DATA_EXPIRY_FRAME:
    281     if (self == NULL) {
    282       return AAC_DEC_INVALID_HANDLE;
    283     }
    284     self->params.expiryFrame = (UINT)value;
    285     break;
    286   default:
    287     return AAC_DEC_SET_PARAM_FAIL;
    288   }  /* switch(param) */
    289 
    290   /* switch on/off processing */
    291   self->enable = ( (self->params.boost > (FIXP_DBL)0)
    292                 || (self->params.cut   > (FIXP_DBL)0)
    293                 || (self->params.applyHeavyCompression != 0)
    294                 || (self->params.targetRefLevel >= 0) );
    295 
    296 
    297   return ErrorStatus;
    298 }
    299 
    300 
    301 static int parseExcludedChannels( UINT *excludedChnsMask,
    302                                   HANDLE_FDK_BITSTREAM bs )
    303 {
    304   UINT excludeMask = 0;
    305   UINT i, j;
    306   int  bitCnt = 9;
    307 
    308   for (i = 0, j = 1; i < 7; i++, j<<=1) {
    309     if (FDKreadBits(bs,1)) {
    310       excludeMask |= j;
    311     }
    312   }
    313 
    314   /* additional_excluded_chns */
    315   while (FDKreadBits(bs,1)) {
    316     for (i = 0; i < 7; i++, j<<=1) {
    317       if (FDKreadBits(bs,1)) {
    318         excludeMask |= j;
    319       }
    320     }
    321     bitCnt += 9;
    322     FDK_ASSERT(j < (UINT)-1);
    323   }
    324 
    325   *excludedChnsMask = excludeMask;
    326 
    327   return (bitCnt);
    328 }
    329 
    330 
    331 /*!
    332   \brief Save DRC payload bitstream position
    333 
    334   \self Handle of DRC info
    335   \bs Handle of FDK bitstream
    336 
    337   \return The number of DRC payload bits
    338 */
    339 int aacDecoder_drcMarkPayload (
    340     HANDLE_AAC_DRC self,
    341     HANDLE_FDK_BITSTREAM bs,
    342     AACDEC_DRC_PAYLOAD_TYPE type )
    343 {
    344   UINT bsStartPos;
    345   int  i, numBands = 1, bitCnt = 0;
    346 
    347   if (self == NULL) {
    348     return 0;
    349   }
    350 
    351   bsStartPos = FDKgetValidBits(bs);
    352 
    353   switch (type) {
    354     case MPEG_DRC_EXT_DATA:
    355     {
    356       bitCnt = 4;
    357 
    358       if (FDKreadBits(bs,1)) {          /* pce_tag_present */
    359         FDKreadBits(bs,8);              /* pce_instance_tag + drc_tag_reserved_bits */
    360         bitCnt+=8;
    361       }
    362 
    363       if (FDKreadBits(bs,1)) {          /* excluded_chns_present */
    364         FDKreadBits(bs,7);              /* exclude mask [0..7] */
    365         bitCnt+=8;
    366         while (FDKreadBits(bs,1)) {     /* additional_excluded_chns */
    367           FDKreadBits(bs,7);            /* exclude mask [x..y] */
    368           bitCnt+=8;
    369         }
    370       }
    371 
    372       if (FDKreadBits(bs,1)) {          /* drc_bands_present */
    373         numBands += FDKreadBits(bs, 4); /* drc_band_incr */
    374         FDKreadBits(bs,4);              /* reserved */
    375         bitCnt+=8;
    376         for (i = 0; i < numBands; i++) {
    377           FDKreadBits(bs,8);            /* drc_band_top[i] */
    378           bitCnt+=8;
    379         }
    380       }
    381 
    382       if (FDKreadBits(bs,1)) {          /* prog_ref_level_present */
    383         FDKreadBits(bs,8);              /* prog_ref_level + prog_ref_level_reserved_bits */
    384         bitCnt+=8;
    385       }
    386 
    387       for (i = 0; i < numBands; i++) {
    388         FDKreadBits(bs,8);              /* dyn_rng_sgn[i] + dyn_rng_ctl[i] */
    389         bitCnt+=8;
    390       }
    391 
    392       if ( (self->numPayloads < MAX_DRC_THREADS)
    393         && ((INT)FDKgetValidBits(bs) >= 0) )
    394       {
    395         self->drcPayloadPosition[self->numPayloads++] = bsStartPos;
    396       }
    397     }
    398     break;
    399 
    400     case DVB_DRC_ANC_DATA:
    401       bitCnt += 8;
    402       /* check sync word */
    403       if (FDKreadBits(bs, 8) == DVB_ANC_DATA_SYNC_BYTE)
    404       {
    405         int dmxLevelsPresent, compressionPresent;
    406         int coarseGrainTcPresent, fineGrainTcPresent;
    407 
    408         /* bs_info field */
    409         FDKreadBits(bs, 8);                          /* mpeg_audio_type, dolby_surround_mode, presentation_mode */
    410         bitCnt+=8;
    411 
    412         /* Evaluate ancillary_data_status */
    413         FDKreadBits(bs, 3);                          /* reserved, set to 0 */
    414         dmxLevelsPresent = FDKreadBits(bs, 1);       /* downmixing_levels_MPEG4_status */
    415         FDKreadBits(bs, 1);                          /* reserved, set to 0 */
    416         compressionPresent   = FDKreadBits(bs, 1);   /* audio_coding_mode_and_compression status */
    417         coarseGrainTcPresent = FDKreadBits(bs, 1);   /* coarse_grain_timecode_status */
    418         fineGrainTcPresent   = FDKreadBits(bs, 1);   /* fine_grain_timecode_status */
    419         bitCnt+=8;
    420 
    421         /* MPEG4 downmixing levels */
    422         if (dmxLevelsPresent) {
    423           FDKreadBits(bs, 8);                        /* downmixing_levels_MPEG4 */
    424           bitCnt+=8;
    425         }
    426         /* audio coding mode and compression status */
    427         if (compressionPresent) {
    428           FDKreadBits(bs, 16);                        /* audio_coding_mode, Compression_value */
    429           bitCnt+=16;
    430         }
    431         /* coarse grain timecode */
    432         if (coarseGrainTcPresent) {
    433           FDKreadBits(bs, 16);                       /* coarse_grain_timecode */
    434           bitCnt+=16;
    435         }
    436         /* fine grain timecode */
    437         if (fineGrainTcPresent) {
    438           FDKreadBits(bs, 16);                       /* fine_grain_timecode */
    439           bitCnt+=16;
    440         }
    441         if ( !self->dvbAncDataAvailable
    442           && ((INT)FDKgetValidBits(bs) >= 0) )
    443         {
    444           self->dvbAncDataPosition  = bsStartPos;
    445           self->dvbAncDataAvailable = 1;
    446         }
    447       }
    448       break;
    449 
    450     default:
    451       break;
    452   }
    453 
    454   return (bitCnt);
    455 }
    456 
    457 
    458 /*!
    459   \brief Parse DRC parameters from bitstream
    460 
    461   \bs Handle of FDK bitstream (in)
    462   \pDrcBs Pointer to DRC payload data container (out)
    463   \payloadPosition Bitstream position of MPEG DRC data junk (in)
    464 
    465   \return Number of bits read (0 in case of a parse error)
    466 */
    467 static int aacDecoder_drcParse (
    468     HANDLE_FDK_BITSTREAM  bs,
    469     CDrcPayload          *pDrcBs,
    470     UINT                  payloadPosition )
    471 {
    472   int i, numBands, bitCnt = 4;
    473 
    474   /* Move to the beginning of the DRC payload field */
    475   FDKpushBiDirectional(bs, FDKgetValidBits(bs)-payloadPosition);
    476 
    477   /* pce_tag_present */
    478   if (FDKreadBits(bs,1))
    479   {
    480     pDrcBs->pceInstanceTag = FDKreadBits(bs, 4);  /* pce_instance_tag */
    481     /* only one program supported */
    482     FDKreadBits(bs, 4);  /* drc_tag_reserved_bits */
    483     bitCnt += 8;
    484   } else {
    485     pDrcBs->pceInstanceTag = -1;  /* not present */
    486   }
    487 
    488   if (FDKreadBits(bs,1)) {        /* excluded_chns_present */
    489     /* get excluded_chn_mask */
    490     bitCnt += parseExcludedChannels(&pDrcBs->excludedChnsMask, bs);
    491   } else {
    492     pDrcBs->excludedChnsMask = 0;
    493   }
    494 
    495   numBands = 1;
    496   if (FDKreadBits(bs,1))  /* drc_bands_present */
    497   {
    498     /* get band_incr */
    499     numBands += FDKreadBits(bs, 4);  /* drc_band_incr */
    500     pDrcBs->channelData.drcInterpolationScheme = FDKreadBits(bs, 4);  /* drc_interpolation_scheme */
    501     bitCnt += 8;
    502     /* band_top */
    503     for (i = 0; i < numBands; i++)
    504     {
    505       pDrcBs->channelData.bandTop[i] = FDKreadBits(bs, 8);  /* drc_band_top[i] */
    506       bitCnt += 8;
    507     }
    508   }
    509   else {
    510     pDrcBs->channelData.bandTop[0] = (1024 >> 2) - 1;  /* ... comprising the whole spectrum. */;
    511   }
    512 
    513   pDrcBs->channelData.numBands = numBands;
    514 
    515   if (FDKreadBits(bs,1))                        /* prog_ref_level_present */
    516   {
    517     pDrcBs->progRefLevel = FDKreadBits(bs, 7);  /* prog_ref_level */
    518     FDKreadBits(bs, 1);                         /* prog_ref_level_reserved_bits */
    519     bitCnt += 8;
    520   } else {
    521     pDrcBs->progRefLevel = -1;
    522   }
    523 
    524   for (i = 0; i < numBands; i++)
    525   {
    526     pDrcBs->channelData.drcValue[i]  = FDKreadBits(bs, 1) << 7;   /* dyn_rng_sgn[i] */
    527     pDrcBs->channelData.drcValue[i] |= FDKreadBits(bs, 7) & 0x7F; /* dyn_rng_ctl[i] */
    528     bitCnt += 8;
    529   }
    530 
    531   /* Set DRC payload type */
    532   pDrcBs->channelData.drcDataType = MPEG_DRC_EXT_DATA;
    533 
    534   return (bitCnt);
    535 }
    536 
    537 
    538 /*!
    539   \brief Parse heavy compression value transported in DSEs of DVB streams with MPEG-4 content.
    540 
    541   \bs Handle of FDK bitstream (in)
    542   \pDrcBs Pointer to DRC payload data container (out)
    543   \payloadPosition Bitstream position of DVB ancillary data junk
    544 
    545   \return Number of bits read (0 in case of a parse error)
    546 */
    547 #define DVB_COMPRESSION_SCALE   ( 8 )       /* 48,164 dB */
    548 
    549 static int aacDecoder_drcReadCompression (
    550     HANDLE_FDK_BITSTREAM  bs,
    551     CDrcPayload          *pDrcBs,
    552     UINT                  payloadPosition )
    553 {
    554   int  bitCnt = 0;
    555   int  dmxLevelsPresent, extensionPresent, compressionPresent;
    556   int  coarseGrainTcPresent, fineGrainTcPresent;
    557 
    558   /* Move to the beginning of the DRC payload field */
    559   FDKpushBiDirectional(bs, FDKgetValidBits(bs)-payloadPosition);
    560 
    561   /* Sanity checks */
    562   if ( FDKgetValidBits(bs) < 24 ) {
    563     return 0;
    564   }
    565 
    566   /* Check sync word */
    567   if (FDKreadBits(bs, 8) != DVB_ANC_DATA_SYNC_BYTE) {
    568     return 0;
    569   }
    570 
    571   /* Evaluate bs_info field */
    572   if (FDKreadBits(bs, 2) != 3) {               /* mpeg_audio_type */
    573     /* No MPEG-4 audio data */
    574     return 0;
    575   }
    576   FDKreadBits(bs, 2);                          /* dolby_surround_mode */
    577   pDrcBs->presMode = FDKreadBits(bs, 2);       /* presentation_mode */
    578   FDKreadBits(bs, 1);                          /* stereo_downmix_mode */
    579   if (FDKreadBits(bs, 1) != 0) {               /* reserved, set to 0 */
    580     return 0;
    581   }
    582 
    583   /* Evaluate ancillary_data_status */
    584   if (FDKreadBits(bs, 3) != 0) {               /* reserved, set to 0 */
    585     return 0;
    586   }
    587   dmxLevelsPresent = FDKreadBits(bs, 1);       /* downmixing_levels_MPEG4_status */
    588   extensionPresent = FDKreadBits(bs, 1);       /* ancillary_data_extension_status; */
    589   compressionPresent   = FDKreadBits(bs, 1);   /* audio_coding_mode_and_compression status */
    590   coarseGrainTcPresent = FDKreadBits(bs, 1);   /* coarse_grain_timecode_status */
    591   fineGrainTcPresent   = FDKreadBits(bs, 1);   /* fine_grain_timecode_status */
    592   bitCnt += 24;
    593 
    594   if (dmxLevelsPresent) {
    595     FDKreadBits(bs, 8);                        /* downmixing_levels_MPEG4 */
    596     bitCnt += 8;
    597   }
    598 
    599   /* audio_coding_mode_and_compression_status */
    600   if (compressionPresent)
    601   {
    602     UCHAR compressionOn, compressionValue;
    603 
    604     /* audio_coding_mode */
    605     if ( FDKreadBits(bs, 7) != 0 ) {  /* The reserved bits shall be set to "0". */
    606       return 0;
    607     }
    608     compressionOn    = (UCHAR)FDKreadBits(bs, 1);  /* compression_on */
    609     compressionValue = (UCHAR)FDKreadBits(bs, 8);  /* Compression_value */
    610     bitCnt += 16;
    611 
    612     if ( compressionOn ) {
    613       /* A compression value is available so store the data just like MPEG DRC data */
    614       pDrcBs->channelData.numBands    =  1;                            /* One band ... */
    615       pDrcBs->channelData.drcValue[0] =  compressionValue;             /* ... with one value ... */
    616       pDrcBs->channelData.bandTop[0]  = (1024 >> 2) - 1;  /* ... comprising the whole spectrum. */
    617       pDrcBs->pceInstanceTag          = -1;                            /* Not present */
    618       pDrcBs->progRefLevel            = -1;                            /* Not present */
    619       pDrcBs->channelData.drcDataType =  DVB_DRC_ANC_DATA;             /* Set DRC payload type to DVB. */
    620     } else {
    621       /* No compression value available */
    622       /* CAUTION: It is not clearly defined by standard how to react in this situation. */
    623       /* Turn down the compression value to aprox. 0dB */
    624       pDrcBs->channelData.numBands    =  1;                            /* One band ... */
    625       pDrcBs->channelData.drcValue[0] =  0x80;                         /* ... with aprox. 0dB ... */
    626       pDrcBs->channelData.bandTop[0]  = (1024 >> 2) - 1;  /* ... comprising the whole spectrum. */
    627       pDrcBs->channelData.drcDataType =  DVB_DRC_ANC_DATA;             /* Set DRC payload type to DVB. */
    628 
    629       /* If compression_on field is set to "0" the compression_value field shall be "0000 0000". */
    630       if (compressionValue != 0) {
    631         return 0;
    632       }
    633     }
    634   }
    635 
    636   /* Read timecodes if available just to get the right amount of bits. */
    637   if (coarseGrainTcPresent) {
    638     FDKreadBits(bs, 16);      /* coarse_grain_timecode */
    639     bitCnt += 16;
    640   }
    641   if (fineGrainTcPresent) {
    642     FDKreadBits(bs, 16);      /* fine_grain_timecode */
    643     bitCnt += 16;
    644   }
    645 
    646   /* Read extension just to get the right amount of bits. */
    647   if (extensionPresent) {
    648     int  extBits = 8;
    649 
    650     FDKreadBits(bs, 1);                     /* reserved, set to 0 */
    651     if (FDKreadBits(bs, 1)) extBits += 8;   /* ext_downmixing_levels_status */
    652     if (FDKreadBits(bs, 1)) extBits += 16;  /* ext_downmixing_global_gains_status */
    653     if (FDKreadBits(bs, 1)) extBits += 8;   /* ext_downmixing_lfe_level_status */
    654 
    655     FDKpushFor(bs, extBits - 4);            /* skip the extension payload remainder. */
    656     bitCnt += extBits;
    657   }
    658 
    659   return (bitCnt);
    660 }
    661 
    662 
    663 /*
    664  * Prepare DRC processing
    665  */
    666 static int aacDecoder_drcExtractAndMap (
    667         HANDLE_AAC_DRC  self,
    668         HANDLE_FDK_BITSTREAM hBs,
    669         CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
    670         UCHAR  pceInstanceTag,
    671         UCHAR  channelMapping[], /* Channel mapping translating drcChannel index to canonical channel index */
    672         int    validChannels )
    673 {
    674   CDrcPayload  threadBs[MAX_DRC_THREADS];
    675   CDrcPayload *validThreadBs[MAX_DRC_THREADS];
    676   CDrcParams  *pParams;
    677   UINT backupBsPosition;
    678   int  i, thread, validThreads = 0;
    679   int  numExcludedChns[MAX_DRC_THREADS];
    680 
    681   FDK_ASSERT(self != NULL);
    682   FDK_ASSERT(hBs != NULL);
    683   FDK_ASSERT(pAacDecoderStaticChannelInfo != NULL);
    684 
    685   pParams = &self->params;
    686 
    687   self->numThreads = 0;
    688   backupBsPosition = FDKgetValidBits(hBs);
    689 
    690   for (i = 0; i < self->numPayloads && self->numThreads < MAX_DRC_THREADS; i++) {
    691     int bitsParsed;
    692 
    693     /* Init payload data chunk. The memclear is very important because it initializes
    694        the most values. Without it the module wouldn't work properly or crash. */
    695     FDKmemclear(&threadBs[self->numThreads], sizeof(CDrcPayload));
    696     threadBs[self->numThreads].channelData.bandTop[0]  = (1024 >> 2) - 1;
    697 
    698     /* Extract payload */
    699     bitsParsed = aacDecoder_drcParse( hBs,
    700                                      &threadBs[self->numThreads],
    701                                       self->drcPayloadPosition[i] );
    702     if (bitsParsed > 0) {
    703       self->numThreads++;
    704     }
    705   }
    706   self->numPayloads = 0;
    707 
    708   if (self->dvbAncDataAvailable && self->numThreads < MAX_DRC_THREADS)
    709   { /* Append a DVB heavy compression payload thread if available. */
    710     int bitsParsed;
    711 
    712     /* Init payload data chunk. The memclear is very important because it initializes
    713        the most values. Without it the module wouldn't work properly or crash. */
    714     FDKmemclear(&threadBs[self->numThreads], sizeof(CDrcPayload));
    715     threadBs[self->numThreads].channelData.bandTop[0]  = (1024 >> 2) - 1;
    716 
    717     /* Extract payload */
    718     bitsParsed = aacDecoder_drcReadCompression( hBs,
    719                                                &threadBs[self->numThreads],
    720                                                 self->dvbAncDataPosition );
    721     if (bitsParsed > 0) {
    722       self->numThreads++;
    723     }
    724   }
    725   self->dvbAncDataAvailable = 0;
    726 
    727   /* Reset the bitbufffer */
    728   FDKpushBiDirectional(hBs, FDKgetValidBits(hBs) - backupBsPosition);
    729 
    730   /* calculate number of valid bits in excl_chn_mask */
    731 
    732   /* coupling channels not supported */
    733 
    734   /* check for valid threads */
    735   for (thread = 0; thread < self->numThreads; thread++) {
    736     CDrcPayload *pThreadBs = &threadBs[thread];
    737     int numExclChns = 0;
    738 
    739     switch ((AACDEC_DRC_PAYLOAD_TYPE)pThreadBs->channelData.drcDataType) {
    740       default:
    741         continue;
    742       case MPEG_DRC_EXT_DATA:
    743       case DVB_DRC_ANC_DATA:
    744         break;
    745     }
    746 
    747     if (pThreadBs->pceInstanceTag >= 0) {  /* if PCE tag present */
    748       if (pThreadBs->pceInstanceTag != pceInstanceTag) {
    749         continue;  /* don't accept */
    750       }
    751     }
    752 
    753     /* calculate number of excluded channels */
    754     if (pThreadBs->excludedChnsMask > 0) {
    755       INT exclMask = pThreadBs->excludedChnsMask;
    756       int ch;
    757       for (ch = 0; ch < validChannels; ch++) {
    758         numExclChns += exclMask & 0x1;
    759         exclMask >>= 1;
    760       }
    761     }
    762     if (numExclChns < validChannels) {
    763       validThreadBs[validThreads]   = pThreadBs;
    764       numExcludedChns[validThreads] = numExclChns;
    765       validThreads++;
    766     }
    767   }
    768 
    769   if (validThreads > 1) {
    770     int ch;
    771 
    772     /* check consistency of excl_chn_mask amongst valid DRC threads */
    773     for (ch = 0; ch < validChannels; ch++) {
    774       int present = 0;
    775 
    776       for (thread = 0; thread < validThreads; thread++) {
    777         CDrcPayload *pThreadBs = validThreadBs[thread];
    778 
    779 
    780         /* thread applies to this channel */
    781         if ( (pThreadBs->channelData.drcDataType == MPEG_DRC_EXT_DATA)
    782           && ( (numExcludedChns[thread] == 0)
    783             || (!(pThreadBs->excludedChnsMask & (1<<ch))) ) ) {
    784           present++;
    785         }
    786       }
    787 
    788 
    789       if (present > 1) {
    790         return -1;
    791       }
    792     }
    793   }
    794 
    795   /* map DRC bitstream information onto DRC channel information */
    796   for (thread = 0; thread < validThreads; thread++)
    797   {
    798     CDrcPayload *pThreadBs = validThreadBs[thread];
    799     INT exclMask = pThreadBs->excludedChnsMask;
    800     AACDEC_DRC_PAYLOAD_TYPE drcPayloadType = (AACDEC_DRC_PAYLOAD_TYPE)pThreadBs->channelData.drcDataType;
    801     int ch;
    802 
    803     /* last progRefLevel transmitted is the one that is used
    804      * (but it should really only be transmitted once per block!)
    805      */
    806     if (pThreadBs->progRefLevel >= 0) {
    807       self->progRefLevel = pThreadBs->progRefLevel;
    808       self->progRefLevelPresent = 1;
    809       self->prlExpiryCount = 0;  /* Got a new value -> Reset counter */
    810     }
    811 
    812     if (drcPayloadType == DVB_DRC_ANC_DATA) {
    813       /* Announce the presentation mode of this valid thread. */
    814       self->presMode = pThreadBs->presMode;
    815     }
    816 
    817     /* SCE, CPE and LFE */
    818     for (ch = 0; ch < validChannels; ch++) {
    819       int mapedChannel = channelMapping[ch];
    820 
    821       if ( ((exclMask & (1<<mapedChannel)) == 0)
    822         && ( (drcPayloadType == MPEG_DRC_EXT_DATA)
    823           || ((drcPayloadType == DVB_DRC_ANC_DATA) && self->params.applyHeavyCompression)
    824          ) ) {
    825         /* copy thread to channel */
    826         pAacDecoderStaticChannelInfo[ch]->drcData = pThreadBs->channelData;
    827       }
    828     }
    829     /* CCEs not supported by now */
    830   }
    831 
    832   /* Increment and check expiry counter for the program reference level: */
    833   if ( (pParams->expiryFrame > 0)
    834     && (self->prlExpiryCount++ > pParams->expiryFrame) )
    835   { /* The program reference level is too old, so set it back to the target level. */
    836     self->progRefLevelPresent = 0;
    837     self->progRefLevel = pParams->targetRefLevel;
    838     self->prlExpiryCount = 0;
    839   }
    840 
    841   return 0;
    842 }
    843 
    844 
    845 void aacDecoder_drcApply (
    846         HANDLE_AAC_DRC          self,
    847         void                   *pSbrDec,
    848         CAacDecoderChannelInfo *pAacDecoderChannelInfo,
    849         CDrcChannelData        *pDrcChData,
    850         FIXP_DBL               *extGain,
    851         int  ch,   /* needed only for SBR */
    852         int  aacFrameSize,
    853         int  bSbrPresent )
    854 {
    855   int band, top, bin, numBands;
    856   int bottom = 0;
    857   int modifyBins = 0;
    858 
    859   FIXP_DBL max_mantissa;
    860   INT max_exponent;
    861 
    862   FIXP_DBL norm_mantissa = FL2FXCONST_DBL(0.5f);
    863   INT  norm_exponent = 1;
    864 
    865   FIXP_DBL fact_mantissa[MAX_DRC_BANDS];
    866   INT  fact_exponent[MAX_DRC_BANDS];
    867 
    868   CDrcParams  *pParams = &self->params;
    869 
    870   FIXP_DBL    *pSpectralCoefficient  =  SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
    871   CIcsInfo    *pIcsInfo              = &pAacDecoderChannelInfo->icsInfo;
    872   SHORT       *pSpecScale            =  pAacDecoderChannelInfo->specScale;
    873 
    874   int winSeq = pIcsInfo->WindowSequence;
    875 
    876   /* Increment and check expiry counter */
    877   if ( (pParams->expiryFrame > 0)
    878     && (++pDrcChData->expiryCount > pParams->expiryFrame) )
    879   { /* The DRC data is too old, so delete it. */
    880     aacDecoder_drcInitChannelData( pDrcChData );
    881   }
    882 
    883   if (!self->enable) {
    884     sbrDecoder_drcDisable( (HANDLE_SBRDECODER)pSbrDec, ch );
    885     if (extGain != NULL) {
    886       INT gainScale = (INT)*extGain;
    887       /* The gain scaling must be passed to the function in the buffer pointed on by extGain. */
    888       if (gainScale >= 0 && gainScale <= DFRACT_BITS) {
    889         *extGain = scaleValue(norm_mantissa, norm_exponent-gainScale);
    890       } else {
    891         FDK_ASSERT(0);
    892       }
    893     }
    894     return;
    895   }
    896 
    897   numBands = pDrcChData->numBands;
    898   top = FDKmax(0, numBands-1);
    899 
    900   pDrcChData->bandTop[0] = fixMin(pDrcChData->bandTop[0], (aacFrameSize >> 2) - 1);
    901 
    902   /* If program reference normalization is done in the digital domain,
    903   modify factor to perform normalization.  prog_ref_level can
    904   alternatively be passed to the system for modification of the level in
    905   the analog domain.  Analog level modification avoids problems with
    906   reduced DAC SNR (if signal is attenuated) or clipping (if signal is
    907   boosted) */
    908 
    909   if (pParams->targetRefLevel >= 0)
    910   {
    911     /* 0.5^((targetRefLevel - progRefLevel)/24) */
    912     norm_mantissa = fLdPow(
    913             FL2FXCONST_DBL(-1.0), /* log2(0.5) */
    914             0,
    915             (FIXP_DBL)((INT)(FL2FXCONST_DBL(1.0f/24.0)>>3) * (INT)(pParams->targetRefLevel-self->progRefLevel)),
    916             3,
    917            &norm_exponent );
    918   }
    919   /* Always export the normalization gain (if possible). */
    920   if (extGain != NULL) {
    921     INT gainScale = (INT)*extGain;
    922     /* The gain scaling must be passed to the function in the buffer pointed on by extGain. */
    923     if (gainScale >= 0 && gainScale <= DFRACT_BITS) {
    924       *extGain = scaleValue(norm_mantissa, norm_exponent-gainScale);
    925     } else {
    926       FDK_ASSERT(0);
    927     }
    928   }
    929   if (self->params.applyDigitalNorm == 0) {
    930     /* Reset normalization gain since this module must not apply it */
    931     norm_mantissa = FL2FXCONST_DBL(0.5f);
    932     norm_exponent = 1;
    933   }
    934 
    935 
    936   /* calc scale factors */
    937   for (band = 0; band < numBands; band++)
    938   {
    939     UCHAR drcVal = pDrcChData->drcValue[band];
    940     top = fixMin((int)( (pDrcChData->bandTop[band]+1)<<2 ), aacFrameSize);
    941 
    942     fact_mantissa[band] = FL2FXCONST_DBL(0.5f);
    943     fact_exponent[band] = 1;
    944 
    945     if (  pParams->applyHeavyCompression
    946       && ((AACDEC_DRC_PAYLOAD_TYPE)pDrcChData->drcDataType == DVB_DRC_ANC_DATA) )
    947     {
    948       INT compressionFactorVal_e;
    949       int valX, valY;
    950 
    951       valX = drcVal >> 4;
    952       valY = drcVal & 0x0F;
    953 
    954       /* calculate the unscaled heavy compression factor.
    955          compressionFactor = 48.164 - 6.0206*valX - 0.4014*valY dB
    956          range: -48.166 dB to 48.164 dB */
    957       if ( drcVal != 0x7F ) {
    958         fact_mantissa[band] =
    959           fPowInt( FL2FXCONST_DBL(0.95483867181), /* -0.4014dB = 0.95483867181 */
    960                    0,
    961                    valY,
    962                   &compressionFactorVal_e );
    963 
    964         /* -0.0008dB (48.164 - 6.0206*8 = -0.0008) */
    965         fact_mantissa[band] = fMult(FL2FXCONST_DBL(0.99990790084), fact_mantissa[band]);
    966 
    967         fact_exponent[band] = DVB_COMPRESSION_SCALE - valX + compressionFactorVal_e;
    968       }
    969     } else
    970     if ((AACDEC_DRC_PAYLOAD_TYPE)pDrcChData->drcDataType == MPEG_DRC_EXT_DATA)
    971     {
    972     /* apply the scaled dynamic range control words to factor.
    973      * if scaling drc_cut (or drc_boost), or control word drc_mantissa is 0
    974      * then there is no dynamic range compression
    975      *
    976      * if pDrcChData->drcSgn[band] is
    977      *  1 then gain is < 1 :  factor = 2^(-self->cut   * pDrcChData->drcMag[band] / 24)
    978      *  0 then gain is > 1 :  factor = 2^( self->boost * pDrcChData->drcMag[band] / 24)
    979      */
    980 
    981     if ((drcVal&0x7F) > 0) {
    982       FIXP_DBL tParamVal = (drcVal & 0x80) ? -pParams->cut : pParams->boost;
    983 
    984       fact_mantissa[band] =
    985         f2Pow( (FIXP_DBL)((INT)fMult(FL2FXCONST_DBL(1.0f/192.0f), tParamVal) * (drcVal&0x7F)),
    986                  3+DRC_PARAM_SCALE,
    987                 &fact_exponent[band] );
    988     }
    989     }
    990 
    991     fact_mantissa[band]  = fMult(fact_mantissa[band], norm_mantissa);
    992     fact_exponent[band] += norm_exponent;
    993 
    994 
    995     bottom = top;
    996 
    997   }  /* end loop over bands */
    998 
    999 
   1000   /* normalizations */
   1001   {
   1002     int res;
   1003 
   1004     max_mantissa = FL2FXCONST_DBL(0.0f);
   1005     max_exponent = 0;
   1006     for (band = 0; band < numBands; band++) {
   1007       max_mantissa = fixMax(max_mantissa, fact_mantissa[band]);
   1008       max_exponent = fixMax(max_exponent, fact_exponent[band]);
   1009     }
   1010 
   1011     /* left shift factors to gain accurancy */
   1012     res = CntLeadingZeros(max_mantissa) - 1;
   1013 
   1014     /* above topmost DRC band gain factor is 1 */
   1015     if (((pDrcChData->bandTop[numBands-1]+1)<<2) < aacFrameSize) res = 0;
   1016 
   1017     if (res > 0) {
   1018       res = fixMin(res, max_exponent);
   1019       max_exponent -= res;
   1020 
   1021       for (band = 0; band < numBands; band++) {
   1022         fact_mantissa[band] <<= res;
   1023         fact_exponent[band]  -= res;
   1024       }
   1025     }
   1026 
   1027     /* normalize magnitudes to one scale factor */
   1028     for (band = 0; band < numBands; band++) {
   1029       if (fact_exponent[band] < max_exponent) {
   1030         fact_mantissa[band] >>= max_exponent - fact_exponent[band];
   1031       }
   1032       if (fact_mantissa[band] != FL2FXCONST_DBL(0.5f)) {
   1033         modifyBins = 1;
   1034       }
   1035     }
   1036     if (max_exponent != 1) {
   1037       modifyBins = 1;
   1038     }
   1039   }
   1040 
   1041   /*  apply factor to spectral lines
   1042    *  short blocks must take care that bands fall on
   1043    *  block boundaries!
   1044    */
   1045   if (!bSbrPresent)
   1046   {
   1047     bottom = 0;
   1048 
   1049     if (!modifyBins) {
   1050       /* We don't have to modify the spectral bins because the fractional part of all factors is 0.5.
   1051          In order to keep accurancy we don't apply the factor but decrease the exponent instead. */
   1052       max_exponent -= 1;
   1053     } else
   1054     {
   1055       for (band = 0; band < numBands; band++)
   1056       {
   1057         top = fixMin((int)( (pDrcChData->bandTop[band]+1)<<2 ), aacFrameSize);   /* ... * DRC_BAND_MULT; */
   1058 
   1059         for (bin = bottom; bin < top; bin++) {
   1060           pSpectralCoefficient[bin] = fMult(pSpectralCoefficient[bin], fact_mantissa[band]);
   1061         }
   1062 
   1063         bottom = top;
   1064       }
   1065     }
   1066 
   1067     /* above topmost DRC band gain factor is 1 */
   1068     if (max_exponent > 0) {
   1069       for (bin = bottom; bin < aacFrameSize; bin+=1) {
   1070         pSpectralCoefficient[bin] >>= max_exponent;
   1071       }
   1072     }
   1073 
   1074     /* adjust scaling */
   1075     pSpecScale[0] += max_exponent;
   1076 
   1077     if (winSeq == EightShortSequence) {
   1078       int win;
   1079       for (win = 1; win < 8; win++) {
   1080         pSpecScale[win] += max_exponent;
   1081       }
   1082     }
   1083   }
   1084   else {
   1085     HANDLE_SBRDECODER hSbrDecoder = (HANDLE_SBRDECODER)pSbrDec;
   1086     UINT numBands = pDrcChData->numBands;
   1087 
   1088     /* feed factors into SBR decoder for application in QMF domain. */
   1089     sbrDecoder_drcFeedChannel (
   1090             hSbrDecoder,
   1091             ch,
   1092             numBands,
   1093             fact_mantissa,
   1094             max_exponent,
   1095             pDrcChData->drcInterpolationScheme,
   1096             winSeq,
   1097             pDrcChData->bandTop
   1098           );
   1099   }
   1100 
   1101   return;
   1102 }
   1103 
   1104 
   1105 /*
   1106  * Prepare DRC processing
   1107  */
   1108 int aacDecoder_drcProlog (
   1109         HANDLE_AAC_DRC  self,
   1110         HANDLE_FDK_BITSTREAM hBs,
   1111         CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
   1112         UCHAR  pceInstanceTag,
   1113         UCHAR  channelMapping[], /* Channel mapping translating drcChannel index to canonical channel index */
   1114         int    validChannels )
   1115 {
   1116   int err = 0;
   1117 
   1118   if (self == NULL) {
   1119     return -1;
   1120   }
   1121 
   1122   if (!self->params.bsDelayEnable)
   1123   {
   1124     err = aacDecoder_drcExtractAndMap (
   1125             self,
   1126             hBs,
   1127             pAacDecoderStaticChannelInfo,
   1128             pceInstanceTag,
   1129             channelMapping,
   1130             validChannels );
   1131   }
   1132 
   1133   return err;
   1134 }
   1135 
   1136 
   1137 /*
   1138  * Finalize DRC processing
   1139  */
   1140 int aacDecoder_drcEpilog (
   1141         HANDLE_AAC_DRC  self,
   1142         HANDLE_FDK_BITSTREAM hBs,
   1143         CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
   1144         UCHAR  pceInstanceTag,
   1145         UCHAR  channelMapping[], /* Channel mapping translating drcChannel index to canonical channel index */
   1146         int    validChannels )
   1147 {
   1148   int err = 0;
   1149 
   1150   if (self == NULL) {
   1151     return -1;
   1152   }
   1153 
   1154   if (self->params.bsDelayEnable)
   1155   {
   1156     err = aacDecoder_drcExtractAndMap (
   1157             self,
   1158             hBs,
   1159             pAacDecoderStaticChannelInfo,
   1160             pceInstanceTag,
   1161             channelMapping,
   1162             validChannels );
   1163   }
   1164 
   1165   return err;
   1166 }
   1167 
   1168 /*
   1169  * Export relevant metadata info from bitstream payload.
   1170  */
   1171 void aacDecoder_drcGetInfo (
   1172         HANDLE_AAC_DRC  self,
   1173         SCHAR          *pPresMode,
   1174         SCHAR          *pProgRefLevel )
   1175 {
   1176   if (self != NULL) {
   1177     if (pPresMode != NULL) {
   1178       *pPresMode = self->presMode;
   1179     }
   1180     if (pProgRefLevel != NULL) {
   1181       if (self->progRefLevelPresent) {
   1182         *pProgRefLevel = self->progRefLevel;
   1183       } else {
   1184         *pProgRefLevel = -1;
   1185       }
   1186     }
   1187   }
   1188 }
   1189