/*  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_AMR_YES)
//---------------------------------------------------------------------------
 
//---------------------------------------------------------------------------
#include "MediaInfo/Audio/File_Amr.h"
#include "ZenLib/Utils.h"
using namespace ZenLib;
//---------------------------------------------------------------------------
 
namespace MediaInfoLib
{
 
//***************************************************************************
// Constants
//***************************************************************************
 
int16u Amr_BitRate[]=
{
     5200,
     5600,
     6400,
     7200,
     8000,
     8400,
    10800,
    12800,
     3600,
     3600,
     3600,
     3600,
        0,
        0,
        0,
      400,
};
 
//***************************************************************************
// Format
//***************************************************************************
 
//---------------------------------------------------------------------------
File_Amr::File_Amr()
:File__Analyze()
{
    //Temp
    Header_Size=(int64u)-1;
    Frame_Number=0;
    FrameType=(int8u)-1;
}
 
//***************************************************************************
// Buffer - File header
//***************************************************************************
 
//---------------------------------------------------------------------------
bool File_Amr::FileHeader_Begin()
{
    if (!Codec.empty()) //Test of header only if it is a file --> The codec field is empty
        return true;
 
    //Testing
    if (Buffer_Size<5)
        return false; //Must wait for more data
    if (CC5(Buffer)!=0x2321414D52LL) //"#!AMR"
    {
        Reject("AMR");
        return false;
    }
 
    //All should be OK...
    return true;
}
 
//***************************************************************************
// Streams management
//***************************************************************************
 
//---------------------------------------------------------------------------
void File_Amr::Streams_Fill()
{
    Stream_Prepare(Stream_Audio);
    Fill(Stream_Audio, 0, Audio_Format, "AMR");
    Fill(Stream_Audio, 0, Audio_Codec, "AMR");
    if (!Codec.empty())
    {
        if (MediaInfoLib::Config.CodecID_Get(Stream_Audio, InfoCodecID_Format_Mpeg4, Codec, InfoCodecID_Profile)==__T("Narrow band"))
            IsWB=false;
        if (MediaInfoLib::Config.CodecID_Get(Stream_Audio, InfoCodecID_Format_Mpeg4, Codec, InfoCodecID_Profile)==__T("Wide band"))
            IsWB=true;
        Channels=1;
    }
    if (Channels==0)
        return; //No more info
 
    if (Header_Size!=(int64u)-1)
        Fill(Stream_General, 0, General_StreamSize, Header_Size);
    Fill(Stream_Audio, 0, Audio_Channel_s_, Channels);
    if (IsWB)
    {
        Fill(Stream_Audio, 0, Audio_Format_Profile, "Wide band");
        Fill(Stream_Audio, 0, Audio_Codec, "sawb", Unlimited, true, true);
        if (Codec.empty()) //If there is a container, trusting the container sampling rate
            Fill(Stream_Audio, 0, Audio_SamplingRate, 16000);
        Fill(Stream_Audio, 0, Audio_BitDepth, 14);
        //Fill(Stream_Audio, 0, Audio_InternetMediaType, "audio/AMR-WB", Unlimited, true, true);
    }
    else
    {
        Fill(Stream_Audio, 0, Audio_Format_Profile, "Narrow band");
        Fill(Stream_Audio, 0, Audio_Codec, "samr", Unlimited, true, true);
        if (Codec.empty()) //If there is a container, trusting the container sampling rate
            Fill(Stream_Audio, 0, Audio_SamplingRate, 8000);
        Fill(Stream_Audio, 0, Audio_BitDepth, 13);
        if (FrameType!=(int8u)-1 && Amr_BitRate[FrameType] && FrameTypes.size()==1)
        {
            Fill(Stream_Audio, 0, Audio_BitRate_Mode, "CBR");
            Fill(Stream_Audio, 0, Audio_BitRate, Amr_BitRate[FrameType]);
            Fill(Stream_General, 0, General_OverallBitRate, Amr_BitRate[FrameType]);
            if (File_Size!=(int64u)-1)
            {
                Fill(Stream_Audio, 0, Audio_Duration, ((float32)(File_Size-Header_Size))*8*1000/Amr_BitRate[FrameType]);
            }
        }
    }
}
 
//---------------------------------------------------------------------------
void File_Amr::Streams_Finish()
{
}
 
//***************************************************************************
// Buffer - Global
//***************************************************************************
 
//---------------------------------------------------------------------------
void File_Amr::FileHeader_Parse()
{
    //From a container
    if (!Codec.empty())
    {
        Accept("AMR");
        Finish("AMR");
        return;
    }
 
    //Parsing
    int64u Signature;
    Skip_C5(                                                    "Signature (Common)");
    Peek_B8(Signature);
    if ((Signature&0xFF00000000000000LL)==0x0A00000000000000LL) //\n
    {
        IsWB=false;
        Channels=1;
    }
    else if ((Signature&0xFFFFFFFFFFFFFF00LL)==0x5F4D43312E300A00LL) //_MC1.0\n
    {
        IsWB=false;
        Channels=2; //Or more, see later
    }
    else if ((Signature&0xFFFFFF0000000000LL)==0x2D57420000000000LL) //-WB
    {
        Skip_C3(                                              "Signature (WB)");
        IsWB=true;
 
        Peek_B8(Signature);
        if ((Signature&0xFF00000000000000LL)==0x0A00000000000000LL) //\n
        {
            Channels=1;
        }
        else if ((Signature&0xFFFFFFFFFFFFFF00LL)==0x5F4D43312E300A00LL) //_MC1.0\n
        {
            Channels=2; //Or more, see later
        }
    }
    else
        Channels=0;
    Skip_B1(                                                    "Signature (Carriage return)");
    /*
    if (Channels==2) //Mutli-channels
    {
        BS_Begin();
        Skip_S4(28,                                             "Reserved");
        Get_S1 ( 4, Channels,                                   "Channels");
    }
    */
    Header_Size=(int8u)Element_Offset;
 
 
    FILLING_BEGIN();
        Accept("AMR");
 
        if (Channels!=1 || IsWB)
            Finish("AMR");
    FILLING_END();
}
 
//***************************************************************************
// Buffer - Per element
//***************************************************************************
 
//---------------------------------------------------------------------------
void File_Amr::Header_Parse()
{
    BS_Begin();
    Skip_SB(                                                "Frame Following");
    Get_S1 ( 4, FrameType,                                  "Frame Type");
    Skip_SB(                                                "Frame Quality");
    Skip_SB(                                                "Unknown");
    Skip_SB(                                                "Unknown");
    BS_End();
 
    //Filling
    if (Amr_BitRate[FrameType]==0)
    {
        Finish("AMR");
        return;
    }
    Header_Fill_Size(Amr_BitRate[FrameType]/400);
    Header_Fill_Code(0, "frame");
}
 
//---------------------------------------------------------------------------
void File_Amr::Data_Parse()
{
    Element_Info1(Frame_Number);
 
    //Parsing
    Skip_XX(Element_Size,                                       "Data");
 
 
    FILLING_BEGIN();
        Frame_Number++;
        FrameTypes[FrameType]++;
        if (Frame_Number>=32)
            Finish("AMR");
    FILLING_END();
}
 
} //NameSpace
 
#endif //MEDIAINFO_AMR_YES
 

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