Hi,

3 months ago I asked if any programs exist that do this according to this 
thread:

http://marc.theaimsgroup.com/?l=openbsd-misc&m=115298981814514&w=2

A bunch of you jumped on me like starving wolves, and well I didn't get
any of the help I was looking for.  So tonight at the beginning of the 
weekend I set out to learn how an MP3 frame is constructed and I "reversed"
the GNU code of MPlayer, feel free to use this information under a BSD 
license for your own programs.  Now all I gotta do is bang out my program
based on this info. :-)

Kind regards,

-peter

MP3 Header

[explanation from RFC 3119]

2. The Structure of MP3 Frames

   In this section we give a brief overview of the structure of a MP3
   frame.  (For more detailed description, see the MPEG 1 audio [3] and
   MPEG 2 audio [4] specifications.)

   Each MPEG audio frame begins with a 4-byte header.  Information
   defined by this header includes:

   -  Whether the audio is MPEG 1 or MPEG 2.
   -  Whether the audio is layer I, II, or III.
      (The remainder of this document assumes layer III, i.e., "MP3"
      frames)
   -  Whether the audio is mono or stereo.
   -  Whether or not there is a 2-byte CRC field following the header.
   -  (indirectly) The size of the frame.

   The following structures appear after the header:
   -  (optionally) A 2-byte CRC field
   -  A "side info" structure.  This has the following length:
      -  32 bytes for MPEG 1 stereo
      -  17 bytes for MPEG 1 mono, or for MPEG 2 stereo
      -  9 bytes for MPEG 2 mono
   -  Encoded audio data, plus optional ancillary data (filling out the
      rest of the frame)

   For the purpose of this document, the "side info" structure is the
   most important, because it defines the location and size of the
   "Application Data Unit" (ADU) that an MP3 decoder will process.  In
   particular, the "side info" structure defines:

   -  "main_data_begin": This is a back-pointer (in bytes) to the start
      of the ADU.  The back-pointer is counted from the beginning of the
      frame, and counts only encoded audio data and any ancillary data
      (i.e., ignoring any header, CRC, or "side info" fields).

   An MP3 decoder processes each ADU independently.  The ADUs will
   generally vary in length, but their average length will, of course,
   be that of the of the MP3 frames (minus the length of the header,
   CRC, and "side info" fields).  (In MPEG literature, this ADU is
   sometimes referred to as a "bit reservoir".)

---

