getid3_ac3::Analyze()   F
last analyzed

Complexity

Conditions 23
Paths > 20000

Size

Total Lines 218
Code Lines 123

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 23
eloc 123
c 1
b 0
f 0
nc 184323
nop 0
dl 0
loc 218
rs 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
// +----------------------------------------------------------------------+
3
// | PHP version 5                                                        |
4
// +----------------------------------------------------------------------+
5
// | Copyright (c) 2002-2006 James Heinrich, Allan Hansen                 |
6
// +----------------------------------------------------------------------+
7
// | This source file is subject to version 2 of the GPL license,         |
8
// | that is bundled with this package in the file license.txt and is     |
9
// | available through the world-wide-web at the following url:           |
10
// | http://www.gnu.org/copyleft/gpl.html                                 |
11
// +----------------------------------------------------------------------+
12
// | getID3() - http://getid3.sourceforge.net or http://www.getid3.org    |
13
// +----------------------------------------------------------------------+
14
// | Authors: James Heinrich <info�getid3*org>                            |
15
// |          Allan Hansen <ah�artemis*dk>                                |
16
// +----------------------------------------------------------------------+
17
// | module.audio.ac3.php                                                 |
18
// | Module for analyzing AC-3 (aka Dolby Digital) audio files            |
19
// | dependencies: NONE                                                   |
20
// +----------------------------------------------------------------------+
21
//
22
// $Id: module.audio.ac3.php,v 1.3 2006/11/02 10:48:01 ah Exp $
23
24
class getid3_ac3 extends getid3_handler
25
{
26
27
    public function Analyze()
28
    {
29
        $getid3 = $this->getid3;
30
31
        // http://www.atsc.org/standards/a_52a.pdf
32
33
        $getid3->info['fileformat']            = 'ac3';
34
        $getid3->info['audio']['dataformat']   = 'ac3';
35
        $getid3->info['audio']['bitrate_mode'] = 'cbr';
36
        $getid3->info['audio']['lossless']     = false;
37
38
        $getid3->info['ac3']['raw']['bsi'] = [];
39
        $info_ac3                          = &$getid3->info['ac3'];
40
        $info_ac3_raw                      = &$info_ac3['raw'];
41
        $info_ac3_raw_bsi                  = &$info_ac3_raw['bsi'];
42
43
        // An AC-3 serial coded audio bit stream is made up of a sequence of synchronization frames
44
        // Each synchronization frame contains 6 coded audio blocks (AB), each of which represent 256
45
        // new audio samples per channel. A synchronization information (SI) header at the beginning
46
        // of each frame contains information needed to acquire and maintain synchronization. A
47
        // bit stream information (BSI) header follows SI, and contains parameters describing the coded
48
        // audio service. The coded audio blocks may be followed by an auxiliary data (Aux) field. At the
49
        // end of each frame is an error check field that includes a CRC word for error detection. An
50
        // additional CRC word is located in the SI header, the use of which, by a decoder, is optional.
51
        //
52
        // syncinfo() | bsi() | AB0 | AB1 | AB2 | AB3 | AB4 | AB5 | Aux | CRC
53
54
        $this->fseek($getid3->info['avdataoffset'], SEEK_SET);
55
        $ac3_header['syncinfo']                 = $this->fread(5);
0 ignored issues
show
Comprehensibility Best Practice introduced by
$ac3_header was never initialized. Although not strictly required by PHP, it is generally a good practice to add $ac3_header = array(); before regardless.
Loading history...
56
        $info_ac3_raw['synchinfo']['synchword'] = substr($ac3_header['syncinfo'], 0, 2);
57
58
        if ("\x0B\x77" != $info_ac3_raw['synchinfo']['synchword']) {
59
            throw new getid3_exception('Expecting "\x0B\x77" at offset ' . $getid3->info['avdataoffset'] . ', found \x' . strtoupper(dechex($ac3_header['syncinfo']{0})) . '\x' . strtoupper(dechex($ac3_header['syncinfo']{1})) . ' instead');
60
        }
61
62
        // syncinfo() {
63
        //      syncword    16
64
        //      crc1        16
65
        //      fscod        2
66
        //      frmsizecod   6
67
        // } /* end of syncinfo */
68
69
        $info_ac3_raw['synchinfo']['crc1']       = getid3_lib::LittleEndian2Int(substr($ac3_header['syncinfo'], 2, 2));
70
        $ac3_synchinfo_fscod_frmsizecod          = getid3_lib::LittleEndian2Int(substr($ac3_header['syncinfo'], 4, 1));
71
        $info_ac3_raw['synchinfo']['fscod']      = ($ac3_synchinfo_fscod_frmsizecod & 0xC0) >> 6;
72
        $info_ac3_raw['synchinfo']['frmsizecod'] = ($ac3_synchinfo_fscod_frmsizecod & 0x3F);
73
74
        $info_ac3['sample_rate'] = getid3_ac3::AC3sampleRateCodeLookup($info_ac3_raw['synchinfo']['fscod']);
75
        if ($info_ac3_raw['synchinfo']['fscod'] <= 3) {
76
            $getid3->info['audio']['sample_rate'] = $info_ac3['sample_rate'];
77
        }
78
79
        $info_ac3['frame_length']         = getid3_ac3::AC3frameSizeLookup($info_ac3_raw['synchinfo']['frmsizecod'], $info_ac3_raw['synchinfo']['fscod']);
80
        $info_ac3['bitrate']              = getid3_ac3::AC3bitrateLookup($info_ac3_raw['synchinfo']['frmsizecod']);
81
        $getid3->info['audio']['bitrate'] = $info_ac3['bitrate'];
82
83
        $ac3_header['bsi'] = getid3_lib::BigEndian2Bin($this->fread(15));
84
85
        $info_ac3_raw_bsi['bsid'] = bindec(substr($ac3_header['bsi'], 0, 5));
86
        if ($info_ac3_raw_bsi['bsid'] > 8) {
87
            // Decoders which can decode version 8 will thus be able to decode version numbers less than 8.
88
            // If this standard is extended by the addition of additional elements or features, a value of bsid greater than 8 will be used.
89
            // Decoders built to this version of the standard will not be able to decode versions with bsid greater than 8.
90
            throw new getid3_exception('Bit stream identification is version ' . $info_ac3_raw_bsi['bsid'] . ', but getID3() only understands up to version 8');
91
        }
92
93
        $info_ac3_raw_bsi['bsmod'] = bindec(substr($ac3_header['bsi'], 5, 3));
94
        $info_ac3_raw_bsi['acmod'] = bindec(substr($ac3_header['bsi'], 8, 3));
95
96
        $info_ac3['service_type'] = getid3_ac3::AC3serviceTypeLookup($info_ac3_raw_bsi['bsmod'], $info_ac3_raw_bsi['acmod']);
97
        $ac3_coding_mode          = getid3_ac3::AC3audioCodingModeLookup($info_ac3_raw_bsi['acmod']);
98
        foreach ($ac3_coding_mode as $key => $value) {
99
            $info_ac3[$key] = $value;
100
        }
101
        switch ($info_ac3_raw_bsi['acmod']) {
102
            case 0:
103
            case 1:
104
                $getid3->info['audio']['channelmode'] = 'mono';
105
                break;
106
            case 3:
107
            case 4:
108
                $getid3->info['audio']['channelmode'] = 'stereo';
109
                break;
110
            default:
111
                $getid3->info['audio']['channelmode'] = 'surround';
112
                break;
113
        }
114
        $getid3->info['audio']['channels'] = $info_ac3['num_channels'];
115
116
        $offset = 11;
117
118
        if ($info_ac3_raw_bsi['acmod'] & 0x01) {
119
            // If the lsb of acmod is a 1, center channel is in use and cmixlev follows in the bit stream.
120
            $info_ac3_raw_bsi['cmixlev']  = bindec(substr($ac3_header['bsi'], $offset, 2));
121
            $info_ac3['center_mix_level'] = getid3_ac3::AC3centerMixLevelLookup($info_ac3_raw_bsi['cmixlev']);
122
            $offset                       += 2;
123
        }
124
125
        if ($info_ac3_raw_bsi['acmod'] & 0x04) {
126
            // If the msb of acmod is a 1, surround channels are in use and surmixlev follows in the bit stream.
127
            $info_ac3_raw_bsi['surmixlev']  = bindec(substr($ac3_header['bsi'], $offset, 2));
128
            $info_ac3['surround_mix_level'] = getid3_ac3::AC3surroundMixLevelLookup($info_ac3_raw_bsi['surmixlev']);
129
            $offset                         += 2;
130
        }
131
132
        if (0x02 == $info_ac3_raw_bsi['acmod']) {
133
            // When operating in the two channel mode, this 2-bit code indicates whether or not the program has been encoded in Dolby Surround.
134
            $info_ac3_raw_bsi['dsurmod']     = bindec(substr($ac3_header['bsi'], $offset, 2));
135
            $info_ac3['dolby_surround_mode'] = getid3_ac3::AC3dolbySurroundModeLookup($info_ac3_raw_bsi['dsurmod']);
136
            $offset                          += 2;
137
        }
138
139
        $info_ac3_raw_bsi['lfeon'] = '1' == $ac3_header['bsi']{$offset++};
140
        $info_ac3['lfe_enabled']   = $info_ac3_raw_bsi['lfeon'];
141
        if ($info_ac3_raw_bsi['lfeon']) {
142
            $getid3->info['audio']['channels'] .= '.1';
143
        }
144
145
        $info_ac3['channels_enabled'] = getid3_ac3::AC3channelsEnabledLookup($info_ac3_raw_bsi['acmod'], $info_ac3_raw_bsi['lfeon']);
146
147
        // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1�31.
148
        // The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
149
        $info_ac3_raw_bsi['dialnorm']       = bindec(substr($ac3_header['bsi'], $offset, 5));
150
        $offset                             += 5;
151
        $info_ac3['dialogue_normalization'] = '-' . $info_ac3_raw_bsi['dialnorm'] . 'dB';
152
153
        $info_ac3_raw_bsi['compre_flag'] = '1' == $ac3_header['bsi']{$offset++};
154
        if ($info_ac3_raw_bsi['compre_flag']) {
155
            $info_ac3_raw_bsi['compr'] = bindec(substr($ac3_header['bsi'], $offset, 8));
156
            $offset                    += 8;
157
158
            $info_ac3['heavy_compression'] = getid3_ac3::AC3heavyCompression($info_ac3_raw_bsi['compr']);
159
        }
160
161
        $info_ac3_raw_bsi['langcode_flag'] = '1' == $ac3_header['bsi']{$offset++};
162
        if ($info_ac3_raw_bsi['langcode_flag']) {
163
            $info_ac3_raw_bsi['langcod'] = bindec(substr($ac3_header['bsi'], $offset, 8));
164
            $offset                      += 8;
165
        }
166
167
        $info_ac3_raw_bsi['audprodie'] = '1' == $ac3_header['bsi']{$offset++};
168
        if ($info_ac3_raw_bsi['audprodie']) {
169
            $info_ac3_raw_bsi['mixlevel'] = bindec(substr($ac3_header['bsi'], $offset, 5));
170
            $offset                       += 5;
171
172
            $info_ac3_raw_bsi['roomtyp'] = bindec(substr($ac3_header['bsi'], $offset, 2));
173
            $offset                      += 2;
174
175
            $info_ac3['mixing_level'] = (80 + $info_ac3_raw_bsi['mixlevel']) . 'dB';
176
            $info_ac3['room_type']    = getid3_ac3::AC3roomTypeLookup($info_ac3_raw_bsi['roomtyp']);
177
        }
178
179
        if (0x00 == $info_ac3_raw_bsi['acmod']) {
180
            // If acmod is 0, then two completely independent program channels (dual mono)
181
            // are encoded into the bit stream, and are referenced as Ch1, Ch2. In this case,
182
            // a number of additional items are present in BSI or audblk to fully describe Ch2.
183
184
            // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1�31.
185
            // The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
186
            $info_ac3_raw_bsi['dialnorm2'] = bindec(substr($ac3_header['bsi'], $offset, 5));
187
            $offset                        += 5;
188
189
            $info_ac3['dialogue_normalization2'] = '-' . $info_ac3_raw_bsi['dialnorm2'] . 'dB';
190
191
            $info_ac3_raw_bsi['compre_flag2'] = '1' == $ac3_header['bsi']{$offset++};
192
            if ($info_ac3_raw_bsi['compre_flag2']) {
193
                $info_ac3_raw_bsi['compr2'] = bindec(substr($ac3_header['bsi'], $offset, 8));
194
                $offset                     += 8;
195
196
                $info_ac3['heavy_compression2'] = getid3_ac3::AC3heavyCompression($info_ac3_raw_bsi['compr2']);
197
            }
198
199
            $info_ac3_raw_bsi['langcode_flag2'] = '1' == $ac3_header['bsi']{$offset++};
200
            if ($info_ac3_raw_bsi['langcode_flag2']) {
201
                $info_ac3_raw_bsi['langcod2'] = bindec(substr($ac3_header['bsi'], $offset, 8));
202
                $offset                       += 8;
203
            }
204
205
            $info_ac3_raw_bsi['audprodie2'] = '1' == $ac3_header['bsi']{$offset++};
206
            if ($info_ac3_raw_bsi['audprodie2']) {
207
                $info_ac3_raw_bsi['mixlevel2'] = bindec(substr($ac3_header['bsi'], $offset, 5));
208
                $offset                        += 5;
209
210
                $info_ac3_raw_bsi['roomtyp2'] = bindec(substr($ac3_header['bsi'], $offset, 2));
211
                $offset                       += 2;
212
213
                $info_ac3['mixing_level2'] = (80 + $info_ac3_raw_bsi['mixlevel2']) . 'dB';
214
                $info_ac3['room_type2']    = getid3_ac3::AC3roomTypeLookup($info_ac3_raw_bsi['roomtyp2']);
215
            }
216
        }
217
218
        $info_ac3_raw_bsi['copyright'] = '1' == $ac3_header['bsi']{$offset++};
219
220
        $info_ac3_raw_bsi['original'] = '1' == $ac3_header['bsi']{$offset++};
221
222
        $info_ac3_raw_bsi['timecode1_flag'] = '1' == $ac3_header['bsi']{$offset++};
223
        if ($info_ac3_raw_bsi['timecode1_flag']) {
224
            $info_ac3_raw_bsi['timecode1'] = bindec(substr($ac3_header['bsi'], $offset, 14));
225
            $offset                        += 14;
226
        }
227
228
        $info_ac3_raw_bsi['timecode2_flag'] = '1' == $ac3_header['bsi']{$offset++};
229
        if ($info_ac3_raw_bsi['timecode2_flag']) {
230
            $info_ac3_raw_bsi['timecode2'] = bindec(substr($ac3_header['bsi'], $offset, 14));
231
            $offset                        += 14;
232
        }
233
234
        $info_ac3_raw_bsi['addbsi_flag'] = '1' == $ac3_header['bsi']{$offset++};
235
        if ($info_ac3_raw_bsi['addbsi_flag']) {
236
            $info_ac3_raw_bsi['addbsi_length'] = bindec(substr($ac3_header['bsi'], $offset, 6));
237
            $offset                            += 6;
238
239
            $ac3_header['bsi'] .= getid3_lib::BigEndian2Bin($this->fread($info_ac3_raw_bsi['addbsi_length']));
240
241
            $info_ac3_raw_bsi['addbsi_data'] = substr($ac3_header['bsi'], 119, $info_ac3_raw_bsi['addbsi_length'] * 8);
242
        }
243
244
        return true;
245
    }
246
247
    public static function AC3sampleRateCodeLookup($fscod)
248
    {
249
        static $lookup = [
250
            0 => 48000,
251
            1 => 44100,
252
            2 => 32000,
253
            3 => 'reserved' // If the reserved code is indicated, the decoder should not attempt to decode audio and should mute.
254
        ];
255
        return (isset($lookup[$fscod]) ? $lookup[$fscod] : false);
256
    }
257
258
    public static function AC3serviceTypeLookup($bsmod, $acmod)
259
    {
260
        static $lookup = [
261
            0 => 'main audio service: complete main (CM)',
262
            1 => 'main audio service: music and effects (ME)',
263
            2 => 'associated service: visually impaired (VI)',
264
            3 => 'associated service: hearing impaired (HI)',
265
            4 => 'associated service: dialogue (D)',
266
            5 => 'associated service: commentary (C)',
267
            6 => 'associated service: emergency (E)',
268
            7 => 'main audio service: karaoke'
269
        ];
270
271
        if (7 == $bsmod && 1 == $acmod) {
272
            return 'associated service: voice over (VO)';
273
        }
274
275
        return (isset($lookup[$bsmod]) ? $lookup[$bsmod] : false);
276
    }
277
278
    public static function AC3audioCodingModeLookup($acmod)
279
    {
280
        // array (channel configuration, # channels (not incl LFE), channel order)
281
        static $lookup = [
282
            0 => ['channel_config' => '1+1', 'num_channels' => 2, 'channel_order' => 'Ch1,Ch2'],
283
            1 => ['channel_config' => '1/0', 'num_channels' => 1, 'channel_order' => 'C'],
284
            2 => ['channel_config' => '2/0', 'num_channels' => 2, 'channel_order' => 'L,R'],
285
            3 => ['channel_config' => '3/0', 'num_channels' => 3, 'channel_order' => 'L,C,R'],
286
            4 => ['channel_config' => '2/1', 'num_channels' => 3, 'channel_order' => 'L,R,S'],
287
            5 => ['channel_config' => '3/1', 'num_channels' => 4, 'channel_order' => 'L,C,R,S'],
288
            6 => ['channel_config' => '2/2', 'num_channels' => 4, 'channel_order' => 'L,R,SL,SR'],
289
            7 => ['channel_config' => '3/2', 'num_channels' => 5, 'channel_order' => 'L,C,R,SL,SR']
290
        ];
291
        return (isset($lookup[$acmod]) ? $lookup[$acmod] : false);
292
    }
293
294
    public static function AC3centerMixLevelLookup($cmixlev)
295
    {
296
        static $lookup;
297
        if (!@$lookup) {
298
            $lookup = [
299
                0 => pow(2, -3.0 / 6), // 0.707 (�3.0 dB)
300
                1 => pow(2, -4.5 / 6), // 0.595 (�4.5 dB)
301
                2 => pow(2, -6.0 / 6), // 0.500 (�6.0 dB)
302
                3 => 'reserved'
303
            ];
304
        }
305
        return (isset($lookup[$cmixlev]) ? $lookup[$cmixlev] : false);
306
    }
307
308
    public static function AC3surroundMixLevelLookup($surmixlev)
309
    {
310
        static $lookup;
311
        if (!@$lookup) {
312
            $lookup = [
313
                0 => pow(2, -3.0 / 6),
314
                1 => pow(2, -6.0 / 6),
315
                2 => 0,
316
                3 => 'reserved'
317
            ];
318
        }
319
        return (isset($lookup[$surmixlev]) ? $lookup[$surmixlev] : false);
320
    }
321
322
    public static function AC3dolbySurroundModeLookup($dsurmod)
323
    {
324
        static $lookup = [
325
            0 => 'not indicated',
326
            1 => 'Not Dolby Surround encoded',
327
            2 => 'Dolby Surround encoded',
328
            3 => 'reserved'
329
        ];
330
        return (isset($lookup[$dsurmod]) ? $lookup[$dsurmod] : false);
331
    }
332
333
    public static function AC3channelsEnabledLookup($acmod, $lfeon)
334
    {
335
        return [
336
            'ch1'            => 0 == $acmod,
337
            'ch2'            => 0 == $acmod,
338
            'left'           => $acmod > 1,
339
            'right'          => $acmod > 1,
340
            'center'         => (bool)($acmod & 0x01),
341
            'surround_mono'  => 4 == $acmod || 5 == $acmod,
342
            'surround_left'  => 6 == $acmod || 7 == $acmod,
343
            'surround_right' => 6 == $acmod || 7 == $acmod,
344
            'lfe'            => $lfeon
345
        ];
346
    }
347
348
    public static function AC3heavyCompression($compre)
349
    {
350
        // The first four bits indicate gain changes in 6.02dB increments which can be
351
        // implemented with an arithmetic shift operation. The following four bits
352
        // indicate linear gain changes, and require a 5-bit multiply.
353
        // We will represent the two 4-bit fields of compr as follows:
354
        //   X0 X1 X2 X3 . Y4 Y5 Y6 Y7
355
        // The meaning of the X values is most simply described by considering X to represent a 4-bit
356
        // signed integer with values from �8 to +7. The gain indicated by X is then (X + 1) * 6.02 dB. The
357
        // following table shows this in detail.
358
359
        // Meaning of 4 msb of compr
360
        //  7    +48.16 dB
361
        //  6    +42.14 dB
362
        //  5    +36.12 dB
363
        //  4    +30.10 dB
364
        //  3    +24.08 dB
365
        //  2    +18.06 dB
366
        //  1    +12.04 dB
367
        //  0     +6.02 dB
368
        // -1         0 dB
369
        // -2     �6.02 dB
370
        // -3    �12.04 dB
371
        // -4    �18.06 dB
372
        // -5    �24.08 dB
373
        // -6    �30.10 dB
374
        // -7    �36.12 dB
375
        // -8    �42.14 dB
376
377
        $fourbit = str_pad(decbin(($compre & 0xF0) >> 4), 4, '0', STR_PAD_LEFT);
378
        if ('1' == $fourbit{0}) {
379
            $log_gain = -8 + bindec(substr($fourbit, 1));
380
        } else {
381
            $log_gain = bindec(substr($fourbit, 1));
382
        }
383
        $log_gain = ($log_gain + 1) * (20 * log10(2));
384
385
        // The value of Y is a linear representation of a gain change of up to �6 dB. Y is considered to
386
        // be an unsigned fractional integer, with a leading value of 1, or: 0.1 Y4 Y5 Y6 Y7 (base 2). Y can
387
        // represent values between 0.111112 (or 31/32) and 0.100002 (or 1/2). Thus, Y can represent gain
388
        // changes from �0.28 dB to �6.02 dB.
389
390
        $lin_gain = (16 + ($compre & 0x0F)) / 32;
391
392
        // The combination of X and Y values allows compr to indicate gain changes from
393
        //  48.16 � 0.28 = +47.89 dB, to
394
        // �42.14 � 6.02 = �48.16 dB.
395
396
        return $log_gain - $lin_gain;
397
    }
398
399
    public static function AC3roomTypeLookup($roomtyp)
400
    {
401
        static $lookup = [
402
            0 => 'not indicated',
403
            1 => 'large room, X curve monitor',
404
            2 => 'small room, flat monitor',
405
            3 => 'reserved'
406
        ];
407
        return (isset($lookup[$roomtyp]) ? $lookup[$roomtyp] : false);
408
    }
409
410
    public static function AC3frameSizeLookup($frmsizecod, $fscod)
411
    {
412
        $padding       = (bool)($frmsizecod % 2);
413
        $frame_size_id = floor($frmsizecod / 2);
414
415
        static $lookup = [
416
            0  => [128, 138, 192],
417
            1  => [40, 160, 174, 240],
418
            2  => [48, 192, 208, 288],
419
            3  => [56, 224, 242, 336],
420
            4  => [64, 256, 278, 384],
421
            5  => [80, 320, 348, 480],
422
            6  => [96, 384, 416, 576],
423
            7  => [112, 448, 486, 672],
424
            8  => [128, 512, 556, 768],
425
            9  => [160, 640, 696, 960],
426
            10 => [192, 768, 834, 1152],
427
            11 => [224, 896, 974, 1344],
428
            12 => [256, 1024, 1114, 1536],
429
            13 => [320, 1280, 1392, 1920],
430
            14 => [384, 1536, 1670, 2304],
431
            15 => [448, 1792, 1950, 2688],
432
            16 => [512, 2048, 2228, 3072],
433
            17 => [576, 2304, 2506, 3456],
434
            18 => [640, 2560, 2786, 3840]
435
        ];
436
        if ((1 == $fscod) && $padding) {
437
            // frame lengths are padded by 1 word (16 bits) at 44100
438
            $lookup[$frmsizecod] += 2;
439
        }
440
        return (isset($lookup[$frame_size_id][$fscod]) ? $lookup[$frame_size_id][$fscod] : false);
441
    }
442
443
    public static function AC3bitrateLookup($frmsizecod)
444
    {
445
        static $lookup = [
446
            0  => 32000,
447
            1  => 40000,
448
            2  => 48000,
449
            3  => 56000,
450
            4  => 64000,
451
            5  => 80000,
452
            6  => 96000,
453
            7  => 112000,
454
            8  => 128000,
455
            9  => 160000,
456
            10 => 192000,
457
            11 => 224000,
458
            12 => 256000,
459
            13 => 320000,
460
            14 => 384000,
461
            15 => 448000,
462
            16 => 512000,
463
            17 => 576000,
464
            18 => 640000
465
        ];
466
        $frame_size_id = floor($frmsizecod / 2);
467
        return (isset($lookup[$frame_size_id]) ? $lookup[$frame_size_id] : false);
468
    }
469
470
}
471
472
473