diff options
Diffstat (limited to 'Src/Plugins/Input/in_mp3/CVbriHeader.cpp')
-rw-r--r-- | Src/Plugins/Input/in_mp3/CVbriHeader.cpp | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/Src/Plugins/Input/in_mp3/CVbriHeader.cpp b/Src/Plugins/Input/in_mp3/CVbriHeader.cpp new file mode 100644 index 00000000..d8eebd84 --- /dev/null +++ b/Src/Plugins/Input/in_mp3/CVbriHeader.cpp @@ -0,0 +1,327 @@ +//---------------------------------------------------------------------------\ +// +// (C) copyright Fraunhofer - IIS (2000) +// All Rights Reserved +// +// filename: CVbriHeader.cpp +// MPEG Layer-3 Audio Decoder +// author : Martin Weishart martin.weishart@iis.fhg.de +// 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; + } +}
\ No newline at end of file |