Update of /cvsroot/freevo/freevo/src/audio/eyeD3
In directory sc8-pr-cvs1:/tmp/cvs-serv9033/eyeD3

Added Files:
        __init__.py binfuncs.py config.py frames.py mp3.py utils.py 
Log Message:
Renamed eyed3 to eyeD3 to match upstream naming conventions. 


--- NEW FILE: __init__.py ---
################################################################################
#
#  Copyright (C) 2002-2003  Travis Shirk <[EMAIL PROTECTED]>
#
#  This program 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.
#
#  This program 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
#
################################################################################

eyeD3Version = "0.5.0";
eyeD3Maintainer = "Travis Shirk <[EMAIL PROTECTED]>";

# Version constants
ID3_CURRENT_VERSION = 0x00; # The version of the linked tag, if any.
ID3_V1              = 0x10;
ID3_V1_0            = 0x11;
ID3_V1_1            = 0x12;
ID3_V2              = 0x20;
#ID3_V2_2            = 0x21; # All versions < v2.3 are obsolete.
ID3_V2_3            = 0x22;
ID3_V2_4            = 0x24;
#ID3_V2_5            = 0x28; # This does not seem imminent.
ID3_DEFAULT_VERSION = ID3_V2_4;
ID3_ANY_VERSION     = ID3_V1 | ID3_V2;

from ID3v2 import *


--- NEW FILE: binfuncs.py ---
################################################################################
#
#  Copyright (C) 2002-2003  Travis Shirk <[EMAIL PROTECTED]>
#  Copyright (C) 2001  Ryan Finne <[EMAIL PROTECTED]>
#
#  This program 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.
#
#  This program 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
#
################################################################################

# Accepts a string of bytes (chars) and returns an array of bits
# representing the bytes in big endian byte (Most significant byte/bit first)
# order.  Each byte can have it's higher bits ignored by passing an sz arg.
def bytes2bin(bytes, sz = 8):
   if sz < 1 or sz > 8:
      raise ValueError("Invalid sz value: " + str(sz));

   retVal = [];
   for b in bytes:
      bits = [];
      b = ord(b);
      while b > 0:
         bits.append(b & 1);
         b >>= 1;

      if len(bits) < sz:
         bits.extend([0] * (sz - len(bits)));
      elif len(bits) > sz:
         bits = bits[:sz];

      # Big endian byte order.
      bits.reverse();
      retVal.extend(bits);

   if len(retVal) == 0:
      retVal = [0];
   return retVal;

# Convert am array of bits (MSB first) into a string of characters.
def bin2bytes(x):
   bits = [];
   bits.extend(x);
   bits.reverse();

   i = 0;
   out = '';
   multi = 1;
   ttl = 0;
   for b in bits:
      i += 1;
      ttl += b * multi;
      multi *= 2;
      if i == 8:
         i = 0;
         out += chr(ttl);
         multi = 1;
         ttl = 0;

   if multi > 1:
      out += chr(ttl);

   out = list(out);
   out.reverse();
   out = ''.join(out);
   return out;

# Convert and array of "bits" (MSB first) to it's decimal value.
def bin2dec(x):
   bits = [];
   bits.extend(x);
   bits.reverse();

   multi = 1;
   value = 0;
   for b in bits:
      value += b * multi;
      multi *= 2;
   return value;

# Convert a decimal value to an array of bits (MSB first), optionally
# padding the overall size to p bits.
def dec2bin(n, p = 0):
   retVal = [];

   while n > 0:
      retVal.append(n & 1);
      n >>= 1;

   if p > 0:
      retVal.extend([0] * (p - len(retVal)));
   retVal.reverse();
   return retVal;

