123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- //---------------------------------------------------------------------------\
- //
- // (C) copyright Fraunhofer - IIS (2000)
- // All Rights Reserved
- //
- // filename: CVbriHeader.cpp
- // MPEG Layer-3 Audio Decoder
- // author : Martin Weishart [email protected]
- // date : 2000-02-11
- // contents/description: provides functions to read a VBRI header
- // of a MPEG Layer 3 bitstream encoded
- // with variable bitrate using Fraunhofer
- // variable bitrate format
- //
- //--------------------------------------------------------------------------/
- #include <windows.h>
- #include "CVbriHeader.h"
- #include "LAMEInfo.h"
- #include <malloc.h>
- //---------------------------------------------------------------------------\
- //
- // Constructor: set position in buffer to parse and create a
- // VbriHeaderTable
- //
- //---------------------------------------------------------------------------/
- CVbriHeader::CVbriHeader(){
- position = 0;
- VbriTable=0;
- VbriStreamFrames=0;
- encoderDelay=0;
- h_id=0;
- SampleRate=0;
- VbriTableSize=0;
- VbriEntryFrames=0;
- VbriStreamBytes=0;
- }
- //---------------------------------------------------------------------------\
- //
- // Destructor: delete a VbriHeaderTable and a VbriHeader
- //
- //---------------------------------------------------------------------------/
- CVbriHeader::~CVbriHeader(){
- free(VbriTable);
- }
- //---------------------------------------------------------------------------\
- //
- // Method: checkheader
- // Reads the header to a struct that has to be stored and is
- // used in other functions to determine file offsets
- // Input: buffer containing the first frame
- // Output: fills struct VbriHeader
- // Return: 0 on success; 1 on error
- //
- //---------------------------------------------------------------------------/
- int CVbriHeader::readVbriHeader(unsigned char *Hbuffer)
- {
- position=0;
- // MPEG header
- MPEGFrame frame;
- frame.ReadBuffer(Hbuffer);
- if (!frame.IsSync())
- return 0;
- SampleRate = frame.GetSampleRate();
- h_id = frame.mpegVersion & 1;
- position += DWORD ;
- // data indicating silence
- position += (8*DWORD) ;
-
- // if a VBRI Header exists read it
- if ( *(Hbuffer+position ) == 'V' &&
- *(Hbuffer+position+1) == 'B' &&
- *(Hbuffer+position+2) == 'R' &&
- *(Hbuffer+position+3) == 'I'){
-
- position += DWORD;
-
- //position += WORD;
- /*unsigned int vbriVersion = */readFromBuffer(Hbuffer, WORD); // version
- encoderDelay = readFromBuffer(Hbuffer, WORD); // delay
- position += WORD;
- //readFromBuffer(Hbuffer, WORD); // quality
- VbriStreamBytes = readFromBuffer(Hbuffer, DWORD);
- VbriStreamFrames = readFromBuffer(Hbuffer, DWORD);
- VbriTableSize = readFromBuffer(Hbuffer, WORD);
- unsigned int VbriTableScale = readFromBuffer(Hbuffer, WORD);
- unsigned int VbriEntryBytes = readFromBuffer(Hbuffer, WORD);
- VbriEntryFrames = readFromBuffer(Hbuffer, WORD);
-
- if (VbriTableSize > 32768) return 1;
-
- VbriTable = (int *)calloc((VbriTableSize + 1), sizeof(int));
- for (unsigned int i = 0 ; i <= VbriTableSize ; i++){
- VbriTable[i] = readFromBuffer(Hbuffer, VbriEntryBytes*BYTE)
- * VbriTableScale ;
- }
- }
- else
- {
- return 0;
- }
- return frame.FrameSize();
- }
- //---------------------------------------------------------------------------\
- //
- // Method: seekPointByTime
- // Returns a point in the file to decode in bytes that is nearest
- // to a given time in seconds
- // Input: time in seconds
- // Output: None
- // Returns: point belonging to the given time value in bytes
- //
- //---------------------------------------------------------------------------/
- int CVbriHeader::seekPointByTime(float EntryTimeInMilliSeconds){
- unsigned int SamplesPerFrame, i=0, SeekPoint = 0 , fraction = 0;
- float TotalDuration ;
- float DurationPerVbriFrames ;
- float AccumulatedTime = 0.0f ;
-
- (SampleRate >= 32000) ? (SamplesPerFrame = 1152) : (SamplesPerFrame = 576) ;
- TotalDuration = ((float)VbriStreamFrames * (float)SamplesPerFrame)
- / (float)SampleRate * 1000.0f ;
- DurationPerVbriFrames = (float)TotalDuration / (float)(VbriTableSize+1) ;
-
- if ( EntryTimeInMilliSeconds > TotalDuration ) EntryTimeInMilliSeconds = TotalDuration;
-
- while ( AccumulatedTime <= EntryTimeInMilliSeconds ){
-
- SeekPoint += VbriTable[i] ;
- AccumulatedTime += DurationPerVbriFrames;
- i++;
-
- }
-
- // Searched too far; correct result
- fraction = ( (int)(((( AccumulatedTime - EntryTimeInMilliSeconds ) / DurationPerVbriFrames )
- + (1.0f/(2.0f*(float)VbriEntryFrames))) * (float)VbriEntryFrames));
-
- SeekPoint -= (int)((float)VbriTable[i-1] * (float)(fraction)
- / (float)VbriEntryFrames) ;
- return SeekPoint ;
- }
- int CVbriHeader::getNumMS()
- {
- if (!VbriStreamFrames || !SampleRate) return 0;
- int nf=VbriStreamFrames;
- int sr=SampleRate;
- if (sr >= 32000) sr/=2;
- //576
- return MulDiv(nf,576*1000,sr);
- }
- #if 0
- //---------------------------------------------------------------------------\
- //
- // Method: seekTimeByPoint
- // Returns a time in the file to decode in seconds that is
- // nearest to a given point in bytes
- // Input: time in seconds
- // Output: None
- // Returns: point belonging to the given time value in bytes
- //
- //---------------------------------------------------------------------------/
- float CVbriHeader::seekTimeByPoint(unsigned int EntryPointInBytes){
- unsigned int SamplesPerFrame, i=0, AccumulatedBytes = 0, fraction = 0;
- float SeekTime = 0.0f;
- float TotalDuration ;
- float DurationPerVbriFrames ;
- (SampleRate >= 32000) ? (SamplesPerFrame = 1152) : (SamplesPerFrame = 576) ;
- TotalDuration = ((float)VbriStreamFrames * (float)SamplesPerFrame)
- / (float)SampleRate;
- DurationPerVbriFrames = (float)TotalDuration / (float)(VbriTableSize+1) ;
-
- while (AccumulatedBytes <= EntryPointInBytes){
-
- AccumulatedBytes += VbriTable[i] ;
- SeekTime += DurationPerVbriFrames;
- i++;
-
- }
-
- // Searched too far; correct result
- fraction = (int)(((( AccumulatedBytes - EntryPointInBytes ) / (float)VbriTable[i-1])
- + (1/(2*(float)VbriEntryFrames))) * (float)VbriEntryFrames);
-
- SeekTime -= (DurationPerVbriFrames * (float) ((float)(fraction) / (float)VbriEntryFrames)) ;
-
- return SeekTime ;
- }
- //---------------------------------------------------------------------------\
- //
- // Method: seekPointByPercent
- // Returns a point in the file to decode in bytes that is
- // nearest to a given percentage of the time of the stream
- // Input: percent of time
- // Output: None
- // Returns: point belonging to the given time percentage value in bytes
- //
- //---------------------------------------------------------------------------/
- int CVbriHeader::seekPointByPercent(float percent){
- int SamplesPerFrame;
- float TotalDuration ;
-
- if (percent >= 100.0f) percent = 100.0f;
- if (percent <= 0.0f) percent = 0.0f;
- (SampleRate >= 32000) ? (SamplesPerFrame = 1152) : (SamplesPerFrame = 576) ;
- TotalDuration = ((float)VbriStreamFrames * (float)SamplesPerFrame)
- / (float)SampleRate;
-
- return seekPointByTime( (percent/100.0f) * TotalDuration * 1000.0f );
-
- }
- #endif
- //---------------------------------------------------------------------------\
- //
- // Method: GetSampleRate
- // Returns the sampling rate of the file to decode
- // Input: Buffer containing the part of the first frame after the
- // syncword
- // Output: None
- // Return: sampling rate of the file to decode
- //
- //---------------------------------------------------------------------------/
- /*int CVbriHeader::getSampleRate(unsigned char * buffer){
-
- unsigned char id, idx, mpeg ;
-
- id = (0xC0 & (buffer[1] << 3)) >> 4;
- idx = (0xC0 & (buffer[2] << 4)) >> 6;
-
- mpeg = id | idx;
-
- switch ((int)mpeg){
-
- case 0 : return 11025;
- case 1 : return 12000;
- case 2 : return 8000;
- case 8 : return 22050;
- case 9 : return 24000;
- case 10: return 16000;
- case 12: return 44100;
- case 13: return 48000;
- case 14: return 32000;
- default: return 0;
- }
- }*/
- //---------------------------------------------------------------------------\
- //
- // Method: readFromBuffer
- // reads from a buffer a segment to an int value
- // Input: Buffer containig the first frame
- // Output: none
- // Return: number containing int value of buffer segmenet
- // length
- //
- //---------------------------------------------------------------------------/
- int CVbriHeader::readFromBuffer ( unsigned char * HBuffer, int length ){
- if (HBuffer)
- {
- int number = 0;
- for(int i = 0; i < length ; i++ )
- {
- int b = length-1-i ;
- number = number | (unsigned int)( HBuffer[position+i] & 0xff ) << ( 8*b );
- }
- position += length ;
- return number;
- }
- else{
- return 0;
- }
- }
|