diff e2gallerypro/e2upload/Backend/Assets/getid3/module.audio.optimfrog.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.optimfrog.php	Mon Feb 22 08:02:39 2010 -0500
     1.3 @@ -0,0 +1,468 @@
     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.optimfrog.php                                           |
    1.21 +// | Module for analyzing OptimFROG Audio files                           |
    1.22 +// | dependencies: module.audio-video.riff.php                            |
    1.23 +// +----------------------------------------------------------------------+
    1.24 +//
    1.25 +// $Id: module.audio.optimfrog.php,v 1.3 2006/11/02 10:48:01 ah Exp $
    1.26 +
    1.27 +        
    1.28 +        
    1.29 +class getid3_optimfrog extends getid3_handler
    1.30 +{
    1.31 +
    1.32 +    public function Analyze() {
    1.33 +        
    1.34 +        $getid3 = $this->getid3;
    1.35 +        
    1.36 +        $getid3->include_module('audio-video.riff');
    1.37 +        
    1.38 +        $getid3->info['audio']['dataformat']   = 'ofr';
    1.39 +        $getid3->info['audio']['bitrate_mode'] = 'vbr';
    1.40 +        $getid3->info['audio']['lossless']     = true;
    1.41 +
    1.42 +        fseek($getid3->fp, $getid3->info['avdataoffset'], SEEK_SET);
    1.43 +        $ofr_header = fread($getid3->fp, 8);
    1.44 +        
    1.45 +        if (substr($ofr_header, 0, 5) == '*RIFF') {
    1.46 +            return $this->ParseOptimFROGheader42($getid3->fp, $getid3->info);
    1.47 +
    1.48 +        } elseif (substr($ofr_header, 0, 3) == 'OFR') {
    1.49 +            return $this->ParseOptimFROGheader45($getid3->fp, $getid3->info);
    1.50 +        }
    1.51 +        
    1.52 +        throw new getid3_exception('Expecting "*RIFF" or "OFR " at offset '.$getid3->info['avdataoffset'].', found "'.$ofr_header.'"');
    1.53 +    }
    1.54 +
    1.55 +
    1.56 +
    1.57 +    private function ParseOptimFROGheader42() {
    1.58 +        
    1.59 +        $getid3 = $this->getid3;
    1.60 +        
    1.61 +        // for fileformat of v4.21 and older
    1.62 +
    1.63 +        fseek($getid3->fp, $getid3->info['avdataoffset'], SEEK_SET);
    1.64 +        
    1.65 +        $ofr_header_data = fread($getid3->fp, 45);
    1.66 +        $getid3->info['avdataoffset'] = 45;
    1.67 +
    1.68 +        $ofr_encoder_version_raw   = getid3_lib::LittleEndian2Int(substr($ofr_header_data, 0, 1));
    1.69 +        $ofr_encoder_version_major = floor($ofr_encoder_version_raw / 10);
    1.70 +        $ofr_encoder_version_minor = $ofr_encoder_version_raw - ($ofr_encoder_version_major * 10);
    1.71 +        $riff_data                 = substr($ofr_header_data, 1, 44);
    1.72 +        $origna_riff_header_size   = getid3_lib::LittleEndian2Int(substr($riff_data,  4, 4)) +  8;
    1.73 +        $origna_riff_data_size     = getid3_lib::LittleEndian2Int(substr($riff_data, 40, 4)) + 44;
    1.74 +
    1.75 +        if ($origna_riff_header_size > $origna_riff_data_size) {
    1.76 +            $getid3->info['avdataend'] -= ($origna_riff_header_size - $origna_riff_data_size);
    1.77 +            fseek($getid3->fp, $getid3->info['avdataend'], SEEK_SET);
    1.78 +            $riff_data .= fread($getid3->fp, $origna_riff_header_size - $origna_riff_data_size);
    1.79 +        }
    1.80 +
    1.81 +        // move the data chunk after all other chunks (if any)
    1.82 +        // so that the RIFF parser doesn't see EOF when trying
    1.83 +        // to skip over the data chunk
    1.84 +        
    1.85 +        $riff_data = substr($riff_data, 0, 36).substr($riff_data, 44).substr($riff_data, 36, 8);
    1.86 +        
    1.87 +        // Save audio info key
    1.88 +        $saved_info_audio = $getid3->info['audio'];
    1.89 +
    1.90 +        // Instantiate riff module and analyze string
    1.91 +        $riff = new getid3_riff($getid3);
    1.92 +        $riff->AnalyzeString($riff_data);
    1.93 +        
    1.94 +        // Restore info key
    1.95 +        $getid3->info['audio'] = $saved_info_audio;
    1.96 +        
    1.97 +        $getid3->info['audio']['encoder']         = 'OptimFROG '.$ofr_encoder_version_major.'.'.$ofr_encoder_version_minor;
    1.98 +        $getid3->info['audio']['channels']        = $getid3->info['riff']['audio'][0]['channels'];
    1.99 +        $getid3->info['audio']['sample_rate']     = $getid3->info['riff']['audio'][0]['sample_rate'];
   1.100 +        $getid3->info['audio']['bits_per_sample'] = $getid3->info['riff']['audio'][0]['bits_per_sample'];
   1.101 +        $getid3->info['playtime_seconds']         = $origna_riff_data_size / ($getid3->info['audio']['channels'] * $getid3->info['audio']['sample_rate'] * ($getid3->info['audio']['bits_per_sample'] / 8));
   1.102 +        $getid3->info['audio']['bitrate']         = (($getid3->info['avdataend'] - $getid3->info['avdataoffset']) * 8) / $getid3->info['playtime_seconds'];
   1.103 +        
   1.104 +        $getid3->info['fileformat'] = 'ofr';
   1.105 +
   1.106 +        return true;
   1.107 +    }
   1.108 +
   1.109 +
   1.110 +
   1.111 +    private function ParseOptimFROGheader45() {
   1.112 +        
   1.113 +        $getid3 = $this->getid3;
   1.114 +        
   1.115 +        // for fileformat of v4.50a and higher
   1.116 +
   1.117 +        $riff_data = '';
   1.118 +        fseek($getid3->fp, $getid3->info['avdataoffset'], SEEK_SET);
   1.119 +        
   1.120 +        while (!feof($getid3->fp) && (ftell($getid3->fp) < $getid3->info['avdataend'])) {
   1.121 +        
   1.122 +            $block_offset = ftell($getid3->fp);
   1.123 +            $block_data   = fread($getid3->fp, 8);
   1.124 +            $offset       = 8;
   1.125 +            $block_name   =                  substr($block_data, 0, 4);
   1.126 +            $block_size   = getid3_lib::LittleEndian2Int(substr($block_data, 4, 4));
   1.127 +
   1.128 +            if ($block_name == 'OFRX') {
   1.129 +                $block_name = 'OFR ';
   1.130 +            }
   1.131 +            if (!isset($getid3->info['ofr'][$block_name])) {
   1.132 +                $getid3->info['ofr'][$block_name] = array ();
   1.133 +            }
   1.134 +            $info_ofr_this_block = &$getid3->info['ofr'][$block_name];
   1.135 +
   1.136 +            switch ($block_name) {
   1.137 +                case 'OFR ':
   1.138 +
   1.139 +                    // shortcut
   1.140 +                    $info_ofr_this_block['offset'] = $block_offset;
   1.141 +                    $info_ofr_this_block['size']   = $block_size;
   1.142 +
   1.143 +                    $getid3->info['audio']['encoder'] = 'OptimFROG 4.50 alpha';
   1.144 +                    switch ($block_size) {
   1.145 +                        case 12:
   1.146 +                        case 15:
   1.147 +                            // good
   1.148 +                            break;
   1.149 +
   1.150 +                        default:
   1.151 +                            $getid3->warning('"'.$block_name.'" contains more data than expected (expected 12 or 15 bytes, found '.$block_size.' bytes)');
   1.152 +                            break;
   1.153 +                    }
   1.154 +                    $block_data .= fread($getid3->fp, $block_size);
   1.155 +
   1.156 +                    $info_ofr_this_block['total_samples']      = getid3_lib::LittleEndian2Int(substr($block_data, $offset, 6));
   1.157 +                    $offset += 6;
   1.158 +                    
   1.159 +                    $info_ofr_this_block['raw']['sample_type'] = getid3_lib::LittleEndian2Int($block_data{$offset++});
   1.160 +                    $info_ofr_this_block['sample_type']        = $this->OptimFROGsampleTypeLookup($info_ofr_this_block['raw']['sample_type']);
   1.161 +                    
   1.162 +                    $info_ofr_this_block['channel_config']     = getid3_lib::LittleEndian2Int($block_data{$offset++});
   1.163 +                    $info_ofr_this_block['channels']           = $info_ofr_this_block['channel_config'];
   1.164 +
   1.165 +                    $info_ofr_this_block['sample_rate']        = getid3_lib::LittleEndian2Int(substr($block_data, $offset, 4));
   1.166 +                    $offset += 4;
   1.167 +
   1.168 +                    if ($block_size > 12) {
   1.169 +
   1.170 +                        // OFR 4.504b or higher
   1.171 +                        $info_ofr_this_block['channels']           = $this->OptimFROGchannelConfigNumChannelsLookup($info_ofr_this_block['channel_config']);
   1.172 +                        $info_ofr_this_block['raw']['encoder_id']  = getid3_lib::LittleEndian2Int(substr($block_data, $offset, 2));
   1.173 +                        $info_ofr_this_block['encoder']            = $this->OptimFROGencoderNameLookup($info_ofr_this_block['raw']['encoder_id']);
   1.174 +                        $offset += 2;
   1.175 +
   1.176 +                        $info_ofr_this_block['raw']['compression'] = getid3_lib::LittleEndian2Int($block_data{$offset++});
   1.177 +                        $info_ofr_this_block['compression']        = $this->OptimFROGcompressionLookup($info_ofr_this_block['raw']['compression']);
   1.178 +                        $info_ofr_this_block['speedup']            = $this->OptimFROGspeedupLookup($info_ofr_this_block['raw']['compression']);
   1.179 +
   1.180 +                        $getid3->info['audio']['encoder']         = 'OptimFROG '.$info_ofr_this_block['encoder'];
   1.181 +                        $getid3->info['audio']['encoder_options'] = '--mode '.$info_ofr_this_block['compression'];
   1.182 +
   1.183 +                        if ((($info_ofr_this_block['raw']['encoder_id'] & 0xF0) >> 4) == 7) { // v4.507
   1.184 +                            if (preg_match('/\.ofs$/i', $getid3->filename)) {
   1.185 +                                // OptimFROG DualStream format is lossy, but as of v4.507 there is no way to tell the difference
   1.186 +                                // between lossless and lossy other than the file extension.
   1.187 +                                $getid3->info['audio']['dataformat']   = 'ofs';
   1.188 +                                $getid3->info['audio']['lossless']     = true;
   1.189 +                            }
   1.190 +                        }
   1.191 +                    }
   1.192 +
   1.193 +                    $getid3->info['audio']['channels']        = $info_ofr_this_block['channels'];
   1.194 +                    $getid3->info['audio']['sample_rate']     = $info_ofr_this_block['sample_rate'];
   1.195 +                    $getid3->info['audio']['bits_per_sample'] = $this->OptimFROGbitsPerSampleTypeLookup($info_ofr_this_block['raw']['sample_type']);
   1.196 +                    break;
   1.197 +
   1.198 +
   1.199 +                case 'COMP':
   1.200 +                    // unlike other block types, there CAN be multiple COMP blocks
   1.201 +
   1.202 +                    $comp_data['offset'] = $block_offset;
   1.203 +                    $comp_data['size']   = $block_size;
   1.204 +
   1.205 +                    if ($getid3->info['avdataoffset'] == 0) {
   1.206 +                        $getid3->info['avdataoffset'] = $block_offset;
   1.207 +                    }
   1.208 +
   1.209 +                    // Only interested in first 14 bytes (only first 12 needed for v4.50 alpha), not actual audio data
   1.210 +                    $block_data .= fread($getid3->fp, 14);
   1.211 +                    fseek($getid3->fp, $block_size - 14, SEEK_CUR);
   1.212 +
   1.213 +                    $comp_data['crc_32']                       = getid3_lib::LittleEndian2Int(substr($block_data, $offset, 4));
   1.214 +                    $offset += 4;
   1.215 +                    
   1.216 +                    $comp_data['sample_count']                 = getid3_lib::LittleEndian2Int(substr($block_data, $offset, 4));
   1.217 +                    $offset += 4;
   1.218 +                    
   1.219 +                    $comp_data['raw']['sample_type']           = getid3_lib::LittleEndian2Int($block_data{$offset++});
   1.220 +                    $comp_data['sample_type']                  = $this->OptimFROGsampleTypeLookup($comp_data['raw']['sample_type']);
   1.221 +                    
   1.222 +                    $comp_data['raw']['channel_configuration'] = getid3_lib::LittleEndian2Int($block_data{$offset++});
   1.223 +                    $comp_data['channel_configuration']        = $this->OptimFROGchannelConfigurationLookup($comp_data['raw']['channel_configuration']);
   1.224 +
   1.225 +                    $comp_data['raw']['algorithm_id']          = getid3_lib::LittleEndian2Int(substr($block_data, $offset, 2));
   1.226 +                    $offset += 2;
   1.227 +
   1.228 +                    if ($getid3->info['ofr']['OFR ']['size'] > 12) {
   1.229 +
   1.230 +                        // OFR 4.504b or higher
   1.231 +                        $comp_data['raw']['encoder_id']        = getid3_lib::LittleEndian2Int(substr($block_data, $offset, 2));
   1.232 +                        $comp_data['encoder']                  = $this->OptimFROGencoderNameLookup($comp_data['raw']['encoder_id']);
   1.233 +                        $offset += 2;
   1.234 +                    }
   1.235 +
   1.236 +                    if ($comp_data['crc_32'] == 0x454E4F4E) {
   1.237 +                        // ASCII value of 'NONE' - placeholder value in v4.50a
   1.238 +                        $comp_data['crc_32'] = false;
   1.239 +                    }
   1.240 +
   1.241 +                    $info_ofr_this_block[] = $comp_data;
   1.242 +                    break;
   1.243 +
   1.244 +                case 'HEAD':
   1.245 +                    $info_ofr_this_block['offset'] = $block_offset;
   1.246 +                    $info_ofr_this_block['size']   = $block_size;
   1.247 +
   1.248 +                    $riff_data .= fread($getid3->fp, $block_size);
   1.249 +                    break;
   1.250 +
   1.251 +                case 'TAIL':
   1.252 +                    $info_ofr_this_block['offset'] = $block_offset;
   1.253 +                    $info_ofr_this_block['size']   = $block_size;
   1.254 +
   1.255 +                    if ($block_size > 0) {
   1.256 +                        $riff_data .= fread($getid3->fp, $block_size);
   1.257 +                    }
   1.258 +                    break;
   1.259 +
   1.260 +                case 'RECV':
   1.261 +                    // block contains no useful meta data - simply note and skip
   1.262 +
   1.263 +                    $info_ofr_this_block['offset'] = $block_offset;
   1.264 +                    $info_ofr_this_block['size']   = $block_size;
   1.265 +
   1.266 +                    fseek($getid3->fp, $block_size, SEEK_CUR);
   1.267 +                    break;
   1.268 +
   1.269 +
   1.270 +                case 'APET':
   1.271 +                    // APEtag v2
   1.272 +
   1.273 +                    $info_ofr_this_block['offset'] = $block_offset;
   1.274 +                    $info_ofr_this_block['size']   = $block_size;
   1.275 +                    $getid3->warning('APEtag processing inside OptimFROG not supported in this version ('.GETID3_VERSION.') of getID3()');
   1.276 +
   1.277 +                    fseek($getid3->fp, $block_size, SEEK_CUR);
   1.278 +                    break;
   1.279 +
   1.280 +
   1.281 +                case 'MD5 ':
   1.282 +                    // APEtag v2
   1.283 +
   1.284 +                    $info_ofr_this_block['offset'] = $block_offset;
   1.285 +                    $info_ofr_this_block['size']   = $block_size;
   1.286 +
   1.287 +                    if ($block_size == 16) {
   1.288 +
   1.289 +                        $info_ofr_this_block['md5_binary'] = fread($getid3->fp, $block_size);
   1.290 +                        $info_ofr_this_block['md5_string'] = getid3_lib::PrintHexBytes($info_ofr_this_block['md5_binary'], true, false, false);
   1.291 +                        $getid3->info['md5_data_source']   = $info_ofr_this_block['md5_string'];
   1.292 +
   1.293 +                    } else {
   1.294 +
   1.295 +                        $getid3->warning('Expecting block size of 16 in "MD5 " chunk, found '.$block_size.' instead');
   1.296 +                        fseek($getid3->fp, $block_size, SEEK_CUR);
   1.297 +
   1.298 +                    }
   1.299 +                    break;
   1.300 +
   1.301 +
   1.302 +                default:
   1.303 +                    $info_ofr_this_block['offset'] = $block_offset;
   1.304 +                    $info_ofr_this_block['size']   = $block_size;
   1.305 +
   1.306 +                    $getid3->warning('Unhandled OptimFROG block type "'.$block_name.'" at offset '.$info_ofr_this_block['offset']);
   1.307 +                    fseek($getid3->fp, $block_size, SEEK_CUR);
   1.308 +                    break;
   1.309 +            }
   1.310 +        }
   1.311 +        
   1.312 +        if (isset($getid3->info['ofr']['TAIL']['offset'])) {
   1.313 +            $getid3->info['avdataend'] = $getid3->info['ofr']['TAIL']['offset'];
   1.314 +        }
   1.315 +
   1.316 +        $getid3->info['playtime_seconds'] = (float)$getid3->info['ofr']['OFR ']['total_samples'] / ($getid3->info['audio']['channels'] * $getid3->info['audio']['sample_rate']);
   1.317 +        $getid3->info['audio']['bitrate'] = (($getid3->info['avdataend'] - $getid3->info['avdataoffset']) * 8) / $getid3->info['playtime_seconds'];
   1.318 +
   1.319 +        // move the data chunk after all other chunks (if any)
   1.320 +        // so that the RIFF parser doesn't see EOF when trying
   1.321 +        // to skip over the data chunk
   1.322 +        
   1.323 +        $riff_data = substr($riff_data, 0, 36).substr($riff_data, 44).substr($riff_data, 36, 8);
   1.324 +        
   1.325 +        // Save audio info key
   1.326 +        $saved_info_audio = $getid3->info['audio'];
   1.327 +
   1.328 +        // Instantiate riff module and analyze string
   1.329 +        $riff = new getid3_riff($getid3);
   1.330 +        $riff->AnalyzeString($riff_data);
   1.331 +        
   1.332 +        // Restore info key
   1.333 +        $getid3->info['audio'] = $saved_info_audio;
   1.334 +        
   1.335 +        $getid3->info['fileformat'] = 'ofr';
   1.336 +
   1.337 +        return true;
   1.338 +    }
   1.339 +
   1.340 +
   1.341 +
   1.342 +    public static function OptimFROGsampleTypeLookup($sample_type) {
   1.343 +        
   1.344 +        static $lookup = array (
   1.345 +            0  => 'unsigned int (8-bit)',
   1.346 +            1  => 'signed int (8-bit)',
   1.347 +            2  => 'unsigned int (16-bit)',
   1.348 +            3  => 'signed int (16-bit)',
   1.349 +            4  => 'unsigned int (24-bit)',
   1.350 +            5  => 'signed int (24-bit)',
   1.351 +            6  => 'unsigned int (32-bit)',
   1.352 +            7  => 'signed int (32-bit)',
   1.353 +            8  => 'float 0.24 (32-bit)',
   1.354 +            9  => 'float 16.8 (32-bit)',
   1.355 +            10 => 'float 24.0 (32-bit)'
   1.356 +        );
   1.357 +        
   1.358 +        return @$lookup[$sample_type];
   1.359 +    }
   1.360 +
   1.361 +
   1.362 +
   1.363 +    public static function OptimFROGbitsPerSampleTypeLookup($sample_type) {
   1.364 +
   1.365 +        static $lookup = array (
   1.366 +            0  => 8,
   1.367 +            1  => 8,
   1.368 +            2  => 16,
   1.369 +            3  => 16,
   1.370 +            4  => 24,
   1.371 +            5  => 24,
   1.372 +            6  => 32,
   1.373 +            7  => 32,
   1.374 +            8  => 32,
   1.375 +            9  => 32,
   1.376 +            10 => 32
   1.377 +        );
   1.378 +        
   1.379 +        return @$lookup[$sample_type];
   1.380 +    }
   1.381 +
   1.382 +
   1.383 +
   1.384 +    public static function OptimFROGchannelConfigurationLookup($channel_configuration) {
   1.385 +        
   1.386 +        static $lookup = array (
   1.387 +            0 => 'mono',
   1.388 +            1 => 'stereo'
   1.389 +        );
   1.390 +        
   1.391 +        return @$lookup[$channel_configuration];
   1.392 +    }
   1.393 +
   1.394 +
   1.395 +
   1.396 +    public static function OptimFROGchannelConfigNumChannelsLookup($channel_configuration) {
   1.397 +
   1.398 +        static $lookup = array (
   1.399 +            0 => 1,
   1.400 +            1 => 2
   1.401 +        );
   1.402 +        
   1.403 +        return @$lookup[$channel_configuration];
   1.404 +    }
   1.405 +
   1.406 +
   1.407 +
   1.408 +    public static function OptimFROGencoderNameLookup($encoder_id) {
   1.409 +
   1.410 +        // version = (encoderID >> 4) + 4500
   1.411 +        // system  =  encoderID & 0xF
   1.412 +
   1.413 +        $encoder_version   = number_format(((($encoder_id & 0xF0) >> 4) + 4500) / 1000, 3);
   1.414 +        $encoder_system_id = ($encoder_id & 0x0F);
   1.415 +
   1.416 +        static $lookup = array (
   1.417 +            0x00 => 'Windows console',
   1.418 +            0x01 => 'Linux console',
   1.419 +            0x0F => 'unknown'
   1.420 +        );
   1.421 +        return $encoder_version.' ('.(isset($lookup[$encoder_system_id]) ? $lookup[$encoder_system_id] : 'undefined encoder type (0x'.dechex($encoder_system_id).')').')';
   1.422 +    }
   1.423 +
   1.424 +
   1.425 +
   1.426 +    public static function OptimFROGcompressionLookup($compression_id) {
   1.427 +
   1.428 +        // mode    = compression >> 3
   1.429 +        // speedup = compression & 0x07
   1.430 +
   1.431 +        $compression_mode_id    = ($compression_id & 0xF8) >> 3;
   1.432 +        //$compression_speed_up_id = ($compression_id & 0x07);
   1.433 +
   1.434 +        static $lookup = array (
   1.435 +            0x00 => 'fast',
   1.436 +            0x01 => 'normal',
   1.437 +            0x02 => 'high',
   1.438 +            0x03 => 'extra', // extranew (some versions)
   1.439 +            0x04 => 'best',  // bestnew (some versions)
   1.440 +            0x05 => 'ultra',
   1.441 +            0x06 => 'insane',
   1.442 +            0x07 => 'highnew',
   1.443 +            0x08 => 'extranew',
   1.444 +            0x09 => 'bestnew'
   1.445 +        );
   1.446 +        return (isset($lookup[$compression_mode_id]) ? $lookup[$compression_mode_id] : 'undefined mode (0x'.str_pad(dechex($compression_mode_id), 2, '0', STR_PAD_LEFT).')');
   1.447 +    }
   1.448 +
   1.449 +
   1.450 +
   1.451 +    public static function OptimFROGspeedupLookup($compression_id) {
   1.452 +
   1.453 +        // mode    = compression >> 3
   1.454 +        // speedup = compression & 0x07
   1.455 +
   1.456 +        //$compression_mode_id    = ($compression_id & 0xF8) >> 3;
   1.457 +        $compression_speed_up_id = ($compression_id & 0x07);
   1.458 +
   1.459 +        static $lookup = array (
   1.460 +            0x00 => '1x',
   1.461 +            0x01 => '2x',
   1.462 +            0x02 => '4x'
   1.463 +        );
   1.464 +
   1.465 +        return (isset($lookup[$compression_speed_up_id]) ? $lookup[$compression_speed_up_id] : 'undefined mode (0x'.dechex($compression_speed_up_id));
   1.466 +    }
   1.467 +
   1.468 +}
   1.469 +
   1.470 +
   1.471 +?>
   1.472 \ No newline at end of file