<?php
/*
$Author: mfboy
$Version: 0.0.1
$Date: 2009-03-29
*/
/*
(array|false) mp3::get_mp3($filename[, $getframesindex = false])
(true|false) mp3::set_mp3($file_input, $file_output[, $id3v1 = array(), $id3v2 = array()])
(true|false) mp3::cut_mp3($file_input, $file_output[, $startframeindex = 0, $endframeindex = -1, $framesindex = array()])
(array|false) mp3::get_frameheader($frameheaders)
(string) mp3::conv_flag($flag)
(string) mp3::conv_time($seconds)
*/
class mp3 {
private $fp, $filesize;
private $id3v1, $id3v2, $data;
private $data_start = 0;
private $data_end = 0;
private $data_frames = array();
private $vbr_bitrate_max = 0;
private $vbr_bitrate_min = 0;
private $vbr_bitrates = 0;
private $vbr_frametotal = 0;
var $id3v1_genres = array
(
'0' => 'Blues',
'1' => 'Classic Rock',
'2' => 'Country',
'3' => 'Dance',
'4' => 'Disco',
'5' => 'Funk',
'6' => 'Grunge',
'7' => 'Hip-Hop',
'8' => 'Jazz',
'9' => 'Metal',
'10' => 'New Age',
'11' => 'Oldies',
'12' => 'Other',
'13' => 'Pop',
'14' => 'R&B',
'15' => 'Rap',
'16' => 'Reggae',
'17' => 'Rock',
'18' => 'Techno',
'19' => 'Industrial',
'20' => 'Alternative',
'21' => 'Ska',
'22' => 'Death Metal',
'23' => 'Pranks',
'24' => 'Soundtrack',
'25' => 'Euro-Techno',
'26' => 'Ambient',
'27' => 'Trip-Hop',
'28' => 'Vocal',
'29' => 'Jazz+Funk',
'30' => 'Fusion',
'31' => 'Trance',
'32' => 'Classical',
'33' => 'Instrumental',
'34' => 'Acid',
'35' => 'House',
'36' => 'Game',
'37' => 'Sound Clip',
'38' => 'Gospel',
'39' => 'Noise',
'40' => 'AlternRock',
'41' => 'Bass',
'42' => 'Soul',
'43' => 'Punk',
'44' => 'Space',
'45' => 'Meditative',
'46' => 'Instrumental Pop',
'47' => 'Instrumental Rock',
'48' => 'Ethnic',
'49' => 'Gothic',
'50' => 'Darkwave',
'51' => 'Techno-Industrial',
'52' => 'Electronic',
'53' => 'Pop-Folk',
'54' => 'Eurodance',
'55' => 'Dream',
'56' => 'Southern Rock',
'57' => 'Comedy',
'58' => 'Cult',
'59' => 'Gangsta',
'60' => 'Top 40',
'61' => 'Christian Rap',
'62' => 'Pop/Funk',
'63' => 'Jungle',
'64' => 'Native American',
'65' => 'Cabaret',
'66' => 'New Wave',
'67' => 'Psychadelic',
'68' => 'Rave',
'69' => 'Showtunes',
'70' => 'Trailer',
'71' => 'Lo-Fi',
'72' => 'Tribal',
'73' => 'Acid Punk',
'74' => 'Acid Jazz',
'75' => 'Polka',
'76' => 'Retro',
'77' => 'Musical',
'78' => 'Rock & Roll',
'79' => 'Hard Rock',
'80' => 'Folk',
'81' => 'Folk/Rock',
'82' => 'National Folk',
'83' => 'Swing',
'84' => 'Fast-Fusion',
'85' => 'Bebob',
'86' => 'Latin',
'87' => 'Revival',
'88' => 'Celtic',
'89' => 'Bluegrass',
'90' => 'Advantgarde',
'91' => 'Gothic Rock',
'92' => 'Progressive Rock',
'93' => 'Psychadelic Rock',
'94' => 'Symphonic Rock',
'95' => 'Slow Rock',
'96' => 'Big Band',
'97' => 'Chorus',
'98' => 'Easy Listening',
'99' => 'Acoustic',
'100' => 'Humour',
'101' => 'Speech',
'102' => 'Chanson',
'103' => 'Opera',
'104' => 'Chamber Music',
'105' => 'Sonata',
'106' => 'Symphony',
'107' => 'Booty Bass',
'108' => 'Primus',
'109' => 'Porn Groove',
'110' => 'Satire',
'111' => 'Slow Jam',
'112' => 'Club',
'113' => 'Tango',
'114' => 'Samba',
'115' => 'Folklore',
);
var $id3v2_frameid_descriptions = array
(
'AENC' => 'Audio encryption',
'APIC' => 'Attached picture',
'COMM' => 'Comments',
'COMR' => 'Commercial frame',
'ENCR' => 'Encryption method registration',
'EQUA' => 'Equalization',
'ETCO' => 'Event timing codes',
'GEOB' => 'General encapsulated object',
'GRID' => 'Group identification registration',
'IPLS' => 'Involved people list',
'LINK' => 'Linked information',
'MCDI' => 'Music CD identifier',
'MLLT' => 'MPEG location lookup table',
'OWNE' => 'Ownership frame',
'PRIV' => 'Private frame',
'PCNT' => 'Play counter',
'POPM' => 'Popularimeter',
'POSS' => 'Position synchronisation frame',
'RBUF' => 'Recommended buffer size',
'RVAD' => 'Relative volume adjustment',
'RVRB' => 'Reverb',
'SYLT' => 'Synchronized lyric/text',
'SYTC' => 'Synchronized tempo codes',
'TALB' => 'Album/Movie/Show title',
'TBPM' => 'BPM (beats per minute)',
'TCOM' => 'Composer',
'TCON' => 'Content type',
'TCOP' => 'Copyright message',
'TDAT' => 'Date',
'TDLY' => 'Playlist delay',
'TENC' => 'Encoded by',
'TEXT' => 'Lyricist/Text writer',
'TFLT' => 'File type',
'TIME' => 'Time',
'TIT1' => 'Content group description',
'TIT2' => 'Title/songname/content description',
'TIT3' => 'Subtitle/Description refinement',
'TKEY' => 'Initial key',
'TLAN' => 'Language(s)',
'TLEN' => 'Length',
'TMED' => 'Media type',
'TOAL' => 'Original album/movie/show title',
'TOFN' => 'Original filename',
'TOLY' => 'Original lyricist(s)/text writer(s)',
'TOPE' => 'Original artist(s)/performer(s)',
'TORY' => 'Original release year',
'TOWN' => 'File owner/licensee',
'TPE1' => 'Lead performer(s)/Soloist(s)',
'TPE2' => 'Band/orchestra/accompaniment',
'TPE3' => 'Conductor/performer refinement',
'TPE4' => 'Interpreted, remixed, or otherwise modified by',
'TPOS' => 'Part of a set',
'TPUB' => 'Publisher',
'TRCK' => 'Track number/Position in set',
'TRDA' => 'Recording dates',
'TRSN' => 'Internet radio station name',
'TRSO' => 'Internet radio station owner',
'TSIZ' => 'Size',
'TSRC' => 'ISRC (international standard recording code)',
'TSSE' => 'Software/Hardware and settings used for encoding',
'TYER' => 'Year',
'UFID' => 'Unique file identifier',
'USER' => 'Terms of use',
'USLT' => 'Unsychronized lyric/text transcription',
'WCOM' => 'Commercial information',
'WCOP' => 'Copyright/Legal information',
'WOAF' => 'Official audio file webpage',
'WOAR' => 'Official artist/performer webpage',
'WOAS' => 'Official audio source webpage',
'WORS' => 'Official internet radio station homepage',
'WPAY' => 'Payment',
'WPUB' => 'Publishers official webpage'
);
var $bitrates = array
(
'0000' => array
(
1 => array('~', '~', '~'),
2 => array('~', '~', '~')
),
'0001' => array
(
1 => array('32', '32', '32'),
2 => array('32', '8', '8')
),
'0010' => array
(
1 => array('64', '48', '40'),
2 => array('48', '16', '16')
),
'0011' => array
(
1 => array('96', '56', '48'),
2 => array('56', '24', '24')
),
'0100' => array
(
1 => array('128', '64', '56'),
2 => array('64', '32', '32')
),
'0101' => array
(
1 => array('160', '80', '64'),
2 => array('80', '40', '40')
),
'0110' => array
(
1 => array('192', '96', '80'),
2 => array('96', '48', '48')
),
'0111' => array
(
1 => array('224', '112', '96'),
2 => array('112', '56', '56')
),
'1000' => array
(
1 => array('256', '128', '112'),
2 => array('128', '64', '64')
),
'1001' => array
(
1 => array('288', '160', '128'),
2 => array('144', '80', '80')
),
'1010' => array
(
1 => array('320', '192', '160'),
2 => array('160', '96', '96')
),
'1011' => array
(
1 => array('352', '224', '192'),
2 => array('176', '112', '112')
),
'1100' => array
(
1 => array('384', '256', '224'),
2 => array('192', '128', '128')
),
'1101' => array
(
1 => array('416', '320', '256'),
2 => array('224', '144', '144')
),
'1110' => array
(
1 => array('448', '384', '320'),
2 => array('256', '160', '160')
)
);
var $sampling_frequencys = array
(
'00' => array('44100', '22050', '11025'),
'01' => array('48000', '24000', '12000'),
'10' => array('32000', '16000', '8000')
);
var $modes = array
(
'00' => 'Stereo',
'01' => 'Joint Stereo',
'10' => 'Dual Channel',
'11' => 'Single Channel'
);
var $mode_extensions = array
(
'00' => array(0, 0),
'01' => array(1, 0),
'10' => array(0, 1),
'11' => array(1, 1),
);
function get_mp3($filename, $getframesindex = false) {
if(!$this->fp = @fopen($filename, 'rb')) {
return false;
}
$this->filesize = filesize($filename);
$this->data = array();
$this->data_start = 0;
$this->data_frames = array();
$this->vbr_bitrate_min = $this->vbr_bitrate_max = 0;
$this->vbr_bitrates = $this->vbr_frametotal = 0;
$this->id3v2 = $this->get_id3v2();
$this->id3v1 = $this->get_id3v1();
$this->data = $this->get_data();
$return = array();
if($this->data) {
$return['Data'] = $this->data;
}
if($this->id3v2) {
$return['ID3v2'] = $this->id3v2;
}
if($this->id3v1) {
$return['ID3v1'] = $this->id3v1;
}
if($getframesindex && $return['Data']) {
$return['Frames'] = $this->get_framesindex($return['Data']['Type'], $return['Data']['Frametotal']);
$return['Data']['Frametotal'] = count($return['Frames']);
$return['Data']['Length'] = ceil($return['Data']['Frametotal'] * 0.026);
$return['Data']['Time'] = $this->conv_time($return['Data']['Length']);
if($this->vbr_bitrates) {
$return['Data']['Bitrate'] = round($this->vbr_bitrates / $this->vbr_frametotal);
$return['Data']['Bitrate_min'] = $this->vbr_bitrate_min;
$return['Data']['Bitrate_max'] = $this->vbr_bitrate_max;
}
}
fclose($this->fp);
return $return;
}
private function get_id3v2() {
rewind($this->fp);
$tag = array();
$headerformat = 'a3Header/CVersion/CRevision/CFlag/CSize0/CSize1/CSize2/CSize3';
$headersize = 10;
$headerdata = fread($this->fp, $headersize);
$header = @unpack($headerformat, $headerdata);
if(!$header || $header['Header'] != 'ID3') {
rewind($this->fp);
return false;
}
$tag['Version'] = $header['Version'];
$tag['Revision'] = $header['Revision'];
$tagflag = $this->conv_flag($header['Flag']);
$tag['Flag'] = array
(
'Unsynchronisation' => $tagflag{0},
'Extra' => $tagflag{1},
'Test' => $tagflag{2}
);
$tagsize = ($header['Size0'] & 0x7F) * 0x200000
+ ($header['Size1'] & 0x7F) * 0x400
+ ($header['Size2'] & 0x7F) * 0x80
+ ($header['Size3']);
if(($tagsize = intval($tagsize)) < 1) {
return $tag;
}
$tag['Size'] = $tagsize;
$tag['Frames'] = array();
$seek_start = ftell($this->fp);
$seek_end = $seek_start + $tagsize - $headersize;
while(1) {
$seek_now = ftell($this->fp);
$seek_last = $seek_end - $seek_now;
if($seek_last <= 0) {
break;
}
$frameheaderformat = 'a4FrameID/CSize0/CSize1/CSize2/CSize3/CFlag0/CFlag1/cCharset';
$frameheader = @unpack($frameheaderformat, fread($this->fp, 11));
if(!$frameheader || !$frameheader['FrameID'] || !$frameheader['Size3']) {
continue;
}
$frameid = $frameheader['FrameID'];
$framedescription = 'Unknown';
if(isset($this->id3v2_frameid_descriptions[$frameid])) {
$framedescription = $this->id3v2_frameid_descriptions[$frameid];
} else {
switch($frameid{0}) {
case 'T': $framedescription = 'User defined text information frame'; break;
case 'W': $framedescription = 'User defined URL link frame'; break;
}
}
$framesize = $frameheader['Size0'] * 0x100000000
+ $frameheader['Size1'] * 0x10000
+ $frameheader['Size2'] * 0x100
+ $frameheader['Size3'];
if($framesize < 1 || $framesize > $seek_last) {
continue;
}
$frameflag = array
(
$this->conv_flag($frameheader['Flag0']),
$this->conv_flag($frameheader['Flag1'])
);
switch($frameheader['Charset']) {
case 0: $framecharset = 'ISO-8859-1'; break;
case 1: $framecharset = 'UTF-16'; break;
case 2: $framecharset = 'UTF-16BE'; break;
case 3: $framecharset = 'UTF-8'; break;
default: $framecharset = 'Unknown'; break;
}
$framedatasize = $framesize - 1;
$framedata = @unpack("a{$framedatasize}Data", fread($this->fp, $framedatasize));
if($frameid == 'COMM') {
$framelang = substr($framedata['Data'], 0, 3);
$framedata = substr($framedata['Data'], 3 + ($framedata['Data']{3} == "\x00" ? 1 : 0));
} else {
$framelang = false;
$framedata = $framedata['Data'];
}
$frame = array
(
'FrameID' => $frameid,
'Description' => $framedescription,
'Flag' => array
(
'Tag_protect' => $frameflag[0]{0},
'File_protect' => $frameflag[0]{1},
'Readonly' => $frameflag[0]{2},
'Compressed' => $frameflag[1]{0},
'Encrypt' => $frameflag[1]{1},
'Group' => $frameflag[1]{2},
),
'Size' => $framesize,
'Charset' => $framecharset,
'Data' => $framedata
);
if($framelang) {
$frame['Language'] = $framelang;
}
$tag['Frames'][$frameid][] = $frame;
}
$this->data_start = $seek_end;
rewind($this->fp);
return $tag;
}
private function get_id3v1() {
$tagsize = 128;
$tagstart = $this->filesize - $tagsize;
fseek($this->fp, $tagstart);
$tagformat = 'a3Header/a30Title/a30Artist/a30Album/a4Year/a28Comment/CReserve/CTrack/CGenre';
$tag = @unpack($tagformat, fread($this->fp, $tagsize));
if($tag['Header'] == 'TAG') {
$this->data_end = $this->filesize - $tagsize;
} else {
$this->data_end = $this->filesize;
return false;
}
$tag['Genre'] = $this->id3v1_genres[$tag['Genre']];
$tag['Genre'] = $tag['Genre'] ? $tag['Genre'] : 'Unknown';
unset($tag['Header']);
rewind($this->fp);
return $tag;
}
private function get_data() {
fseek($this->fp, $this->data_start);
$blank_data = fread($this->fp, 1024);
$blank_size = @max(0, strpos($blank_data, trim($blank_data)));
fseek($this->fp, $this->data_start + $blank_size);
$frameheaders = fread($this->fp, 4);
$frameheader = $this->get_frameheader($frameheaders);
if(!$frameheader || !is_array($frameheader)) {
return false;
}
extract($frameheader);
$framedata = fread($this->fp, 36);
$frametype = strpos($framedata, 'Xing') ? 'VBR' : 'CBR';
if($frametype == 'CBR') {
$frametotal = $this->get_data_cbr($frameheader, $mpegver, $layer, $bitrate, $sampling_frequency, $padding, $quotiety);
} else {
$frametotal = $this->get_data_vbr($frameheader);
}
$framelength = ceil($frametotal * 0.026);
$frametime = $this->conv_time($framelength);
$return = array
(
'Filesize' => $this->filesize,
'MPEGVer' => $mpegver,
'Layer' => $layer,
'Bitrate' => $bitrate,
'Sampling_frequency' => $sampling_frequency,
'Mode' => $mode,
'Mode_extension' => array
(
'Intensity_Stereo' => $mode_extension[0],
'MS_Stereo' => $mode_extension[1]
),
'Copyright' => $copyright,
'Original' => $original,
'Type' => $frametype,
'Length' => $framelength,
'Time' => $frametime,
'Frametotal' => $frametotal
);
return $return;
}
private function get_data_cbr($frameheader, $mpegver, $layer, $bitrate, $sampling_frequency, $padding, $quotiety) {
$framedatasize = $this->data_end - $this->data_start;
$framesize = intval($quotiety * $bitrate * 1000 / $sampling_frequency + intval($padding));
return @ceil($framedatasize / $framesize);
}
private function get_data_vbr($frameheader) {
$framevbrdata = @unpack('NVBR', fread($this->fp, 4));;
$framevbrs = array(1, 3, 5, 7, 9, 11, 13, 15);
if(!in_array($framevbrdata['VBR'], $framevbrs)) {
return 0;
}
$frametotaldata = @unpack('NFrametotal', fread($this->fp, 4));
$frametotal = $frametotaldata['Frametotal'];
return $frametotal;
}
function get_frameheader($frameheaders) {
$frameheader = array();
for($i = 0; $i < 4; $i++) {
$frameheader[] = $this->conv_flag(ord($frameheaders{$i}));
}
if($frameheaders{0} != "\xFF" || substr($frameheader[1], 0, 3) != '111') {
return false;
}
switch(substr($frameheader[1], 3, 2)) {
case '00': $mpegver = '2.5'; break;
case '10': $mpegver = '2'; break;
case '11': $mpegver = '1'; break;
default: return false;
}
switch(substr($frameheader[1], 5, 2)) {
case '01': $layer = '3'; break;
case '10': $layer = '2'; break;
case '11': $layer = '1'; break;
default: return false;
}
$bitrate = substr($frameheader[2], 0, 4);
$bitrate = $this->bitrates[$bitrate][intval($mpegver)][intval($layer) - 1];
$sampling_frequency = substr($frameheader[2], 5, 2);
$sampling_frequency = $this->sampling_frequencys[$sampling_frequency][ceil($mpegver) - 1];
if(!$bitrate || !$sampling_frequency) {
return false;
}
$padding = $frameheader[2]{6};
$mode = substr($frameheader[3], 0, 2);
$mode = $this->modes[$mode];
$mode_extension = substr($frameheader[3], 2, 2);
$mode_extension = $this->mode_extensions[$mode_extension];
if(!$mode || !$mode_extension) {
return false;
}
$copyright = substr($frameheader[3], 4, 1) ? 1 : 0;
$original = substr($frameheader[3], 5, 1) ? 1 : 0;
switch($mpegver) {
case '1':
$quotiety = $layer == '1' ? 48 : 144;
break;
case '2': case '2.5':
$quotiety = $layer == '1' ? 24 : 72;
break;
default:
return false;
}
return array
(
'mpegver' => $mpegver,
'layer' => $layer,
'bitrate' => $bitrate,
'sampling_frequency' => $sampling_frequency,
'padding' => $padding,
'mode' => $mode,
'mode_extension' => $mode_extension,
'copyright' => $copyright,
'original' => $original,
'quotiety' => $quotiety
);
}
private function get_framesindex($frametype, $frametotal) {
$framessize = $this->data_end - $this->data_start;
$frameindexs = array();
fseek($this->fp, $this->data_start);
if($frametype == 'CBR') {
$framesize = intval($framessize / $frametotal);
$framedatasize = $framesize - 4;
for($i = 0; $i < $frametotal; ) {
$frameheaders = fread($this->fp, 4);
$frameseek = ftell($this->fp);
$frameheader = array();
if(($this->data_end - $frameseek) < $framesize) {
break;
}
for($j = 0; $j < 4; $j++) {
$frameheader[] = $this->conv_flag(ord($frameheaders{$j}));
}
if($frameheaders{0} == "\xFF" && substr($frameheader[1], 0, 3) == '111') {
$frameindexs[] = $frameseek - 4;
$i++;
fseek($this->fp, $frameseek + $framedatasize);
continue;
}
fseek($this->fp, $frameseek - 3);
}
} elseif ($frametype == 'VBR') {
$blank_data = fread($this->fp, 1024);
$blank_size = @max(0, strpos($blank_data, trim($blank_data)));
fseek($this->fp, $this->data_start + $blank_size);
for($i = 0; $i < $frametotal; $i++) {
$frameheaders = fread($this->fp, 4);
$frameseek = ftell($this->fp);
if($frameseek >= $this->data_end) {
break;
}
if(!$framedata = $this->get_frameheader($frameheaders)) {
continue;
}
extract($framedata);
$this->vbr_bitrate_min = $this->vbr_bitrate_min > 0 ? min($this->vbr_bitrate_min, $bitrate) : $bitrate;
$this->vbr_bitrate_max = max($this->vbr_bitrate_max, $bitrate);
$this->vbr_bitrates += $bitrate;
$this->vbr_frametotal++;
$framesize = intval($quotiety * $bitrate * 1000 / $sampling_frequency + intval($padding));
$frameindexs[] = $frameseek - 4;
fseek($this->fp, $frameseek + $framesize - 4);
}
}
return $frameindexs;
}
function set_mp3($file_input, $file_output, $id3v1 = array(), $id3v2 = array()) {
if(!$this->fp = @fopen($file_input, 'rb')) {
return false;
}
if(!$fp = @fopen($file_output, 'wb')) {
return false;
}
$this->filesize = filesize($file_input);
$this->id3v2 = $this->get_id3v2();
$this->id3v1 = $this->get_id3v1();
fseek($this->fp, $this->data_start);
$mp3_data_size = $this->data_end - $this->data_start;
$mp3_data = @fread($this->fp, $mp3_data_size);
$id3v1 = is_array($id3v1) ? $id3v1 : array();
$id3v2 = is_array($id3v2) ? $id3v2 : array();
$id3v2['frames'] = is_array($id3v2['frames']) ? $id3v2['frames'] : array();
$id3v2_data = '';
foreach($id3v2['frames'] as $frame) {
if(!is_array($frame) || !$frame) {
continue;
}
if(strlen($frame['frameid']) != 4) {
continue;
}
$frame['tagprotect'] = !empty($frame['tagprotect']) ? 1 : 0;
$frame['fileprotect'] = !empty($frame['fileprotect']) ? 1 : 0;
$frame['readonly'] = !empty($frame['readonly']) ? 1 : 0;
$frame['compressed'] = !empty($frame['compressed']) ? 1 : 0;
$frame['encrypt'] = !empty($frame['encrypt']) ? 1 : 0;
$frame['group'] = !empty($frame['group']) ? 1 : 0;
$frame['Flag0'] = bindec("{$frame[tagprotect]}{$frame[fileprotect]}{$frame[readonly]}00000");
$frame['Flag1'] = bindec("{$frame[compressed]}{$frame[encrypt]}{$frame[group]}00000");
$frame['language'] = in_array($frame['language'], array(0, 1, 2, 3)) ? $frame['language'] : 0;
$frame['data'] = $frame['data'] ? $frame['data'] : '';
$id3v2_data .= pack('a4NCCc', $frame['frameid'], strlen($frame['data']) + 1, $frame['Flag0'], $frame['Flag1'], $frame['language']);
$id3v2_data .= $frame['data'];
}
if($id3v2_data) {
$id3v2['unsynchronisation'] = !empty($id3v2['unsynchronisation']) ? 1 : 0;
$id3v2['extra'] = !empty($id3v2['extra']) ? 1 : 0;
$id3v2['test'] = !empty($id3v2['test']) ? 1 : 0;
$id3v2['Flag0'] = bindec("{$id3v2[unsynchronisation]}{$id3v2[extra]}{$id3v2[test]}00000");
$id3v2_size = strlen($id3v2_data) + 10;
$id3v2_sizes = array();
for($i = 3; $i >= 0; $i--) {
$id3v2_sizes[$i] = ($id3v2_size & 0x7F);
$id3v2_size /= 80;
}
fwrite($fp, pack('a3CCCCCCC', 'ID3', 3, 0, $id3v2['Flag0'], $id3v2_sizes[0], $id3v2_sizes[1], $id3v2_sizes[2], $id3v2_sizes[3]));
fwrite($fp, $id3v2_data);
}
fwrite($fp, $mp3_data);
if($id3v1 && is_array($id3v1)) {
$id3v1_data = pack('a3a30a30a30a4a28CCC', 'TAG', $id3v1[0], $id3v1[1], $id3v1[2], $id3v1[3], $id3v1[4], $id3v1[5], $id3v1[6], $id3v1[7]);
fwrite($fp, $id3v1_data);
}
fclose($this->fp);
fclose($fp);
return true;
}
function cut_mp3($file_input, $file_output, $startframeindex = 0, $endframeindex = -1, $framesindex = array()) {
if(!$framesindex) {
$mp3_info = $this->get_mp3($file_input, true);
if(!$mp3_info || !is_array($mp3_info) || !$mp3_info['Frames']) {
return false;
}
}
if(!$this->fp = @fopen($file_input, 'rb')) {
return false;
}
if(!$fp = @fopen($file_output, 'wb')) {
return false;
}
$framesindex = $mp3_info['Frames'];
$frametotal = count($framesindex);
$framelast = $frametotal - 1;
$framelastsize = $this->data_end - $framesindex[$framelast];
$startframeindex = max(0, $startframeindex);
$endframeindex = $endframeindex < 0 ? $framelast : $endframeindex;
if($startframeindex >= $endframeindex || $endframeindex > $framelast) {
return false;
}
for($i = $startframeindex; $i <= $endframeindex; $i++) {
fseek($this->fp, $framesindex[$i]);
fwrite($fp, fread($this->fp, $i == $framelast ? $framelastsize : ($framesindex[$i + 1] - $framesindex[$i])));
}
fclose($this->fp);
fclose($fp);
return true;
}
function conv_flag($flag) {
$flag = decbin($flag);
$scarcity = 8 - strlen($flag);
if($scarcity < 1) {
return $flag;
}
for($i = 0; $i < $scarcity; $i++) {
$flag = '0'.$flag;
}
return $flag;
}
function conv_time($seconds) {
$return = '';
$separator = ':';
if($seconds > 3600) {
$return .= intval($seconds / 3600).' ';
$seconds -= intval($seconds / 3600) * 3600;
}
if($seconds > 60) {
$return .= sprintf('%02d', intval($seconds / 60)).' ';
$seconds -= intval($seconds / 60) * 60;
} else {
$return .= '00 ';
}
$return .= sprintf('%02d', $seconds);
$return = trim($return);
return str_replace(' ', $separator, $return);
}
}
?>