Call us Toll-Free:
1-800-218-1525
Live ChatEmail us

 Sponsors

mp3 information v0 2

Code Wizard, 12-30-2006

Use the mp3_info class to discern a mp3 files properties, use the load_file to load both the ID3 tag information, and information derived from the header.

<?php
/*
This code (which is a work in progress) is based on the delphi code
"Audio Info" by Andrey V. Sorokin, email: anso@mail.ru
Thanx very much for the fantastic easy to read delphi code.
All credits go to him, all dislikes go to me: dextar@iprimus.com.au

Current Version: 0.2 beta
Added "not so accurate" song length code $mp3_info->seconds

Version: 0.1 beta
First release, had normal id3 tag + mpeg header info
*/

/*
ID3 tag extraction constants
*/
$ID3_V1_TAG_LEN = 128 ;

$GENRES = array (
"Blues","Classic Rock","Country","Dance","Disco","Funk","Grunge",
"Hip-Hop","Jazz","Metal","New Age","Oldies","Other","Pop",
"R&B","Rap","Reggae","Rock","Techno","Industrial", "Alternative",
"Ska","Death Metal","Pranks","Soundtrack","Euro-Techno","Ambient",
"Trip-Hop","Vocal","Jazz+Funk","Fusion","Trance","Classi cal",
"Instrumental","Acid","House","Game","Sound Clip","Gospel",
"Noise","AlternRock","Bass","Soul","Punk","Space", "Meditative",
"Instrumental Pop","Instrumental Rock","Ethnic","Gothic",
"Darkwave","Techno-Industrial","Electronic","Pop-Folk","Eurodance",
"Dream","Southern Rock","Comedy","Cult","Gangsta","Top 40",
"Christian Rap","Pop/Funk","Jungle","Native American","Cabaret",
"New Wave","Psychedelic","Rave","Showtunes","Trailer"," Lo-Fi",
"Tribal","Acid Punk","Acid Jazz","Polka","Retro","Musical",
"Rock & Roll","Hard Rock", // 79 standard genres
"Folk","Folk/Rock","National Folk","Swing","Fast Fusion",
"Bebob","Latin","Revival","Celtic","Bluegrass","Av antgarde",
"Gothic Rock","Progressive Rock","Psychedelic Rock",
"Symphonic Rock","Slow Rock","Big Band","Chorus","Easy Listening",
"Acoustic","Humour","Speech","Chanson","Opera","Ch amber Music",
"Sonata","Symphony","Booty Bass","Primus","Porn Groove",
"Satire","Slow Jam","Club","Tango","Samba","Folklore", // add
"Ballad","Power Ballad","Rhythmic Soul","Freestyle",
"Duet","Punk Rock","Drum Solo","Acapella","Euro-House",
"Dance Hall", "Goa", "Drum & Bass", "Club-House", "Hardcore",
"Terror", "Indie", "BritPop", "Negerpunk", "Polsk Punk", "Beat",
"Christian Gangs", "Heavy Metal", "Black Metal", "Crossover",
"Contemporary Ch?", "Cristian Rock", "Merengue", "Salsa",
"Thrash Metal", "Anime", "JPop", "Synthpop") ; // 0 .. 93h

/*
MP3 Header constants
*/
$MPEG_FRAME_HEADER_SIZE = 4 ;

$MPEG_VER_ERROR = 0 ;
$MPEG_VER_1 = 1 ;
$MPEG_VER_2 = 2 ;
$MPEG_VER_2_5 = 3 ;

$MPEG_VER_STR = array ('?!!', '1.0', '2.0', '2.5') ;

$MPEG_LAYER_ERROR = 0 ;
$MPEG_LAYER_I = 1 ;
$MPEG_LAYER_II = 2 ;
$MPEG_LAYER_III = 3 ;

$MPEG_LAYER_STR = array ('?!!', 'I', 'II', 'III') ;

$MPEG_BITRATE_ERROR = -1 ;
$MPEG_SAMPLINGRATE_ERROR = -1 ;

$MPEG_CHANNEL_STEREO = 0 ;
$MPEG_CHANNEL_JOINTSTEREO = 1 ;
$MPEG_CHANNEL_DUAL = 2 ;
$MPEG_CHANNEL_SINGLE = 3 ;

$MPEG_CHANNEL_STR = array ('Stereo', 'Joint Stereo', 'Dual', 'Mono') ;

$MPEG_EMPHASIS_NONE = 0 ;
$MPEG_EMPHASIS_50_15 = 1 ;
$MPEG_EMPHASIS_ERROR = 2 ;
$MPEG_EMPHASIS_CCIT_J_17 = 3 ;

$MPEG_EMPHASIS_STR = array ('None', '50/15 ms', '?!!', 'CCIT J.17') ;

