动网论坛,站长建站首选,国内使用量最多的论坛软件 动网论坛官方技术讨论区 站长工具 申请属于您自己的免费论坛
首页 | 新闻资讯 | 网站运营 | 网络编程 | 数据库 | 服务器 | 网页设计 | 图像媒体 | 网络应用 | 搜索优化 | 资源下载 | 动网主机 | DVBOX
    本站内  互联网 ASP论坛  ASP.Net论坛  PHP论坛
  
   PHP → 阅读文章

 一个解析mp3 ID3 tag和MPEG信息的类

作者来源: 
阅读 1895 人次 , 2006-3-29 4:10:00 


<?php
/*
 * mp3 class
 *
 * rel. 0.1
 *
 * copyright (c) 2000 sumatra solutions srl http://www.sumatrasolutions.com
 * ludovico magnocavallo ludo@sumatrasolutions.com
 *
 * license type: gnu gpl http://www.gnu.org/copyleft/gpl.html
 *
 * heavily inspired by
 * perl apache::mp3 module (l. stein) -- great module to create an apache-based mp3 server
 * perl mp3::info (c. nandor) -- very complicated, hard stuff but useful
 * java class de.vdheide.mp3 (j. vonderheide) -- great stuff, easy to read, had to debug synchronize() method
 *
 * id3v2 tags support not completed
 *
 * mp3 header reference at http://www.mp3-tech.org/
 *
 * // quick start:
 * $mp3 = new mp3($myfilepath);
 * $mp3->get_info(); // file info in $mp3->info array
 * $mp3->get_id3(); // id3 info in $mp3->id3 array
 * $mp3->send_pls($http_host) // uses physical path to file in playlist url
 * $mp3->stream() // streams file to browser
 *
 * $id: mp3.php,v 1.10 2000/07/18 11:05:16 ludo exp $
 *
 */
class mp3 {
var $id3_genres_array = 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', 'classical', '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', 'psychadelic', 'rave', 'showtunes', 'trailer', 'lo-fi', 'tribal', 'acid punk', 'acid jazz', 'polka', 'retro', 'musical', 'rock & roll', 'hard rock', 'folk', 'folk/rock', 'national folk',
'swing', 'fast fusion', 'bebob', 'latin', 'revival', 'celtic', 'bluegrass', 'avantgarde', 'gothic rock', 'progressive rock', 'psychedelic rock', 'symphonic rock', 'slow rock', 'big band',
'chorus', 'easy listening', 'acoustic', 'humour', 'speech', 'chanson', 'opera', 'chamber music', 'sonata', 'symphony', 'booty bass', 'primus', 'porn groove', 'satire', 'slow jam', 'club', 'tango', 'samba',
'folklore', 'ballad', 'power ballad', 'rhythmic soul', 'freestyle', 'duet', 'punk rock', 'drum solo', 'acapella', 'euro-house', 'dance hall'
);
var $info_bitrates = array(
1 => array(
1 => array( 0 => 0, 16 => 32, 32 => 64, 48 => 96, 64 => 128, 80 => 160, 96 => 192, 112 => 224, 128 => 256, 144 => 288, 160 => 320, 176 => 352, 192 => 384, 208 => 416, 224 => 448, 240 => false),
2 => array( 0 => 0, 16 => 32, 32 => 48, 48 => 56, 64 => 64, 80 => 80, 96 => 96, 112 => 112, 128 => 128, 144 => 160, 160 => 192, 176 => 224, 192 => 256, 208 => 320, 224 => 384, 240 => false),
3 => array( 0 => 0, 16 => 32, 32 => 40, 48 => 48, 64 => 56, 80 => 64, 96 => 80, 112 => 96, 128 => 112, 144 => 128, 160 => 160, 176 => 192, 192 => 224, 208 => 256, 224 => 320, 240 => false)
),
2 => array(
1 => array( 0 => 0, 16 => 32, 32 => 48, 48 => 56, 64 => 64, 80 => 80, 96 => 96, 112 => 112, 128 => 128, 144 => 144, 160 => 160, 176 => 176, 192 => 192, 208 => 224, 224 => 256, 240 => false),
2 => array( 0 => 0, 16 => 8, 32 => 16, 48 => 24, 64 => 32, 80 => 40, 96 => 48, 112 => 56, 128 => 64, 144 => 80, 160 => 96, 176 => 112, 192 => 128, 208 => 144, 224 => 160, 240 => false),
3 => array( 0 => 0, 16 => 8, 32 => 16, 48 => 24, 64 => 32, 80 => 40, 96 => 48, 112 => 56, 128 => 64, 144 => 80, 160 => 96, 176 => 112, 192 => 128, 208 => 144, 224 => 160, 240 => false)
),
);
var $info_versions = array(0 => "reserved", 1 => "mpeg version 1", 2 => "mpeg version 2", 2.5 => "mpeg version 2.5");
var $info_layers = array("reserved", "layer i", "layer ii", "layer iii");
var $info_sampling_rates = array(
0 => array(0 => false, 4 => false, 8 => false, 12 => false),
1 => array(0 => "44100 hz", 4 => "48000 hz", 8 => "32000 hz", 12 => false),
2 => array(0 => "22050 hz", 4 => "24000 hz", 8 => "16000 hz", 12 => false),
2.5 => array(0 => "11025 hz", 4 => "12000 hz", 8 => "8000 hz", 12 => false),
);
var $info_channel_modes = array(0 => "stereo", 64 => "joint stereo", 128 => "dual channel", 192 => "single channel");
var $file = "";
var $fh = false;
var $error = false;
var $id3_parsed = false;
var $id3 = array(
/* "tag" => "",
"title" => "unknown",
"author" => "unknown",
"album" => "unknown",
"year" => "unknown",
"comment" => "unknown",
"genre_id" => 0,
"genre" => "unknown"
*/ );
var $url = "";
var $info = array();
 
