├── #user.php ├── config.php ├── archive └── index.html ├── upload └── index.html ├── logout.php ├── #auth.php ├── functions.php ├── README ├── upload.php ├── index.php ├── split.php ├── setup.php └── mp3lib.php /#user.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /config.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /archive/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /upload/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /logout.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /#auth.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /functions.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | PHP-HTTP-Audiofile-streamer is a PHP based HTTP-Streaming server for MP3 files. 2 | HTTP-Streams are working with MacOS 10.6, iOS 3.x, 4.x. VLC Player support the basics. Flash Player 10.1 also support HTTP-Streaming. 3 | PHP-HTTP-Audiofile-streamer only support Streaming a ready MP3-File (no live streaming). 4 | 5 | This Software is LGPL: http://www.gnu.org/licenses/lgpl.html 6 | 7 | Install: 8 | This is not ready for productive use! Only test and development Version! 9 | 10 | 1. Copy files to an Folder on your PHP-Server. 11 | 2. Give write Access to #user.php, config.php and the dirs upload and archive 12 | 4. open the dir in your browser and configure the setup 13 | 14 | 3. -upload an MP3-File on upload.php 15 | -hope everything works 16 | -get streamURL and try -------------------------------------------------------------------------------- /upload.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 40 | 41 | Upload to HTTP-Stream 42 | 43 | 44 |
45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |
Name:
Part-length: seconds
File:

Settings | Logout
53 |
54 | 55 | 56 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 47 | 48 | 49 | 81 | 82 | Upload to HTTP-Stream - Login 83 | 84 | 85 |
86 | 87 | 88 | 89 | 90 |
Username:
Password:
91 |
92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /split.php: -------------------------------------------------------------------------------- 1 | "; 44 | //remove dir becouse it isn't needed anymore (becouse is no content if upload failed) 45 | rmdir($archive_path."/".$current_file_dir); 46 | 47 | //echo Upload Error 48 | if(!$_FILES['file']) 49 | { 50 | $upload_error = "No file was uploaded."; 51 | } 52 | else 53 | { 54 | switch($_FILES['file']['error']) 55 | { 56 | case 0: $upload_error = "here is no error, the file uploaded with success."; 57 | case 1: $upload_error = "The uploaded file exceeds the upload_max_filesize directive in php.ini."; 58 | case 2: $upload_error = "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form."; 59 | case 3: $upload_error = "The uploaded file was only partially uploaded."; 60 | case 4: $upload_error = "No file was uploaded."; 61 | case 5: $upload_error = "-"; 62 | case 6: $upload_error = "Missing a temporary folder."; 63 | case 7: $upload_error = "Failed to write file to disk."; 64 | case 8: $upload_error = "A PHP extension stopped the file upload. PHP does not provide a way to ascertain which extension caused the file upload to stop; examining the list of loaded extensions with phpinfo() may help."; 65 | default: $upload_error = "unknown upload error"; 66 | } 67 | } 68 | echo("Upload Error: ".$upload_error."
"); 69 | //die 70 | die(); 71 | } 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | //get path for original mp3file 82 | $path = $upload_dir.'/'.$current_file_dir.".mp3"; 83 | //read MP3 84 | $mp3 = new mp3($path); 85 | 86 | 87 | 88 | //create m3u8 header 89 | $m3u8_file = "#EXTM3U 90 | #EXT-X-MEDIA-SEQUENCE:0 91 | #EXT-X-TARGETDURATION:".$partlenght." 92 | "; 93 | 94 | 95 | 96 | 97 | //start on second 0 98 | $position = 0; 99 | //continue the loop while $continue_mp3split_loop = 1 100 | $continue_mp3split_loop = 1; 101 | while($continue_mp3split_loop==1) 102 | { 103 | 104 | //split the part 105 | $mp3_1 = $mp3->extract($position,$partlenght); 106 | //export and save the part as file 107 | $mp3_1->save($archive_path."/".$current_file_dir.'/'.'file'.$position.'.mp3'); 108 | 109 | 110 | 111 | //check if title has ended 112 | if (filesize($archive_path."/".$current_file_dir.'/'.'file'.$position.'.mp3')<2) 113 | { 114 | //stop the loop 115 | $continue_mp3split_loop = 0; 116 | //delete last empty file 117 | unlink($archive_path."/".$current_file_dir.'/'.'file'.$position.'.mp3'); 118 | } 119 | 120 | //file is OK 121 | else { 122 | //write file URL to m3u8-index 123 | $m3u8_file = $m3u8_file."#EXTINF:".$partlenght.", 124 | ".$extern_archive_path."/".$current_file_dir.'/'.'file'.$position.'.mp3 125 | ';} 126 | 127 | //count up the secondcounter for next part 128 | $position = $position + $partlenght; 129 | } 130 | 131 | 132 | //finish m3u8-index-file 133 | $m3u8_file = $m3u8_file."#EXT-X-ENDLIST"; 134 | 135 | //write m3u8-index-file 136 | $dz = fopen($archive_path."/".$current_file_dir.'/'.'index.m3u8',w); 137 | fwrite($dz,$m3u8_file); 138 | fclose($dz); 139 | 140 | //write empty index.html file 141 | $dz = fopen($archive_path."/".$current_file_dir.'/'.'index.html',w); 142 | fwrite($dz,''); 143 | fclose($dz); 144 | 145 | //echo / save stream index URL 146 | $streanurlcontent = "Upload completet: Stream URL
"; 149 | //delete original MP3-file 150 | unlink($upload_dir."/".$current_file_dir.".mp3"); 151 | 152 | ?> 153 | 154 | 155 | 187 | 188 | HTTP-Stream - URL 189 | 190 | 191 |
192 |
193 |
194 | 195 | 196 | 197 | -------------------------------------------------------------------------------- /setup.php: -------------------------------------------------------------------------------- 1 | 1) 5 | { 6 | include("#auth.php"); 7 | } 8 | 9 | 10 | include("./config.php"); 11 | include("./#user.php"); 12 | 13 | 14 | 15 | 16 | 17 | if ($_POST['Button_save'] == "Save") 18 | { 19 | $save = new SaveConfig; 20 | $save->srightusername=$_POST['newusername']; 21 | $save->srightpassword=$_POST['newpassword']; 22 | $save->srightpassword2=$_POST['newpassword2']; 23 | $save->sexternarchivepath=$_POST['externarchivepath']; 24 | $save->sarchive_path=$_POST['archivepath']; 25 | $save->supload_dir=$_POST['uploadpath']; 26 | $save->sdefault_mp3_part_length=$_POST['defaultlength']; 27 | 28 | $save->save(); 29 | 30 | 31 | } 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | include("./config.php"); 42 | 43 | 44 | //fill in existing Userdata 45 | if (filesize("./#user.php")>1) 46 | { 47 | include("./#user.php"); 48 | $rightusername = decodeuserdata($rightusername); 49 | $externarchivepath = $extern_archive_path; 50 | $archive_path = $archive_path; 51 | $upload_dir = $upload_dir; 52 | $default_mp3_part_length = $default_mp3_part_length; 53 | } 54 | //OR generate new Settings on new installation OR Passwordreset 55 | else 56 | { 57 | $currentpath = 'http://' . $_SERVER['HTTP_HOST'] . str_replace("setup.php","",$_SERVER['SCRIPT_NAME']); 58 | $externarchivepath = $currentpath."archive"; 59 | 60 | $archive_path = "archive"; 61 | $upload_dir = "upload"; 62 | $default_mp3_part_length = "10"; 63 | } 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | class SaveConfig 79 | { 80 | public $srightusername; 81 | public $srightpassword; 82 | public $srightpassword2; 83 | public $sexternarchivepath; 84 | public $sarchive_path; 85 | public $supload_dir; 86 | public $sdefault_mp3_part_length; 87 | 88 | private $errormessage; 89 | private $successmessage; 90 | 91 | function checkUserChanges() 92 | { 93 | //Username and both passwords are given 94 | if(($this->srightusername)&&($this->srightpassword)&&($this->srightpassword2)) 95 | { 96 | //Passwords are not identic 97 | if (($this->srightpassword)!=($this->srightpassword2)) 98 | { 99 | $this->addErrorMessage("Passwords not identical"); 100 | return false; 101 | } 102 | //Username given, both passwords didentic -> all right 103 | else 104 | { 105 | return true; 106 | } 107 | } 108 | //Passwords given but no username 109 | elseif ($this->srightusername == "") 110 | { 111 | $this->addErrorMessage("No Username"); 112 | return false; 113 | } 114 | //don't use Data to save 115 | else 116 | { 117 | return false; 118 | } 119 | 120 | 121 | } 122 | 123 | //Save User Chaneges as fliped Base64 in #user.php 124 | function saveUserChanges() 125 | { 126 | 127 | //decode 128 | $this->usernameToSave = $this->encodeUserData($this->srightusername); 129 | $this->passwordToSave = $this->encodeUserData($this->srightpassword); 130 | 131 | $data_to_write = "usernameToSave."\"; 133 | \$rightpassword = \"".$this->passwordToSave."\"; 134 | ?>"; 135 | //write file 136 | $dz = fopen('#user.php',w); 137 | fwrite($dz,$data_to_write); 138 | fclose($dz); 139 | 140 | } 141 | 142 | //encode user data (fliped Base64) 143 | function encodeUserData($string) 144 | { 145 | $string = base64_encode($string); 146 | $string = strrev($string); 147 | return($string); 148 | } 149 | 150 | function addErrorMessage($message) 151 | { 152 | $this->errormessage = $this->errormessage."
  • ".$message."
  • "; 153 | } 154 | 155 | function returnErrorMessage() 156 | { 157 | if($this->errormessage) 158 | { 159 | return "

    Error

    "; 160 | } 161 | } 162 | 163 | function addSuccessMessage($message) 164 | { 165 | $this->successmessage = $this->successmessage."
  • ".$message."
  • "; 166 | } 167 | 168 | function returnSuccessMessage() 169 | { 170 | if($this->successmessage) 171 | { 172 | return "

    Success

    "; 173 | } 174 | } 175 | 176 | 177 | 178 | //checks settings configuration 179 | function checkConfig() 180 | { 181 | $this->checkDir($this->sarchive_path); 182 | $this->checkDir($this->supload_dir); 183 | //Check MP3 lenth is set 184 | if(round($this->sdefault_mp3_part_length==0)) 185 | { 186 | $this->addErrorMessage("MP3 lenth is not a Number"); 187 | } 188 | elseif(!$this->sexternarchivepath) 189 | { 190 | $this->addErrorMessage("Extern Archive URL not set"); 191 | } 192 | else 193 | { 194 | return true; 195 | } 196 | 197 | } 198 | 199 | //checks directorys for write access and existence 200 | function checkDir($dir) 201 | { 202 | if (is_writeable($dir)) 203 | { 204 | return(true); 205 | } 206 | else 207 | { 208 | $this->addErrorMessage("no write Access to Dir: ".$dir); 209 | return(false); 210 | } 211 | } 212 | 213 | function save() 214 | { 215 | if ($this->checkUserChanges()) 216 | { 217 | //check for write access for #user.php 218 | if(is_writeable('#user.php')) 219 | { 220 | $this->SaveUserChanges(); 221 | $this->addSuccessMessage("Userdata Saved"); 222 | } 223 | else 224 | { 225 | $this->addErrorMessage("no write Access to #user.php"); 226 | } 227 | } 228 | 229 | //Ceck Config Save 230 | if ($this->checkConfig()) 231 | { 232 | if(is_writeable('config.php')) 233 | { 234 | $this->SaveServerChanges(); 235 | $this->addSuccessMessage("Config Saved"); 236 | } 237 | else 238 | { 239 | $this->addErrorMessage("no write Access to config.php"); 240 | } 241 | } 242 | } 243 | 244 | //save Configdata 245 | function SaveServerChanges() 246 | { 247 | $data_to_write = "sarchive_path."\"; //Path to Archive Dir 251 | \$extern_archive_path = \"".$this->sexternarchivepath."\"; 252 | \$upload_dir = \"".$this->supload_dir."\"; 253 | /*MP3 SPLIT OPTIONS*/ 254 | \$default_mp3_part_length = \"".round($this->sdefault_mp3_part_length)."\"; //default length of MP3 parts in seconds 255 | ?>"; 256 | //write file 257 | $dz = fopen('config.php',w); 258 | fwrite($dz,$data_to_write); 259 | fclose($dz); 260 | } 261 | 262 | } 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | ?> 290 | 291 | 292 | 293 | 344 | 345 | Setup HTTP-Stream 346 | 347 | 348 | returnErrorMessage()) 352 | { 353 | echo "
    ".$save->returnErrorMessage()."
    "; 354 | } 355 | 356 | if($save->returnSuccessMessage()) 357 | { 358 | echo "
    ".$save->returnSuccessMessage()."
    back
    "; 359 | die(""); 360 | } 361 | } 362 | ?> 363 |
    364 |

    Setup

    365 | 371 |

    Usersettings

    372 | 373 | 374 | 375 | 376 |
    New Username:
    New Password:
    New Password:
    377 |
    378 |

    Serversettings

    379 | 380 | 381 | 382 | 383 |
    Extern archive path:
    archive path:
    upload path:
    384 |
    385 |

    Audiosettings

    386 | 387 | 388 |
    Default part length (in seconds):
    389 |
    390 | 391 |
    392 | 393 | 394 | -------------------------------------------------------------------------------- /mp3lib.php: -------------------------------------------------------------------------------- 1 | http://www.sourcerally.net/regin 5 | 6 | 7 | /* 8 | //Merge two files 9 | $path = 'path.mp3'; 10 | $path1 = 'path1.mp3'; 11 | $mp3 = new mp3($path); 12 | 13 | $newpath = 'path.mp3'; 14 | $mp3->striptags(); 15 | 16 | $mp3_1 = new mp3($path1); 17 | $mp3->mergeBehind($mp3_1); 18 | $mp3->striptags(); 19 | $mp3->setIdv3_2('01','Track Title','Artist','Album','Year','Genre','Comments','Composer','OrigArtist', 20 | 'Copyright','url','encodedBy'); 21 | $mp3->save($newpath); 22 | 23 | 24 | //Extract 30 seconds starting after 10 seconds. 25 | $path = 'path.mp3'; 26 | $mp3 = new mp3($path); 27 | $mp3_1 = $mp3->extract(10,30); 28 | $mp3_1->save('newpath.mp3'); 29 | 30 | //Extract the exact length of time 31 | $path = 'path.mp3'; 32 | $mp3 = new mp3($path); 33 | $mp3->setFileInfoExact(); 34 | echo $mp3->time; 35 | //note that this is the exact length! 36 | */ 37 | class mp3 38 | { 39 | var $str; 40 | var $time; 41 | var $frames; 42 | 43 | function mp3($path="") 44 | { 45 | if($path!="") 46 | { 47 | $this->str = file_get_contents($path); 48 | } 49 | } 50 | 51 | function setStr($str) 52 | { 53 | $this->str = $str; 54 | } 55 | 56 | function setFileInfoExact() 57 | { 58 | $maxStrLen = strlen($this->str); 59 | $currentStrPos = $this->getStart(); 60 | $framesCount=0; 61 | $time = 0; 62 | while($currentStrPos < $maxStrLen) 63 | { 64 | $str = substr($this->str,$currentStrPos,4); 65 | $strlen = strlen($str); 66 | $parts = array(); 67 | for($i=0;$i < $strlen;$i++) 68 | { 69 | $parts[] = $this->decbinFill(ord($str[$i]),8); 70 | } 71 | if($parts[0] != "11111111") 72 | { 73 | if(($maxStrLen-128) > $currentStrPos) 74 | { 75 | return false; 76 | } 77 | else 78 | { 79 | $this->time = $time; 80 | $this->frames = $framesCount; 81 | return true; 82 | } 83 | } 84 | $a = $this->doFrameStuff($parts); 85 | $currentStrPos += $a[0]; 86 | $time += $a[1]; 87 | $framesCount++; 88 | } 89 | $this->time = $time; 90 | $this->frames = $framesCount; 91 | return true; 92 | } 93 | 94 | function extract($start,$length) 95 | { 96 | $maxStrLen = strlen($this->str); 97 | $currentStrPos = $this->getStart(); 98 | $framesCount=0; 99 | $time = 0; 100 | $startCount = -1; 101 | $endCount = -1; 102 | while($currentStrPos < $maxStrLen) 103 | { 104 | if($startCount==-1&&$time>=$start) 105 | { 106 | $startCount = $currentStrPos; 107 | } 108 | if($endCount==-1&&$time>=($start+$length)) 109 | { 110 | $endCount = $currentStrPos-$startCount; 111 | } 112 | $doFrame = true; 113 | $str = substr($this->str,$currentStrPos,4); 114 | $strlen = strlen($str); 115 | $parts = array(); 116 | for($i=0;$i < $strlen;$i++) 117 | { 118 | $parts[] = $this->decbinFill(ord($str[$i]),8); 119 | } 120 | if($parts[0] != "11111111") 121 | { 122 | if(($maxStrLen-128) > $currentStrPos) 123 | { 124 | $doFrame = false; 125 | } 126 | else 127 | { 128 | $doFrame = false; 129 | } 130 | } 131 | if($doFrame) 132 | { 133 | $a = $this->doFrameStuff($parts); 134 | $currentStrPos += $a[0]; 135 | $time += $a[1]; 136 | $framesCount++; 137 | } 138 | else break; 139 | } 140 | $mp3 = new mp3(); 141 | if($endCount == -1) 142 | { 143 | $endCount = $maxStrLen-$startCount; 144 | } 145 | if($startCount!=-1&&$endCount!=-1) 146 | { 147 | $mp3->setStr(substr($this->str,$startCount,$endCount)); 148 | } 149 | return $mp3; 150 | } 151 | 152 | function decbinFill($dec,$length=0) 153 | { 154 | $str = decbin($dec); 155 | $nulls = $length-strlen($str); 156 | if($nulls>0) 157 | { 158 | for($i=0;$i<$nulls;$i++) 159 | { 160 | $str = '0'.$str; 161 | } 162 | } 163 | return $str; 164 | } 165 | 166 | function doFrameStuff($parts) 167 | { 168 | //Get Audio Version 169 | $errors = array(); 170 | switch(substr($parts[1],3,2)) 171 | { 172 | case '01': 173 | $errors[]='Reserved audio version'; 174 | break; 175 | case '00': 176 | $audio = 2.5; 177 | break; 178 | case '10': 179 | $audio = 2; 180 | break; 181 | case '11': 182 | $audio = 1; 183 | break; 184 | } 185 | //Get Layer 186 | switch(substr($parts[1],5,2)) 187 | { 188 | case '01': 189 | $layer = 3; 190 | break; 191 | case '00': 192 | $errors[]='Reserved layer'; 193 | break; 194 | case '10': 195 | $layer = 2; 196 | break; 197 | case '11': 198 | $layer = 1; 199 | break; 200 | } 201 | //Get Bitrate 202 | $bitFlag = substr($parts[2],0,4); 203 | $bitArray = array( 204 | '0000' => array(free, free, free, free, free), 205 | '0001' => array(32, 32, 32, 32, 8), 206 | '0010' => array(64, 48, 40, 48, 16), 207 | '0011' => array(96, 56, 48, 56, 24), 208 | '0100' => array(128, 64, 56, 64, 32), 209 | '0101' => array(160, 80, 64, 80, 40), 210 | '0110' => array(192, 96, 80, 96, 48), 211 | '0111' => array(224, 112, 96, 112, 56), 212 | '1000' => array(256, 128, 112, 128, 64), 213 | '1001' => array(288, 160, 128, 144, 80), 214 | '1010' => array(320, 192, 160, 160, 96), 215 | '1011' => array(352, 224, 192, 176, 112), 216 | '1100' => array(384, 256, 224, 192, 128), 217 | '1101' => array(416, 320, 256, 224, 144), 218 | '1110' => array(448, 384, 320, 256, 160), 219 | '1111' => array(bad, bad, bad, bad, bad) 220 | ); 221 | $bitPart = $bitArray[$bitFlag]; 222 | $bitArrayNumber; 223 | if($audio==1) 224 | { 225 | switch($layer) 226 | { 227 | case 1: 228 | $bitArrayNumber=0; 229 | break; 230 | case 2: 231 | $bitArrayNumber=1; 232 | break; 233 | case 3: 234 | $bitArrayNumber=2; 235 | break; 236 | } 237 | } 238 | else 239 | { 240 | switch($layer) 241 | { 242 | case 1: 243 | $bitArrayNumber=3; 244 | break; 245 | case 2: 246 | $bitArrayNumber=4; 247 | break; 248 | case 3: 249 | $bitArrayNumber=4; 250 | break; 251 | } 252 | } 253 | $bitRate = $bitPart[$bitArrayNumber]; 254 | //Get Frequency 255 | $frequencies = array( 256 | 1=>array('00'=>44100, 257 | '01'=>48000, 258 | '10'=>32000, 259 | '11'=>'reserved'), 260 | 2=>array('00'=>44100, 261 | '01'=>48000, 262 | '10'=>32000, 263 | '11'=>'reserved'), 264 | 2.5=>array('00'=>44100, 265 | '01'=>48000, 266 | '10'=>32000, 267 | '11'=>'reserved')); 268 | $freq = $frequencies[$audio][substr($parts[2],4,2)]; 269 | //IsPadded? 270 | $padding = substr($parts[2],6,1); 271 | if($layer==3||$layer==2) 272 | { 273 | //FrameLengthInBytes = 144 * BitRate / SampleRate + Padding 274 | $frameLength = 144 * $bitRate * 1000 / $freq + $padding; 275 | } 276 | $frameLength = floor($frameLength); 277 | $seconds += $frameLength*8/($bitRate*1000); 278 | return array($frameLength,$seconds); 279 | //Calculate next when next frame starts. 280 | //Capture next frame. 281 | } 282 | 283 | function setIdv3_2($track,$title,$artist,$album,$year,$genre,$comments,$composer,$origArtist, 284 | $copyright,$url,$encodedBy) 285 | { 286 | $urlLength = (int)(strlen($url)+2); 287 | $copyrightLength = (int)(strlen($copyright)+1); 288 | $origArtistLength = (int)(strlen($origArtist)+1); 289 | $composerLength = (int)(strlen($composer)+1); 290 | $commentsLength = (int)strlen($comments)+5; 291 | $titleLength = (int) strlen($title)+1; 292 | $artistLength = (int)strlen($artist)+1; 293 | $albumLength = (int) strlen($album)+1; 294 | $genreLength = (int) strlen($genre)+1; 295 | $encodedByLength = (int)(strlen($encodedBy)+1); 296 | $trackLength = (int) strlen($track) + 1; 297 | $yearLength = (int) strlen($year)+1; 298 | $str .= chr(73);//I 299 | $str .= chr(68);//D 300 | $str .= chr(51);//3 301 | $str .= chr(3);// 302 | $str .= chr(0);// 303 | $str .= chr(0);// 304 | $str .= chr(0);// 305 | $str .= chr(0);// 306 | $str .= chr(8);// 307 | $str .= chr(53);//5 308 | $str .= chr(84);//T 309 | $str .= chr(82);//R 310 | $str .= chr(67);//C 311 | $str .= chr(75);//K 312 | $str .= chr(0);// 313 | $str .= chr(0);// 314 | $str .= chr(0);// 315 | $str .= chr($trackLength);// 316 | $str .= chr(0);// 317 | $str .= chr(0);// 318 | $str .= chr(0);// 319 | $str .= $track; 320 | $str .= chr(84);//T 321 | $str .= chr(69);//E 322 | $str .= chr(78);//N 323 | $str .= chr(67);//C 324 | $str .= chr(0);// 325 | $str .= chr(0);// 326 | $str .= chr(0);// 327 | $str .= chr($encodedByLength);// 328 | $str .= chr(64);//@ 329 | $str .= chr(0);// 330 | $str .= chr(0);// 331 | $str .= $encodedBy; 332 | $str .= chr(87);//W 333 | $str .= chr(88);//X 334 | $str .= chr(88);//X 335 | $str .= chr(88);//X 336 | $str .= chr(0);// 337 | $str .= chr(0);// 338 | $str .= chr(0);// 339 | $str .= chr($urlLength);// 340 | $str .= chr(0);// 341 | $str .= chr(0);// 342 | $str .= chr(0);// 343 | $str .= chr(0);// 344 | $str .= $url; 345 | $str .= chr(84);//T 346 | $str .= chr(67);//C 347 | $str .= chr(79);//O 348 | $str .= chr(80);//P 349 | $str .= chr(0);// 350 | $str .= chr(0);// 351 | $str .= chr(0);// 352 | $str .= chr($copyrightLength);// 353 | $str .= chr(0);// 354 | $str .= chr(0);// 355 | $str .= chr(0);// 356 | $str .= $copyright; 357 | $str .= chr(84);//T 358 | $str .= chr(79);//O 359 | $str .= chr(80);//P 360 | $str .= chr(69);//E 361 | $str .= chr(0);// 362 | $str .= chr(0);// 363 | $str .= chr(0);// 364 | $str .= chr($origArtistLength);// 365 | $str .= chr(0);// 366 | $str .= chr(0);// 367 | $str .= chr(0);// 368 | $str .= $origArtist; 369 | $str .= chr(84);//T 370 | $str .= chr(67);//C 371 | $str .= chr(79);//O 372 | $str .= chr(77);//M 373 | $str .= chr(0);// 374 | $str .= chr(0);// 375 | $str .= chr(0);// 376 | $str .= chr($composerLength);// 377 | $str .= chr(0);// 378 | $str .= chr(0);// 379 | $str .= chr(0);// 380 | $str .= $composer; 381 | $str .= chr(67);//C 382 | $str .= chr(79);//O 383 | $str .= chr(77);//M 384 | $str .= chr(77);//M 385 | $str .= chr(0);// 386 | $str .= chr(0);// 387 | $str .= chr(0);// 388 | $str .= chr($commentsLength);// 389 | $str .= chr(0);// 390 | $str .= chr(0);// 391 | $str .= chr(0);// 392 | $str .= chr(0);// 393 | $str .= chr(9);// 394 | $str .= chr(0);// 395 | $str .= chr(0);// 396 | $str .= $comments; 397 | $str .= chr(84);//T 398 | 399 | $str .= chr(67);//C 400 | $str .= chr(79);//O 401 | $str .= chr(78);//N 402 | $str .= chr(0);// 403 | $str .= chr(0);// 404 | $str .= chr(0);// 405 | $str .= chr($genreLength);// 406 | $str .= chr(0);// 407 | $str .= chr(0);// 408 | $str .= chr(0);// 409 | $str .= $genre; 410 | $str .= chr(84);//T 411 | $str .= chr(89);//Y 412 | $str .= chr(69);//E 413 | $str .= chr(82);//R 414 | $str .= chr(0);// 415 | $str .= chr(0);// 416 | $str .= chr(0);// 417 | $str .= chr($yearLength);// 418 | $str .= chr(0);// 419 | $str .= chr(0);// 420 | $str .= chr(0);// 421 | $str .= $year; 422 | $str .= chr(84);//T 423 | $str .= chr(65);//A 424 | $str .= chr(76);//L 425 | $str .= chr(66);//B 426 | $str .= chr(0);// 427 | $str .= chr(0);// 428 | $str .= chr(0);// 429 | $str .= chr($albumLength);// 430 | $str .= chr(0);// 431 | $str .= chr(0);// 432 | $str .= chr(0);// 433 | $str .= $album; 434 | $str .= chr(84);//T 435 | $str .= chr(80);//P 436 | $str .= chr(69);//E 437 | $str .= chr(49);//1 438 | $str .= chr(0);// 439 | $str .= chr(0);// 440 | $str .= chr(0);// 441 | $str .= chr($artistLength);// 442 | $str .= chr(0);// 443 | $str .= chr(0);// 444 | $str .= chr(0);// 445 | $str .= $artist; 446 | $str .= chr(84);//T 447 | $str .= chr(73);//I 448 | $str .= chr(84);//T 449 | $str .= chr(50);//2 450 | $str .= chr(0);// 451 | $str .= chr(0);// 452 | $str .= chr(0);// 453 | $str .= chr($titleLength);// 454 | $str .= chr(0);// 455 | $str .= chr(0);// 456 | $str .= chr(0);// 457 | $str .= $title; 458 | $this->str = $str.$this->str; 459 | } 460 | 461 | function mergeBehind(mp3 $mp3) 462 | { 463 | $this->str .= $mp3->str; 464 | } 465 | 466 | function mergeInfront(mp3 $mp3) 467 | { 468 | $this->str = $mp3->str.$this->str; 469 | } 470 | 471 | function getIdvEnd() 472 | { 473 | $strlen = strlen($this->str); 474 | $str = substr($this->str,($strlen-128)); 475 | $str1 = substr($str,0,3); 476 | if(strtolower($str1) == strtolower('TAG')) 477 | { 478 | return $str; 479 | } 480 | else 481 | { 482 | return false; 483 | } 484 | } 485 | 486 | function getStart() 487 | { 488 | $strlen = strlen($this->str); 489 | for($i=0;$i<$strlen;$i++) 490 | { 491 | $v = substr($this->str,$i,1); 492 | $value = ord($v); 493 | if($value == 255) 494 | { 495 | return $i; 496 | } 497 | } 498 | } 499 | 500 | function striptags() 501 | { 502 | //Remove start stuff... 503 | $newStr = ''; 504 | $s = $start = $this->getStart(); 505 | if($s===false) 506 | { 507 | return false; 508 | } 509 | else 510 | { 511 | $this->str = substr($this->str,$start); 512 | } 513 | //Remove end tag stuff 514 | $end = $this->getIdvEnd(); 515 | if($end!==false) 516 | { 517 | $this->str = substr($this->str,0,(strlen($this->str)-129)); 518 | } 519 | } 520 | 521 | function save($path) 522 | { 523 | $fp = fopen($path,'w'); 524 | fwrite($fp,$this->str); 525 | fclose($fp); 526 | } 527 | 528 | 529 | //join various MP3s 530 | function multiJoin($newpath,$array) 531 | { 532 | foreach ($array as $path) 533 | { 534 | $mp3 = new mp3($path); 535 | $mp3->striptags(); 536 | $mp3_1 = new mp3($newpath); 537 | $mp3->mergeBehind($mp3_1); 538 | $mp3->save($newpath); 539 | } 540 | } 541 | } 542 | ?> --------------------------------------------------------------------------------