diff options
author | momo-i <momo-i@ampache> | 2009-03-11 07:47:25 +0000 |
---|---|---|
committer | momo-i <momo-i@ampache> | 2009-03-11 07:47:25 +0000 |
commit | bb0405fc9caa97a8517807a1ea43767751734512 (patch) | |
tree | ee15b4e7838ab2787f42f4c87382cf9510066deb | |
parent | a1dd62bf2d74362e5553d124df67eef766acc008 (diff) | |
download | ampache-bb0405fc9caa97a8517807a1ea43767751734512.tar.gz ampache-bb0405fc9caa97a8517807a1ea43767751734512.tar.bz2 ampache-bb0405fc9caa97a8517807a1ea43767751734512.zip |
Updated: getid3-2.0.0b5
-rw-r--r-- | modules/getid3/getid3.php | 310 | ||||
-rw-r--r-- | modules/getid3/module.audio-video.quicktime.php | 235 | ||||
-rw-r--r-- | modules/getid3/module.audio.aac_adts.php | 5 | ||||
-rw-r--r-- | modules/getid3/module.audio.mpc7.php (renamed from modules/getid3/module.audio.mpc.php) | 98 | ||||
-rw-r--r-- | modules/getid3/module.audio.mpc8.php | 324 | ||||
-rw-r--r-- | modules/getid3/module.tag.id3v2.php | 239 | ||||
-rw-r--r-- | modules/getid3/write.id3v2.php | 2 |
7 files changed, 821 insertions, 392 deletions
diff --git a/modules/getid3/getid3.php b/modules/getid3/getid3.php index 7f6a8eb8..f6cb8532 100644 --- a/modules/getid3/getid3.php +++ b/modules/getid3/getid3.php @@ -61,7 +61,7 @@ class getid3 protected $iconv_present; // Class constants - const VERSION = '2.0.0b4'; + const VERSION = '2.0.0b5'; const FREAD_BUFFER_SIZE = 16384; // Read buffer size in bytes. const ICONV_TEST_STRING = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ '; @@ -286,7 +286,7 @@ class getid3 // Supported format signature pattern detected, but module deleted. if (!file_exists($this->include_path.$determined_format['include'])) { fclose($this->fp); - throw new getid3_exception('Format not supported, module, '.$determined_format['include'].', was removed.'); + throw new getid3_exception('Format not supported, module "'.$determined_format['include'].'" was removed.'); } // Include module @@ -295,7 +295,7 @@ class getid3 // Instantiate module class and analyze $class_name = 'getid3_'.$determined_format['module']; if (!class_exists($class_name)) { - throw new getid3_exception('Format not supported, module, '.$determined_format['include'].', is corrupt.'); + throw new getid3_exception('Format not supported, module "'.$determined_format['include'].'" is corrupt.'); } $class = new $class_name($this); @@ -320,95 +320,11 @@ class getid3 //// Optional - perform more calculations if ($this->option_extra_info) { - - // Set channelmode on audio - if (@$this->info['audio']['channels'] == '1') { - $this->info['audio']['channelmode'] = 'mono'; - } elseif (@$this->info['audio']['channels'] == '2') { - $this->info['audio']['channelmode'] = 'stereo'; - } - - // Calculate combined bitrate - audio + video - $combined_bitrate = 0; - $combined_bitrate += (isset($this->info['audio']['bitrate']) ? $this->info['audio']['bitrate'] : 0); - $combined_bitrate += (isset($this->info['video']['bitrate']) ? $this->info['video']['bitrate'] : 0); - if (($combined_bitrate > 0) && empty($this->info['bitrate'])) { - $this->info['bitrate'] = $combined_bitrate; - } - if (!isset($this->info['playtime_seconds']) && !empty($this->info['bitrate'])) { - $this->info['playtime_seconds'] = (($this->info['avdataend'] - $this->info['avdataoffset']) * 8) / $this->info['bitrate']; - } - - // Set playtime string - if (!empty($this->info['playtime_seconds']) && empty($this->info['playtime_string'])) { - $this->info['playtime_string'] = floor(round($this->info['playtime_seconds']) / 60) . ':' . str_pad(floor(round($this->info['playtime_seconds']) % 60), 2, 0, STR_PAD_LEFT);; - } - - - // CalculateCompressionRatioVideo() { - if (@$this->info['video'] && @$this->info['video']['resolution_x'] && @$this->info['video']['resolution_y'] && @$this->info['video']['bits_per_sample']) { - - // From static image formats - if (in_array($this->info['video']['dataformat'], array ('bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff'))) { - $frame_rate = 1; - $bitrate_compressed = $this->info['filesize'] * 8; - } - - // From video formats - else { - $frame_rate = @$this->info['video']['frame_rate']; - $bitrate_compressed = @$this->info['video']['bitrate']; - } - - if ($frame_rate && $bitrate_compressed) { - $this->info['video']['compression_ratio'] = $bitrate_compressed / ($this->info['video']['resolution_x'] * $this->info['video']['resolution_y'] * $this->info['video']['bits_per_sample'] * $frame_rate); - } - } - - - // CalculateCompressionRatioAudio() { - if (@$this->info['audio']['bitrate'] && @$this->info['audio']['channels'] && @$this->info['audio']['sample_rate']) { - $this->info['audio']['compression_ratio'] = $this->info['audio']['bitrate'] / ($this->info['audio']['channels'] * $this->info['audio']['sample_rate'] * (@$this->info['audio']['bits_per_sample'] ? $this->info['audio']['bits_per_sample'] : 16)); - } - - if (@$this->info['audio']['streams']) { - foreach ($this->info['audio']['streams'] as $stream_number => $stream_data) { - if (@$stream_data['bitrate'] && @$stream_data['channels'] && @$stream_data['sample_rate']) { - $this->info['audio']['streams'][$stream_number]['compression_ratio'] = $stream_data['bitrate'] / ($stream_data['channels'] * $stream_data['sample_rate'] * (@$stream_data['bits_per_sample'] ? $stream_data['bits_per_sample'] : 16)); - } - } - } - - - // CalculateReplayGain() { - if (@$this->info['replay_gain']) { - if (!@$this->info['replay_gain']['reference_volume']) { - $this->info['replay_gain']['reference_volume'] = 89; - } - if (isset($this->info['replay_gain']['track']['adjustment'])) { - $this->info['replay_gain']['track']['volume'] = $this->info['replay_gain']['reference_volume'] - $this->info['replay_gain']['track']['adjustment']; - } - if (isset($this->info['replay_gain']['album']['adjustment'])) { - $this->info['replay_gain']['album']['volume'] = $this->info['replay_gain']['reference_volume'] - $this->info['replay_gain']['album']['adjustment']; - } - - if (isset($this->info['replay_gain']['track']['peak'])) { - $this->info['replay_gain']['track']['max_noclip_gain'] = 0 - 20 * log10($this->info['replay_gain']['track']['peak']); - } - if (isset($this->info['replay_gain']['album']['peak'])) { - $this->info['replay_gain']['album']['max_noclip_gain'] = 0 - 20 * log10($this->info['replay_gain']['album']['peak']); - } - } - - - // ProcessAudioStreams() { - if (@!$this->info['audio']['streams'] && (@$this->info['audio']['bitrate'] || @$this->info['audio']['channels'] || @$this->info['audio']['sample_rate'])) { - foreach ($this->info['audio'] as $key => $value) { - if ($key != 'streams') { - $this->info['audio']['streams'][0][$key] = $value; - } - } - } + $this->ChannelsBitratePlaytimeCalculations(); + $this->CalculateCompressionRatioVideo(); + $this->CalculateCompressionRatioAudio(); + $this->CalculateReplayGain(); + $this->ProcessAudioStreams(); } @@ -662,11 +578,19 @@ class getid3 'mime_type' => 'audio/s3m', ), - // MPC - audio - Musepack / MPEGplus SV7+ - 'mpc' => array ( + // MPC - audio - Musepack SV7 + 'mpc8' => array ( + 'pattern' => '^(MPCK)', + 'group' => 'audio', + 'module' => 'mpc8', + 'mime_type' => 'audio/x-musepack', + ), + + // MPC - audio - Musepack SV7 + 'mpc7' => array ( 'pattern' => '^(MP\+)', 'group' => 'audio', - 'module' => 'mpc', + 'module' => 'mpc7', 'mime_type' => 'audio/x-musepack', ), @@ -1035,6 +959,173 @@ class getid3 + protected function ChannelsBitratePlaytimeCalculations() { + + // set channelmode on audio + if (@$this->info['audio']['channels'] == '1') { + $this->info['audio']['channelmode'] = 'mono'; + } elseif (@$this->info['audio']['channels'] == '2') { + $this->info['audio']['channelmode'] = 'stereo'; + } + + // Calculate combined bitrate - audio + video + $CombinedBitrate = 0; + $CombinedBitrate += (isset($this->info['audio']['bitrate']) ? $this->info['audio']['bitrate'] : 0); + $CombinedBitrate += (isset($this->info['video']['bitrate']) ? $this->info['video']['bitrate'] : 0); + if (($CombinedBitrate > 0) && empty($this->info['bitrate'])) { + $this->info['bitrate'] = $CombinedBitrate; + } + //if ((isset($this->info['video']) && !isset($this->info['video']['bitrate'])) || (isset($this->info['audio']) && !isset($this->info['audio']['bitrate']))) { + // // for example, VBR MPEG video files cannot determine video bitrate: + // // should not set overall bitrate and playtime from audio bitrate only + // unset($this->info['bitrate']); + //} + + // video bitrate undetermined, but calculable + if (isset($this->info['video']['dataformat']) && $this->info['video']['dataformat'] && (!isset($this->info['video']['bitrate']) || ($this->info['video']['bitrate'] == 0))) { + // if video bitrate not set + if (isset($this->info['audio']['bitrate']) && ($this->info['audio']['bitrate'] > 0) && ($this->info['audio']['bitrate'] == $this->info['bitrate'])) { + // AND if audio bitrate is set to same as overall bitrate + if (isset($this->info['playtime_seconds']) && ($this->info['playtime_seconds'] > 0)) { + // AND if playtime is set + if (isset($this->info['avdataend']) && isset($this->info['avdataoffset'])) { + // AND if AV data offset start/end is known + // THEN we can calculate the video bitrate + $this->info['bitrate'] = round((($this->info['avdataend'] - $this->info['avdataoffset']) * 8) / $this->info['playtime_seconds']); + $this->info['video']['bitrate'] = $this->info['bitrate'] - $this->info['audio']['bitrate']; + } + } + } + } + + if ((!isset($this->info['playtime_seconds']) || ($this->info['playtime_seconds'] <= 0)) && !empty($this->info['bitrate'])) { + $this->info['playtime_seconds'] = (($this->info['avdataend'] - $this->info['avdataoffset']) * 8) / $this->info['bitrate']; + } + + if (!isset($this->info['bitrate']) && !empty($this->info['playtime_seconds'])) { + $this->info['bitrate'] = (($this->info['avdataend'] - $this->info['avdataoffset']) * 8) / $this->info['playtime_seconds']; + } +//echo '<pre>'; +//var_dump($this->info['bitrate']); +//var_dump($this->info['audio']['bitrate']); +//var_dump($this->info['video']['bitrate']); +//echo '</pre>'; + if (isset($this->info['bitrate']) && empty($this->info['audio']['bitrate']) && empty($this->info['video']['bitrate'])) { + if (isset($this->info['audio']['dataformat']) && empty($this->info['video']['resolution_x'])) { + // audio only + $this->info['audio']['bitrate'] = $this->info['bitrate']; + } elseif (isset($this->info['video']['resolution_x']) && empty($this->info['audio']['dataformat'])) { + // video only + $this->info['video']['bitrate'] = $this->info['bitrate']; + } + } + + // Set playtime string + if (!empty($this->info['playtime_seconds']) && empty($this->info['playtime_string'])) { + $this->info['playtime_string'] = getid3_lib::PlaytimeString($this->info['playtime_seconds']); + } + } + + + protected function CalculateCompressionRatioVideo() { + if (empty($this->info['video'])) { + return false; + } + if (empty($this->info['video']['resolution_x']) || empty($this->info['video']['resolution_y'])) { + return false; + } + if (empty($this->info['video']['bits_per_sample'])) { + return false; + } + + switch ($this->info['video']['dataformat']) { + case 'bmp': + case 'gif': + case 'jpeg': + case 'jpg': + case 'png': + case 'tiff': + $FrameRate = 1; + $PlaytimeSeconds = 1; + $BitrateCompressed = $this->info['filesize'] * 8; + break; + + default: + if (!empty($this->info['video']['frame_rate'])) { + $FrameRate = $this->info['video']['frame_rate']; + } else { + return false; + } + if (!empty($this->info['playtime_seconds'])) { + $PlaytimeSeconds = $this->info['playtime_seconds']; + } else { + return false; + } + if (!empty($this->info['video']['bitrate'])) { + $BitrateCompressed = $this->info['video']['bitrate']; + } else { + return false; + } + break; + } + $BitrateUncompressed = $this->info['video']['resolution_x'] * $this->info['video']['resolution_y'] * $this->info['video']['bits_per_sample'] * $FrameRate; + + $this->info['video']['compression_ratio'] = $BitrateCompressed / $BitrateUncompressed; + return true; + } + + + protected function CalculateCompressionRatioAudio() { + if (empty($this->info['audio']['bitrate']) || empty($this->info['audio']['channels']) || empty($this->info['audio']['sample_rate'])) { + return false; + } + $this->info['audio']['compression_ratio'] = $this->info['audio']['bitrate'] / ($this->info['audio']['channels'] * $this->info['audio']['sample_rate'] * (!empty($this->info['audio']['bits_per_sample']) ? $this->info['audio']['bits_per_sample'] : 16)); + + if (!empty($this->info['audio']['streams'])) { + foreach ($this->info['audio']['streams'] as $streamnumber => $streamdata) { + if (!empty($streamdata['bitrate']) && !empty($streamdata['channels']) && !empty($streamdata['sample_rate'])) { + $this->info['audio']['streams'][$streamnumber]['compression_ratio'] = $streamdata['bitrate'] / ($streamdata['channels'] * $streamdata['sample_rate'] * (!empty($streamdata['bits_per_sample']) ? $streamdata['bits_per_sample'] : 16)); + } + } + } + return true; + } + + + protected function CalculateReplayGain() { + if (isset($this->info['replay_gain'])) { + $this->info['replay_gain']['reference_volume'] = 89; + if (isset($this->info['replay_gain']['track']['adjustment'])) { + $this->info['replay_gain']['track']['volume'] = $this->info['replay_gain']['reference_volume'] - $this->info['replay_gain']['track']['adjustment']; + } + if (isset($this->info['replay_gain']['album']['adjustment'])) { + $this->info['replay_gain']['album']['volume'] = $this->info['replay_gain']['reference_volume'] - $this->info['replay_gain']['album']['adjustment']; + } + + if (isset($this->info['replay_gain']['track']['peak'])) { + $this->info['replay_gain']['track']['max_noclip_gain'] = 0 - getid3_lib::RGADamplitude2dB($this->info['replay_gain']['track']['peak']); + } + if (isset($this->info['replay_gain']['album']['peak'])) { + $this->info['replay_gain']['album']['max_noclip_gain'] = 0 - getid3_lib::RGADamplitude2dB($this->info['replay_gain']['album']['peak']); + } + } + return true; + } + + protected function ProcessAudioStreams() { + if (!empty($this->info['audio']['bitrate']) || !empty($this->info['audio']['channels']) || !empty($this->info['audio']['sample_rate'])) { + if (!isset($this->info['audio']['streams'])) { + foreach ($this->info['audio'] as $key => $value) { + if ($key != 'streams') { + $this->info['audio']['streams'][0][$key] = $value; + } + } + } + } + return true; + } + + // Convert and copy tags protected function HandleAllTags() { @@ -1275,18 +1366,18 @@ abstract class getid3_handler_write ignore_user_abort($this->user_abort); } - - + + protected function save_permissions() { - + $this->owner = fileowner($this->filename); $this->group = filegroup($this->filename); $this->perms = fileperms($this->filename); } - - + + protected function restore_permissions() { - + @chown($this->filename, $this->owner); @chgrp($this->filename, $this->group); @chmod($this->filename, $this->perms); @@ -1485,6 +1576,11 @@ class getid3_lib } + public static function RGADamplitude2dB($amplitude) { + return 20 * log10($amplitude); + } + + public static function PrintHexBytes($string, $hex=true, $spaces=true, $html_safe=true) { $return_string = ''; @@ -1505,6 +1601,18 @@ class getid3_lib } + public static function PlaytimeString($playtimeseconds) { + $sign = (($playtimeseconds < 0) ? '-' : ''); + $playtimeseconds = abs($playtimeseconds); + $contentseconds = round((($playtimeseconds / 60) - floor($playtimeseconds / 60)) * 60); + $contentminutes = floor($playtimeseconds / 60); + if ($contentseconds >= 60) { + $contentseconds -= 60; + $contentminutes++; + } + return $sign.intval($contentminutes).':'.str_pad($contentseconds, 2, 0, STR_PAD_LEFT); + } + // Process header data string - read several values with algorithm and add to target // algorithm is one one the getid3_lib::Something2Something() function names diff --git a/modules/getid3/module.audio-video.quicktime.php b/modules/getid3/module.audio-video.quicktime.php index 559c1065..3af2bccc 100644 --- a/modules/getid3/module.audio-video.quicktime.php +++ b/modules/getid3/module.audio-video.quicktime.php @@ -22,19 +22,19 @@ // // $Id: module.audio-video.quicktime.php,v 1.7 2006/11/02 16:03:28 ah Exp $ - - + + class getid3_quicktime extends getid3_handler { public function Analyze() { - + $getid3 = $this->getid3; $info = &$getid3->info; - + $getid3->include_module('audio.mp3'); - + $info['quicktime'] = array (); $info_quicktime = &$info['quicktime']; @@ -52,7 +52,7 @@ class getid3_quicktime extends getid3_handler $atom_size = getid3_lib::BigEndian2Int(substr($atom_header, 0, 4)); $atom_name = substr($atom_header, 4, 4); - + $info_quicktime[$atom_name]['name'] = $atom_name; $info_quicktime[$atom_name]['size'] = $atom_size; $info_quicktime[$atom_name]['offset'] = $offset; @@ -67,9 +67,9 @@ class getid3_quicktime extends getid3_handler // to read user data atoms, you should allow for the terminating 0. break; } - + switch ($atom_name) { - + case 'mdat': // Media DATa atom // 'mdat' contains the actual data for the audio/video if (($atom_size > 8) && (!isset($info['avdataend_tmp']) || ($info_quicktime[$atom_name]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) { @@ -78,28 +78,28 @@ class getid3_quicktime extends getid3_handler $old_av_data_end = $info['avdataend']; $info['avdataend'] = $info_quicktime[$atom_name]['offset'] + $info_quicktime[$atom_name]['size']; - + //// MP3 - + if (!$getid3->include_module_optional('audio.mp3')) { $getid3->warning('MP3 skipped because mpeg module is missing.'); } - + else { - + // Clone getid3 - messing with offsets - better safe than sorry $clone = clone $getid3; - + if (getid3_mp3::MPEGaudioHeaderValid(getid3_mp3::MPEGaudioHeaderDecode(fread($clone->fp, 4)))) { - + $mp3 = new getid3_mp3($clone); $mp3->AnalyzeMPEGaudioInfo(); - + // Import from clone and destroy if (isset($clone->info['mpeg']['audio'])) { - + $info['mpeg']['audio'] = $clone->info['mpeg']['audio']; - + $info['audio']['dataformat'] = 'mp3'; $info['audio']['codec'] = (!empty($info['mpeg']['audio']['encoder']) ? $info['mpeg']['audio']['encoder'] : (!empty($info['mpeg']['audio']['codec']) ? $info['mpeg']['audio']['codec'] : (!empty($info['mpeg']['audio']['LAME']) ? 'LAME' :'mp3'))); $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate']; @@ -107,19 +107,19 @@ class getid3_quicktime extends getid3_handler $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate']; $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']); $info['bitrate'] = $info['audio']['bitrate']; - + $getid3->warning($clone->warnings()); unset($clone); } } } - + $info['avdataend'] = $old_av_data_end; unset($old_av_data_end); } break; - + case 'free': // FREE space atom case 'skip': // SKIP atom @@ -148,11 +148,23 @@ class getid3_quicktime extends getid3_handler if (!isset($info['bitrate']) && isset($info['playtime_seconds'])) { $info['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds']; } - + if (isset($info['bitrate']) && !isset($info['audio']['bitrate']) && !isset($info_quicktime['video'])) { $info['audio']['bitrate'] = $info['bitrate']; } + if (@$info['playtime_seconds'] && !isset($info['video']['frame_rate']) && !empty($info['quicktime']['stts_framecount'])) { + foreach ($info['quicktime']['stts_framecount'] as $key => $samples_count) { + $samples_per_second = $samples_count / $info['playtime_seconds']; + if ($samples_per_second > 240) { + // has to be audio samples + } else { + $info['video']['frame_rate'] = $samples_per_second; + break; + } + } + } + if ((@$info['audio']['dataformat'] == 'mp4') && empty($info['video']['resolution_x'])) { $info['fileformat'] = 'mp4'; $info['mime_type'] = 'audio/mp4'; @@ -166,7 +178,7 @@ class getid3_quicktime extends getid3_handler if (empty($info['audio']['dataformat']) && !empty($info_quicktime['audio'])) { $info['audio']['dataformat'] = 'quicktime'; } - + if (empty($info['video']['dataformat']) && !empty($info_quicktime['video'])) { $info['video']['dataformat'] = 'quicktime'; } @@ -177,11 +189,11 @@ class getid3_quicktime extends getid3_handler private function QuicktimeParseAtom($atom_name, $atom_size, $atom_data, $base_offset, &$atom_hierarchy) { - + // http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm - + $getid3 = $this->getid3; - + $info = &$getid3->info; $info_quicktime = &$info['quicktime']; @@ -311,17 +323,17 @@ class getid3_quicktime extends getid3_handler case 'rdrf': // Reference movie Data ReFerence atom - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( - 'version' => 1, - 'flags_raw' => 3, + 'version' => 1, + 'flags_raw' => 3, 'reference_type_name' => -4, - 'reference_length' => 4, + 'reference_length' => 4, ) ); - + $atom_structure['flags']['internal_data'] = (bool)($atom_structure['flags_raw'] & 0x000001); - + switch ($atom_structure['reference_type_name']) { case 'url ': $atom_structure['url'] = $this->NoNullString(substr($atom_data, 12)); @@ -348,7 +360,7 @@ class getid3_quicktime extends getid3_handler case 'rmcs': // Reference Movie Cpu Speed atom - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( 'version' => 1, 'flags_raw' => 3, // hardcoded: 0x0000 @@ -359,7 +371,7 @@ class getid3_quicktime extends getid3_handler case 'rmvc': // Reference Movie Version Check atom - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( 'version' => 1, 'flags_raw' => 3, // hardcoded: 0x0000 @@ -373,7 +385,7 @@ class getid3_quicktime extends getid3_handler case 'rmcd': // Reference Movie Component check atom - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( 'version' => 1, 'flags_raw' => 3, // hardcoded: 0x0000 @@ -389,7 +401,7 @@ class getid3_quicktime extends getid3_handler case 'rmdr': // Reference Movie Data Rate atom - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( 'version' => 1, 'flags_raw' => 3, // hardcoded: 0x0000 @@ -402,7 +414,7 @@ class getid3_quicktime extends getid3_handler case 'rmla': // Reference Movie Language Atom - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( 'version' => 1, 'flags_raw' => 3, // hardcoded: 0x0000 @@ -418,7 +430,7 @@ class getid3_quicktime extends getid3_handler case 'rmla': // Reference Movie Language Atom - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( 'version' => 1, 'flags_raw' => 3, // hardcoded: 0x0000 @@ -430,7 +442,7 @@ class getid3_quicktime extends getid3_handler case 'ptv ': // Print To Video - defines a movie's full screen mode // http://developer.apple.com/documentation/QuickTime/APIREF/SOURCESIV/at_ptv-_pg.htm - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( 'display_size_raw' => 2, 'reserved_1' => 2, // hardcoded: 0x0000 @@ -457,7 +469,7 @@ class getid3_quicktime extends getid3_handler case 'stsd': // Sample Table Sample Description atom - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( 'version' => 1, 'flags_raw' => 3, // hardcoded: 0x0000 @@ -466,8 +478,8 @@ class getid3_quicktime extends getid3_handler ); $stsd_entries_data_offset = 8; for ($i = 0; $i < $atom_structure['number_entries']; $i++) { - - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure['sample_description_table'][$i], $atom_data, $stsd_entries_data_offset, + + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure['sample_description_table'][$i], $atom_data, $stsd_entries_data_offset, array ( 'size' => 4, 'data_format' => -4, @@ -499,7 +511,7 @@ class getid3_quicktime extends getid3_handler 'audio_packet_size' => 2 ) ); - + $atom_structure['sample_description_table'][$i]['audio_sample_rate'] = getid3_quicktime::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 16, 4)); switch ($atom_structure['sample_description_table'][$i]['data_format']) { @@ -554,7 +566,7 @@ class getid3_quicktime extends getid3_handler $atom_structure['sample_description_table'][$i]['video_resolution_x'] = getid3_quicktime::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 20, 4)); $atom_structure['sample_description_table'][$i]['video_resolution_y'] = getid3_quicktime::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24, 4)); getid3_lib::ReadSequence('BigEndian2Int', $atom_structure['sample_description_table'][$i], $atom_structure['sample_description_table'][$i]['data'], 28, - array ( + array ( 'video_data_size' => 4, 'video_frame_count' => 2, 'video_encoder_name_len' => 1 @@ -622,53 +634,38 @@ class getid3_quicktime extends getid3_handler case 'stts': // Sample Table Time-to-Sample atom - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( 'version' => 1, 'flags_raw' => 3, // hardcoded: 0x0000 'number_entries' => 4 ) ); - + $stts_entries_data_offset = 8; - $frame_rate_calculator_array = array (); + //$frame_rate_calculator_array = array (); + $frames_count = 0; for ($i = 0; $i < $atom_structure['number_entries']; $i++) { - + $atom_structure['time_to_sample_table'][$i]['sample_count'] = getid3_lib::BigEndian2Int(substr($atom_data, $stts_entries_data_offset, 4)); $stts_entries_data_offset += 4; - + $atom_structure['time_to_sample_table'][$i]['sample_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, $stts_entries_data_offset, 4)); $stts_entries_data_offset += 4; - if (!empty($info_quicktime['time_scale']) && (@$atoms_structure['time_to_sample_table'][$i]['sample_duration'] > 0)) { + $frames_count += $atom_structure['time_to_sample_table'][$i]['sample_count']; - $stts_new_framerate = $info_quicktime['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration']; - if ($stts_new_framerate <= 60) { - // some atoms have durations of "1" giving a very large framerate, which probably is not right - $info['video']['frame_rate'] = max(@$info['video']['frame_rate'], $stts_new_framerate); - } - } + //if (!empty($info_quicktime['time_scale']) && (@$atoms_structure['time_to_sample_table'][$i]['sample_duration'] > 0)) { + // + // $stts_new_framerate = $info_quicktime['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration']; + // if ($stts_new_framerate <= 60) { + // // some atoms have durations of "1" giving a very large framerate, which probably is not right + // $info['video']['frame_rate'] = max(@$info['video']['frame_rate'], $stts_new_framerate); + // } + //} //@$frame_rate_calculator_array[($info_quicktime['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'])] += $atom_structure['time_to_sample_table'][$i]['sample_count']; } - /* - $stts_frames_total = 0; - $stts_seconds_total = 0; - foreach ($frame_rate_calculator_array as $frames_per_second => $frame_count) { - if (($frames_per_second > 60) || ($frames_per_second < 1)) { - // not video FPS information, probably audio information - $stts_frames_total = 0; - $stts_seconds_total = 0; - break; - } - $stts_frames_total += $frame_count; - $stts_seconds_total += $frame_count / $frames_per_second; - } - if (($stts_frames_total > 0) && ($stts_seconds_total > 0)) { - if (($stts_frames_total / $stts_seconds_total) > @$info['video']['frame_rate']) { - $info['video']['frame_rate'] = $stts_frames_total / $stts_seconds_total; - } - } - */ + $info['quicktime']['stts_framecount'][] = $frames_count; break; @@ -736,18 +733,18 @@ class getid3_quicktime extends getid3_handler case 'dref': // Data REFerence atom - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( 'version' => 1, 'flags_raw' => 3, // hardcoded: 0x0000 'number_entries' => 4 ) ); - + $dref_data_offset = 8; for ($i = 0; $i < $atom_structure['number_entries']; $i++) { - - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure['data_references'][$i], $atom_data, $dref_data_offset, + + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure['data_references'][$i], $atom_data, $dref_data_offset, array ( 'size' => 4, 'type' => -4, @@ -756,7 +753,7 @@ class getid3_quicktime extends getid3_handler ) ); $dref_data_offset += 12; - + $atom_structure['data_references'][$i]['data'] = substr($atom_data, $dref_data_offset, ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3)); $dref_data_offset += ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3); @@ -766,7 +763,7 @@ class getid3_quicktime extends getid3_handler case 'gmin': // base Media INformation atom - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( 'version' => 1, 'flags_raw' => 3, // hardcoded: 0x0000 @@ -782,7 +779,7 @@ class getid3_quicktime extends getid3_handler case 'smhd': // Sound Media information HeaDer atom - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( 'version' => 1, 'flags_raw' => 3, // hardcoded: 0x0000 @@ -794,7 +791,7 @@ class getid3_quicktime extends getid3_handler case 'vmhd': // Video Media information HeaDer atom - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( 'version' => 1, 'flags_raw' => 3, @@ -809,7 +806,7 @@ class getid3_quicktime extends getid3_handler case 'hdlr': // HanDLeR reference atom - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( 'version' => 1, 'flags_raw' => 3, // hardcoded: 0x0000 @@ -830,7 +827,7 @@ class getid3_quicktime extends getid3_handler case 'mdhd': // MeDia HeaDer atom - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( 'version' => 1, 'flags_raw' => 3, // hardcoded: 0x0000 @@ -847,7 +844,7 @@ class getid3_quicktime extends getid3_handler throw new getid3_exception('Corrupt Quicktime file: mdhd.time_scale == zero'); } $info_quicktime['time_scale'] = max(@$info['quicktime']['time_scale'], $atom_structure['time_scale']); - + $atom_structure['creation_time_unix'] = (int)($atom_structure['creation_time'] - 2082844800); // DateMac2Unix() $atom_structure['modify_time_unix'] = (int)($atom_structure['modify_time'] - 2082844800); // DateMac2Unix() $atom_structure['playtime_seconds'] = $atom_structure['duration'] / $atom_structure['time_scale']; @@ -859,7 +856,7 @@ class getid3_quicktime extends getid3_handler case 'pnot': // Preview atom - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( 'modification_date' => 4, // "standard Macintosh format" 'version_number' => 2, // hardcoded: 0x00 @@ -879,7 +876,7 @@ class getid3_quicktime extends getid3_handler case 'load': // track LOAD settings atom - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( 'preload_start_time' => 4, 'preload_duration' => 4, @@ -905,14 +902,14 @@ class getid3_quicktime extends getid3_handler case 'elst': // Edit LiST atom - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( 'version' => 1, 'flags_raw' => 3, // hardcoded: 0x0000 'number_entries' => 4 ) - ); - + ); + for ($i = 0; $i < $atom_structure['number_entries']; $i++ ) { $atom_structure['edit_list'][$i]['track_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 0, 4)); $atom_structure['edit_list'][$i]['media_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 4, 4)); @@ -942,7 +939,7 @@ class getid3_quicktime extends getid3_handler case 'mvhd': // MoVie HeaDer atom - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( 'version' => 1, 'flags_raw' => 3, @@ -965,8 +962,8 @@ class getid3_quicktime extends getid3_handler $atom_structure['matrix_x'] = getid3_quicktime::FixedPoint16_16(substr($atom_data, 60, 4)); $atom_structure['matrix_y'] = getid3_quicktime::FixedPoint16_16(substr($atom_data, 64, 4)); $atom_structure['matrix_w'] = getid3_quicktime::FixedPoint2_30(substr($atom_data, 68, 4)); - - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 72, + + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 72, array ( 'preview_time' => 4, 'preview_duration' => 4, @@ -981,7 +978,7 @@ class getid3_quicktime extends getid3_handler if ($atom_structure['time_scale'] == 0) { throw new getid3_exception('Corrupt Quicktime file: mvhd.time_scale == zero'); } - + $atom_structure['creation_time_unix'] = (int)($atom_structure['creation_time'] - 2082844800); // DateMac2Unix() $atom_structure['modify_time_unix'] = (int)($atom_structure['modify_time'] - 2082844800); // DateMac2Unix() $info_quicktime['time_scale'] = max(@$info['quicktime']['time_scale'], $atom_structure['time_scale']); @@ -991,7 +988,7 @@ class getid3_quicktime extends getid3_handler case 'tkhd': // TracK HeaDer atom - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( 'version' => 1, 'flags_raw' => 3, @@ -1005,7 +1002,7 @@ class getid3_quicktime extends getid3_handler 'alternate_group' => 2 ) ); - + $atom_structure['volume'] = getid3_quicktime::FixedPoint8_8(substr($atom_data, 36, 2)); $atom_structure['reserved3'] = getid3_lib::BigEndian2Int(substr($atom_data, 38, 2)); $atom_structure['matrix_a'] = getid3_quicktime::FixedPoint16_16(substr($atom_data, 40, 4)); @@ -1031,12 +1028,12 @@ class getid3_quicktime extends getid3_handler $info['video']['resolution_x'] = $atom_structure['width']; $info['video']['resolution_y'] = $atom_structure['height']; } - + if ($atom_structure['flags']['enabled'] == 1) { $info['video']['resolution_x'] = max($info['video']['resolution_x'], $atom_structure['width']); $info['video']['resolution_y'] = max($info['video']['resolution_y'], $atom_structure['height']); } - + if (!empty($info['video']['resolution_x']) && !empty($info['video']['resolution_y'])) { $info_quicktime['video']['resolution_x'] = $info['video']['resolution_x']; $info_quicktime['video']['resolution_y'] = $info['video']['resolution_y']; @@ -1066,7 +1063,7 @@ class getid3_quicktime extends getid3_handler break; case 'ftyp': // FileTYPe (?) atom (for MP4 it seems) - getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, array ( 'signature' => -4, 'unknown_1' => 4, @@ -1113,7 +1110,7 @@ class getid3_quicktime extends getid3_handler case 'pano': // PANOrama track (seen on QTVR) $atom_structure['pano'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); break; - + case 'hint': // HINT track case 'hinf': // case 'hinv': // @@ -1148,20 +1145,20 @@ class getid3_quicktime extends getid3_handler private function QuicktimeParseContainerAtom($atom_data, $base_offset, &$atom_hierarchy) { - + if ((strlen($atom_data) == 4) && (getid3_lib::BigEndian2Int($atom_data) == 0x00000000)) { return false; } - + $atom_structure = false; $subatom_offset = 0; - + while ($subatom_offset < strlen($atom_data)) { - + $subatom_size = getid3_lib::BigEndian2Int(substr($atom_data, $subatom_offset + 0, 4)); $subatom_name = substr($atom_data, $subatom_offset + 4, 4); $subatom_data = substr($atom_data, $subatom_offset + 8, $subatom_size - 8); - + if ($subatom_size == 0) { // Furthermore, for historical reasons the list of atoms is optionally // terminated by a 32-bit integer set to 0. If you are writing a program @@ -1175,9 +1172,9 @@ class getid3_quicktime extends getid3_handler } return $atom_structure; } - - - + + + private function CopyToAppropriateCommentsSection($key_name, $data) { // http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt @@ -1344,7 +1341,7 @@ class getid3_quicktime extends getid3_handler 137 => 'Dzongkha', 138 => 'JavaneseRom' ); - + return (isset($lookup[$language_id]) ? $lookup[$language_id] : 'invalid'); } @@ -1405,7 +1402,7 @@ class getid3_quicktime extends getid3_handler 'WRAW' => 'Windows RAW', 'y420' => 'YUV420' ); - + return (isset($lookup[$codec_id]) ? $lookup[$codec_id] : ''); } @@ -1453,7 +1450,7 @@ class getid3_quicktime extends getid3_handler 'twos' => 'signed/two\'s complement (Big Endian)', 'ulaw' => 'mu-law 2:1', ); - + return (isset($lookup[$codec_id]) ? $lookup[$codec_id] : ''); } @@ -1472,7 +1469,7 @@ class getid3_quicktime extends getid3_handler public static function QuicktimeColorNameLookup($color_depth_id) { - + static $lookup = array ( 1 => '2-color (monochrome)', 2 => '4-color', @@ -1486,7 +1483,7 @@ class getid3_quicktime extends getid3_handler 36 => '16-gray', 40 => '256-gray', ); - + return (isset($lookup[$color_depth_id]) ? $lookup[$color_depth_id] : 'invalid'); } @@ -1498,12 +1495,12 @@ class getid3_quicktime extends getid3_handler if (substr($null_terminated_string, strlen($null_terminated_string) - 1, 1) === "\x00") { return substr($null_terminated_string, 0, strlen($null_terminated_string) - 1); } - + return $null_terminated_string; } - - - + + + public static function FixedPoint8_8($raw_data) { return getid3_lib::BigEndian2Int($raw_data{0}) + (float)(getid3_lib::BigEndian2Int($raw_data{1}) / 256); @@ -1512,14 +1509,14 @@ class getid3_quicktime extends getid3_handler public static function FixedPoint16_16($raw_data) { - + return getid3_lib::BigEndian2Int(substr($raw_data, 0, 2)) + (float)(getid3_lib::BigEndian2Int(substr($raw_data, 2, 2)) / 65536); } public static function FixedPoint2_30($raw_data) { - + $binary_string = getid3_lib::BigEndian2Bin($raw_data); return bindec(substr($binary_string, 0, 2)) + (float)(bindec(substr($binary_string, 2, 30)) / 1073741824); } diff --git a/modules/getid3/module.audio.aac_adts.php b/modules/getid3/module.audio.aac_adts.php index 1a3f39f5..aa7f8f73 100644 --- a/modules/getid3/module.audio.aac_adts.php +++ b/modules/getid3/module.audio.aac_adts.php @@ -93,8 +93,7 @@ class getid3_aac_adts extends getid3_handler $info_aac = &$getid3->info['aac']; $info_aac_header = & $info_aac['header']; - $byte_offset = $getid3->info['avdataoffset']; - $frame_number = 0; + $byte_offset = $frame_number = 0; while (true) { @@ -280,4 +279,4 @@ class getid3_aac_adts extends getid3_handler } -?> +?>
\ No newline at end of file diff --git a/modules/getid3/module.audio.mpc.php b/modules/getid3/module.audio.mpc7.php index 59d2802e..2671c909 100644 --- a/modules/getid3/module.audio.mpc.php +++ b/modules/getid3/module.audio.mpc7.php @@ -1,35 +1,35 @@ <?php -// +----------------------------------------------------------------------+
-// | PHP version 5 |
-// +----------------------------------------------------------------------+
-// | Copyright (c) 2002-2006 James Heinrich, Allan Hansen |
-// +----------------------------------------------------------------------+
-// | This source file is subject to version 2 of the GPL license, |
-// | that is bundled with this package in the file license.txt and is |
-// | available through the world-wide-web at the following url: |
+// +----------------------------------------------------------------------+ +// | PHP version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 2002-2006 James Heinrich, Allan Hansen | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 2 of the GPL license, | +// | that is bundled with this package in the file license.txt and is | +// | available through the world-wide-web at the following url: | // | http://www.gnu.org/copyleft/gpl.html | // +----------------------------------------------------------------------+ // | getID3() - http://getid3.sourceforge.net or http://www.getid3.org | -// +----------------------------------------------------------------------+
-// | Authors: James Heinrich <infogetid3*org> |
-// | Allan Hansen <ahartemis*dk> |
+// +----------------------------------------------------------------------+ +// | Authors: James Heinrich <infoetid3*org> | +// | Allan Hansen <ahartemis*dk> | // +----------------------------------------------------------------------+ // | module.audio.mpc.php | // | Module for analyzing Musepack/MPEG+ Audio files | // | dependencies: NONE | -// +----------------------------------------------------------------------+
-//
-// $Id: module.audio.mpc.php,v 1.3 2006/11/02 10:48:01 ah Exp $ +// +----------------------------------------------------------------------+ +// +// $Id$ + + - - -class getid3_mpc extends getid3_handler +class getid3_mpc7 extends getid3_handler { public function Analyze() { $getid3 = $this->getid3; - + // http://www.uni-jena.de/~pfk/mpp/sv8/header.html $getid3->info['fileformat'] = 'mpc'; @@ -37,83 +37,83 @@ class getid3_mpc extends getid3_handler $getid3->info['audio']['bitrate_mode'] = 'vbr'; $getid3->info['audio']['channels'] = 2; // the format appears to be hardcoded for stereo only $getid3->info['audio']['lossless'] = false; - + $getid3->info['mpc']['header'] = array (); $info_mpc_header = &$getid3->info['mpc']['header']; $info_mpc_header['size'] = 28; $info_mpc_header['raw']['preamble'] = 'MP+'; // Magic bytes - + fseek($getid3->fp, $getid3->info['avdataoffset'], SEEK_SET); $mpc_header_data = fread($getid3->fp, 28); - + $stream_version_byte = getid3_lib::LittleEndian2Int(substr($mpc_header_data, 3, 1)); $info_mpc_header['stream_major_version'] = ($stream_version_byte & 0x0F); $info_mpc_header['stream_minor_version'] = ($stream_version_byte & 0xF0) >> 4; if ($info_mpc_header['stream_major_version'] != 7) { throw new getid3_exception('Only Musepack SV7 supported'); } - + $info_mpc_header['frame_count'] = getid3_lib::LittleEndian2Int(substr($mpc_header_data, 4, 4)); - + $info_mpc_header['raw']['title_peak'] = getid3_lib::LittleEndian2Int(substr($mpc_header_data, 12, 2)); $info_mpc_header['raw']['title_gain'] = getid3_lib::LittleEndian2Int(substr($mpc_header_data, 14, 2), true); $info_mpc_header['raw']['album_peak'] = getid3_lib::LittleEndian2Int(substr($mpc_header_data, 16, 2)); $info_mpc_header['raw']['album_gain'] = getid3_lib::LittleEndian2Int(substr($mpc_header_data, 18, 2), true); - + $info_mpc_header['raw']['not_sure_what'] = getid3_lib::LittleEndian2Int(substr($mpc_header_data, 24, 3)); $info_mpc_header['raw']['encoder_version'] = getid3_lib::LittleEndian2Int(substr($mpc_header_data, 27, 1)); - - $flags_dword1 = getid3_lib::LittleEndian2Int(substr($mpc_header_data, 8, 4)); + + $flags_dword1 = getid3_lib::LittleEndian2Int(substr($mpc_header_data, 8, 4)); $flags_dword2 = getid3_lib::LittleEndian2Int(substr($mpc_header_data, 20, 4)); - - $info_mpc_header['intensity_stereo'] = (bool)(($flags_dword1 & 0x80000000) >> 31); - $info_mpc_header['mid_side_stereo'] = (bool)(($flags_dword1 & 0x40000000) >> 30); + + $info_mpc_header['intensity_stereo'] = (bool) (($flags_dword1 & 0x80000000) >> 31); + $info_mpc_header['mid_side_stereo'] = (bool) (($flags_dword1 & 0x40000000) >> 30); $info_mpc_header['max_subband'] = ($flags_dword1 & 0x3F000000) >> 24; $info_mpc_header['raw']['profile'] = ($flags_dword1 & 0x00F00000) >> 20; - $info_mpc_header['begin_loud'] = (bool)(($flags_dword1 & 0x00080000) >> 19); - $info_mpc_header['end_loud'] = (bool)(($flags_dword1 & 0x00040000) >> 18); + $info_mpc_header['begin_loud'] = (bool) (($flags_dword1 & 0x00080000) >> 19); + $info_mpc_header['end_loud'] = (bool) (($flags_dword1 & 0x00040000) >> 18); $info_mpc_header['raw']['sample_rate'] = ($flags_dword1 & 0x00030000) >> 16; $info_mpc_header['max_level'] = ($flags_dword1 & 0x0000FFFF); - - $info_mpc_header['true_gapless'] = (bool)(($flags_dword2 & 0x80000000) >> 31); + + $info_mpc_header['true_gapless'] = (bool) (($flags_dword2 & 0x80000000) >> 31); $info_mpc_header['last_frame_length'] = ($flags_dword2 & 0x7FF00000) >> 20; - - $info_mpc_header['profile'] = getid3_mpc::MPCprofileNameLookup($info_mpc_header['raw']['profile']); - $info_mpc_header['sample_rate'] = getid3_mpc::MPCfrequencyLookup($info_mpc_header['raw']['sample_rate']); + + $info_mpc_header['profile'] = getid3_mpc7::MPCprofileNameLookup($info_mpc_header['raw']['profile']); + $info_mpc_header['sample_rate'] = getid3_mpc7::MPCfrequencyLookup($info_mpc_header['raw']['sample_rate']); $getid3->info['audio']['sample_rate'] = $info_mpc_header['sample_rate']; $info_mpc_header['samples'] = ((($info_mpc_header['frame_count'] - 1) * 1152) + $info_mpc_header['last_frame_length']) * $getid3->info['audio']['channels']; $getid3->info['playtime_seconds'] = ($info_mpc_header['samples'] / $getid3->info['audio']['channels']) / $getid3->info['audio']['sample_rate']; $getid3->info['avdataoffset'] += $info_mpc_header['size']; - + $getid3->info['audio']['bitrate'] = (($getid3->info['avdataend'] - $getid3->info['avdataoffset']) * 8) / $getid3->info['playtime_seconds']; $info_mpc_header['title_peak'] = $info_mpc_header['raw']['title_peak']; - $info_mpc_header['title_peak_db'] = getid3_mpc::MPCpeakDBLookup($info_mpc_header['title_peak']); + $info_mpc_header['title_peak_db'] = getid3_mpc7::MPCpeakDBLookup($info_mpc_header['title_peak']); if ($info_mpc_header['raw']['title_gain'] < 0) { $info_mpc_header['title_gain_db'] = (float)(32768 + $info_mpc_header['raw']['title_gain']) / -100; - } + } else { $info_mpc_header['title_gain_db'] = (float)$info_mpc_header['raw']['title_gain'] / 100; } $info_mpc_header['album_peak'] = $info_mpc_header['raw']['album_peak']; - $info_mpc_header['album_peak_db'] = getid3_mpc::MPCpeakDBLookup($info_mpc_header['album_peak']); + $info_mpc_header['album_peak_db'] = getid3_mpc7::MPCpeakDBLookup($info_mpc_header['album_peak']); if ($info_mpc_header['raw']['album_gain'] < 0) { $info_mpc_header['album_gain_db'] = (float)(32768 + $info_mpc_header['raw']['album_gain']) / -100; - } + } else { $info_mpc_header['album_gain_db'] = (float)$info_mpc_header['raw']['album_gain'] / 100;; } - $info_mpc_header['encoder_version'] = getid3_mpc::MPCencoderVersionLookup($info_mpc_header['raw']['encoder_version']); + $info_mpc_header['encoder_version'] = getid3_mpc7::MPCencoderVersionLookup($info_mpc_header['raw']['encoder_version']); $getid3->info['replay_gain']['track']['adjustment'] = $info_mpc_header['title_gain_db']; $getid3->info['replay_gain']['album']['adjustment'] = $info_mpc_header['album_gain_db']; if ($info_mpc_header['title_peak'] > 0) { $getid3->info['replay_gain']['track']['peak'] = $info_mpc_header['title_peak']; - } + } elseif (round($info_mpc_header['max_level'] * 1.18) > 0) { $getid3->info['replay_gain']['track']['peak'] = (int)(round($info_mpc_header['max_level'] * 1.18)); // why? I don't know - see mppdec.c } @@ -123,14 +123,14 @@ class getid3_mpc extends getid3_handler $getid3->info['audio']['encoder'] = $info_mpc_header['encoder_version']; $getid3->info['audio']['encoder_options'] = $info_mpc_header['profile']; - + return true; } public static function MPCprofileNameLookup($profileid) { - + static $lookup = array ( 0 => 'no profile', 1 => 'Experimental', @@ -155,7 +155,7 @@ class getid3_mpc extends getid3_handler public static function MPCfrequencyLookup($frequencyid) { - + static $lookup = array ( 0 => 44100, 1 => 48000, @@ -168,7 +168,7 @@ class getid3_mpc extends getid3_handler public static function MPCpeakDBLookup($int_value) { - + if ($int_value > 0) { return ((log10($int_value) / log10(2)) - 15) * 6; } @@ -178,7 +178,7 @@ class getid3_mpc extends getid3_handler public static function MPCencoderVersionLookup($encoder_version) { - + //Encoder version * 100 (106 = 1.06) //EncoderVersion % 10 == 0 Release (1.0) //EncoderVersion % 2 == 0 Beta (1.06) @@ -208,4 +208,4 @@ class getid3_mpc extends getid3_handler } -?>
\ No newline at end of file +?> diff --git a/modules/getid3/module.audio.mpc8.php b/modules/getid3/module.audio.mpc8.php new file mode 100644 index 00000000..8de44186 --- /dev/null +++ b/modules/getid3/module.audio.mpc8.php @@ -0,0 +1,324 @@ +<?php +// +----------------------------------------------------------------------+ +// | PHP version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 2002-2006 James Heinrich, Allan Hansen | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 2 of the GPL license, | +// | that is bundled with this package in the file license.txt and is | +// | available through the world-wide-web at the following url: | +// | http://www.gnu.org/copyleft/gpl.html | +// +----------------------------------------------------------------------+ +// | getID3() - http://getid3.sourceforge.net or http://www.getid3.org | +// +----------------------------------------------------------------------+ +// | Authors: James Heinrich <infoetid3*org> | +// | Allan Hansen <ahartemis*dk> | +// +----------------------------------------------------------------------+ +// | module.audio.mpc.php | +// | Module for analyzing Musepack/MPEG+ Audio files | +// | dependencies: NONE | +// +----------------------------------------------------------------------+ +// +// $Id$ + + + +class getid3_mpc8 extends getid3_handler +{ + + public function Analyze() { + $getid3 = $this->getid3; + + $getid3->info['fileformat'] = 'mpc'; + $getid3->info['audio']['dataformat'] = 'mpc'; + $getid3->info['audio']['bitrate_mode'] = 'vbr'; + $getid3->info['audio']['lossless'] = false; + + fseek($getid3->fp, $getid3->info['avdataoffset'], SEEK_SET); + $MPCheaderData = fread($getid3->fp, 4); + $getid3->info['mpc']['header']['preamble'] = substr($MPCheaderData, 0, 4); // should be 'MPCK' (SV8) or 'MP+' (SV7), otherwise possible stream data (SV4-SV6) + if (ereg('^MPCK', $getid3->info['mpc']['header']['preamble'])) { + + // this is SV8 + // http://trac.musepack.net/trac/wiki/SV8Specification + + $thisfile_mpc_header = &$getid3->info['mpc']['header']; + + $keyNameSize = 2; + $maxHandledPacketLength = 9; // specs say: "n*8; 0 < n < 10" + + $offset = ftell($getid3->fp); + while ($offset < $getid3->info['avdataend']) { + $thisPacket = array(); + $thisPacket['offset'] = $offset; + $packet_offset = 0; + + // Size is a variable-size field, could be 1-4 bytes (possibly more?) + // read enough data in and figure out the exact size later + $MPCheaderData = fread($getid3->fp, $keyNameSize + $maxHandledPacketLength); + $packet_offset += $keyNameSize; + $thisPacket['key'] = substr($MPCheaderData, 0, $keyNameSize); + $thisPacket['key_name'] = $this->MPCsv8PacketName($thisPacket['key']); + if ($thisPacket['key'] == $thisPacket['key_name']) { + $getid3->info['error'][] = 'Found unexpected key value "'.$thisPacket['key'].'" at offset '.$thisPacket['offset']; + return false; + } + $packetLength = 0; + $thisPacket['packet_size'] = $this->SV8variableLengthInteger(substr($MPCheaderData, $keyNameSize), $packetLength); // includes keyname and packet_size field + if ($thisPacket['packet_size'] === false) { + $getid3->info['error'][] = 'Did not find expected packet length within '.$maxHandledPacketLength.' bytes at offset '.($thisPacket['offset'] + $keyNameSize); + return false; + } + $packet_offset += $packetLength; + $offset += $thisPacket['packet_size']; + + switch ($thisPacket['key']) { + case 'SH': // Stream Header + $moreBytesToRead = $thisPacket['packet_size'] - $keyNameSize - $maxHandledPacketLength; + if ($moreBytesToRead > 0) { + $MPCheaderData .= fread($getid3->fp, $moreBytesToRead); + } + $thisPacket['crc'] = getid3_lib::BigEndian2Int(substr($MPCheaderData, $packet_offset, 4)); + $packet_offset += 4; + $thisPacket['stream_version'] = getid3_lib::BigEndian2Int(substr($MPCheaderData, $packet_offset, 1)); + $packet_offset += 1; + + $packetLength = 0; + $thisPacket['sample_count'] = $this->SV8variableLengthInteger(substr($MPCheaderData, $packet_offset, $maxHandledPacketLength), $packetLength); + $packet_offset += $packetLength; + + $packetLength = 0; + $thisPacket['beginning_silence'] = $this->SV8variableLengthInteger(substr($MPCheaderData, $packet_offset, $maxHandledPacketLength), $packetLength); + $packet_offset += $packetLength; + + $otherUsefulData = getid3_lib::BigEndian2Int(substr($MPCheaderData, $packet_offset, 2)); + $packet_offset += 2; + $thisPacket['sample_frequency_raw'] = (($otherUsefulData & 0xE000) >> 13); + $thisPacket['max_bands_used'] = (($otherUsefulData & 0x1F00) >> 8); + $thisPacket['channels'] = (($otherUsefulData & 0x00F0) >> 4) + 1; + $thisPacket['ms_used'] = (bool) (($otherUsefulData & 0x0008) >> 3); + $thisPacket['audio_block_frames'] = (($otherUsefulData & 0x0007) >> 0); + $thisPacket['sample_frequency'] = $this->MPCfrequencyLookup($thisPacket['sample_frequency_raw']); + + $thisfile_mpc_header['mid_side_stereo'] = $thisPacket['ms_used']; + $thisfile_mpc_header['sample_rate'] = $thisPacket['sample_frequency']; + $thisfile_mpc_header['samples'] = $thisPacket['sample_count']; + $thisfile_mpc_header['stream_version_major'] = $thisPacket['stream_version']; + + $getid3->info['audio']['channels'] = $thisPacket['channels']; + $getid3->info['audio']['sample_rate'] = $thisPacket['sample_frequency']; + $getid3->info['playtime_seconds'] = $thisPacket['sample_count'] / $thisPacket['sample_frequency']; + $getid3->info['audio']['bitrate'] = (($getid3->info['avdataend'] - $getid3->info['avdataoffset']) * 8) / $getid3->info['playtime_seconds']; + break; + + case 'RG': // Replay Gain + $moreBytesToRead = $thisPacket['packet_size'] - $keyNameSize - $maxHandledPacketLength; + if ($moreBytesToRead > 0) { + $MPCheaderData .= fread($getid3->fp, $moreBytesToRead); + } + $thisPacket['replaygain_version'] = getid3_lib::BigEndian2Int(substr($MPCheaderData, $packet_offset, 1)); + $packet_offset += 1; + $thisPacket['replaygain_title_gain'] = getid3_lib::BigEndian2Int(substr($MPCheaderData, $packet_offset, 2)); + $packet_offset += 2; + $thisPacket['replaygain_title_peak'] = getid3_lib::BigEndian2Int(substr($MPCheaderData, $packet_offset, 2)); + $packet_offset += 2; + $thisPacket['replaygain_album_gain'] = getid3_lib::BigEndian2Int(substr($MPCheaderData, $packet_offset, 2)); + $packet_offset += 2; + $thisPacket['replaygain_album_peak'] = getid3_lib::BigEndian2Int(substr($MPCheaderData, $packet_offset, 2)); + $packet_offset += 2; + + if ($thisPacket['replaygain_title_gain']) { $getid3->info['replay_gain']['title']['gain'] = $thisPacket['replaygain_title_gain']; } + if ($thisPacket['replaygain_title_peak']) { $getid3->info['replay_gain']['title']['peak'] = $thisPacket['replaygain_title_peak']; } + if ($thisPacket['replaygain_album_gain']) { $getid3->info['replay_gain']['album']['gain'] = $thisPacket['replaygain_album_gain']; } + if ($thisPacket['replaygain_album_peak']) { $getid3->info['replay_gain']['album']['peak'] = $thisPacket['replaygain_album_peak']; } + break; + + case 'EI': // Encoder Info + $moreBytesToRead = $thisPacket['packet_size'] - $keyNameSize - $maxHandledPacketLength; + if ($moreBytesToRead > 0) { + $MPCheaderData .= fread($getid3->fp, $moreBytesToRead); + } + $profile_pns = getid3_lib::BigEndian2Int(substr($MPCheaderData, $packet_offset, 1)); + $packet_offset += 1; + $quality_int = (($profile_pns & 0xF0) >> 4); + $quality_dec = (($profile_pns & 0x0E) >> 3); + $thisPacket['quality'] = (float) $quality_int + ($quality_dec / 8); + $thisPacket['pns_tool'] = (bool) (($profile_pns & 0x01) >> 0); + $thisPacket['version_major'] = getid3_lib::BigEndian2Int(substr($MPCheaderData, $packet_offset, 1)); + $packet_offset += 1; + $thisPacket['version_minor'] = getid3_lib::BigEndian2Int(substr($MPCheaderData, $packet_offset, 1)); + $packet_offset += 1; + $thisPacket['version_build'] = getid3_lib::BigEndian2Int(substr($MPCheaderData, $packet_offset, 1)); + $packet_offset += 1; + $thisPacket['version'] = $thisPacket['version_major'].'.'.$thisPacket['version_minor'].'.'.$thisPacket['version_build']; + + $getid3->info['audio']['encoder'] = 'MPC v'.$thisPacket['version'].' ('.(($thisPacket['version_minor'] % 2) ? 'unstable' : 'stable').')'; + $thisfile_mpc_header['encoder_version'] = $getid3->info['audio']['encoder']; + //$thisfile_mpc_header['quality'] = (float) ($thisPacket['quality'] / 1.5875); // values can range from 0.000 to 15.875, mapped to qualities of 0.0 to 10.0 + $thisfile_mpc_header['quality'] = (float) ($thisPacket['quality'] - 5); // values can range from 0.000 to 15.875, of which 0..4 are "reserved/experimental", and 5..15 are mapped to qualities of 0.0 to 10.0 + break; + + case 'SO': // Seek Table Offset + $packetLength = 0; + $thisPacket['seek_table_offset'] = $thisPacket['offset'] + $this->SV8variableLengthInteger(substr($MPCheaderData, $packet_offset, $maxHandledPacketLength), $packetLength); + $packet_offset += $packetLength; + break; + + case 'ST': // Seek Table + case 'SE': // Stream End + case 'AP': // Audio Data + // nothing useful here, just skip this packet + $thisPacket = array(); + break; + + default: + $getid3->info['error'][] = 'Found unhandled key type "'.$thisPacket['key'].'" at offset '.$thisPacket['offset']; + return false; + break; + } + if (!empty($thisPacket)) { + $getid3->info['mpc']['packets'][] = $thisPacket; + } + fseek($getid3->fp, $offset); + } + $thisfile_mpc_header['size'] = $offset; + return true; + + } else { + + $getid3->info['error'][] = 'Expecting "MP+" or "MPCK" at offset '.$getid3->info['avdataoffset'].', found "'.substr($MPCheaderData, 0, 4).'"'; + unset($getid3->info['fileformat']); + unset($getid3->info['mpc']); + return false; + + } + return false; + } + + + + public static function MPCprofileNameLookup($profileid) { + + static $lookup = array ( + 0 => 'no profile', + 1 => 'Experimental', + 2 => 'unused', + 3 => 'unused', + 4 => 'unused', + 5 => 'below Telephone (q = 0.0)', + 6 => 'below Telephone (q = 1.0)', + 7 => 'Telephone (q = 2.0)', + 8 => 'Thumb (q = 3.0)', + 9 => 'Radio (q = 4.0)', + 10 => 'Standard (q = 5.0)', + 11 => 'Extreme (q = 6.0)', + 12 => 'Insane (q = 7.0)', + 13 => 'BrainDead (q = 8.0)', + 14 => 'above BrainDead (q = 9.0)', + 15 => 'above BrainDead (q = 10.0)' + ); + return (isset($lookup[$profileid]) ? $lookup[$profileid] : 'invalid'); + } + + + + public static function MPCfrequencyLookup($frequencyid) { + + static $lookup = array ( + 0 => 44100, + 1 => 48000, + 2 => 37800, + 3 => 32000 + ); + return (isset($lookup[$frequencyid]) ? $lookup[$frequencyid] : 'invalid'); + } + + + + public static function MPCpeakDBLookup($int_value) { + + if ($int_value > 0) { + return ((log10($int_value) / log10(2)) - 15) * 6; + } + return false; + } + + + + public static function MPCencoderVersionLookup($encoder_version) { + + //Encoder version * 100 (106 = 1.06) + //EncoderVersion % 10 == 0 Release (1.0) + //EncoderVersion % 2 == 0 Beta (1.06) + //EncoderVersion % 2 == 1 Alpha (1.05a...z) + + if ($encoder_version == 0) { + // very old version, not known exactly which + return 'Buschmann v1.7.0-v1.7.9 or Klemm v0.90-v1.05'; + } + + if (($encoder_version % 10) == 0) { + + // release version + return number_format($encoder_version / 100, 2); + + } elseif (($encoder_version % 2) == 0) { + + // beta version + return number_format($encoder_version / 100, 2).' beta'; + + } + + // alpha version + return number_format($encoder_version / 100, 2).' alpha'; + } + + + + public static function SV8variableLengthInteger($data, &$packetLength, $maxHandledPacketLength=9) { + $packet_size = 0; + for ($packetLength = 1; $packetLength <= $maxHandledPacketLength; $packetLength++) { + // variable-length size field: + // bits, big-endian + // 0xxx xxxx - value 0 to 2^7-1 + // 1xxx xxxx 0xxx xxxx - value 0 to 2^14-1 + // 1xxx xxxx 1xxx xxxx 0xxx xxxx - value 0 to 2^21-1 + // 1xxx xxxx 1xxx xxxx 1xxx xxxx 0xxx xxxx - value 0 to 2^28-1 + // ... + $thisbyte = ord(substr($data, ($packetLength - 1), 1)); + // look through bytes until find a byte with MSB==0 + $packet_size = ($packet_size << 7); + $packet_size = ($packet_size | ($thisbyte & 0x7F)); + if (($thisbyte & 0x80) === 0) { + break; + } + if ($packetLength >= $maxHandledPacketLength) { + return false; + } + } + return $packet_size; + } + + + + public static function MPCsv8PacketName($packetKey) { + static $MPCsv8PacketName = array(); + if (empty($MPCsv8PacketName)) { + $MPCsv8PacketName = array( + 'AP' => 'Audio Packet', + 'CT' => 'Chapter Tag', + 'EI' => 'Encoder Info', + 'RG' => 'Replay Gain', + 'SE' => 'Stream End', + 'SH' => 'Stream Header', + 'SO' => 'Seek Table Offset', + 'ST' => 'Seek Table', + ); + } + return (isset($MPCsv8PacketName[$packetKey]) ? $MPCsv8PacketName[$packetKey] : $packetKey); + } + +} + + +?> diff --git a/modules/getid3/module.tag.id3v2.php b/modules/getid3/module.tag.id3v2.php index deaa5abc..c1ee70ab 100644 --- a/modules/getid3/module.tag.id3v2.php +++ b/modules/getid3/module.tag.id3v2.php @@ -24,8 +24,8 @@ // $Id: module.tag.id3v2.php,v 1.15 2006/12/03 23:47:29 ah Exp $ - - + + class getid3_id3v2 extends getid3_handler { @@ -35,11 +35,11 @@ class getid3_id3v2 extends getid3_handler public function Analyze() { $getid3 = $this->getid3; - + // dependency $getid3->include_module('tag.id3v1'); - - if ($getid3->option_tags_images) { + + if ($getid3->option_tags_images) { $getid3->include_module('lib.image_size'); } @@ -124,7 +124,7 @@ class getid3_id3v2 extends getid3_handler // Frames - + // All ID3v2 frames consists of one frame header followed by one or more // fields containing the actual information. The header is always 10 // bytes and laid out as follows: @@ -137,11 +137,11 @@ class getid3_id3v2 extends getid3_handler if (@$info_id3v2['exthead']['length']) { $size_of_frames -= ($info_id3v2['exthead']['length'] + 4); } - + if (@$info_id3v2_flags['isfooter']) { $size_of_frames -= 10; // footer takes last 10 bytes of ID3v2 header, after frame data, before audio } - + if ($size_of_frames > 0) { $frame_data = $this->fread($size_of_frames); // read all frames from file into $frame_data variable @@ -149,7 +149,7 @@ class getid3_id3v2 extends getid3_handler if (@$info_id3v2_flags['unsynch'] && ($id3v2_major_version <= 3)) { $frame_data = str_replace("\xFF\x00", "\xFF", $frame_data); } - + // [in ID3v2.4.0] Unsynchronisation [S:6.1] is done on frame level, instead // of on tag level, making it easier to skip frames, increasing the streamability // of the tag. The unsynchronisation flag in the header [S:3.1] indicates that @@ -190,8 +190,8 @@ class getid3_id3v2 extends getid3_handler } $extended_header_offset += $info_id3v2['exthead']['padding_size']; - } - + } + elseif ($id3v2_major_version == 4) { // v2.4 definition: @@ -237,12 +237,12 @@ class getid3_id3v2 extends getid3_handler $frame_data_offset += $extended_header_offset; $frame_data = substr($frame_data, $extended_header_offset); } // end extended header - - - - - - + + + + + + while (isset($frame_data) && (strlen($frame_data) > 0)) { // cycle through until no more frame data is left to parse if (strlen($frame_data) <= ($id3v2_major_version == 2 ? 6 : 10)) { // insufficient room left in ID3v2 header for actual data - must be padding @@ -259,7 +259,7 @@ class getid3_id3v2 extends getid3_handler } break; // skip rest of ID3v2 header } - + if ($id3v2_major_version == 2) { // Frame ID $xx xx xx (three characters) // Size $xx xx xx (24-bit integer) @@ -313,7 +313,7 @@ class getid3_id3v2 extends getid3_handler $info_id3v2['padding']['start'] = $frame_data_offset; $info_id3v2['padding']['length'] = strlen($frame_header) + strlen($frame_data); $info_id3v2['padding']['valid'] = true; - + $len = strlen($frame_data); for ($i = 0; $i < $len; $i++) { if ($frame_data{$i} != "\x00") { @@ -376,7 +376,7 @@ class getid3_id3v2 extends getid3_handler if (!getid3_id3v2::IsValidID3v2FrameName($frame_name, $id3v2_major_version)) { switch ($frame_name) { - + case "\x00\x00".'MP': case "\x00".'MP3': case ' MP3': @@ -411,7 +411,7 @@ class getid3_id3v2 extends getid3_handler // Footer - + // The footer is a copy of the header, but with a different identifier. // ID3v2 identifier "3DI" // ID3v2 version $04 00 @@ -450,9 +450,9 @@ class getid3_id3v2 extends getid3_handler } } } - - // Use year from recording time if year is empty - if (!strlen($info_id3v2['comments']['year']) && ereg('^([0-9]{4})', @$info_id3v2['comments']['recording_time'][0], $matches)) { + + // Use year from recording time if year not set + if (!isset($info_id3v2['comments']['year']) && ereg('^([0-9]{4})', @$info_id3v2['comments']['recording_time'][0], $matches)) { $info_id3v2['comments']['year'] = array ($matches[1]); } @@ -468,19 +468,19 @@ class getid3_id3v2 extends getid3_handler private function ParseID3v2Frame(&$parsed_frame) { - + $getid3 = $this->getid3; $id3v2_major_version = $getid3->info['id3v2']['majorversion']; $frame_name_long = getid3_id3v2::FrameNameLongLookup($parsed_frame['frame_name']); if ($frame_name_long) { - $parsed_frame['framenamelong'] = $frame_name_long; + $parsed_frame['framenamelong'] = $frame_name_long; } - + $frame_name_short = getid3_id3v2::FrameNameShortLookup($parsed_frame['frame_name']); if ($frame_name_short) { - $parsed_frame['framenameshort'] = $frame_name_short; + $parsed_frame['framenameshort'] = $frame_name_short; } if ($id3v2_major_version >= 3) { // frame flags are not part of the ID3v2.2 standard @@ -521,7 +521,7 @@ class getid3_id3v2 extends getid3_handler // Frame-level de-compression if ($parsed_frame['flags']['compression']) { $parsed_frame['decompressed_size'] = getid3_lib::BigEndian2Int(substr($parsed_frame['data'], 0, 4)); - + if (!function_exists('gzuncompress')) { $getid3->warning('gzuncompress() support required to decompress ID3v2 frame "'.$parsed_frame['frame_name'].'"'); } elseif ($decompressed_data = @gzuncompress(substr($parsed_frame['data'], 4))) { @@ -547,8 +547,8 @@ class getid3_id3v2 extends getid3_handler $getid3->warning($warning); return true; } - - + + if ((($id3v2_major_version >= 3) && ($parsed_frame['frame_name'] == 'UFID')) || // 4.1 UFID Unique file identifier (($id3v2_major_version == 2) && ($parsed_frame['frame_name'] == 'UFI'))) { // 4.1 UFI Unique file identifier @@ -602,7 +602,7 @@ class getid3_id3v2 extends getid3_handler unset($parsed_frame['data']); return true; } - + if ($parsed_frame['frame_name']{0} == 'T') { // 4.2. T??[?] Text information frame @@ -624,11 +624,11 @@ class getid3_id3v2 extends getid3_handler $parsed_frame['encoding'] = $this->TextEncodingNameLookup($frame_text_encoding); if (!empty($parsed_frame['framenameshort']) && !empty($parsed_frame['data'])) { - + // remove possible terminating \x00 (put by encoding id or software bug) $string = $getid3->iconv($parsed_frame['encoding'], 'UTF-8', $parsed_frame['data']); - if ($string[strlen($string)-1] == "\x00") { - $string = substr($string, 0, strlen($string)-1); + if ($string[strlen($string) - 1] == "\x00") { + $string = substr($string, 0, strlen($string) - 1); } $getid3->info['id3v2']['comments'][$parsed_frame['framenameshort']][] = $string; unset($string); @@ -639,7 +639,7 @@ class getid3_id3v2 extends getid3_handler if ((($id3v2_major_version >= 3) && ($parsed_frame['frame_name'] == 'WXXX')) || // 4.3.2 WXXX User defined URL link frame (($id3v2_major_version == 2) && ($parsed_frame['frame_name'] == 'WXX'))) { // 4.3.2 WXX User defined URL link frame - + // There may be more than one 'WXXX' frame in each tag, // but only one with the same description // <Header for 'User defined URL link frame', ID: 'WXXX'> @@ -775,7 +775,7 @@ class getid3_id3v2 extends getid3_handler if ((($id3v2_major_version >= 3) && ($parsed_frame['frame_name'] == 'MLLT')) || // 4.6 MLLT MPEG location lookup table (($id3v2_major_version == 2) && ($parsed_frame['frame_name'] == 'MLL'))) { // 4.7 MLL MPEG location lookup table - + // There may only be one 'MLLT' frame in each tag // <Header for 'Location lookup table', ID: 'MLLT'> // MPEG frames between reference $xx xx @@ -794,7 +794,7 @@ class getid3_id3v2 extends getid3_handler $parsed_frame['bitsforbytesdeviation'] = getid3_lib::BigEndian2Int($parsed_frame['data'][8]); $parsed_frame['bitsformsdeviation'] = getid3_lib::BigEndian2Int($parsed_frame['data'][9]); $parsed_frame['data'] = substr($parsed_frame['data'], 10); - + while ($frame_offset < strlen($parsed_frame['data'])) { $deviation_bitstream .= getid3_lib::BigEndian2Bin($parsed_frame['data']{$frame_offset++}); } @@ -812,7 +812,7 @@ class getid3_id3v2 extends getid3_handler if ((($id3v2_major_version >= 3) && ($parsed_frame['frame_name'] == 'SYTC')) || // 4.7 SYTC Synchronised tempo codes (($id3v2_major_version == 2) && ($parsed_frame['frame_name'] == 'STC'))) { // 4.8 STC Synchronised tempo codes - + // There may only be one 'SYTC' frame in each tag // <Header for 'Synchronised tempo codes', ID: 'SYTC'> // Time stamp format $xx @@ -837,10 +837,10 @@ class getid3_id3v2 extends getid3_handler return true; } - + if ((($id3v2_major_version >= 3) && ($parsed_frame['frame_name'] == 'USLT')) || // 4.8 USLT Unsynchronised lyric/text transcription (($id3v2_major_version == 2) && ($parsed_frame['frame_name'] == 'ULT'))) { // 4.9 ULT Unsynchronised lyric/text transcription - + // There may be more than one 'Unsynchronised lyrics/text transcription' frame // in each tag, but only one with the same language and content descriptor. // <Header for 'Unsynchronised lyrics/text transcription', ID: 'USLT'> @@ -886,7 +886,7 @@ class getid3_id3v2 extends getid3_handler if ((($id3v2_major_version >= 3) && ($parsed_frame['frame_name'] == 'SYLT')) || // 4.9 SYLT Synchronised lyric/text (($id3v2_major_version == 2) && ($parsed_frame['frame_name'] == 'SLT'))) { // 4.10 SLT Synchronised lyric/text - + // There may be more than one 'SYLT' frame in each tag, // but only one with the same language and content descriptor. // <Header for 'Synchronised lyrics/text', ID: 'SYLT'> @@ -947,7 +947,7 @@ class getid3_id3v2 extends getid3_handler if ((($id3v2_major_version >= 3) && ($parsed_frame['frame_name'] == 'COMM')) || // 4.10 COMM Comments (($id3v2_major_version == 2) && ($parsed_frame['frame_name'] == 'COM'))) { // 4.11 COM Comments - + // There may be more than one comment frame in each tag, // but only one with the same language and content descriptor. // <Header for 'Comment', ID: 'COMM'> @@ -991,10 +991,10 @@ class getid3_id3v2 extends getid3_handler } return true; } - + if (($id3v2_major_version >= 4) && ($parsed_frame['frame_name'] == 'RVA2')) { // 4.11 RVA2 Relative volume adjustment (2) (ID3v2.4+ only) - + // There may be more than one 'RVA2' frame in each tag, // but only one with the same identification string // <Header for 'Relative volume adjustment (2)', ID: 'RVA2'> @@ -1014,7 +1014,7 @@ class getid3_id3v2 extends getid3_handler } $frame_remaining_data = substr($parsed_frame['data'], $frame_terminator_pos + strlen("\x00")); $parsed_frame['description'] = $frame_id_string; - + while (strlen($frame_remaining_data)) { $frame_offset = 0; $frame_channeltypeid = ord(substr($frame_remaining_data, $frame_offset++, 1)); @@ -1030,11 +1030,11 @@ class getid3_id3v2 extends getid3_handler unset($parsed_frame['data']); return true; } - + if ((($id3v2_major_version == 3) && ($parsed_frame['frame_name'] == 'RVAD')) || // 4.12 RVAD Relative volume adjustment (ID3v2.3 only) (($id3v2_major_version == 2) && ($parsed_frame['frame_name'] == 'RVA'))) { // 4.12 RVA Relative volume adjustment (ID3v2.2 only) - + // There may only be one 'RVA' frame in each tag // <Header for 'Relative volume adjustment', ID: 'RVA'> // ID3v2.2 => Increment/decrement %000000ba @@ -1125,7 +1125,7 @@ class getid3_id3v2 extends getid3_handler if (($id3v2_major_version >= 4) && ($parsed_frame['frame_name'] == 'EQU2')) { // 4.12 EQU2 Equalisation (2) (ID3v2.4+ only) - + // There may be more than one 'EQU2' frame in each tag, // but only one with the same identification string // <Header of 'Equalisation (2)', ID: 'EQU2'> @@ -1159,7 +1159,7 @@ class getid3_id3v2 extends getid3_handler if ((($id3v2_major_version == 3) && ($parsed_frame['frame_name'] == 'EQUA')) || // 4.12 EQUA Equalisation (ID3v2.3 only) (($id3v2_major_version == 2) && ($parsed_frame['frame_name'] == 'EQU'))) { // 4.13 EQU Equalisation (ID3v2.2 only) - + // There may only be one 'EQUA' frame in each tag // <Header for 'Relative volume adjustment', ID: 'EQU'> // Adjustment bits $xx @@ -1193,7 +1193,7 @@ class getid3_id3v2 extends getid3_handler if ((($id3v2_major_version >= 3) && ($parsed_frame['frame_name'] == 'RVRB')) || // 4.13 RVRB Reverb (($id3v2_major_version == 2) && ($parsed_frame['frame_name'] == 'REV'))) { // 4.14 REV Reverb - + // There may only be one 'RVRB' frame in each tag. // <Header for 'Reverb', ID: 'RVRB'> // Reverb left (ms) $xx xx @@ -1245,7 +1245,7 @@ class getid3_id3v2 extends getid3_handler $getid3->warning('Invalid text encoding byte ('.$frame_text_encoding.') in frame "'.$parsed_frame['frame_name'].'" - defaulting to ISO-8859-1 encoding'); } - if ($id3v2_major_version == 2 && strlen($parsed_frame['data']) > $frame_offset) { + if ($id3v2_major_version == 2 && strlen($parsed_frame['data']) > $frame_offset) { $frame_imagetype = substr($parsed_frame['data'], $frame_offset, 3); if (strtolower($frame_imagetype) == 'ima') { // complete hack for mp3Rage (www.chaoticsoftware.com) that puts ID3v2.3-formatted @@ -1264,7 +1264,7 @@ class getid3_id3v2 extends getid3_handler $frame_offset += 3; } } - + if ($id3v2_major_version > 2 && strlen($parsed_frame['data']) > $frame_offset) { $frame_terminator_pos = @strpos($parsed_frame['data'], "\x00", $frame_offset); $frame_mimetype = substr($parsed_frame['data'], $frame_offset, $frame_terminator_pos - $frame_offset); @@ -1298,19 +1298,19 @@ class getid3_id3v2 extends getid3_handler $parsed_frame['data'] = substr($parsed_frame['data'], $frame_terminator_pos + strlen(getid3_id3v2::TextEncodingTerminatorLookup($frame_text_encoding))); if ($getid3->option_tags_images) { - + $image_chunk_check = getid3_lib_image_size::get($parsed_frame['data']); if (($image_chunk_check[2] >= 1) && ($image_chunk_check[2] <= 3)) { $parsed_frame['image_mime'] = image_type_to_mime_type($image_chunk_check[2]); - + if ($image_chunk_check[0]) { $parsed_frame['image_width'] = $image_chunk_check[0]; } - + if ($image_chunk_check[1]) { $parsed_frame['image_height'] = $image_chunk_check[1]; } - + $parsed_frame['image_bytes'] = strlen($parsed_frame['data']); } } @@ -1321,7 +1321,7 @@ class getid3_id3v2 extends getid3_handler if ((($id3v2_major_version >= 3) && ($parsed_frame['frame_name'] == 'GEOB')) || // 4.15 GEOB General encapsulated object (($id3v2_major_version == 2) && ($parsed_frame['frame_name'] == 'GEO'))) { // 4.16 GEO General encapsulated object - + // There may be more than one 'GEOB' frame in each tag, // but only one with the same content descriptor // <Header for 'General encapsulated object', ID: 'GEOB'> @@ -1377,7 +1377,7 @@ class getid3_id3v2 extends getid3_handler if ((($id3v2_major_version >= 3) && ($parsed_frame['frame_name'] == 'PCNT')) || // 4.16 PCNT Play counter (($id3v2_major_version == 2) && ($parsed_frame['frame_name'] == 'CNT'))) { // 4.17 CNT Play counter - + // There may only be one 'PCNT' frame in each tag. // When the counter reaches all one's, one byte is inserted in // front of the counter thus making the counter eight bits bigger @@ -1391,7 +1391,7 @@ class getid3_id3v2 extends getid3_handler if ((($id3v2_major_version >= 3) && ($parsed_frame['frame_name'] == 'POPM')) || // 4.17 POPM Popularimeter (($id3v2_major_version == 2) && ($parsed_frame['frame_name'] == 'POP'))) { // 4.18 POP Popularimeter - + // There may be more than one 'POPM' frame in each tag, // but only one with the same email address // <Header for 'Popularimeter', ID: 'POPM'> @@ -1417,7 +1417,7 @@ class getid3_id3v2 extends getid3_handler if ((($id3v2_major_version >= 3) && ($parsed_frame['frame_name'] == 'RBUF')) || // 4.18 RBUF Recommended buffer size (($id3v2_major_version == 2) && ($parsed_frame['frame_name'] == 'BUF'))) { // 4.19 BUF Recommended buffer size - + // There may only be one 'RBUF' frame in each tag // <Header for 'Recommended buffer size', ID: 'RBUF'> // Buffer size $xx xx xx @@ -1437,7 +1437,7 @@ class getid3_id3v2 extends getid3_handler if (($id3v2_major_version == 2) && ($parsed_frame['frame_name'] == 'CRM')) { // 4.20 Encrypted meta frame (ID3v2.2 only) - + // There may be more than one 'CRM' frame in a tag, // but only one with the same 'owner identifier' // <Header for 'Encrypted meta frame', ID: 'CRM'> @@ -1467,7 +1467,7 @@ class getid3_id3v2 extends getid3_handler if ((($id3v2_major_version >= 3) && ($parsed_frame['frame_name'] == 'AENC')) || // 4.19 AENC Audio encryption (($id3v2_major_version == 2) && ($parsed_frame['frame_name'] == 'CRA'))) { // 4.21 CRA Audio encryption - + // There may be more than one 'AENC' frames in a tag, // but only one with the same 'Owner identifier' // <Header for 'Audio encryption', ID: 'AENC'> @@ -1496,7 +1496,7 @@ class getid3_id3v2 extends getid3_handler if ((($id3v2_major_version >= 3) && ($parsed_frame['frame_name'] == 'LINK')) || // 4.20 LINK Linked information (($id3v2_major_version == 2) && ($parsed_frame['frame_name'] == 'LNK'))) { // 4.22 LNK Linked information - + // There may be more than one 'LINK' frame in a tag, // but only one with the same contents // <Header for 'Linked information', ID: 'LINK'> @@ -1532,7 +1532,7 @@ class getid3_id3v2 extends getid3_handler if (($id3v2_major_version >= 3) && ($parsed_frame['frame_name'] == 'POSS')) { // 4.21 POSS Position synchronisation frame (ID3v2.3+ only) - + // There may only be one 'POSS' frame in each tag // <Head for 'Position synchronisation', ID: 'POSS'> // Time stamp format $xx @@ -1547,7 +1547,7 @@ class getid3_id3v2 extends getid3_handler if (($id3v2_major_version >= 3) && ($parsed_frame['frame_name'] == 'USER')) { // 4.22 USER Terms of use (ID3v2.3+ only) - + // There may be more than one 'Terms of use' frame in a tag, // but only one with the same 'Language' // <Header for 'Terms of use frame', ID: 'USER'> @@ -1577,7 +1577,7 @@ class getid3_id3v2 extends getid3_handler if (($id3v2_major_version >= 3) && ($parsed_frame['frame_name'] == 'OWNE')) { // 4.23 OWNE Ownership frame (ID3v2.3+ only) - + // There may only be one 'OWNE' frame in a tag // <Header for 'Ownership frame', ID: 'OWNE'> // Text encoding $xx @@ -1614,7 +1614,7 @@ class getid3_id3v2 extends getid3_handler if (($id3v2_major_version >= 3) && ($parsed_frame['frame_name'] == 'COMR')) { // 4.24 COMR Commercial frame (ID3v2.3+ only) - + // There may be more than one 'commercial frame' in a tag, // but no two may be identical // <Header for 'Commercial frame', ID: 'COMR'> @@ -1657,24 +1657,24 @@ class getid3_id3v2 extends getid3_handler if (ord(substr($parsed_frame['data'], $frame_terminator_pos + strlen(getid3_id3v2::TextEncodingTerminatorLookup($frame_text_encoding)), 1)) === 0) { $frame_terminator_pos++; // @strpos() fooled because 2nd byte of Unicode chars are often 0x00 } - + $frame_sellername = substr($parsed_frame['data'], $frame_offset, $frame_terminator_pos - $frame_offset); if (ord($frame_sellername) === 0) { $frame_sellername = ''; } - + $frame_offset = $frame_terminator_pos + strlen(getid3_id3v2::TextEncodingTerminatorLookup($frame_text_encoding)); $frame_terminator_pos = @strpos($parsed_frame['data'], getid3_id3v2::TextEncodingTerminatorLookup($frame_text_encoding), $frame_offset); if (ord(substr($parsed_frame['data'], $frame_terminator_pos + strlen(getid3_id3v2::TextEncodingTerminatorLookup($frame_text_encoding)), 1)) === 0) { $frame_terminator_pos++; // @strpos() fooled because 2nd byte of Unicode chars are often 0x00 } - + $frame_description = substr($parsed_frame['data'], $frame_offset, $frame_terminator_pos - $frame_offset); if (ord($frame_description) === 0) { $frame_description = ''; } - + $frame_offset = $frame_terminator_pos + strlen(getid3_id3v2::TextEncodingTerminatorLookup($frame_text_encoding)); $frame_terminator_pos = @strpos($parsed_frame['data'], "\x00", $frame_offset); @@ -1699,7 +1699,7 @@ class getid3_id3v2 extends getid3_handler if (($id3v2_major_version >= 3) && ($parsed_frame['frame_name'] == 'ENCR')) { // 4.25 ENCR Encryption method registration (ID3v2.3+ only) - + // There may be several 'ENCR' frames in a tag, // but only one containing the same symbol // and only one containing the same owner identifier @@ -1721,7 +1721,7 @@ class getid3_id3v2 extends getid3_handler $parsed_frame['data'] = (string)substr($parsed_frame['data'], $frame_offset); return true; } - + if (($id3v2_major_version >= 3) && ($parsed_frame['frame_name'] == 'GRID')) { // 4.26 GRID Group identification registration (ID3v2.3+ only) @@ -1749,7 +1749,7 @@ class getid3_id3v2 extends getid3_handler if (($id3v2_major_version >= 3) && ($parsed_frame['frame_name'] == 'PRIV')) { // 4.27 PRIV Private frame (ID3v2.3+ only) - + // The tag may contain more than one 'PRIV' frame // but only with different contents // <Header for 'Private frame', ID: 'PRIV'> @@ -1771,7 +1771,7 @@ class getid3_id3v2 extends getid3_handler if (($id3v2_major_version >= 4) && ($parsed_frame['frame_name'] == 'SIGN')) { // 4.28 SIGN Signature frame (ID3v2.4+ only) - + // There may be more than one 'signature frame' in a tag, // but no two may be identical // <Header for 'Signature frame', ID: 'SIGN'> @@ -1786,7 +1786,7 @@ class getid3_id3v2 extends getid3_handler if (($id3v2_major_version >= 4) && ($parsed_frame['frame_name'] == 'SEEK')) { // 4.29 SEEK Seek frame (ID3v2.4+ only) - + // There may only be one 'seek frame' in a tag // <Header for 'Seek frame', ID: 'SEEK'> // Minimum offset to next tag $xx xx xx xx @@ -1798,7 +1798,7 @@ class getid3_id3v2 extends getid3_handler if (($id3v2_major_version >= 4) && ($parsed_frame['frame_name'] == 'ASPI')) { // 4.30 ASPI Audio seek point index (ID3v2.4+ only) - + // There may only be one 'audio seek point index' frame in a tag // <Header for 'Seek Point Index', ID: 'ASPI'> // Indexed data start (S) $xx xx xx xx @@ -1840,16 +1840,16 @@ class getid3_id3v2 extends getid3_handler // d - replay gain adjustment $frame_offset = 0; - + $parsed_frame['peakamplitude'] = (float)getid3_lib::BigEndian2Int(substr($parsed_frame['data'], $frame_offset, 4)); $frame_offset += 4; - + $rg_track_adjustment = decbin(substr($parsed_frame['data'], $frame_offset, 2)); $frame_offset += 2; - + $rg_album_adjustment = decbin(substr($parsed_frame['data'], $frame_offset, 2)); $frame_offset += 2; - + $parsed_frame['raw']['track']['name'] = bindec(substr($rg_track_adjustment, 0, 3)); $parsed_frame['raw']['track']['originator'] = bindec(substr($rg_track_adjustment, 3, 3)); $parsed_frame['raw']['track']['signbit'] = bindec($rg_track_adjustment[6]); @@ -1877,32 +1877,32 @@ class getid3_id3v2 extends getid3_handler return true; } - - - + + + private function TextEncodingNameLookup($encoding) { - + // Override specification - BRAINDEAD taggers if (!$encoding) { return $this->getid3->encoding_id3v2; } - + // http://www.id3.org/id3v2.4.0-structure.txt static $lookup = array ( - 0 => 'ISO-8859-1', - 1 => 'UTF-16', - 2 => 'UTF-16BE', - 3 => 'UTF-8', + 0 => 'ISO-8859-1', + 1 => 'UTF-16', + 2 => 'UTF-16BE', + 3 => 'UTF-8', 255 => 'UTF-16BE' ); - + return (isset($lookup[$encoding]) ? $lookup[$encoding] : 'ISO-8859-1'); } public static function ParseID3v2GenreString($genre_string) { - + // Parse genres into arrays of genreName and genreID // ID3v2.2.x, ID3v2.3.x: '(21)' or '(4)Eurodisco' or '(51)(39)' or '(55)((I think...)' // ID3v2.4.x: '21' $00 'Eurodisco' $00 @@ -1913,12 +1913,15 @@ class getid3_id3v2 extends getid3_handler $unprocessed = trim($genre_string); // trailing nulls will cause an infinite loop. $genre_string = ''; while (strpos($unprocessed, "\x00") !== false) { - // convert null-seperated v2.4-format into v2.3 ()-seperated format - $end_pos = strpos($unprocessed, "\x00"); - $genre_string .= '('.substr($unprocessed, 0, $end_pos).')'; - $unprocessed = substr($unprocessed, $end_pos + 1); + // convert null-seperated v2.4-format into v2.3 ()-seperated format + $end_pos = strpos($unprocessed, "\x00"); + $genre_string .= '('.substr($unprocessed, 0, $end_pos).')'; + $unprocessed = substr($unprocessed, $end_pos + 1); } unset($unprocessed); + } elseif (eregi('^([0-9]+|CR|RX)$', $genre_string)) { + // some tagging program (including some that use TagLib) fail to include null byte after numeric genre + $genre_string = '('.$genre_string.')'; } if (getid3_id3v1::LookupGenreID($genre_string)) { @@ -1936,7 +1939,7 @@ class getid3_id3v2 extends getid3_handler } $element = substr($genre_string, $start_pos + 1, $end_pos - ($start_pos + 1)); $genre_string = substr($genre_string, 0, $start_pos).substr($genre_string, $end_pos + 1); - + if (getid3_id3v1::LookupGenreName($element)) { // $element is a valid genre id/abbreviation if (empty($return_array['genre']) || !in_array(getid3_id3v1::LookupGenreName($element), $return_array['genre'])) { // avoid duplicate entires @@ -1958,9 +1961,9 @@ class getid3_id3v2 extends getid3_handler return $return_array; } - - - + + + public static function LookupCurrencyUnits($currency_id) { static $lookup = array ( @@ -2341,7 +2344,7 @@ class getid3_id3v2 extends getid3_handler 'ZMK' => 'Zambia', 'ZWD' => 'Zimbabwe' ); - + return @$lookup[$currency_id]; } @@ -2793,15 +2796,15 @@ class getid3_id3v2 extends getid3_handler 'zho' => 'Chinese', 'zul' => 'Zulu', 'zun' => 'Zuni' - ); + ); return @$lookup[$language_code]; } - + public static function ETCOEventLookup($index) { - + if (($index >= 0x17) && ($index <= 0xDF)) { return 'reserved for future use'; } @@ -2890,7 +2893,7 @@ class getid3_id3v2 extends getid3_handler 0x13 => 'Band/artist logotype', 0x14 => 'Publisher/Studio logotype' ); - + if ($return_array) { return $lookup; } @@ -2919,7 +2922,7 @@ class getid3_id3v2 extends getid3_handler public static function RVA2ChannelTypeLookup($index) { - + static $lookup = array ( 0x00 => 'Other', 0x01 => 'Master volume', @@ -3098,8 +3101,8 @@ class getid3_id3v2 extends getid3_handler 'TFEA' => 'Featured Artist', 'TSTU' => 'Recording Studio', 'rgad' => 'Replay Gain Adjustment' - ); - + ); + return @$lookup[$frame_name]; // Last three: @@ -3146,13 +3149,11 @@ class getid3_id3v2 extends getid3_handler 'TP2' => 'band', 'TP3' => 'conductor', 'TP4' => 'remixer', - 'TPA' => 'pos', 'TPB' => 'publisher', 'TPE1' => 'artist', 'TPE2' => 'band', 'TPE3' => 'conductor', 'TPE4' => 'remixer', - 'TPOS' => 'pos', 'TPUB' => 'publisher', 'TRC' => 'isrc', 'TRCK' => 'track', @@ -3208,10 +3209,10 @@ class getid3_id3v2 extends getid3_handler // $03 UTF-8 encoded Unicode. Terminated with $00. static $lookup = array ( - 0 => "\x00", - 1 => "\x00\x00", - 2 => "\x00\x00", - 3 => "\x00", + 0 => "\x00", + 1 => "\x00\x00", + 2 => "\x00\x00", + 3 => "\x00", 255 => "\x00\x00" ); @@ -3243,7 +3244,7 @@ class getid3_id3v2 extends getid3_handler if ((int)$date_stamp) { return false; } - + $year = substr($date_stamp, 0, 4); $month = substr($date_stamp, 4, 2); $day = substr($date_stamp, 6, 2); @@ -3258,8 +3259,8 @@ class getid3_id3v2 extends getid3_handler } return true; } - - + + public static function array_merge_noclobber($array1, $array2) { if (!is_array($array1) || !is_array($array2)) { @@ -3279,4 +3280,4 @@ class getid3_id3v2 extends getid3_handler } -?> +?>
\ No newline at end of file diff --git a/modules/getid3/write.id3v2.php b/modules/getid3/write.id3v2.php index 5c4ae4d7..f122b6b0 100644 --- a/modules/getid3/write.id3v2.php +++ b/modules/getid3/write.id3v2.php @@ -375,7 +375,7 @@ class getid3_write_id3v2 extends getid3_handler_write // rewrite file - no tag present or new tag longer than old tag else - { + if (!$fp_source = @fopen($this->filename, 'rb')) { throw new getid3_exception('Could not open '.$this->filename.' mode "rb"'); } |