# Convert a list of bits (MSB first) to a synch safe list of bits (section 6.2
# of the ID3 2.4 spec).
def bin2synchsafe(x):
   if len(x) > 32 or bin2dec(x) > 268435456:   # 2^28
      raise ValueError("Invalid value");
   elif len(x) < 8:
      return x;

   n = bin2dec(x);
   bites = "";
   bites += chr((n >> 21) & 0x7f);
   bites += chr((n >> 14) & 0x7f);
   bites += chr((n >>  7) & 0x7f);
   bites += chr((n >>  0) & 0x7f);
   bits = bytes2bin(bites);
   if len(bits) < 32:
      bits = ([0] * (32 - len(x))) + bits;

   return bits;

--- NEW FILE: config.py ---
#
#  Copyright (C) 2002  Travis Shirk <[EMAIL PROTECTED]>
#
#  This program 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.
#
#  This program 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
#
version = "0.2.0"

--- NEW FILE: frames.py ---
################################################################################
#
#  Copyright (C) 2002-2003  Travis Shirk <[EMAIL PROTECTED]>
#  Copyright (C) 2001  Ryan Finne <[EMAIL PROTECTED]>
#
#  This program 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.
#
#  This program 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
#
[...1210 lines suppressed...]
   # multiple times in a tag.  To sum it all up htis method returns
   # string or None when indexed using an integer, and a 0 to N length
   # list of strings when indexed with a frame ID.
   #
   # Throws IndexError and TypeError.
   def __getitem__(self, key):
      if isinstance(key, int):
         if key >= 0 and key < len(self):
            return list.__getitem__(self, key);
         else:
            raise IndexError("FrameSet index out of range");
      elif isinstance(key, str):
         retList = list();
         for f in self:
            if f.header.id == key:
               retList.append(f);
         return retList;
      else:
         raise TypeError("FrameSet key must be type int or string");


--- NEW FILE: mp3.py ---
################################################################################
#
#  Copyright (C) 2002-2003  Travis Shirk <[EMAIL PROTECTED]>
#
#  This program 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.
#
#  This program 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
#
################################################################################
from eyeD3.binfuncs import *;
from eyeD3.utils import *;

#######################################################################
class Mp3Exception:
   msg = "";

   def __init__(self, msg):
      self.msg = msg;

   def __str__(self):
      return self.msg;


#                   MPEG1  MPEG2  MPEG2.5
SAMPLE_FREQ_TABLE = ((44100, 22050, 11025),
                     (48000, 24000, 12000),
                     (32000, 16000, 8000),
                     (None,  None,  None));

#              V1/L1  V1/L2 V1/L3 V2/L1 V2/L2&L3 
BIT_RATE_TABLE = ((0,    0,    0,    0,    0),
                  (32,   32,   32,   32,   8),
                  (64,   48,   40,   48,   16),
                  (96,   56,   48,   56,   24),
                  (128,  64,   56,   64,   32),
                  (160,  80,   64,   80,   40),
                  (192,  96,   80,   96,   44),
                  (224,  112,  96,   112,  56),
                  (256,  128,  112,  128,  64),
                  (288,  160,  128,  144,  80),
                  (320,  192,  160,  160,  96),
                  (352,  224,  192,  176,  112),
                  (384,  256,  224,  192,  128),
                  (416,  320,  256,  224,  144),
                  (448,  384,  320,  256,  160),
                  (None, None, None, None, None));

#                             L1    L2    L3
TIME_PER_FRAME_TABLE = (None, 384, 1152, 1152);

# Emphasis constants
EMPHASIS_NONE = "None";
EMPHASIS_5015 = "50/15 ms";
EMPHASIS_CCIT = "CCIT J.17";

# Mode constants
MODE_STEREO              = "Stereo";
MODE_JOINT_STEREO        = "Joint stereo";
MODE_DUAL_CHANNEL_STEREO = "Dual channel stereo";
MODE_MONO                = "Mono";

# Flag bits
FRAMES_FLAG    = 0x0001
BYTES_FLAG     = 0x0002
TOC_FLAG       = 0x0004
VBR_SCALE_FLAG = 0x0008

#######################################################################
def computeTimePerFrame(frameHeader):
   tpf = TIME_PER_FRAME_TABLE[frameHeader.layer];
   tpf = float(tpf) / float(frameHeader.sampleFreq);
   return tpf;

