File indexing completed on 2024-12-22 05:33:12
0001 <?php 0002 ///////////////////////////////////////////////////////////////// 0003 /// getID3() by James Heinrich <info@getid3.org> // 0004 // available at http://getid3.sourceforge.net // 0005 // or http://www.getid3.org // 0006 // also https://github.com/JamesHeinrich/getID3 // 0007 ///////////////////////////////////////////////////////////////// 0008 // See readme.txt for more details // 0009 ///////////////////////////////////////////////////////////////// 0010 // // 0011 // module.audio.aac.php // 0012 // module for analyzing AAC Audio files // 0013 // dependencies: NONE // 0014 // /// 0015 ///////////////////////////////////////////////////////////////// 0016 0017 0018 class getid3_aac extends getid3_handler 0019 { 0020 public function Analyze() { 0021 $info = &$this->getid3->info; 0022 $this->fseek($info['avdataoffset']); 0023 if ($this->fread(4) == 'ADIF') { 0024 $this->getAACADIFheaderFilepointer(); 0025 } else { 0026 $this->getAACADTSheaderFilepointer(); 0027 } 0028 return true; 0029 } 0030 0031 0032 0033 public function getAACADIFheaderFilepointer() { 0034 $info = &$this->getid3->info; 0035 $info['fileformat'] = 'aac'; 0036 $info['audio']['dataformat'] = 'aac'; 0037 $info['audio']['lossless'] = false; 0038 0039 $this->fseek($info['avdataoffset']); 0040 $AACheader = $this->fread(1024); 0041 $offset = 0; 0042 0043 if (substr($AACheader, 0, 4) == 'ADIF') { 0044 0045 // http://faac.sourceforge.net/wiki/index.php?page=ADIF 0046 0047 // http://libmpeg.org/mpeg4/doc/w2203tfs.pdf 0048 // adif_header() { 0049 // adif_id 32 0050 // copyright_id_present 1 0051 // if( copyright_id_present ) 0052 // copyright_id 72 0053 // original_copy 1 0054 // home 1 0055 // bitstream_type 1 0056 // bitrate 23 0057 // num_program_config_elements 4 0058 // for (i = 0; i < num_program_config_elements + 1; i++ ) { 0059 // if( bitstream_type == '0' ) 0060 // adif_buffer_fullness 20 0061 // program_config_element() 0062 // } 0063 // } 0064 0065 $AACheaderBitstream = getid3_lib::BigEndian2Bin($AACheader); 0066 $bitoffset = 0; 0067 0068 $info['aac']['header_type'] = 'ADIF'; 0069 $bitoffset += 32; 0070 $info['aac']['header']['mpeg_version'] = 4; 0071 0072 $info['aac']['header']['copyright'] = (bool) (substr($AACheaderBitstream, $bitoffset, 1) == '1'); 0073 $bitoffset += 1; 0074 if ($info['aac']['header']['copyright']) { 0075 $info['aac']['header']['copyright_id'] = getid3_lib::Bin2String(substr($AACheaderBitstream, $bitoffset, 72)); 0076 $bitoffset += 72; 0077 } 0078 $info['aac']['header']['original_copy'] = (bool) (substr($AACheaderBitstream, $bitoffset, 1) == '1'); 0079 $bitoffset += 1; 0080 $info['aac']['header']['home'] = (bool) (substr($AACheaderBitstream, $bitoffset, 1) == '1'); 0081 $bitoffset += 1; 0082 $info['aac']['header']['is_vbr'] = (bool) (substr($AACheaderBitstream, $bitoffset, 1) == '1'); 0083 $bitoffset += 1; 0084 if ($info['aac']['header']['is_vbr']) { 0085 $info['audio']['bitrate_mode'] = 'vbr'; 0086 $info['aac']['header']['bitrate_max'] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 23)); 0087 $bitoffset += 23; 0088 } else { 0089 $info['audio']['bitrate_mode'] = 'cbr'; 0090 $info['aac']['header']['bitrate'] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 23)); 0091 $bitoffset += 23; 0092 $info['audio']['bitrate'] = $info['aac']['header']['bitrate']; 0093 } 0094 if ($info['audio']['bitrate'] == 0) { 0095 $info['error'][] = 'Corrupt AAC file: bitrate_audio == zero'; 0096 return false; 0097 } 0098 $info['aac']['header']['num_program_configs'] = 1 + getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4)); 0099 $bitoffset += 4; 0100 0101 for ($i = 0; $i < $info['aac']['header']['num_program_configs']; $i++) { 0102 // http://www.audiocoding.com/wiki/index.php?page=program_config_element 0103 0104 // buffer_fullness 20 0105 0106 // element_instance_tag 4 0107 // object_type 2 0108 // sampling_frequency_index 4 0109 // num_front_channel_elements 4 0110 // num_side_channel_elements 4 0111 // num_back_channel_elements 4 0112 // num_lfe_channel_elements 2 0113 // num_assoc_data_elements 3 0114 // num_valid_cc_elements 4 0115 // mono_mixdown_present 1 0116 // mono_mixdown_element_number 4 if mono_mixdown_present == 1 0117 // stereo_mixdown_present 1 0118 // stereo_mixdown_element_number 4 if stereo_mixdown_present == 1 0119 // matrix_mixdown_idx_present 1 0120 // matrix_mixdown_idx 2 if matrix_mixdown_idx_present == 1 0121 // pseudo_surround_enable 1 if matrix_mixdown_idx_present == 1 0122 // for (i = 0; i < num_front_channel_elements; i++) { 0123 // front_element_is_cpe[i] 1 0124 // front_element_tag_select[i] 4 0125 // } 0126 // for (i = 0; i < num_side_channel_elements; i++) { 0127 // side_element_is_cpe[i] 1 0128 // side_element_tag_select[i] 4 0129 // } 0130 // for (i = 0; i < num_back_channel_elements; i++) { 0131 // back_element_is_cpe[i] 1 0132 // back_element_tag_select[i] 4 0133 // } 0134 // for (i = 0; i < num_lfe_channel_elements; i++) { 0135 // lfe_element_tag_select[i] 4 0136 // } 0137 // for (i = 0; i < num_assoc_data_elements; i++) { 0138 // assoc_data_element_tag_select[i] 4 0139 // } 0140 // for (i = 0; i < num_valid_cc_elements; i++) { 0141 // cc_element_is_ind_sw[i] 1 0142 // valid_cc_element_tag_select[i] 4 0143 // } 0144 // byte_alignment() VAR 0145 // comment_field_bytes 8 0146 // for (i = 0; i < comment_field_bytes; i++) { 0147 // comment_field_data[i] 8 0148 // } 0149 0150 if (!$info['aac']['header']['is_vbr']) { 0151 $info['aac']['program_configs'][$i]['buffer_fullness'] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 20)); 0152 $bitoffset += 20; 0153 } 0154 $info['aac']['program_configs'][$i]['element_instance_tag'] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4)); 0155 $bitoffset += 4; 0156 $info['aac']['program_configs'][$i]['object_type'] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2)); 0157 $bitoffset += 2; 0158 $info['aac']['program_configs'][$i]['sampling_frequency_index'] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4)); 0159 $bitoffset += 4; 0160 $info['aac']['program_configs'][$i]['num_front_channel_elements'] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4)); 0161 $bitoffset += 4; 0162 $info['aac']['program_configs'][$i]['num_side_channel_elements'] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4)); 0163 $bitoffset += 4; 0164 $info['aac']['program_configs'][$i]['num_back_channel_elements'] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4)); 0165 $bitoffset += 4; 0166 $info['aac']['program_configs'][$i]['num_lfe_channel_elements'] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2)); 0167 $bitoffset += 2; 0168 $info['aac']['program_configs'][$i]['num_assoc_data_elements'] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 3)); 0169 $bitoffset += 3; 0170 $info['aac']['program_configs'][$i]['num_valid_cc_elements'] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4)); 0171 $bitoffset += 4; 0172 $info['aac']['program_configs'][$i]['mono_mixdown_present'] = (bool) getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1)); 0173 $bitoffset += 1; 0174 if ($info['aac']['program_configs'][$i]['mono_mixdown_present']) { 0175 $info['aac']['program_configs'][$i]['mono_mixdown_element_number'] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4)); 0176 $bitoffset += 4; 0177 } 0178 $info['aac']['program_configs'][$i]['stereo_mixdown_present'] = (bool) getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1)); 0179 $bitoffset += 1; 0180 if ($info['aac']['program_configs'][$i]['stereo_mixdown_present']) { 0181 $info['aac']['program_configs'][$i]['stereo_mixdown_element_number'] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4)); 0182 $bitoffset += 4; 0183 } 0184 $info['aac']['program_configs'][$i]['matrix_mixdown_idx_present'] = (bool) getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1)); 0185 $bitoffset += 1; 0186 if ($info['aac']['program_configs'][$i]['matrix_mixdown_idx_present']) { 0187 $info['aac']['program_configs'][$i]['matrix_mixdown_idx'] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2)); 0188 $bitoffset += 2; 0189 $info['aac']['program_configs'][$i]['pseudo_surround_enable'] = (bool) getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1)); 0190 $bitoffset += 1; 0191 } 0192 for ($j = 0; $j < $info['aac']['program_configs'][$i]['num_front_channel_elements']; $j++) { 0193 $info['aac']['program_configs'][$i]['front_element_is_cpe'][$j] = (bool) getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1)); 0194 $bitoffset += 1; 0195 $info['aac']['program_configs'][$i]['front_element_tag_select'][$j] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4)); 0196 $bitoffset += 4; 0197 } 0198 for ($j = 0; $j < $info['aac']['program_configs'][$i]['num_side_channel_elements']; $j++) { 0199 $info['aac']['program_configs'][$i]['side_element_is_cpe'][$j] = (bool) getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1)); 0200 $bitoffset += 1; 0201 $info['aac']['program_configs'][$i]['side_element_tag_select'][$j] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4)); 0202 $bitoffset += 4; 0203 } 0204 for ($j = 0; $j < $info['aac']['program_configs'][$i]['num_back_channel_elements']; $j++) { 0205 $info['aac']['program_configs'][$i]['back_element_is_cpe'][$j] = (bool) getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1)); 0206 $bitoffset += 1; 0207 $info['aac']['program_configs'][$i]['back_element_tag_select'][$j] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4)); 0208 $bitoffset += 4; 0209 } 0210 for ($j = 0; $j < $info['aac']['program_configs'][$i]['num_lfe_channel_elements']; $j++) { 0211 $info['aac']['program_configs'][$i]['lfe_element_tag_select'][$j] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4)); 0212 $bitoffset += 4; 0213 } 0214 for ($j = 0; $j < $info['aac']['program_configs'][$i]['num_assoc_data_elements']; $j++) { 0215 $info['aac']['program_configs'][$i]['assoc_data_element_tag_select'][$j] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4)); 0216 $bitoffset += 4; 0217 } 0218 for ($j = 0; $j < $info['aac']['program_configs'][$i]['num_valid_cc_elements']; $j++) { 0219 $info['aac']['program_configs'][$i]['cc_element_is_ind_sw'][$j] = (bool) getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1)); 0220 $bitoffset += 1; 0221 $info['aac']['program_configs'][$i]['valid_cc_element_tag_select'][$j] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4)); 0222 $bitoffset += 4; 0223 } 0224 0225 $bitoffset = ceil($bitoffset / 8) * 8; 0226 0227 $info['aac']['program_configs'][$i]['comment_field_bytes'] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 8)); 0228 $bitoffset += 8; 0229 $info['aac']['program_configs'][$i]['comment_field'] = getid3_lib::Bin2String(substr($AACheaderBitstream, $bitoffset, 8 * $info['aac']['program_configs'][$i]['comment_field_bytes'])); 0230 $bitoffset += 8 * $info['aac']['program_configs'][$i]['comment_field_bytes']; 0231 0232 0233 $info['aac']['header']['profile'] = self::AACprofileLookup($info['aac']['program_configs'][$i]['object_type'], $info['aac']['header']['mpeg_version']); 0234 $info['aac']['program_configs'][$i]['sampling_frequency'] = self::AACsampleRateLookup($info['aac']['program_configs'][$i]['sampling_frequency_index']); 0235 $info['audio']['sample_rate'] = $info['aac']['program_configs'][$i]['sampling_frequency']; 0236 $info['audio']['channels'] = self::AACchannelCountCalculate($info['aac']['program_configs'][$i]); 0237 if ($info['aac']['program_configs'][$i]['comment_field']) { 0238 $info['aac']['comments'][] = $info['aac']['program_configs'][$i]['comment_field']; 0239 } 0240 } 0241 $info['playtime_seconds'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['audio']['bitrate']; 0242 0243 $info['audio']['encoder_options'] = $info['aac']['header_type'].' '.$info['aac']['header']['profile']; 0244 0245 0246 0247 return true; 0248 0249 } else { 0250 0251 unset($info['fileformat']); 0252 unset($info['aac']); 0253 $info['error'][] = 'AAC-ADIF synch not found at offset '.$info['avdataoffset'].' (expected "ADIF", found "'.substr($AACheader, 0, 4).'" instead)'; 0254 return false; 0255 0256 } 0257 0258 } 0259 0260 0261 public function getAACADTSheaderFilepointer($MaxFramesToScan=1000000, $ReturnExtendedInfo=false) { 0262 $info = &$this->getid3->info; 0263 0264 // based loosely on code from AACfile by Jurgen Faul <jfaulØgmx.de> 0265 // http://jfaul.de/atl or http://j-faul.virtualave.net/atl/atl.html 0266 0267 0268 // http://faac.sourceforge.net/wiki/index.php?page=ADTS // dead link 0269 // http://wiki.multimedia.cx/index.php?title=ADTS 0270 0271 // * ADTS Fixed Header: these don't change from frame to frame 0272 // syncword 12 always: '111111111111' 0273 // ID 1 0: MPEG-4, 1: MPEG-2 0274 // MPEG layer 2 If you send AAC in MPEG-TS, set to 0 0275 // protection_absent 1 0: CRC present; 1: no CRC 0276 // profile 2 0: AAC Main; 1: AAC LC (Low Complexity); 2: AAC SSR (Scalable Sample Rate); 3: AAC LTP (Long Term Prediction) 0277 // sampling_frequency_index 4 15 not allowed 0278 // private_bit 1 usually 0 0279 // channel_configuration 3 0280 // original/copy 1 0: original; 1: copy 0281 // home 1 usually 0 0282 // emphasis 2 only if ID == 0 (ie MPEG-4) // not present in some documentation? 0283 0284 // * ADTS Variable Header: these can change from frame to frame 0285 // copyright_identification_bit 1 0286 // copyright_identification_start 1 0287 // aac_frame_length 13 length of the frame including header (in bytes) 0288 // adts_buffer_fullness 11 0x7FF indicates VBR 0289 // no_raw_data_blocks_in_frame 2 0290 0291 // * ADTS Error check 0292 // crc_check 16 only if protection_absent == 0 0293 0294 $byteoffset = $info['avdataoffset']; 0295 $framenumber = 0; 0296 0297 // Init bit pattern array 0298 static $decbin = array(); 0299 0300 // Populate $bindec 0301 for ($i = 0; $i < 256; $i++) { 0302 $decbin[chr($i)] = str_pad(decbin($i), 8, '0', STR_PAD_LEFT); 0303 } 0304 0305 // used to calculate bitrate below 0306 $BitrateCache = array(); 0307 0308 0309 while (true) { 0310 // breaks out when end-of-file encountered, or invalid data found, 0311 // or MaxFramesToScan frames have been scanned 0312 0313 if (!getid3_lib::intValueSupported($byteoffset)) { 0314 $info['warning'][] = 'Unable to parse AAC file beyond '.$this->ftell().' (PHP does not support file operations beyond '.round(PHP_INT_MAX / 1073741824).'GB)'; 0315 return false; 0316 } 0317 $this->fseek($byteoffset); 0318 0319 // First get substring 0320 $substring = $this->fread(9); // header is 7 bytes (or 9 if CRC is present) 0321 $substringlength = strlen($substring); 0322 if ($substringlength != 9) { 0323 $info['error'][] = 'Failed to read 7 bytes at offset '.($this->ftell() - $substringlength).' (only read '.$substringlength.' bytes)'; 0324 return false; 0325 } 0326 // this would be easier with 64-bit math, but split it up to allow for 32-bit: 0327 $header1 = getid3_lib::BigEndian2Int(substr($substring, 0, 2)); 0328 $header2 = getid3_lib::BigEndian2Int(substr($substring, 2, 4)); 0329 $header3 = getid3_lib::BigEndian2Int(substr($substring, 6, 1)); 0330 0331 $info['aac']['header']['raw']['syncword'] = ($header1 & 0xFFF0) >> 4; 0332 if ($info['aac']['header']['raw']['syncword'] != 0x0FFF) { 0333 $info['error'][] = 'Synch pattern (0x0FFF) not found at offset '.($this->ftell() - $substringlength).' (found 0x0'.strtoupper(dechex($info['aac']['header']['raw']['syncword'])).' instead)'; 0334 //if ($info['fileformat'] == 'aac') { 0335 // return true; 0336 //} 0337 unset($info['aac']); 0338 return false; 0339 } 0340 0341 // Gather info for first frame only - this takes time to do 1000 times! 0342 if ($framenumber == 0) { 0343 $info['aac']['header_type'] = 'ADTS'; 0344 $info['fileformat'] = 'aac'; 0345 $info['audio']['dataformat'] = 'aac'; 0346 0347 $info['aac']['header']['raw']['mpeg_version'] = ($header1 & 0x0008) >> 3; 0348 $info['aac']['header']['raw']['mpeg_layer'] = ($header1 & 0x0006) >> 1; 0349 $info['aac']['header']['raw']['protection_absent'] = ($header1 & 0x0001) >> 0; 0350 0351 $info['aac']['header']['raw']['profile_code'] = ($header2 & 0xC0000000) >> 30; 0352 $info['aac']['header']['raw']['sample_rate_code'] = ($header2 & 0x3C000000) >> 26; 0353 $info['aac']['header']['raw']['private_stream'] = ($header2 & 0x02000000) >> 25; 0354 $info['aac']['header']['raw']['channels_code'] = ($header2 & 0x01C00000) >> 22; 0355 $info['aac']['header']['raw']['original'] = ($header2 & 0x00200000) >> 21; 0356 $info['aac']['header']['raw']['home'] = ($header2 & 0x00100000) >> 20; 0357 $info['aac']['header']['raw']['copyright_stream'] = ($header2 & 0x00080000) >> 19; 0358 $info['aac']['header']['raw']['copyright_start'] = ($header2 & 0x00040000) >> 18; 0359 $info['aac']['header']['raw']['frame_length'] = ($header2 & 0x0003FFE0) >> 5; 0360 0361 $info['aac']['header']['mpeg_version'] = ($info['aac']['header']['raw']['mpeg_version'] ? 2 : 4); 0362 $info['aac']['header']['crc_present'] = ($info['aac']['header']['raw']['protection_absent'] ? false: true); 0363 $info['aac']['header']['profile'] = self::AACprofileLookup($info['aac']['header']['raw']['profile_code'], $info['aac']['header']['mpeg_version']); 0364 $info['aac']['header']['sample_frequency'] = self::AACsampleRateLookup($info['aac']['header']['raw']['sample_rate_code']); 0365 $info['aac']['header']['private'] = (bool) $info['aac']['header']['raw']['private_stream']; 0366 $info['aac']['header']['original'] = (bool) $info['aac']['header']['raw']['original']; 0367 $info['aac']['header']['home'] = (bool) $info['aac']['header']['raw']['home']; 0368 $info['aac']['header']['channels'] = (($info['aac']['header']['raw']['channels_code'] == 7) ? 8 : $info['aac']['header']['raw']['channels_code']); 0369 if ($ReturnExtendedInfo) { 0370 $info['aac'][$framenumber]['copyright_id_bit'] = (bool) $info['aac']['header']['raw']['copyright_stream']; 0371 $info['aac'][$framenumber]['copyright_id_start'] = (bool) $info['aac']['header']['raw']['copyright_start']; 0372 } 0373 0374 if ($info['aac']['header']['raw']['mpeg_layer'] != 0) { 0375 $info['warning'][] = 'Layer error - expected "0", found "'.$info['aac']['header']['raw']['mpeg_layer'].'" instead'; 0376 } 0377 if ($info['aac']['header']['sample_frequency'] == 0) { 0378 $info['error'][] = 'Corrupt AAC file: sample_frequency == zero'; 0379 return false; 0380 } 0381 0382 $info['audio']['sample_rate'] = $info['aac']['header']['sample_frequency']; 0383 $info['audio']['channels'] = $info['aac']['header']['channels']; 0384 } 0385 0386 $FrameLength = ($header2 & 0x0003FFE0) >> 5; 0387 0388 if (!isset($BitrateCache[$FrameLength])) { 0389 $BitrateCache[$FrameLength] = ($info['aac']['header']['sample_frequency'] / 1024) * $FrameLength * 8; 0390 } 0391 getid3_lib::safe_inc($info['aac']['bitrate_distribution'][$BitrateCache[$FrameLength]], 1); 0392 0393 $info['aac'][$framenumber]['aac_frame_length'] = $FrameLength; 0394 0395 $info['aac'][$framenumber]['adts_buffer_fullness'] = (($header2 & 0x0000001F) << 6) & (($header3 & 0xFC) >> 2); 0396 if ($info['aac'][$framenumber]['adts_buffer_fullness'] == 0x07FF) { 0397 $info['audio']['bitrate_mode'] = 'vbr'; 0398 } else { 0399 $info['audio']['bitrate_mode'] = 'cbr'; 0400 } 0401 $info['aac'][$framenumber]['num_raw_data_blocks'] = (($header3 & 0x03) >> 0); 0402 0403 if ($info['aac']['header']['crc_present']) { 0404 //$info['aac'][$framenumber]['crc'] = getid3_lib::BigEndian2Int(substr($substring, 7, 2); 0405 } 0406 0407 if (!$ReturnExtendedInfo) { 0408 unset($info['aac'][$framenumber]); 0409 } 0410 0411 /* 0412 $rounded_precision = 5000; 0413 $info['aac']['bitrate_distribution_rounded'] = array(); 0414 foreach ($info['aac']['bitrate_distribution'] as $bitrate => $count) { 0415 $rounded_bitrate = round($bitrate / $rounded_precision) * $rounded_precision; 0416 getid3_lib::safe_inc($info['aac']['bitrate_distribution_rounded'][$rounded_bitrate], $count); 0417 } 0418 ksort($info['aac']['bitrate_distribution_rounded']); 0419 */ 0420 0421 $byteoffset += $FrameLength; 0422 if ((++$framenumber < $MaxFramesToScan) && (($byteoffset + 10) < $info['avdataend'])) { 0423 0424 // keep scanning 0425 0426 } else { 0427 0428 $info['aac']['frames'] = $framenumber; 0429 $info['playtime_seconds'] = ($info['avdataend'] / $byteoffset) * (($framenumber * 1024) / $info['aac']['header']['sample_frequency']); // (1 / % of file scanned) * (samples / (samples/sec)) = seconds 0430 if ($info['playtime_seconds'] == 0) { 0431 $info['error'][] = 'Corrupt AAC file: playtime_seconds == zero'; 0432 return false; 0433 } 0434 $info['audio']['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds']; 0435 ksort($info['aac']['bitrate_distribution']); 0436 0437 $info['audio']['encoder_options'] = $info['aac']['header_type'].' '.$info['aac']['header']['profile']; 0438 0439 return true; 0440 0441 } 0442 } 0443 // should never get here. 0444 } 0445 0446 public static function AACsampleRateLookup($samplerateid) { 0447 static $AACsampleRateLookup = array(); 0448 if (empty($AACsampleRateLookup)) { 0449 $AACsampleRateLookup[0] = 96000; 0450 $AACsampleRateLookup[1] = 88200; 0451 $AACsampleRateLookup[2] = 64000; 0452 $AACsampleRateLookup[3] = 48000; 0453 $AACsampleRateLookup[4] = 44100; 0454 $AACsampleRateLookup[5] = 32000; 0455 $AACsampleRateLookup[6] = 24000; 0456 $AACsampleRateLookup[7] = 22050; 0457 $AACsampleRateLookup[8] = 16000; 0458 $AACsampleRateLookup[9] = 12000; 0459 $AACsampleRateLookup[10] = 11025; 0460 $AACsampleRateLookup[11] = 8000; 0461 $AACsampleRateLookup[12] = 0; 0462 $AACsampleRateLookup[13] = 0; 0463 $AACsampleRateLookup[14] = 0; 0464 $AACsampleRateLookup[15] = 0; 0465 } 0466 return (isset($AACsampleRateLookup[$samplerateid]) ? $AACsampleRateLookup[$samplerateid] : 'invalid'); 0467 } 0468 0469 public static function AACprofileLookup($profileid, $mpegversion) { 0470 static $AACprofileLookup = array(); 0471 if (empty($AACprofileLookup)) { 0472 $AACprofileLookup[2][0] = 'Main profile'; 0473 $AACprofileLookup[2][1] = 'Low Complexity profile (LC)'; 0474 $AACprofileLookup[2][2] = 'Scalable Sample Rate profile (SSR)'; 0475 $AACprofileLookup[2][3] = '(reserved)'; 0476 $AACprofileLookup[4][0] = 'AAC_MAIN'; 0477 $AACprofileLookup[4][1] = 'AAC_LC'; 0478 $AACprofileLookup[4][2] = 'AAC_SSR'; 0479 $AACprofileLookup[4][3] = 'AAC_LTP'; 0480 } 0481 return (isset($AACprofileLookup[$mpegversion][$profileid]) ? $AACprofileLookup[$mpegversion][$profileid] : 'invalid'); 0482 } 0483 0484 public static function AACchannelCountCalculate($program_configs) { 0485 $channels = 0; 0486 for ($i = 0; $i < $program_configs['num_front_channel_elements']; $i++) { 0487 $channels++; 0488 if ($program_configs['front_element_is_cpe'][$i]) { 0489 // each front element is channel pair (CPE = Channel Pair Element) 0490 $channels++; 0491 } 0492 } 0493 for ($i = 0; $i < $program_configs['num_side_channel_elements']; $i++) { 0494 $channels++; 0495 if ($program_configs['side_element_is_cpe'][$i]) { 0496 // each side element is channel pair (CPE = Channel Pair Element) 0497 $channels++; 0498 } 0499 } 0500 for ($i = 0; $i < $program_configs['num_back_channel_elements']; $i++) { 0501 $channels++; 0502 if ($program_configs['back_element_is_cpe'][$i]) { 0503 // each back element is channel pair (CPE = Channel Pair Element) 0504 $channels++; 0505 } 0506 } 0507 for ($i = 0; $i < $program_configs['num_lfe_channel_elements']; $i++) { 0508 $channels++; 0509 } 0510 return $channels; 0511 } 0512 0513 }