source: extensions/charlies_content/getid3/getid3/module.audio.aac.php @ 9130

Last change on this file since 9130 was 3544, checked in by vdigital, 15 years ago

Change: getid3 upgraded to -> 1.7.9

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Author Date Id Revision
File size: 24.6 KB
Line 
1<?php
2/////////////////////////////////////////////////////////////////
3/// getID3() by James Heinrich <info@getid3.org>               //
4//  available at http://getid3.sourceforge.net                 //
5//            or http://www.getid3.org                         //
6/////////////////////////////////////////////////////////////////
7// See readme.txt for more details                             //
8/////////////////////////////////////////////////////////////////
9//                                                             //
10// module.audio.aac.php                                        //
11// module for analyzing AAC Audio files                        //
12// dependencies: NONE                                          //
13//                                                            ///
14/////////////////////////////////////////////////////////////////
15
16
17class getid3_aac
18{
19
20        // new combined constructor
21        function getid3_aac(&$fd, &$ThisFileInfo, $option) {
22
23                if ($option === 'adif') {
24                        $this->getAACADIFheaderFilepointer($fd, $ThisFileInfo);
25                }
26                elseif ($option === 'adts') {
27                        $this->getAACADTSheaderFilepointer($fd, $ThisFileInfo);
28                }
29        }
30
31
32
33        function getAACADIFheaderFilepointer(&$fd, &$ThisFileInfo) {
34                $ThisFileInfo['fileformat']          = 'aac';
35                $ThisFileInfo['audio']['dataformat'] = 'aac';
36                $ThisFileInfo['audio']['lossless']   = false;
37
38                fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
39                $AACheader = fread($fd, 1024);
40                $offset    = 0;
41
42                if (substr($AACheader, 0, 4) == 'ADIF') {
43
44                        // http://faac.sourceforge.net/wiki/index.php?page=ADIF
45
46                        // http://libmpeg.org/mpeg4/doc/w2203tfs.pdf
47                        // adif_header() {
48                        //     adif_id                                32
49                        //     copyright_id_present                    1
50                        //     if( copyright_id_present )
51                        //         copyright_id                       72
52                        //     original_copy                           1
53                        //     home                                    1
54                        //     bitstream_type                          1
55                        //     bitrate                                23
56                        //     num_program_config_elements             4
57                        //     for (i = 0; i < num_program_config_elements + 1; i++ ) {
58                        //         if( bitstream_type == '0' )
59                        //             adif_buffer_fullness           20
60                        //         program_config_element()
61                        //     }
62                        // }
63
64                        $AACheaderBitstream = getid3_lib::BigEndian2Bin($AACheader);
65                        $bitoffset          = 0;
66
67                        $ThisFileInfo['aac']['header_type']                   = 'ADIF';
68                        $bitoffset += 32;
69                        $ThisFileInfo['aac']['header']['mpeg_version']        = 4;
70
71                        $ThisFileInfo['aac']['header']['copyright']           = (bool) (substr($AACheaderBitstream, $bitoffset, 1) == '1');
72                        $bitoffset += 1;
73                        if ($ThisFileInfo['aac']['header']['copyright']) {
74                                $ThisFileInfo['aac']['header']['copyright_id']    = getid3_lib::Bin2String(substr($AACheaderBitstream, $bitoffset, 72));
75                                $bitoffset += 72;
76                        }
77                        $ThisFileInfo['aac']['header']['original_copy']       = (bool) (substr($AACheaderBitstream, $bitoffset, 1) == '1');
78                        $bitoffset += 1;
79                        $ThisFileInfo['aac']['header']['home']                = (bool) (substr($AACheaderBitstream, $bitoffset, 1) == '1');
80                        $bitoffset += 1;
81                        $ThisFileInfo['aac']['header']['is_vbr']              = (bool) (substr($AACheaderBitstream, $bitoffset, 1) == '1');
82                        $bitoffset += 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));
86                                $bitoffset += 23;
87                        } else {
88                                $ThisFileInfo['audio']['bitrate_mode']            = 'cbr';
89                                $ThisFileInfo['aac']['header']['bitrate']         = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 23));
90                                $bitoffset += 23;
91                                $ThisFileInfo['audio']['bitrate']                 = $ThisFileInfo['aac']['header']['bitrate'];
92                        }
93                        if ($ThisFileInfo['audio']['bitrate'] == 0) {
94                                $ThisFileInfo['error'][] = 'Corrupt AAC file: bitrate_audio == zero';
95                                return false;
96                        }
97                        $ThisFileInfo['aac']['header']['num_program_configs'] = 1 + getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
98                        $bitoffset += 4;
99
100                        for ($i = 0; $i < $ThisFileInfo['aac']['header']['num_program_configs']; $i++) {
101                                // http://www.audiocoding.com/wiki/index.php?page=program_config_element
102
103                                // buffer_fullness                       20
104
105                                // element_instance_tag                   4
106                                // object_type                            2
107                                // sampling_frequency_index               4
108                                // num_front_channel_elements             4
109                                // num_side_channel_elements              4
110                                // num_back_channel_elements              4
111                                // num_lfe_channel_elements               2
112                                // num_assoc_data_elements                3
113                                // num_valid_cc_elements                  4
114                                // mono_mixdown_present                   1
115                                // mono_mixdown_element_number            4   if mono_mixdown_present == 1
116                                // stereo_mixdown_present                 1
117                                // stereo_mixdown_element_number          4   if stereo_mixdown_present == 1
118                                // matrix_mixdown_idx_present             1
119                                // matrix_mixdown_idx                     2   if matrix_mixdown_idx_present == 1
120                                // pseudo_surround_enable                 1   if matrix_mixdown_idx_present == 1
121                                // for (i = 0; i < num_front_channel_elements; i++) {
122                                //     front_element_is_cpe[i]            1
123                                //     front_element_tag_select[i]        4
124                                // }
125                                // for (i = 0; i < num_side_channel_elements; i++) {
126                                //     side_element_is_cpe[i]             1
127                                //     side_element_tag_select[i]         4
128                                // }
129                                // for (i = 0; i < num_back_channel_elements; i++) {
130                                //     back_element_is_cpe[i]             1
131                                //     back_element_tag_select[i]         4
132                                // }
133                                // for (i = 0; i < num_lfe_channel_elements; i++) {
134                                //     lfe_element_tag_select[i]          4
135                                // }
136                                // for (i = 0; i < num_assoc_data_elements; i++) {
137                                //     assoc_data_element_tag_select[i]   4
138                                // }
139                                // for (i = 0; i < num_valid_cc_elements; i++) {
140                                //     cc_element_is_ind_sw[i]            1
141                                //     valid_cc_element_tag_select[i]     4
142                                // }
143                                // byte_alignment()                       VAR
144                                // comment_field_bytes                    8
145                                // for (i = 0; i < comment_field_bytes; i++) {
146                                //     comment_field_data[i]              8
147                                // }
148
149                                if (!$ThisFileInfo['aac']['header']['is_vbr']) {
150                                        $ThisFileInfo['aac']['program_configs'][$i]['buffer_fullness']        = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 20));
151                                        $bitoffset += 20;
152                                }
153                                $ThisFileInfo['aac']['program_configs'][$i]['element_instance_tag']       = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
154                                $bitoffset += 4;
155                                $ThisFileInfo['aac']['program_configs'][$i]['object_type']                = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2));
156                                $bitoffset += 2;
157                                $ThisFileInfo['aac']['program_configs'][$i]['sampling_frequency_index']   = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
158                                $bitoffset += 4;
159                                $ThisFileInfo['aac']['program_configs'][$i]['num_front_channel_elements'] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
160                                $bitoffset += 4;
161                                $ThisFileInfo['aac']['program_configs'][$i]['num_side_channel_elements']  = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
162                                $bitoffset += 4;
163                                $ThisFileInfo['aac']['program_configs'][$i]['num_back_channel_elements']  = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
164                                $bitoffset += 4;
165                                $ThisFileInfo['aac']['program_configs'][$i]['num_lfe_channel_elements']   = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2));
166                                $bitoffset += 2;
167                                $ThisFileInfo['aac']['program_configs'][$i]['num_assoc_data_elements']    = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 3));
168                                $bitoffset += 3;
169                                $ThisFileInfo['aac']['program_configs'][$i]['num_valid_cc_elements']      = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
170                                $bitoffset += 4;
171                                $ThisFileInfo['aac']['program_configs'][$i]['mono_mixdown_present']       = (bool) getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
172                                $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));
175                                        $bitoffset += 4;
176                                }
177                                $ThisFileInfo['aac']['program_configs'][$i]['stereo_mixdown_present']             = (bool) getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
178                                $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));
181                                        $bitoffset += 4;
182                                }
183                                $ThisFileInfo['aac']['program_configs'][$i]['matrix_mixdown_idx_present']         = (bool) getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
184                                $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));
187                                        $bitoffset += 2;
188                                        $ThisFileInfo['aac']['program_configs'][$i]['pseudo_surround_enable']         = (bool) getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
189                                        $bitoffset += 1;
190                                }
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));
193                                        $bitoffset += 1;
194                                        $ThisFileInfo['aac']['program_configs'][$i]['front_element_tag_select'][$j] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
195                                        $bitoffset += 4;
196                                }
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));
199                                        $bitoffset += 1;
200                                        $ThisFileInfo['aac']['program_configs'][$i]['side_element_tag_select'][$j] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
201                                        $bitoffset += 4;
202                                }
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));
205                                        $bitoffset += 1;
206                                        $ThisFileInfo['aac']['program_configs'][$i]['back_element_tag_select'][$j] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
207                                        $bitoffset += 4;
208                                }
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));
211                                        $bitoffset += 4;
212                                }
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));
215                                        $bitoffset += 4;
216                                }
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));
219                                        $bitoffset += 1;
220                                        $ThisFileInfo['aac']['program_configs'][$i]['valid_cc_element_tag_select'][$j]   = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
221                                        $bitoffset += 4;
222                                }
223
224                                $bitoffset = ceil($bitoffset / 8) * 8;
225
226                                $ThisFileInfo['aac']['program_configs'][$i]['comment_field_bytes'] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 8));
227                                $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'];
230
231
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'];
235                                $ThisFileInfo['audio']['channels']                                  = $this->AACchannelCountCalculate($ThisFileInfo['aac']['program_configs'][$i]);
236                                if ($ThisFileInfo['aac']['program_configs'][$i]['comment_field']) {
237                                        $ThisFileInfo['aac']['comments'][]                          = $ThisFileInfo['aac']['program_configs'][$i]['comment_field'];
238                                }
239                        }
240                        $ThisFileInfo['playtime_seconds'] = (($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / $ThisFileInfo['audio']['bitrate'];
241
242                        $ThisFileInfo['audio']['encoder_options'] = $ThisFileInfo['aac']['header_type'].' '.$ThisFileInfo['aac']['header']['profile_text'];
243
244
245
246                        return true;
247
248                } else {
249
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)';
253                        return false;
254
255                }
256
257        }
258
259
260        function getAACADTSheaderFilepointer(&$fd, &$ThisFileInfo, $MaxFramesToScan=1000000, $ReturnExtendedInfo=false) {
261                // based loosely on code from AACfile by Jurgen Faul  <jfaulØgmx.de>
262                // http://jfaul.de/atl  or  http://j-faul.virtualave.net/atl/atl.html
263
264
265                // http://faac.sourceforge.net/wiki/index.php?page=ADTS
266
267                // * ADTS Fixed Header: these don't change from frame to frame
268                // syncword                                       12    always: '111111111111'
269                // ID                                              1    0: MPEG-4, 1: MPEG-2
270                // layer                                           2    always: '00'
271                // protection_absent                               1
272                // profile                                         2
273                // sampling_frequency_index                        4
274                // private_bit                                     1
275                // channel_configuration                           3
276                // original/copy                                   1
277                // home                                            1
278                // emphasis                                        2    only if ID == 0 (ie MPEG-4)
279
280                // * ADTS Variable Header: these can change from frame to frame
281                // copyright_identification_bit                    1
282                // copyright_identification_start                  1
283                // aac_frame_length                               13    length of the frame including header (in bytes)
284                // adts_buffer_fullness                           11    0x7FF indicates VBR
285                // no_raw_data_blocks_in_frame                     2
286
287                // * ADTS Error check
288                // crc_check                                      16    only if protection_absent == 0
289
290                $byteoffset  = 0;
291                $framenumber = 0;
292
293                // Init bit pattern array
294                static $decbin = array();
295
296                // Populate $bindec
297                for ($i = 0; $i < 256; $i++) {
298                        $decbin[chr($i)] = str_pad(decbin($i), 8, '0', STR_PAD_LEFT);
299                }
300
301                // used to calculate bitrate below
302                $BitrateCache = array();
303
304
305                while (true) {
306                        // breaks out when end-of-file encountered, or invalid data found,
307                        // or MaxFramesToScan frames have been scanned
308
309                        if ($byteoffset >= pow(2, 31)) {
310                                $ThisFileInfo['warning'][] = 'Unable to parse AAC file beyond '.ftell($fd).' (PHP does not support file operations beyond 2GB)';
311                                return false;
312                        }
313                        fseek($fd, $byteoffset, SEEK_SET);
314
315                        // First get substring
316                        $substring = fread($fd, 10);
317                        $substringlength = strlen($substring);
318                        if ($substringlength != 10) {
319                                $ThisFileInfo['error'][] = 'Failed to read 10 bytes at offset '.(ftell($fd) - $substringlength).' (only read '.$substringlength.' bytes)';
320                                return false;
321                        }
322
323                        // Initialise $AACheaderBitstream
324                        $AACheaderBitstream = '';
325
326                        // Loop thru substring chars
327                        for ($i = 0; $i < 10; $i++) {
328                                $AACheaderBitstream .= $decbin[$substring{$i}];
329                        }
330
331                        $bitoffset = 0;
332
333                        $synctest = bindec(substr($AACheaderBitstream, $bitoffset, 12));
334
335                        $bitoffset += 12;
336                        if ($synctest != 0x0FFF) {
337                                $ThisFileInfo['error'][] = 'Synch pattern (0x0FFF) not found at offset '.(ftell($fd) - 10).' (found 0x0'.strtoupper(dechex($synctest)).' instead)';
338                                if ($ThisFileInfo['fileformat'] == 'aac') {
339                                        return true;
340                                }
341                                return false;
342                        }
343
344                        // Gather info for first frame only - this takes time to do 1000 times!
345                        if ($framenumber > 0) {
346
347                                if (!$AACheaderBitstream[$bitoffset]) {
348
349                                        // MPEG-4
350                                        $bitoffset += 20;
351
352                                } else {
353
354                                        // MPEG-2
355                                        $bitoffset += 18;
356
357                                }
358
359                        } else {
360
361                                $ThisFileInfo['aac']['header_type']                      = 'ADTS';
362                                $ThisFileInfo['aac']['header']['synch']                  = $synctest;
363                                $ThisFileInfo['fileformat']                              = 'aac';
364                                $ThisFileInfo['audio']['dataformat']                     = 'aac';
365
366                                $ThisFileInfo['aac']['header']['mpeg_version']           = ((substr($AACheaderBitstream, $bitoffset, 1) == '0') ? 4 : 2);
367                                $bitoffset += 1;
368                                $ThisFileInfo['aac']['header']['layer']                  = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2));
369                                $bitoffset += 2;
370                                if ($ThisFileInfo['aac']['header']['layer'] != 0) {
371                                        $ThisFileInfo['error'][] = 'Layer error - expected 0x00, found 0x'.dechex($ThisFileInfo['aac']['header']['layer']).' instead';
372                                        return false;
373                                }
374                                $ThisFileInfo['aac']['header']['crc_present']            = ((substr($AACheaderBitstream, $bitoffset, 1) == '0') ? true : false);
375                                $bitoffset += 1;
376                                $ThisFileInfo['aac']['header']['profile_id']             = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2));
377                                $bitoffset += 2;
378                                $ThisFileInfo['aac']['header']['profile_text']           = $this->AACprofileLookup($ThisFileInfo['aac']['header']['profile_id'], $ThisFileInfo['aac']['header']['mpeg_version']);
379
380                                $ThisFileInfo['aac']['header']['sample_frequency_index'] = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
381                                $bitoffset += 4;
382                                $ThisFileInfo['aac']['header']['sample_frequency']       = $this->AACsampleRateLookup($ThisFileInfo['aac']['header']['sample_frequency_index']);
383                                if ($ThisFileInfo['aac']['header']['sample_frequency'] == 0) {
384                                        $ThisFileInfo['error'][] = 'Corrupt AAC file: sample_frequency == zero';
385                                        return false;
386                                }
387                                $ThisFileInfo['audio']['sample_rate']                    = $ThisFileInfo['aac']['header']['sample_frequency'];
388
389                                $ThisFileInfo['aac']['header']['private']                = (bool) getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
390                                $bitoffset += 1;
391                                $ThisFileInfo['aac']['header']['channel_configuration']  = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 3));
392                                $bitoffset += 3;
393                                $ThisFileInfo['audio']['channels']                       = $ThisFileInfo['aac']['header']['channel_configuration'];
394                                $ThisFileInfo['aac']['header']['original']               = (bool) getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
395                                $bitoffset += 1;
396                                $ThisFileInfo['aac']['header']['home']                   = (bool) getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
397                                $bitoffset += 1;
398
399                                if ($ThisFileInfo['aac']['header']['mpeg_version'] == 4) {
400                                        $ThisFileInfo['aac']['header']['emphasis']           = getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 2));
401                                        $bitoffset += 2;
402                                }
403
404                                if ($ReturnExtendedInfo) {
405
406                                        $ThisFileInfo['aac'][$framenumber]['copyright_id_bit']   = (bool) getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
407                                        $bitoffset += 1;
408                                        $ThisFileInfo['aac'][$framenumber]['copyright_id_start'] = (bool) getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 1));
409                                        $bitoffset += 1;
410
411                                } else {
412
413                                        $bitoffset += 2;
414
415                                }
416
417                        }
418
419                        $FrameLength = bindec(substr($AACheaderBitstream, $bitoffset, 13));
420
421                        if (!isset($BitrateCache[$FrameLength])) {
422                                $BitrateCache[$FrameLength] = ($ThisFileInfo['aac']['header']['sample_frequency'] / 1024) * $FrameLength * 8;
423                        }
424                        @$ThisFileInfo['aac']['bitrate_distribution'][$BitrateCache[$FrameLength]]++;
425
426                        $ThisFileInfo['aac'][$framenumber]['aac_frame_length']     = $FrameLength;
427                        $bitoffset += 13;
428                        $ThisFileInfo['aac'][$framenumber]['adts_buffer_fullness'] = bindec(substr($AACheaderBitstream, $bitoffset, 11));
429                        $bitoffset += 11;
430                        if ($ThisFileInfo['aac'][$framenumber]['adts_buffer_fullness'] == 0x07FF) {
431                                $ThisFileInfo['audio']['bitrate_mode'] = 'vbr';
432                        } else {
433                                $ThisFileInfo['audio']['bitrate_mode'] = 'cbr';
434                        }
435                        $ThisFileInfo['aac'][$framenumber]['num_raw_data_blocks']  = bindec(substr($AACheaderBitstream, $bitoffset, 2));
436                        $bitoffset += 2;
437
438                        if ($ThisFileInfo['aac']['header']['crc_present']) {
439                                //$ThisFileInfo['aac'][$framenumber]['crc']              = bindec(substr($AACheaderBitstream, $bitoffset, 16));
440                                $bitoffset += 16;
441                        }
442
443                        if (!$ReturnExtendedInfo) {
444                                unset($ThisFileInfo['aac'][$framenumber]);
445                        }
446
447                        $byteoffset += $FrameLength;
448                        if ((++$framenumber < $MaxFramesToScan) && (($byteoffset + 10) < $ThisFileInfo['avdataend'])) {
449
450                                // keep scanning
451
452                        } else {
453
454                                $ThisFileInfo['aac']['frames']    = $framenumber;
455                                $ThisFileInfo['playtime_seconds'] = ($ThisFileInfo['avdataend'] / $byteoffset) * (($framenumber * 1024) / $ThisFileInfo['aac']['header']['sample_frequency']);  // (1 / % of file scanned) * (samples / (samples/sec)) = seconds
456                                if ($ThisFileInfo['playtime_seconds'] == 0) {
457                                        $ThisFileInfo['error'][] = 'Corrupt AAC file: playtime_seconds == zero';
458                                        return false;
459                                }
460                                $ThisFileInfo['audio']['bitrate']    = (($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / $ThisFileInfo['playtime_seconds'];
461                                ksort($ThisFileInfo['aac']['bitrate_distribution']);
462
463                                $ThisFileInfo['audio']['encoder_options'] = $ThisFileInfo['aac']['header_type'].' '.$ThisFileInfo['aac']['header']['profile_text'];
464
465                                return true;
466
467                        }
468                }
469                // should never get here.
470        }
471
472        function AACsampleRateLookup($samplerateid) {
473                static $AACsampleRateLookup = array();
474                if (empty($AACsampleRateLookup)) {
475                        $AACsampleRateLookup[0]  = 96000;
476                        $AACsampleRateLookup[1]  = 88200;
477                        $AACsampleRateLookup[2]  = 64000;
478                        $AACsampleRateLookup[3]  = 48000;
479                        $AACsampleRateLookup[4]  = 44100;
480                        $AACsampleRateLookup[5]  = 32000;
481                        $AACsampleRateLookup[6]  = 24000;
482                        $AACsampleRateLookup[7]  = 22050;
483                        $AACsampleRateLookup[8]  = 16000;
484                        $AACsampleRateLookup[9]  = 12000;
485                        $AACsampleRateLookup[10] = 11025;
486                        $AACsampleRateLookup[11] = 8000;
487                        $AACsampleRateLookup[12] = 0;
488                        $AACsampleRateLookup[13] = 0;
489                        $AACsampleRateLookup[14] = 0;
490                        $AACsampleRateLookup[15] = 0;
491                }
492                return (isset($AACsampleRateLookup[$samplerateid]) ? $AACsampleRateLookup[$samplerateid] : 'invalid');
493        }
494
495        function AACprofileLookup($profileid, $mpegversion) {
496                static $AACprofileLookup = array();
497                if (empty($AACprofileLookup)) {
498                        $AACprofileLookup[2][0]  = 'Main profile';
499                        $AACprofileLookup[2][1]  = 'Low Complexity profile (LC)';
500                        $AACprofileLookup[2][2]  = 'Scalable Sample Rate profile (SSR)';
501                        $AACprofileLookup[2][3]  = '(reserved)';
502                        $AACprofileLookup[4][0]  = 'AAC_MAIN';
503                        $AACprofileLookup[4][1]  = 'AAC_LC';
504                        $AACprofileLookup[4][2]  = 'AAC_SSR';
505                        $AACprofileLookup[4][3]  = 'AAC_LTP';
506                }
507                return (isset($AACprofileLookup[$mpegversion][$profileid]) ? $AACprofileLookup[$mpegversion][$profileid] : 'invalid');
508        }
509
510        function AACchannelCountCalculate($program_configs) {
511                $channels = 0;
512                for ($i = 0; $i < $program_configs['num_front_channel_elements']; $i++) {
513                        $channels++;
514                        if ($program_configs['front_element_is_cpe'][$i]) {
515                                // each front element is channel pair (CPE = Channel Pair Element)
516                                $channels++;
517                        }
518                }
519                for ($i = 0; $i < $program_configs['num_side_channel_elements']; $i++) {
520                        $channels++;
521                        if ($program_configs['side_element_is_cpe'][$i]) {
522                                // each side element is channel pair (CPE = Channel Pair Element)
523                                $channels++;
524                        }
525                }
526                for ($i = 0; $i < $program_configs['num_back_channel_elements']; $i++) {
527                        $channels++;
528                        if ($program_configs['back_element_is_cpe'][$i]) {
529                                // each back element is channel pair (CPE = Channel Pair Element)
530                                $channels++;
531                        }
532                }
533                for ($i = 0; $i < $program_configs['num_lfe_channel_elements']; $i++) {
534                        $channels++;
535                }
536                return $channels;
537        }
538
539}
540
541
542?>
Note: See TracBrowser for help on using the repository browser.