aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/Input/in_mp3/CVbriHeader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Plugins/Input/in_mp3/CVbriHeader.cpp')
-rw-r--r--Src/Plugins/Input/in_mp3/CVbriHeader.cpp327
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