#######################################################################
class Header:
   version = float();
   layer = int();
   errorProtection = 0;
   bitRate = int();
   playTime = long();
   sampleFreq = int();
   padding = 0;
   privateBit = 0;
   copyright = 0;
   original = 0;
   emphasis = str();
   mode = str();
   # This value is left as is: 0 <= modeExtension <= 3.  Consult the
   # mp3 spec here http://www.dv.co.yu/mpgscript/mpeghdr.htm if you wish to 
   # interpret it.
   modeExtension = 0;

   # Pass in a 4 byte integer to determine if it matches a valid mp3 frame
   # header.
   def isValid(self, header):
      # Test for the mp3 frame sync: 11 set bits.
      if (header & 0xffe00000L) != 0xffe00000L:
         return 0;
      if not ((header >> 17) & 3):
         return 0;
      if ((header >> 12) & 0xf) == 0xf:
         return 0;
      if not ((header >> 12) & 0xf):
         return 0;
      if ((header >> 10) & 0x3) == 0x3:
         return 0;
      if (((header >> 19) & 1) == 1) and (((header >> 17) & 3) == 3) and \
         (((header >> 16) & 1) == 1):
         return 0;
      if (header & 0xffff0000L) == 0xfffe0000L:
         return 0;

      return 1;

   # This may throw an Mp3Exception if the header is malformed.
   def decode(self, header):
      # MPEG audio version from bits 19 and 20.
      if not header & (1 << 20) and header & (1 << 19):
         raise Mp3Exception("Illegal MPEG audio version");
      elif not header & (1 << 20) and not header & (1 << 19):
         self.version = 2.5;
      else:
         if not header & (1 << 19):
            self.version = 2.0;
         else:
            self.version = 1.0;

      
      # MPEG audio layer from bits 18 and 17.
      if not header & (1 << 18) and not header & (1 << 17):
         raise Mp3Exception("Illegal MPEG layer value");
      elif not header & (1 << 18) and header & (1 << 17):
         self.layer = 3;
      elif header & (1 << 18) and not header & (1 << 17):
         self.layer = 2;
      else:
         self.layer = 1;

      # Decode some simple values.
      self.errorProtection = not (header >> 16) & 0x1;
      self.padding = (header >> 9) & 0x1;
      self.privateBit = (header >> 8) & 0x1;
      self.copyright = (header >> 3) & 0x1;
      self.original = (header >> 2) & 0x1;

      # Obtain sampling frequency.
      sampleBits = (header >> 10) & 0x3;
      if self.version == 2.5:
         freqCol = 2;
      else:
         freqCol = int(self.version - 1);
      self.sampleFreq = SAMPLE_FREQ_TABLE[sampleBits][freqCol];
      if not self.sampleFreq:
         raise Mp3Exception("Illegal MPEG sampling frequency");


      # Compute bitrate.
      bitRateIndex = (header >> 12) & 0xf;
      if int(self.version) == 1 and self.layer == 1:
         bitRateCol = 0;
      elif int(self.version) == 1 and self.layer == 2:
         bitRateCol = 1;
      elif int(self.version) == 1 and self.layer == 3:
         bitRateCol = 2;
      elif int(self.version) == 2 and self.layer == 1:
         bitRateCol = 3;
      elif int(self.version) == 2 and (self.layer == 2 or \
                                       self.layer == 3):
         bitRateCol = 4;
      else:
         raise Mp3Exception("Mp3 version %f and layer %d is an invalid "\
                            "combination" % (self.version, self.layer));
      self.bitRate = BIT_RATE_TABLE[bitRateIndex][bitRateCol];
      if self.bitRate == None:
         raise Mp3Exception("Invalid bit rate");
      # We know know the bit rate specified in this frame, but if the file
      # is VBR we need to obtain the average from the Xing header.
      # This is done by the caller since right now all we have is the frame
      # header.

      # Emphasis; whatever that means??
      emph = header & 0x3;
      if emph == 0:
         self.emphasis = EMPHASIS_NONE;
      elif emph == 1:
         self.emphasis = EMPHASIS_5015;
      elif emph == 2:
         self.emphasis = EMPHASIS_CCIT;
      else:
         raise Mp3Exception("Illegal mp3 emphasis value");

      # Channel mode.
      modeBits = (header >> 6) & 0x3;
      if modeBits == 0:
         self.mode = MODE_STEREO;
      elif modeBits == 1:
         self.mode = MODE_JOINT_STEREO;
      elif modeBits == 2:
         self.mode = MODE_DUAL_CHANNEL_STEREO;
      else:
         self.mode = MODE_MONO;
      self.modeExtension = (header >> 4) & 0x3; 

      # Layer II has restrictions wrt to mode and bit rate.  This code
      # enforces them.
      if self.layer == 2:
         m = self.mode;
         br = self.bitRate;
         if (br == 32 or br == 48 or br == 56 or br == 80) and \
            (m != MODE_MONO):
            raise Mp3Exception("Invalid mode/bitrate combination for layer "\
                               "II");
         if (br == 224 or br == 256 or br == 320 or br == 384) and \
            (m == MODE_MONO):
            raise Mp3Exception("Invalid mode/bitrate combination for layer "\
                               "II");

      br = self.bitRate * 1000;
      sf = self.sampleFreq;
      p  = self.padding;
      if self.layer == 1:
         # Layer 1 uses 32 bit slots for padding.
         p  = self.padding * 4;
         self.frameLength = int((((12 * br) / sf) + p) * 4);
      else:
         # Layer 2 and 3 uses 8 bit slots for padding.
         p  = self.padding * 1;
         self.frameLength = int(((144 * br) / sf) + p);

      # Dump the state.
      TRACE_MSG("MPEG audio version: " + str(self.version));
      TRACE_MSG("MPEG audio layer: " + ("I" * self.layer));
      TRACE_MSG("MPEG sampling frequency: " + str(self.sampleFreq));
      TRACE_MSG("MPEG bit rate: " + str(self.bitRate));
      TRACE_MSG("MPEG channel mode: " + self.mode);
      TRACE_MSG("MPEG channel mode extension: " + str(self.modeExtension));
      TRACE_MSG("MPEG CRC error protection: " + str(self.errorProtection));
      TRACE_MSG("MPEG original: " + str(self.original));
      TRACE_MSG("MPEG copyright: " + str(self.copyright));
      TRACE_MSG("MPEG private bit: " + str(self.privateBit));
      TRACE_MSG("MPEG padding: " + str(self.padding));
      TRACE_MSG("MPEG emphasis: " + str(self.emphasis));
      TRACE_MSG("MPEG frame length: " + str(self.frameLength));

