diff e2gallerypro/e2upload/Backend/Assets/getid3/module.audio.ac3.php @ 3:3f6b44aa6b35 judyates

[svn r4] added ability to buy stuff, from a Prints page, but it doesn't work well with the css, and it also has not been fitted into the perl make system.
author rlm
date Mon, 22 Feb 2010 08:02:39 -0500
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/e2gallerypro/e2upload/Backend/Assets/getid3/module.audio.ac3.php	Mon Feb 22 08:02:39 2010 -0500
     1.3 @@ -0,0 +1,500 @@
     1.4 +<?php
     1.5 +// +----------------------------------------------------------------------+
     1.6 +// | PHP version 5                                                        |
     1.7 +// +----------------------------------------------------------------------+
     1.8 +// | Copyright (c) 2002-2006 James Heinrich, Allan Hansen                 |
     1.9 +// +----------------------------------------------------------------------+
    1.10 +// | This source file is subject to version 2 of the GPL license,         |
    1.11 +// | that is bundled with this package in the file license.txt and is     |
    1.12 +// | available through the world-wide-web at the following url:           |
    1.13 +// | http://www.gnu.org/copyleft/gpl.html                                 |
    1.14 +// +----------------------------------------------------------------------+
    1.15 +// | getID3() - http://getid3.sourceforge.net or http://www.getid3.org    |
    1.16 +// +----------------------------------------------------------------------+
    1.17 +// | Authors: James Heinrich <infoุgetid3*org>                            |
    1.18 +// |          Allan Hansen <ahุartemis*dk>                                |
    1.19 +// +----------------------------------------------------------------------+
    1.20 +// | module.audio.ac3.php                                                 |
    1.21 +// | Module for analyzing AC-3 (aka Dolby Digital) audio files            |
    1.22 +// | dependencies: NONE                                                   |
    1.23 +// +----------------------------------------------------------------------+
    1.24 +//
    1.25 +// $Id: module.audio.ac3.php,v 1.3 2006/11/02 10:48:01 ah Exp $
    1.26 +
    1.27 +        
    1.28 +        
    1.29 +class getid3_ac3 extends getid3_handler
    1.30 +{
    1.31 +
    1.32 +    public function Analyze() {
    1.33 +
    1.34 +        $getid3 = $this->getid3;
    1.35 +        
    1.36 +        // http://www.atsc.org/standards/a_52a.pdf
    1.37 +
    1.38 +        $getid3->info['fileformat']            = 'ac3';
    1.39 +        $getid3->info['audio']['dataformat']   = 'ac3';
    1.40 +        $getid3->info['audio']['bitrate_mode'] = 'cbr';
    1.41 +        $getid3->info['audio']['lossless']     = false;
    1.42 +
    1.43 +        $getid3->info['ac3']['raw']['bsi'] = array ();
    1.44 +        $info_ac3         = &$getid3->info['ac3'];
    1.45 +        $info_ac3_raw     = &$info_ac3['raw'];
    1.46 +        $info_ac3_raw_bsi = &$info_ac3_raw['bsi'];
    1.47 +
    1.48 +
    1.49 +        // An AC-3 serial coded audio bit stream is made up of a sequence of synchronization frames
    1.50 +        // Each synchronization frame contains 6 coded audio blocks (AB), each of which represent 256
    1.51 +        // new audio samples per channel. A synchronization information (SI) header at the beginning
    1.52 +        // of each frame contains information needed to acquire and maintain synchronization. A
    1.53 +        // bit stream information (BSI) header follows SI, and contains parameters describing the coded
    1.54 +        // audio service. The coded audio blocks may be followed by an auxiliary data (Aux) field. At the
    1.55 +        // end of each frame is an error check field that includes a CRC word for error detection. An
    1.56 +        // additional CRC word is located in the SI header, the use of which, by a decoder, is optional.
    1.57 +        //
    1.58 +        // syncinfo() | bsi() | AB0 | AB1 | AB2 | AB3 | AB4 | AB5 | Aux | CRC
    1.59 +
    1.60 +        $this->fseek($getid3->info['avdataoffset'], SEEK_SET);
    1.61 +        $ac3_header['syncinfo'] = $this->fread(5);
    1.62 +        $info_ac3_raw['synchinfo']['synchword'] = substr($ac3_header['syncinfo'], 0, 2);
    1.63 +
    1.64 +        if ($info_ac3_raw['synchinfo']['synchword'] != "\x0B\x77") {
    1.65 +            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');
    1.66 +        } 
    1.67 +
    1.68 +
    1.69 +        // syncinfo() {
    1.70 +        //      syncword    16
    1.71 +        //      crc1        16
    1.72 +        //      fscod        2
    1.73 +        //      frmsizecod   6
    1.74 +        // } /* end of syncinfo */
    1.75 +
    1.76 +        $info_ac3_raw['synchinfo']['crc1']       = getid3_lib::LittleEndian2Int(substr($ac3_header['syncinfo'], 2, 2));
    1.77 +        $ac3_synchinfo_fscod_frmsizecod          = getid3_lib::LittleEndian2Int(substr($ac3_header['syncinfo'], 4, 1));
    1.78 +        $info_ac3_raw['synchinfo']['fscod']      = ($ac3_synchinfo_fscod_frmsizecod & 0xC0) >> 6;
    1.79 +        $info_ac3_raw['synchinfo']['frmsizecod'] = ($ac3_synchinfo_fscod_frmsizecod & 0x3F);
    1.80 +
    1.81 +        $info_ac3['sample_rate'] = getid3_ac3::AC3sampleRateCodeLookup($info_ac3_raw['synchinfo']['fscod']);
    1.82 +        if ($info_ac3_raw['synchinfo']['fscod'] <= 3) {
    1.83 +            $getid3->info['audio']['sample_rate'] = $info_ac3['sample_rate'];
    1.84 +        }
    1.85 +
    1.86 +        $info_ac3['frame_length'] = getid3_ac3::AC3frameSizeLookup($info_ac3_raw['synchinfo']['frmsizecod'], $info_ac3_raw['synchinfo']['fscod']);
    1.87 +        $info_ac3['bitrate']      = getid3_ac3::AC3bitrateLookup($info_ac3_raw['synchinfo']['frmsizecod']);
    1.88 +        $getid3->info['audio']['bitrate'] = $info_ac3['bitrate'];
    1.89 +
    1.90 +        $ac3_header['bsi'] = getid3_lib::BigEndian2Bin($this->fread(15));
    1.91 +
    1.92 +        $info_ac3_raw_bsi['bsid'] = bindec(substr($ac3_header['bsi'], 0, 5));
    1.93 +        if ($info_ac3_raw_bsi['bsid'] > 8) {
    1.94 +            // Decoders which can decode version 8 will thus be able to decode version numbers less than 8.
    1.95 +            // If this standard is extended by the addition of additional elements or features, a value of bsid greater than 8 will be used.
    1.96 +            // Decoders built to this version of the standard will not be able to decode versions with bsid greater than 8.
    1.97 +            throw new getid3_exception('Bit stream identification is version '.$info_ac3_raw_bsi['bsid'].', but getID3() only understands up to version 8');
    1.98 +        }
    1.99 +
   1.100 +        $info_ac3_raw_bsi['bsmod'] = bindec(substr($ac3_header['bsi'], 5, 3));
   1.101 +        $info_ac3_raw_bsi['acmod'] = bindec(substr($ac3_header['bsi'], 8, 3));
   1.102 +
   1.103 +        $info_ac3['service_type'] = getid3_ac3::AC3serviceTypeLookup($info_ac3_raw_bsi['bsmod'], $info_ac3_raw_bsi['acmod']);
   1.104 +        $ac3_coding_mode = getid3_ac3::AC3audioCodingModeLookup($info_ac3_raw_bsi['acmod']);
   1.105 +        foreach($ac3_coding_mode as $key => $value) {
   1.106 +            $info_ac3[$key] = $value;
   1.107 +        }
   1.108 +        switch ($info_ac3_raw_bsi['acmod']) {
   1.109 +            case 0:
   1.110 +            case 1:
   1.111 +                $getid3->info['audio']['channelmode'] = 'mono';
   1.112 +                break;
   1.113 +            case 3:
   1.114 +            case 4:
   1.115 +                $getid3->info['audio']['channelmode'] = 'stereo';
   1.116 +                break;
   1.117 +            default:
   1.118 +                $getid3->info['audio']['channelmode'] = 'surround';
   1.119 +                break;
   1.120 +        }
   1.121 +        $getid3->info['audio']['channels'] = $info_ac3['num_channels'];
   1.122 +        
   1.123 +        $offset = 11;
   1.124 +
   1.125 +        if ($info_ac3_raw_bsi['acmod'] & 0x01) {
   1.126 +            // If the lsb of acmod is a 1, center channel is in use and cmixlev follows in the bit stream.
   1.127 +            $info_ac3_raw_bsi['cmixlev'] = bindec(substr($ac3_header['bsi'], $offset, 2));
   1.128 +            $info_ac3['center_mix_level'] = getid3_ac3::AC3centerMixLevelLookup($info_ac3_raw_bsi['cmixlev']);
   1.129 +            $offset += 2;
   1.130 +        }
   1.131 +
   1.132 +        if ($info_ac3_raw_bsi['acmod'] & 0x04) {
   1.133 +            // If the msb of acmod is a 1, surround channels are in use and surmixlev follows in the bit stream.
   1.134 +            $info_ac3_raw_bsi['surmixlev'] = bindec(substr($ac3_header['bsi'], $offset, 2));
   1.135 +            $info_ac3['surround_mix_level'] = getid3_ac3::AC3surroundMixLevelLookup($info_ac3_raw_bsi['surmixlev']);
   1.136 +            $offset += 2;
   1.137 +        }
   1.138 +
   1.139 +        if ($info_ac3_raw_bsi['acmod'] == 0x02) {
   1.140 +            // When operating in the two channel mode, this 2-bit code indicates whether or not the program has been encoded in Dolby Surround.
   1.141 +            $info_ac3_raw_bsi['dsurmod'] = bindec(substr($ac3_header['bsi'], $offset, 2));
   1.142 +            $info_ac3['dolby_surround_mode'] = getid3_ac3::AC3dolbySurroundModeLookup($info_ac3_raw_bsi['dsurmod']);
   1.143 +            $offset += 2;
   1.144 +        }
   1.145 +
   1.146 +        $info_ac3_raw_bsi['lfeon'] = $ac3_header['bsi']{$offset++} == '1';
   1.147 +        $info_ac3['lfe_enabled'] = $info_ac3_raw_bsi['lfeon'];
   1.148 +        if ($info_ac3_raw_bsi['lfeon']) {
   1.149 +            $getid3->info['audio']['channels'] .= '.1';
   1.150 +        }
   1.151 +
   1.152 +        $info_ac3['channels_enabled'] = getid3_ac3::AC3channelsEnabledLookup($info_ac3_raw_bsi['acmod'], $info_ac3_raw_bsi['lfeon']);
   1.153 +
   1.154 +        // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1–31.
   1.155 +        // 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.
   1.156 +        $info_ac3_raw_bsi['dialnorm'] = bindec(substr($ac3_header['bsi'], $offset, 5));
   1.157 +        $offset += 5;
   1.158 +        $info_ac3['dialogue_normalization'] = '-'.$info_ac3_raw_bsi['dialnorm'].'dB';
   1.159 +
   1.160 +        $info_ac3_raw_bsi['compre_flag'] = $ac3_header['bsi']{$offset++} == '1';
   1.161 +        if ($info_ac3_raw_bsi['compre_flag']) {
   1.162 +            $info_ac3_raw_bsi['compr'] = bindec(substr($ac3_header['bsi'], $offset, 8));
   1.163 +            $offset += 8;
   1.164 +            
   1.165 +            $info_ac3['heavy_compression'] = getid3_ac3::AC3heavyCompression($info_ac3_raw_bsi['compr']);
   1.166 +        }
   1.167 +
   1.168 +        $info_ac3_raw_bsi['langcode_flag'] = $ac3_header['bsi']{$offset++} == '1';
   1.169 +        if ($info_ac3_raw_bsi['langcode_flag']) {
   1.170 +            $info_ac3_raw_bsi['langcod'] = bindec(substr($ac3_header['bsi'], $offset, 8));
   1.171 +            $offset += 8;
   1.172 +        }
   1.173 +
   1.174 +        $info_ac3_raw_bsi['audprodie'] = $ac3_header['bsi']{$offset++} == '1';
   1.175 +        if ($info_ac3_raw_bsi['audprodie']) {
   1.176 +            $info_ac3_raw_bsi['mixlevel'] = bindec(substr($ac3_header['bsi'], $offset, 5));
   1.177 +            $offset += 5;
   1.178 +            
   1.179 +            $info_ac3_raw_bsi['roomtyp']  = bindec(substr($ac3_header['bsi'], $offset, 2));
   1.180 +            $offset += 2;
   1.181 +
   1.182 +            $info_ac3['mixing_level'] = (80 + $info_ac3_raw_bsi['mixlevel']).'dB';
   1.183 +            $info_ac3['room_type']    = getid3_ac3::AC3roomTypeLookup($info_ac3_raw_bsi['roomtyp']);
   1.184 +        }
   1.185 +
   1.186 +        if ($info_ac3_raw_bsi['acmod'] == 0x00) {
   1.187 +            // If acmod is 0, then two completely independent program channels (dual mono)
   1.188 +            // are encoded into the bit stream, and are referenced as Ch1, Ch2. In this case,
   1.189 +            // a number of additional items are present in BSI or audblk to fully describe Ch2.
   1.190 +
   1.191 +
   1.192 +            // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1–31.
   1.193 +            // 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.
   1.194 +            $info_ac3_raw_bsi['dialnorm2'] = bindec(substr($ac3_header['bsi'], $offset, 5));
   1.195 +            $offset += 5;
   1.196 +            
   1.197 +            $info_ac3['dialogue_normalization2'] = '-'.$info_ac3_raw_bsi['dialnorm2'].'dB';
   1.198 +
   1.199 +            $info_ac3_raw_bsi['compre_flag2'] = $ac3_header['bsi']{$offset++} == '1';
   1.200 +            if ($info_ac3_raw_bsi['compre_flag2']) {
   1.201 +                $info_ac3_raw_bsi['compr2'] = bindec(substr($ac3_header['bsi'], $offset, 8));
   1.202 +                $offset += 8;
   1.203 +                
   1.204 +                $info_ac3['heavy_compression2'] = getid3_ac3::AC3heavyCompression($info_ac3_raw_bsi['compr2']);
   1.205 +            }
   1.206 +
   1.207 +            $info_ac3_raw_bsi['langcode_flag2'] = $ac3_header['bsi']{$offset++} == '1';
   1.208 +            if ($info_ac3_raw_bsi['langcode_flag2']) {
   1.209 +                $info_ac3_raw_bsi['langcod2'] = bindec(substr($ac3_header['bsi'], $offset, 8));
   1.210 +                $offset += 8;
   1.211 +            }
   1.212 +
   1.213 +            $info_ac3_raw_bsi['audprodie2'] = $ac3_header['bsi']{$offset++} == '1';
   1.214 +            if ($info_ac3_raw_bsi['audprodie2']) {
   1.215 +                $info_ac3_raw_bsi['mixlevel2'] = bindec(substr($ac3_header['bsi'], $offset, 5));
   1.216 +                $offset += 5;
   1.217 +                
   1.218 +                $info_ac3_raw_bsi['roomtyp2']  = bindec(substr($ac3_header['bsi'], $offset, 2));
   1.219 +                $offset += 2;
   1.220 +
   1.221 +                $info_ac3['mixing_level2'] = (80 + $info_ac3_raw_bsi['mixlevel2']).'dB';
   1.222 +                $info_ac3['room_type2']    = getid3_ac3::AC3roomTypeLookup($info_ac3_raw_bsi['roomtyp2']);
   1.223 +            }
   1.224 +
   1.225 +        }
   1.226 +
   1.227 +        $info_ac3_raw_bsi['copyright'] = $ac3_header['bsi']{$offset++} == '1';
   1.228 +
   1.229 +        $info_ac3_raw_bsi['original']  = $ac3_header['bsi']{$offset++} == '1';
   1.230 +
   1.231 +        $info_ac3_raw_bsi['timecode1_flag'] = $ac3_header['bsi']{$offset++} == '1';
   1.232 +        if ($info_ac3_raw_bsi['timecode1_flag']) {
   1.233 +            $info_ac3_raw_bsi['timecode1'] = bindec(substr($ac3_header['bsi'], $offset, 14));
   1.234 +            $offset += 14;
   1.235 +        }
   1.236 +
   1.237 +        $info_ac3_raw_bsi['timecode2_flag'] = $ac3_header['bsi']{$offset++} == '1';
   1.238 +        if ($info_ac3_raw_bsi['timecode2_flag']) {
   1.239 +            $info_ac3_raw_bsi['timecode2'] = bindec(substr($ac3_header['bsi'], $offset, 14));
   1.240 +            $offset += 14;
   1.241 +        }
   1.242 +
   1.243 +        $info_ac3_raw_bsi['addbsi_flag'] = $ac3_header['bsi']{$offset++} == '1';
   1.244 +        if ($info_ac3_raw_bsi['addbsi_flag']) {
   1.245 +            $info_ac3_raw_bsi['addbsi_length'] = bindec(substr($ac3_header['bsi'], $offset, 6));
   1.246 +            $offset += 6;
   1.247 +
   1.248 +            $ac3_header['bsi'] .= getid3_lib::BigEndian2Bin($this->fread($info_ac3_raw_bsi['addbsi_length']));
   1.249 +
   1.250 +            $info_ac3_raw_bsi['addbsi_data'] = substr($ac3_header['bsi'], 119, $info_ac3_raw_bsi['addbsi_length'] * 8);
   1.251 +        }
   1.252 +
   1.253 +        return true;
   1.254 +    }
   1.255 +
   1.256 +
   1.257 +
   1.258 +    public static function AC3sampleRateCodeLookup($fscod) {
   1.259 +
   1.260 +        static $lookup = array (
   1.261 +            0 => 48000,
   1.262 +            1 => 44100,
   1.263 +            2 => 32000,
   1.264 +            3 => 'reserved' // If the reserved code is indicated, the decoder should not attempt to decode audio and should mute.
   1.265 +        );
   1.266 +        return (isset($lookup[$fscod]) ? $lookup[$fscod] : false);
   1.267 +    }
   1.268 +
   1.269 +
   1.270 +
   1.271 +    public static function AC3serviceTypeLookup($bsmod, $acmod) {
   1.272 +
   1.273 +        static $lookup = array (
   1.274 +            0 => 'main audio service: complete main (CM)',
   1.275 +            1 => 'main audio service: music and effects (ME)',
   1.276 +            2 => 'associated service: visually impaired (VI)',
   1.277 +            3 => 'associated service: hearing impaired (HI)',
   1.278 +            4 => 'associated service: dialogue (D)',
   1.279 +            5 => 'associated service: commentary (C)',
   1.280 +            6 => 'associated service: emergency (E)',
   1.281 +            7 => 'main audio service: karaoke'
   1.282 +        );
   1.283 +        
   1.284 +        if ($bsmod == 7  &&  $acmod == 1) {
   1.285 +            return 'associated service: voice over (VO)';
   1.286 +        }
   1.287 +        
   1.288 +        return (isset($lookup[$bsmod]) ? $lookup[$bsmod] : false);
   1.289 +    }
   1.290 +
   1.291 +
   1.292 +
   1.293 +    public static function AC3audioCodingModeLookup($acmod) {
   1.294 +
   1.295 +        // array (channel configuration, # channels (not incl LFE), channel order)
   1.296 +        static $lookup = array (
   1.297 +            0 => array ('channel_config'=>'1+1', 'num_channels'=>2, 'channel_order'=>'Ch1,Ch2'),
   1.298 +            1 => array ('channel_config'=>'1/0', 'num_channels'=>1, 'channel_order'=>'C'),
   1.299 +            2 => array ('channel_config'=>'2/0', 'num_channels'=>2, 'channel_order'=>'L,R'),
   1.300 +            3 => array ('channel_config'=>'3/0', 'num_channels'=>3, 'channel_order'=>'L,C,R'),
   1.301 +            4 => array ('channel_config'=>'2/1', 'num_channels'=>3, 'channel_order'=>'L,R,S'),
   1.302 +            5 => array ('channel_config'=>'3/1', 'num_channels'=>4, 'channel_order'=>'L,C,R,S'),
   1.303 +            6 => array ('channel_config'=>'2/2', 'num_channels'=>4, 'channel_order'=>'L,R,SL,SR'),
   1.304 +            7 => array ('channel_config'=>'3/2', 'num_channels'=>5, 'channel_order'=>'L,C,R,SL,SR')
   1.305 +        );
   1.306 +        return (isset($lookup[$acmod]) ? $lookup[$acmod] : false);
   1.307 +    }
   1.308 +
   1.309 +
   1.310 +
   1.311 +    public static function AC3centerMixLevelLookup($cmixlev) {
   1.312 +        
   1.313 +        static $lookup;
   1.314 +        if (!@$lookup) {
   1.315 +            $lookup = array (
   1.316 +                0 => pow(2, -3.0 / 6), // 0.707 (–3.0 dB)
   1.317 +                1 => pow(2, -4.5 / 6), // 0.595 (–4.5 dB)
   1.318 +                2 => pow(2, -6.0 / 6), // 0.500 (–6.0 dB)
   1.319 +                3 => 'reserved'
   1.320 +            );
   1.321 +        }
   1.322 +        return (isset($lookup[$cmixlev]) ? $lookup[$cmixlev] : false);
   1.323 +    }
   1.324 +
   1.325 +
   1.326 +
   1.327 +    public static function AC3surroundMixLevelLookup($surmixlev) {
   1.328 +        
   1.329 +        static $lookup;
   1.330 +        if (!@$lookup) {
   1.331 +            $lookup = array (
   1.332 +                0 => pow(2, -3.0 / 6),
   1.333 +                1 => pow(2, -6.0 / 6),
   1.334 +                2 => 0,
   1.335 +                3 => 'reserved'
   1.336 +            );
   1.337 +        }
   1.338 +        return (isset($lookup[$surmixlev]) ? $lookup[$surmixlev] : false);
   1.339 +    }
   1.340 +
   1.341 +
   1.342 +
   1.343 +    public static function AC3dolbySurroundModeLookup($dsurmod) {
   1.344 +
   1.345 +        static $lookup = array (
   1.346 +            0 => 'not indicated',
   1.347 +            1 => 'Not Dolby Surround encoded',
   1.348 +            2 => 'Dolby Surround encoded',
   1.349 +            3 => 'reserved'
   1.350 +        );
   1.351 +        return (isset($lookup[$dsurmod]) ? $lookup[$dsurmod] : false);
   1.352 +    }
   1.353 +    
   1.354 +    
   1.355 +
   1.356 +    public static function AC3channelsEnabledLookup($acmod, $lfeon) {
   1.357 +        
   1.358 +        return array (
   1.359 +            'ch1'            => $acmod == 0,
   1.360 +            'ch2'            => $acmod == 0,
   1.361 +            'left'           => $acmod > 1,
   1.362 +            'right'          => $acmod > 1,
   1.363 +            'center'         => (bool)($acmod & 0x01),
   1.364 +            'surround_mono'  => $acmod == 4 || $acmod == 5,
   1.365 +            'surround_left'  => $acmod == 6 || $acmod == 7,
   1.366 +            'surround_right' => $acmod == 6 || $acmod == 7,
   1.367 +            'lfe'            => $lfeon
   1.368 +        );
   1.369 +    }
   1.370 +
   1.371 +
   1.372 +
   1.373 +    public static function AC3heavyCompression($compre) {
   1.374 +
   1.375 +        // The first four bits indicate gain changes in 6.02dB increments which can be
   1.376 +        // implemented with an arithmetic shift operation. The following four bits
   1.377 +        // indicate linear gain changes, and require a 5-bit multiply.
   1.378 +        // We will represent the two 4-bit fields of compr as follows:
   1.379 +        //   X0 X1 X2 X3 . Y4 Y5 Y6 Y7
   1.380 +        // The meaning of the X values is most simply described by considering X to represent a 4-bit
   1.381 +        // signed integer with values from –8 to +7. The gain indicated by X is then (X + 1) * 6.02 dB. The
   1.382 +        // following table shows this in detail.
   1.383 +
   1.384 +        // Meaning of 4 msb of compr
   1.385 +        //  7    +48.16 dB
   1.386 +        //  6    +42.14 dB
   1.387 +        //  5    +36.12 dB
   1.388 +        //  4    +30.10 dB
   1.389 +        //  3    +24.08 dB
   1.390 +        //  2    +18.06 dB
   1.391 +        //  1    +12.04 dB
   1.392 +        //  0     +6.02 dB
   1.393 +        // -1         0 dB
   1.394 +        // -2     –6.02 dB
   1.395 +        // -3    –12.04 dB
   1.396 +        // -4    –18.06 dB
   1.397 +        // -5    –24.08 dB
   1.398 +        // -6    –30.10 dB
   1.399 +        // -7    –36.12 dB
   1.400 +        // -8    –42.14 dB
   1.401 +
   1.402 +        $fourbit = str_pad(decbin(($compre & 0xF0) >> 4), 4, '0', STR_PAD_LEFT);
   1.403 +        if ($fourbit{0} == '1') {
   1.404 +            $log_gain = -8 + bindec(substr($fourbit, 1));
   1.405 +        } else {
   1.406 +            $log_gain = bindec(substr($fourbit, 1));
   1.407 +        }
   1.408 +        $log_gain = ($log_gain + 1) * (20 * log10(2));
   1.409 +
   1.410 +        // The value of Y is a linear representation of a gain change of up to –6 dB. Y is considered to
   1.411 +        // be an unsigned fractional integer, with a leading value of 1, or: 0.1 Y4 Y5 Y6 Y7 (base 2). Y can
   1.412 +        // represent values between 0.111112 (or 31/32) and 0.100002 (or 1/2). Thus, Y can represent gain
   1.413 +        // changes from –0.28 dB to –6.02 dB.
   1.414 +
   1.415 +        $lin_gain = (16 + ($compre & 0x0F)) / 32;
   1.416 +
   1.417 +        // The combination of X and Y values allows compr to indicate gain changes from
   1.418 +        //  48.16 – 0.28 = +47.89 dB, to
   1.419 +        // –42.14 – 6.02 = –48.16 dB.
   1.420 +
   1.421 +        return $log_gain - $lin_gain;
   1.422 +    }
   1.423 +
   1.424 +
   1.425 +
   1.426 +    public static function AC3roomTypeLookup($roomtyp) {
   1.427 +        
   1.428 +        static $lookup = array (
   1.429 +            0 => 'not indicated',
   1.430 +            1 => 'large room, X curve monitor',
   1.431 +            2 => 'small room, flat monitor',
   1.432 +            3 => 'reserved'
   1.433 +        );
   1.434 +        return (isset($lookup[$roomtyp]) ? $lookup[$roomtyp] : false);
   1.435 +    }
   1.436 +
   1.437 +
   1.438 +
   1.439 +    public static function AC3frameSizeLookup($frmsizecod, $fscod) {
   1.440 +        
   1.441 +        $padding     = (bool)($frmsizecod % 2);
   1.442 +        $frame_size_id =   floor($frmsizecod / 2);
   1.443 +
   1.444 +        static $lookup = array (
   1.445 +            0  => array (128, 138, 192),
   1.446 +            1  => array (40, 160, 174, 240),
   1.447 +            2  => array (48, 192, 208, 288),
   1.448 +            3  => array (56, 224, 242, 336),
   1.449 +            4  => array (64, 256, 278, 384),
   1.450 +            5  => array (80, 320, 348, 480),
   1.451 +            6  => array (96, 384, 416, 576),
   1.452 +            7  => array (112, 448, 486, 672),
   1.453 +            8  => array (128, 512, 556, 768),
   1.454 +            9  => array (160, 640, 696, 960),
   1.455 +            10 => array (192, 768, 834, 1152),
   1.456 +            11 => array (224, 896, 974, 1344),
   1.457 +            12 => array (256, 1024, 1114, 1536),
   1.458 +            13 => array (320, 1280, 1392, 1920),
   1.459 +            14 => array (384, 1536, 1670, 2304),
   1.460 +            15 => array (448, 1792, 1950, 2688),
   1.461 +            16 => array (512, 2048, 2228, 3072),
   1.462 +            17 => array (576, 2304, 2506, 3456),
   1.463 +            18 => array (640, 2560, 2786, 3840)
   1.464 +        );
   1.465 +        if (($fscod == 1) && $padding) {
   1.466 +            // frame lengths are padded by 1 word (16 bits) at 44100
   1.467 +            $lookup[$frmsizecod] += 2;
   1.468 +        }
   1.469 +        return (isset($lookup[$frame_size_id][$fscod]) ? $lookup[$frame_size_id][$fscod] : false);
   1.470 +    }
   1.471 +
   1.472 +
   1.473 +
   1.474 +    public static function AC3bitrateLookup($frmsizecod) {
   1.475 +        
   1.476 +        static $lookup = array (
   1.477 +            0  => 32000,
   1.478 +            1  => 40000,
   1.479 +            2  => 48000,
   1.480 +            3  => 56000,
   1.481 +            4  => 64000,
   1.482 +            5  => 80000,
   1.483 +            6  => 96000,
   1.484 +            7  => 112000,
   1.485 +            8  => 128000,
   1.486 +            9  => 160000,
   1.487 +            10 => 192000,
   1.488 +            11 => 224000,
   1.489 +            12 => 256000,
   1.490 +            13 => 320000,
   1.491 +            14 => 384000,
   1.492 +            15 => 448000,
   1.493 +            16 => 512000,
   1.494 +            17 => 576000,
   1.495 +            18 => 640000
   1.496 +        );
   1.497 +        $frame_size_id = floor($frmsizecod / 2);
   1.498 +        return (isset($lookup[$frame_size_id]) ? $lookup[$frame_size_id] : false);
   1.499 +    }
   1.500 +
   1.501 +}
   1.502 +
   1.503 +?>
   1.504 \ No newline at end of file