CVbriHeader.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. //---------------------------------------------------------------------------\
  2. //
  3. // (C) copyright Fraunhofer - IIS (2000)
  4. // All Rights Reserved
  5. //
  6. // filename: CVbriHeader.cpp
  7. // MPEG Layer-3 Audio Decoder
  8. // author : Martin Weishart [email protected]
  9. // date : 2000-02-11
  10. // contents/description: provides functions to read a VBRI header
  11. // of a MPEG Layer 3 bitstream encoded
  12. // with variable bitrate using Fraunhofer
  13. // variable bitrate format
  14. //
  15. //--------------------------------------------------------------------------/
  16. #include <windows.h>
  17. #include "CVbriHeader.h"
  18. #include "LAMEInfo.h"
  19. #include <malloc.h>
  20. //---------------------------------------------------------------------------\
  21. //
  22. // Constructor: set position in buffer to parse and create a
  23. // VbriHeaderTable
  24. //
  25. //---------------------------------------------------------------------------/
  26. CVbriHeader::CVbriHeader(){
  27. position = 0;
  28. VbriTable=0;
  29. VbriStreamFrames=0;
  30. encoderDelay=0;
  31. h_id=0;
  32. SampleRate=0;
  33. VbriTableSize=0;
  34. VbriEntryFrames=0;
  35. VbriStreamBytes=0;
  36. }
  37. //---------------------------------------------------------------------------\
  38. //
  39. // Destructor: delete a VbriHeaderTable and a VbriHeader
  40. //
  41. //---------------------------------------------------------------------------/
  42. CVbriHeader::~CVbriHeader(){
  43. free(VbriTable);
  44. }
  45. //---------------------------------------------------------------------------\
  46. //
  47. // Method: checkheader
  48. // Reads the header to a struct that has to be stored and is
  49. // used in other functions to determine file offsets
  50. // Input: buffer containing the first frame
  51. // Output: fills struct VbriHeader
  52. // Return: 0 on success; 1 on error
  53. //
  54. //---------------------------------------------------------------------------/
  55. int CVbriHeader::readVbriHeader(unsigned char *Hbuffer)
  56. {
  57. position=0;
  58. // MPEG header
  59. MPEGFrame frame;
  60. frame.ReadBuffer(Hbuffer);
  61. if (!frame.IsSync())
  62. return 0;
  63. SampleRate = frame.GetSampleRate();
  64. h_id = frame.mpegVersion & 1;
  65. position += DWORD ;
  66. // data indicating silence
  67. position += (8*DWORD) ;
  68. // if a VBRI Header exists read it
  69. if ( *(Hbuffer+position ) == 'V' &&
  70. *(Hbuffer+position+1) == 'B' &&
  71. *(Hbuffer+position+2) == 'R' &&
  72. *(Hbuffer+position+3) == 'I'){
  73. position += DWORD;
  74. //position += WORD;
  75. /*unsigned int vbriVersion = */readFromBuffer(Hbuffer, WORD); // version
  76. encoderDelay = readFromBuffer(Hbuffer, WORD); // delay
  77. position += WORD;
  78. //readFromBuffer(Hbuffer, WORD); // quality
  79. VbriStreamBytes = readFromBuffer(Hbuffer, DWORD);
  80. VbriStreamFrames = readFromBuffer(Hbuffer, DWORD);
  81. VbriTableSize = readFromBuffer(Hbuffer, WORD);
  82. unsigned int VbriTableScale = readFromBuffer(Hbuffer, WORD);
  83. unsigned int VbriEntryBytes = readFromBuffer(Hbuffer, WORD);
  84. VbriEntryFrames = readFromBuffer(Hbuffer, WORD);
  85. if (VbriTableSize > 32768) return 1;
  86. VbriTable = (int *)calloc((VbriTableSize + 1), sizeof(int));
  87. for (unsigned int i = 0 ; i <= VbriTableSize ; i++){
  88. VbriTable[i] = readFromBuffer(Hbuffer, VbriEntryBytes*BYTE)
  89. * VbriTableScale ;
  90. }
  91. }
  92. else
  93. {
  94. return 0;
  95. }
  96. return frame.FrameSize();
  97. }
  98. //---------------------------------------------------------------------------\
  99. //
  100. // Method: seekPointByTime
  101. // Returns a point in the file to decode in bytes that is nearest
  102. // to a given time in seconds
  103. // Input: time in seconds
  104. // Output: None
  105. // Returns: point belonging to the given time value in bytes
  106. //
  107. //---------------------------------------------------------------------------/
  108. int CVbriHeader::seekPointByTime(float EntryTimeInMilliSeconds){
  109. unsigned int SamplesPerFrame, i=0, SeekPoint = 0 , fraction = 0;
  110. float TotalDuration ;
  111. float DurationPerVbriFrames ;
  112. float AccumulatedTime = 0.0f ;
  113. (SampleRate >= 32000) ? (SamplesPerFrame = 1152) : (SamplesPerFrame = 576) ;
  114. TotalDuration = ((float)VbriStreamFrames * (float)SamplesPerFrame)
  115. / (float)SampleRate * 1000.0f ;
  116. DurationPerVbriFrames = (float)TotalDuration / (float)(VbriTableSize+1) ;
  117. if ( EntryTimeInMilliSeconds > TotalDuration ) EntryTimeInMilliSeconds = TotalDuration;
  118. while ( AccumulatedTime <= EntryTimeInMilliSeconds ){
  119. SeekPoint += VbriTable[i] ;
  120. AccumulatedTime += DurationPerVbriFrames;
  121. i++;
  122. }
  123. // Searched too far; correct result
  124. fraction = ( (int)(((( AccumulatedTime - EntryTimeInMilliSeconds ) / DurationPerVbriFrames )
  125. + (1.0f/(2.0f*(float)VbriEntryFrames))) * (float)VbriEntryFrames));
  126. SeekPoint -= (int)((float)VbriTable[i-1] * (float)(fraction)
  127. / (float)VbriEntryFrames) ;
  128. return SeekPoint ;
  129. }
  130. int CVbriHeader::getNumMS()
  131. {
  132. if (!VbriStreamFrames || !SampleRate) return 0;
  133. int nf=VbriStreamFrames;
  134. int sr=SampleRate;
  135. if (sr >= 32000) sr/=2;
  136. //576
  137. return MulDiv(nf,576*1000,sr);
  138. }
  139. #if 0
  140. //---------------------------------------------------------------------------\
  141. //
  142. // Method: seekTimeByPoint
  143. // Returns a time in the file to decode in seconds that is
  144. // nearest to a given point in bytes
  145. // Input: time in seconds
  146. // Output: None
  147. // Returns: point belonging to the given time value in bytes
  148. //
  149. //---------------------------------------------------------------------------/
  150. float CVbriHeader::seekTimeByPoint(unsigned int EntryPointInBytes){
  151. unsigned int SamplesPerFrame, i=0, AccumulatedBytes = 0, fraction = 0;
  152. float SeekTime = 0.0f;
  153. float TotalDuration ;
  154. float DurationPerVbriFrames ;
  155. (SampleRate >= 32000) ? (SamplesPerFrame = 1152) : (SamplesPerFrame = 576) ;
  156. TotalDuration = ((float)VbriStreamFrames * (float)SamplesPerFrame)
  157. / (float)SampleRate;
  158. DurationPerVbriFrames = (float)TotalDuration / (float)(VbriTableSize+1) ;
  159. while (AccumulatedBytes <= EntryPointInBytes){
  160. AccumulatedBytes += VbriTable[i] ;
  161. SeekTime += DurationPerVbriFrames;
  162. i++;
  163. }
  164. // Searched too far; correct result
  165. fraction = (int)(((( AccumulatedBytes - EntryPointInBytes ) / (float)VbriTable[i-1])
  166. + (1/(2*(float)VbriEntryFrames))) * (float)VbriEntryFrames);
  167. SeekTime -= (DurationPerVbriFrames * (float) ((float)(fraction) / (float)VbriEntryFrames)) ;
  168. return SeekTime ;
  169. }
  170. //---------------------------------------------------------------------------\
  171. //
  172. // Method: seekPointByPercent
  173. // Returns a point in the file to decode in bytes that is
  174. // nearest to a given percentage of the time of the stream
  175. // Input: percent of time
  176. // Output: None
  177. // Returns: point belonging to the given time percentage value in bytes
  178. //
  179. //---------------------------------------------------------------------------/
  180. int CVbriHeader::seekPointByPercent(float percent){
  181. int SamplesPerFrame;
  182. float TotalDuration ;
  183. if (percent >= 100.0f) percent = 100.0f;
  184. if (percent <= 0.0f) percent = 0.0f;
  185. (SampleRate >= 32000) ? (SamplesPerFrame = 1152) : (SamplesPerFrame = 576) ;
  186. TotalDuration = ((float)VbriStreamFrames * (float)SamplesPerFrame)
  187. / (float)SampleRate;
  188. return seekPointByTime( (percent/100.0f) * TotalDuration * 1000.0f );
  189. }
  190. #endif
  191. //---------------------------------------------------------------------------\
  192. //
  193. // Method: GetSampleRate
  194. // Returns the sampling rate of the file to decode
  195. // Input: Buffer containing the part of the first frame after the
  196. // syncword
  197. // Output: None
  198. // Return: sampling rate of the file to decode
  199. //
  200. //---------------------------------------------------------------------------/
  201. /*int CVbriHeader::getSampleRate(unsigned char * buffer){
  202. unsigned char id, idx, mpeg ;
  203. id = (0xC0 & (buffer[1] << 3)) >> 4;
  204. idx = (0xC0 & (buffer[2] << 4)) >> 6;
  205. mpeg = id | idx;
  206. switch ((int)mpeg){
  207. case 0 : return 11025;
  208. case 1 : return 12000;
  209. case 2 : return 8000;
  210. case 8 : return 22050;
  211. case 9 : return 24000;
  212. case 10: return 16000;
  213. case 12: return 44100;
  214. case 13: return 48000;
  215. case 14: return 32000;
  216. default: return 0;
  217. }
  218. }*/
  219. //---------------------------------------------------------------------------\
  220. //
  221. // Method: readFromBuffer
  222. // reads from a buffer a segment to an int value
  223. // Input: Buffer containig the first frame
  224. // Output: none
  225. // Return: number containing int value of buffer segmenet
  226. // length
  227. //
  228. //---------------------------------------------------------------------------/
  229. int CVbriHeader::readFromBuffer ( unsigned char * HBuffer, int length ){
  230. if (HBuffer)
  231. {
  232. int number = 0;
  233. for(int i = 0; i < length ; i++ )
  234. {
  235. int b = length-1-i ;
  236. number = number | (unsigned int)( HBuffer[position+i] & 0xff ) << ( 8*b );
  237. }
  238. position += length ;
  239. return number;
  240. }
  241. else{
  242. return 0;
  243. }
  244. }