Location: PHPKode > projects > Mummi (Multi-user MOD_MP3 Interface) > mummi.0.6/lib/audio.inc
<?
class AUDIO_PARSER extends FILESYS{
	// php class to scan compressed audio files for information.

	var $ap_mpeg_bitrates = array(
			24=>array(
				6=>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),
				4=>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),
				2=>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)),
			16=>array(
				6=>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),
				4=>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),
				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)),
			0=>array(
				6=>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),
				4=>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),
				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)));
	var $ap_mpeg_frequency = array(
			24 => array(0 => 44100, 4 => 48000, 8 => 32000),
			16 => array(0 => 22050, 4 => 24000, 8 => 16000),
			0 => array(0 => 11025, 4 => 12000, 8 => 8000));
	var $ap_mpeg_version_modes = array(0=>3,16=>2,24=>1);
	var $ap_mpeg_layer_modes = array(2=>3,4=>2,6=>1);
	var $ap_mpeg_channel_modes = array(0=>4,64=>3,128=>2,192=>1);
	var $ap_mpeg_emphasis_modes = array(0=>3,1=>2,3=>1);
	var $ap_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=>'Avantgarde',91=>'Gothic Rock',92=>'Progressive Rock',93=>'Psychedelic 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,116=>Ballad,117=>'Power Ballad',118=>'Rhythmic Soul',119=>Freestyle,
			120=>Duet,121=>'Punk Rock',122=>'Drum Solo',123=>Acapella,124=>'Euro-House',125=>'Dance Hall',126=>Goa,127=>'Drum & Bass',128=>'Club-House',129=>Hardcore,
			130=>Terror,131=>Indie,132=>BritPop,133=>Negerpunk,134=>'Polsk Punk',135=>Beat,136=>'Christian Gangsta Rap',137=>'Heavy Metal',138=>'Black Metal',139=>Crossover,
			140=>'Contemporary Christian',141=>'Christian Rock',142=>Merengue,143=>Salsa,144=>'Thrash Metal',145=>Anime,146=>JPop,147=>Synthpop);

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */





/*
0            1           2
0123 4 5 67890123 4567 8901 2345 67->
AAAA B C DDDDDDDD EEEE FFFF GGGG HI->

OggS p ì JØb1vorb isD¬ ÿÿÿÿ ôÿÿÿ ÿ¸
OggS p ì J°;Zÿÿÿÿ ÿÿÿÿ ÿÿÿÿ ÿÿÿÿ vorbis Xiphophorus libVorbis I 20010218ARTIST=Del The Funky HomosapienTITLE=Phoney PhranchiseALBUM=Both Sides Of The BrainvorbisBCV+¼÷kÎ-:Æ2bRL!å$ÅZk¯½×B
OggSpìJD4Bÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯Dö^!¨½V{ï½÷Þ{ï½÷ÞAJ½7ÄaïÚ{½÷Þ{ï½÷Þ{若Ü{(ô½Çbï½÷Þ{ï½÷sï½çYï½bÖ{N-÷Þ{ï½÷Þ{ï½÷Þ{ï$÷ÞKɽ÷Ú{ï½÷Þ{ï½÷


A = capture pattern = "oggs"
B = Stream Structure version
C = header_type_flags
D = PCM absolute position
E = stream serial number
F = page sequence no
G = page checksum
H = page_segments
I = segment_table (containing packet lacing values)


note: the segment_table (aka lacing values) is variable in size.
note: the first page of an ogg/vorbis has onyl one packet.


*/

	// I finally asked xiphmont how to do this.
	// Ofcource he said to read the docs, but I understand now.
	function sync_ogg($offset='0'){
		rewind($this->fs_file_id);

		while(!feof($this->fs_file_id)){
			// we are looking for the letter "o".
			$byte_1 = ord(fgetc($this->fs_file_id));
			$ogg_info[byte1_pos] = ftell($this->fs_file_id);
			if($byte_1 != 111)continue;

			// We are looking for the letterr "g".
			$byte_2 = ord(fgetc($this->fs_file_id));
			if($byte_2 != 103){
				fseek($this->fs_file_id,$ogg_info[byte1_pos]);
				continue;
			}
			// We are looking for the letterr "g".
 			$byte_3 = ord(fgetc($this->fs_file_id));
			if($byte_3 != 103){
				fseek($this->fs_file_id,$ogg_info[byte1_pos]);
				continue;
			}
			// We are looking for the letterr "g".
			$byte_4 = ord(fgetc($this->fs_file_id));
			if($byte_4 != 115){
				fseek($this->fs_file_id,$ogg_info[byte1_pos]);
				continue;
			}
			// If we passed the above, we have found the frame_id.
			// But we must now check the other parts to make sure.

			// The bit flags
			// This byte has bits set that indicate the frames context.
			// according to xiphmont, reserve bits must be set to zero.
			$byte_5 = ord(fgetc($this->fs_file_id));
			if($byte_5 >= 8){
				fseek($this->fs_file_id,$ogg_info[byte1_pos]);
				continue;
			}
			// PCM absolute position
			// 8 bytes of god-only knows.
			$ogg_pap = fread($this->fs_file_id,8);
		}//eo while loop



	}//eo ogg function

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */






	function sync_mp3($offset='0'){
		rewind($this->fs_file_id);
		// this is my home-brew method to speed up files that have trash at the top.
		if(isset($offset)){
			fseek($this->fs_file_id,$offset);
			$tolerance = 1000 + $offset;
			$next_step = 1000;
			$iteration = $offset;
		}else{
			$tolerance = 1000;
			$next_step = 1000;
			$iteration = 0;
		}
		while(!feof($this->fs_file_id)){
			$iteration++;
			if($iteration == $tolerance){
				$iteration += $next_step;
				$tolerance += (2*$next_step);
				fseek($this->fs_file_id,ftell($this->fs_file_id)+$next_step);
			}
			$byte_1 = ord(fgetc($this->fs_file_id));
			$mpeg_info[byte1_pos] = ftell($this->fs_file_id);
			if($byte_1 != 255)continue;
	//echo "byte1 = $byte_1 -- $mpeg_info[byte1_pos]<br>\n";
			// Start the 2nd byte proof.
			$byte_2 = ord(fgetc($this->fs_file_id));
	//echo "byte2 = $byte_2<br>\n";
			if(($byte_2 & 224) != 224){
	//echo "2nd byte rejected, sync.<br>\n";
				fseek($this->fs_file_id,$mpeg_info[byte1_pos]);
				continue;
			}
			elseif(($byte_2 & 24) == 8){
	//echo "2nd byte rejected, bad version.<br>\n";
				fseek($this->fs_file_id,$mpeg_info[byte1_pos]);
				continue;
			}elseif(($byte_2 & 6) == 0){
	//echo "2nd byte rejected, bad layer.<br>\n";
				fseek($this->fs_file_id,$mpeg_info[byte1_pos]);
				continue;
			}
			// Parse out the variables
			$mpeg_info[version_id] = ($byte_2 & 24);
			$mpeg_info[layer_id] = ($byte_2 & 6);
			$mpeg_info[crc_id] = ($byte_2 & 1);
			// Start the 3rd byte proof.
			$byte_3 = ord(fgetc($this->fs_file_id));
	//echo "byte3 = $byte_3<br>\n";
			if($byte_3 >= 240){
	//echo "3rd byte rejected, bitrate reserved.<br>\n";
				fseek($this->fs_file_id,$mpeg_info[byte1_pos]);
				continue;
			}elseif(($byte_3 & 12) == 12){
	//echo "3rd byte rejected, reserved freq.<br>\n";
				fseek($this->fs_file_id,$mpeg_info[byte1_pos]);
				continue;
			}
			// Parse out the variables
			$mpeg_info[bitrate_id] = ($byte_3 & 240);
			$mpeg_info[freq_id] = ($byte_3 & 12);
			$mpeg_info[padding_id] = ($byte_3 & 2);
			$mpeg_info[private_id] = ($byte_3 & 1);
			// Get the bitrate.
			if(!$mpeg_info[bitrate] = $this->ap_mpeg_bitrates["$mpeg_info[version_id]"]["$mpeg_info[layer_id]"]["$mpeg_info[bitrate_id]"]){
	//echo "problem calculating bitrate<br>\n";
				fseek($this->fs_file_id,$mpeg_info[byte1_pos]);
				continue;
			}
			// Get the frequency.
			if(!$mpeg_info[freq] = $this->ap_mpeg_frequency["$mpeg_info[version_id]"]["$mpeg_info[freq_id]"]){
	//echo "problem calculating the frequncy<br>\n";
				fseek($this->fs_file_id,$mpeg_info[byte1_pos]);
				continue;
			}
			// Get the frame size in bytes
			$pad=0;if($mpeg_info[layer_id] == 6){
				if($padding_id == 1)$pad = 4;
				$mpeg_info[frame_length] = floor((((12 * ($mpeg_info[bitrate] * 1000)) / $mpeg_info[freq]) + $pad) * 4);
			}elseif($mpeg_info[layer_id] < 6){
				if($padding_id == 1)$pad = 1;
				$mpeg_info[frame_length] = floor(((144 * ($mpeg_info[bitrate] * 1000)) / $mpeg_info[freq]) + $pad);
			}
			// Parse the 4th byte, and prove.
			$byte_4 = ord(fgetc($this->fs_file_id));
			if(($byte_4 & 3) == 2){
	//echo "byte4 = $byte_4<br>\n";
				fseek($this->fs_file_id,$mpeg_info[byte1_pos]);
				continue;
			}
			// Parse out the variables.
			$mpeg_info[channel_mode_id] = ($byte_4 & 192);
			$mpeg_info[mode_extension_id] = ($byte_4 & 48);
			$mpeg_info[copyright_id] = ($byte_4 & 8);
			$mpeg_info[original_id] = ($byte_4 & 4);
			$mpeg_info[emphasis_id] = ($byte_4 & 3);
			// Seek the next byte.
			fseek($this->fs_file_id,($mpeg_info[byte1_pos] + $mpeg_info[frame_length])-1);
			$nbyte_1 = ord(fgetc($this->fs_file_id));
			if($nbyte_1 != 255){
	//echo "could not find the next frame-sync<br>\n";
			 	fseek($this->fs_file_id,$mpeg_info[byte1_pos]);
			 	continue;
			}
			// Next check the 2nd n_byte.
			$nbyte_2 = ord(fgetc($this->fs_file_id));
			if(($nbyte_2 & 224) != 224){
	//echo "2nd frame 2nd byte sync bits are wack!<br>\n";
				fseek($this->fs_file_id,$mpeg_info[byte1_pos]);
				continue;
			}elseif(($nbyte_2 & 24) < 16){
	//echo "2nd frame version is wack!<br>\n";
				fseek($this->fs_file_id,$mpeg_info[byte1_pos]);
				continue;
			}elseif(($nbyte_2 & 6) == 0){
	//echo "2nd frame layer is wack!<br>\n";
				fseek($this->fs_file_id,$mpeg_info[byte1_pos]);
				continue;
			}
			// We have, without question, found valid frame-sync.
			$return_array = array();
			$return_array[filesize] = $this->fs_filesize;
			$return_array[header] = ($mpeg_info[byte1_pos] -1);
			$return_array[version] = $this->ap_mpeg_version_modes[$mpeg_info[version_id]];
			$return_array[layer] = $this->ap_mpeg_layer_modes[$mpeg_info[layer_id]];
			$return_array[crc] = $mpeg_info[crc_id] == 1? "0" : "1";
			$return_array[bitrate] = $mpeg_info[bitrate];
			$return_array[freq] = $mpeg_info[freq];
			$return_array[pad] = $mpeg_info[padding_id] == 0? "0" : "1";
			$return_array[private] = $mpeg_info[private_id] == 0? "0" : "1";
			$return_array[channel_mode] = $this->ap_mpeg_channel_modes[$mpeg_info[channel_mode_id]];
			$return_array[copyright] = $mpeg_info[copyright_id] == 0? "0" : "1";
			$return_array[original] = $mpeg_info[original_id] == 0? "0" : "1";
			$return_array[emphasis] = $this->ap_mpeg_emphasis_modes[$mpeg_info[emphasis_id]];
			$return_array[framesize] = $mpeg_info[frame_length];
			$return_array[frames] = floor(($this->fs_filesize - $mpeg_info[byte1_pos]) / $mpeg_info[frame_length]);
			$return_array[seconds] = floor((($this->fs_filesize - $return_array[header]) * 8) / ($mpeg_info[bitrate] * 1000));
			$return_array[fps] = (($mpeg_info[bitrate]*1000) / ($return_array[framesize]*8));
			break;
		}
		if(feof($this->fs_file_id)) return false;


		return $return_array;
	}//eo sync_mpeg function

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */



// id3 handlers







	function get_id3v1(){
		fseek($this->fs_file_id, -128, SEEK_END);
		$tag_id = fread($this->fs_file_id, 128);
		if(!strncmp($tag_id, "TAG", 3)){
			$id3 = unpack("a3tag/a30title/a30artist/a30album/a4year/a29comment/C1track/C1genre_id", $tag_id);
			unset($id3[tag]);
		}else{
			return false;
		}
		if($id3[track]=="32") $id3[track] = "0";
		if(!$id3[genre] = $this->ap_id3v1_genres["$id3[genre_id]"]) $id3[genre_id] = 255;
		return $id3;
	}//eo get_id3v1 function

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */








	// This can create, or update id3v11 tag.
	function set_id3v1($title="", $artist="", $album="", $year="", $comment="", $track="", $genre_id){
		$update_id = pack("a3a30a30a30a4a29C1C1", "TAG", $title, $artist, $album, $year, $comment, $track, $genre_id);
		if(!$genre_id) $new_id = pack("a3a30a30a30a4a29C1C1", "TAG", $title, $artist, $album, $year, $comment, $track, 255);
		else $new_id = pack("a3a30a30a30a4a29C1C1", "TAG", $title, $artist, $album, $year, $comment, $track, $genre_id);
		fseek($this->fs_file_id, ($this->fs_filesize - 128));
		$tag_id = fread($this->fs_file_id, 128);
		if(strncmp($tag_id, "TAG", 3)){
			//If the tag does NOT exist, write a new one.
			fseek($this->fs_file_id, $this->fs_filesize);
			fwrite($this->fs_file_id, $new_id, 128);
			$this->fs_filesize = $this->fs_filesize + 128;
		}else{
			//If the tag exist, overwrite it.
			fseek($this->fs_file_id, ($this->fs_filesize - 128));
			fwrite($this->fs_file_id, $update_id, 128);
		}
		return true;
	}//eo set_id3v1 function

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */



	function remove_id3v1(){
		fseek($this->fs_file_id, ($this->fs_filesize-128));
		$tag_id = fread($this->fs_file_id, 3);
		//echo "tag = $tag_id<br>\n";
		if(strncmp($tag_id,'TAG', 3)){
			//echo "No tag found to remove, failure!<br>\n";
			return false;
		}else{
			rewind($this->fs_file_id);
			if(!ftruncate($this->fs_file_id,$this->fs_filesize-128)){
				//echo "Tag found, but not removed, failure.<br>\n";
				return false;
			}else{
				//echo "Tag found and removed, success!<br>\n";
				return true;
			}
		}
	}//eo remove_id3v1 function

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */










	function id3v2_syncsafe_to_size($b1,$b2,$b3,$b4){
		$size = (($b1 & 127) << 21)+
			(($b2 & 127) << 14)+
			(($b3 & 127) << 7)+
			($b4 & 127);
		return 10+$size;
	}




	function id3v2_size_to_syncsafe($dec){
		$b1 = (($dec & 266338304)>>21);
		$b2 = (($dec & 2080768)>>14);
		$b3 = (($dec & 16256)>>7);
		$b4 = ($dec & 127);
		return array($b1,$b2,$b3,$b4);
	}




	// 5 bytes, 35 bits used.
	// $b1 == MSB, $b5 == LSB.
	function id3v2_syncsafe_to_crc32($b1,$b2,$b3,$b4,$b5){
		$crc32 = (($b1 & 127) << 28)+
			(($b2 & 127) << 21)+
			(($b3 & 127) << 14)+
			(($b4 & 127) << 7)+
			($b5 & 127);
		echo "$b1 - $b2 - $b3 - $b4 - $b5 -> $crc32";
		return $crc32;
	}

	function id3v2_crc32_to_syncsafe($crc32){
		//$b1 = (($crc32 & 4026531840)>>28);
		$b2 = (($crc32 & 266338304)>>21);
		$b3 = (($crc32 & 2080768)>>14);
		$b4 = (($crc32 & 16256)>>7);
		$b5 = ($crc32 & 127);
		echo "$crc32 -> $b1 - $b2 - $b3 - $b4 - $b5<br>\n";
		return array($b1,$b2,$b3,$b4,$b5);
	}