#######################################################################
class XingHeader:
   numFrames = int();
   numBytes = int();
   toc = [0] * 100;
   vbrScale = int();

   # Pass in the first mp3 frame from the file as a byte string.
   # If an Xing header is present in the file it'll be in the first mp3
   # frame.  This method returns true if the Xing header is found in the
   # frame, and false otherwise.
   def decode(self, frame):
      # mp3 version
      id      = (ord(frame[1]) >> 3) & 0x1;
      # channel mode.
      mode    = (ord(frame[3]) >> 6) & 0x3;

      # Find the start of the Xing header.
      if id:
         if mode != 3:
            pos = 32 + 4;
         else:
            pos = 17 + 4;
      else:
         if mode != 3:
            pos = 17 + 4;
         else:
            pos = 9 + 4;
      if frame[pos] != 'X' or frame[pos + 1] != 'i' or \
         frame[pos + 2] != 'n' or frame[pos + 3] != 'g':
         return 0;
      TRACE_MSG("Xing header detected");
      pos += 4;

      # Read Xing flags.
      headFlags = bin2dec(bytes2bin(frame[pos:pos + 4]));
      pos += 4;
      TRACE_MSG("Xing header flags: 0x%x" % headFlags);

      # Read frames header flag and value if present
      if headFlags & FRAMES_FLAG:
         self.numFrames = bin2dec(bytes2bin(frame[pos:pos + 4]));
         pos += 4;
         TRACE_MSG("Xing numFrames: %d" % self.numFrames);

      # Read bytes header flag and value if present
      if headFlags & BYTES_FLAG:
         self.numBytes = bin2dec(bytes2bin(frame[pos:pos + 4]));
         pos += 4;
         TRACE_MSG("Xing numBytes: %d" % self.numBytes);

      # Read TOC header flag and value if present
      if headFlags & TOC_FLAG:
         i = 0;
         self.toc = frame[pos:pos + 100];
         pos += 100;
         TRACE_MSG("Xing TOC (100 bytes): PRESENT");
      else:
         TRACE_MSG("Xing TOC (100 bytes): NOT PRESENT");

      # Read vbr scale header flag and value if present
      if headFlags & VBR_SCALE_FLAG:
         self.vbrScale = bin2dec(bytes2bin(frame[pos:pos + 4]));
         pos += 4;
         TRACE_MSG("Xing vbrScale: %d" % self.vbrScale);

      return 1;

