<?php

// ----------------------------------------------------------------------
// MP3 Info Function 
//
// $infoarray = mp3info(filename)
// Returns associative array with MP3 info
// errorcode 1 if file not found
//           2 if not an mp3-file
// See bottom for sample usage.
//
// Based on code by Chester@hackster.com
// found on PHP Code Exchange http://px.sklar.com
// This code made possible by Jim Beam black label bourbon.
// and the info found on http://www.dv.co.yu/mpgscript/mpeghdr.htm .
//
// Marcel Hicking has added the MPEG Audio Tag ID part,
// streamlined the code slightly and made changes to return an
// associative array instead of a scalar (numeric) one.
//
// ----------------------------------------------------------------------



function mp3info($filename) {

	// MH: MPEG Audio Tag ID3v1 stuff
	$genre[0]="Blues";
	$genre[1]="Classic Rock";
	$genre[2]="Country";
	$genre[3]="Dance";
	$genre[4]="Disco";
	$genre[5]="Funk";
	$genre[6]="Grunge";
	$genre[7]="Hip-Hop";
	$genre[8]="Jazz";
	$genre[9]="Metal";
	$genre[10]="New Age";
	$genre[11]="Oldies";
	$genre[12]="Other";
	$genre[13]="Pop";
	$genre[14]="R&amp;B";
	$genre[15]="Rap";
	$genre[16]="Reggae";
	$genre[17]="Rock";
	$genre[18]="Techno";
	$genre[19]="Industrial";
	$genre[20]="Alternative";
	$genre[21]="Ska";
	$genre[22]="Death Metal";
	$genre[23]="Pranks";
	$genre[24]="Soundtrack";
	$genre[25]="Euro-Techno";
	$genre[26]="Ambient";
	$genre[27]="Trip-Hop";
	$genre[28]="Vocal";
	$genre[29]="Jazz+Funk";
	$genre[30]="Fusion";
	$genre[31]="Trance";
	$genre[32]="Classical";
	$genre[33]="Instrumental";
	$genre[34]="Acid";
	$genre[35]="House";
	$genre[36]="Game";
	$genre[37]="Sound Clip";
	$genre[38]="Gospel";
	$genre[39]="Noise";
	$genre[40]="AlternRock";
	$genre[41]="Bass";
	$genre[42]="Soul";
	$genre[43]="Punk";
	$genre[44]="Space";
	$genre[45]="Meditative";
	$genre[46]="Instrumental Pop";
	$genre[47]="Instrumental Rock";
	$genre[48]="Ethnic";
	$genre[49]="Gothic";
	$genre[50]="Darkwave";
	$genre[51]="Techno-Industrial";
	$genre[52]="Electronic";
	$genre[53]="Pop-Folk";
	$genre[54]="Eurodance";
	$genre[55]="Dream";
	$genre[56]="Southern Rock";
	$genre[57]="Comedy";
	$genre[58]="Cult";
	$genre[59]="Gangsta";
	$genre[60]="Top 40";
	$genre[61]="Christian Rap";
	$genre[62]="Pop/Funk";
	$genre[63]="Jungle";
	$genre[64]="Native American";
	$genre[65]="Cabaret";
	$genre[66]="New Wave";
	$genre[67]="Psychadelic";
	$genre[68]="Rave";
	$genre[69]="Showtunes";
	$genre[70]="Trailer";
	$genre[71]="Lo-Fi";
	$genre[72]="Tribal";
	$genre[73]="Acid Punk";
	$genre[74]="Acid Jazz";
	$genre[75]="Polka";
	$genre[76]="Retro";
	$genre[77]="Musical";
	$genre[78]="Rock &amp; Roll";
	$genre[79]="Hard Rock";
	# WinAmp expanded the above with the following:
	$genre[80]="Folk";
	$genre[81]="Folk-Rock";
	$genre[82]="National Folk";
	$genre[83]="Swing";
	$genre[84]="Fast Fusion";
	$genre[85]="Bebob";
	$genre[86]="Latin";
	$genre[87]="Revival";
	$genre[88]="Celtic";
	$genre[89]="Bluegrass";
	$genre[90]="Avantgarde";
	$genre[91]="Gothic Rock";
	$genre[92]="Progressive Rock";
	$genre[93]="Psychedelic Rock";
	$genre[94]="Symphonic Rock";
	$genre[95]="Slow Rock";
	$genre[96]="Big Band";
	$genre[97]="Chorus";
	$genre[98]="Easy Listening";
	$genre[99]="Acoustic";
	$genre[100]="Humour";
	$genre[101]="Speech";
	$genre[102]="Chanson";
	$genre[103]="Opera";
	$genre[104]="Chamber Music";
	$genre[105]="Sonata";
	$genre[106]="Symphony";
	$genre[107]="Booty Brass";
	$genre[108]="Primus";
	$genre[109]="Porn Groove";
	$genre[110]="Satire";
	$genre[111]="Slow Jam";
	$genre[112]="Club";
	$genre[113]="Tango";
	$genre[114]="Samba";
	$genre[115]="Folklore";
	$genre[116]="Ballad";
	$genre[117]="Poweer Ballad";
	$genre[118]="Rhytmic Soul";
	$genre[119]="Freestyle";
	$genre[120]="Duet";
	$genre[121]="Punk Rock";
	$genre[122]="Drum Solo";
	$genre[123]="A Capela";
	$genre[124]="Euro-House";
	$genre[125]="Dance Hall";


	// Ensure file exists!
	if (!$fp = @fopen($filename,"rb")) {
		return (1);
	}

	// Checking to make sure I can find Frame Sync
	while (!feof($fp)) {
			$tmp=fgetc($fp);
			if (ord($tmp)==255) {
				$tmp=fgetc($fp);
				if (substr((decbin(ord($tmp))),0,3)=="111") {
					break;
				}
			}
	} // eo while

	// If end of file is reached before Frame Sync is found then bail...
	if (feof($fp)) {
		fclose($fp);
		return (2);
	}

	// We have declared all engines go.

	// Assign filesize
	$fred['filesize']=filesize($filename);

	// Assign all important information to $bitstream variable.
	$inf=decbin(ord($tmp));
	$inf=sprintf("%08d",$inf);
	$bitstream = $inf;
	$tmp=fgetc($fp);
	$inf=decbin(ord($tmp));
	$inf=sprintf("%08d",$inf);
	$bitstream = $bitstream.$inf;
	$tmp=fgetc($fp);
	$inf=decbin(ord($tmp));
	$inf=sprintf("%08d",$inf);
	$bitstream = $bitstream.$inf;

	// $bitstream now totals the 3 important bytes of the header of this frame.

	// Determine Version of Mpeg.
	switch (substr($bitstream,3,2)) {
			case "00":
				$fred['version']="2.5";
				break;
			case "01":
				$fred['version']="0";
				break;
			case "10":
				$fred['version']="2";
				break;
			case "11":
				$fred['version']="1";
				break;
	} // eo switch

	// Determine Layer.
	switch (substr($bitstream,5,2)) {
			case "00":
				$fred['layer']="0";
				break;
			case "01":
				$fred['layer']="3";
				break;
			case "10":
				$fred['layer']="2";
				break;
			case "11":
				$fred['layer']="1";
				break;
	} // eo switch

	// Determine CRC checking enabled / disabled 1==disabled
	$fred['crc'] = substr($bitstream,7,1);

	// Determine Bitrate
	// Setting an index variable ... trust me in this
	// state tis the only way I can think of doing it...
	if (($fred['version']=="1")&($fred['layer']=="1")) {
			$index="1";
	} elseif (($fred['version']=="1")&($fred['layer']=="2")) {
			$index="2";
	}
	elseif ($fred['version']=="1") {
			$index="3";
	}
	elseif ($fred['layer']=="1") {
			$index="4";
	}
	else	{
			$index="5";
	}

	switch (substr($bitstream,8,4)) {
			case "0000":
				$fred['bitrate']="free";
				break;
			case "0001":
				if (($fred['layer']>1)and($fred['version']>1))
					{
						$fred['bitrate']="8000";
					}
				else
					{
						$fred['bitrate']="32000";
					}
				break;
			case "0010":
				switch ($index)
					{
						case "1":
							$fred['bitrate']="64000";
							break;
						case "2":
							$fred['bitrate']="48000";
							break;
						case "3":
							$fred['bitrate']="40000";
							break;
						case "4":
							$fred['bitrate']="48000";
							break;
						case "5":
							$fred['bitrate']="16000";
							break;
					}
				break;
			case "0011":
				switch ($index)
					{
						case "1":
							$fred['bitrate']="96000";
							break;
						case "2":
							$fred['bitrate']="56000";
							break;
						case "3":
							$fred['bitrate']="48000";
							break;
						case "4":
							$fred['bitrate']="56000";
							break;
						case "5":
							$fred['bitrate']="24000";
							break;
					}
				break;
			case "0100":
				switch ($index)
					{
						case "1":
							$fred['bitrate']="128000";
							break;
						case "2":
							$fred['bitrate']="64000";
							break;
						case "3":
							$fred['bitrate']="56000";
							break;
						case "4":
							$fred['bitrate']="64000";
							break;
						case "5":
							$fred['bitrate']="32000";
							break;
					}
				break;
			case "0101":
				switch ($index)
					{
						case "1":
							$fred['bitrate']="160000";
							break;
						case "2":
							$fred['bitrate']="80000";
							break;
						case "3":
							$fred['bitrate']="64000";
							break;
						case "4":
							$fred['bitrate']="80000";
							break;
						case "5":
							$fred['bitrate']="40000";
							break;
					}
				break;
			case "0110":
				switch ($index)
					{
						case "1":
							$fred['bitrate']="192000";
							break;
						case "2":
							$fred['bitrate']="96000";
							break;
						case "3":
							$fred['bitrate']="80000";
							break;
						case "4":
							$fred['bitrate']="96000";
							break;
						case "5":
							$fred['bitrate']="48000";
							break;
					}
				break;
			case "0111":
				switch ($index)
					{
						case "1":
							$fred['bitrate']="224000";
							break;
						case "2":
							$fred['bitrate']="112000";
							break;
						case "3":
							$fred['bitrate']="96000";
							break;
						case "4":
							$fred['bitrate']="112000";
							break;
						case "5":
							$fred['bitrate']="56000";
							break;
					}
				break;
			case "1000":
				switch ($index)
					{
						case "1":
							$fred['bitrate']="256000";
							break;
						case "2":
							$fred['bitrate']="128000";
							break;
						case "3":
							$fred['bitrate']="112000";
							break;
						case "4":
							$fred['bitrate']="128000";
							break;
						case "5":
							$fred['bitrate']="64000";
							break;
					}
				break;
			case "1001":
				switch ($index)
					{
						case "1":
							$fred['bitrate']="288000";
							break;
						case "2":
							$fred['bitrate']="160000";
							break;
						case "3":
							$fred['bitrate']="128000";
							break;
						case "4":
							$fred['bitrate']="144000";
							break;
						case "5":
							$fred['bitrate']="80000";
							break;
					}
				break;
			case "1010":
				switch ($index)
					{
						case "1":
							$fred['bitrate']="320000";
							break;
						case "2":
							$fred['bitrate']="192000";
							break;
						case "3":
							$fred['bitrate']="160000";
							break;
						case "4":
							$fred['bitrate']="160000";
							break;
						case "5":
							$fred['bitrate']="96000";
							break;
					}
				break;
			case "1011":
				switch ($index)
					{
						case "1":
							$fred['bitrate']="352000";
							break;
						case "2":
							$fred['bitrate']="224000";
							break;
						case "3":
							$fred['bitrate']="192000";
							break;
						case "4":
							$fred['bitrate']="176000";
							break;
						case "5":
							$fred['bitrate']="112000";
							break;
					}
				break;
			case "1100":
				switch ($index)
					{
						case "1":
							$fred['bitrate']="384000";
							break;
						case "2":
							$fred['bitrate']="256000";
							break;
						case "3":
							$fred['bitrate']="224000";
							break;
						case "4":
							$fred['bitrate']="192000";
							break;
						case "5":
							$fred['bitrate']="128000";
							break;
					}
				break;
			case "1101":
				switch ($index)
					{
						case "1":
							$fred['bitrate']="416000";
							break;
						case "2":
							$fred['bitrate']="320000";
							break;
						case "3":
							$fred['bitrate']="256000";
							break;
						case "4":
							$fred['bitrate']="224000";
							break;
						case "5":
							$fred['bitrate']="144000";
							break;
					}
				break;
			case "1110":
				switch ($index)
					{
						case "1":
							$fred['bitrate']="448000";
							break;
						case "2":
							$fred['bitrate']="384000";
							break;
						case "3":
							$fred['bitrate']="320000";
							break;
						case "4":
							$fred['bitrate']="256000";
							break;
						case "5":
							$fred['bitrate']="160000";
							break;
					}
				break;
			case "1111":
				$fred['bitrate']="bad";
				break;
	} // eo switch

	// Determine Sample Rate
	switch ($fred['version']) {
			case "1":
				switch (substr($bitstream,12,2)) {
						case "00":
							$fred['samplerate']="44100";
							break;
						case "01":
							$fred['samplerate']="48000";
							break;
						case "10":
							$fred['samplerate']="32000";
							break;
						case "11":
							$fred['samplerate']="reserved";
							break;
				} // eo switch
				break;
			case "2":
				switch (substr($bitstream,12,2)) {
						case "00":
							$fred['samplerate']="22050";
							break;
						case "01":
							$fred['samplerate']="24000";
							break;
						case "10":
							$fred['samplerate']="16000";
							break;
						case "11":
							$fred['samplerate']="reserved";
							break;
				} // eo switch
				break;
			case "2.5":
				switch (substr($bitstream,12,2)) {
						case "00":
							$fred['samplerate']="11025";
							break;
						case "01":
							$fred['samplerate']="12000";
							break;
						case "10":
							$fred['samplerate']="8000";
							break;
						case "11":
							$fred['samplerate']="reserved";
							break;
				} // eo switch
				break;
	} // eo switch

	// Determine whether padding is set on. 0 == no & 1 == yes
	$padding = substr($bitstream,14,1);

	// Determine the private bit's value. Dont know what for though?
	$private = substr($bitstream,15,1);

	// Determine Channel mode
	switch (substr($bitstream,16,2)) {
			case "00":
				$fred['cmode']="Stereo";
				break;
			case "01":
				$fred['cmode']="Joint Stereo";
				break;
			case "10":
				$fred['cmode']="Dual Channel";
				break;
			case "11":
				$fred['cmode']="Mono";
				break;
	} // eo switch
		
	/*
	// Determine Mode Extension, actually who cares for the moment
	switch (substr($bitstream,18,2)) {
			case "00":
				$mext="0";
				break;
			case "01":
				$mext="3";
				break;
			case "10":
				$mext="2";
				break;
			case "11":
				$mext="1";
				break;
	} // eo switch
	*/
		
	// Determine Copyright 0 == no & 1 == yes
	$fred['copyright'] = substr($bitstream,20,1);

	// Determine Original 0 == Copy & 1 == Original
	$fred['original'] = substr($bitstream,21,1);

	// Determine Emphasis
	switch (substr($bitstream,22,2)) {
			case "00":
				$fred['emphasis']="none";
				break;
			case "01":
				$fred['emphasis']="50/15 ms";
				break;
			case "10":
				$fred['emphasis']="reserved";
				break;
			case "11":
				$fred['emphasis']="CCIT J.17";
				break;
	} // eo switch

	// Determine number of frames.
	if ((isset($fred['samplerate'])) and (isset($fred['bitrate']))) {
		if ($fred['layer']=="1") {
			$fred['frames']=floor($fred['filesize']/(floor(((12*$fred['bitrate'])/($fred['samplerate']+$padding))*4)));	
		} else {
			$fred['frames']=floor($fred['filesize']/(floor((144*$fred['bitrate'])/($fred['samplerate']))));
		} // eo if
		
		// Determine number of seconds in song.
		if ($fred['layer']=="1") {
			$fred['time']=floor((384/$fred['samplerate'])*$fred['frames']);
		} else {
			$fred['time']=floor((1152/$fred['samplerate'])*$fred['frames']);
		} // eo if
	} // eo if




	// MH: Get MPEG Audio Tag info

	fseek($fp,$fred['filesize']-128);
	$tag=fread($fp,128);
	if (substr($tag,0,3) == "TAG") {
		$fred['tagtitle']=substr($tag,3,30);
		$fred['tagartist']=substr($tag,33,30);
		$fred['tagalbum']=substr($tag,63,30);
		$fred['tagyear']=substr($tag,93,4);
		$fred['tagcomment']=substr($tag,97,30);
		$fred['taggenreid']=ord(substr($tag,127,1));
		$fred['taggenrename']= ( $fred['taggenreid'] >= 0 && $fred['taggenreid'] <= 125) ? $genre[$fred['taggenreid']] : "(unkown)";
	} // has audio tag ?

	fclose($fp);

	$fred['filename']=$filename;
	return($fred);

} // eo fkt mp3info



