| 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;  }}
 |