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