function mp3($file, $exitonerror=true) {
if (file_exists($file)) {
$this->file = $file;
$this->fh = fopen($this->file,"r");
global $http_host, $php_self;
$this->url = "http://$http_host/$php_self";
} else {
$this->error = "no such file";
if ($exitonerror) $this->exitonerror();
}
}
function exitonerror() {
echo($this->error);
exit;
}
function set_id3($title = "", $author = "", $album = "", $year = "", $comment = "", $genre_id = 0) {
$this->error = false;
$this->wfh = fopen($this->file,"a");
fseek($this->wfh, -128, seek_end);
fwrite($this->wfh, pack("a3a30a30a30a4a30c1", "tag", $title, $author, $album, $year, $comment, $genre_id), 128);
fclose($this->wfh);
}
function get_id3() {
$this->id3_parsed = true;
fseek($this->fh, -128, seek_end);
$line = fread($this->fh, 10000);
if (preg_match("/^tag/", $line)) {
$this->id3 = unpack("a3tag/a30title/a30author/a30album/a4year/a30comment/c1genre_id", $line);
$this->id3["genre"] = $this->id3_genres_array[$this->id3]["genre_id"]];
return(true);
} else {
$this->error = "no idv3 tag found";
return(false);
}
}
// get_info() helper methods
function calculate_length($id3v2_tagsize = 0) {
$length = floor(($this->info["filesize"] - $id3v2_tagsize) / $this->info["bitrate"] * 0.008);
$min = floor($length / 60);
$min = strlen($min) == 1 ? "0$min" : $min;
$sec = $length % 60;
$sec = strlen($sec) == 1 ? "0$sec" : $sec;
return("$min:$sec");
}
function get_info() {
// $this->get_id3v2header();
$second = $this->synchronize();
// echo("2nd byte = $second <b>" . decbin($second) . "</b><br>");
$third = ord(fread($this->fh, 1));
$fourth = ord(fread($this->fh, 1));
$this->info["version_id"] = ($second & 16) > 0 ? ( ($second & 8) > 0 ? 1 : 2 ) : ( ($second & 8) > 0 ? 0 : 2.5 );
$this->info["version"] = $this->info_versions[ $this->info]["version_id"] ];
$this->info["layer_id"] = ($second & 4) > 0 ? ( ($second & 2) > 0 ? 1 : 2 ) : ( ($second & 2) > 0 ? 3 : 0 );  ;
$this->info["layer"] = $this->info_layers[ $this->info]["layer_id"] ];
$this->info["protection"] = ($second & 1) > 0 ? "no crc" : "crc";
$this->info["bitrate"] = $this->info_bitrates[ $this->info]["version_id"] ][ $this->info]["layer_id"] ][ ($third & 240) ];
$this->info["sampling_rate"] = $this->info_sampling_rates[ $this->info]["version_id"] ][ ($third & 12)];
$this->info["padding"] = ($third & 2) > 0 ? "on" : "off";
$this->info["private"] = ($third & 1) > 0 ? "on" : "off";
$this->info["channel_mode"] = $this->info_channel_modes[$fourth & 192];
$this->info["copyright"] = ($fourth & 8) > 0 ? "on" : "off";
$this->info["original"] = ($fourth & 4) > 0 ? "on" : "off";
$this->info["filesize"] = filesize($this->file);
$this->info["length"] = $this->calculate_length();
}
function synchronize() {
$finished = false;
rewind($this->fh);
while (!$finished) {
$skip = ord(fread($this->fh, 1));
// echo("inside synchronize() skip = $skip <b>" . decbin($skip) . "</b><br>");
while ($skip != 255 && !feof($this->fh)) {
$skip = ord(fread($this->fh, 1));
// echo("inside synchronize() skip = $skip <b>" . decbin($skip) . "</b><br>");
}
if (feof($this->fh)) {
$this->error("no info header found");
if ($exitonerror) $this->exitonerror();
}
$store = ord(fread($this->fh, 1));
// echo("inside synchronize() store = $store <b>" . decbin($store) . "</b><br>");
if ($store >= 225) {
$finished = true;
} else if (feof($this->fh)) {
$this->error("no info header found");
if ($exitonerror) $this->exitonerror();
}
}
return($store);
}
function get_id3v2header() {
$bytes = fread($this->fh, 3);
if ($bytes != "id3") {
echo("no id3 tag");
return(false);
}
// get major and minor versions
$major = fread($this->fh, 1);
$minor = fread($this->fh, 1);
echo("id3v$major.$minor");
}
function stream() {
if (!$this->id3_parsed) {
$this->get_id3();
}
header("icy 200 ok\r\n");
header("icy-notice1:this stream requires a shoutcast/icecast compatible player.<br>\r\n");
header("icy-notice2:php mp3 class<br>\r\n");
header("icy-name:" . (count($this->id3) > 0 ? $this->id3["title"] . " - " . $this->id3["author"] . " - " . $this->id3["album"] . " - " . $this->id3["year"] : $this->file) . "\r\n");
header("icy-genre:" . (count($this->id3) > 0 ? $this->id3["genre"] : "unspecified") . "\r\n");
header("icy-url:bbb\r\n");
header("icy-pub:1\r\n");
header("icy-br:320\r\n");
rewind($this->fh);
fpassthru($this->fh);
}
function send_playlist_header($numentries = 1) {
header("content-type: audio/mpegurl;");
echo("[playlist]\r\n\r\n");
echo("numberofentries=$numentries\r\n");
}
function send_pls($server) {
$this->send_playlist_header();
$path = "/";
$path_array = explode("/", dirname($this->file));
while(list($key,$val) = each($path_array)) {
$path .= empty($val) ? "" : rawurlencode($val);
}
$path .= "/";
$file = rawurlencode(preg_replace("/\.mp3$/", "", basename($this->file)));
echo("file1=http://$server$path$file.mps\r\n");
}
function close() {
@fclose($this->fh);
}
}

?>

 本文TagsTag  mp3  tag  
 收藏本文  打印本文  论坛讨论  关闭窗口
· 上一篇:如何文档化你的PHP类
· 下一篇:PHP4.03关于session不能自动去除的临时处理方法
· 在一个字符串中查找另一个字符串
· 超越模板引擎
· 第二节--PHP5 的对象模型 -- Classes and Objects in PHP5 [2]
· 建立灵巧结构的PHP程序
· 将PHP作为Shell脚本语言使用


关于本站 | 联系我们 | 业务合作 | 客户案例 | 诚聘英才 | 广告合作 | 收藏本站
海口动网先锋网络科技有限公司版权所有
Copyright © 2000 - 2006 Cndw.Com
中华人民共和国电信与信息服务业务经营许可证编号 琼 ICP 020077