wp/wp-includes/ID3/module.audio.ac3.php
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 16 a86126ab1dd4
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
    18 class getid3_ac3 extends getid3_handler
    18 class getid3_ac3 extends getid3_handler
    19 {
    19 {
    20     private $AC3header = array();
    20     private $AC3header = array();
    21     private $BSIoffset = 0;
    21     private $BSIoffset = 0;
    22 
    22 
    23     const syncword = "\x0B\x77";
    23     const syncword = 0x0B77;
    24 
    24 
    25 	public function Analyze() {
    25 	public function Analyze() {
    26 		$info = &$this->getid3->info;
    26 		$info = &$this->getid3->info;
    27 
    27 
    28 		///AH
    28 		///AH
    53 		// 	 fscod        2
    53 		// 	 fscod        2
    54 		// 	 frmsizecod   6
    54 		// 	 frmsizecod   6
    55 		// } /* end of syncinfo */
    55 		// } /* end of syncinfo */
    56 
    56 
    57 		$this->fseek($info['avdataoffset']);
    57 		$this->fseek($info['avdataoffset']);
    58 		$this->AC3header['syncinfo'] = $this->fread(5);
    58 		$tempAC3header = $this->fread(100); // should be enough to cover all data, there are some variable-length fields...?
    59 
    59 		$this->AC3header['syncinfo']  =     getid3_lib::BigEndian2Int(substr($tempAC3header, 0, 2));
    60 		if (strpos($this->AC3header['syncinfo'], self::syncword) === 0) {
    60 		$this->AC3header['bsi']       =     getid3_lib::BigEndian2Bin(substr($tempAC3header, 2));
    61 			$thisfile_ac3_raw['synchinfo']['synchword'] = self::syncword;
    61 		$thisfile_ac3_raw_bsi['bsid'] = (getid3_lib::LittleEndian2Int(substr($tempAC3header, 5, 1)) & 0xF8) >> 3; // AC3 and E-AC3 put the "bsid" version identifier in the same place, but unfortnately the 4 bytes between the syncword and the version identifier are interpreted differently, so grab it here so the following code structure can make sense
    62 			$offset = 2;
    62 		unset($tempAC3header);
    63 		} else {
    63 
       
    64 		if ($this->AC3header['syncinfo'] !== self::syncword) {
    64 			if (!$this->isDependencyFor('matroska')) {
    65 			if (!$this->isDependencyFor('matroska')) {
    65 				unset($info['fileformat'], $info['ac3']);
    66 				unset($info['fileformat'], $info['ac3']);
    66 				return $this->error('Expecting "'.getid3_lib::PrintHexBytes(self::syncword).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($this->AC3header['syncinfo'], 0, 2)).'"');
    67 				return $this->error('Expecting "'.dechex(self::syncword).'" at offset '.$info['avdataoffset'].', found "'.dechex($this->AC3header['syncinfo']).'"');
    67 			}
    68 			}
    68 			$offset = 0;
       
    69 			$this->fseek(-2, SEEK_CUR);
       
    70 		}
    69 		}
    71 
    70 
    72 		$info['audio']['dataformat']   = 'ac3';
    71 		$info['audio']['dataformat']   = 'ac3';
    73 		$info['audio']['bitrate_mode'] = 'cbr';
    72 		$info['audio']['bitrate_mode'] = 'cbr';
    74 		$info['audio']['lossless']     = false;
    73 		$info['audio']['lossless']     = false;
    75 
    74 
    76 		$thisfile_ac3_raw['synchinfo']['crc1']       = getid3_lib::LittleEndian2Int(substr($this->AC3header['syncinfo'], $offset, 2));
    75 		if ($thisfile_ac3_raw_bsi['bsid'] <= 8) {
    77 		$ac3_synchinfo_fscod_frmsizecod              = getid3_lib::LittleEndian2Int(substr($this->AC3header['syncinfo'], ($offset + 2), 1));
    76 
    78 		$thisfile_ac3_raw['synchinfo']['fscod']      = ($ac3_synchinfo_fscod_frmsizecod & 0xC0) >> 6;
    77 			$thisfile_ac3_raw_bsi['crc1']       = getid3_lib::Bin2Dec($this->readHeaderBSI(16));
    79 		$thisfile_ac3_raw['synchinfo']['frmsizecod'] = ($ac3_synchinfo_fscod_frmsizecod & 0x3F);
    78 			$thisfile_ac3_raw_bsi['fscod']      =                     $this->readHeaderBSI(2);   // 5.4.1.3
    80 
    79 			$thisfile_ac3_raw_bsi['frmsizecod'] =                     $this->readHeaderBSI(6);   // 5.4.1.4
    81 		$thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup($thisfile_ac3_raw['synchinfo']['fscod']);
    80 			if ($thisfile_ac3_raw_bsi['frmsizecod'] > 37) { // binary: 100101 - see Table 5.18 Frame Size Code Table (1 word = 16 bits)
    82 		if ($thisfile_ac3_raw['synchinfo']['fscod'] <= 3) {
    81 				$this->warning('Unexpected ac3.bsi.frmsizecod value: '.$thisfile_ac3_raw_bsi['frmsizecod'].', bitrate not set correctly');
    83 			$info['audio']['sample_rate'] = $thisfile_ac3['sample_rate'];
    82 			}
    84 		}
    83 
    85 
    84 			$thisfile_ac3_raw_bsi['bsid']  = $this->readHeaderBSI(5); // we already know this from pre-parsing the version identifier, but re-read it to let the bitstream flow as intended
    86 		$thisfile_ac3['frame_length'] = self::frameSizeLookup($thisfile_ac3_raw['synchinfo']['frmsizecod'], $thisfile_ac3_raw['synchinfo']['fscod']);
    85 			$thisfile_ac3_raw_bsi['bsmod'] = $this->readHeaderBSI(3);
    87 		$thisfile_ac3['bitrate']      = self::bitrateLookup($thisfile_ac3_raw['synchinfo']['frmsizecod']);
    86 			$thisfile_ac3_raw_bsi['acmod'] = $this->readHeaderBSI(3);
    88 		$info['audio']['bitrate'] = $thisfile_ac3['bitrate'];
    87 
    89 
    88 			if ($thisfile_ac3_raw_bsi['acmod'] & 0x01) {
    90 		$this->AC3header['bsi'] = getid3_lib::BigEndian2Bin($this->fread(15));
    89 				// If the lsb of acmod is a 1, center channel is in use and cmixlev follows in the bit stream.
    91 		$ac3_bsi_offset = 0;
    90 				$thisfile_ac3_raw_bsi['cmixlev'] = $this->readHeaderBSI(2);
    92 
    91 				$thisfile_ac3['center_mix_level'] = self::centerMixLevelLookup($thisfile_ac3_raw_bsi['cmixlev']);
    93 		$thisfile_ac3_raw_bsi['bsid'] = $this->readHeaderBSI(5);
    92 			}
    94 		if ($thisfile_ac3_raw_bsi['bsid'] > 8) {
    93 
    95 			// Decoders which can decode version 8 will thus be able to decode version numbers less than 8.
    94 			if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) {
    96 			// If this standard is extended by the addition of additional elements or features, a value of bsid greater than 8 will be used.
    95 				// If the msb of acmod is a 1, surround channels are in use and surmixlev follows in the bit stream.
    97 			// Decoders built to this version of the standard will not be able to decode versions with bsid greater than 8.
    96 				$thisfile_ac3_raw_bsi['surmixlev'] = $this->readHeaderBSI(2);
    98 			$this->error('Bit stream identification is version '.$thisfile_ac3_raw_bsi['bsid'].', but getID3() only understands up to version 8');
    97 				$thisfile_ac3['surround_mix_level'] = self::surroundMixLevelLookup($thisfile_ac3_raw_bsi['surmixlev']);
       
    98 			}
       
    99 
       
   100 			if ($thisfile_ac3_raw_bsi['acmod'] == 0x02) {
       
   101 				// When operating in the two channel mode, this 2-bit code indicates whether or not the program has been encoded in Dolby Surround.
       
   102 				$thisfile_ac3_raw_bsi['dsurmod'] = $this->readHeaderBSI(2);
       
   103 				$thisfile_ac3['dolby_surround_mode'] = self::dolbySurroundModeLookup($thisfile_ac3_raw_bsi['dsurmod']);
       
   104 			}
       
   105 
       
   106 			$thisfile_ac3_raw_bsi['flags']['lfeon'] = (bool) $this->readHeaderBSI(1);
       
   107 
       
   108 			// This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31.
       
   109 			// The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
       
   110 			$thisfile_ac3_raw_bsi['dialnorm'] = $this->readHeaderBSI(5);                 // 5.4.2.8 dialnorm: Dialogue Normalization, 5 Bits
       
   111 
       
   112 			$thisfile_ac3_raw_bsi['flags']['compr'] = (bool) $this->readHeaderBSI(1);       // 5.4.2.9 compre: Compression Gain Word Exists, 1 Bit
       
   113 			if ($thisfile_ac3_raw_bsi['flags']['compr']) {
       
   114 				$thisfile_ac3_raw_bsi['compr'] = $this->readHeaderBSI(8);                // 5.4.2.10 compr: Compression Gain Word, 8 Bits
       
   115 				$thisfile_ac3['heavy_compression'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr']);
       
   116 			}
       
   117 
       
   118 			$thisfile_ac3_raw_bsi['flags']['langcod'] = (bool) $this->readHeaderBSI(1);     // 5.4.2.11 langcode: Language Code Exists, 1 Bit
       
   119 			if ($thisfile_ac3_raw_bsi['flags']['langcod']) {
       
   120 				$thisfile_ac3_raw_bsi['langcod'] = $this->readHeaderBSI(8);              // 5.4.2.12 langcod: Language Code, 8 Bits
       
   121 			}
       
   122 
       
   123 			$thisfile_ac3_raw_bsi['flags']['audprodinfo'] = (bool) $this->readHeaderBSI(1);  // 5.4.2.13 audprodie: Audio Production Information Exists, 1 Bit
       
   124 			if ($thisfile_ac3_raw_bsi['flags']['audprodinfo']) {
       
   125 				$thisfile_ac3_raw_bsi['mixlevel'] = $this->readHeaderBSI(5);             // 5.4.2.14 mixlevel: Mixing Level, 5 Bits
       
   126 				$thisfile_ac3_raw_bsi['roomtyp']  = $this->readHeaderBSI(2);             // 5.4.2.15 roomtyp: Room Type, 2 Bits
       
   127 
       
   128 				$thisfile_ac3['mixing_level'] = (80 + $thisfile_ac3_raw_bsi['mixlevel']).'dB';
       
   129 				$thisfile_ac3['room_type']    = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp']);
       
   130 			}
       
   131 
       
   132 
       
   133 			$thisfile_ac3_raw_bsi['dialnorm2'] = $this->readHeaderBSI(5);                // 5.4.2.16 dialnorm2: Dialogue Normalization, ch2, 5 Bits
       
   134 			$thisfile_ac3['dialogue_normalization2'] = '-'.$thisfile_ac3_raw_bsi['dialnorm2'].'dB';  // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31. The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
       
   135 
       
   136 			$thisfile_ac3_raw_bsi['flags']['compr2'] = (bool) $this->readHeaderBSI(1);       // 5.4.2.17 compr2e: Compression Gain Word Exists, ch2, 1 Bit
       
   137 			if ($thisfile_ac3_raw_bsi['flags']['compr2']) {
       
   138 				$thisfile_ac3_raw_bsi['compr2'] = $this->readHeaderBSI(8);               // 5.4.2.18 compr2: Compression Gain Word, ch2, 8 Bits
       
   139 				$thisfile_ac3['heavy_compression2'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr2']);
       
   140 			}
       
   141 
       
   142 			$thisfile_ac3_raw_bsi['flags']['langcod2'] = (bool) $this->readHeaderBSI(1);    // 5.4.2.19 langcod2e: Language Code Exists, ch2, 1 Bit
       
   143 			if ($thisfile_ac3_raw_bsi['flags']['langcod2']) {
       
   144 				$thisfile_ac3_raw_bsi['langcod2'] = $this->readHeaderBSI(8);             // 5.4.2.20 langcod2: Language Code, ch2, 8 Bits
       
   145 			}
       
   146 
       
   147 			$thisfile_ac3_raw_bsi['flags']['audprodinfo2'] = (bool) $this->readHeaderBSI(1); // 5.4.2.21 audprodi2e: Audio Production Information Exists, ch2, 1 Bit
       
   148 			if ($thisfile_ac3_raw_bsi['flags']['audprodinfo2']) {
       
   149 				$thisfile_ac3_raw_bsi['mixlevel2'] = $this->readHeaderBSI(5);            // 5.4.2.22 mixlevel2: Mixing Level, ch2, 5 Bits
       
   150 				$thisfile_ac3_raw_bsi['roomtyp2']  = $this->readHeaderBSI(2);            // 5.4.2.23 roomtyp2: Room Type, ch2, 2 Bits
       
   151 
       
   152 				$thisfile_ac3['mixing_level2'] = (80 + $thisfile_ac3_raw_bsi['mixlevel2']).'dB';
       
   153 				$thisfile_ac3['room_type2']    = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp2']);
       
   154 			}
       
   155 
       
   156 			$thisfile_ac3_raw_bsi['copyright'] = (bool) $this->readHeaderBSI(1);         // 5.4.2.24 copyrightb: Copyright Bit, 1 Bit
       
   157 
       
   158 			$thisfile_ac3_raw_bsi['original']  = (bool) $this->readHeaderBSI(1);         // 5.4.2.25 origbs: Original Bit Stream, 1 Bit
       
   159 
       
   160 			$thisfile_ac3_raw_bsi['flags']['timecod1'] = $this->readHeaderBSI(2);            // 5.4.2.26 timecod1e, timcode2e: Time Code (first and second) Halves Exist, 2 Bits
       
   161 			if ($thisfile_ac3_raw_bsi['flags']['timecod1'] & 0x01) {
       
   162 				$thisfile_ac3_raw_bsi['timecod1'] = $this->readHeaderBSI(14);            // 5.4.2.27 timecod1: Time code first half, 14 bits
       
   163 				$thisfile_ac3['timecode1'] = 0;
       
   164 				$thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x3E00) >>  9) * 3600;  // The first 5 bits of this 14-bit field represent the time in hours, with valid values of 0�23
       
   165 				$thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x01F8) >>  3) *   60;  // The next 6 bits represent the time in minutes, with valid values of 0�59
       
   166 				$thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x0003) >>  0) *    8;  // The final 3 bits represents the time in 8 second increments, with valid values of 0�7 (representing 0, 8, 16, ... 56 seconds)
       
   167 			}
       
   168 			if ($thisfile_ac3_raw_bsi['flags']['timecod1'] & 0x02) {
       
   169 				$thisfile_ac3_raw_bsi['timecod2'] = $this->readHeaderBSI(14);            // 5.4.2.28 timecod2: Time code second half, 14 bits
       
   170 				$thisfile_ac3['timecode2'] = 0;
       
   171 				$thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x3800) >> 11) *   1;              // The first 3 bits of this 14-bit field represent the time in seconds, with valid values from 0�7 (representing 0-7 seconds)
       
   172 				$thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x07C0) >>  6) *  (1 / 30);        // The next 5 bits represents the time in frames, with valid values from 0�29 (one frame = 1/30th of a second)
       
   173 				$thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x003F) >>  0) * ((1 / 30) / 60);  // The final 6 bits represents fractions of 1/64 of a frame, with valid values from 0�63
       
   174 			}
       
   175 
       
   176 			$thisfile_ac3_raw_bsi['flags']['addbsi'] = (bool) $this->readHeaderBSI(1);
       
   177 			if ($thisfile_ac3_raw_bsi['flags']['addbsi']) {
       
   178 				$thisfile_ac3_raw_bsi['addbsi_length'] = $this->readHeaderBSI(6) + 1; // This 6-bit code, which exists only if addbside is a 1, indicates the length in bytes of additional bit stream information. The valid range of addbsil is 0�63, indicating 1�64 additional bytes, respectively.
       
   179 
       
   180 				$this->AC3header['bsi'] .= getid3_lib::BigEndian2Bin($this->fread($thisfile_ac3_raw_bsi['addbsi_length']));
       
   181 
       
   182 				$thisfile_ac3_raw_bsi['addbsi_data'] = substr($this->AC3header['bsi'], $this->BSIoffset, $thisfile_ac3_raw_bsi['addbsi_length'] * 8);
       
   183 				$this->BSIoffset += $thisfile_ac3_raw_bsi['addbsi_length'] * 8;
       
   184 			}
       
   185 
       
   186 
       
   187 		} elseif ($thisfile_ac3_raw_bsi['bsid'] <= 16) { // E-AC3
       
   188 
       
   189 
       
   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.');
       
   191 			$info['audio']['dataformat'] = 'eac3';
       
   192 
       
   193 			$thisfile_ac3_raw_bsi['strmtyp']          =        $this->readHeaderBSI(2);
       
   194 			$thisfile_ac3_raw_bsi['substreamid']      =        $this->readHeaderBSI(3);
       
   195 			$thisfile_ac3_raw_bsi['frmsiz']           =        $this->readHeaderBSI(11);
       
   196 			$thisfile_ac3_raw_bsi['fscod']            =        $this->readHeaderBSI(2);
       
   197 			if ($thisfile_ac3_raw_bsi['fscod'] == 3) {
       
   198 				$thisfile_ac3_raw_bsi['fscod2']       =        $this->readHeaderBSI(2);
       
   199 				$thisfile_ac3_raw_bsi['numblkscod'] = 3; // six blocks per syncframe
       
   200 			} else {
       
   201 				$thisfile_ac3_raw_bsi['numblkscod']   =        $this->readHeaderBSI(2);
       
   202 			}
       
   203 			$thisfile_ac3['bsi']['blocks_per_sync_frame'] = self::blocksPerSyncFrame($thisfile_ac3_raw_bsi['numblkscod']);
       
   204 			$thisfile_ac3_raw_bsi['acmod']            =        $this->readHeaderBSI(3);
       
   205 			$thisfile_ac3_raw_bsi['flags']['lfeon']   = (bool) $this->readHeaderBSI(1);
       
   206 			$thisfile_ac3_raw_bsi['bsid']             =        $this->readHeaderBSI(5); // we already know this from pre-parsing the version identifier, but re-read it to let the bitstream flow as intended
       
   207 			$thisfile_ac3_raw_bsi['dialnorm']         =        $this->readHeaderBSI(5);
       
   208 			$thisfile_ac3_raw_bsi['flags']['compr']       = (bool) $this->readHeaderBSI(1);
       
   209 			if ($thisfile_ac3_raw_bsi['flags']['compr']) {
       
   210 				$thisfile_ac3_raw_bsi['compr']        =        $this->readHeaderBSI(8);
       
   211 			}
       
   212 			if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
       
   213 				$thisfile_ac3_raw_bsi['dialnorm2']    =        $this->readHeaderBSI(5);
       
   214 				$thisfile_ac3_raw_bsi['flags']['compr2']  = (bool) $this->readHeaderBSI(1);
       
   215 				if ($thisfile_ac3_raw_bsi['flags']['compr2']) {
       
   216 					$thisfile_ac3_raw_bsi['compr2']   =        $this->readHeaderBSI(8);
       
   217 				}
       
   218 			}
       
   219 			if ($thisfile_ac3_raw_bsi['strmtyp'] == 1) { // if dependent stream
       
   220 				$thisfile_ac3_raw_bsi['flags']['chanmap'] = (bool) $this->readHeaderBSI(1);
       
   221 				if ($thisfile_ac3_raw_bsi['flags']['chanmap']) {
       
   222 					$thisfile_ac3_raw_bsi['chanmap']  =        $this->readHeaderBSI(8);
       
   223 				}
       
   224 			}
       
   225 			$thisfile_ac3_raw_bsi['flags']['mixmdat']     = (bool) $this->readHeaderBSI(1);
       
   226 			if ($thisfile_ac3_raw_bsi['flags']['mixmdat']) { // Mixing metadata
       
   227 				if ($thisfile_ac3_raw_bsi['acmod'] > 2) { // if more than 2 channels
       
   228 					$thisfile_ac3_raw_bsi['dmixmod']  =        $this->readHeaderBSI(2);
       
   229 				}
       
   230 				if (($thisfile_ac3_raw_bsi['acmod'] & 0x01) && ($thisfile_ac3_raw_bsi['acmod'] > 2)) { // if three front channels exist
       
   231 					$thisfile_ac3_raw_bsi['ltrtcmixlev'] =        $this->readHeaderBSI(3);
       
   232 					$thisfile_ac3_raw_bsi['lorocmixlev'] =        $this->readHeaderBSI(3);
       
   233 				}
       
   234 				if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) { // if a surround channel exists
       
   235 					$thisfile_ac3_raw_bsi['ltrtsurmixlev'] =        $this->readHeaderBSI(3);
       
   236 					$thisfile_ac3_raw_bsi['lorosurmixlev'] =        $this->readHeaderBSI(3);
       
   237 				}
       
   238 				if ($thisfile_ac3_raw_bsi['flags']['lfeon']) { // if the LFE channel exists
       
   239 					$thisfile_ac3_raw_bsi['flags']['lfemixlevcod'] = (bool) $this->readHeaderBSI(1);
       
   240 					if ($thisfile_ac3_raw_bsi['flags']['lfemixlevcod']) {
       
   241 						$thisfile_ac3_raw_bsi['lfemixlevcod']  =        $this->readHeaderBSI(5);
       
   242 					}
       
   243 				}
       
   244 				if ($thisfile_ac3_raw_bsi['strmtyp'] == 0) { // if independent stream
       
   245 					$thisfile_ac3_raw_bsi['flags']['pgmscl'] = (bool) $this->readHeaderBSI(1);
       
   246 					if ($thisfile_ac3_raw_bsi['flags']['pgmscl']) {
       
   247 						$thisfile_ac3_raw_bsi['pgmscl']  =        $this->readHeaderBSI(6);
       
   248 					}
       
   249 					if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
       
   250 						$thisfile_ac3_raw_bsi['flags']['pgmscl2'] = (bool) $this->readHeaderBSI(1);
       
   251 						if ($thisfile_ac3_raw_bsi['flags']['pgmscl2']) {
       
   252 							$thisfile_ac3_raw_bsi['pgmscl2']  =        $this->readHeaderBSI(6);
       
   253 						}
       
   254 					}
       
   255 					$thisfile_ac3_raw_bsi['flags']['extpgmscl'] = (bool) $this->readHeaderBSI(1);
       
   256 					if ($thisfile_ac3_raw_bsi['flags']['extpgmscl']) {
       
   257 						$thisfile_ac3_raw_bsi['extpgmscl']  =        $this->readHeaderBSI(6);
       
   258 					}
       
   259 					$thisfile_ac3_raw_bsi['mixdef']  =        $this->readHeaderBSI(2);
       
   260 					if ($thisfile_ac3_raw_bsi['mixdef'] == 1) { // mixing option 2
       
   261 						$thisfile_ac3_raw_bsi['premixcmpsel']  = (bool) $this->readHeaderBSI(1);
       
   262 						$thisfile_ac3_raw_bsi['drcsrc']        = (bool) $this->readHeaderBSI(1);
       
   263 						$thisfile_ac3_raw_bsi['premixcmpscl']  =        $this->readHeaderBSI(3);
       
   264 					} elseif ($thisfile_ac3_raw_bsi['mixdef'] == 2) { // mixing option 3
       
   265 						$thisfile_ac3_raw_bsi['mixdata']       =        $this->readHeaderBSI(12);
       
   266 					} elseif ($thisfile_ac3_raw_bsi['mixdef'] == 3) { // mixing option 4
       
   267 						$mixdefbitsread = 0;
       
   268 						$thisfile_ac3_raw_bsi['mixdeflen']     =        $this->readHeaderBSI(5); $mixdefbitsread += 5;
       
   269 						$thisfile_ac3_raw_bsi['flags']['mixdata2'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
       
   270 						if ($thisfile_ac3_raw_bsi['flags']['mixdata2']) {
       
   271 							$thisfile_ac3_raw_bsi['premixcmpsel']  = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
       
   272 							$thisfile_ac3_raw_bsi['drcsrc']        = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
       
   273 							$thisfile_ac3_raw_bsi['premixcmpscl']  =        $this->readHeaderBSI(3); $mixdefbitsread += 3;
       
   274 							$thisfile_ac3_raw_bsi['flags']['extpgmlscl']   = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
       
   275 							if ($thisfile_ac3_raw_bsi['flags']['extpgmlscl']) {
       
   276 								$thisfile_ac3_raw_bsi['extpgmlscl']    =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
       
   277 							}
       
   278 							$thisfile_ac3_raw_bsi['flags']['extpgmcscl']   = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
       
   279 							if ($thisfile_ac3_raw_bsi['flags']['extpgmcscl']) {
       
   280 								$thisfile_ac3_raw_bsi['extpgmcscl']    =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
       
   281 							}
       
   282 							$thisfile_ac3_raw_bsi['flags']['extpgmrscl']   = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
       
   283 							if ($thisfile_ac3_raw_bsi['flags']['extpgmrscl']) {
       
   284 								$thisfile_ac3_raw_bsi['extpgmrscl']    =        $this->readHeaderBSI(4);
       
   285 							}
       
   286 							$thisfile_ac3_raw_bsi['flags']['extpgmlsscl']  = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
       
   287 							if ($thisfile_ac3_raw_bsi['flags']['extpgmlsscl']) {
       
   288 								$thisfile_ac3_raw_bsi['extpgmlsscl']   =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
       
   289 							}
       
   290 							$thisfile_ac3_raw_bsi['flags']['extpgmrsscl']  = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
       
   291 							if ($thisfile_ac3_raw_bsi['flags']['extpgmrsscl']) {
       
   292 								$thisfile_ac3_raw_bsi['extpgmrsscl']   =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
       
   293 							}
       
   294 							$thisfile_ac3_raw_bsi['flags']['extpgmlfescl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
       
   295 							if ($thisfile_ac3_raw_bsi['flags']['extpgmlfescl']) {
       
   296 								$thisfile_ac3_raw_bsi['extpgmlfescl']  =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
       
   297 							}
       
   298 							$thisfile_ac3_raw_bsi['flags']['dmixscl']      = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
       
   299 							if ($thisfile_ac3_raw_bsi['flags']['dmixscl']) {
       
   300 								$thisfile_ac3_raw_bsi['dmixscl']       =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
       
   301 							}
       
   302 							$thisfile_ac3_raw_bsi['flags']['addch']        = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
       
   303 							if ($thisfile_ac3_raw_bsi['flags']['addch']) {
       
   304 								$thisfile_ac3_raw_bsi['flags']['extpgmaux1scl']   = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
       
   305 								if ($thisfile_ac3_raw_bsi['flags']['extpgmaux1scl']) {
       
   306 									$thisfile_ac3_raw_bsi['extpgmaux1scl']    =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
       
   307 								}
       
   308 								$thisfile_ac3_raw_bsi['flags']['extpgmaux2scl']   = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
       
   309 								if ($thisfile_ac3_raw_bsi['flags']['extpgmaux2scl']) {
       
   310 									$thisfile_ac3_raw_bsi['extpgmaux2scl']    =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
       
   311 								}
       
   312 							}
       
   313 						}
       
   314 						$thisfile_ac3_raw_bsi['flags']['mixdata3'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
       
   315 						if ($thisfile_ac3_raw_bsi['flags']['mixdata3']) {
       
   316 							$thisfile_ac3_raw_bsi['spchdat']   =        $this->readHeaderBSI(5); $mixdefbitsread += 5;
       
   317 							$thisfile_ac3_raw_bsi['flags']['addspchdat'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
       
   318 							if ($thisfile_ac3_raw_bsi['flags']['addspchdat']) {
       
   319 								$thisfile_ac3_raw_bsi['spchdat1']   =         $this->readHeaderBSI(5); $mixdefbitsread += 5;
       
   320 								$thisfile_ac3_raw_bsi['spchan1att'] =         $this->readHeaderBSI(2); $mixdefbitsread += 2;
       
   321 								$thisfile_ac3_raw_bsi['flags']['addspchdat1'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
       
   322 								if ($thisfile_ac3_raw_bsi['flags']['addspchdat1']) {
       
   323 									$thisfile_ac3_raw_bsi['spchdat2']   =         $this->readHeaderBSI(5); $mixdefbitsread += 5;
       
   324 									$thisfile_ac3_raw_bsi['spchan2att'] =         $this->readHeaderBSI(3); $mixdefbitsread += 3;
       
   325 								}
       
   326 							}
       
   327 						}
       
   328 						$mixdata_bits = (8 * ($thisfile_ac3_raw_bsi['mixdeflen'] + 2)) - $mixdefbitsread;
       
   329 						$mixdata_fill = (($mixdata_bits % 8) ? 8 - ($mixdata_bits % 8) : 0);
       
   330 						$thisfile_ac3_raw_bsi['mixdata']     =        $this->readHeaderBSI($mixdata_bits);
       
   331 						$thisfile_ac3_raw_bsi['mixdatafill'] =        $this->readHeaderBSI($mixdata_fill);
       
   332 						unset($mixdefbitsread, $mixdata_bits, $mixdata_fill);
       
   333 					}
       
   334 					if ($thisfile_ac3_raw_bsi['acmod'] < 2) { // if mono or dual mono source
       
   335 						$thisfile_ac3_raw_bsi['flags']['paninfo'] = (bool) $this->readHeaderBSI(1);
       
   336 						if ($thisfile_ac3_raw_bsi['flags']['paninfo']) {
       
   337 							$thisfile_ac3_raw_bsi['panmean']   =        $this->readHeaderBSI(8);
       
   338 							$thisfile_ac3_raw_bsi['paninfo']   =        $this->readHeaderBSI(6);
       
   339 						}
       
   340 						if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
       
   341 							$thisfile_ac3_raw_bsi['flags']['paninfo2'] = (bool) $this->readHeaderBSI(1);
       
   342 							if ($thisfile_ac3_raw_bsi['flags']['paninfo2']) {
       
   343 								$thisfile_ac3_raw_bsi['panmean2']   =        $this->readHeaderBSI(8);
       
   344 								$thisfile_ac3_raw_bsi['paninfo2']   =        $this->readHeaderBSI(6);
       
   345 							}
       
   346 						}
       
   347 					}
       
   348 					$thisfile_ac3_raw_bsi['flags']['frmmixcfginfo'] = (bool) $this->readHeaderBSI(1);
       
   349 					if ($thisfile_ac3_raw_bsi['flags']['frmmixcfginfo']) { // mixing configuration information
       
   350 						if ($thisfile_ac3_raw_bsi['numblkscod'] == 0) {
       
   351 							$thisfile_ac3_raw_bsi['blkmixcfginfo'][0]  =        $this->readHeaderBSI(5);
       
   352 						} else {
       
   353 							for ($blk = 0; $blk < $thisfile_ac3_raw_bsi['numblkscod']; $blk++) {
       
   354 								$thisfile_ac3_raw_bsi['flags']['blkmixcfginfo'.$blk] = (bool) $this->readHeaderBSI(1);
       
   355 								if ($thisfile_ac3_raw_bsi['flags']['blkmixcfginfo'.$blk]) { // mixing configuration information
       
   356 									$thisfile_ac3_raw_bsi['blkmixcfginfo'][$blk]  =        $this->readHeaderBSI(5);
       
   357 								}
       
   358 							}
       
   359 						}
       
   360 					}
       
   361 				}
       
   362 			}
       
   363 			$thisfile_ac3_raw_bsi['flags']['infomdat']          = (bool) $this->readHeaderBSI(1);
       
   364 			if ($thisfile_ac3_raw_bsi['flags']['infomdat']) { // Informational metadata
       
   365 				$thisfile_ac3_raw_bsi['bsmod']                  =        $this->readHeaderBSI(3);
       
   366 				$thisfile_ac3_raw_bsi['flags']['copyrightb']    = (bool) $this->readHeaderBSI(1);
       
   367 				$thisfile_ac3_raw_bsi['flags']['origbs']        = (bool) $this->readHeaderBSI(1);
       
   368 				if ($thisfile_ac3_raw_bsi['acmod'] == 2) { //  if in 2/0 mode
       
   369 					$thisfile_ac3_raw_bsi['dsurmod']            =        $this->readHeaderBSI(2);
       
   370 					$thisfile_ac3_raw_bsi['dheadphonmod']       =        $this->readHeaderBSI(2);
       
   371 				}
       
   372 				if ($thisfile_ac3_raw_bsi['acmod'] >= 6) { //  if both surround channels exist
       
   373 					$thisfile_ac3_raw_bsi['dsurexmod']          =        $this->readHeaderBSI(2);
       
   374 				}
       
   375 				$thisfile_ac3_raw_bsi['flags']['audprodi']      = (bool) $this->readHeaderBSI(1);
       
   376 				if ($thisfile_ac3_raw_bsi['flags']['audprodi']) {
       
   377 					$thisfile_ac3_raw_bsi['mixlevel']           =        $this->readHeaderBSI(5);
       
   378 					$thisfile_ac3_raw_bsi['roomtyp']            =        $this->readHeaderBSI(2);
       
   379 					$thisfile_ac3_raw_bsi['flags']['adconvtyp'] = (bool) $this->readHeaderBSI(1);
       
   380 				}
       
   381 				if ($thisfile_ac3_raw_bsi['acmod'] == 0) { //  if 1+1 mode (dual mono, so some items need a second value)
       
   382 					$thisfile_ac3_raw_bsi['flags']['audprodi2']      = (bool) $this->readHeaderBSI(1);
       
   383 					if ($thisfile_ac3_raw_bsi['flags']['audprodi2']) {
       
   384 						$thisfile_ac3_raw_bsi['mixlevel2']           =        $this->readHeaderBSI(5);
       
   385 						$thisfile_ac3_raw_bsi['roomtyp2']            =        $this->readHeaderBSI(2);
       
   386 						$thisfile_ac3_raw_bsi['flags']['adconvtyp2'] = (bool) $this->readHeaderBSI(1);
       
   387 					}
       
   388 				}
       
   389 				if ($thisfile_ac3_raw_bsi['fscod'] < 3) { // if not half sample rate
       
   390 					$thisfile_ac3_raw_bsi['flags']['sourcefscod'] = (bool) $this->readHeaderBSI(1);
       
   391 				}
       
   392 			}
       
   393 			if (($thisfile_ac3_raw_bsi['strmtyp'] == 0) && ($thisfile_ac3_raw_bsi['numblkscod'] != 3)) { //  if both surround channels exist
       
   394 				$thisfile_ac3_raw_bsi['flags']['convsync'] = (bool) $this->readHeaderBSI(1);
       
   395 			}
       
   396 			if ($thisfile_ac3_raw_bsi['strmtyp'] == 2) { //  if bit stream converted from AC-3
       
   397 				if ($thisfile_ac3_raw_bsi['numblkscod'] != 3) { // 6 blocks per syncframe
       
   398 					$thisfile_ac3_raw_bsi['flags']['blkid']  = 1;
       
   399 				} else {
       
   400 					$thisfile_ac3_raw_bsi['flags']['blkid']  = (bool) $this->readHeaderBSI(1);
       
   401 				}
       
   402 				if ($thisfile_ac3_raw_bsi['flags']['blkid']) {
       
   403 					$thisfile_ac3_raw_bsi['frmsizecod']  =        $this->readHeaderBSI(6);
       
   404 				}
       
   405 			}
       
   406 			$thisfile_ac3_raw_bsi['flags']['addbsi']  = (bool) $this->readHeaderBSI(1);
       
   407 			if ($thisfile_ac3_raw_bsi['flags']['addbsi']) {
       
   408 				$thisfile_ac3_raw_bsi['addbsil']  =        $this->readHeaderBSI(6);
       
   409 				$thisfile_ac3_raw_bsi['addbsi']   =        $this->readHeaderBSI(($thisfile_ac3_raw_bsi['addbsil'] + 1) * 8);
       
   410 			}
       
   411 
       
   412 		} else {
       
   413 
       
   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.');
    99 		    unset($info['ac3']);
   415 		    unset($info['ac3']);
   100 			return false;
   416 			return false;
   101 		}
   417 
   102 
   418 		}
   103 		$thisfile_ac3_raw_bsi['bsmod'] = $this->readHeaderBSI(3);
   419 
   104 		$thisfile_ac3_raw_bsi['acmod'] = $this->readHeaderBSI(3);
   420 		if (isset($thisfile_ac3_raw_bsi['fscod2'])) {
       
   421 			$thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup2($thisfile_ac3_raw_bsi['fscod2']);
       
   422 		} else {
       
   423 			$thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup($thisfile_ac3_raw_bsi['fscod']);
       
   424 		}
       
   425 		if ($thisfile_ac3_raw_bsi['fscod'] <= 3) {
       
   426 			$info['audio']['sample_rate'] = $thisfile_ac3['sample_rate'];
       
   427 		} else {
       
   428 			$this->warning('Unexpected ac3.bsi.fscod value: '.$thisfile_ac3_raw_bsi['fscod']);
       
   429 		}
       
   430 		if (isset($thisfile_ac3_raw_bsi['frmsizecod'])) {
       
   431 			$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']);
       
   433 		} elseif (!empty($thisfile_ac3_raw_bsi['frmsiz'])) {
       
   434 // 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!
       
   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.
       
   437 // kludge-fix to make it approximately the expected value, still not "right":
       
   438 $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16000;
       
   439 		}
       
   440 		$info['audio']['bitrate'] = $thisfile_ac3['bitrate'];
   105 
   441 
   106 		$thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']);
   442 		$thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']);
   107 		$ac3_coding_mode = self::audioCodingModeLookup($thisfile_ac3_raw_bsi['acmod']);
   443 		$ac3_coding_mode = self::audioCodingModeLookup($thisfile_ac3_raw_bsi['acmod']);
   108 		foreach($ac3_coding_mode as $key => $value) {
   444 		foreach($ac3_coding_mode as $key => $value) {
   109 			$thisfile_ac3[$key] = $value;
   445 			$thisfile_ac3[$key] = $value;
   121 				$info['audio']['channelmode'] = 'surround';
   457 				$info['audio']['channelmode'] = 'surround';
   122 				break;
   458 				break;
   123 		}
   459 		}
   124 		$info['audio']['channels'] = $thisfile_ac3['num_channels'];
   460 		$info['audio']['channels'] = $thisfile_ac3['num_channels'];
   125 
   461 
   126 		if ($thisfile_ac3_raw_bsi['acmod'] & 0x01) {
   462 		$thisfile_ac3['lfe_enabled'] = $thisfile_ac3_raw_bsi['flags']['lfeon'];
   127 			// If the lsb of acmod is a 1, center channel is in use and cmixlev follows in the bit stream.
   463 		if ($thisfile_ac3_raw_bsi['flags']['lfeon']) {
   128 			$thisfile_ac3_raw_bsi['cmixlev'] = $this->readHeaderBSI(2);
       
   129 			$thisfile_ac3['center_mix_level'] = self::centerMixLevelLookup($thisfile_ac3_raw_bsi['cmixlev']);
       
   130 		}
       
   131 
       
   132 		if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) {
       
   133 			// If the msb of acmod is a 1, surround channels are in use and surmixlev follows in the bit stream.
       
   134 			$thisfile_ac3_raw_bsi['surmixlev'] = $this->readHeaderBSI(2);
       
   135 			$thisfile_ac3['surround_mix_level'] = self::surroundMixLevelLookup($thisfile_ac3_raw_bsi['surmixlev']);
       
   136 		}
       
   137 
       
   138 		if ($thisfile_ac3_raw_bsi['acmod'] == 0x02) {
       
   139 			// When operating in the two channel mode, this 2-bit code indicates whether or not the program has been encoded in Dolby Surround.
       
   140 			$thisfile_ac3_raw_bsi['dsurmod'] = $this->readHeaderBSI(2);
       
   141 			$thisfile_ac3['dolby_surround_mode'] = self::dolbySurroundModeLookup($thisfile_ac3_raw_bsi['dsurmod']);
       
   142 		}
       
   143 
       
   144 		$thisfile_ac3_raw_bsi['lfeon'] = (bool) $this->readHeaderBSI(1);
       
   145 		$thisfile_ac3['lfe_enabled'] = $thisfile_ac3_raw_bsi['lfeon'];
       
   146 		if ($thisfile_ac3_raw_bsi['lfeon']) {
       
   147 			//$info['audio']['channels']++;
       
   148 			$info['audio']['channels'] .= '.1';
   464 			$info['audio']['channels'] .= '.1';
   149 		}
   465 		}
   150 
   466 
   151 		$thisfile_ac3['channels_enabled'] = self::channelsEnabledLookup($thisfile_ac3_raw_bsi['acmod'], $thisfile_ac3_raw_bsi['lfeon']);
   467 		$thisfile_ac3['channels_enabled'] = self::channelsEnabledLookup($thisfile_ac3_raw_bsi['acmod'], $thisfile_ac3_raw_bsi['flags']['lfeon']);
   152 
       
   153 		// This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31.
       
   154 		// The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
       
   155 		$thisfile_ac3_raw_bsi['dialnorm'] = $this->readHeaderBSI(5);
       
   156 		$thisfile_ac3['dialogue_normalization'] = '-'.$thisfile_ac3_raw_bsi['dialnorm'].'dB';
   468 		$thisfile_ac3['dialogue_normalization'] = '-'.$thisfile_ac3_raw_bsi['dialnorm'].'dB';
   157 
       
   158 		$thisfile_ac3_raw_bsi['compre_flag'] = (bool) $this->readHeaderBSI(1);
       
   159 		if ($thisfile_ac3_raw_bsi['compre_flag']) {
       
   160 			$thisfile_ac3_raw_bsi['compr'] = $this->readHeaderBSI(8);
       
   161 			$thisfile_ac3['heavy_compression'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr']);
       
   162 		}
       
   163 
       
   164 		$thisfile_ac3_raw_bsi['langcode_flag'] = (bool) $this->readHeaderBSI(1);
       
   165 		if ($thisfile_ac3_raw_bsi['langcode_flag']) {
       
   166 			$thisfile_ac3_raw_bsi['langcod'] = $this->readHeaderBSI(8);
       
   167 		}
       
   168 
       
   169 		$thisfile_ac3_raw_bsi['audprodie'] = (bool) $this->readHeaderBSI(1);
       
   170 		if ($thisfile_ac3_raw_bsi['audprodie']) {
       
   171 			$thisfile_ac3_raw_bsi['mixlevel'] = $this->readHeaderBSI(5);
       
   172 			$thisfile_ac3_raw_bsi['roomtyp']  = $this->readHeaderBSI(2);
       
   173 
       
   174 			$thisfile_ac3['mixing_level'] = (80 + $thisfile_ac3_raw_bsi['mixlevel']).'dB';
       
   175 			$thisfile_ac3['room_type']    = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp']);
       
   176 		}
       
   177 
       
   178 		if ($thisfile_ac3_raw_bsi['acmod'] == 0x00) {
       
   179 			// If acmod is 0, then two completely independent program channels (dual mono)
       
   180 			// are encoded into the bit stream, and are referenced as Ch1, Ch2. In this case,
       
   181 			// a number of additional items are present in BSI or audblk to fully describe Ch2.
       
   182 
       
   183 			// This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31.
       
   184 			// The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
       
   185 			$thisfile_ac3_raw_bsi['dialnorm2'] = $this->readHeaderBSI(5);
       
   186 			$thisfile_ac3['dialogue_normalization2'] = '-'.$thisfile_ac3_raw_bsi['dialnorm2'].'dB';
       
   187 
       
   188 			$thisfile_ac3_raw_bsi['compre_flag2'] = (bool) $this->readHeaderBSI(1);
       
   189 			if ($thisfile_ac3_raw_bsi['compre_flag2']) {
       
   190 				$thisfile_ac3_raw_bsi['compr2'] = $this->readHeaderBSI(8);
       
   191 				$thisfile_ac3['heavy_compression2'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr2']);
       
   192 			}
       
   193 
       
   194 			$thisfile_ac3_raw_bsi['langcode_flag2'] = (bool) $this->readHeaderBSI(1);
       
   195 			if ($thisfile_ac3_raw_bsi['langcode_flag2']) {
       
   196 				$thisfile_ac3_raw_bsi['langcod2'] = $this->readHeaderBSI(8);
       
   197 			}
       
   198 
       
   199 			$thisfile_ac3_raw_bsi['audprodie2'] = (bool) $this->readHeaderBSI(1);
       
   200 			if ($thisfile_ac3_raw_bsi['audprodie2']) {
       
   201 				$thisfile_ac3_raw_bsi['mixlevel2'] = $this->readHeaderBSI(5);
       
   202 				$thisfile_ac3_raw_bsi['roomtyp2']  = $this->readHeaderBSI(2);
       
   203 
       
   204 				$thisfile_ac3['mixing_level2'] = (80 + $thisfile_ac3_raw_bsi['mixlevel2']).'dB';
       
   205 				$thisfile_ac3['room_type2']    = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp2']);
       
   206 			}
       
   207 
       
   208 		}
       
   209 
       
   210 		$thisfile_ac3_raw_bsi['copyright'] = (bool) $this->readHeaderBSI(1);
       
   211 
       
   212 		$thisfile_ac3_raw_bsi['original']  = (bool) $this->readHeaderBSI(1);
       
   213 
       
   214 		$thisfile_ac3_raw_bsi['timecode1_flag'] = (bool) $this->readHeaderBSI(1);
       
   215 		if ($thisfile_ac3_raw_bsi['timecode1_flag']) {
       
   216 			$thisfile_ac3_raw_bsi['timecode1'] = $this->readHeaderBSI(14);
       
   217 		}
       
   218 
       
   219 		$thisfile_ac3_raw_bsi['timecode2_flag'] = (bool) $this->readHeaderBSI(1);
       
   220 		if ($thisfile_ac3_raw_bsi['timecode2_flag']) {
       
   221 			$thisfile_ac3_raw_bsi['timecode2'] = $this->readHeaderBSI(14);
       
   222 		}
       
   223 
       
   224 		$thisfile_ac3_raw_bsi['addbsi_flag'] = (bool) $this->readHeaderBSI(1);
       
   225 		if ($thisfile_ac3_raw_bsi['addbsi_flag']) {
       
   226 			$thisfile_ac3_raw_bsi['addbsi_length'] = $this->readHeaderBSI(6);
       
   227 
       
   228 			$this->AC3header['bsi'] .= getid3_lib::BigEndian2Bin($this->fread($thisfile_ac3_raw_bsi['addbsi_length']));
       
   229 
       
   230 			$thisfile_ac3_raw_bsi['addbsi_data'] = substr($this->AC3header['bsi'], $this->BSIoffset, $thisfile_ac3_raw_bsi['addbsi_length'] * 8);
       
   231 			$this->BSIoffset += $thisfile_ac3_raw_bsi['addbsi_length'] * 8;
       
   232 		}
       
   233 
   469 
   234 		return true;
   470 		return true;
   235 	}
   471 	}
   236 
   472 
   237 	private function readHeaderBSI($length) {
   473 	private function readHeaderBSI($length) {
   247 			1 => 44100,
   483 			1 => 44100,
   248 			2 => 32000,
   484 			2 => 32000,
   249 			3 => 'reserved' // If the reserved code is indicated, the decoder should not attempt to decode audio and should mute.
   485 			3 => 'reserved' // If the reserved code is indicated, the decoder should not attempt to decode audio and should mute.
   250 		);
   486 		);
   251 		return (isset($sampleRateCodeLookup[$fscod]) ? $sampleRateCodeLookup[$fscod] : false);
   487 		return (isset($sampleRateCodeLookup[$fscod]) ? $sampleRateCodeLookup[$fscod] : false);
       
   488 	}
       
   489 
       
   490 	public static function sampleRateCodeLookup2($fscod2) {
       
   491 		static $sampleRateCodeLookup2 = array(
       
   492 			0 => 24000,
       
   493 			1 => 22050,
       
   494 			2 => 16000,
       
   495 			3 => 'reserved' // If the reserved code is indicated, the decoder should not attempt to decode audio and should mute.
       
   496 		);
       
   497 		return (isset($sampleRateCodeLookup2[$fscod2]) ? $sampleRateCodeLookup2[$fscod2] : false);
   252 	}
   498 	}
   253 
   499 
   254 	public static function serviceTypeLookup($bsmod, $acmod) {
   500 	public static function serviceTypeLookup($bsmod, $acmod) {
   255 		static $serviceTypeLookup = array();
   501 		static $serviceTypeLookup = array();
   256 		if (empty($serviceTypeLookup)) {
   502 		if (empty($serviceTypeLookup)) {
   407 		);
   653 		);
   408 		return (isset($roomTypeLookup[$roomtyp]) ? $roomTypeLookup[$roomtyp] : false);
   654 		return (isset($roomTypeLookup[$roomtyp]) ? $roomTypeLookup[$roomtyp] : false);
   409 	}
   655 	}
   410 
   656 
   411 	public static function frameSizeLookup($frmsizecod, $fscod) {
   657 	public static function frameSizeLookup($frmsizecod, $fscod) {
   412 		$padding     = (bool) ($frmsizecod % 2);
   658 		// LSB is whether padding is used or not
   413 		$framesizeid =   floor($frmsizecod / 2);
   659 		$padding     = (bool) ($frmsizecod & 0x01);
       
   660 		$framesizeid =        ($frmsizecod & 0x3E) >> 1;
   414 
   661 
   415 		static $frameSizeLookup = array();
   662 		static $frameSizeLookup = array();
   416 		if (empty($frameSizeLookup)) {
   663 		if (empty($frameSizeLookup)) {
   417 			$frameSizeLookup = array (
   664 			$frameSizeLookup = array (
   418 				0  => array(128, 138, 192),
   665 				0  => array( 128,  138,  192),  //  32 kbps
   419 				1  => array(40, 160, 174, 240),
   666 				1  => array( 160,  174,  240),  //  40 kbps
   420 				2  => array(48, 192, 208, 288),
   667 				2  => array( 192,  208,  288),  //  48 kbps
   421 				3  => array(56, 224, 242, 336),
   668 				3  => array( 224,  242,  336),  //  56 kbps
   422 				4  => array(64, 256, 278, 384),
   669 				4  => array( 256,  278,  384),  //  64 kbps
   423 				5  => array(80, 320, 348, 480),
   670 				5  => array( 320,  348,  480),  //  80 kbps
   424 				6  => array(96, 384, 416, 576),
   671 				6  => array( 384,  416,  576),  //  96 kbps
   425 				7  => array(112, 448, 486, 672),
   672 				7  => array( 448,  486,  672),  // 112 kbps
   426 				8  => array(128, 512, 556, 768),
   673 				8  => array( 512,  556,  768),  // 128 kbps
   427 				9  => array(160, 640, 696, 960),
   674 				9  => array( 640,  696,  960),  // 160 kbps
   428 				10 => array(192, 768, 834, 1152),
   675 				10 => array( 768,  834, 1152),  // 192 kbps
   429 				11 => array(224, 896, 974, 1344),
   676 				11 => array( 896,  974, 1344),  // 224 kbps
   430 				12 => array(256, 1024, 1114, 1536),
   677 				12 => array(1024, 1114, 1536),  // 256 kbps
   431 				13 => array(320, 1280, 1392, 1920),
   678 				13 => array(1280, 1392, 1920),  // 320 kbps
   432 				14 => array(384, 1536, 1670, 2304),
   679 				14 => array(1536, 1670, 2304),  // 384 kbps
   433 				15 => array(448, 1792, 1950, 2688),
   680 				15 => array(1792, 1950, 2688),  // 448 kbps
   434 				16 => array(512, 2048, 2228, 3072),
   681 				16 => array(2048, 2228, 3072),  // 512 kbps
   435 				17 => array(576, 2304, 2506, 3456),
   682 				17 => array(2304, 2506, 3456),  // 576 kbps
   436 				18 => array(640, 2560, 2786, 3840)
   683 				18 => array(2560, 2786, 3840)   // 640 kbps
   437 			);
   684 			);
   438 		}
   685 		}
   439 		if (($fscod == 1) && $padding) {
   686 		if (($fscod == 1) && $padding) {
   440 			// frame lengths are padded by 1 word (16 bits) at 44100
   687 			// frame lengths are padded by 1 word (16 bits) at 44100
   441 			$frameSizeLookup[$frmsizecod] += 2;
   688 			$frameSizeLookup[$frmsizecod] += 2;
   442 		}
   689 		}
   443 		return (isset($frameSizeLookup[$framesizeid][$fscod]) ? $frameSizeLookup[$framesizeid][$fscod] : false);
   690 		return (isset($frameSizeLookup[$framesizeid][$fscod]) ? $frameSizeLookup[$framesizeid][$fscod] : false);
   444 	}
   691 	}
   445 
   692 
   446 	public static function bitrateLookup($frmsizecod) {
   693 	public static function bitrateLookup($frmsizecod) {
   447 		$framesizeid =   floor($frmsizecod / 2);
   694 		// LSB is whether padding is used or not
       
   695 		$padding     = (bool) ($frmsizecod & 0x01);
       
   696 		$framesizeid =        ($frmsizecod & 0x3E) >> 1;
   448 
   697 
   449 		static $bitrateLookup = array(
   698 		static $bitrateLookup = array(
   450 			0  => 32000,
   699 			 0 =>  32000,
   451 			1  => 40000,
   700 			 1 =>  40000,
   452 			2  => 48000,
   701 			 2 =>  48000,
   453 			3  => 56000,
   702 			 3 =>  56000,
   454 			4  => 64000,
   703 			 4 =>  64000,
   455 			5  => 80000,
   704 			 5 =>  80000,
   456 			6  => 96000,
   705 			 6 =>  96000,
   457 			7  => 112000,
   706 			 7 => 112000,
   458 			8  => 128000,
   707 			 8 => 128000,
   459 			9  => 160000,
   708 			 9 => 160000,
   460 			10 => 192000,
   709 			10 => 192000,
   461 			11 => 224000,
   710 			11 => 224000,
   462 			12 => 256000,
   711 			12 => 256000,
   463 			13 => 320000,
   712 			13 => 320000,
   464 			14 => 384000,
   713 			14 => 384000,
   465 			15 => 448000,
   714 			15 => 448000,
   466 			16 => 512000,
   715 			16 => 512000,
   467 			17 => 576000,
   716 			17 => 576000,
   468 			18 => 640000
   717 			18 => 640000,
   469 		);
   718 		);
   470 		return (isset($bitrateLookup[$framesizeid]) ? $bitrateLookup[$framesizeid] : false);
   719 		return (isset($bitrateLookup[$framesizeid]) ? $bitrateLookup[$framesizeid] : false);
   471 	}
   720 	}
   472 
   721 
       
   722 	public static function blocksPerSyncFrame($numblkscod) {
       
   723 		static $blocksPerSyncFrameLookup = array(
       
   724 			0 => 1,
       
   725 			1 => 2,
       
   726 			2 => 3,
       
   727 			3 => 6,
       
   728 		);
       
   729 		return (isset($blocksPerSyncFrameLookup[$numblkscod]) ? $blocksPerSyncFrameLookup[$numblkscod] : false);
       
   730 	}
       
   731 
   473 
   732 
   474 }
   733 }