37 $info = &$this->getid3->info;
38 fseek($this->getid3->fp,
$info[
'avdataoffset'], SEEK_SET);
39 if (
fread($this->getid3->fp, 4) ==
'ADIF') {
54 $info = &$this->getid3->info;
55 $info[
'fileformat'] =
'aac';
56 $info[
'audio'][
'dataformat'] =
'aac';
57 $info[
'audio'][
'lossless'] =
false;
59 fseek($this->getid3->fp,
$info[
'avdataoffset'], SEEK_SET);
60 $AACheader =
fread($this->getid3->fp, 1024);
63 if (substr($AACheader, 0, 4) ==
'ADIF') {
88 $info[
'aac'][
'header_type'] =
'ADIF';
90 $info[
'aac'][
'header'][
'mpeg_version'] = 4;
92 $info[
'aac'][
'header'][
'copyright'] = (bool) (substr($AACheaderBitstream, $bitoffset, 1) ==
'1');
94 if (
$info[
'aac'][
'header'][
'copyright']) {
98 $info[
'aac'][
'header'][
'original_copy'] = (bool) (substr($AACheaderBitstream, $bitoffset, 1) ==
'1');
100 $info[
'aac'][
'header'][
'home'] = (bool) (substr($AACheaderBitstream, $bitoffset, 1) ==
'1');
102 $info[
'aac'][
'header'][
'is_vbr'] = (bool) (substr($AACheaderBitstream, $bitoffset, 1) ==
'1');
104 if (
$info[
'aac'][
'header'][
'is_vbr']) {
105 $info[
'audio'][
'bitrate_mode'] =
'vbr';
106 $info[
'aac'][
'header'][
'bitrate_max'] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 23));
109 $info[
'audio'][
'bitrate_mode'] =
'cbr';
110 $info[
'aac'][
'header'][
'bitrate'] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 23));
112 $info[
'audio'][
'bitrate'] =
$info[
'aac'][
'header'][
'bitrate'];
114 if (
$info[
'audio'][
'bitrate'] == 0) {
115 $info[
'error'][] =
'Corrupt AAC file: bitrate_audio == zero';
119 $info[
'aac'][
'header'][
'num_program_configs'] = 1 +
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
122 for ($i = 0; $i <
$info[
'aac'][
'header'][
'num_program_configs']; $i++) {
171 if (!$info[
'aac'][
'header'][
'is_vbr']) {
172 $info[
'aac'][
'program_configs'][$i][
'buffer_fullness'] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 20));
175 $info[
'aac'][
'program_configs'][$i][
'element_instance_tag'] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
177 $info[
'aac'][
'program_configs'][$i][
'object_type'] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2));
179 $info[
'aac'][
'program_configs'][$i][
'sampling_frequency_index'] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
181 $info[
'aac'][
'program_configs'][$i][
'num_front_channel_elements'] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
183 $info[
'aac'][
'program_configs'][$i][
'num_side_channel_elements'] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
185 $info[
'aac'][
'program_configs'][$i][
'num_back_channel_elements'] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
187 $info[
'aac'][
'program_configs'][$i][
'num_lfe_channel_elements'] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2));
189 $info[
'aac'][
'program_configs'][$i][
'num_assoc_data_elements'] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 3));
191 $info[
'aac'][
'program_configs'][$i][
'num_valid_cc_elements'] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
193 $info[
'aac'][
'program_configs'][$i][
'mono_mixdown_present'] = (bool)
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
195 if ($info[
'aac'][
'program_configs'][$i][
'mono_mixdown_present']) {
196 $info[
'aac'][
'program_configs'][$i][
'mono_mixdown_element_number'] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
199 $info[
'aac'][
'program_configs'][$i][
'stereo_mixdown_present'] = (bool)
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
201 if ($info[
'aac'][
'program_configs'][$i][
'stereo_mixdown_present']) {
202 $info[
'aac'][
'program_configs'][$i][
'stereo_mixdown_element_number'] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
205 $info[
'aac'][
'program_configs'][$i][
'matrix_mixdown_idx_present'] = (bool)
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
207 if ($info[
'aac'][
'program_configs'][$i][
'matrix_mixdown_idx_present']) {
208 $info[
'aac'][
'program_configs'][$i][
'matrix_mixdown_idx'] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2));
210 $info[
'aac'][
'program_configs'][$i][
'pseudo_surround_enable'] = (bool)
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
213 for ($j = 0; $j < $info[
'aac'][
'program_configs'][$i][
'num_front_channel_elements']; $j++) {
214 $info[
'aac'][
'program_configs'][$i][
'front_element_is_cpe'][$j] = (bool)
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
216 $info[
'aac'][
'program_configs'][$i][
'front_element_tag_select'][$j] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
219 for ($j = 0; $j < $info[
'aac'][
'program_configs'][$i][
'num_side_channel_elements']; $j++) {
220 $info[
'aac'][
'program_configs'][$i][
'side_element_is_cpe'][$j] = (bool)
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
222 $info[
'aac'][
'program_configs'][$i][
'side_element_tag_select'][$j] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
225 for ($j = 0; $j < $info[
'aac'][
'program_configs'][$i][
'num_back_channel_elements']; $j++) {
226 $info[
'aac'][
'program_configs'][$i][
'back_element_is_cpe'][$j] = (bool)
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
228 $info[
'aac'][
'program_configs'][$i][
'back_element_tag_select'][$j] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
231 for ($j = 0; $j < $info[
'aac'][
'program_configs'][$i][
'num_lfe_channel_elements']; $j++) {
232 $info[
'aac'][
'program_configs'][$i][
'lfe_element_tag_select'][$j] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
235 for ($j = 0; $j < $info[
'aac'][
'program_configs'][$i][
'num_assoc_data_elements']; $j++) {
236 $info[
'aac'][
'program_configs'][$i][
'assoc_data_element_tag_select'][$j] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
239 for ($j = 0; $j < $info[
'aac'][
'program_configs'][$i][
'num_valid_cc_elements']; $j++) {
240 $info[
'aac'][
'program_configs'][$i][
'cc_element_is_ind_sw'][$j] = (bool)
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
242 $info[
'aac'][
'program_configs'][$i][
'valid_cc_element_tag_select'][$j] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
246 $bitoffset = ceil($bitoffset / 8) * 8;
248 $info[
'aac'][
'program_configs'][$i][
'comment_field_bytes'] =
Helper::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 8));
250 $info[
'aac'][
'program_configs'][$i][
'comment_field'] =
Helper::Bin2String(substr($AACheaderBitstream, $bitoffset, 8 * $info[
'aac'][
'program_configs'][$i][
'comment_field_bytes']));
251 $bitoffset += 8 * $info[
'aac'][
'program_configs'][$i][
'comment_field_bytes'];
253 $info[
'aac'][
'header'][
'profile'] = self::AACprofileLookup($info[
'aac'][
'program_configs'][$i][
'object_type'], $info[
'aac'][
'header'][
'mpeg_version']);
254 $info[
'aac'][
'program_configs'][$i][
'sampling_frequency'] = self::AACsampleRateLookup($info[
'aac'][
'program_configs'][$i][
'sampling_frequency_index']);
255 $info[
'audio'][
'sample_rate'] = $info[
'aac'][
'program_configs'][$i][
'sampling_frequency'];
256 $info[
'audio'][
'channels'] = self::AACchannelCountCalculate($info[
'aac'][
'program_configs'][$i]);
257 if ($info[
'aac'][
'program_configs'][$i][
'comment_field']) {
258 $info[
'aac'][
'comments'][] = $info[
'aac'][
'program_configs'][$i][
'comment_field'];
261 $info[
'playtime_seconds'] = (($info[
'avdataend'] - $info[
'avdataoffset']) * 8) / $info[
'audio'][
'bitrate'];
263 $info[
'audio'][
'encoder_options'] = $info[
'aac'][
'header_type'].
' '.$info[
'aac'][
'header'][
'profile'];
269 unset(
$info[
'fileformat']);
271 $info[
'error'][] =
'AAC-ADIF synch not found at offset '.$info[
'avdataoffset'].
' (expected "ADIF", found "'.substr($AACheader, 0, 4).
'" instead)';
288 $info = &$this->getid3->info;
319 $byteoffset =
$info[
'avdataoffset'];
323 static $decbin =
array();
326 for ($i = 0; $i < 256; $i++) {
327 $decbin[chr($i)] = str_pad(decbin($i), 8,
'0', STR_PAD_LEFT);
331 $BitrateCache =
array();
339 $info[
'warning'][] =
'Unable to parse AAC file beyond '.ftell($this->getid3->fp).
' (PHP does not support file operations beyond '.round(PHP_INT_MAX / 1073741824).
'GB)';
343 fseek($this->getid3->fp, $byteoffset, SEEK_SET);
346 $substring =
fread($this->getid3->fp, 9);
347 $substringlength = strlen($substring);
348 if ($substringlength != 9) {
349 $info[
'error'][] =
'Failed to read 7 bytes at offset '.(ftell($this->getid3->fp) - $substringlength).
' (only read '.$substringlength.
' bytes)';
358 $info[
'aac'][
'header'][
'raw'][
'syncword'] = ($header1 & 0xFFF0) >> 4;
359 if (
$info[
'aac'][
'header'][
'raw'][
'syncword'] != 0x0FFF) {
360 $info[
'error'][] =
'Synch pattern (0x0FFF) not found at offset '.(ftell($this->getid3->fp) - $substringlength).
' (found 0x0'.strtoupper(dechex(
$info[
'aac'][
'header'][
'raw'][
'syncword'])).
' instead)';
370 if ($framenumber == 0) {
371 $info[
'aac'][
'header_type'] =
'ADTS';
372 $info[
'fileformat'] =
'aac';
373 $info[
'audio'][
'dataformat'] =
'aac';
375 $info[
'aac'][
'header'][
'raw'][
'mpeg_version'] = ($header1 & 0x0008) >> 3;
376 $info[
'aac'][
'header'][
'raw'][
'mpeg_layer'] = ($header1 & 0x0006) >> 1;
377 $info[
'aac'][
'header'][
'raw'][
'protection_absent'] = ($header1 & 0x0001) >> 0;
379 $info[
'aac'][
'header'][
'raw'][
'profile_code'] = ($header2 & 0xC0000000) >> 30;
380 $info[
'aac'][
'header'][
'raw'][
'sample_rate_code'] = ($header2 & 0x3C000000) >> 26;
381 $info[
'aac'][
'header'][
'raw'][
'private_stream'] = ($header2 & 0x02000000) >> 25;
382 $info[
'aac'][
'header'][
'raw'][
'channels_code'] = ($header2 & 0x01C00000) >> 22;
383 $info[
'aac'][
'header'][
'raw'][
'original'] = ($header2 & 0x00200000) >> 21;
384 $info[
'aac'][
'header'][
'raw'][
'home'] = ($header2 & 0x00100000) >> 20;
385 $info[
'aac'][
'header'][
'raw'][
'copyright_stream'] = ($header2 & 0x00080000) >> 19;
386 $info[
'aac'][
'header'][
'raw'][
'copyright_start'] = ($header2 & 0x00040000) >> 18;
387 $info[
'aac'][
'header'][
'raw'][
'frame_length'] = ($header2 & 0x0003FFE0) >> 5;
389 $info[
'aac'][
'header'][
'mpeg_version'] = (
$info[
'aac'][
'header'][
'raw'][
'mpeg_version'] ? 2 : 4);
390 $info[
'aac'][
'header'][
'crc_present'] = (
$info[
'aac'][
'header'][
'raw'][
'protection_absent'] ?
false:
true);
391 $info[
'aac'][
'header'][
'profile'] = self::AACprofileLookup(
$info[
'aac'][
'header'][
'raw'][
'profile_code'],
$info[
'aac'][
'header'][
'mpeg_version']);
392 $info[
'aac'][
'header'][
'sample_frequency'] = self::AACsampleRateLookup(
$info[
'aac'][
'header'][
'raw'][
'sample_rate_code']);
393 $info[
'aac'][
'header'][
'private'] = (bool)
$info[
'aac'][
'header'][
'raw'][
'private_stream'];
394 $info[
'aac'][
'header'][
'original'] = (bool)
$info[
'aac'][
'header'][
'raw'][
'original'];
395 $info[
'aac'][
'header'][
'home'] = (bool)
$info[
'aac'][
'header'][
'raw'][
'home'];
396 $info[
'aac'][
'header'][
'channels'] = ((
$info[
'aac'][
'header'][
'raw'][
'channels_code'] == 7) ? 8 :
$info[
'aac'][
'header'][
'raw'][
'channels_code']);
397 if ($ReturnExtendedInfo) {
398 $info[
'aac'][$framenumber][
'copyright_id_bit'] = (bool)
$info[
'aac'][
'header'][
'raw'][
'copyright_stream'];
399 $info[
'aac'][$framenumber][
'copyright_id_start'] = (bool)
$info[
'aac'][
'header'][
'raw'][
'copyright_start'];
402 if (
$info[
'aac'][
'header'][
'raw'][
'mpeg_layer'] != 0) {
403 $info[
'warning'][] =
'Layer error - expected "0", found "'.$info[
'aac'][
'header'][
'raw'][
'mpeg_layer'].
'" instead';
405 if (
$info[
'aac'][
'header'][
'sample_frequency'] == 0) {
406 $info[
'error'][] =
'Corrupt AAC file: sample_frequency == zero';
411 $info[
'audio'][
'sample_rate'] =
$info[
'aac'][
'header'][
'sample_frequency'];
412 $info[
'audio'][
'channels'] =
$info[
'aac'][
'header'][
'channels'];
415 $FrameLength = ($header2 & 0x0003FFE0) >> 5;
417 if (!isset($BitrateCache[$FrameLength])) {
418 $BitrateCache[$FrameLength] = (
$info[
'aac'][
'header'][
'sample_frequency'] / 1024) * $FrameLength * 8;
422 $info[
'aac'][$framenumber][
'aac_frame_length'] = $FrameLength;
424 $info[
'aac'][$framenumber][
'adts_buffer_fullness'] = (($header2 & 0x0000001F) << 6) & (($header3 & 0xFC) >> 2);
425 if (
$info[
'aac'][$framenumber][
'adts_buffer_fullness'] == 0x07FF) {
426 $info[
'audio'][
'bitrate_mode'] =
'vbr';
428 $info[
'audio'][
'bitrate_mode'] =
'cbr';
430 $info[
'aac'][$framenumber][
'num_raw_data_blocks'] = (($header3 & 0x03) >> 0);
432 if (
$info[
'aac'][
'header'][
'crc_present']) {
436 if (!$ReturnExtendedInfo) {
437 unset(
$info[
'aac'][$framenumber]);
450 $byteoffset += $FrameLength;
451 if ((++$framenumber < $MaxFramesToScan) && (($byteoffset + 10) <
$info[
'avdataend'])) {
457 $info[
'aac'][
'frames'] = $framenumber;
458 $info[
'playtime_seconds'] = (
$info[
'avdataend'] / $byteoffset) * (($framenumber * 1024) /
$info[
'aac'][
'header'][
'sample_frequency']);
459 if (
$info[
'playtime_seconds'] == 0) {
460 $info[
'error'][] =
'Corrupt AAC file: playtime_seconds == zero';
464 $info[
'audio'][
'bitrate'] = ((
$info[
'avdataend'] -
$info[
'avdataoffset']) * 8) /
$info[
'playtime_seconds'];
465 ksort(
$info[
'aac'][
'bitrate_distribution']);
467 $info[
'audio'][
'encoder_options'] =
$info[
'aac'][
'header_type'].
' '.
$info[
'aac'][
'header'][
'profile'];
484 static $AACsampleRateLookup =
array();
485 if (empty($AACsampleRateLookup)) {
486 $AACsampleRateLookup[0] = 96000;
487 $AACsampleRateLookup[1] = 88200;
488 $AACsampleRateLookup[2] = 64000;
489 $AACsampleRateLookup[3] = 48000;
490 $AACsampleRateLookup[4] = 44100;
491 $AACsampleRateLookup[5] = 32000;
492 $AACsampleRateLookup[6] = 24000;
493 $AACsampleRateLookup[7] = 22050;
494 $AACsampleRateLookup[8] = 16000;
495 $AACsampleRateLookup[9] = 12000;
496 $AACsampleRateLookup[10] = 11025;
497 $AACsampleRateLookup[11] = 8000;
498 $AACsampleRateLookup[12] = 0;
499 $AACsampleRateLookup[13] = 0;
500 $AACsampleRateLookup[14] = 0;
501 $AACsampleRateLookup[15] = 0;
504 return (isset($AACsampleRateLookup[$samplerateid]) ? $AACsampleRateLookup[$samplerateid] :
'invalid');
516 static $AACprofileLookup =
array();
517 if (empty($AACprofileLookup)) {
518 $AACprofileLookup[2][0] =
'Main profile';
519 $AACprofileLookup[2][1] =
'Low Complexity profile (LC)';
520 $AACprofileLookup[2][2] =
'Scalable Sample Rate profile (SSR)';
521 $AACprofileLookup[2][3] =
'(reserved)';
522 $AACprofileLookup[4][0] =
'AAC_MAIN';
523 $AACprofileLookup[4][1] =
'AAC_LC';
524 $AACprofileLookup[4][2] =
'AAC_SSR';
525 $AACprofileLookup[4][3] =
'AAC_LTP';
528 return (isset($AACprofileLookup[$mpegversion][$profileid]) ? $AACprofileLookup[$mpegversion][$profileid] :
'invalid');
539 for ($i = 0; $i < $program_configs[
'num_front_channel_elements']; $i++) {
541 if ($program_configs[
'front_element_is_cpe'][$i]) {
546 for ($i = 0; $i < $program_configs[
'num_side_channel_elements']; $i++) {
548 if ($program_configs[
'side_element_is_cpe'][$i]) {
553 for ($i = 0; $i < $program_configs[
'num_back_channel_elements']; $i++) {
555 if ($program_configs[
'back_element_is_cpe'][$i]) {
560 for ($i = 0; $i < $program_configs[
'num_lfe_channel_elements']; $i++) {
static BigEndian2Bin($byteword)
getAACADIFheaderFilepointer()
getAACADTSheaderFilepointer($MaxFramesToScan=1000000, $ReturnExtendedInfo=false)
array $decbin
GetId3() by James Heinrich info@getid3.org //.
GetId3() by James Heinrich info@getid3.org //.
static AACchannelCountCalculate($program_configs)
fseek($bytes, $whence=SEEK_SET)
static AACprofileLookup($profileid, $mpegversion)
array $AACprofileLookup
static AACsampleRateLookup($samplerateid)
array $AACsampleRateLookup
Create styles array
The data for the language used.
static BigEndian2Int($byteword, $synchsafe=false, $signed=false)
static intValueSupported($num)
null $hasINT64
static safe_inc(&$variable, $increment=1)
static Bin2String($binstring)
static Bin2Dec($binstring, $signed=false)