home *** CD-ROM | disk | FTP | other *** search
/ HTML Examples / WP.iso / wordpress / wp-includes / ID3 / module.audio.dts.php < prev    next >
Encoding:
PHP Script  |  2015-06-27  |  10.2 KB  |  292 lines

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