[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/ID3/ -> module.audio.dts.php (source)

   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  }


Generated: Sun Jul 12 01:00:03 2020 Cross-referenced by PHPXref 0.7.1