[Reverse engineered from MPlayer-1.0pre7/libmpdemux/mpeg_hdr.c]
[// based on libmpeg2/header.c by Aaron Holtzman <[EMAIL PROTECTED]>]
[which has the following license: ]
/*
 * header.c
 * Copyright (C) 2000-2003 Michel Lespinasse <[EMAIL PROTECTED]>
 * Copyright (C) 2003      Regis Duchesne <[EMAIL PROTECTED]>
 * Copyright (C) 1999-2000 Aaron Holtzman <[EMAIL PROTECTED]>
 *
 * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
 * See http://libmpeg2.sourceforge.net/ for updates.
 *
 * mpeg2dec is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * mpeg2dec is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *
 * Modified for use with MPlayer, see libmpeg-0.4.0.diff for the exact changes.
 * detailed CVS changelog at http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
 * $Id: header.c,v 1.18 2005/02/19 02:32:12 diego Exp $
 */

+----------------+----------------+----------------+----------------+
|                      |[D]|[B]|[E|  [F]  |[C]|G|  |[H]|   [I]      |
|  13 bits set [A]     |   |   |] |       |   |*|  |   |            |
+----------------+----------------+----------------+----------------+

[ following struct written by Peter Philipp (could be erroneous) based on ]
[ the information taken from the above mentioned files ]

/* network byte order */
struct mp3_header {
        u_int16_t first;
#define FIRST_13_BITS   0xFFE0          /* must be set */
#define HAS_CRC         0x1             /* if set CRC trails header */
#define HAS_LAYER3      0x2
#define HAS_LAYER2      0x4
#define HAS_LAYER1      0x6
#define HAS_MPEG1       0x8             /* if not set MPEG 2.0 leftshift 1 */
#define HAS_MPEG1ORMPEG2 0x16           /* if not set MPEG 2.5 */
        u_int16_t second;
#define HAS_MONO                0xC0    /* if set is MONO (1 channel) */
#define HAS_PADDING             0x200   /* if set has padding byte */
/* sample frequency if none set it's MPEG 1.0 */
#define HAS_SAMPLE_FQ1          0x400   /* MPEG 2.0 */
#define HAS_SAMPLE_FQ2          0x800   /* MPEG 2.5 */
/* frequency bits */
                                        /* MP3 layers 1, 2, 2.5 respectively */
#define HAS_FREQ_SLOT1          0x1000  /* 32, 32, 32   with lsf 32, 8, 8 */
#define HAS_FREQ_SLOT2          0x2000  /* 64, 48, 40   with lsf 48, 16, 16 */
#define HAS_FREQ_SLOT3          0x3000  /* 96, 56, 48   with lsf 56, 24, 24 */
#define HAS_FREQ_SLOT4          0x4000  /* 128, 64, 56  with lsf 64, 32, 32 */
#define HAS_FREQ_SLOT5          0x5000  /* 160, 80, 64  with lsf 80, 40, 40 */
#define HAS_FREQ_SLOT6          0x6000  /* 192, 96, 80  with lsf 96, 48, 48 */
#define HAS_FREQ_SLOT7          0x7000  /* 224, 112, 96 with lsf 112, 56, 56 */
#define HAS_FREQ_SLOT8          0x8000  /* 256, 128, 112 with lsf 128, 64, 64 */
#define HAS_FREQ_SLOT9          0x9000  /* 288, 160, 128 with lsf 144, 80, 80 */
#define HAS_FREQ_SLOT10         0xA000  /* 320, 192, 160 with lsf 160, 96, 96 */
#define HAS_FREQ_SLOT11         0xB000  /* 352, 224, 192 with lsf 176, 112, 112 
*/
#define HAS_FREQ_SLOT12         0xC000  /* 384, 256, 224 with lsf 192, 128, 128 
*/
#define HAS_FREQ_SLOT13         0xD000  /* 416, 320, 256 with lsf 224, 144, 144 
*/
#define HAS_FREQ_SLOT14         0xE000  /* 448, 384, 320 with lsf 256, 160, 160 
*/
#define HAS_FREQ_SLOT15         0xF000  /* not used */
};

---
[explanation of 4 byte header drawing]

[A] If the first 13 bits are not set, this is not a MP3 frame

[B] defines layer (2 bits) (something there must be set or not layer 1/2/3)
    0x1 = layer3
    0x2 = layer2
    0x3 = layer1

[C] sampling frequency valid are 0,1 and 2.
    0x0
    0x1
    0x2
    0x3 Invalid

[D] LSF (?) Leftshift Sampling Frequency (?)
    0x1 if set sampling frequency stays as is, if not set add 0x3 to it.
        lsf = 1 if not set else 0
    0x2 if set indicates MPEG 1.0 or MPEG 2.0, if not set MPEG 2.5

    if MPEG 2.5 add 0x6 to sampling frequency.
    lsf = 1.

static long freqs[9] = { 44100, 48000, 32000,   // MPEG 1.0
                         22050, 24000, 16000,   // MPEG 2.0
                         11025, 12000,  8000};  // MPEG 2.5

     The value of LSF determines the offset of the table-matrix above,
     if MPEG 1.0 (bits 0x1 and 0x2 set), if MPEG 2.0 (bit 0x2 set)      
     if MPEG 2.5 (bit 0x2 not set)

[E] if this bit is set, CRC trails 4 byte header (2 bytes CRC)

[F] 4 bits (1 nibble) indicating the bitrate index
        
[G] if set indicates there is padding...

[H] indicates whether stereo or mono
    0x0 stereo (2)
    0x1 stereo (2) if 0x2 unset
    0x2 stereo (2) if 0x1 unset
    0x3 mono

if lsf the ssize is 9 if Mono, else it's 17 if stereo
if lsf not set ssize is 17 if Mono else 32 if stereo

add 2 to ssize if CRC[E] is set 

[I] Unused.

FRAMESIZE is then determined by this TABLE-MATRIX (result is bits)

/* tabsel for layer 1, or layer 2 (layer 2.5 is part of layer 2) */
static int tabsel_123[2][3][16] = {
   { {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
     {0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,0},
     {0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,0} },

   { {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0},
     {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0},
     {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0} }
};

framesize = tabsel_123[lsf][layer-1][bitrate_index] * mult[layer-1];

In MP3's case this is only the following:

no lsf     { {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
with lsf   { {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0},

Take your pick from the bitrate index (should be 0 through 15, terminated with 
0)

In the end the result is multiplied by the multiplier table which depends
on the layer:

Layer 1 - 144000
Layer 2 - 144000
Layer 3 - 12000 

----

    framesize /= freqs[sampling_frequency]<<lsf;        

    Divide by "sampling frequency" frequency with leftshift if needed.
        
    if(layer==1)
      framesize = (framesize+padding)*4;
    else
      framesize += padding;

     Add padding byte if needed.


-- 
Here my ticker tape .signature #### My name is Peter Philipp #### lynx -dump 
"http://en.wikipedia.org/w/index.php?title=Pufferfish&oldid=20768394"; | sed -n 
131,137p #### http://centroid.eu #### So long and thanks for all the fish!!!

Reply via email to