[ Index ] |
PHP Cross Reference of WordPress |
[Summary view] [Print] [Text view]
1 <?php 2 3 ///////////////////////////////////////////////////////////////// 4 /// getID3() by James Heinrich <info@getid3.org> // 5 // available at https://github.com/JamesHeinrich/getID3 // 6 // or https://www.getid3.org // 7 // or http://getid3.sourceforge.net // 8 // see readme.txt for more details // 9 ///////////////////////////////////////////////////////////////// 10 // // 11 // module.audio.dts.php // 12 // module for analyzing DTS Audio files // 13 // dependencies: NONE // 14 // // 15 ///////////////////////////////////////////////////////////////// 16 17 if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers 18 exit; 19 } 20 21 /** 22 * @tutorial http://wiki.multimedia.cx/index.php?title=DTS 23 */ 24 class getid3_dts extends getid3_handler 25 { 26 /** 27 * Default DTS syncword used in native .cpt or .dts formats. 28 */ 29 const syncword = "\x7F\xFE\x80\x01"; 30 31 /** 32 * @var int 33 */ 34 private $readBinDataOffset = 0; 35 36 /** 37 * Possible syncwords indicating bitstream encoding. 38 */ 39 public static $syncwords = array( 40 0 => "\x7F\xFE\x80\x01", // raw big-endian 41 1 => "\xFE\x7F\x01\x80", // raw little-endian 42 2 => "\x1F\xFF\xE8\x00", // 14-bit big-endian 43 3 => "\xFF\x1F\x00\xE8"); // 14-bit little-endian 44 45 /** 46 * @return bool 47 */ 48 public function Analyze() { 49 $info = &$this->getid3->info; 50 $info['fileformat'] = 'dts'; 51 52 $this->fseek($info['avdataoffset']); 53 $DTSheader = $this->fread(20); // we only need 2 words magic + 6 words frame header, but these words may be normal 16-bit words OR 14-bit words with 2 highest bits set to zero, so 8 words can be either 8*16/8 = 16 bytes OR 8*16*(16/14)/8 = 18.3 bytes 54 55 // check syncword 56 $sync = substr($DTSheader, 0, 4); 57 if (($encoding = array_search($sync, self::$syncwords)) !== false) { 58 59 $info['dts']['raw']['magic'] = $sync; 60 $this->readBinDataOffset = 32; 61 62 } elseif ($this->isDependencyFor('matroska')) { 63 64 // Matroska contains DTS without syncword encoded as raw big-endian format 65 $encoding = 0; 66 $this->readBinDataOffset = 0; 67 68 } else { 69 70 unset($info['fileformat']); 71 return $this->error('Expecting "'.implode('| ', array_map('getid3_lib::PrintHexBytes', self::$syncwords)).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($sync).'"'); 72 73 } 74 75 // decode header 76 $fhBS = ''; 77 for ($word_offset = 0; $word_offset <= strlen($DTSheader); $word_offset += 2) { 78 switch ($encoding) { 79 case 0: // raw big-endian 80 $fhBS .= getid3_lib::BigEndian2Bin( substr($DTSheader, $word_offset, 2) ); 81 break; 82 case 1: // raw little-endian 83 $fhBS .= getid3_lib::BigEndian2Bin(strrev(substr($DTSheader, $word_offset, 2))); 84 break; 85 case 2: // 14-bit big-endian 86 $fhBS .= substr(getid3_lib::BigEndian2Bin( substr($DTSheader, $word_offset, 2) ), 2, 14); 87 break; 88 case 3: // 14-bit little-endian 89 $fhBS .= substr(getid3_lib::BigEndian2Bin(strrev(substr($DTSheader, $word_offset, 2))), 2, 14); 90 break; 91 } 92 } 93 94 $info['dts']['raw']['frame_type'] = $this->readBinData($fhBS, 1); 95 $info['dts']['raw']['deficit_samples'] = $this->readBinData($fhBS, 5); 96 $info['dts']['flags']['crc_present'] = (bool) $this->readBinData($fhBS, 1); 97 $info['dts']['raw']['pcm_sample_blocks'] = $this->readBinData($fhBS, 7); 98 $info['dts']['raw']['frame_byte_size'] = $this->readBinData($fhBS, 14); 99 $info['dts']['raw']['channel_arrangement'] = $this->readBinData($fhBS, 6); 100 $info['dts']['raw']['sample_frequency'] = $this->readBinData($fhBS, 4); 101 $info['dts']['raw']['bitrate'] = $this->readBinData($fhBS, 5); 102 $info['dts']['flags']['embedded_downmix'] = (bool) $this->readBinData($fhBS, 1); 103 $info['dts']['flags']['dynamicrange'] = (bool) $this->readBinData($fhBS, 1); 104 $info['dts']['flags']['timestamp'] = (bool) $this->readBinData($fhBS, 1); 105 $info['dts']['flags']['auxdata'] = (bool) $this->readBinData($fhBS, 1); 106 $info['dts']['flags']['hdcd'] = (bool) $this->readBinData($fhBS, 1); 107 $info['dts']['raw']['extension_audio'] = $this->readBinData($fhBS, 3); 108 $info['dts']['flags']['extended_coding'] = (bool) $this->readBinData($fhBS, 1); 109 $info['dts']['flags']['audio_sync_insertion'] = (bool) $this->readBinData($fhBS, 1); 110 $info['dts']['raw']['lfe_effects'] = $this->readBinData($fhBS, 2); 111 $info['dts']['flags']['predictor_history'] = (bool) $this->readBinData($fhBS, 1); 112 if ($info['dts']['flags']['crc_present']) { 113 $info['dts']['raw']['crc16'] = $this->readBinData($fhBS, 16); 114 } 115 $info['dts']['flags']['mri_perfect_reconst'] = (bool) $this->readBinData($fhBS, 1); 116 $info['dts']['raw']['encoder_soft_version'] = $this->readBinData($fhBS, 4); 117 $info['dts']['raw']['copy_history'] = $this->readBinData($fhBS, 2); 118 $info['dts']['raw']['bits_per_sample'] = $this->readBinData($fhBS, 2); 119 $info['dts']['flags']['surround_es'] = (bool) $this->readBinData($fhBS, 1); 120 $info['dts']['flags']['front_sum_diff'] = (bool) $this->readBinData($fhBS, 1); 121 $info['dts']['flags']['surround_sum_diff'] = (bool) $this->readBinData($fhBS, 1); 122 $info['dts']['raw']['dialog_normalization'] = $this->readBinData($fhBS, 4); 123 124 125 $info['dts']['bitrate'] = self::bitrateLookup($info['dts']['raw']['bitrate']); 126 $info['dts']['bits_per_sample'] = self::bitPerSampleLookup($info['dts']['raw']['bits_per_sample']); 127 $info['dts']['sample_rate'] = self::sampleRateLookup($info['dts']['raw']['sample_frequency']); 128 $info['dts']['dialog_normalization'] = self::dialogNormalization($info['dts']['raw']['dialog_normalization'], $info['dts']['raw']['encoder_soft_version']); 129 $info['dts']['flags']['lossless'] = (($info['dts']['raw']['bitrate'] == 31) ? true : false); 130 $info['dts']['bitrate_mode'] = (($info['dts']['raw']['bitrate'] == 30) ? 'vbr' : 'cbr'); 131 $info['dts']['channels'] = self::numChannelsLookup($info['dts']['raw']['channel_arrangement']); 132 $info['dts']['channel_arrangement'] = self::channelArrangementLookup($info['dts']['raw']['channel_arrangement']); 133 134 $info['audio']['dataformat'] = 'dts'; 135 $info['audio']['lossless'] = $info['dts']['flags']['lossless']; 136 $info['audio']['bitrate_mode'] = $info['dts']['bitrate_mode']; 137 $info['audio']['bits_per_sample'] = $info['dts']['bits_per_sample']; 138 $info['audio']['sample_rate'] = $info['dts']['sample_rate']; 139 $info['audio']['channels'] = $info['dts']['channels']; 140 $info['audio']['bitrate'] = $info['dts']['bitrate']; 141 if (isset($info['avdataend']) && !empty($info['dts']['bitrate']) && is_numeric($info['dts']['bitrate'])) { 142 $info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset']) / ($info['dts']['bitrate'] / 8); 143 if (($encoding == 2) || ($encoding == 3)) { 144 // 14-bit data packed into 16-bit words, so the playtime is wrong because only (14/16) of the bytes in the data portion of the file are used at the specified bitrate 145 $info['playtime_seconds'] *= (14 / 16); 146 } 147 } 148 return true; 149 } 150 151 /** 152 * @param string $bin 153 * @param int $length 154 * 155 * @return int 156 */ 157 private function readBinData($bin, $length) { 158 $data = substr($bin, $this->readBinDataOffset, $length); 159 $this->readBinDataOffset += $length; 160 161 return bindec($data); 162 } 163 164 /** 165 * @param int $index 166 * 167 * @return int|string|false 168 */ 169 public static function bitrateLookup($index) { 170 static $lookup = array( 171 0 => 32000, 172 1 => 56000, 173 2 => 64000, 174 3 => 96000, 175 4 => 112000, 176 5 => 128000, 177 6 => 192000, 178 7 => 224000, 179 8 => 256000, 180 9 => 320000, 181 10 => 384000, 182 11 => 448000, 183 12 => 512000, 184 13 => 576000, 185 14 => 640000, 186 15 => 768000, 187 16 => 960000, 188 17 => 1024000, 189 18 => 1152000, 190 19 => 1280000, 191 20 => 1344000, 192 21 => 1408000, 193 22 => 1411200, 194 23 => 1472000, 195 24 => 1536000, 196 25 => 1920000, 197 26 => 2048000, 198 27 => 3072000, 199 28 => 3840000, 200 29 => 'open', 201 30 => 'variable', 202 31 => 'lossless', 203 ); 204 return (isset($lookup[$index]) ? $lookup[$index] : false); 205 } 206 207 /** 208 * @param int $index 209 * 210 * @return int|string|false 211 */ 212 public static function sampleRateLookup($index) { 213 static $lookup = array( 214 0 => 'invalid', 215 1 => 8000, 216 2 => 16000, 217 3 => 32000, 218 4 => 'invalid', 219 5 => 'invalid', 220 6 => 11025, 221 7 => 22050, 222 8 => 44100, 223 9 => 'invalid', 224 10 => 'invalid', 225 11 => 12000, 226 12 => 24000, 227 13 => 48000, 228 14 => 'invalid', 229 15 => 'invalid', 230 ); 231 return (isset($lookup[$index]) ? $lookup[$index] : false); 232 } 233 234 /** 235 * @param int $index 236 * 237 * @return int|false 238 */ 239 public static function bitPerSampleLookup($index) { 240 static $lookup = array( 241 0 => 16, 242 1 => 20, 243 2 => 24, 244 3 => 24, 245 ); 246 return (isset($lookup[$index]) ? $lookup[$index] : false); 247 } 248 249 /** 250 * @param int $index 251 * 252 * @return int|false 253 */ 254 public static function numChannelsLookup($index) { 255 switch ($index) { 256 case 0: 257 return 1; 258 case 1: 259 case 2: 260 case 3: 261 case 4: 262 return 2; 263 case 5: 264 case 6: 265 return 3; 266 case 7: 267 case 8: 268 return 4; 269 case 9: 270 return 5; 271 case 10: 272 case 11: 273 case 12: 274 return 6; 275 case 13: 276 return 7; 277 case 14: 278 case 15: 279 return 8; 280 } 281 return false; 282 } 283 284 /** 285 * @param int $index 286 * 287 * @return string 288 */ 289 public static function channelArrangementLookup($index) { 290 static $lookup = array( 291 0 => 'A', 292 1 => 'A + B (dual mono)', 293 2 => 'L + R (stereo)', 294 3 => '(L+R) + (L-R) (sum-difference)', 295 4 => 'LT + RT (left and right total)', 296 5 => 'C + L + R', 297 6 => 'L + R + S', 298 7 => 'C + L + R + S', 299 8 => 'L + R + SL + SR', 300 9 => 'C + L + R + SL + SR', 301 10 => 'CL + CR + L + R + SL + SR', 302 11 => 'C + L + R+ LR + RR + OV', 303 12 => 'CF + CR + LF + RF + LR + RR', 304 13 => 'CL + C + CR + L + R + SL + SR', 305 14 => 'CL + CR + L + R + SL1 + SL2 + SR1 + SR2', 306 15 => 'CL + C+ CR + L + R + SL + S + SR', 307 ); 308 return (isset($lookup[$index]) ? $lookup[$index] : 'user-defined'); 309 } 310 311 /** 312 * @param int $index 313 * @param int $version 314 * 315 * @return int|false 316 */ 317 public static function dialogNormalization($index, $version) { 318 switch ($version) { 319 case 7: 320 return 0 - $index; 321 case 6: 322 return 0 - 16 - $index; 323 } 324 return false; 325 } 326 327 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Nov 21 01:00:03 2024 | Cross-referenced by PHPXref 0.7.1 |