/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */





	function get_id3v2(){

		if($this->fs_filesize<=10){
			return false;
		}

		rewind($this->fs_file_id);


		$id3v2_info = array();
		$header = fread($this->fs_file_id,10);


//echo "<FONT COLOR=red>$header</FONT><br>\n";


		$id3v2_header = unpack("a3id3/C1major/C1minor/C1flags/C4size", $header);

//echo "<FONT COLOR=red>$id3v2_header[id3]</FONT><br>\n";


		if(!ereg('ID3',$id3v2_header[id3])) return false;



        // check the version byte.
        // we need to support ver 3 & 4, then 2.


		switch($id3v2_header[major]){
			case '255': return false;

			// version 3 only.
			case '3':
				if(($id3v2_header[flags] & 31) > 0) return false;
				$id3v2_info[unsync] = ($id3v2_header[flags] & 128) != 0 ? "1": "0";
				$id3v2_info[extra_header] = ($id3v2_header[flags] & 64) != 0 ? "1": "0";
				$id3v2_info[experimental] = ($id3v2_header[flags] & 32) != 0 ? "1": "0";

				$id3v2_info[id_size] = $this->id3v2_syncsafe_to_size($id3v2_header[size1],$id3v2_header[size2],$id3v2_header[size3],$id3v2_header[size4]);
	//echo "tag size total = $id3v2_info[id_size]<br>\n";

				// start the extra header stuff
				if($id3v2_info[extra_header] != 0){
	echo "extended header detected<br>\n";
					$ext_header = fread($this->fs_file_id,10);
					$id3v2_ext_header = unpack("C4size/C2flags/C4pad_size", $ext_header);

					$id3v2_info[ext_header_size] = id3v2_syncsafe_to_size($id3v2_ext_header[size1],$id3v2_ext_header[size2],$id3v2_ext_header[size3],$id3v2_ext_header[size4]);
	echo "extended header size = $id3v2_info[ext_header_size]<br>\n";


					$id3v2_info[pad_size] = id3v2_syncsafe_to_size($id3v2_ext_header[pad_size1],$id3v2_ext_header[pad_size1],$id3v2_ext_header[pad_size3],$id3v2_ext_header[pad_size4]);
	echo "extended header pad size = $id3v2_info[pad_size]<br>\n";

					if(($id3v2_ext_header[flags1] & 128) != 0){
						$ext_header_crc32 = fread($this->fs_file_id, 4);
						$id3v2_info[crc] = crc32($ext_header_crc32);
					}
				} //eo extra header stuff


				// get the frames

				$i = ftell($this->fs_file_id);
				$x = 0;
				while($i < $id3v2_info[id_size]){

					$k = ftell($this->fs_file_id);
					if($k > $id3v2_info[id_size]) break;
					//if(($k || ($k+10)) > $id3v2_info[id_size]) break;

					$frame_header = fread($this->fs_file_id,10);

					$i = ftell($this->fs_file_id);
					if($i > $id3v2_info[id_size]) break;

					$frame = unpack("a4id/C4size/C2flags",$frame_header);

					if(!ereg("([0-9A-Z]{4})", $frame[id], $regs))continue;

					$frame_data_pos = ftell($this->fs_file_id);

					// IF the size bytes are >= than 0x80 individually, then break.
					if(($frame[size1] > 127)or($frame[size2] > 127)or($frame[size3] > 127)or($frame[size4] > 127))break;

					$frame_data_size = $this->id3v2_syncsafe_to_size($frame[size1],$frame[size2],$frame[size3],$frame[size4])-10;

					// This protects against frames that have bad size set.
					if($frame_data_size > $id3v2_info[id_size])break;

					$frame_data = fread($this->fs_file_id,$frame_data_size);
					$j = ftell($this->fs_file_id);

					// frame flags.
					$tag_alter = ($frame[flags1] & 128) != 0 ? "1": "0";
					$file_alter = ($frame[flags1] & 64) != 0 ? "1": "0";
					$readonly = ($frame[flags1] & 32) != 0 ? "1": "0";

					$compression = ($frame[flags1] & 128) != 0 ? "1": "0";
					$encryption = ($frame[flags1] & 64) != 0 ? "1": "0";
					$grouping = ($frame[flags1] & 32) != 0 ? "1": "0";

					// do somehing about the chance a flag is set.





					$tag_array["$frame[id]"] = $frame_data;


					$i = ftell($this->fs_file_id);

				}//eo while
			break;














			// version 4 only.

			case '4':


				if(($id3v2_header[flags] & 15) > 0) return false;

				$id3v2_info[unsync] = ($id3v2_header[flags] & 128) != 0 ? "1": "0";
				$id3v2_info[extra_header] = ($id3v2_header[flags] & 64) != 0 ? "1": "0";
				$id3v2_info[experimental] = ($id3v2_header[flags] & 32) != 0 ? "1": "0";
				$id3v2_info[footer_present] = ($id3v2_header[flags] & 16) != 0 ? "1": "0";



// id3v4 specific
// if a footer present, compensate the size.
				if($id3v2_info[footer_present] == 1){
					$id3v2_info[id_size] = $this->id3v2_syncsafe_to_size($id3v2_header[size1],$id3v2_header[size2],$id3v2_header[size3],$id3v2_header[size4]) + 10;
				}else{
					$id3v2_info[id_size] = $this->id3v2_syncsafe_to_size($id3v2_header[size1],$id3v2_header[size2],$id3v2_header[size3],$id3v2_header[size4]);
				}

	echo "tag size total = $id3v2_info[id_size]<br>\n";





//     Extended header size   4 * %0xxxxxxx
//     Number of flag bytes       $01
//     Extended Flags             $xx


// note: extended headers are 6 bytes in version 4.
// version 3 uses 10 bytes.


				// start the extra header stuff
				if($id3v2_info[extra_header] != 0){
	echo "extended header detected<br>\n";


// check
					$ext_header_size = fread($this->fs_file_id,4);
					$id3v2_ext_header = unpack("C4size", $ext_header_size);

					// after getting the size, fread that amount.


					$ext_header = fread($this->fs_file_id,$id3v2_ext_header[size]- 4);	// notice the arith at the end.
					$id3v2_ext_header += unpack("C1flag_bytes", $ext_header_size);

					$id3v2_ext_header = unpack("C4size/C1flag_bytes/C1ext_flags", $ext_header);



					$id3v2_info[ext_header_size] = id3v2_syncsafe_to_size($id3v2_ext_header[size1],$id3v2_ext_header[size2],$id3v2_ext_header[size3],$id3v2_ext_header[size4]);
	echo "extended header size = $id3v2_info[ext_header_size]<br>\n";


					//$id3v2_info[pad_size] = id3v2_syncsafe_to_size($id3v2_ext_header[pad_size1],$id3v2_ext_header[pad_size1],$id3v2_ext_header[pad_size3],$id3v2_ext_header[pad_size4]);
	echo "extended header pad size = $id3v2_info[pad_size]<br>\n";

					if(($id3v2_ext_header[flags1] & 128) != 0){
						$ext_header_crc32 = fread($this->fs_file_id, 4);
						$id3v2_info[crc] = crc32($ext_header_crc32);
					}
				} //eo extra header stuff


				// get the frames

				$i = ftell($this->fs_file_id);
				$x = 0;
				while($i < $id3v2_info[id_size]){

					$k = ftell($this->fs_file_id);
					if($k > $id3v2_info[id_size]) break;
					//if(($k || ($k+10)) > $id3v2_info[id_size]) break;

					$frame_header = fread($this->fs_file_id,10);

					$i = ftell($this->fs_file_id);
					if($i > $id3v2_info[id_size]) break;

					$frame = unpack("a4id/C4size/C2flags",$frame_header);

					if(!ereg("([0-9A-Z]{4})", $frame[id], $regs))continue;

					$frame_data_pos = ftell($this->fs_file_id);

					// IF the size bytes are >= than 0x80 individually, then break.
					if(($frame[size1] > 127)or($frame[size2] > 127)or($frame[size3] > 127)or($frame[size4] > 127))break;

					$frame_data_size = $this->id3v2_syncsafe_to_size($frame[size1],$frame[size2],$frame[size3],$frame[size4])-10;

					// This protects against frames that have bad size set.
					if($frame_data_size > $id3v2_info[id_size])break;

					$frame_data = fread($this->fs_file_id,$frame_data_size);
					$j = ftell($this->fs_file_id);

					// frame flags.
					$tag_alter = ($frame[flags1] & 128) != 0 ? "1": "0";
					$file_alter = ($frame[flags1] & 64) != 0 ? "1": "0";
					$readonly = ($frame[flags1] & 32) != 0 ? "1": "0";

					$compression = ($frame[flags1] & 128) != 0 ? "1": "0";
					$encryption = ($frame[flags1] & 64) != 0 ? "1": "0";
					$grouping = ($frame[flags1] & 32) != 0 ? "1": "0";

					// do somehing about the chance a flag is set.





					$tag_array["$frame[id]"] = $frame_data;


					$i = ftell($this->fs_file_id);

				}//eo while
			break;

















		} //eo switch




		$return_array = array();


//		$return_array[filepath] = $filepath;
		$return_array[id3v2] = $id3v2_header[id3];
		$return_array[major] = $id3v2_header[major];
		$return_array[minor] = $id3v2_header[minor];
		$return_array[unsync] = $id3v2_info[unsync];
		$return_array[extra_header] = $id3v2_info[extra_header];
		$return_array[experimental] = $id3v2_info[experimental];


		$return_array[size] = $id3v2_info[id_size];
		$return_array[ext_header_size] = $id3v2_info[ext_header_size];
		$return_array[crc] = $id3v2_info[crc];

		$return_array[tags] = $tag_array;


	return $return_array;
	}//eo get_id3v2 function






}//eo class



?>
Return current item: Mummi (Multi-user MOD_MP3 Interface)