/*  Copyright (c) MediaArea.net SARL. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license that can
 *  be found in the License.html file in the root of the source tree.
 */
 
//---------------------------------------------------------------------------
// Pre-compilation
#include "MediaInfo/PreComp.h"
#ifdef __BORLANDC__
    #pragma hdrstop
#endif
//---------------------------------------------------------------------------
 
//---------------------------------------------------------------------------
#include "MediaInfo/Setup.h"
//---------------------------------------------------------------------------
 
//---------------------------------------------------------------------------
#if defined(MEDIAINFO_AAC_YES) || defined(MEDIAINFO_MPEGH3DA_YES)
//---------------------------------------------------------------------------
 
//---------------------------------------------------------------------------
#include "MediaInfo/Audio/File_Usac.h"
#include <algorithm>
using namespace std;
//---------------------------------------------------------------------------
 
namespace MediaInfoLib
{
 
//***************************************************************************
// Info
//***************************************************************************
 
//---------------------------------------------------------------------------
extern int8u Aac_AudioSpecificConfig_sampling_frequency_index(const int64s sampling_frequency);
extern const size_t Aac_sampling_frequency_Size_Usac;
extern const int32u Aac_sampling_frequency[];
extern string Aac_Channels_GetString(int8u ChannelLayout);
extern string Aac_ChannelConfiguration_GetString(int8u ChannelLayout);
extern string Aac_ChannelConfiguration2_GetString(int8u ChannelLayout);
extern string Aac_ChannelLayout_GetString(int8u ChannelLayout, bool IsMpegH=false);
extern string Aac_OutputChannelPosition_GetString(int8u OutputChannelPosition);
 
//---------------------------------------------------------------------------
struct coreSbrFrameLengthIndex_mapping
{
    int8u    sbrRatioIndex;
    int8u    outputFrameLengthDivided256;
};
extern const size_t coreSbrFrameLengthIndex_Mapping_Size=5;
extern coreSbrFrameLengthIndex_mapping coreSbrFrameLengthIndex_Mapping[coreSbrFrameLengthIndex_Mapping_Size] =
{
    { 0,  3 },
    { 0,  4 },
    { 2,  8 },
    { 3,  8 },
    { 1, 16 },
};
 
//---------------------------------------------------------------------------
static const size_t LoudnessMeaning_Size=9;
static const char* LoudnessMeaning[LoudnessMeaning_Size]=
{
    "Loudness_Program",
    "Loudness_Anchor",
    "Loudness_MaximumOfRange",
    "Loudness_MaximumMomentary",
    "Loudness_MaximumShortTerm",
    "Loudness_Range",
    "Loudness_ProductionMixingLevel",
    "Loudness_RoomType",
    "Loudness_ShortTerm",
};
 
//***************************************************************************
// Constructor/Destructor
//***************************************************************************
 
//---------------------------------------------------------------------------
File_Usac::File_Usac()
:File__Analyze()
{
    channelConfiguration=(int8u)-1;
    sampling_frequency_index=(int8u)-1;
    extension_sampling_frequency_index=(int8u)-1;
}
 
//---------------------------------------------------------------------------
File_Usac::~File_Usac()
{
}
 
//***************************************************************************
// Elements - USAC
//***************************************************************************
 
//---------------------------------------------------------------------------
void File_Usac::UsacConfig()
{
    // Init
    loudnessInfoSet_Present=false;
 
    Element_Begin1("UsacConfig");
    int8u coreSbrFrameLengthIndex;
    bool usacConfigExtensionPresent;
    Get_S1 (5, sampling_frequency_index,                        "usacSamplingFrequencyIndex"); Param_Info1C(sampling_frequency_index<Aac_sampling_frequency_Size_Usac && Aac_sampling_frequency[sampling_frequency_index], Aac_sampling_frequency[sampling_frequency_index]);
    if (sampling_frequency_index==Aac_sampling_frequency_Size_Usac)
    {
        int32u samplingFrequency;
        Get_S3 (24, samplingFrequency,                          "usacSamplingFrequency");
        Frequency_b=samplingFrequency;
        sampling_frequency_index=Aac_AudioSpecificConfig_sampling_frequency_index(Frequency_b);
    }
    else
        Frequency_b=Aac_sampling_frequency[sampling_frequency_index];
    Get_S1 (3, coreSbrFrameLengthIndex,                         "coreSbrFrameLengthIndex");
    Get_S1 (5, channelConfiguration,                            "channelConfiguration"); Param_Info1C(channelConfiguration, Aac_ChannelLayout_GetString(channelConfiguration));
    if (!channelConfiguration)
    {
        int32u numOutChannels;
        escapedValue(numOutChannels, 5, 8, 16,                  "numOutChannels");
        for (int32u i=0; i<numOutChannels; i++)
        {
            Info_S1(5, bsOutChannelPos,                         "bsOutChannelPos"); Param_Info1(Aac_OutputChannelPosition_GetString(bsOutChannelPos));
        }
    }
    if (coreSbrFrameLengthIndex>=coreSbrFrameLengthIndex_Mapping_Size)
    {
        Skip_BS(Data_BS_Remain(),                               "(Not implemented)");
        Element_End0();
        return;
    }
    UsacDecoderConfig(coreSbrFrameLengthIndex);
    Get_SB (usacConfigExtensionPresent,                         "usacConfigExtensionPresent");
    if (usacConfigExtensionPresent)
        UsacConfigExtension();
    Element_End0();
 
    // Filling
    Fill(Stream_Audio, 0, Audio_SamplesPerFrame, coreSbrFrameLengthIndex_Mapping[coreSbrFrameLengthIndex].outputFrameLengthDivided256 << 8, true);
    Fill_DRC();
    Fill_Loudness();
}
 
//---------------------------------------------------------------------------
void File_Usac::Fill_DRC(const char* Prefix)
{
    if (!drcInstructionsUniDrc_Data.empty())
    {
        string FieldPrefix;
        if (Prefix)
        {
            FieldPrefix+=Prefix;
            FieldPrefix += ' ';
        }
 
        Fill(Stream_Audio, 0, (FieldPrefix+"DrcSets_Count").c_str(), drcInstructionsUniDrc_Data.size());
        Fill_SetOptions(Stream_Audio, 0, (FieldPrefix + "DrcSets_Count").c_str(), "N NI"); // Hidden in text output
        ZtringList Ids, Data;
        for (std::map<int16u, drc_info>::iterator Item=drcInstructionsUniDrc_Data.begin(); Item!=drcInstructionsUniDrc_Data.end(); ++Item)
        {
            int8u drcSetId=Item->first>>8;
            int8u downmixId=Item->first&((1<<8)-1);
            Ztring Id;
            if (drcSetId || downmixId)
                Id=Ztring::ToZtring(drcSetId)+=__T('-')+Ztring::ToZtring(downmixId);
            Ids.push_back(Id);
            Data.push_back(Ztring().From_UTF8(Item->second.drcSetEffectTotal));
        }
        Fill(Stream_Audio, 0, (FieldPrefix+"DrcSets_Effects").c_str(), Data, Ids);
    }
}
 
//---------------------------------------------------------------------------
void File_Usac::Fill_Loudness(const char* Prefix, bool NoConCh)
{
    string FieldPrefix;
    if (Prefix)
    {
        FieldPrefix+=Prefix;
        FieldPrefix += ' ';
    }
    string FieldSuffix;
 
    bool DefaultIdPresent=false;
    for (int8u i=0; i<2; i++)
    {
        if (i)
            FieldSuffix="_Album";
        if (!loudnessInfo_Data[i].empty())
        {
            Fill(Stream_Audio, 0, (FieldPrefix+"Loudness_Count"+FieldSuffix).c_str(), loudnessInfo_Data[i].size());
            Fill_SetOptions(Stream_Audio, 0, (FieldPrefix+"Loudness_Count"+FieldSuffix).c_str(), "N NI"); // Hidden in text output
        }
        ZtringList Ids;
        ZtringList SamplePeakLevel;
        ZtringList TruePeakLevel;
        ZtringList Measurements[16];
        for (std::map<Ztring, loudness_info>::iterator Item=loudnessInfo_Data[i].begin(); Item!=loudnessInfo_Data[i].end(); ++Item)
        {
            Ids.push_back(Item->first);
            SamplePeakLevel.push_back(Item->second.SamplePeakLevel);
            TruePeakLevel.push_back(Item->second.TruePeakLevel);
            for (int8u j=1; j<16; j++)
                Measurements[j].push_back(Item->second.Measurements.Values[j]);
        }
        if (Ids.size()>=1 && Ids.front().empty())
        {
            if (!i)
                DefaultIdPresent=true;
            if (Ids.size()==1)
                Ids.clear();
        }
        Fill(Stream_Audio, 0, (FieldPrefix+"SamplePeakLevel"+FieldSuffix).c_str(), SamplePeakLevel, Ids);
        Fill(Stream_Audio, 0, (FieldPrefix+"TruePeakLevel"+FieldSuffix).c_str(), TruePeakLevel, Ids);
        for (int8u j=1; j<16; j++)
        {
            string Field;
            if (j<=LoudnessMeaning_Size)
                Field=LoudnessMeaning[j-1];
            else
                Field="LoudnessMeaning"+Ztring::ToZtring(j).To_UTF8();
            Fill(Stream_Audio, 0, (FieldPrefix+Field+FieldSuffix).c_str(), Measurements[j], Ids);
        }
    }
 
    if (NoConCh)
        return;
    if (!loudnessInfoSet_Present)
    {
        Fill(Stream_Audio, 0, (FieldPrefix+"ConformanceCheck").c_str(), "Invalid: loudnessInfoSet is missing");
        Fill(Stream_Audio, 0, "ConformanceCheck/Short", "Invalid: loudnessInfoSet missing");
    }
    else if (loudnessInfo_Data[0].empty())
    {
        Fill(Stream_Audio, 0, (FieldPrefix+"ConformanceCheck").c_str(), "Invalid: loudnessInfoSet is empty");
        Fill(Stream_Audio, 0, "ConformanceCheck/Short", "Invalid: loudnessInfoSet empty");
    }
    else if (!DefaultIdPresent)
    {
        Fill(Stream_Audio, 0, (FieldPrefix+"ConformanceCheck").c_str(), "Invalid: Default loudnessInfo is missing");
        Fill(Stream_Audio, 0, "ConformanceCheck/Short", "Invalid: Default loudnessInfo missing");
    }
    else if (loudnessInfo_Data[0].begin()->second.Measurements.Values[1].empty() && loudnessInfo_Data[0].begin()->second.Measurements.Values[2].empty())
    {
        Fill(Stream_Audio, 0, (FieldPrefix+"ConformanceCheck").c_str(), "Invalid: None of program loudness or anchor loudness is present in default loudnessInfo");
        Fill(Stream_Audio, 0, "ConformanceCheck/Short", "Invalid: Default loudnessInfo incomplete");
    }
    if (!Retrieve_Const(Stream_Audio, 0, "ConformanceCheck/Short").empty())
        Fill_SetOptions(Stream_Audio, 0, "ConformanceCheck/Short", "N NT"); // Hidden in text output
}
 
//---------------------------------------------------------------------------
void File_Usac::UsacDecoderConfig(int8u coreSbrFrameLengthIndex)
{
    Element_Begin1("UsacDecoderConfig");
    int32u numElements;
    escapedValue(numElements, 4, 8, 16,                         "numElements minus 1");
 
    for (int32u elemIdx=0; elemIdx<=numElements; elemIdx++)
    {
        Element_Begin1("usacElement");
        int8u usacElementType;
        Get_S1(2, usacElementType,                              "usacElementType");
        switch (usacElementType)
        {
            case 0: //ID_USAC_SCE
                UsacSingleChannelElementConfig(coreSbrFrameLengthIndex);
                break;
            case 1: //ID_USAC_CPE
                UsacChannelPairElementConfig(coreSbrFrameLengthIndex);
                break;
            case 2: //ID_USAC_LFE
                UsacLfeElementConfig(); 
                break;
            case 3: //ID_USAC_EXT
                UsacExtElementConfig();
                break;
        }
        Element_End0();
    }
 
    Element_End0();
}
 
//---------------------------------------------------------------------------
void File_Usac::UsacSingleChannelElementConfig(int8u coreSbrFrameLengthIndex)
{
    Element_Begin1("UsacSingleChannelElementConfig");
 
    UsacCoreConfig();
    if (coreSbrFrameLengthIndex_Mapping[coreSbrFrameLengthIndex].sbrRatioIndex)
        SbrConfig();
 
    Element_End0();
}
 
//---------------------------------------------------------------------------
void File_Usac::UsacChannelPairElementConfig(int8u coreSbrFrameLengthIndex)
{
    Element_Begin1("UsacChannelPairElementConfig");
 
    UsacCoreConfig();
    if (coreSbrFrameLengthIndex_Mapping[coreSbrFrameLengthIndex].sbrRatioIndex)
    {
        int8u stereoConfiglindex;
        SbrConfig();
        Get_S1(2, stereoConfiglindex,                           "stereoConfiglindex");
        if (stereoConfiglindex)
            Mps212Config(stereoConfiglindex);
    }
 
    Element_End0();
}
 
//---------------------------------------------------------------------------
void File_Usac::UsacLfeElementConfig()
{
    // Nothing here
}
 
//---------------------------------------------------------------------------
static const size_t UsacExtElementConfig_usacExtElementType_Size=5;
static const char* UsacExtElementConfig_usacExtElementType[UsacExtElementConfig_usacExtElementType_Size]=
{
    "FILL",
    "MPEGS",
    "SAOC",
    "AUDIOPREROLL",
    "UNI_DRC",
};
void File_Usac::UsacExtElementConfig()
{
    Element_Begin1("UsacExtElementConfig");
 
    int32u usacExtElementType, usacExtElementConfigLength, usacExtElementDefaultLength;
    bool usacExtElementDefaultLengthPresent, usacExtElementPayloadFlag;
    escapedValue(usacExtElementType, 4, 8, 16,                  "usacExtElementType"); Param_Info1C(usacExtElementType<UsacExtElementConfig_usacExtElementType_Size, UsacExtElementConfig_usacExtElementType[usacExtElementType]); Element_Info1C(usacExtElementType<UsacExtElementConfig_usacExtElementType_Size, UsacExtElementConfig_usacExtElementType[usacExtElementType]);
    escapedValue(usacExtElementConfigLength, 4, 8, 16,          "usacExtElementConfigLength");
    Get_SB (usacExtElementDefaultLengthPresent,                 "usacExtElementDefaultLengthPresent");
    if (usacExtElementDefaultLengthPresent)
        escapedValue(usacExtElementDefaultLength, 8, 16, 0,     "usacExtElementDefaultLength");
    else
        usacExtElementDefaultLength=0;
    Get_SB (usacExtElementPayloadFlag,                          "usacExtElementPayloadFlag");
 
    size_t End;
    if (Data_BS_Remain()>usacExtElementConfigLength*8)
        End=Data_BS_Remain()-usacExtElementConfigLength*8;
    else
        End=0; //Problem
    switch (usacExtElementType)
    {
        case 0: //ID_EXT_ELE_FILL
        case 3: //ID_EXT_ELE_AUDIOPREROLL
            break;
        case 4: //ID_EXT_ELE_UNI_DRC
            uniDrcConfig();
            break;
        default:
            if (usacExtElementConfigLength)
                Skip_BS(usacExtElementConfigLength*8,           "(Unknown)");
            break;
    }
    if (Data_BS_Remain()>End)
    {
        size_t Size=Data_BS_Remain()-End;
        int8u Padding=1;
        if (Size<8)
            Peek_S1((int8u)Size, Padding);
        Skip_BS(Data_BS_Remain()-End,                           Padding?"(Unknown)":"Padding");
    }
 
    Element_End0();
}
 
//---------------------------------------------------------------------------
void File_Usac::UsacCoreConfig()
{
    Element_Begin1("UsacCoreConfig");
 
    Skip_SB(                                                    "tw_mdct");
    Skip_SB(                                                    "noiseFilling");
 
    Element_End0();
}
 
//---------------------------------------------------------------------------
void File_Usac::SbrConfig()
{
    Element_Begin1("SbrConfig");
 
    Skip_SB(                                                    "harmonicsSBR");
    Skip_SB(                                                    "bs_interTes");
    Skip_SB(                                                    "bs_pvc");
    SbrDlftHeader();
 
    Element_End0();
}
 
//---------------------------------------------------------------------------
void File_Usac::SbrDlftHeader()
{
    Element_Begin1("SbrDlftHeader");
 
    bool dflt_header_extra1, dflt_header_extra2;
    Skip_S1(4,                                                  "dflt_start_freq");
    Skip_S1(4,                                                  "dflt_stop_freq");
    Get_SB (   dflt_header_extra1,                              "dflt_header_extra1");
    Get_SB (   dflt_header_extra2,                              "dflt_header_extra2");
    if (dflt_header_extra1)
    {
        Skip_S1(2,                                              "dflt_freq_scale");
        Skip_SB(                                                "dflt_alter_scale");
        Skip_S1(2,                                              "dflt_noise_bands");
    }
    if (dflt_header_extra2)
    {
        Skip_S1(2,                                              "dflt_limiter_bands");
        Skip_S1(2,                                              "dflt_limiter_gains");
        Skip_SB(                                                "dflt_interpol_freq");
        Skip_SB(                                                "dflt_smoothing_mode");
    }
 
    Element_End0();
}
 
//---------------------------------------------------------------------------
void File_Usac::Mps212Config(int8u StereoConfigindex)
{
    Element_Begin1("Mps212Config");
 
    int8u bsTempShapeConfig;
    bool bsOttBandsPhasePresent;
    Skip_S1(3,                                                  "bsFreqRes");
    Skip_S1(3,                                                  "bsFixedGainDMX");
    Get_S1 (2, bsTempShapeConfig,                               "bsTempShapeConfig");
    Skip_S1(2,                                                  "bsDecorrConfig");
    Skip_SB(                                                    "bsHighRatelMode");
    Skip_SB(                                                    "bsPhaseCoding");
    Get_SB (   bsOttBandsPhasePresent,                          "bsOttBandsPhasePresent");
    if (bsOttBandsPhasePresent)
    {
        Skip_S1(5,                                              "bsOttBandsPhase");
    }
    if (StereoConfigindex>1)
    {
        Skip_S1(5,                                              "bsResidualBands");
        Skip_SB(                                                "bSPseudor");
    }
    if (bsTempShapeConfig==2)
    {
        Skip_SB(                                                "bSEnvOuantMode");
    }
 
    Element_End0();
}
 
//---------------------------------------------------------------------------
void File_Usac::uniDrcConfig()
{
    downmixInstructions_Data.clear();
    drcInstructionsUniDrc_Data.clear();
    loudnessInfo_Data[0].clear();
    loudnessInfo_Data[1].clear();
 
    Element_Begin1("uniDrcConfig");
 
    int8u downmixInstructionsCount, drcCoefficientsBasicCount, drcInstructionsBasicCount, drcCoefficientsUniDrcCount, drcInstructionsUniDrcCount;
    TEST_SB_SKIP(                                               "sampleRatePresent");
        Skip_S3(18,                                             "bsSampleRate");
    TEST_SB_END();
    Get_S1 (7, downmixInstructionsCount,                        "downmixInstructionsCount");
    TESTELSE_SB_SKIP(                                           "drcDescriptionBasicPresent");
        Get_S1 (3, drcCoefficientsBasicCount,                   "drcCoefficientsBasicCount");
        Get_S1 (4, drcInstructionsBasicCount,                   "drcInstructionsBasicCount");
    TESTELSE_SB_ELSE(                                           "drcDescriptionBasicPresent");
        drcCoefficientsBasicCount=0;
        drcInstructionsBasicCount=0;
    TESTELSE_SB_END();
    Get_S1 (3, drcCoefficientsUniDrcCount,                      "drcCoefficientsUniDrcCount");
    Get_S1 (6, drcInstructionsUniDrcCount,                      "drcInstructionsUniDrcCount");
    channelLayout();
    for (int8u i=0; i<downmixInstructionsCount; i++)
        downmixInstructions();
    for (int8u i=0; i<drcCoefficientsBasicCount; i++)
        drcCoefficientsBasic();
    for (int8u i=0; i<drcInstructionsBasicCount; i++)
        drcInstructionsBasic();
    for (int8u i=0; i<drcCoefficientsUniDrcCount; i++)
        drcCoefficientsUniDrc();
    for (int8u i=0; i<drcInstructionsUniDrcCount; i++)
        drcInstructionsUniDrc();
    bool uniDrcConfigExtPresent;
    Get_SB (   uniDrcConfigExtPresent,                          "uniDrcConfigExtPresent");
    if (uniDrcConfigExtPresent)
        uniDrcConfigExtension();
 
    Element_End0();
}
 
//---------------------------------------------------------------------------
void File_Usac::uniDrcConfigExtension()
{
    Element_Begin1("uniDrcConfigExtension");
 
    for (;;)
    {
        int32u bitSize;
        int8u uniDrcConfigExtType, extSizeBits;
        Get_S1 (4, uniDrcConfigExtType,                         "uniDrcConfigExtType");
        if (!uniDrcConfigExtType) // UNIDRCCONFEXT_TERM
            break;
        Get_S1 (4, extSizeBits,                                 "bitSizeLen");
        extSizeBits+=4;
        Get_S4 (extSizeBits, bitSize,                           "bitSize");
        bitSize++;
 
        switch (uniDrcConfigExtType)
        {
            /*
            case 1 : // UNIDRCCONFEXT_PARAM_DRC
                {
                size_t End;
                if (Data_BS_Remain()>bitSize)
                    End=Data_BS_Remain()-bitSize;
                else
                    End=0; //Problem
                drcCoefficientsParametricDrc();
                int8u parametricDrcInstructionsCount;
                Get_S1 (4, parametricDrcInstructionsCount,      "parametricDrcInstructionsCount");
                for (int8u i=0; i<parametricDrcInstructionsCount; i++)
                    parametricDrcInstructions();
                if (Data_BS_Remain()>End)
                    Skip_BS(Data_BS_Remain()-End,               "(Unknown)");
                }
                break;
            */
            case 2 : // UNIDRCCONFEXT_V1
                {
                size_t End;
                if (Data_BS_Remain()>bitSize)
                    End=Data_BS_Remain()-bitSize;
                else
                    End=0; //Problem
                TEST_SB_SKIP(                                   "downmixInstructionsV1Present");
                    int8u downmixInstructionsV1Count;
                    Get_S1 (7, downmixInstructionsV1Count,      "downmixInstructionsV1Count");
                    for (int8u i=0; i<downmixInstructionsV1Count; i++)
                        downmixInstructions(true);
                TEST_SB_END();
                TEST_SB_SKIP(                                   "drcCoeffsAndInstructionsUniDrcV1Present");
                    int8u drcCoefficientsUniDrcV1Count;
                    Get_S1 (3, drcCoefficientsUniDrcV1Count,    "drcCoefficientsUniDrcV1Count");
                    for (int8u i=0; i<drcCoefficientsUniDrcV1Count; i++)
                        drcCoefficientsUniDrc(true);
                    int8u drcInstructionsUniDrcV1Count;
                    Get_S1 (6, drcInstructionsUniDrcV1Count,    "drcInstructionsUniDrcV1Count");
                    for (int8u i=0; i<drcInstructionsUniDrcV1Count; i++)
                        drcInstructionsUniDrc(true);
                TEST_SB_END();
                bool MustSkip=false;
                TEST_SB_SKIP(                                   "loudEqInstructionsPresent");
                    int8u loudEqInstructionsCount;
                    Get_S1 (4, loudEqInstructionsCount,         "loudEqInstructionsCount");
                    for (int8u i=0; i<loudEqInstructionsCount; i++)
                        MustSkip=true; // Not yet implemented
                    //    loudEqInstructions();
                TEST_SB_END();
                if (!MustSkip)
                TEST_SB_SKIP(                                   "eqPresent");
                    // Not yet implemented
                    //int8u eqInstructionsCount;
                    //eqCoefficients();
                    //Get_S1 (4, eqInstructionsCount,             "eqInstructionsCount");
                    //for (int8u i=0; i<eqInstructionsCount; i++)
                    //    eqInstructions();
                TEST_SB_END();
                if (Data_BS_Remain()>End)
                    Skip_BS(Data_BS_Remain()-End,               "(Unknown)");
                }
                break;
            default:
                if (bitSize)
                    Skip_BS(bitSize,                            "(Unknown)");
        }
    }
 
    Element_End0();
}
 
//---------------------------------------------------------------------------
void File_Usac::downmixInstructions(bool V1)
{
    Element_Begin1("downmixInstructionsV1");
 
    bool layoutSignalingPresent;
    int8u downmixId, targetChannelCount;
    Get_S1 (7, downmixId,                                       "downmixId");
    Get_S1 (7, targetChannelCount,                              "targetChannelCount");
    Skip_S1(8,                                                  "targetLayout");
    Get_SB (   layoutSignalingPresent,                          "layoutSignalingPresent");
    if (layoutSignalingPresent)
    {
        if (V1)
            Skip_S1(4,                                          "bsDownmixOffset");
        for (int8u i=0; i<targetChannelCount; i++)
            for (int8u j=0; j<baseChannelCount; j++)
                Skip_S1(V1?5:4,                                 V1?"bsDownmixCoefficientV1":"bsDownmixCoefficient");
    }
    downmixInstructions_Data[downmixId].targetChannelCount=targetChannelCount;
    Element_End0();
}
 
//---------------------------------------------------------------------------
void File_Usac::drcCoefficientsBasic()
{
    Element_Begin1("drcCoefficientsBasic");
 
    Skip_S1(4,                                                  "drcLocation");
    Skip_S1(7,                                                  "drcCharacteristic");
 
    Element_End0();
}
 
//---------------------------------------------------------------------------
void File_Usac::drcCoefficientsUniDrc(bool V1)
{
    Element_Begin1(V1?"drcCoefficientsUniDrcV1":"drcCoefficientsUniDrc");
 
    bool drcFrameSizePresent;
    Skip_S1(4,                                                  "drcLocation");
    Get_SB (   drcFrameSizePresent,                             "drcFrameSizePresent");
    if (drcFrameSizePresent)
        Skip_S2(15,                                             "bsDrcFrameSize");
    if (V1)
    {
        bool drcCharacteristicLeftPresent;
        Get_SB (   drcCharacteristicLeftPresent,                "drcCharacteristicLeftPresent");
        if (drcCharacteristicLeftPresent)
        {
            int8u characteristicLeftCount;
            Get_S1 (4, characteristicLeftCount,                 "characteristicLeftCount");
            for (int8u k=0; k<characteristicLeftCount; k++)
            {
                bool characteristicFormat;
                Get_SB (   characteristicFormat,                "characteristicFormat");
                if (!characteristicFormat)
                {
                    Skip_S1(6,                                  "bsGainLeft");
                    Skip_S1(4,                                  "bsIoRatioLeft");
                    Skip_S1(4,                                  "bsExpLeft");
                    Skip_SB(                                    "flipSignLeft");
                }
                else
                {
                    int8u bsCharNodeCount;
                    Get_S1 (2, bsCharNodeCount,                 "bsCharNodeCount");
                    for (int8u n=0; n<=bsCharNodeCount; n++)
                    {
                        Skip_S1(5,                              "bsNodeLevelDelta");
                        Skip_S1(8,                              "bsNodeGain");
                    }
                }
            }
        }
        bool drcCharacteristicRightPresent;
        Get_SB (   drcCharacteristicRightPresent,               "drcCharacteristicRightPresent");
        if (drcCharacteristicLeftPresent)
        {
            int8u characteristicRightCount;
            Get_S1 (4, characteristicRightCount,                "characteristicRightCount");
            for (int8u k=0; k<characteristicRightCount; k++)
            {
                bool characteristicFormat;
                Get_SB (   characteristicFormat,                "characteristicFormat");
                if (!characteristicFormat)
                {
                    Skip_S1(6,                                  "bsGainLeft");
                    Skip_S1(4,                                  "bsIoRatioLeft");
                    Skip_S1(4,                                  "bsExpLeft");
                    Skip_SB(                                    "flipSignLeft");
                }
                else
                {
                    int8u bsCharNodeCount;
                    Get_S1 (2, bsCharNodeCount,                 "bsCharNodeCount");
                    for (int8u n=0; n<=bsCharNodeCount; n++)
                    {
                        Skip_S1(5,                              "bsNodeLevelDelta");
                        Skip_S1(8,                              "bsNodeGain");
                    }
                }
            }
        }
        bool shapeFiltersPresent;
        Get_SB (   shapeFiltersPresent,                         "shapeFiltersPresent");
        if (shapeFiltersPresent)
        {
            int8u shapeFilterCount;
            Get_S1 (4, shapeFilterCount,                        "shapeFilterCount");
            for (int8u k=0; k<shapeFilterCount; k++)
            {
                TEST_SB_SKIP(                                   "lfCutFilterPresent");
                    Skip_S1(3,                                  "lfCornerFreqIndex");
                    Skip_S1(2,                                  "lfFilterStrengthIndex");
                TEST_SB_END();
                TEST_SB_SKIP(                                   "lfBoostFilterPresent");
                    Skip_S1(3,                                  "lfCornerFreqIndex");
                    Skip_S1(2,                                  "lfFilterStrengthIndex");
                TEST_SB_END();
                TEST_SB_SKIP(                                   "hfCutFilterPresent");
                    Skip_S1(3,                                  "lfCornerFreqIndex");
                    Skip_S1(2,                                  "lfFilterStrengthIndex");
                TEST_SB_END();
                TEST_SB_SKIP(                                   "hfBoostFilterPresent");
                    Skip_S1(3,                                  "lfCornerFreqIndex");
                    Skip_S1(2,                                  "lfFilterStrengthIndex");
                TEST_SB_END();
            }
        }
        Skip_S1(6,                                              "gainSequenceCount");
    }
    int8u gainSetCount;
    Get_S1 (6, gainSetCount,                                    "gainSetCount");
    gainSets.clear();
    for (int8u i=0; i<gainSetCount; i++)
    {
        Element_Begin1("gainSet");
        gain_set gainSet;
        int8u gainCodingProfile;
        Get_S1 (2, gainCodingProfile,                           "gainCodingProfile");
        Skip_SB(                                                "gainInterpolationType");
        Skip_SB(                                                "fullFrame");
        Skip_SB(                                                "timeAlignment");
        TEST_SB_SKIP(                                           "timeDeltaMinPresent");
            Skip_S2(11,                                         "bsTimeDeltaMin");
        TEST_SB_END();
        if (gainCodingProfile != 3)
        {
            bool drcBandType;
            Get_S1 (4, gainSet.bandCount,                       "bandCount");
            if (gainSet.bandCount>1)
                Get_SB (drcBandType,                            "drcBandType");
            for (int8u i=0; i<gainSet.bandCount; i++)
            {
                Element_Begin1("bandCount");
                if (V1)
                {
                    TEST_SB_SKIP(                               "indexPresent");
                        Skip_S1(6,                              "bsIndex");
                    TEST_SB_END();
                }
                if (!V1)
                {
                    Skip_S1(7,                                  "drcCharacteristic");
                }
                else //V1
                {
                    TEST_SB_SKIP(                               "drcCharacteristicPresent");
                        bool drcCharacteristicFormatIsCICP;
                        Get_SB (drcCharacteristicFormatIsCICP,  "drcCharacteristicFormatIsCICP");
                        if (drcCharacteristicFormatIsCICP)
                        {
                            Skip_S1(7,                          "drcCharacteristic");
                        }
                        else
                        {
                            Skip_S1(4,                          "drcCharacteristicLeftIndex");
                            Skip_S1(4,                          "drcCharacteristicRightIndex");
                        }
                    TEST_SB_END();
                }
                Element_End0();
            }
            for (int8u i=1; i <gainSet.bandCount; i++)
            {
                if (drcBandType)
                    Skip_S1( 4,                                 "crossoverFreqIndex");
                else
                    Skip_S2(10,                                 "startSubBandIndex");
            }
        }
        else
            gainSet.bandCount=1;
        gainSets.push_back(gainSet);
        Element_End0();
    }
 
    Element_End0();
}
 
//---------------------------------------------------------------------------
void File_Usac::drcInstructionsBasic()
{
    Element_Begin1("drcInstructionsBasic");
 
    int16u drcSetEffect;
    Skip_S1(6,                                                  "drcSetId");
    Skip_S1(4,                                                  "drcLocation");
    Skip_S1(7,                                                  "downmixId");
    TEST_SB_SKIP(                                               "additionalDownmixIdPresent");
        int8u additionalDownmixIdCount;
        Get_S1 (3, additionalDownmixIdCount,                    "additionalDownmixIdCount");
        for (int8u i=1; i <additionalDownmixIdCount; i++)
            Skip_S1(7,                                          "additionalDownmixId");
    TEST_SB_END();
    Get_S2 (16, drcSetEffect,                                   "drcSetEffect");
    if ((drcSetEffect & (3<<10)) == 0)
    {
        TEST_SB_SKIP(                                           "limiterPeakTargetPresent");
            Skip_S1(8,                                          "bsLimiterPeakTarget");
        TEST_SB_END();
    }
    TEST_SB_SKIP(                                               "drcSetTargetLoudnessPresent");
        Skip_S1(6,                                              "bsDrcSetTargetLoudnessValueUpper");
        TEST_SB_SKIP(                                           "drcSetTargetLoudnessValueLowerPresent");
            Skip_S1(6,                                          "bsDrcSetTargetLoudnessValueLower");
        TEST_SB_END();
    TEST_SB_END();
 
    Element_End0();
}
 
static const size_t drcSetEffect_List_Size=12;
static const char* drcSetEffect_List[drcSetEffect_List_Size] =
{
    "Night",
    "Noisy",
    "Limited",
    "LowLevel",
    "Dialog",
    "General",
    "Expand",
    "Artistic",
    "Clipping",
    "Fade",
    "DuckOther",
    "DuckSelf",
};
 
//---------------------------------------------------------------------------
bool File_Usac::drcInstructionsUniDrc(bool V1, bool NoV0)
{
    Element_Begin1(V1?"drcInstructionsUniDrcV1":"drcInstructionsUniDrc");
 
    int8u channelCount=baseChannelCount;
    vector<int8s> gainSetIndex;
    int16u drcSetEffect;
    int8u drcSetId, downmixId;
    bool downmixIdPresent;
    Get_S1 (6, drcSetId,                                        "drcSetId");
    if (V1)
        Skip_S1(4,                                              "drcSetComplexityLevel");
    Skip_S1(4,                                                  "drcLocation");
    if (V1)
        Get_SB (downmixIdPresent,                               "downmixIdPresent");
    else
        downmixIdPresent=true;
    if (downmixIdPresent)
    {
        bool drcApplyToDownmix;
        Get_S1(7, downmixId,                                    "downmixId");
        if (V1)
            Get_SB (   drcApplyToDownmix,                       "drcApplyToDownmix");
        else
            drcApplyToDownmix=downmixId?true:false;
        int8u additionalDownmixIdCount;
        TESTELSE_SB_SKIP(                                       "additionalDownmixIdPresent");
            Get_S1 (3, additionalDownmixIdCount,                "additionalDownmixIdCount");
            for (int8u i=0; i<additionalDownmixIdCount; i++)
                Skip_S1(7,                                      "additionalDownmixId");
        TESTELSE_SB_ELSE(                                       "additionalDownmixIdPresent");
            additionalDownmixIdCount=0;
        TESTELSE_SB_END();
        if ((!V1 || drcApplyToDownmix) && downmixId && downmixId!=0x7F && !additionalDownmixIdCount)
        {
            std::map<int8u, downmix_instruction>::iterator downmixInstruction_Data=downmixInstructions_Data.find(downmixId);
            if (downmixInstruction_Data!=downmixInstructions_Data.end())
                channelCount=downmixInstruction_Data->second.targetChannelCount;
            else
                channelCount=1;
        }
        else if ((!V1 || drcApplyToDownmix) && (downmixId==0x7F || additionalDownmixIdCount))
            channelCount=1;
    }
    else
        downmixId=0; // 0 is default
    Get_S2 (16, drcSetEffect,                                   "drcSetEffect");
    bool IsNOK=false;
    if (drcSetEffect>>drcSetEffect_List_Size)
    {
        Param_Info1("(Unknown)");
        Fill(Stream_Audio, 0, "TEMP_drcSetEffect", drcSetEffect, 16); //TEMP
        IsNOK=true;
    }
    if ((drcSetEffect & (3<<10)) == 0)
    {
        TEST_SB_SKIP(                                           "limiterPeakTargetPresent");
            Skip_S1(8,                                          "bsLimiterPeakTarget");
        TEST_SB_END();
    }
    else
        channelCount=baseChannelCount; // TEMP
    TEST_SB_SKIP(                                               "drcSetTargetLoudnessPresent");
        Skip_S1(6,                                              "bsDrcSetTargetLoudnessValueUpper");
        TEST_SB_SKIP(                                           "drcSetTargetLoudnessValueLowerPresent");
            Skip_S1(6,                                          "bsDrcSetTargetLoudnessValueLower");
        TEST_SB_END();
    TEST_SB_END();
    TESTELSE_SB_SKIP(                                           "dependsOnDrcSetPresent");
        Skip_S1(6,                                              "dependsOnDrcSet");
    TESTELSE_SB_ELSE(                                           "dependsOnDrcSetPresent");
        Skip_SB(                                                "noIndependentUse");
    TESTELSE_SB_END();
    if (V1)
        Skip_SB(                                                "requiresEq");
    for (int8u c=0; c<channelCount; c++)
    {
        Element_Begin1("channel");
        int8u bsGainSetIndex;
        Get_S1 (6, bsGainSetIndex,                              "bsGainSetIndex");
        gainSetIndex.push_back(bsGainSetIndex);
        if ((drcSetEffect & (3<<10)) != 0)
        {
            TEST_SB_SKIP(                                       "duckingScalingPresent");
                Skip_S1(4,                                      "bsDuckingScaling");
            TEST_SB_END();
        }
        TEST_SB_SKIP(                                           "repeatGainSetIndex");
            int8u bsRepeatGainSetIndexCount;
            Get_S1 (5, bsRepeatGainSetIndexCount,               "bsRepeatGainSetIndexCount");
            bsRepeatGainSetIndexCount++;
            gainSetIndex.resize(gainSetIndex.size()+bsRepeatGainSetIndexCount, bsGainSetIndex);
            c+=bsRepeatGainSetIndexCount;
        TEST_SB_END();
        Element_End0();
    }
 
    set<int8s> DrcChannelGroups=set<int8s>(gainSetIndex.begin(), gainSetIndex.end());
 
    for (set<int8s>::iterator DrcChannelGroup=DrcChannelGroups.begin(); DrcChannelGroup!=DrcChannelGroups.end(); ++DrcChannelGroup)
    {
        if (!*DrcChannelGroup || (drcSetEffect & (3<<10)))
            continue; // 0 means not present
        Element_Begin1("DrcChannel");
        int8s gainSetIndex=*DrcChannelGroup-1;
        int8u bandCount=V1?(gainSetIndex<gainSets.size()?gainSets[gainSetIndex].bandCount:0):1;
        for (int8u k=0; k<bandCount; k++)
        {
            Element_Begin1("band");
            if (V1)
            {
            TEST_SB_SKIP(                                       "targetCharacteristicLeftPresent");
                Skip_S1(4,                                      "targetCharacteristicLeftIndex");
            TEST_SB_END();
            TEST_SB_SKIP(                                       "targetCharacteristicRightPresent");
                Skip_S1(4,                                      "targetCharacteristicRightIndex");
            TEST_SB_END();
            }
            TEST_SB_SKIP(                                       "gainScalingPresent");
                Skip_S1(4,                                      "bsAttenuationScaling");
                Skip_S1(4,                                      "bsAmplificationScaling");
            TEST_SB_END();
            TEST_SB_SKIP(                                       "gainOffsetPresent");
                Skip_SB(                                        "bsGainSign");
                Skip_S1(5,                                      "bsGainOffset");
            TEST_SB_END();
            Element_End0();
        }
        if (V1 && bandCount==1)
        {
            TEST_SB_SKIP(                                       "shapeFilterPresent");
                Skip_S1(4,                                      "shapeFilterIndex");
            TEST_SB_END();
        }
        Element_End0();
    }
 
    Element_End0();
 
    if (V1 || NoV0) //We want to display only V1 information
    {
        string Value;
        for (int8u i=0; i<16; i++)
            if (drcSetEffect&(1<<i))
            {
                if (!Value.empty())
                    Value+=" & ";
                if (i<drcSetEffect_List_Size)
                    Value+=drcSetEffect_List[i];
                else
                {
                    if (i>=10)
                        Value+='1';
                    Value+='0'+(i%10);
                }
            }
 
        int16u Id=drcSetId<<8|downmixId;
        drcInstructionsUniDrc_Data[Id].drcSetEffectTotal=Value;
    }
 
    return false;
}
 
//---------------------------------------------------------------------------
void File_Usac::channelLayout()
{
    Element_Begin1("channelLayout");
 
    bool layoutSignalingPresent;
    Get_S1 (7, baseChannelCount,                                "baseChannelCount");
    Get_SB (   layoutSignalingPresent,                          "layoutSignalingPresent");
    if (layoutSignalingPresent)
    {
        int8u definedLayout;
        Get_S1 (8, definedLayout,                               "definedLayout");
        if (!definedLayout)
        {
            for (int8u i=0; i<baseChannelCount; i++)
            {
                Info_S1(7, speakerPosition,                     "speakerPosition"); Param_Info1(Aac_OutputChannelPosition_GetString(speakerPosition));
            }
        }
    }
 
    Element_End0();
}
 
//---------------------------------------------------------------------------
static const size_t UsacConfigExtension_usacConfigExtType_Size=8;
static const char* UsacConfigExtension_usacConfigExtType[UsacConfigExtension_usacConfigExtType_Size]=
{
    "FILL",
    NULL,
    "LOUDNESS_INFO",
    NULL,
    NULL,
    NULL,
    NULL,
    "STREAM_ID",
};
void File_Usac::UsacConfigExtension()
{
    Element_Begin1("UsacConfigExtension");
 
    int32u numConfigExtensions;
    escapedValue(numConfigExtensions, 2, 4, 8,                  "numConfigExtensions minus 1");
 
    for (int32u confExtIdx=0; confExtIdx<=numConfigExtensions; confExtIdx++) 
    {
        Element_Begin1("usacConfigExtension");
        int32u usacConfigExtType, usacConfigExtLength;
        escapedValue(usacConfigExtType, 4, 8, 16,               "usacConfigExtType"); Param_Info1C(usacConfigExtType<UsacConfigExtension_usacConfigExtType_Size && UsacConfigExtension_usacConfigExtType[usacConfigExtType], UsacConfigExtension_usacConfigExtType[usacConfigExtType]);
        escapedValue(usacConfigExtLength, 4, 8, 16,             "usacExtElementConfigLength");
        size_t End;
        if (Data_BS_Remain()>usacConfigExtLength*8)
            End=Data_BS_Remain()-usacConfigExtLength*8;
        else
            End=0; //Problem
 
        switch (usacConfigExtType)
        {
            case 0: //ID_CONFIG_EXT_FILL
                if (usacConfigExtLength)
                    Skip_BS(usacConfigExtLength *8,             "10100101"); //TODO: check if value is the right one
                break;
            case 2: //ID_CONFIG_EXT_LOUDNESS_INFO
                loudnessInfoSet();
                break;
            case 7: //ID_CONFIG_EXT_STREAM_ID
                streamId();
                break;
            default:
                if (usacConfigExtLength)
                    Skip_BS(usacConfigExtLength *8,             "(Unknown)");
                break;
        }
 
        if (Data_BS_Remain()>End)
        {
            size_t Size=Data_BS_Remain()-End;
            int8u Padding=1;
            if (Size<8)
                Peek_S1((int8u)Size, Padding);
            Skip_BS(Data_BS_Remain()-End,                           Padding?"(Unknown)":"Padding");
        }
        Element_End0();
    }
 
    Element_End0();
}
 
//---------------------------------------------------------------------------
void File_Usac::loudnessInfoSet(bool V1)
{
    Element_Begin1(V1?"loudnessInfoSetV1":"loudnessInfoSet");
    loudnessInfoSet_Present=true;
 
    int8u loudnessInfoAlbumCount, loudnessInfoCount;
    bool loudnessInfoSetExtPresent;
    Get_S1 (6, loudnessInfoAlbumCount,                          "loudnessInfoAlbumCount");
    Get_S1 (6, loudnessInfoCount,                               "loudnessInfoCount");
    for (int8u i=0; i<loudnessInfoAlbumCount; i++)
        loudnessInfo(true, V1);
    for (int8u i=0; i<loudnessInfoCount; i++)
        loudnessInfo(false, V1);
    if (!V1)
    {
        Get_SB (loudnessInfoSetExtPresent,                      "loudnessInfoSetExtPresent");
        if (loudnessInfoSetExtPresent)
            loudnessInfoSetExtension();
    }
 
    Element_End0();
}
 
//---------------------------------------------------------------------------
static const size_t methodDefinition_Format_Size=10;
static const int8u methodDefinition_Format[methodDefinition_Format_Size]=
{
    8, 8, 8, 8, 8, 8, 8, 5, 2, 8,
};
bool File_Usac::loudnessInfo(bool FromAlbum, bool V1)
{
    Element_Begin1(V1?"loudnessInfoV1":"loudnessInfo");
 
    loudness_info::measurements Measurements;
    int16u bsSamplePeakLevel, bsTruePeakLevel;
    int8u measurementCount;
    bool samplePeakLevelPresent, truePeakLevelPresent;
    int8u drcSetId, eqSetId, downmixId;
    Get_S1 (6, drcSetId,                                        "drcSetId");
    if (V1)
        Get_S1 (6, eqSetId,                                     "eqSetId");
    Get_S1 (7, downmixId,                                       "downmixId");
    Get_SB (samplePeakLevelPresent,                             "samplePeakLevelPresent");
    if (samplePeakLevelPresent)
        Get_S2(12, bsSamplePeakLevel,                           "bsSamplePeakLevel");
    Get_SB (truePeakLevelPresent,                               "truePeakLevelPresent");
    if (truePeakLevelPresent)
    {
        Get_S2 (12, bsTruePeakLevel,                            "bsTruePeakLevel");
        Skip_S1( 4,                                             "measurementSystem");
        Skip_S1( 2,                                             "reliability");
    }
    Get_S1 (4, measurementCount,                                "measurementCount");
    bool IsNOK=false;
    for (int8u i=0; i<measurementCount; i++)
    {
        int8u methodDefinition, methodValue;
        Get_S1 (4, methodDefinition,                            "methodDefinition");
        int8u Size;
        if (methodDefinition>=methodDefinition_Format_Size)
        {
            Param_Info1("(Unsupported)");
            Measurements.Values[methodDefinition].From_UTF8("(Unsupported)");
            IsNOK=true;
            break;
        }
        Get_S1 (methodDefinition_Format[methodDefinition], methodValue, "methodValue");
        Skip_S1(4,                                              "measurementSystem");
        Skip_S1(2,                                              "reliability");
 
        Ztring measurement;
        switch (methodDefinition)
        {
            case 0:
                    break;
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
                    measurement=Ztring::ToZtring(-57.75+((double)methodValue)/4, 2)+__T(" LKFS");
                    break;
            case 6: 
                    {
                    int8u Value;
                    if (methodValue==0)
                        Value=0;
                    else if (methodValue<=128)
                        Value=methodValue/4;
                    else if (methodValue<=204)
                        Value=methodValue/2-32;
                    else
                        Value=methodValue-134; 
                    measurement=Ztring::ToZtring(Value)+__T(" LU");
                    }
                    break;
            case 7: 
                    measurement=Ztring::ToZtring(80+methodValue)+__T(" dB");
                    break;
            case 8:
                    switch(methodValue)
                    {
                        case 0: break;
                        case 1: measurement=__T("Large room"); break;
                        case 2: measurement=__T("Small room"); break;
                        default: measurement=Ztring::ToZtring(methodValue); break;
                    }
                    break;
            case 9:
                    measurement=Ztring::ToZtring(-116+((double)methodValue)/2, 1)+__T(" LKFS");
                    break;
            default:
                    measurement.From_Number(methodValue);
        }
 
        if (methodDefinition)
        {
            Ztring& Content=Measurements.Values[methodDefinition];
            if (!Content.empty())
                Content+=__T(" & ");
            Content+=measurement;
        }
    }
 
    Ztring Id=Ztring::ToZtring(drcSetId);
    Id+=__T('-')+Ztring::ToZtring(downmixId);
    //if (V1)
    //    Id+=__T('-')+Ztring::ToZtring(eqSetId); // No eqSetId for the moment
    if (Id==__T("0-0") || Id==__T("0-0-0"))
        Id.clear();
    loudnessInfo_Data[FromAlbum][Id].SamplePeakLevel=((samplePeakLevelPresent && bsSamplePeakLevel)?(Ztring::ToZtring(20-((double)bsSamplePeakLevel)/32)+__T(" dBFS")):Ztring());
    loudnessInfo_Data[FromAlbum][Id].TruePeakLevel=((truePeakLevelPresent && bsTruePeakLevel)?(Ztring::ToZtring(20-((double)bsTruePeakLevel)/32)+__T(" dBTP")):Ztring());
    loudnessInfo_Data[FromAlbum][Id].Measurements=Measurements;
    Element_End0();
 
    return IsNOK;
}
 
//---------------------------------------------------------------------------
void File_Usac::loudnessInfoSetExtension()
{
    Element_Begin1("loudnessInfoSetExtension");
 
    for (;;)
    {
        int32u bitSize;
        int8u loudnessInfoSetExtType, extSizeBits;
        Get_S1 (4, loudnessInfoSetExtType,                      "loudnessInfoSetExtType");
        if (!loudnessInfoSetExtType) // UNIDRCLOUDEXT_TERM
            break;
        Get_S1 (4, extSizeBits,                                 "bitSizeLen");
        extSizeBits+=4;
        Get_S4 (extSizeBits, bitSize,                           "bitSize");
        bitSize++;
 
        switch (loudnessInfoSetExtType)
        {
            case 1 : // UNIDRCLOUDEXT_EQ
                loudnessInfoSet(true);
                break;
            default:
                if (bitSize)
                    Skip_BS(bitSize,                            "(Unknown)");
        }
    }
 
    Element_End0();
}
 
//---------------------------------------------------------------------------
void File_Usac::streamId()
{
    Element_Begin1("streamId");
 
    int16u streamIdentifier;
    Get_S2 (16, streamIdentifier,                               "streamIdentifier");
 
    Fill(Stream_Audio, 0,  "streamIdentifier", streamIdentifier);
    Element_End0();
}
 
//---------------------------------------------------------------------------
void File_Usac::escapedValue(int32u &Value, int8u nBits1, int8u nBits2, int8u nBits3, const char* Name)
{
    Element_Begin1(Name);
    Get_S4(nBits1, Value,                                       "nBits1");
    if (Value==((1<<nBits1)-1))
    {
        int32u ValueAdd;
        Get_S4(nBits2, ValueAdd,                                "nBits2");
        Value+=ValueAdd;
        if (nBits3 && ValueAdd==((1<<nBits2)-1))
        {
            Get_S4(nBits3, ValueAdd,                            "nBits3");
            Value+=ValueAdd;
        }
    }
    Element_Info1(Value);
    Element_End0();
}
 
//***************************************************************************
// C++
//***************************************************************************
 
} //NameSpace
 
#endif //defined(MEDIAINFO_AAC_YES) || defined(MEDIAINFO_MPEGH3DA_YES)

V730 Not all members of a class are initialized inside the constructor. Consider inspecting: baseChannelCount, loudnessInfoSet_Present.

V547 Expression 'i >= 10' is always true.

V525 The code contains the collection of similar blocks. Check items '6', '4', '4' in lines 652, 653, 654.

V525 The code contains the collection of similar blocks. Check items '6', '4', '4' in lines 681, 682, 683.

V601 The 'true' value is implicitly cast to the integer type. Inspect the fifth argument.

V820 The 'Value' variable is not used after copying. Copying can be replaced with move/swap for optimization.

V807 Decreased performance. Consider creating a reference to avoid using the 'Item->second' expression repeatedly.