id3lib  3.8.3
mp3_parse.cpp
Go to the documentation of this file.
1 // -*- C++ -*-
2 // $Id: mp3_parse.cpp,v 1.6 2002/11/02 17:48:51 t1mpy Exp $
3 
4 // id3lib: a C++ library for creating and manipulating id3v1/v2 tags
5 // Copyright 2002, Thijmen Klok (thijmen@id3lib.org)
6 
7 // This library is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU Library General Public License as published by
9 // the Free Software Foundation; either version 2 of the License, or (at your
10 // option) any later version.
11 //
12 // This library is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
15 // License for more details.
16 //
17 // You should have received a copy of the GNU Library General Public License
18 // along with this library; if not, write to the Free Software Foundation,
19 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 
21 // The id3lib authors encourage improvements and optimisations to be sent to
22 // the id3lib coordinator. Please see the README file for details on where to
23 // send such submissions. See the AUTHORS file for a list of people who have
24 // contributed to id3lib. See the ChangeLog file for a list of changes to
25 // id3lib. These files are distributed with id3lib at
26 // http://download.sourceforge.net/id3lib/
27 
28 #include "mp3_header.h"
29 
30 #define FRAMES_FLAG 0x0001
31 #define BYTES_FLAG 0x0002
32 #define TOC_FLAG 0x0004
33 #define SCALE_FLAG 0x0008
34 
35 static int ExtractI4(unsigned char *buf)
36 {
37  int x;
38  // big endian extract
39 
40  x = buf[0];
41  x <<= 8;
42  x |= buf[1];
43  x <<= 8;
44  x |= buf[2];
45  x <<= 8;
46  x |= buf[3];
47 
48  return x;
49 }
50 
51 uint32 fto_nearest_i(float f)
52 {
53  uint32 i;
54 
55  i = (uint32)f;
56  if (i < f)
57  {
58  f -= i;
59  if (f >= 0.5)
60  return i+1;
61  else
62  return i;
63  }
64  else
65  return i;
66 }
67 
68 uint16 calcCRC(char *pFrame, size_t audiodatasize)
69 {
70  size_t icounter;
71  int tmpchar, crcmask, tmpi;
72  uint16 crc = 0xffff;
73 
74  for (icounter = 2; icounter < audiodatasize; ++icounter)
75  {
76  if (icounter != 4 && icounter != 5) //skip the 2 chars of the crc itself
77  {
78  crcmask = 1 << 8;
79  tmpchar = pFrame[icounter];
80  while (crcmask >>= 1)
81  {
82  tmpi = crc & 0x8000;
83  crc <<= 1;
84  if (!tmpi ^ !(tmpchar & crcmask))
85  crc ^= 0x8005;
86  }
87  }
88  }
89  crc &= 0xffff;
90  return crc;
91 }
92 
94 {
95  if (_mp3_header_output != NULL)
96  delete _mp3_header_output;
97  _mp3_header_output = NULL;
98 }
99 
100 using namespace dami;
101 
102 bool Mp3Info::Parse(ID3_Reader& reader, size_t mp3size)
103 {
104  MP3_BitRates _mp3_bitrates[2][3][16] =
105  {
106  {
107  { //MPEG 1, LAYER I
124  },
125  { //MPEG 1, LAYER II
142  },
143  { //MPEG 1, LAYER III
160  }
161  },
162  {
163  { //MPEG 2 or 2.5, LAYER I
180  },
181  { //MPEG 2 or 2.5, LAYER II
198  },
199  { //MPEG 2 or 2.5, LAYER III
216  }
217  }
218  };
219 
220  Mp3_Frequencies _mp3_frequencies[4][4] =
221  {
226  };
227 
228  _mp3_header_internal *_tmpheader;
229 
230  const size_t HEADERSIZE = 4;//
231  char buf[HEADERSIZE+1]; //+1 to hold the \0 char
232  ID3_Reader::pos_type beg = reader.getCur() ;
233  ID3_Reader::pos_type end = beg + HEADERSIZE ;
234  reader.setCur(beg);
235  int bitrate_index;
236 
237  _mp3_header_output->layer = MPEGLAYER_FALSE;
238  _mp3_header_output->version = MPEGVERSION_FALSE;
239  _mp3_header_output->bitrate = MP3BITRATE_FALSE;
240  _mp3_header_output->channelmode = MP3CHANNELMODE_FALSE;
241  _mp3_header_output->modeext = MP3MODEEXT_FALSE;
242  _mp3_header_output->emphasis = MP3EMPHASIS_FALSE;
243  _mp3_header_output->crc = MP3CRC_MISMATCH;
244  _mp3_header_output->frequency = 0;
245  _mp3_header_output->framesize = 0;
246  _mp3_header_output->frames = 0;
247  _mp3_header_output->time = 0;
248  _mp3_header_output->vbr_bitrate = 0;
249 
250  reader.readChars(buf, HEADERSIZE);
251  buf[HEADERSIZE]='\0';
252  // copy the pointer to the struct
253 
254  if (((buf[0] & 0xFF) != 0xFF) || ((buf[1] & 0xE0) != 0xE0)) //first 11 bits should be 1
255  {
256  this->Clean();
257  return false;
258  }
259 
260  _tmpheader = reinterpret_cast<_mp3_header_internal *>(buf);
261 
262  bitrate_index = 0;
263  switch (_tmpheader->id)
264  {
265  case 3:
266  _mp3_header_output->version = MPEGVERSION_1;
267  bitrate_index = 0;
268  break;
269  case 2:
270  _mp3_header_output->version = MPEGVERSION_2;
271  bitrate_index = 1;
272  break;
273  case 1:
274  this->Clean();
275  return false; //wouldn't know how to handle it
276  break;
277  case 0:
278  _mp3_header_output->version = MPEGVERSION_2_5;
279  bitrate_index = 1;
280  break;
281  default:
282  this->Clean();
283  return false;
284  break;
285  };
286 
287  switch (_tmpheader->layer)
288  {
289  case 3:
290  _mp3_header_output->layer = MPEGLAYER_I;
291  break;
292  case 2:
293  _mp3_header_output->layer = MPEGLAYER_II;
294  break;
295  case 1:
296  _mp3_header_output->layer = MPEGLAYER_III;
297  break;
298  case 0:
299  this->Clean();
300  return false; //wouldn't know how to handle it
301  break;
302  default:
303  this->Clean();
304  return false; //how can two unsigned bits be something else??
305  break;
306  };
307 
308  // mpegversion, layer and bitrate are all valid
309  _mp3_header_output->bitrate = _mp3_bitrates[bitrate_index][3-_tmpheader->layer][_tmpheader->bitrate_index];
310  if (_mp3_header_output->bitrate == MP3BITRATE_FALSE)
311  {
312  this->Clean();
313  return false;
314  }
315  _mp3_header_output->frequency = _mp3_frequencies[_tmpheader->id][_tmpheader->frequency];
316  if (_mp3_header_output->frequency == MP3FREQUENCIES_Reserved)
317  {
318  this->Clean();
319  return false;
320  }
321 
322  _mp3_header_output->privatebit = (bool)_tmpheader->private_bit;
323  _mp3_header_output->copyrighted = (bool)_tmpheader->copyright;
324  _mp3_header_output->original = (bool)_tmpheader->original;
325  _mp3_header_output->crc = (Mp3_Crc)!(bool)_tmpheader->protection_bit;
326 
327  switch (_tmpheader->mode)
328  {
329  case 3:
330  _mp3_header_output->channelmode = MP3CHANNELMODE_SINGLE_CHANNEL;
331  break;
332  case 2:
333  _mp3_header_output->channelmode = MP3CHANNELMODE_DUAL_CHANNEL;
334  break;
335  case 1:
336  _mp3_header_output->channelmode = MP3CHANNELMODE_JOINT_STEREO;
337  break;
338  case 0:
339  _mp3_header_output->channelmode = MP3CHANNELMODE_STEREO;
340  break;
341  default:
342  this->Clean();
343  return false; //wouldn't know how to handle it
344  break;
345  }
346 
347  if (_mp3_header_output->channelmode == MP3CHANNELMODE_JOINT_STEREO)
348  {
349  // these have a different meaning for different layers, better give them a generic name in the enum
350  switch (_tmpheader->mode_ext)
351  {
352  case 3:
353  _mp3_header_output->modeext = MP3MODEEXT_3;
354  break;
355  case 2:
356  _mp3_header_output->modeext = MP3MODEEXT_2;
357  break;
358  case 1:
359  _mp3_header_output->modeext = MP3MODEEXT_1;
360  break;
361  case 0:
362  _mp3_header_output->modeext = MP3MODEEXT_0;
363  break;
364  default:
365  this->Clean();
366  return false; //wouldn't know how to handle it
367  break;
368  }
369  }
370  else //it's valid to have a valid false one in this case, since it's only used with joint stereo
371  _mp3_header_output->modeext = MP3MODEEXT_FALSE;
372 
373  switch (_tmpheader->emphasis)
374  {
375  case 3:
376  _mp3_header_output->emphasis = MP3EMPHASIS_CCIT_J17;
377  break;
378  case 2:
379  _mp3_header_output->emphasis = MP3EMPHASIS_Reserved;
380  break;
381  case 1:
382  _mp3_header_output->emphasis = MP3EMPHASIS_50_15MS;
383  break;
384  case 0:
385  _mp3_header_output->emphasis = MP3EMPHASIS_NONE;
386  break;
387  default:
388  this->Clean();
389  return false; //wouldn't know how to handle it
390  break;
391  }
392 
393 //http://www.mp3-tech.org/programmer/frame_header.html
394  if (_mp3_header_output->bitrate != MP3BITRATE_NONE && _mp3_header_output->frequency > 0)
395  {
396 
397  switch(_mp3_header_output->layer)
398  {
399  case MPEGLAYER_I: // Layer 1
400  _mp3_header_output->framesize = 4 * (12 * _mp3_header_output->bitrate / _mp3_header_output->frequency + (_tmpheader->padding_bit ? 1 : 0));
401  break;
402  case MPEGLAYER_II: // Layer 2
403  _mp3_header_output->framesize = 144 * _mp3_header_output->bitrate / _mp3_header_output->frequency + (_tmpheader->padding_bit ? 1 : 0);
404  break;
405  case MPEGLAYER_III: // Layer 3
406  if(_mp3_header_output->version == MPEGVERSION_2_5)
407  _mp3_header_output->framesize = 144 * _mp3_header_output->bitrate / _mp3_header_output->frequency + (_tmpheader->padding_bit ? 1 : 0); //Mpeg1
408  else
409  _mp3_header_output->framesize = 72000 * _mp3_header_output->bitrate / _mp3_header_output->frequency + (_tmpheader->padding_bit ? 1 : 0); //Mpeg2 + Mpeg2.5
410  break;
411  default:
412  break;
413  }
414 // if (_mp3_header_output->layer == MPEGLAYER_I)
415 // _mp3_header_output->framesize = fto_nearest_i((float)((48 * (float)_mp3_header_output->bitrate) / _mp3_header_output->frequency)) + (_tmpheader->padding_bit ? 4 : 0);
416 // else
417 // _mp3_header_output->framesize = fto_nearest_i((float)((144 * (float)_mp3_header_output->bitrate) / _mp3_header_output->frequency)) + (_tmpheader->padding_bit ? 1 : 0);
418  }
419  else
420  _mp3_header_output->framesize = 0; //unable to determine
421 
422  const size_t CRCSIZE = 2;
423  size_t sideinfo_len;
424 
425  if (_mp3_header_output->version == MPEGVERSION_1) /* MPEG 1 */
426  sideinfo_len = (_mp3_header_output->channelmode == MP3CHANNELMODE_SINGLE_CHANNEL) ? 4 + 17 : 4 + 32;
427  else /* MPEG 2 */
428  sideinfo_len = (_mp3_header_output->channelmode == MP3CHANNELMODE_SINGLE_CHANNEL) ? 4 + 9 : 4 + 17;
429 
430  int vbr_header_offest = beg + sideinfo_len;
431  int vbr_frames = 0;
432 
433  sideinfo_len += 2; // add two for the crc itself
434 
435  if ((_mp3_header_output->crc == MP3CRC_OK) && mp3size < sideinfo_len)
436  _mp3_header_output->crc = MP3CRC_ERROR_SIZE;
437 
438  if (_mp3_header_output->crc == MP3CRC_OK)
439  {
440  char audiodata[38 + 1]; //+1 to hold the 0 char
441  uint16 crc16;
442  uint16 crcstored;
443 
444  _mp3_header_output->crc = MP3CRC_MISMATCH; //as a starting point, we assume the worst
445 
446  reader.setCur(beg);
447 
448  reader.readChars(audiodata, sideinfo_len);
449  audiodata[sideinfo_len] = '\0';
450 
451  crc16 = calcCRC(audiodata, sideinfo_len);
452 
453  beg = end;
454  end = beg + CRCSIZE;
455 
456  reader.setCur(beg);
457  crcstored = (uint16)io::readBENumber(reader, CRCSIZE);
458 
459  // a mismatch doesn't mean the file is unusable
460  // it has just some bits in the wrong place
461  if (crcstored == crc16)
462  _mp3_header_output->crc = MP3CRC_OK;
463  }
464 
465  // read xing/vbr header if present
466  // derived from code in vbrheadersdk.zip
467  // from http://www.xingtech.com/developer/mp3/
468 
469  const size_t VBR_HEADER_MIN_SIZE = 8; // "xing" + flags are fixed
470  const size_t VBR_HEADER_MAX_SIZE = 120; // frames, bytes, toc and scale are optional
471 
472  if (mp3size >= vbr_header_offest + VBR_HEADER_MIN_SIZE)
473  {
474  char vbrheaderdata[VBR_HEADER_MAX_SIZE+1]; //+1 to hold the 0 char
475  unsigned char *pvbrdata = (unsigned char *)vbrheaderdata;
476  int vbr_filesize = 0;
477  int vbr_scale = 0;
478  int vbr_flags = 0;
479 
480  // get fixed part of vbr header
481  // and check if valid
482 
483  beg = vbr_header_offest;
484  reader.setCur(beg);
485  reader.readChars(vbrheaderdata, VBR_HEADER_MIN_SIZE);
486  vbrheaderdata[VBR_HEADER_MIN_SIZE] = '\0';
487 
488  if (pvbrdata[0] == 'X' &&
489  pvbrdata[1] == 'i' &&
490  pvbrdata[2] == 'n' &&
491  pvbrdata[3] == 'g')
492  {
493  // get vbr flags
494  pvbrdata += 4;
495  vbr_flags = ExtractI4(pvbrdata);
496  pvbrdata += 4;
497 
498  // read entire vbr header
499  unsigned int vbr_header_size = VBR_HEADER_MIN_SIZE
500  + ((vbr_flags & FRAMES_FLAG)? 4:0)
501  + ((vbr_flags & BYTES_FLAG)? 4:0)
502  + ((vbr_flags & TOC_FLAG)? 100:0)
503  + ((vbr_flags & SCALE_FLAG)? 4:0);
504 
505  if (mp3size >= vbr_header_offest + vbr_header_size)
506  {
507  reader.readChars(&vbrheaderdata[VBR_HEADER_MIN_SIZE], vbr_header_size - VBR_HEADER_MIN_SIZE);
508  vbrheaderdata[vbr_header_size] = '\0';
509 
510  // get frames, bytes, toc and scale
511 
512  if (vbr_flags & FRAMES_FLAG)
513  {
514  vbr_frames = ExtractI4(pvbrdata);
515  pvbrdata +=4;
516  }
517 
518  if (vbr_flags & BYTES_FLAG)
519  {
520  vbr_filesize = ExtractI4(pvbrdata);
521  pvbrdata +=4;
522  }
523 
524  if (vbr_flags & TOC_FLAG)
525  {
526  // seek offsets
527  // we are not using
528  // for(i=0;i<100;i++) seek_offsets[i] = pvbrdata[i];
529 
530  pvbrdata +=100;
531  }
532 
533  if (vbr_flags & SCALE_FLAG)
534  {
535  vbr_scale = ExtractI4(pvbrdata);
536  pvbrdata +=4;
537  }
538 
539  if (vbr_frames > 0)
540  {
541  _mp3_header_output->vbr_bitrate = (((vbr_filesize!=0) ? vbr_filesize : mp3size) / vbr_frames) * _mp3_header_output->frequency / 144;
542  _mp3_header_output->vbr_bitrate -= _mp3_header_output->vbr_bitrate%1000; // round the bitrate:
543  }
544  }
545  }
546  }
547 
548  if (_mp3_header_output->framesize > 0 && mp3size >= _mp3_header_output->framesize) // this means bitrate is not none too
549  {
550  if (vbr_frames == 0)
551  _mp3_header_output->frames = fto_nearest_i((float)mp3size / _mp3_header_output->framesize);
552  else
553  _mp3_header_output->frames = vbr_frames;
554 
555  // bitrate becomes byterate (per second) if divided by 8
556  if (_mp3_header_output->vbr_bitrate == 0)
557  _mp3_header_output->time = fto_nearest_i( (float)mp3size / (_mp3_header_output->bitrate / 8) );
558  else
559  _mp3_header_output->time = fto_nearest_i( (float)mp3size / (_mp3_header_output->vbr_bitrate / 8) );
560  }
561  else
562  {
563  _mp3_header_output->frames = 0;
564  _mp3_header_output->time = 0;
565  }
566  //if we got to here it's okay
567  return true;
568 }
569 
570 
virtual pos_type setCur(pos_type pos)=0
Set the value of the current position for reading.
virtual pos_type getCur()=0
Return the current position in the reader.
virtual size_type readChars(char_type buf[], size_type len)=0
Read up to len characters into buf and advance the internal position accordingly.
uint32 pos_type
Definition: reader.h:38
void Clean()
Definition: mp3_parse.cpp:93
bool Parse(ID3_Reader &, size_t mp3size)
Definition: mp3_parse.cpp:102
#define NULL
Definition: globals.h:743
@ MP3MODEEXT_3
Definition: globals.h:501
@ MP3MODEEXT_0
Definition: globals.h:498
@ MP3MODEEXT_2
Definition: globals.h:500
@ MP3MODEEXT_1
Definition: globals.h:499
@ MP3MODEEXT_FALSE
Definition: globals.h:497
Mp3_Frequencies
Definition: globals.h:472
@ MP3FREQUENCIES_48000HZ
Definition: globals.h:482
@ MP3FREQUENCIES_24000HZ
Definition: globals.h:480
@ MP3FREQUENCIES_44100HZ
Definition: globals.h:483
@ MP3FREQUENCIES_11025HZ
Definition: globals.h:476
@ MP3FREQUENCIES_32000HZ
Definition: globals.h:481
@ MP3FREQUENCIES_22050HZ
Definition: globals.h:479
@ MP3FREQUENCIES_16000HZ
Definition: globals.h:478
@ MP3FREQUENCIES_8000HZ
Definition: globals.h:475
@ MP3FREQUENCIES_12000HZ
Definition: globals.h:477
@ MP3FREQUENCIES_Reserved
Definition: globals.h:474
@ MP3EMPHASIS_50_15MS
Definition: globals.h:508
@ MP3EMPHASIS_CCIT_J17
Definition: globals.h:510
@ MP3EMPHASIS_FALSE
Definition: globals.h:506
@ MP3EMPHASIS_NONE
Definition: globals.h:507
@ MP3EMPHASIS_Reserved
Definition: globals.h:509
@ MPEGLAYER_I
Definition: globals.h:459
@ MPEGLAYER_II
Definition: globals.h:458
@ MPEGLAYER_FALSE
Definition: globals.h:455
@ MPEGLAYER_III
Definition: globals.h:457
@ MP3CHANNELMODE_DUAL_CHANNEL
Definition: globals.h:491
@ MP3CHANNELMODE_STEREO
Definition: globals.h:489
@ MP3CHANNELMODE_SINGLE_CHANNEL
Definition: globals.h:492
@ MP3CHANNELMODE_FALSE
Definition: globals.h:488
@ MP3CHANNELMODE_JOINT_STEREO
Definition: globals.h:490
Mp3_Crc
Definition: globals.h:514
@ MP3CRC_MISMATCH
Definition: globals.h:516
@ MP3CRC_ERROR_SIZE
Definition: globals.h:515
@ MP3CRC_OK
Definition: globals.h:518
MP3_BitRates
Definition: globals.h:424
@ MP3BITRATE_NONE
Definition: globals.h:426
@ MP3BITRATE_80K
Definition: globals.h:435
@ MP3BITRATE_448K
Definition: globals.h:450
@ MP3BITRATE_416K
Definition: globals.h:449
@ MP3BITRATE_160K
Definition: globals.h:440
@ MP3BITRATE_288K
Definition: globals.h:445
@ MP3BITRATE_128K
Definition: globals.h:438
@ MP3BITRATE_176K
Definition: globals.h:441
@ MP3BITRATE_224K
Definition: globals.h:443
@ MP3BITRATE_8K
Definition: globals.h:427
@ MP3BITRATE_96K
Definition: globals.h:436
@ MP3BITRATE_48K
Definition: globals.h:432
@ MP3BITRATE_16K
Definition: globals.h:428
@ MP3BITRATE_352K
Definition: globals.h:447
@ MP3BITRATE_40K
Definition: globals.h:431
@ MP3BITRATE_192K
Definition: globals.h:442
@ MP3BITRATE_112K
Definition: globals.h:437
@ MP3BITRATE_24K
Definition: globals.h:429
@ MP3BITRATE_56K
Definition: globals.h:433
@ MP3BITRATE_FALSE
Definition: globals.h:425
@ MP3BITRATE_256K
Definition: globals.h:444
@ MP3BITRATE_32K
Definition: globals.h:430
@ MP3BITRATE_384K
Definition: globals.h:448
@ MP3BITRATE_64K
Definition: globals.h:434
@ MP3BITRATE_144K
Definition: globals.h:439
@ MP3BITRATE_320K
Definition: globals.h:446
@ MPEGVERSION_2_5
Definition: globals.h:465
@ MPEGVERSION_FALSE
Definition: globals.h:464
@ MPEGVERSION_2
Definition: globals.h:467
@ MPEGVERSION_1
Definition: globals.h:468
#define BYTES_FLAG
Definition: mp3_parse.cpp:31
uint16 calcCRC(char *pFrame, size_t audiodatasize)
Definition: mp3_parse.cpp:68
#define FRAMES_FLAG
Definition: mp3_parse.cpp:30
#define SCALE_FLAG
Definition: mp3_parse.cpp:33
uint32 fto_nearest_i(float f)
Definition: mp3_parse.cpp:51
#define TOC_FLAG
Definition: mp3_parse.cpp:32
Definition: tag_impl.h:42