function thdots($s,$delim=".") {
	while ($s) {
		// print "s: $s\n";
		$d = substr($s,strlen($s)-3,strlen($s)) .$delim.$d;
		// print "d: $d\n";
		$s=substr($s,0,strlen($s)-3);
		// print "s: $s\n";
		// print "\n";
	}
	// Remove trailing dot
	return (substr($d,0,strlen($d)-1));
} // eo fkt thdots







// -------------------------------------------------------
//  Here's a usage sample
// -------------------------------------------------------

$myfilename = $REDIRECT_URL ? preg_replace ("/.*\//","",$REDIRECT_URL) : $myfilename;

print "<PRE>";
print "<form action=$PHP_SELF method=get>";
print "Enter MP3 filename: <input type=text name=myfilename value=\"$myfilename\"> <input type=submit value=\" info \"> <input type=submit name=\"showdir\" value=\" ls \">";
print "</form>";
print "<HR size=1 noshade>";

if ( ($myfilename || $REDIRECT_URL) && !$showdir) {
	// OK, we have a filename. Try to get info.
	$info=mp3info($myfilename);
	switch ($info) {
		case 1:
			print("<FONT color=maroon>Cannot open $myfilename. Click on [ls] for file list</FONT>");
			exit;
		case 2:
			print ("<FONT color=maroon>$myfilename does not look like an MP3 file</FONT>");
			exit;
		default:
			if (gettype($info)!="array") {
				print("<FONT color=maroon>Strange things happen...</FONT>");
				exit;
			}
			break;
	} // eo switch

	print "<PRE>\n";
	print "Filename     : ". $info['filename'] ."\n";
	print "Filesize     : ". thdots($info['filesize'])  ." bytes\n";
	print "Playing time : ". date("i:s",$info['time']) ." minutes (". $info['time'] ." seconds)\n";
	print "Bitrate      : ". $info['bitrate']/1000 ." kbit\n";
	print "Samplerate   : ". $info['samplerate'] ." hz\n";
	print "Frames       : ". $info['frames'] ."\n";
	print "Emphasis     : ". $info['emphasis'] ."\n";
	print "Channelmode  : ". $info['cmode'] ."\n";
	print "Version      : MPEG ". $info['version'] ." Layer ". $info['layer'] ."\n";
	print "CRC          : ". $info['crc'] ."\n";
	print "Copyright    : ". $info['copyright'] ."\n";
	print "Original     : ". $info['original'] ."\n";
	print "\n";
	if (isset($info['tagtitle'])) {
		print "MPEG Audio Tag ID:\n";
		print "Title        : ". $info['tagtitle'] ."\n";
		print "Artist       : ". $info['tagartist'] ."\n";
		print "Album        : ". $info['tagalbum'] ."\n";
		print "Year         : ". $info['tagyear'] ."\n";
		print "Comment      : ". $info['tagcomment'] ."\n";
		print "Genre        : ". $info['taggenrename'] ." (#". $info['taggenreid'] .")\n";
	print "</PRE>\n";
	} else {
		print "No MPEG Audio Tag ID found\n";
	} // eo has tag?
} else {
	// No filename or showdir set. Show available files.
	$dhnd=opendir('.');
	echo "<PRE>\n";
	echo "<B>MP3-files in current dir:</B>\n";
	while ($file=readdir($dhnd)) {
		if (ereg("mp3$",$file)) print "$file\n";
	}
	closedir($dhnd); 
	echo "</PRE>\n";

} // eo if got filename?
?>

<hr noshade size=1>
Please see Brian Wallace' for a better analysis tool:  <a href="http://sourceforge.net/projects/mpeg-database/">http://sourceforge.net/projects/mpeg-database/</a><br>
According to Wallace there's a bug in the framesync detection:<br>
<pre>
You need to ensure n=(ord)255 and n+1>=(ord)224
An ord >= 224 (128+64+32)=224 ensures that the binary expression has at least 8 bits in it and the
first three high order bits are set (i.e. 1)  for examle n=(ord)255 & n+1=(ord)=225  the binary
would be:
      11111111   11100001 ==  sync detected...  continue
</pre>
Thanks for the hint, Wallace. Sorry, I don't have the time to fix this right now.<br>
<hr>
View PHP source anyway: <a href="index.phps"><u>fancy</u></a> | <a href="index.txt"><u>plain</u></a><br>
<small>You cannot download the mp3 files. Although they where taken from IUMA and similar websites, I am not sure they are free. Sorry, but given the way the music industry behaves...</small><br>