--- NEW FILE: utils.py ---
#
#  Copyright (C) 2002  Travis Shirk <[EMAIL PROTECTED]>
#
#  This program 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.
#
#  This program 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
#
version = "0.4.0";
maintainer = "Travis Shirk <[EMAIL PROTECTED]>";

TRACE = 0;
prefix = "eyeD3 trace> ";

def TRACE_MSG(msg):
   if TRACE:
      print prefix + msg;
################################################################################
#  Copyright (C) 2003  Travis Shirk <[EMAIL PROTECTED]>
#
#  This program 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.
#
#  This program 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
#
#  $Id: utils.py,v 1.1 2003/06/09 18:01:45 outlyer Exp $
################################################################################
from eyeD3 import *;

def versionsToConstant(v):
   major = v[0];
   minor = v[1];
   rev = v[2];
   if major == 1:
      if minor == 0:
         return ID3_V1_0;
      elif minor == 1:
         return ID3_V1_1;
   elif major == 2:
      if minor == 3:
         return ID3_V2_3;
      elif minor == 4:
         return ID3_V2_4;
   raise str("Invalid ID3 version: %s" % str(v));

def versionToString(v):
   if v & ID3_V1:
      if v == ID3_V1_0:
         return "v1.0";
      elif v == ID3_V1_1:
         return "v1.1";
      elif v == ID3_V1:
         return "v1.x";
   elif v & ID3_V2:
      if v == ID3_V2_3:
         return "v2.3";
      elif v == ID3_V2_4:
         return "v2.4";
      elif v == ID3_V2:
         return "v2.x";

   if v == ID3_ANY_VERSION:
      return "v1.x/v2.x";
   raise str("versionToString - Invalid ID3 version constant: %s" % hex(v));

def constantToVersions(v):
   if v & ID3_V1:
      if v == ID3_V1_0:
         return [1, 0, 0];
      elif v == ID3_V1_1:
         return [1, 1, 0];
      elif v == ID3_V1:
         return [1, 1, 0];
   elif v & ID3_V2:
      if v == ID3_V2_3:
         return [2, 3, 0];
      elif v == ID3_V2_4:
         return [2, 4, 0];
      elif v == ID3_V2:
         return [2, 4, 0];
   raise str("constantToVersions - Invalid ID3 version constant: %s" % hex(v));

################################################################################
TRACE = 0;
prefix = "eyeD3 trace> ";
def TRACE_MSG(msg):
   if TRACE:
      print prefix + msg;




-------------------------------------------------------
This SF.net email is sponsored by:  Etnus, makers of TotalView, The best
thread debugger on the planet. Designed with thread debugging features
you've never dreamed of, try TotalView 6 free at www.etnus.com.
_______________________________________________
Freevo-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to