/*
CLASS: mp3_info
DESCRIPTION:
Use the load_file method to load id3 tag & mpeg header information into the
class variables (For whats available, see below)
*/
class mp3_info {
/*
Public ID3 information variables
*/
var $id3ok ;
var $title ;
var $artist ;
var $album ;
var $year ;
var $comment ;
var $v1 ;
var $track ;
var $genreID ;
var $genre ;

/*
Public mp3 header variables
*/
var $mphok ;
var $sync ;
var $version ;
var $versionstr ;
var $layer ;
var $layerstr ;
var $crc ;
var $kbitrate ;
var $samplingrate ;
var $channelmode ;
var $channelmodestr ;
var $channelmodeext ;
var $channelmodeextstr ;
var $copyright ;
var $original ;
var $emphasis ;
var $emphasisstr ;
var $seconds ;

/*
FUNCTION: load_id3_tag
DESCRIPTION: Load id3 tag information
*/
function load_id3_tag ($filename) {
global $ID3_V1_TAG_LEN, $GENRES ;
if ((filesize ($filename) >= $ID3_V1_TAG_LEN) &&
($file = fopen ($filename, "r"))) {
fseek ($file, filesize ($filename) - $ID3_V1_TAG_LEN) ;
$buf = fread ($file, $ID3_V1_TAG_LEN) ;
fclose ($file) ;
} else {
$this->id3ok = false ;
} ;
if ((strlen ($buf) >= $ID3_V1_TAG_LEN) && (substr ($buf, 0, 3) == "TAG")) {
$this->id3ok = true ;
$this->title = chop (substr ($buf, 3, 30)) ;
$this->artist = chop (substr ($buf, 33, 30)) ;
$this->album = chop (substr ($buf, 63, 30)) ;
$this->year = chop (substr ($buf, 93, 4)) ;
$this->comment = chop (substr ($buf, 97, 30)) ;
if (($buf[97 + 28] == 0) && ($buf[97 + 29] != 0)) {
$this->v1 = false ;
$this->track = ord ($buf[97 + 29]) ;
} else {
$this->v1 = true ;
} ;
$this->genreID = ord ($buf[127]) ;
$this->genre = $GENRES[$this->genreID] ;
} else {
$this->id3ok = false ;
} ;
return $this->id3ok ;
}

/*
FUNCTION: load_mp3_header
DESCRIPTION: Load id3 tag information
*/
function load_mp3_header ($filename) {
global
$MPEG_FRAME_HEADER_SIZE, $MPEG_VER_2_5, $MPEG_VER_2, $MPEG_VER_1,
$MPEG_VER_ERROR, $MPEG_VER_STR, $MPEG_LAYER_STR, $MPEG_LAYER_ERROR,
$MPEG_BITRATE_ERROR, $MPEG_SAMPLINGRATE_ERROR, $MPEG_CHANNEL_STR,
$MPEG_CHANNEL_JOINTSTEREO, $MPEG_LAYER_III, $MPEG_EMPHASIS_STR ;
if ((filesize ($filename) >= $MPEG_FRAME_HEADER_SIZE) &&
($file = fopen ($filename, "r"))) {
$buf = fread ($file, $MPEG_FRAME_HEADER_SIZE) ;
fclose ($file) ;
$this->mphok = true ;
} else {
$this->mphok = false ;
} ;

//echo ord ($buf[0]) . " " . ord ($buf[1]) . " " . ord ($buf[2]) . " " . ord ($buf[3]) . "<BR>
" ;
//echo bin2hex ($buf[0]) . " " . bin2hex ($buf[1]) . " " . bin2hex ($buf[2]) . " " . bin2hex ($buf[3]) . "<BR>
";

//version, versionStr
if (strlen ($buf) == $MPEG_FRAME_HEADER_SIZE) {
switch ((ord ($buf[1]) >> 3) & 3) {
case 0: $this->version = $MPEG_VER_2_5 ; break ;
case 2: $this->version = $MPEG_VER_2 ; break ;
case 3: $this->version = $MPEG_VER_1 ; break ;
default: $this->version = $MPEG_VER_ERROR ; break ;
} ;
$this->versionstr = $MPEG_VER_STR[$this->version] ;
} ;

//layer, layerstr
$this->layer = (4 - ((ord ($buf[1]) >> 1) & 3)) & 3 ;
$this->layerstr = $MPEG_LAYER_STR[$this->layer] ;

//crc
$this->crc = (ord ($buf[1]) & 1) == 0 ;

//kbitrate (kbps)
$mpegkbitrate = array (
1 => array (//MPEG 1
1 => array (0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448, $MPEG_BITRATE_ERROR), //Layer I
2 => array (0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384, $MPEG_BITRATE_ERROR), //Layer II
3 => array (0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320, $MPEG_BITRATE_ERROR) //Layer III
),
2 => array (//MPEG 2
1 => array (0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256, $MPEG_BITRATE_ERROR), //Layer I)
2 => array (0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160, $MPEG_BITRATE_ERROR), //Layer II
3 => array (0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160, $MPEG_BITRATE_ERROR) //Layer III
),
3 => array (//MPEG 2.5
1 => array (0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256, $MPEG_BITRATE_ERROR), //Layer I)
2 => array (0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160, $MPEG_BITRATE_ERROR), //Layer II
3 => array (0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160, $MPEG_BITRATE_ERROR) //Layer III
)
) ;
if (($this->version != $MPEG_VER_ERROR) &&
($this->layer != $MPEG_LAYER_ERROR)) {
$this->kbitrate =
$mpegkbitrate[$this->version][$this->layer][(ord ($buf[2]) >> 4) & 0xF];
} else {
$this->kbitrate = $MPEG_BITRATE_ERROR ;
} ;

//samplingrate
$mpegsamplingrate = array (
1 => array (44100, 48000, 32000, $MPEG_SAMPLINGRATE_ERROR), //MPEG 1
2 => array (22050, 24000, 16000, $MPEG_SAMPLINGRATE_ERROR), //MPEG 2
3 => array (32000, 16000, 8000, $MPEG_SAMPLINGRATE_ERROR) //MPEG 2.5
) ;
if ($this->version != $MPEG_VER_ERROR) {
$this->samplingrate =
$mpegsamplingrate[$this->version][(ord ($buf[2]) >> 2) & 3] ;
} else {
$this->samplingrate = $MPEG_SAMPLINGRATE_ERROR ;
} ;

//channelmode
$this->channelmode = (ord ($buf[3]) >> 6) & 3 ;
$this->channelmodestr = $MPEG_CHANNEL_STR[$this->channelmode] ;

$this->channelmodeext = (ord ($buf[3]) >> 4) & 3 ;

$channelextstr = array (
array ('Bands 4-31', 'Bands 8-31', 'Bands 12-31', 'Bands 16-31'),
array ('', 'Intensity', 'MS', 'MS/Intensity')
) ;

if ($this->channelmode == $MPEG_CHANNEL_JOINTSTEREO) {
$this->channelmodeextstr = ($this->layer = $MPEG_LAYER_III) ?
$channelextstr[1][$this->channelmodeext] :
$channelextstr[0][$this->channelmodeext] ;
} else {
$this->channelmodeextstr = "" ;
} ;
//copyright
$this->copyright = ((ord ($buf[3]) >> 3) & 1) == 1 ;

//original
$this->original = ((ord ($buf[3]) >> 2) & 1) == 1 ;

//emphasis
$this->emphasis = ord ($buf[3]) & 3 ;
$this->emphasisstr = $MPEG_EMPHASIS_STR[$this->emphasis] ;

return $this->mphok ;
}

/*
FUNCTION: load_seconds
DESCRIPTION: Calculates the song length
PRE-REQUISETS(?): load_id3_tag + load_mp3_header should have been called
*/

function calc_seconds ($filename) {
global $ID3_V1_TAG_LEN, $MPEG_BIT_RATE_ERROR, $MPEG_FRAME_HEADER_SIZE ;
//LAST ONE IS UGLY ONE... SONG LENGTH...
//...SO I JUST USE THIS "NOT SO ACCURATE" FORMULA FOR NOW
if (($this->mphok) && ($this->kbitrate != $MPEG_BIT_RATE_ERROR)) {
$this->seconds = filesize ($filename) - $MPEG_FRAME_HEADER_SIZE ;
if ($this->id3ok) {$this->seconds -= $ID3_V1_TAG_LEN ; } ;
$this->seconds = round ($this->seconds * 8 / ($this->kbitrate * 1000)) ;
} else {
$this->seconds = 0 ;
} ;
return $this->seconds ;
}

/*
FUNCTION: load_file
DESCRIPTION: Loads id3 && mp3 header information returns true if BOTH OK.
*/
function load_file ($filename) {
$a = $this->load_id3_tag ($filename) ;
$b = $this->load_mp3_header ($filename) ;

$c = $this->calc_seconds ($filename) ;

return ($a && $b) ;
}
} ;
?>
Enjoyed this post?

Subscribe Now to receive new posts via Email as soon as they come out.

 Comments
Post your comments












Note: No link spamming! If your message contains link/s, it will NOT be published on the site before manually approved by one of our moderators.



About Us  |  Contact us  |  Privacy Policy  |  Terms & Conditions