23 if ($option ===
'adif') {
26 elseif ($option ===
'adts') {
34 $ThisFileInfo[
'fileformat'] =
'aac';
35 $ThisFileInfo[
'audio'][
'dataformat'] =
'aac';
36 $ThisFileInfo[
'audio'][
'lossless'] =
false;
38 fseek($fd, $ThisFileInfo[
'avdataoffset'], SEEK_SET);
39 $AACheader = fread($fd, 1024);
42 if (substr($AACheader, 0, 4) ==
'ADIF') {
67 $ThisFileInfo[
'aac'][
'header_type'] =
'ADIF';
69 $ThisFileInfo[
'aac'][
'header'][
'mpeg_version'] = 4;
71 $ThisFileInfo[
'aac'][
'header'][
'copyright'] = (bool) (substr($AACheaderBitstream, $bitoffset, 1) ==
'1');
73 if ($ThisFileInfo[
'aac'][
'header'][
'copyright']) {
74 $ThisFileInfo[
'aac'][
'header'][
'copyright_id'] =
getid3_lib::Bin2String(substr($AACheaderBitstream, $bitoffset, 72));
77 $ThisFileInfo[
'aac'][
'header'][
'original_copy'] = (bool) (substr($AACheaderBitstream, $bitoffset, 1) ==
'1');
79 $ThisFileInfo[
'aac'][
'header'][
'home'] = (bool) (substr($AACheaderBitstream, $bitoffset, 1) ==
'1');
81 $ThisFileInfo[
'aac'][
'header'][
'is_vbr'] = (bool) (substr($AACheaderBitstream, $bitoffset, 1) ==
'1');
83 if ($ThisFileInfo[
'aac'][
'header'][
'is_vbr']) {
84 $ThisFileInfo[
'audio'][
'bitrate_mode'] =
'vbr';
85 $ThisFileInfo[
'aac'][
'header'][
'bitrate_max'] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 23));
88 $ThisFileInfo[
'audio'][
'bitrate_mode'] =
'cbr';
89 $ThisFileInfo[
'aac'][
'header'][
'bitrate'] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 23));
91 $ThisFileInfo[
'audio'][
'bitrate'] = $ThisFileInfo[
'aac'][
'header'][
'bitrate'];
93 if ($ThisFileInfo[
'audio'][
'bitrate'] == 0) {
94 $ThisFileInfo[
'error'][] =
'Corrupt AAC file: bitrate_audio == zero';
97 $ThisFileInfo[
'aac'][
'header'][
'num_program_configs'] = 1 +
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
100 for ($i = 0; $i < $ThisFileInfo[
'aac'][
'header'][
'num_program_configs']; $i++) {
149 if (!$ThisFileInfo[
'aac'][
'header'][
'is_vbr']) {
150 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'buffer_fullness'] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 20));
153 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'element_instance_tag'] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
155 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'object_type'] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2));
157 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'sampling_frequency_index'] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
159 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'num_front_channel_elements'] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
161 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'num_side_channel_elements'] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
163 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'num_back_channel_elements'] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
165 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'num_lfe_channel_elements'] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2));
167 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'num_assoc_data_elements'] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 3));
169 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'num_valid_cc_elements'] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
171 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'mono_mixdown_present'] = (bool)
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
173 if ($ThisFileInfo[
'aac'][
'program_configs'][$i][
'mono_mixdown_present']) {
174 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'mono_mixdown_element_number'] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
177 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'stereo_mixdown_present'] = (bool)
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
179 if ($ThisFileInfo[
'aac'][
'program_configs'][$i][
'stereo_mixdown_present']) {
180 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'stereo_mixdown_element_number'] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
183 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'matrix_mixdown_idx_present'] = (bool)
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
185 if ($ThisFileInfo[
'aac'][
'program_configs'][$i][
'matrix_mixdown_idx_present']) {
186 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'matrix_mixdown_idx'] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2));
188 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'pseudo_surround_enable'] = (bool)
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
191 for ($j = 0; $j < $ThisFileInfo[
'aac'][
'program_configs'][$i][
'num_front_channel_elements']; $j++) {
192 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'front_element_is_cpe'][$j] = (bool)
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
194 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'front_element_tag_select'][$j] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
197 for ($j = 0; $j < $ThisFileInfo[
'aac'][
'program_configs'][$i][
'num_side_channel_elements']; $j++) {
198 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'side_element_is_cpe'][$j] = (bool)
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
200 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'side_element_tag_select'][$j] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
203 for ($j = 0; $j < $ThisFileInfo[
'aac'][
'program_configs'][$i][
'num_back_channel_elements']; $j++) {
204 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'back_element_is_cpe'][$j] = (bool)
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
206 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'back_element_tag_select'][$j] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
209 for ($j = 0; $j < $ThisFileInfo[
'aac'][
'program_configs'][$i][
'num_lfe_channel_elements']; $j++) {
210 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'lfe_element_tag_select'][$j] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
213 for ($j = 0; $j < $ThisFileInfo[
'aac'][
'program_configs'][$i][
'num_assoc_data_elements']; $j++) {
214 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'assoc_data_element_tag_select'][$j] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
217 for ($j = 0; $j < $ThisFileInfo[
'aac'][
'program_configs'][$i][
'num_valid_cc_elements']; $j++) {
218 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'cc_element_is_ind_sw'][$j] = (bool)
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
220 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'valid_cc_element_tag_select'][$j] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
224 $bitoffset = ceil($bitoffset / 8) * 8;
226 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'comment_field_bytes'] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 8));
228 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'comment_field'] =
getid3_lib::Bin2String(substr($AACheaderBitstream, $bitoffset, 8 * $ThisFileInfo[
'aac'][
'program_configs'][$i][
'comment_field_bytes']));
229 $bitoffset += 8 * $ThisFileInfo[
'aac'][
'program_configs'][$i][
'comment_field_bytes'];
232 $ThisFileInfo[
'aac'][
'header'][
'profile_text'] = $this->
AACprofileLookup($ThisFileInfo[
'aac'][
'program_configs'][$i][
'object_type'], $ThisFileInfo[
'aac'][
'header'][
'mpeg_version']);
233 $ThisFileInfo[
'aac'][
'program_configs'][$i][
'sampling_frequency'] = $this->
AACsampleRateLookup($ThisFileInfo[
'aac'][
'program_configs'][$i][
'sampling_frequency_index']);
234 $ThisFileInfo[
'audio'][
'sample_rate'] = $ThisFileInfo[
'aac'][
'program_configs'][$i][
'sampling_frequency'];
236 if ($ThisFileInfo[
'aac'][
'program_configs'][$i][
'comment_field']) {
237 $ThisFileInfo[
'aac'][
'comments'][] = $ThisFileInfo[
'aac'][
'program_configs'][$i][
'comment_field'];
240 $ThisFileInfo[
'playtime_seconds'] = (($ThisFileInfo[
'avdataend'] - $ThisFileInfo[
'avdataoffset']) * 8) / $ThisFileInfo[
'audio'][
'bitrate'];
242 $ThisFileInfo[
'audio'][
'encoder_options'] = $ThisFileInfo[
'aac'][
'header_type'].
' '.$ThisFileInfo[
'aac'][
'header'][
'profile_text'];
250 unset($ThisFileInfo[
'fileformat']);
251 unset($ThisFileInfo[
'aac']);
252 $ThisFileInfo[
'error'][] =
'AAC-ADIF synch not found at offset '.$ThisFileInfo[
'avdataoffset'].
' (expected "ADIF", found "'.substr($AACheader, 0, 4).
'" instead)';
294 static $decbin = array();
297 for ($i = 0; $i < 256; $i++) {
298 $decbin[chr($i)] = str_pad(decbin($i), 8,
'0', STR_PAD_LEFT);
302 $BitrateCache = array();
309 fseek($fd, $byteoffset, SEEK_SET);
312 $substring = fread($fd, 10);
313 $substringlength = strlen($substring);
314 if ($substringlength != 10) {
315 $ThisFileInfo[
'error'][] =
'Failed to read 10 bytes at offset '.(ftell($fd) - $substringlength).
' (only read '.$substringlength.
' bytes)';
320 $AACheaderBitstream =
'';
323 for ($i = 0; $i < 10; $i++) {
324 $AACheaderBitstream .= $decbin[$substring{$i}];
329 $synctest = bindec(substr($AACheaderBitstream, $bitoffset, 12));
332 if ($synctest != 0x0FFF) {
333 $ThisFileInfo[
'error'][] =
'Synch pattern (0x0FFF) not found at offset '.(ftell($fd) - 10).
' (found 0x0'.strtoupper(dechex($synctest)).
' instead)';
334 if ($ThisFileInfo[
'fileformat'] ==
'aac') {
341 if ($framenumber > 0) {
343 if (!$AACheaderBitstream[$bitoffset]) {
357 $ThisFileInfo[
'aac'][
'header_type'] =
'ADTS';
358 $ThisFileInfo[
'aac'][
'header'][
'synch'] = $synctest;
359 $ThisFileInfo[
'fileformat'] =
'aac';
360 $ThisFileInfo[
'audio'][
'dataformat'] =
'aac';
362 $ThisFileInfo[
'aac'][
'header'][
'mpeg_version'] = ((substr($AACheaderBitstream, $bitoffset, 1) ==
'0') ? 4 : 2);
364 $ThisFileInfo[
'aac'][
'header'][
'layer'] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2));
366 if ($ThisFileInfo[
'aac'][
'header'][
'layer'] != 0) {
367 $ThisFileInfo[
'error'][] =
'Layer error - expected 0x00, found 0x'.dechex($ThisFileInfo[
'aac'][
'header'][
'layer']).
' instead';
370 $ThisFileInfo[
'aac'][
'header'][
'crc_present'] = ((substr($AACheaderBitstream, $bitoffset, 1) ==
'0') ?
true :
false);
372 $ThisFileInfo[
'aac'][
'header'][
'profile_id'] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2));
374 $ThisFileInfo[
'aac'][
'header'][
'profile_text'] = $this->
AACprofileLookup($ThisFileInfo[
'aac'][
'header'][
'profile_id'], $ThisFileInfo[
'aac'][
'header'][
'mpeg_version']);
376 $ThisFileInfo[
'aac'][
'header'][
'sample_frequency_index'] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
378 $ThisFileInfo[
'aac'][
'header'][
'sample_frequency'] = $this->
AACsampleRateLookup($ThisFileInfo[
'aac'][
'header'][
'sample_frequency_index']);
379 if ($ThisFileInfo[
'aac'][
'header'][
'sample_frequency'] == 0) {
380 $ThisFileInfo[
'error'][] =
'Corrupt AAC file: sample_frequency == zero';
383 $ThisFileInfo[
'audio'][
'sample_rate'] = $ThisFileInfo[
'aac'][
'header'][
'sample_frequency'];
385 $ThisFileInfo[
'aac'][
'header'][
'private'] = (bool)
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
387 $ThisFileInfo[
'aac'][
'header'][
'channel_configuration'] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 3));
389 $ThisFileInfo[
'audio'][
'channels'] = $ThisFileInfo[
'aac'][
'header'][
'channel_configuration'];
390 $ThisFileInfo[
'aac'][
'header'][
'original'] = (bool)
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
392 $ThisFileInfo[
'aac'][
'header'][
'home'] = (bool)
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
395 if ($ThisFileInfo[
'aac'][
'header'][
'mpeg_version'] == 4) {
396 $ThisFileInfo[
'aac'][
'header'][
'emphasis'] =
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2));
400 if ($ReturnExtendedInfo) {
402 $ThisFileInfo[
'aac'][$framenumber][
'copyright_id_bit'] = (bool)
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
404 $ThisFileInfo[
'aac'][$framenumber][
'copyright_id_start'] = (bool)
getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
415 $FrameLength = bindec(substr($AACheaderBitstream, $bitoffset, 13));
417 if (!isset($BitrateCache[$FrameLength])) {
418 $BitrateCache[$FrameLength] = ($ThisFileInfo[
'aac'][
'header'][
'sample_frequency'] / 1024) * $FrameLength * 8;
420 @$ThisFileInfo[
'aac'][
'bitrate_distribution'][$BitrateCache[$FrameLength]]++;
422 $ThisFileInfo[
'aac'][$framenumber][
'aac_frame_length'] = $FrameLength;
424 $ThisFileInfo[
'aac'][$framenumber][
'adts_buffer_fullness'] = bindec(substr($AACheaderBitstream, $bitoffset, 11));
426 if ($ThisFileInfo[
'aac'][$framenumber][
'adts_buffer_fullness'] == 0x07FF) {
427 $ThisFileInfo[
'audio'][
'bitrate_mode'] =
'vbr';
429 $ThisFileInfo[
'audio'][
'bitrate_mode'] =
'cbr';
431 $ThisFileInfo[
'aac'][$framenumber][
'num_raw_data_blocks'] = bindec(substr($AACheaderBitstream, $bitoffset, 2));
434 if ($ThisFileInfo[
'aac'][
'header'][
'crc_present']) {
439 if (!$ReturnExtendedInfo) {
440 unset($ThisFileInfo[
'aac'][$framenumber]);
443 $byteoffset += $FrameLength;
444 if ((++$framenumber < $MaxFramesToScan) && (($byteoffset + 10) < $ThisFileInfo[
'avdataend'])) {
450 $ThisFileInfo[
'aac'][
'frames'] = $framenumber;
451 $ThisFileInfo[
'playtime_seconds'] = ($ThisFileInfo[
'avdataend'] / $byteoffset) * (($framenumber * 1024) / $ThisFileInfo[
'aac'][
'header'][
'sample_frequency']);
452 if ($ThisFileInfo[
'playtime_seconds'] == 0) {
453 $ThisFileInfo[
'error'][] =
'Corrupt AAC file: playtime_seconds == zero';
456 $ThisFileInfo[
'audio'][
'bitrate'] = (($ThisFileInfo[
'avdataend'] - $ThisFileInfo[
'avdataoffset']) * 8) / $ThisFileInfo[
'playtime_seconds'];
457 ksort($ThisFileInfo[
'aac'][
'bitrate_distribution']);
459 $ThisFileInfo[
'audio'][
'encoder_options'] = $ThisFileInfo[
'aac'][
'header_type'].
' '.$ThisFileInfo[
'aac'][
'header'][
'profile_text'];
469 static $AACsampleRateLookup = array();
470 if (empty($AACsampleRateLookup)) {
471 $AACsampleRateLookup[0] = 96000;
472 $AACsampleRateLookup[1] = 88200;
473 $AACsampleRateLookup[2] = 64000;
474 $AACsampleRateLookup[3] = 48000;
475 $AACsampleRateLookup[4] = 44100;
476 $AACsampleRateLookup[5] = 32000;
477 $AACsampleRateLookup[6] = 24000;
478 $AACsampleRateLookup[7] = 22050;
479 $AACsampleRateLookup[8] = 16000;
480 $AACsampleRateLookup[9] = 12000;
481 $AACsampleRateLookup[10] = 11025;
482 $AACsampleRateLookup[11] = 8000;
483 $AACsampleRateLookup[12] = 0;
484 $AACsampleRateLookup[13] = 0;
485 $AACsampleRateLookup[14] = 0;
486 $AACsampleRateLookup[15] = 0;
488 return (isset($AACsampleRateLookup[$samplerateid]) ? $AACsampleRateLookup[$samplerateid] :
'invalid');
492 static $AACprofileLookup = array();
493 if (empty($AACprofileLookup)) {
494 $AACprofileLookup[2][0] =
'Main profile';
495 $AACprofileLookup[2][1] =
'Low Complexity profile (LC)';
496 $AACprofileLookup[2][2] =
'Scalable Sample Rate profile (SSR)';
497 $AACprofileLookup[2][3] =
'(reserved)';
498 $AACprofileLookup[4][0] =
'AAC_MAIN';
499 $AACprofileLookup[4][1] =
'AAC_LC';
500 $AACprofileLookup[4][2] =
'AAC_SSR';
501 $AACprofileLookup[4][3] =
'AAC_LTP';
503 return (isset($AACprofileLookup[$mpegversion][$profileid]) ? $AACprofileLookup[$mpegversion][$profileid] :
'invalid');
508 for ($i = 0; $i < $program_configs[
'num_front_channel_elements']; $i++) {
510 if ($program_configs[
'front_element_is_cpe'][$i]) {
515 for ($i = 0; $i < $program_configs[
'num_side_channel_elements']; $i++) {
517 if ($program_configs[
'side_element_is_cpe'][$i]) {
522 for ($i = 0; $i < $program_configs[
'num_back_channel_elements']; $i++) {
524 if ($program_configs[
'back_element_is_cpe'][$i]) {
529 for ($i = 0; $i < $program_configs[
'num_lfe_channel_elements']; $i++) {