wp/wp-includes/ID3/module.audio.ac3.php
changeset 16 a86126ab1dd4
parent 7 cf61fcea0001
equal deleted inserted replaced
15:3d4e9c994f10 16:a86126ab1dd4
     1 <?php
     1 <?php
       
     2 
     2 /////////////////////////////////////////////////////////////////
     3 /////////////////////////////////////////////////////////////////
     3 /// getID3() by James Heinrich <info@getid3.org>               //
     4 /// getID3() by James Heinrich <info@getid3.org>               //
     4 //  available at http://getid3.sourceforge.net                 //
     5 //  available at https://github.com/JamesHeinrich/getID3       //
     5 //            or http://www.getid3.org                         //
     6 //            or https://www.getid3.org                        //
     6 //          also https://github.com/JamesHeinrich/getID3       //
     7 //            or http://getid3.sourceforge.net                 //
     7 /////////////////////////////////////////////////////////////////
     8 //  see readme.txt for more details                            //
     8 // See readme.txt for more details                             //
       
     9 /////////////////////////////////////////////////////////////////
     9 /////////////////////////////////////////////////////////////////
    10 //                                                             //
    10 //                                                             //
    11 // module.audio.ac3.php                                        //
    11 // module.audio.ac3.php                                        //
    12 // module for analyzing AC-3 (aka Dolby Digital) audio files   //
    12 // module for analyzing AC-3 (aka Dolby Digital) audio files   //
    13 // dependencies: NONE                                          //
    13 // dependencies: NONE                                          //
    14 //                                                            ///
    14 //                                                            ///
    15 /////////////////////////////////////////////////////////////////
    15 /////////////////////////////////////////////////////////////////
    16 
    16 
       
    17 if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
       
    18 	exit;
       
    19 }
    17 
    20 
    18 class getid3_ac3 extends getid3_handler
    21 class getid3_ac3 extends getid3_handler
    19 {
    22 {
    20     private $AC3header = array();
    23 	/**
    21     private $BSIoffset = 0;
    24 	 * @var array
    22 
    25 	 */
    23     const syncword = 0x0B77;
    26 	private $AC3header = array();
    24 
    27 
       
    28 	/**
       
    29 	 * @var int
       
    30 	 */
       
    31 	private $BSIoffset = 0;
       
    32 
       
    33 	const syncword = 0x0B77;
       
    34 
       
    35 	/**
       
    36 	 * @return bool
       
    37 	 */
    25 	public function Analyze() {
    38 	public function Analyze() {
    26 		$info = &$this->getid3->info;
    39 		$info = &$this->getid3->info;
    27 
    40 
    28 		///AH
    41 		///AH
    29 		$info['ac3']['raw']['bsi'] = array();
    42 		$info['ac3']['raw']['bsi'] = array();
   185 
   198 
   186 
   199 
   187 		} elseif ($thisfile_ac3_raw_bsi['bsid'] <= 16) { // E-AC3
   200 		} elseif ($thisfile_ac3_raw_bsi['bsid'] <= 16) { // E-AC3
   188 
   201 
   189 
   202 
   190 $this->error('E-AC3 parsing is incomplete and experimental in this version of getID3 ('.$this->getid3->version().'). Notably the bitrate calculations are wrong -- value might (or not) be correct, but it is not calculated correctly. Email info@getid3.org if you know how to calculate EAC3 bitrate correctly.');
   203 			$this->error('E-AC3 parsing is incomplete and experimental in this version of getID3 ('.$this->getid3->version().'). Notably the bitrate calculations are wrong -- value might (or not) be correct, but it is not calculated correctly. Email info@getid3.org if you know how to calculate EAC3 bitrate correctly.');
   191 			$info['audio']['dataformat'] = 'eac3';
   204 			$info['audio']['dataformat'] = 'eac3';
   192 
   205 
   193 			$thisfile_ac3_raw_bsi['strmtyp']          =        $this->readHeaderBSI(2);
   206 			$thisfile_ac3_raw_bsi['strmtyp']          =        $this->readHeaderBSI(2);
   194 			$thisfile_ac3_raw_bsi['substreamid']      =        $this->readHeaderBSI(3);
   207 			$thisfile_ac3_raw_bsi['substreamid']      =        $this->readHeaderBSI(3);
   195 			$thisfile_ac3_raw_bsi['frmsiz']           =        $this->readHeaderBSI(11);
   208 			$thisfile_ac3_raw_bsi['frmsiz']           =        $this->readHeaderBSI(11);
   410 			}
   423 			}
   411 
   424 
   412 		} else {
   425 		} else {
   413 
   426 
   414 			$this->error('Bit stream identification is version '.$thisfile_ac3_raw_bsi['bsid'].', but getID3() only understands up to version 16. Please submit a support ticket with a sample file.');
   427 			$this->error('Bit stream identification is version '.$thisfile_ac3_raw_bsi['bsid'].', but getID3() only understands up to version 16. Please submit a support ticket with a sample file.');
   415 		    unset($info['ac3']);
   428 			unset($info['ac3']);
   416 			return false;
   429 			return false;
   417 
   430 
   418 		}
   431 		}
   419 
   432 
   420 		if (isset($thisfile_ac3_raw_bsi['fscod2'])) {
   433 		if (isset($thisfile_ac3_raw_bsi['fscod2'])) {
   429 		}
   442 		}
   430 		if (isset($thisfile_ac3_raw_bsi['frmsizecod'])) {
   443 		if (isset($thisfile_ac3_raw_bsi['frmsizecod'])) {
   431 			$thisfile_ac3['frame_length'] = self::frameSizeLookup($thisfile_ac3_raw_bsi['frmsizecod'], $thisfile_ac3_raw_bsi['fscod']);
   444 			$thisfile_ac3['frame_length'] = self::frameSizeLookup($thisfile_ac3_raw_bsi['frmsizecod'], $thisfile_ac3_raw_bsi['fscod']);
   432 			$thisfile_ac3['bitrate']      = self::bitrateLookup($thisfile_ac3_raw_bsi['frmsizecod']);
   445 			$thisfile_ac3['bitrate']      = self::bitrateLookup($thisfile_ac3_raw_bsi['frmsizecod']);
   433 		} elseif (!empty($thisfile_ac3_raw_bsi['frmsiz'])) {
   446 		} elseif (!empty($thisfile_ac3_raw_bsi['frmsiz'])) {
   434 // this isn't right, but it's (usually) close, roughly 5% less than it should be.
   447 			// this isn't right, but it's (usually) close, roughly 5% less than it should be.
   435 // but WHERE is the actual bitrate value stored in EAC3?? email info@getid3.org if you know!
   448 			// but WHERE is the actual bitrate value stored in EAC3?? email info@getid3.org if you know!
   436 			$thisfile_ac3['bitrate']      = ($thisfile_ac3_raw_bsi['frmsiz'] + 1) * 16 * 30; // The frmsiz field shall contain a value one less than the overall size of the coded syncframe in 16-bit words. That is, this field may assume a value ranging from 0 to 2047, and these values correspond to syncframe sizes ranging from 1 to 2048.
   449 			$thisfile_ac3['bitrate']      = ($thisfile_ac3_raw_bsi['frmsiz'] + 1) * 16 * 30; // The frmsiz field shall contain a value one less than the overall size of the coded syncframe in 16-bit words. That is, this field may assume a value ranging from 0 to 2047, and these values correspond to syncframe sizes ranging from 1 to 2048.
   437 // kludge-fix to make it approximately the expected value, still not "right":
   450 			// kludge-fix to make it approximately the expected value, still not "right":
   438 $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16000;
   451 			$thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16000;
   439 		}
   452 		}
   440 		$info['audio']['bitrate'] = $thisfile_ac3['bitrate'];
   453 		$info['audio']['bitrate'] = $thisfile_ac3['bitrate'];
   441 
   454 
   442 		$thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']);
   455 		if (isset($thisfile_ac3_raw_bsi['bsmod']) && isset($thisfile_ac3_raw_bsi['acmod'])) {
       
   456 			$thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']);
       
   457 		}
   443 		$ac3_coding_mode = self::audioCodingModeLookup($thisfile_ac3_raw_bsi['acmod']);
   458 		$ac3_coding_mode = self::audioCodingModeLookup($thisfile_ac3_raw_bsi['acmod']);
   444 		foreach($ac3_coding_mode as $key => $value) {
   459 		foreach($ac3_coding_mode as $key => $value) {
   445 			$thisfile_ac3[$key] = $value;
   460 			$thisfile_ac3[$key] = $value;
   446 		}
   461 		}
   447 		switch ($thisfile_ac3_raw_bsi['acmod']) {
   462 		switch ($thisfile_ac3_raw_bsi['acmod']) {
   468 		$thisfile_ac3['dialogue_normalization'] = '-'.$thisfile_ac3_raw_bsi['dialnorm'].'dB';
   483 		$thisfile_ac3['dialogue_normalization'] = '-'.$thisfile_ac3_raw_bsi['dialnorm'].'dB';
   469 
   484 
   470 		return true;
   485 		return true;
   471 	}
   486 	}
   472 
   487 
       
   488 	/**
       
   489 	 * @param int $length
       
   490 	 *
       
   491 	 * @return int
       
   492 	 */
   473 	private function readHeaderBSI($length) {
   493 	private function readHeaderBSI($length) {
   474 		$data = substr($this->AC3header['bsi'], $this->BSIoffset, $length);
   494 		$data = substr($this->AC3header['bsi'], $this->BSIoffset, $length);
   475 		$this->BSIoffset += $length;
   495 		$this->BSIoffset += $length;
   476 
   496 
   477 		return bindec($data);
   497 		return bindec($data);
   478 	}
   498 	}
   479 
   499 
       
   500 	/**
       
   501 	 * @param int $fscod
       
   502 	 *
       
   503 	 * @return int|string|false
       
   504 	 */
   480 	public static function sampleRateCodeLookup($fscod) {
   505 	public static function sampleRateCodeLookup($fscod) {
   481 		static $sampleRateCodeLookup = array(
   506 		static $sampleRateCodeLookup = array(
   482 			0 => 48000,
   507 			0 => 48000,
   483 			1 => 44100,
   508 			1 => 44100,
   484 			2 => 32000,
   509 			2 => 32000,
   485 			3 => 'reserved' // If the reserved code is indicated, the decoder should not attempt to decode audio and should mute.
   510 			3 => 'reserved' // If the reserved code is indicated, the decoder should not attempt to decode audio and should mute.
   486 		);
   511 		);
   487 		return (isset($sampleRateCodeLookup[$fscod]) ? $sampleRateCodeLookup[$fscod] : false);
   512 		return (isset($sampleRateCodeLookup[$fscod]) ? $sampleRateCodeLookup[$fscod] : false);
   488 	}
   513 	}
   489 
   514 
       
   515 	/**
       
   516 	 * @param int $fscod2
       
   517 	 *
       
   518 	 * @return int|string|false
       
   519 	 */
   490 	public static function sampleRateCodeLookup2($fscod2) {
   520 	public static function sampleRateCodeLookup2($fscod2) {
   491 		static $sampleRateCodeLookup2 = array(
   521 		static $sampleRateCodeLookup2 = array(
   492 			0 => 24000,
   522 			0 => 24000,
   493 			1 => 22050,
   523 			1 => 22050,
   494 			2 => 16000,
   524 			2 => 16000,
   495 			3 => 'reserved' // If the reserved code is indicated, the decoder should not attempt to decode audio and should mute.
   525 			3 => 'reserved' // If the reserved code is indicated, the decoder should not attempt to decode audio and should mute.
   496 		);
   526 		);
   497 		return (isset($sampleRateCodeLookup2[$fscod2]) ? $sampleRateCodeLookup2[$fscod2] : false);
   527 		return (isset($sampleRateCodeLookup2[$fscod2]) ? $sampleRateCodeLookup2[$fscod2] : false);
   498 	}
   528 	}
   499 
   529 
       
   530 	/**
       
   531 	 * @param int $bsmod
       
   532 	 * @param int $acmod
       
   533 	 *
       
   534 	 * @return string|false
       
   535 	 */
   500 	public static function serviceTypeLookup($bsmod, $acmod) {
   536 	public static function serviceTypeLookup($bsmod, $acmod) {
   501 		static $serviceTypeLookup = array();
   537 		static $serviceTypeLookup = array();
   502 		if (empty($serviceTypeLookup)) {
   538 		if (empty($serviceTypeLookup)) {
   503 			for ($i = 0; $i <= 7; $i++) {
   539 			for ($i = 0; $i <= 7; $i++) {
   504 				$serviceTypeLookup[0][$i] = 'main audio service: complete main (CM)';
   540 				$serviceTypeLookup[0][$i] = 'main audio service: complete main (CM)';
   516 			}
   552 			}
   517 		}
   553 		}
   518 		return (isset($serviceTypeLookup[$bsmod][$acmod]) ? $serviceTypeLookup[$bsmod][$acmod] : false);
   554 		return (isset($serviceTypeLookup[$bsmod][$acmod]) ? $serviceTypeLookup[$bsmod][$acmod] : false);
   519 	}
   555 	}
   520 
   556 
       
   557 	/**
       
   558 	 * @param int $acmod
       
   559 	 *
       
   560 	 * @return array|false
       
   561 	 */
   521 	public static function audioCodingModeLookup($acmod) {
   562 	public static function audioCodingModeLookup($acmod) {
   522 		// array(channel configuration, # channels (not incl LFE), channel order)
   563 		// array(channel configuration, # channels (not incl LFE), channel order)
   523 		static $audioCodingModeLookup = array (
   564 		static $audioCodingModeLookup = array (
   524 			0 => array('channel_config'=>'1+1', 'num_channels'=>2, 'channel_order'=>'Ch1,Ch2'),
   565 			0 => array('channel_config'=>'1+1', 'num_channels'=>2, 'channel_order'=>'Ch1,Ch2'),
   525 			1 => array('channel_config'=>'1/0', 'num_channels'=>1, 'channel_order'=>'C'),
   566 			1 => array('channel_config'=>'1/0', 'num_channels'=>1, 'channel_order'=>'C'),
   531 			7 => array('channel_config'=>'3/2', 'num_channels'=>5, 'channel_order'=>'L,C,R,SL,SR'),
   572 			7 => array('channel_config'=>'3/2', 'num_channels'=>5, 'channel_order'=>'L,C,R,SL,SR'),
   532 		);
   573 		);
   533 		return (isset($audioCodingModeLookup[$acmod]) ? $audioCodingModeLookup[$acmod] : false);
   574 		return (isset($audioCodingModeLookup[$acmod]) ? $audioCodingModeLookup[$acmod] : false);
   534 	}
   575 	}
   535 
   576 
       
   577 	/**
       
   578 	 * @param int $cmixlev
       
   579 	 *
       
   580 	 * @return int|float|string|false
       
   581 	 */
   536 	public static function centerMixLevelLookup($cmixlev) {
   582 	public static function centerMixLevelLookup($cmixlev) {
   537 		static $centerMixLevelLookup;
   583 		static $centerMixLevelLookup;
   538 		if (empty($centerMixLevelLookup)) {
   584 		if (empty($centerMixLevelLookup)) {
   539 			$centerMixLevelLookup = array(
   585 			$centerMixLevelLookup = array(
   540 				0 => pow(2, -3.0 / 6), // 0.707 (-3.0 dB)
   586 				0 => pow(2, -3.0 / 6), // 0.707 (-3.0 dB)
   544 			);
   590 			);
   545 		}
   591 		}
   546 		return (isset($centerMixLevelLookup[$cmixlev]) ? $centerMixLevelLookup[$cmixlev] : false);
   592 		return (isset($centerMixLevelLookup[$cmixlev]) ? $centerMixLevelLookup[$cmixlev] : false);
   547 	}
   593 	}
   548 
   594 
       
   595 	/**
       
   596 	 * @param int $surmixlev
       
   597 	 *
       
   598 	 * @return int|float|string|false
       
   599 	 */
   549 	public static function surroundMixLevelLookup($surmixlev) {
   600 	public static function surroundMixLevelLookup($surmixlev) {
   550 		static $surroundMixLevelLookup;
   601 		static $surroundMixLevelLookup;
   551 		if (empty($surroundMixLevelLookup)) {
   602 		if (empty($surroundMixLevelLookup)) {
   552 			$surroundMixLevelLookup = array(
   603 			$surroundMixLevelLookup = array(
   553 				0 => pow(2, -3.0 / 6),
   604 				0 => pow(2, -3.0 / 6),
   557 			);
   608 			);
   558 		}
   609 		}
   559 		return (isset($surroundMixLevelLookup[$surmixlev]) ? $surroundMixLevelLookup[$surmixlev] : false);
   610 		return (isset($surroundMixLevelLookup[$surmixlev]) ? $surroundMixLevelLookup[$surmixlev] : false);
   560 	}
   611 	}
   561 
   612 
       
   613 	/**
       
   614 	 * @param int $dsurmod
       
   615 	 *
       
   616 	 * @return string|false
       
   617 	 */
   562 	public static function dolbySurroundModeLookup($dsurmod) {
   618 	public static function dolbySurroundModeLookup($dsurmod) {
   563 		static $dolbySurroundModeLookup = array(
   619 		static $dolbySurroundModeLookup = array(
   564 			0 => 'not indicated',
   620 			0 => 'not indicated',
   565 			1 => 'Not Dolby Surround encoded',
   621 			1 => 'Not Dolby Surround encoded',
   566 			2 => 'Dolby Surround encoded',
   622 			2 => 'Dolby Surround encoded',
   567 			3 => 'reserved'
   623 			3 => 'reserved'
   568 		);
   624 		);
   569 		return (isset($dolbySurroundModeLookup[$dsurmod]) ? $dolbySurroundModeLookup[$dsurmod] : false);
   625 		return (isset($dolbySurroundModeLookup[$dsurmod]) ? $dolbySurroundModeLookup[$dsurmod] : false);
   570 	}
   626 	}
   571 
   627 
       
   628 	/**
       
   629 	 * @param int  $acmod
       
   630 	 * @param bool $lfeon
       
   631 	 *
       
   632 	 * @return array
       
   633 	 */
   572 	public static function channelsEnabledLookup($acmod, $lfeon) {
   634 	public static function channelsEnabledLookup($acmod, $lfeon) {
   573 		$lookup = array(
   635 		$lookup = array(
   574 			'ch1'=>(bool) ($acmod == 0),
   636 			'ch1'=>($acmod == 0),
   575 			'ch2'=>(bool) ($acmod == 0),
   637 			'ch2'=>($acmod == 0),
   576 			'left'=>(bool) ($acmod > 1),
   638 			'left'=>($acmod > 1),
   577 			'right'=>(bool) ($acmod > 1),
   639 			'right'=>($acmod > 1),
   578 			'center'=>(bool) ($acmod & 0x01),
   640 			'center'=>(bool) ($acmod & 0x01),
   579 			'surround_mono'=>false,
   641 			'surround_mono'=>false,
   580 			'surround_left'=>false,
   642 			'surround_left'=>false,
   581 			'surround_right'=>false,
   643 			'surround_right'=>false,
   582 			'lfe'=>$lfeon);
   644 			'lfe'=>$lfeon);
   592 				break;
   654 				break;
   593 		}
   655 		}
   594 		return $lookup;
   656 		return $lookup;
   595 	}
   657 	}
   596 
   658 
       
   659 	/**
       
   660 	 * @param int $compre
       
   661 	 *
       
   662 	 * @return float|int
       
   663 	 */
   597 	public static function heavyCompression($compre) {
   664 	public static function heavyCompression($compre) {
   598 		// The first four bits indicate gain changes in 6.02dB increments which can be
   665 		// The first four bits indicate gain changes in 6.02dB increments which can be
   599 		// implemented with an arithmetic shift operation. The following four bits
   666 		// implemented with an arithmetic shift operation. The following four bits
   600 		// indicate linear gain changes, and require a 5-bit multiply.
   667 		// indicate linear gain changes, and require a 5-bit multiply.
   601 		// We will represent the two 4-bit fields of compr as follows:
   668 		// We will represent the two 4-bit fields of compr as follows:
   621 		// -6    -30.10 dB
   688 		// -6    -30.10 dB
   622 		// -7    -36.12 dB
   689 		// -7    -36.12 dB
   623 		// -8    -42.14 dB
   690 		// -8    -42.14 dB
   624 
   691 
   625 		$fourbit = str_pad(decbin(($compre & 0xF0) >> 4), 4, '0', STR_PAD_LEFT);
   692 		$fourbit = str_pad(decbin(($compre & 0xF0) >> 4), 4, '0', STR_PAD_LEFT);
   626 		if ($fourbit{0} == '1') {
   693 		if ($fourbit[0] == '1') {
   627 			$log_gain = -8 + bindec(substr($fourbit, 1));
   694 			$log_gain = -8 + bindec(substr($fourbit, 1));
   628 		} else {
   695 		} else {
   629 			$log_gain = bindec(substr($fourbit, 1));
   696 			$log_gain = bindec(substr($fourbit, 1));
   630 		}
   697 		}
   631 		$log_gain = ($log_gain + 1) * getid3_lib::RGADamplitude2dB(2);
   698 		$log_gain = ($log_gain + 1) * getid3_lib::RGADamplitude2dB(2);
   642 		// -42.14 - 6.02 = -48.16 dB.
   709 		// -42.14 - 6.02 = -48.16 dB.
   643 
   710 
   644 		return $log_gain - $lin_gain;
   711 		return $log_gain - $lin_gain;
   645 	}
   712 	}
   646 
   713 
       
   714 	/**
       
   715 	 * @param int $roomtyp
       
   716 	 *
       
   717 	 * @return string|false
       
   718 	 */
   647 	public static function roomTypeLookup($roomtyp) {
   719 	public static function roomTypeLookup($roomtyp) {
   648 		static $roomTypeLookup = array(
   720 		static $roomTypeLookup = array(
   649 			0 => 'not indicated',
   721 			0 => 'not indicated',
   650 			1 => 'large room, X curve monitor',
   722 			1 => 'large room, X curve monitor',
   651 			2 => 'small room, flat monitor',
   723 			2 => 'small room, flat monitor',
   652 			3 => 'reserved'
   724 			3 => 'reserved'
   653 		);
   725 		);
   654 		return (isset($roomTypeLookup[$roomtyp]) ? $roomTypeLookup[$roomtyp] : false);
   726 		return (isset($roomTypeLookup[$roomtyp]) ? $roomTypeLookup[$roomtyp] : false);
   655 	}
   727 	}
   656 
   728 
       
   729 	/**
       
   730 	 * @param int $frmsizecod
       
   731 	 * @param int $fscod
       
   732 	 *
       
   733 	 * @return int|false
       
   734 	 */
   657 	public static function frameSizeLookup($frmsizecod, $fscod) {
   735 	public static function frameSizeLookup($frmsizecod, $fscod) {
   658 		// LSB is whether padding is used or not
   736 		// LSB is whether padding is used or not
   659 		$padding     = (bool) ($frmsizecod & 0x01);
   737 		$padding     = (bool) ($frmsizecod & 0x01);
   660 		$framesizeid =        ($frmsizecod & 0x3E) >> 1;
   738 		$framesizeid =        ($frmsizecod & 0x3E) >> 1;
   661 
   739 
   681 				16 => array(2048, 2228, 3072),  // 512 kbps
   759 				16 => array(2048, 2228, 3072),  // 512 kbps
   682 				17 => array(2304, 2506, 3456),  // 576 kbps
   760 				17 => array(2304, 2506, 3456),  // 576 kbps
   683 				18 => array(2560, 2786, 3840)   // 640 kbps
   761 				18 => array(2560, 2786, 3840)   // 640 kbps
   684 			);
   762 			);
   685 		}
   763 		}
       
   764 		$paddingBytes = 0;
   686 		if (($fscod == 1) && $padding) {
   765 		if (($fscod == 1) && $padding) {
   687 			// frame lengths are padded by 1 word (16 bits) at 44100
   766 			// frame lengths are padded by 1 word (16 bits) at 44100
   688 			$frameSizeLookup[$frmsizecod] += 2;
   767 			// (fscode==1) means 44100Hz (see sampleRateCodeLookup)
   689 		}
   768 			$paddingBytes = 2;
   690 		return (isset($frameSizeLookup[$framesizeid][$fscod]) ? $frameSizeLookup[$framesizeid][$fscod] : false);
   769 		}
   691 	}
   770 		return (isset($frameSizeLookup[$framesizeid][$fscod]) ? $frameSizeLookup[$framesizeid][$fscod] + $paddingBytes : false);
   692 
   771 	}
       
   772 
       
   773 	/**
       
   774 	 * @param int $frmsizecod
       
   775 	 *
       
   776 	 * @return int|false
       
   777 	 */
   693 	public static function bitrateLookup($frmsizecod) {
   778 	public static function bitrateLookup($frmsizecod) {
   694 		// LSB is whether padding is used or not
   779 		// LSB is whether padding is used or not
   695 		$padding     = (bool) ($frmsizecod & 0x01);
   780 		$padding     = (bool) ($frmsizecod & 0x01);
   696 		$framesizeid =        ($frmsizecod & 0x3E) >> 1;
   781 		$framesizeid =        ($frmsizecod & 0x3E) >> 1;
   697 
   782 
   717 			18 => 640000,
   802 			18 => 640000,
   718 		);
   803 		);
   719 		return (isset($bitrateLookup[$framesizeid]) ? $bitrateLookup[$framesizeid] : false);
   804 		return (isset($bitrateLookup[$framesizeid]) ? $bitrateLookup[$framesizeid] : false);
   720 	}
   805 	}
   721 
   806 
       
   807 	/**
       
   808 	 * @param int $numblkscod
       
   809 	 *
       
   810 	 * @return int|false
       
   811 	 */
   722 	public static function blocksPerSyncFrame($numblkscod) {
   812 	public static function blocksPerSyncFrame($numblkscod) {
   723 		static $blocksPerSyncFrameLookup = array(
   813 		static $blocksPerSyncFrameLookup = array(
   724 			0 => 1,
   814 			0 => 1,
   725 			1 => 2,
   815 			1 => 2,
   726 			2 => 3,
   816 			2 => 3,