diff e2gallerypro/e2upload/Backend/Assets/getid3/module.audio.mp3.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.mp3.php	Mon Feb 22 08:02:39 2010 -0500
     1.3 @@ -0,0 +1,1696 @@
     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.mp3.php                                                 |
    1.21 +// | Module for analyzing MPEG Audio Layer 1,2,3 files.                   |
    1.22 +// | dependencies: none                                                   |
    1.23 +// +----------------------------------------------------------------------+
    1.24 +//
    1.25 +// $Id: module.audio.mp3.php,v 1.10 2006/11/16 22:57:57 ah Exp $
    1.26 +
    1.27 +
    1.28 +
    1.29 +class getid3_mp3 extends getid3_handler
    1.30 +{
    1.31 +    // Number of frames to scan to determine if MPEG-audio sequence is valid.
    1.32 +    // Lower this number to 5-20 for faster scanning
    1.33 +    // Increase this number to 50+ for most accurate detection of valid VBR/CBR mpeg-audio streams
    1.34 +    const VALID_CHECK_FRAMES = 35;
    1.35 +    
    1.36 +
    1.37 +    public function Analyze() {
    1.38 +
    1.39 +        $this->getAllMPEGInfo($this->getid3->fp, $this->getid3->info);
    1.40 +
    1.41 +        return true;   
    1.42 +    }
    1.43 +    
    1.44 +    
    1.45 +    public function AnalyzeMPEGaudioInfo() {
    1.46 +        
    1.47 +        $this->getOnlyMPEGaudioInfo($this->getid3->fp, $this->getid3->info, $this->getid3->info['avdataoffset'], false);
    1.48 +    }
    1.49 +
    1.50 +
    1.51 +    public function getAllMPEGInfo(&$fd, &$info) {
    1.52 +
    1.53 +        $this->getOnlyMPEGaudioInfo($fd, $info, 0 + $info['avdataoffset']);
    1.54 +
    1.55 +        if (isset($info['mpeg']['audio']['bitrate_mode'])) {
    1.56 +            $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
    1.57 +        }
    1.58 +
    1.59 +        if (((isset($info['id3v2']['headerlength']) && ($info['avdataoffset'] > $info['id3v2']['headerlength'])) || (!isset($info['id3v2']) && ($info['avdataoffset'] > 0)))) {
    1.60 +
    1.61 +            $synch_offset_warning = 'Unknown data before synch ';
    1.62 +            if (isset($info['id3v2']['headerlength'])) {
    1.63 +                $synch_offset_warning .= '(ID3v2 header ends at '.$info['id3v2']['headerlength'].', then '.($info['avdataoffset'] - $info['id3v2']['headerlength']).' bytes garbage, ';
    1.64 +            } else {
    1.65 +                $synch_offset_warning .= '(should be at beginning of file, ';
    1.66 +            }
    1.67 +            $synch_offset_warning .= 'synch detected at '.$info['avdataoffset'].')';
    1.68 +            if ($info['audio']['bitrate_mode'] == 'cbr') {
    1.69 +
    1.70 +                if (!empty($info['id3v2']['headerlength']) && (($info['avdataoffset'] - $info['id3v2']['headerlength']) == $info['mpeg']['audio']['framelength'])) {
    1.71 +
    1.72 +                    $synch_offset_warning .= '. This is a known problem with some versions of LAME (3.90-3.92) DLL in CBR mode.';
    1.73 +                    $info['audio']['codec'] = 'LAME';
    1.74 +                    $current_data_lame_version_string = 'LAME3.';
    1.75 +
    1.76 +                } elseif (empty($info['id3v2']['headerlength']) && ($info['avdataoffset'] == $info['mpeg']['audio']['framelength'])) {
    1.77 +
    1.78 +                    $synch_offset_warning .= '. This is a known problem with some versions of LAME (3.90 - 3.92) DLL in CBR mode.';
    1.79 +                    $info['audio']['codec'] = 'LAME';
    1.80 +                    $current_data_lame_version_string = 'LAME3.';
    1.81 +
    1.82 +                }
    1.83 +
    1.84 +            }
    1.85 +            $this->getid3->warning($synch_offset_warning);
    1.86 +
    1.87 +        }
    1.88 +
    1.89 +        if (isset($info['mpeg']['audio']['LAME'])) {
    1.90 +            $info['audio']['codec'] = 'LAME';
    1.91 +            if (!empty($info['mpeg']['audio']['LAME']['long_version'])) {
    1.92 +                $info['audio']['encoder'] = rtrim($info['mpeg']['audio']['LAME']['long_version'], "\x00");
    1.93 +            } elseif (!empty($info['mpeg']['audio']['LAME']['short_version'])) {
    1.94 +                $info['audio']['encoder'] = rtrim($info['mpeg']['audio']['LAME']['short_version'], "\x00");
    1.95 +            }
    1.96 +        }
    1.97 +
    1.98 +        $current_data_lame_version_string = (!empty($current_data_lame_version_string) ? $current_data_lame_version_string : @$info['audio']['encoder']);
    1.99 +        if (!empty($current_data_lame_version_string) && (substr($current_data_lame_version_string, 0, 6) == 'LAME3.') && !preg_match('[0-9\)]', substr($current_data_lame_version_string, -1))) {
   1.100 +            // a version number of LAME that does not end with a number like "LAME3.92"
   1.101 +            // or with a closing parenthesis like "LAME3.88 (alpha)"
   1.102 +            // or a version of LAME with the LAMEtag-not-filled-in-DLL-mode bug (3.90-3.92)
   1.103 +
   1.104 +            // not sure what the actual last frame length will be, but will be less than or equal to 1441
   1.105 +            $possibly_longer_lame_version_frame_length = 1441;
   1.106 +
   1.107 +            // Not sure what version of LAME this is - look in padding of last frame for longer version string
   1.108 +            $possible_lame_version_string_offset = $info['avdataend'] - $possibly_longer_lame_version_frame_length;
   1.109 +            fseek($fd, $possible_lame_version_string_offset);
   1.110 +            $possibly_longer_lame_version_data = fread($fd, $possibly_longer_lame_version_frame_length);
   1.111 +            switch (substr($current_data_lame_version_string, -1)) {
   1.112 +                case 'a':
   1.113 +                case 'b':
   1.114 +                    // "LAME3.94a" will have a longer version string of "LAME3.94 (alpha)" for example
   1.115 +                    // need to trim off "a" to match longer string
   1.116 +                    $current_data_lame_version_string = substr($current_data_lame_version_string, 0, -1);
   1.117 +                    break;
   1.118 +            }
   1.119 +            if (($possibly_longer_lame_version_string = strstr($possibly_longer_lame_version_data, $current_data_lame_version_string)) !== false) {
   1.120 +                if (substr($possibly_longer_lame_version_string, 0, strlen($current_data_lame_version_string)) == $current_data_lame_version_string) {
   1.121 +                    $possibly_longer_lame_version_new_string = substr($possibly_longer_lame_version_string, 0, strspn($possibly_longer_lame_version_string, 'LAME0123456789., (abcdefghijklmnopqrstuvwxyzJFSOND)')); //"LAME3.90.3"  "LAME3.87 (beta 1, Sep 27 2000)" "LAME3.88 (beta)"
   1.122 +                    if (strlen($possibly_longer_lame_version_new_string) > strlen(@$info['audio']['encoder'])) {
   1.123 +                        $info['audio']['encoder'] = $possibly_longer_lame_version_new_string;
   1.124 +                    }
   1.125 +                }
   1.126 +            }
   1.127 +        }
   1.128 +        if (!empty($info['audio']['encoder'])) {
   1.129 +            $info['audio']['encoder'] = rtrim($info['audio']['encoder'], "\x00 ");
   1.130 +        }
   1.131 +
   1.132 +        switch (@$info['mpeg']['audio']['layer']) {
   1.133 +            case 1:
   1.134 +            case 2:
   1.135 +                $info['audio']['dataformat'] = 'mp'.$info['mpeg']['audio']['layer'];
   1.136 +                break;
   1.137 +        }
   1.138 +        if (@$info['fileformat'] == 'mp3') {
   1.139 +            switch ($info['audio']['dataformat']) {
   1.140 +                case 'mp1':
   1.141 +                case 'mp2':
   1.142 +                case 'mp3':
   1.143 +                    $info['fileformat'] = $info['audio']['dataformat'];
   1.144 +                    break;
   1.145 +
   1.146 +                default:
   1.147 +                    $this->getid3->warning('Expecting [audio][dataformat] to be mp1/mp2/mp3 when fileformat == mp3, [audio][dataformat] actually "'.$info['audio']['dataformat'].'"');
   1.148 +                    break;
   1.149 +            }
   1.150 +        }
   1.151 +        
   1.152 +        $info['mime_type']         = 'audio/mpeg';
   1.153 +        $info['audio']['lossless'] = false;
   1.154 +
   1.155 +        // Calculate playtime
   1.156 +        if (!isset($info['playtime_seconds']) && isset($info['audio']['bitrate']) && ($info['audio']['bitrate'] > 0)) {
   1.157 +            $info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset']) * 8 / $info['audio']['bitrate'];
   1.158 +        }
   1.159 +
   1.160 +        $info['audio']['encoder_options'] = getid3_mp3::GuessEncoderOptions($info);
   1.161 +
   1.162 +        return true;
   1.163 +    }
   1.164 +
   1.165 +
   1.166 +
   1.167 +    public static function GuessEncoderOptions(&$info) {
   1.168 +        // shortcuts
   1.169 +        if (!empty($info['mpeg']['audio'])) {
   1.170 +            $thisfile_mpeg_audio = &$info['mpeg']['audio'];
   1.171 +            if (!empty($thisfile_mpeg_audio['LAME'])) {
   1.172 +                $thisfile_mpeg_audio_lame = &$thisfile_mpeg_audio['LAME'];
   1.173 +            }
   1.174 +        }
   1.175 +
   1.176 +        $encoder_options = '';
   1.177 +        static $named_preset_bitrates = array (16, 24, 40, 56, 112, 128, 160, 192, 256);
   1.178 +
   1.179 +        if ((@$thisfile_mpeg_audio['VBR_method'] == 'Fraunhofer') && !empty($thisfile_mpeg_audio['VBR_quality'])) {
   1.180 +
   1.181 +            $encoder_options = 'VBR q'.$thisfile_mpeg_audio['VBR_quality'];
   1.182 +
   1.183 +        } elseif (!empty($thisfile_mpeg_audio_lame['preset_used']) && (!in_array($thisfile_mpeg_audio_lame['preset_used_id'], $named_preset_bitrates))) {
   1.184 +
   1.185 +            $encoder_options = $thisfile_mpeg_audio_lame['preset_used'];
   1.186 +
   1.187 +        } elseif (!empty($thisfile_mpeg_audio_lame['vbr_quality'])) {
   1.188 +
   1.189 +            static $known_encoder_values = array ();
   1.190 +            if (empty($known_encoder_values)) {
   1.191 +
   1.192 +                //$known_encoder_values[abrbitrate_minbitrate][vbr_quality][raw_vbr_method][raw_noise_shaping][raw_stereo_mode][ath_type][lowpass_frequency] = 'preset name';
   1.193 +                $known_encoder_values[0xFF][58][1][1][3][2][20500] = '--alt-preset insane';        // 3.90,   3.90.1, 3.92
   1.194 +                $known_encoder_values[0xFF][58][1][1][3][2][20600] = '--alt-preset insane';        // 3.90.2, 3.90.3, 3.91
   1.195 +                $known_encoder_values[0xFF][57][1][1][3][4][20500] = '--alt-preset insane';        // 3.94,   3.95
   1.196 +                $known_encoder_values['**'][78][3][2][3][2][19500] = '--alt-preset extreme';       // 3.90,   3.90.1, 3.92
   1.197 +                $known_encoder_values['**'][78][3][2][3][2][19600] = '--alt-preset extreme';       // 3.90.2, 3.91
   1.198 +                $known_encoder_values['**'][78][3][1][3][2][19600] = '--alt-preset extreme';       // 3.90.3
   1.199 +                $known_encoder_values['**'][78][4][2][3][2][19500] = '--alt-preset fast extreme';  // 3.90,   3.90.1, 3.92
   1.200 +                $known_encoder_values['**'][78][4][2][3][2][19600] = '--alt-preset fast extreme';  // 3.90.2, 3.90.3, 3.91
   1.201 +                $known_encoder_values['**'][78][3][2][3][4][19000] = '--alt-preset standard';      // 3.90,   3.90.1, 3.90.2, 3.91, 3.92
   1.202 +                $known_encoder_values['**'][78][3][1][3][4][19000] = '--alt-preset standard';      // 3.90.3
   1.203 +                $known_encoder_values['**'][78][4][2][3][4][19000] = '--alt-preset fast standard'; // 3.90,   3.90.1, 3.90.2, 3.91, 3.92
   1.204 +                $known_encoder_values['**'][78][4][1][3][4][19000] = '--alt-preset fast standard'; // 3.90.3
   1.205 +                $known_encoder_values['**'][88][4][1][3][3][19500] = '--r3mix';                    // 3.90,   3.90.1, 3.92
   1.206 +                $known_encoder_values['**'][88][4][1][3][3][19600] = '--r3mix';                    // 3.90.2, 3.90.3, 3.91
   1.207 +                $known_encoder_values['**'][67][4][1][3][4][18000] = '--r3mix';                    // 3.94,   3.95
   1.208 +                $known_encoder_values['**'][68][3][2][3][4][18000] = '--alt-preset medium';        // 3.90.3
   1.209 +                $known_encoder_values['**'][68][4][2][3][4][18000] = '--alt-preset fast medium';   // 3.90.3
   1.210 +
   1.211 +                $known_encoder_values[0xFF][99][1][1][1][2][0]     = '--preset studio';            // 3.90,   3.90.1, 3.90.2, 3.91, 3.92
   1.212 +                $known_encoder_values[0xFF][58][2][1][3][2][20600] = '--preset studio';            // 3.90.3, 3.93.1
   1.213 +                $known_encoder_values[0xFF][58][2][1][3][2][20500] = '--preset studio';            // 3.93
   1.214 +                $known_encoder_values[0xFF][57][2][1][3][4][20500] = '--preset studio';            // 3.94,   3.95
   1.215 +                $known_encoder_values[0xC0][88][1][1][1][2][0]     = '--preset cd';                // 3.90,   3.90.1, 3.90.2,   3.91, 3.92
   1.216 +                $known_encoder_values[0xC0][58][2][2][3][2][19600] = '--preset cd';                // 3.90.3, 3.93.1
   1.217 +                $known_encoder_values[0xC0][58][2][2][3][2][19500] = '--preset cd';                // 3.93
   1.218 +                $known_encoder_values[0xC0][57][2][1][3][4][19500] = '--preset cd';                // 3.94,   3.95
   1.219 +                $known_encoder_values[0xA0][78][1][1][3][2][18000] = '--preset hifi';              // 3.90,   3.90.1, 3.90.2,   3.91, 3.92
   1.220 +                $known_encoder_values[0xA0][58][2][2][3][2][18000] = '--preset hifi';              // 3.90.3, 3.93,   3.93.1
   1.221 +                $known_encoder_values[0xA0][57][2][1][3][4][18000] = '--preset hifi';              // 3.94,   3.95
   1.222 +                $known_encoder_values[0x80][67][1][1][3][2][18000] = '--preset tape';              // 3.90,   3.90.1, 3.90.2,   3.91, 3.92
   1.223 +                $known_encoder_values[0x80][67][1][1][3][2][15000] = '--preset radio';             // 3.90,   3.90.1, 3.90.2,   3.91, 3.92
   1.224 +                $known_encoder_values[0x70][67][1][1][3][2][15000] = '--preset fm';                // 3.90,   3.90.1, 3.90.2,   3.91, 3.92
   1.225 +                $known_encoder_values[0x70][58][2][2][3][2][16000] = '--preset tape/radio/fm';     // 3.90.3, 3.93,   3.93.1
   1.226 +                $known_encoder_values[0x70][57][2][1][3][4][16000] = '--preset tape/radio/fm';     // 3.94,   3.95
   1.227 +                $known_encoder_values[0x38][58][2][2][0][2][10000] = '--preset voice';             // 3.90.3, 3.93,   3.93.1
   1.228 +                $known_encoder_values[0x38][57][2][1][0][4][15000] = '--preset voice';             // 3.94,   3.95
   1.229 +                $known_encoder_values[0x38][57][2][1][0][4][16000] = '--preset voice';             // 3.94a14
   1.230 +                $known_encoder_values[0x28][65][1][1][0][2][7500]  = '--preset mw-us';             // 3.90,   3.90.1, 3.92
   1.231 +                $known_encoder_values[0x28][65][1][1][0][2][7600]  = '--preset mw-us';             // 3.90.2, 3.91
   1.232 +                $known_encoder_values[0x28][58][2][2][0][2][7000]  = '--preset mw-us';             // 3.90.3, 3.93,   3.93.1
   1.233 +                $known_encoder_values[0x28][57][2][1][0][4][10500] = '--preset mw-us';             // 3.94,   3.95
   1.234 +                $known_encoder_values[0x28][57][2][1][0][4][11200] = '--preset mw-us';             // 3.94a14
   1.235 +                $known_encoder_values[0x28][57][2][1][0][4][8800]  = '--preset mw-us';             // 3.94a15
   1.236 +                $known_encoder_values[0x18][58][2][2][0][2][4000]  = '--preset phon+/lw/mw-eu/sw'; // 3.90.3, 3.93.1
   1.237 +                $known_encoder_values[0x18][58][2][2][0][2][3900]  = '--preset phon+/lw/mw-eu/sw'; // 3.93
   1.238 +                $known_encoder_values[0x18][57][2][1][0][4][5900]  = '--preset phon+/lw/mw-eu/sw'; // 3.94,   3.95
   1.239 +                $known_encoder_values[0x18][57][2][1][0][4][6200]  = '--preset phon+/lw/mw-eu/sw'; // 3.94a14
   1.240 +                $known_encoder_values[0x18][57][2][1][0][4][3200]  = '--preset phon+/lw/mw-eu/sw'; // 3.94a15
   1.241 +                $known_encoder_values[0x10][58][2][2][0][2][3800]  = '--preset phone';             // 3.90.3, 3.93.1
   1.242 +                $known_encoder_values[0x10][58][2][2][0][2][3700]  = '--preset phone';             // 3.93
   1.243 +                $known_encoder_values[0x10][57][2][1][0][4][5600]  = '--preset phone';             // 3.94,   3.95
   1.244 +            }
   1.245 +
   1.246 +            if (isset($known_encoder_values[$thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate']][$thisfile_mpeg_audio_lame['vbr_quality']][$thisfile_mpeg_audio_lame['raw']['vbr_method']][$thisfile_mpeg_audio_lame['raw']['noise_shaping']][$thisfile_mpeg_audio_lame['raw']['stereo_mode']][$thisfile_mpeg_audio_lame['ath_type']][$thisfile_mpeg_audio_lame['lowpass_frequency']])) {
   1.247 +
   1.248 +                $encoder_options = $known_encoder_values[$thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate']][$thisfile_mpeg_audio_lame['vbr_quality']][$thisfile_mpeg_audio_lame['raw']['vbr_method']][$thisfile_mpeg_audio_lame['raw']['noise_shaping']][$thisfile_mpeg_audio_lame['raw']['stereo_mode']][$thisfile_mpeg_audio_lame['ath_type']][$thisfile_mpeg_audio_lame['lowpass_frequency']];
   1.249 +
   1.250 +            } elseif (isset($known_encoder_values['**'][$thisfile_mpeg_audio_lame['vbr_quality']][$thisfile_mpeg_audio_lame['raw']['vbr_method']][$thisfile_mpeg_audio_lame['raw']['noise_shaping']][$thisfile_mpeg_audio_lame['raw']['stereo_mode']][$thisfile_mpeg_audio_lame['ath_type']][$thisfile_mpeg_audio_lame['lowpass_frequency']])) {
   1.251 +
   1.252 +                $encoder_options = $known_encoder_values['**'][$thisfile_mpeg_audio_lame['vbr_quality']][$thisfile_mpeg_audio_lame['raw']['vbr_method']][$thisfile_mpeg_audio_lame['raw']['noise_shaping']][$thisfile_mpeg_audio_lame['raw']['stereo_mode']][$thisfile_mpeg_audio_lame['ath_type']][$thisfile_mpeg_audio_lame['lowpass_frequency']];
   1.253 +
   1.254 +            } elseif ($info['audio']['bitrate_mode'] == 'vbr') {
   1.255 +
   1.256 +                // http://gabriel.mp3-tech.org/mp3infotag.html
   1.257 +                // int    Quality = (100 - 10 * gfp->VBR_q - gfp->quality)h
   1.258 +
   1.259 +
   1.260 +                $lame_v_value = 10 - ceil($thisfile_mpeg_audio_lame['vbr_quality'] / 10);
   1.261 +                $lame_q_value = 100 - $thisfile_mpeg_audio_lame['vbr_quality'] - ($lame_v_value * 10);
   1.262 +                $encoder_options = '-V'.$lame_v_value.' -q'.$lame_q_value;
   1.263 +
   1.264 +            } elseif ($info['audio']['bitrate_mode'] == 'cbr') {
   1.265 +
   1.266 +                $encoder_options = strtoupper($info['audio']['bitrate_mode']).ceil($info['audio']['bitrate'] / 1000);
   1.267 +
   1.268 +            } else {
   1.269 +
   1.270 +                $encoder_options = strtoupper($info['audio']['bitrate_mode']);
   1.271 +
   1.272 +            }
   1.273 +
   1.274 +        } elseif (!empty($thisfile_mpeg_audio_lame['bitrate_abr'])) {
   1.275 +
   1.276 +            $encoder_options = 'ABR'.$thisfile_mpeg_audio_lame['bitrate_abr'];
   1.277 +
   1.278 +        } elseif (!empty($info['audio']['bitrate'])) {
   1.279 +
   1.280 +            if ($info['audio']['bitrate_mode'] == 'cbr') {
   1.281 +                $encoder_options = strtoupper($info['audio']['bitrate_mode']).ceil($info['audio']['bitrate'] / 1000);
   1.282 +            } else {
   1.283 +                $encoder_options = strtoupper($info['audio']['bitrate_mode']);
   1.284 +            }
   1.285 +
   1.286 +        }
   1.287 +        if (!empty($thisfile_mpeg_audio_lame['bitrate_min'])) {
   1.288 +            $encoder_options .= ' -b'.$thisfile_mpeg_audio_lame['bitrate_min'];
   1.289 +        }
   1.290 +
   1.291 +        if (@$thisfile_mpeg_audio_lame['encoding_flags']['nogap_prev'] || @$thisfile_mpeg_audio_lame['encoding_flags']['nogap_next']) {
   1.292 +            $encoder_options .= ' --nogap';
   1.293 +        }
   1.294 +
   1.295 +        if (!empty($thisfile_mpeg_audio_lame['lowpass_frequency'])) {
   1.296 +            $exploded_options = explode(' ', $encoder_options, 4);
   1.297 +            if ($exploded_options[0] == '--r3mix') {
   1.298 +                $exploded_options[1] = 'r3mix';
   1.299 +            }
   1.300 +            switch ($exploded_options[0]) {
   1.301 +                case '--preset':
   1.302 +                case '--alt-preset':
   1.303 +                case '--r3mix':
   1.304 +                    if ($exploded_options[1] == 'fast') {
   1.305 +                        $exploded_options[1] .= ' '.$exploded_options[2];
   1.306 +                    }
   1.307 +                    switch ($exploded_options[1]) {
   1.308 +                        case 'portable':
   1.309 +                        case 'medium':
   1.310 +                        case 'standard':
   1.311 +                        case 'extreme':
   1.312 +                        case 'insane':
   1.313 +                        case 'fast portable':
   1.314 +                        case 'fast medium':
   1.315 +                        case 'fast standard':
   1.316 +                        case 'fast extreme':
   1.317 +                        case 'fast insane':
   1.318 +                        case 'r3mix':
   1.319 +                            static $expected_lowpass = array (
   1.320 +                                    'insane|20500'        => 20500,
   1.321 +                                    'insane|20600'        => 20600,  // 3.90.2, 3.90.3, 3.91
   1.322 +                                    'medium|18000'        => 18000,
   1.323 +                                    'fast medium|18000'   => 18000,
   1.324 +                                    'extreme|19500'       => 19500,  // 3.90,   3.90.1, 3.92, 3.95
   1.325 +                                    'extreme|19600'       => 19600,  // 3.90.2, 3.90.3, 3.91, 3.93.1
   1.326 +                                    'fast extreme|19500'  => 19500,  // 3.90,   3.90.1, 3.92, 3.95
   1.327 +                                    'fast extreme|19600'  => 19600,  // 3.90.2, 3.90.3, 3.91, 3.93.1
   1.328 +                                    'standard|19000'      => 19000,
   1.329 +                                    'fast standard|19000' => 19000,
   1.330 +                                    'r3mix|19500'         => 19500,  // 3.90,   3.90.1, 3.92
   1.331 +                                    'r3mix|19600'         => 19600,  // 3.90.2, 3.90.3, 3.91
   1.332 +                                    'r3mix|18000'         => 18000,  // 3.94,   3.95
   1.333 +                                );
   1.334 +                            if (!isset($expected_lowpass[$exploded_options[1].'|'.$thisfile_mpeg_audio_lame['lowpass_frequency']]) && ($thisfile_mpeg_audio_lame['lowpass_frequency'] < 22050) && (round($thisfile_mpeg_audio_lame['lowpass_frequency'] / 1000) < round($thisfile_mpeg_audio['sample_rate'] / 2000))) {
   1.335 +                                $encoder_options .= ' --lowpass '.$thisfile_mpeg_audio_lame['lowpass_frequency'];
   1.336 +                            }
   1.337 +                            break;
   1.338 +
   1.339 +                        default:
   1.340 +                            break;
   1.341 +                    }
   1.342 +                    break;
   1.343 +            }
   1.344 +        }
   1.345 +
   1.346 +        if (isset($thisfile_mpeg_audio_lame['raw']['source_sample_freq'])) {
   1.347 +            if (($thisfile_mpeg_audio['sample_rate'] == 44100) && ($thisfile_mpeg_audio_lame['raw']['source_sample_freq'] != 1)) {
   1.348 +                $encoder_options .= ' --resample 44100';
   1.349 +            } elseif (($thisfile_mpeg_audio['sample_rate'] == 48000) && ($thisfile_mpeg_audio_lame['raw']['source_sample_freq'] != 2)) {
   1.350 +                $encoder_options .= ' --resample 48000';
   1.351 +            } elseif ($thisfile_mpeg_audio['sample_rate'] < 44100) {
   1.352 +                switch ($thisfile_mpeg_audio_lame['raw']['source_sample_freq']) {
   1.353 +                    case 0: // <= 32000
   1.354 +                        // may or may not be same as source frequency - ignore
   1.355 +                        break;
   1.356 +                    case 1: // 44100
   1.357 +                    case 2: // 48000
   1.358 +                    case 3: // 48000+
   1.359 +                        $exploded_options = explode(' ', $encoder_options, 4);
   1.360 +                        switch ($exploded_options[0]) {
   1.361 +                            case '--preset':
   1.362 +                            case '--alt-preset':
   1.363 +                                switch ($exploded_options[1]) {
   1.364 +                                    case 'fast':
   1.365 +                                    case 'portable':
   1.366 +                                    case 'medium':
   1.367 +                                    case 'standard':
   1.368 +                                    case 'extreme':
   1.369 +                                    case 'insane':
   1.370 +                                        $encoder_options .= ' --resample '.$thisfile_mpeg_audio['sample_rate'];
   1.371 +                                        break;
   1.372 +
   1.373 +                                    default:
   1.374 +                                        static $expected_resampled_rate = array (
   1.375 +                                                'phon+/lw/mw-eu/sw|16000' => 16000,
   1.376 +                                                'mw-us|24000'             => 24000, // 3.95
   1.377 +                                                'mw-us|32000'             => 32000, // 3.93
   1.378 +                                                'mw-us|16000'             => 16000, // 3.92
   1.379 +                                                'phone|16000'             => 16000,
   1.380 +                                                'phone|11025'             => 11025, // 3.94a15
   1.381 +                                                'radio|32000'             => 32000, // 3.94a15
   1.382 +                                                'fm/radio|32000'          => 32000, // 3.92
   1.383 +                                                'fm|32000'                => 32000, // 3.90
   1.384 +                                                'voice|32000'             => 32000);
   1.385 +                                        if (!isset($expected_resampled_rate[$exploded_options[1].'|'.$thisfile_mpeg_audio['sample_rate']])) {
   1.386 +                                            $encoder_options .= ' --resample '.$thisfile_mpeg_audio['sample_rate'];
   1.387 +                                        }
   1.388 +                                        break;
   1.389 +                                }
   1.390 +                                break;
   1.391 +
   1.392 +                            case '--r3mix':
   1.393 +                            default:
   1.394 +                                $encoder_options .= ' --resample '.$thisfile_mpeg_audio['sample_rate'];
   1.395 +                                break;
   1.396 +                        }
   1.397 +                        break;
   1.398 +                }
   1.399 +            }
   1.400 +        }
   1.401 +        if (empty($encoder_options) && !empty($info['audio']['bitrate']) && !empty($info['audio']['bitrate_mode'])) {
   1.402 +            //$encoder_options = strtoupper($info['audio']['bitrate_mode']).ceil($info['audio']['bitrate'] / 1000);
   1.403 +            $encoder_options = strtoupper($info['audio']['bitrate_mode']);
   1.404 +        }
   1.405 +
   1.406 +        return $encoder_options;
   1.407 +    }
   1.408 +
   1.409 +
   1.410 +    
   1.411 +    public function decodeMPEGaudioHeader($fd, $offset, &$info, $recursive_search=true, $scan_as_cbr=false, $fast_mpeg_header_scan=false) {
   1.412 +
   1.413 +        static $mpeg_audio_version_lookup;
   1.414 +        static $mpeg_audio_layer_lookup;
   1.415 +        static $mpeg_audio_bitrate_lookup;
   1.416 +        static $mpeg_audio_frequency_lookup;
   1.417 +        static $mpeg_audio_channel_mode_lookup;
   1.418 +        static $mpeg_audio_mode_extension_lookup;
   1.419 +        static $mpeg_audio_emphasis_lookup;
   1.420 +        if (empty($mpeg_audio_version_lookup)) {
   1.421 +            $mpeg_audio_version_lookup        = getid3_mp3::MPEGaudioVersionarray();
   1.422 +            $mpeg_audio_layer_lookup          = getid3_mp3::MPEGaudioLayerarray();
   1.423 +            $mpeg_audio_bitrate_lookup        = getid3_mp3::MPEGaudioBitratearray();
   1.424 +            $mpeg_audio_frequency_lookup      = getid3_mp3::MPEGaudioFrequencyarray();
   1.425 +            $mpeg_audio_channel_mode_lookup   = getid3_mp3::MPEGaudioChannelModearray();
   1.426 +            $mpeg_audio_mode_extension_lookup = getid3_mp3::MPEGaudioModeExtensionarray();
   1.427 +            $mpeg_audio_emphasis_lookup       = getid3_mp3::MPEGaudioEmphasisarray();
   1.428 +        }
   1.429 +
   1.430 +        if ($offset >= $info['avdataend']) {
   1.431 +
   1.432 +            // non-fatal error: 'end of file encounter looking for MPEG synch'
   1.433 +            return;
   1.434 +            
   1.435 +        }
   1.436 +        fseek($fd, $offset, SEEK_SET);
   1.437 +        $header_string = fread($fd, 226); // LAME header at offset 36 + 190 bytes of Xing/LAME data
   1.438 +
   1.439 +        // MP3 audio frame structure:
   1.440 +        // $aa $aa $aa $aa [$bb $bb] $cc...
   1.441 +        // where $aa..$aa is the four-byte mpeg-audio header (below)
   1.442 +        // $bb $bb is the optional 2-byte CRC
   1.443 +        // and $cc... is the audio data
   1.444 +
   1.445 +        $head4 = substr($header_string, 0, 4);
   1.446 +
   1.447 +        if (isset($mpeg_audio_header_decode_cache[$head4])) {
   1.448 +            $mpeg_header_raw_array= $mpeg_audio_header_decode_cache[$head4];
   1.449 +        } else {
   1.450 +            $mpeg_header_raw_array = getid3_mp3::MPEGaudioHeaderDecode($head4);
   1.451 +            $mpeg_audio_header_decode_cache[$head4] = $mpeg_header_raw_array;
   1.452 +        }
   1.453 +
   1.454 +        // Not in cache
   1.455 +        if (!isset($mpeg_audio_header_valid_cache[$head4])) {
   1.456 +            $mpeg_audio_header_valid_cache[$head4] = getid3_mp3::MPEGaudioHeaderValid($mpeg_header_raw_array, false, false);
   1.457 +        }
   1.458 +
   1.459 +        // shortcut
   1.460 +        if (!isset($info['mpeg']['audio'])) {
   1.461 +            $info['mpeg']['audio'] = array ();
   1.462 +        }
   1.463 +        $thisfile_mpeg_audio = &$info['mpeg']['audio'];
   1.464 +
   1.465 +
   1.466 +        if ($mpeg_audio_header_valid_cache[$head4]) {
   1.467 +            $thisfile_mpeg_audio['raw'] = $mpeg_header_raw_array;
   1.468 +        } else {
   1.469 +            
   1.470 +            // non-fatal error: Invalid MPEG audio header at offset $offset
   1.471 +            return;
   1.472 +        }
   1.473 +
   1.474 +        if (!$fast_mpeg_header_scan) {
   1.475 +
   1.476 +            $thisfile_mpeg_audio['version']       = $mpeg_audio_version_lookup[$thisfile_mpeg_audio['raw']['version']];
   1.477 +            $thisfile_mpeg_audio['layer']         = $mpeg_audio_layer_lookup[$thisfile_mpeg_audio['raw']['layer']];
   1.478 +
   1.479 +            $thisfile_mpeg_audio['channelmode']   = $mpeg_audio_channel_mode_lookup[$thisfile_mpeg_audio['raw']['channelmode']];
   1.480 +            $thisfile_mpeg_audio['channels']      = (($thisfile_mpeg_audio['channelmode'] == 'mono') ? 1 : 2);
   1.481 +            $thisfile_mpeg_audio['sample_rate']   = $mpeg_audio_frequency_lookup[$thisfile_mpeg_audio['version']][$thisfile_mpeg_audio['raw']['sample_rate']];
   1.482 +            $thisfile_mpeg_audio['protection']    = !$thisfile_mpeg_audio['raw']['protection'];
   1.483 +            $thisfile_mpeg_audio['private']       = (bool) $thisfile_mpeg_audio['raw']['private'];
   1.484 +            $thisfile_mpeg_audio['modeextension'] = $mpeg_audio_mode_extension_lookup[$thisfile_mpeg_audio['layer']][$thisfile_mpeg_audio['raw']['modeextension']];
   1.485 +            $thisfile_mpeg_audio['copyright']     = (bool) $thisfile_mpeg_audio['raw']['copyright'];
   1.486 +            $thisfile_mpeg_audio['original']      = (bool) $thisfile_mpeg_audio['raw']['original'];
   1.487 +            $thisfile_mpeg_audio['emphasis']      = $mpeg_audio_emphasis_lookup[$thisfile_mpeg_audio['raw']['emphasis']];
   1.488 +
   1.489 +            $info['audio']['channels']    = $thisfile_mpeg_audio['channels'];
   1.490 +            $info['audio']['sample_rate'] = $thisfile_mpeg_audio['sample_rate'];
   1.491 +
   1.492 +            if ($thisfile_mpeg_audio['protection']) {
   1.493 +                $thisfile_mpeg_audio['crc'] = getid3_lib::BigEndian2Int(substr($header_string, 4, 2));
   1.494 +            }
   1.495 +
   1.496 +        }
   1.497 +
   1.498 +        if ($thisfile_mpeg_audio['raw']['bitrate'] == 15) {
   1.499 +            // http://www.hydrogenaudio.org/?act=ST&f=16&t=9682&st=0
   1.500 +            $this->getid3->warning('Invalid bitrate index (15), this is a known bug in free-format MP3s encoded by LAME v3.90 - 3.93.1');
   1.501 +            $thisfile_mpeg_audio['raw']['bitrate'] = 0;
   1.502 +        }
   1.503 +        $thisfile_mpeg_audio['padding'] = (bool) $thisfile_mpeg_audio['raw']['padding'];
   1.504 +        $thisfile_mpeg_audio['bitrate'] = $mpeg_audio_bitrate_lookup[$thisfile_mpeg_audio['version']][$thisfile_mpeg_audio['layer']][$thisfile_mpeg_audio['raw']['bitrate']];
   1.505 +
   1.506 +        if (($thisfile_mpeg_audio['bitrate'] == 'free') && ($offset == $info['avdataoffset'])) {
   1.507 +            // only skip multiple frame check if free-format bitstream found at beginning of file
   1.508 +            // otherwise is quite possibly simply corrupted data
   1.509 +            $recursive_search = false;
   1.510 +        }
   1.511 +
   1.512 +        // For Layer 2 there are some combinations of bitrate and mode which are not allowed.
   1.513 +        if (!$fast_mpeg_header_scan && ($thisfile_mpeg_audio['layer'] == '2')) {
   1.514 +
   1.515 +            $info['audio']['dataformat'] = 'mp2';
   1.516 +            switch ($thisfile_mpeg_audio['channelmode']) {
   1.517 +
   1.518 +                case 'mono':
   1.519 +                    if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] <= 192000)) {
   1.520 +                        // these are ok
   1.521 +                    } else {
   1.522 +                        
   1.523 +                        // non-fatal error: bitrate not allowed in Layer 2/mono
   1.524 +                        return;
   1.525 +                    }
   1.526 +                    break;
   1.527 +
   1.528 +                case 'stereo':
   1.529 +                case 'joint stereo':
   1.530 +                case 'dual channel':
   1.531 +                    if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] == 64000) || ($thisfile_mpeg_audio['bitrate'] >= 96000)) {
   1.532 +                        // these are ok
   1.533 +                    } else {
   1.534 +                        
   1.535 +                        // non-fatal error: bitrate not allowed in Layer 2/stereo/joint stereo/dual channel
   1.536 +                        return;
   1.537 +                    }
   1.538 +                    break;
   1.539 +
   1.540 +            }
   1.541 +
   1.542 +        }
   1.543 +
   1.544 +
   1.545 +        if ($info['audio']['sample_rate'] > 0) {
   1.546 +            $thisfile_mpeg_audio['framelength'] = getid3_mp3::MPEGaudioFrameLength($thisfile_mpeg_audio['bitrate'], $thisfile_mpeg_audio['version'], $thisfile_mpeg_audio['layer'], (int) $thisfile_mpeg_audio['padding'], $info['audio']['sample_rate']);
   1.547 +        }
   1.548 +
   1.549 +        $next_frame_test_offset = $offset + 1;
   1.550 +        if ($thisfile_mpeg_audio['bitrate'] != 'free') {
   1.551 +
   1.552 +            $info['audio']['bitrate'] = $thisfile_mpeg_audio['bitrate'];
   1.553 +
   1.554 +            if (isset($thisfile_mpeg_audio['framelength'])) {
   1.555 +                $next_frame_test_offset = $offset + $thisfile_mpeg_audio['framelength'];
   1.556 +            } else {
   1.557 +
   1.558 +                // non-fatal error: Frame at offset('.$offset.') is has an invalid frame length.
   1.559 +                return;
   1.560 +            }
   1.561 +
   1.562 +        }
   1.563 +
   1.564 +        $expected_number_of_audio_bytes = 0;
   1.565 +
   1.566 +        ////////////////////////////////////////////////////////////////////////////////////
   1.567 +        // Variable-bitrate headers
   1.568 +
   1.569 +        if (substr($header_string, 4 + 32, 4) == 'VBRI') {
   1.570 +            // Fraunhofer VBR header is hardcoded 'VBRI' at offset 0x24 (36)
   1.571 +            // specs taken from http://minnie.tuhs.org/pipermail/mp3encoder/2001-January/001800.html
   1.572 +
   1.573 +            $thisfile_mpeg_audio['bitrate_mode'] = 'vbr';
   1.574 +            $thisfile_mpeg_audio['VBR_method']   = 'Fraunhofer';
   1.575 +            $info['audio']['codec']                = 'Fraunhofer';
   1.576 +
   1.577 +            $side_info_data = substr($header_string, 4 + 2, 32);
   1.578 +
   1.579 +            $fraunhofer_vbr_offset = 36;
   1.580 +
   1.581 +            $thisfile_mpeg_audio['VBR_encoder_version']     = getid3_lib::BigEndian2Int(substr($header_string, $fraunhofer_vbr_offset +  4, 2)); // VbriVersion
   1.582 +            $thisfile_mpeg_audio['VBR_encoder_delay']       = getid3_lib::BigEndian2Int(substr($header_string, $fraunhofer_vbr_offset +  6, 2)); // VbriDelay
   1.583 +            $thisfile_mpeg_audio['VBR_quality']             = getid3_lib::BigEndian2Int(substr($header_string, $fraunhofer_vbr_offset +  8, 2)); // VbriQuality
   1.584 +            $thisfile_mpeg_audio['VBR_bytes']               = getid3_lib::BigEndian2Int(substr($header_string, $fraunhofer_vbr_offset + 10, 4)); // VbriStreamBytes
   1.585 +            $thisfile_mpeg_audio['VBR_frames']              = getid3_lib::BigEndian2Int(substr($header_string, $fraunhofer_vbr_offset + 14, 4)); // VbriStreamFrames
   1.586 +            $thisfile_mpeg_audio['VBR_seek_offsets']        = getid3_lib::BigEndian2Int(substr($header_string, $fraunhofer_vbr_offset + 18, 2)); // VbriTableSize
   1.587 +            $thisfile_mpeg_audio['VBR_seek_scale']          = getid3_lib::BigEndian2Int(substr($header_string, $fraunhofer_vbr_offset + 20, 2)); // VbriTableScale
   1.588 +            $thisfile_mpeg_audio['VBR_entry_bytes']         = getid3_lib::BigEndian2Int(substr($header_string, $fraunhofer_vbr_offset + 22, 2)); // VbriEntryBytes
   1.589 +            $thisfile_mpeg_audio['VBR_entry_frames']        = getid3_lib::BigEndian2Int(substr($header_string, $fraunhofer_vbr_offset + 24, 2)); // VbriEntryFrames
   1.590 +
   1.591 +            $expected_number_of_audio_bytes = $thisfile_mpeg_audio['VBR_bytes'];
   1.592 +
   1.593 +            $previous_byte_offset = $offset;
   1.594 +            for ($i = 0; $i < $thisfile_mpeg_audio['VBR_seek_offsets']; $i++) {
   1.595 +                $fraunhofer_offset_n = getid3_lib::BigEndian2Int(substr($header_string, $fraunhofer_vbr_offset, $thisfile_mpeg_audio['VBR_entry_bytes']));
   1.596 +                $fraunhofer_vbr_offset += $thisfile_mpeg_audio['VBR_entry_bytes'];
   1.597 +                $thisfile_mpeg_audio['VBR_offsets_relative'][$i] = ($fraunhofer_offset_n * $thisfile_mpeg_audio['VBR_seek_scale']);
   1.598 +                $thisfile_mpeg_audio['VBR_offsets_absolute'][$i] = ($fraunhofer_offset_n * $thisfile_mpeg_audio['VBR_seek_scale']) + $previous_byte_offset;
   1.599 +                $previous_byte_offset += $fraunhofer_offset_n;
   1.600 +            }
   1.601 +
   1.602 +
   1.603 +        } else {
   1.604 +
   1.605 +            // Xing VBR header is hardcoded 'Xing' at a offset 0x0D (13), 0x15 (21) or 0x24 (36)
   1.606 +            // depending on MPEG layer and number of channels
   1.607 +
   1.608 +            $vbr_id_offset = getid3_mp3::XingVBRidOffset($thisfile_mpeg_audio['version'], $thisfile_mpeg_audio['channelmode']);
   1.609 +            $side_info_data = substr($header_string, 4 + 2, $vbr_id_offset - 4);
   1.610 +
   1.611 +            if ((substr($header_string, $vbr_id_offset, strlen('Xing')) == 'Xing') || (substr($header_string, $vbr_id_offset, strlen('Info')) == 'Info')) {
   1.612 +                // 'Xing' is traditional Xing VBR frame
   1.613 +                // 'Info' is LAME-encoded CBR (This was done to avoid CBR files to be recognized as traditional Xing VBR files by some decoders.)
   1.614 +                // 'Info' *can* legally be used to specify a VBR file as well, however.
   1.615 +
   1.616 +                // http://www.multiweb.cz/twoinches/MP3inside.htm
   1.617 +                //00..03 = "Xing" or "Info"
   1.618 +                //04..07 = Flags:
   1.619 +                //  0x01  Frames Flag     set if value for number of frames in file is stored
   1.620 +                //  0x02  Bytes Flag      set if value for filesize in bytes is stored
   1.621 +                //  0x04  TOC Flag        set if values for TOC are stored
   1.622 +                //  0x08  VBR Scale Flag  set if values for VBR scale is stored
   1.623 +                //08..11  Frames: Number of frames in file (including the first Xing/Info one)
   1.624 +                //12..15  Bytes:  File length in Bytes
   1.625 +                //16..115  TOC (Table of Contents):
   1.626 +                //  Contains of 100 indexes (one Byte length) for easier lookup in file. Approximately solves problem with moving inside file.
   1.627 +                //  Each Byte has a value according this formula:
   1.628 +                //  (TOC[i] / 256) * fileLenInBytes
   1.629 +                //  So if song lasts eg. 240 sec. and you want to jump to 60. sec. (and file is 5 000 000 Bytes length) you can use:
   1.630 +                //  TOC[(60/240)*100] = TOC[25]
   1.631 +                //  and corresponding Byte in file is then approximately at:
   1.632 +                //  (TOC[25]/256) * 5000000
   1.633 +                //116..119  VBR Scale
   1.634 +
   1.635 +
   1.636 +                // should be safe to leave this at 'vbr' and let it be overriden to 'cbr' if a CBR preset/mode is used by LAME
   1.637 +                $thisfile_mpeg_audio['bitrate_mode'] = 'vbr';
   1.638 +                $thisfile_mpeg_audio['VBR_method']   = 'Xing';
   1.639 +
   1.640 +                $thisfile_mpeg_audio['xing_flags_raw'] = getid3_lib::BigEndian2Int(substr($header_string, $vbr_id_offset + 4, 4));
   1.641 +
   1.642 +                $thisfile_mpeg_audio['xing_flags']['frames']    = (bool) ($thisfile_mpeg_audio['xing_flags_raw'] & 0x00000001);
   1.643 +                $thisfile_mpeg_audio['xing_flags']['bytes']     = (bool) ($thisfile_mpeg_audio['xing_flags_raw'] & 0x00000002);
   1.644 +                $thisfile_mpeg_audio['xing_flags']['toc']       = (bool) ($thisfile_mpeg_audio['xing_flags_raw'] & 0x00000004);
   1.645 +                $thisfile_mpeg_audio['xing_flags']['vbr_scale'] = (bool) ($thisfile_mpeg_audio['xing_flags_raw'] & 0x00000008);
   1.646 +
   1.647 +                if ($thisfile_mpeg_audio['xing_flags']['frames']) {
   1.648 +                    $thisfile_mpeg_audio['VBR_frames'] = getid3_lib::BigEndian2Int(substr($header_string, $vbr_id_offset +  8, 4));
   1.649 +                }
   1.650 +                if ($thisfile_mpeg_audio['xing_flags']['bytes']) {
   1.651 +                    $thisfile_mpeg_audio['VBR_bytes']  = getid3_lib::BigEndian2Int(substr($header_string, $vbr_id_offset + 12, 4));
   1.652 +                }
   1.653 +
   1.654 +                if (!empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
   1.655 +
   1.656 +                    $frame_lengthfloat = $thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames'];
   1.657 +
   1.658 +                    if ($thisfile_mpeg_audio['layer'] == '1') {
   1.659 +                        // BitRate = (((FrameLengthInBytes / 4) - Padding) * SampleRate) / 12
   1.660 +                        $info['audio']['bitrate'] = ($frame_lengthfloat / 4) * $thisfile_mpeg_audio['sample_rate'] * (2 / $info['audio']['channels']) / 12;
   1.661 +                    } else {
   1.662 +                        // Bitrate = ((FrameLengthInBytes - Padding) * SampleRate) / 144
   1.663 +                        $info['audio']['bitrate'] = $frame_lengthfloat * $thisfile_mpeg_audio['sample_rate'] * (2 / $info['audio']['channels']) / 144;
   1.664 +                    }
   1.665 +                    $thisfile_mpeg_audio['framelength'] = floor($frame_lengthfloat);
   1.666 +                }
   1.667 +
   1.668 +                if ($thisfile_mpeg_audio['xing_flags']['toc']) {
   1.669 +                    $lame_toc_data = substr($header_string, $vbr_id_offset + 16, 100);
   1.670 +                    for ($i = 0; $i < 100; $i++) {
   1.671 +                        $thisfile_mpeg_audio['toc'][$i] = ord($lame_toc_data{$i});
   1.672 +                    }
   1.673 +                }
   1.674 +                if ($thisfile_mpeg_audio['xing_flags']['vbr_scale']) {
   1.675 +                    $thisfile_mpeg_audio['VBR_scale'] = getid3_lib::BigEndian2Int(substr($header_string, $vbr_id_offset + 116, 4));
   1.676 +                }
   1.677 +
   1.678 +
   1.679 +                // http://gabriel.mp3-tech.org/mp3infotag.html
   1.680 +                if (substr($header_string, $vbr_id_offset + 120, 4) == 'LAME') {
   1.681 +
   1.682 +                    // shortcut
   1.683 +                    $thisfile_mpeg_audio['LAME'] = array ();
   1.684 +                    $thisfile_mpeg_audio_lame    = &$thisfile_mpeg_audio['LAME'];
   1.685 +
   1.686 +
   1.687 +                    $thisfile_mpeg_audio_lame['long_version']  = substr($header_string, $vbr_id_offset + 120, 20);
   1.688 +                    $thisfile_mpeg_audio_lame['short_version'] = substr($thisfile_mpeg_audio_lame['long_version'], 0, 9);
   1.689 +
   1.690 +                    if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.90') {
   1.691 +
   1.692 +                        // extra 11 chars are not part of version string when LAMEtag present
   1.693 +                        unset($thisfile_mpeg_audio_lame['long_version']);
   1.694 +
   1.695 +                        // It the LAME tag was only introduced in LAME v3.90
   1.696 +                        // http://www.hydrogenaudio.org/?act=ST&f=15&t=9933
   1.697 +
   1.698 +                        // Offsets of various bytes in http://gabriel.mp3-tech.org/mp3infotag.html
   1.699 +                        // are assuming a 'Xing' identifier offset of 0x24, which is the case for
   1.700 +                        // MPEG-1 non-mono, but not for other combinations
   1.701 +                        $lame_tag_offset_contant = $vbr_id_offset - 0x24;
   1.702 +
   1.703 +                        // shortcuts
   1.704 +                        $thisfile_mpeg_audio_lame['RGAD']    = array ('track'=>array(), 'album'=>array());
   1.705 +                        $thisfile_mpeg_audio_lame_rgad       = &$thisfile_mpeg_audio_lame['RGAD'];
   1.706 +                        $thisfile_mpeg_audio_lame_rgad_track = &$thisfile_mpeg_audio_lame_rgad['track'];
   1.707 +                        $thisfile_mpeg_audio_lame_rgad_album = &$thisfile_mpeg_audio_lame_rgad['album'];
   1.708 +                        $thisfile_mpeg_audio_lame['raw']     = array ();
   1.709 +                        $thisfile_mpeg_audio_lame_raw        = &$thisfile_mpeg_audio_lame['raw'];
   1.710 +
   1.711 +                        // byte $9B  VBR Quality
   1.712 +                        // This field is there to indicate a quality level, although the scale was not precised in the original Xing specifications.
   1.713 +                        // Actually overwrites original Xing bytes
   1.714 +                        unset($thisfile_mpeg_audio['VBR_scale']);
   1.715 +                        $thisfile_mpeg_audio_lame['vbr_quality'] = getid3_lib::BigEndian2Int(substr($header_string, $lame_tag_offset_contant + 0x9B, 1));
   1.716 +
   1.717 +                        // bytes $9C-$A4  Encoder short VersionString
   1.718 +                        $thisfile_mpeg_audio_lame['short_version'] = substr($header_string, $lame_tag_offset_contant + 0x9C, 9);
   1.719 +
   1.720 +                        // byte $A5  Info Tag revision + VBR method
   1.721 +                        $lame_tagRevisionVBRmethod = getid3_lib::BigEndian2Int(substr($header_string, $lame_tag_offset_contant + 0xA5, 1));
   1.722 +
   1.723 +                        $thisfile_mpeg_audio_lame['tag_revision']      = ($lame_tagRevisionVBRmethod & 0xF0) >> 4;
   1.724 +                        $thisfile_mpeg_audio_lame_raw['vbr_method'] =  $lame_tagRevisionVBRmethod & 0x0F;
   1.725 +                        $thisfile_mpeg_audio_lame['vbr_method']        = getid3_mp3::LAMEvbrMethodLookup($thisfile_mpeg_audio_lame_raw['vbr_method']);
   1.726 +                        $thisfile_mpeg_audio['bitrate_mode']           = substr($thisfile_mpeg_audio_lame['vbr_method'], 0, 3); // usually either 'cbr' or 'vbr', but truncates 'vbr-old / vbr-rh' to 'vbr'
   1.727 +
   1.728 +                        // byte $A6  Lowpass filter value
   1.729 +                        $thisfile_mpeg_audio_lame['lowpass_frequency'] = getid3_lib::BigEndian2Int(substr($header_string, $lame_tag_offset_contant + 0xA6, 1)) * 100;
   1.730 +
   1.731 +                        // bytes $A7-$AE  Replay Gain
   1.732 +                        // http://privatewww.essex.ac.uk/~djmrob/replaygain/rg_data_format.html
   1.733 +                        // bytes $A7-$AA : 32 bit floating point "Peak signal amplitude"
   1.734 +                        if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.94b') {
   1.735 +                            // LAME 3.94a16 and later - 9.23 fixed point
   1.736 +                            // ie 0x0059E2EE / (2^23) = 5890798 / 8388608 = 0.7022378444671630859375
   1.737 +                            $thisfile_mpeg_audio_lame_rgad['peak_amplitude'] = (float) ((getid3_lib::BigEndian2Int(substr($header_string, $lame_tag_offset_contant + 0xA7, 4))) / 8388608);
   1.738 +                        } else {
   1.739 +                            // LAME 3.94a15 and earlier - 32-bit floating point
   1.740 +                            // Actually 3.94a16 will fall in here too and be WRONG, but is hard to detect 3.94a16 vs 3.94a15
   1.741 +                            $thisfile_mpeg_audio_lame_rgad['peak_amplitude'] = getid3_lib::LittleEndian2Float(substr($header_string, $lame_tag_offset_contant + 0xA7, 4));
   1.742 +                        }
   1.743 +                        if ($thisfile_mpeg_audio_lame_rgad['peak_amplitude'] == 0) {
   1.744 +                            unset($thisfile_mpeg_audio_lame_rgad['peak_amplitude']);
   1.745 +                        } else {
   1.746 +                            $thisfile_mpeg_audio_lame_rgad['peak_db'] = 20 * log10($thisfile_mpeg_audio_lame_rgad['peak_amplitude']);
   1.747 +                        }
   1.748 +
   1.749 +                        $thisfile_mpeg_audio_lame_raw['RGAD_track']      =   getid3_lib::BigEndian2Int(substr($header_string, $lame_tag_offset_contant + 0xAB, 2));
   1.750 +                        $thisfile_mpeg_audio_lame_raw['RGAD_album']      =   getid3_lib::BigEndian2Int(substr($header_string, $lame_tag_offset_contant + 0xAD, 2));
   1.751 +
   1.752 +
   1.753 +                        if ($thisfile_mpeg_audio_lame_raw['RGAD_track'] != 0) {
   1.754 +
   1.755 +                            $thisfile_mpeg_audio_lame_rgad_track['raw']['name']        = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0xE000) >> 13;
   1.756 +                            $thisfile_mpeg_audio_lame_rgad_track['raw']['originator']  = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x1C00) >> 10;
   1.757 +                            $thisfile_mpeg_audio_lame_rgad_track['raw']['sign_bit']    = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x0200) >> 9;
   1.758 +                            $thisfile_mpeg_audio_lame_rgad_track['raw']['gain_adjust'] =  $thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x01FF;
   1.759 +                            $thisfile_mpeg_audio_lame_rgad_track['name']       = getid3_lib_replaygain::NameLookup($thisfile_mpeg_audio_lame_rgad_track['raw']['name']);
   1.760 +                            $thisfile_mpeg_audio_lame_rgad_track['originator'] = getid3_lib_replaygain::OriginatorLookup($thisfile_mpeg_audio_lame_rgad_track['raw']['originator']);
   1.761 +                            $thisfile_mpeg_audio_lame_rgad_track['gain_db']    = getid3_lib_replaygain::AdjustmentLookup($thisfile_mpeg_audio_lame_rgad_track['raw']['gain_adjust'], $thisfile_mpeg_audio_lame_rgad_track['raw']['sign_bit']);
   1.762 +
   1.763 +                            if (!empty($thisfile_mpeg_audio_lame_rgad['peak_amplitude'])) {
   1.764 +                                $info['replay_gain']['track']['peak']   = $thisfile_mpeg_audio_lame_rgad['peak_amplitude'];
   1.765 +                            }
   1.766 +                            $info['replay_gain']['track']['originator'] = $thisfile_mpeg_audio_lame_rgad_track['originator'];
   1.767 +                            $info['replay_gain']['track']['adjustment'] = $thisfile_mpeg_audio_lame_rgad_track['gain_db'];
   1.768 +                        } else {
   1.769 +                            unset($thisfile_mpeg_audio_lame_rgad['track']);
   1.770 +                        }
   1.771 +                        if ($thisfile_mpeg_audio_lame_raw['RGAD_album'] != 0) {
   1.772 +
   1.773 +                            $thisfile_mpeg_audio_lame_rgad_album['raw']['name']        = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0xE000) >> 13;
   1.774 +                            $thisfile_mpeg_audio_lame_rgad_album['raw']['originator']  = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x1C00) >> 10;
   1.775 +                            $thisfile_mpeg_audio_lame_rgad_album['raw']['sign_bit']    = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x0200) >> 9;
   1.776 +                            $thisfile_mpeg_audio_lame_rgad_album['raw']['gain_adjust'] =  $thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x01FF;
   1.777 +                            $thisfile_mpeg_audio_lame_rgad_album['name']       = getid3_lib_replaygain::NameLookup($thisfile_mpeg_audio_lame_rgad_album['raw']['name']);
   1.778 +                            $thisfile_mpeg_audio_lame_rgad_album['originator'] = getid3_lib_replaygain::OriginatorLookup($thisfile_mpeg_audio_lame_rgad_album['raw']['originator']);
   1.779 +                            $thisfile_mpeg_audio_lame_rgad_album['gain_db']    = getid3_lib_replaygain::AdjustmentLookup($thisfile_mpeg_audio_lame_rgad_album['raw']['gain_adjust'], $thisfile_mpeg_audio_lame_rgad_album['raw']['sign_bit']);
   1.780 +
   1.781 +                            if (!empty($thisfile_mpeg_audio_lame_rgad['peak_amplitude'])) {
   1.782 +                                $info['replay_gain']['album']['peak']   = $thisfile_mpeg_audio_lame_rgad['peak_amplitude'];
   1.783 +                            }
   1.784 +                            $info['replay_gain']['album']['originator'] = $thisfile_mpeg_audio_lame_rgad_album['originator'];
   1.785 +                            $info['replay_gain']['album']['adjustment'] = $thisfile_mpeg_audio_lame_rgad_album['gain_db'];
   1.786 +                        } else {
   1.787 +                            unset($thisfile_mpeg_audio_lame_rgad['album']);
   1.788 +                        }
   1.789 +                        if (empty($thisfile_mpeg_audio_lame_rgad)) {
   1.790 +                            unset($thisfile_mpeg_audio_lame['RGAD']);
   1.791 +                        }
   1.792 +
   1.793 +
   1.794 +                        // byte $AF  Encoding flags + ATH Type
   1.795 +                        $encoding_flags_ath_type = getid3_lib::BigEndian2Int(substr($header_string, $lame_tag_offset_contant + 0xAF, 1));
   1.796 +                        $thisfile_mpeg_audio_lame['encoding_flags']['nspsytune']   = (bool) ($encoding_flags_ath_type & 0x10);
   1.797 +                        $thisfile_mpeg_audio_lame['encoding_flags']['nssafejoint'] = (bool) ($encoding_flags_ath_type & 0x20);
   1.798 +                        $thisfile_mpeg_audio_lame['encoding_flags']['nogap_next']  = (bool) ($encoding_flags_ath_type & 0x40);
   1.799 +                        $thisfile_mpeg_audio_lame['encoding_flags']['nogap_prev']  = (bool) ($encoding_flags_ath_type & 0x80);
   1.800 +                        $thisfile_mpeg_audio_lame['ath_type']                      =         $encoding_flags_ath_type & 0x0F;
   1.801 +
   1.802 +                        // byte $B0  if ABR {specified bitrate} else {minimal bitrate}
   1.803 +                        $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'] = getid3_lib::BigEndian2Int(substr($header_string, $lame_tag_offset_contant + 0xB0, 1));
   1.804 +                        if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 2) { // Average BitRate (ABR)
   1.805 +                            $thisfile_mpeg_audio_lame['bitrate_abr'] = $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'];
   1.806 +                        } elseif ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) { // Constant BitRate (CBR)
   1.807 +                            // ignore
   1.808 +                        } elseif ($thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'] > 0) { // Variable BitRate (VBR) - minimum bitrate
   1.809 +                            $thisfile_mpeg_audio_lame['bitrate_min'] = $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'];
   1.810 +                        }
   1.811 +
   1.812 +                        // bytes $B1-$B3  Encoder delays
   1.813 +                        $encoder_delays = getid3_lib::BigEndian2Int(substr($header_string, $lame_tag_offset_contant + 0xB1, 3));
   1.814 +                        $thisfile_mpeg_audio_lame['encoder_delay'] = ($encoder_delays & 0xFFF000) >> 12;
   1.815 +                        $thisfile_mpeg_audio_lame['end_padding']   =  $encoder_delays & 0x000FFF;
   1.816 +
   1.817 +                        // byte $B4  Misc
   1.818 +                        $misc_byte = getid3_lib::BigEndian2Int(substr($header_string, $lame_tag_offset_contant + 0xB4, 1));
   1.819 +                        $thisfile_mpeg_audio_lame_raw['noise_shaping']       = ($misc_byte & 0x03);
   1.820 +                        $thisfile_mpeg_audio_lame_raw['stereo_mode']         = ($misc_byte & 0x1C) >> 2;
   1.821 +                        $thisfile_mpeg_audio_lame_raw['not_optimal_quality'] = ($misc_byte & 0x20) >> 5;
   1.822 +                        $thisfile_mpeg_audio_lame_raw['source_sample_freq']  = ($misc_byte & 0xC0) >> 6;
   1.823 +                        $thisfile_mpeg_audio_lame['noise_shaping']           = $thisfile_mpeg_audio_lame_raw['noise_shaping'];
   1.824 +                        $thisfile_mpeg_audio_lame['stereo_mode']             = getid3_mp3::LAMEmiscStereoModeLookup($thisfile_mpeg_audio_lame_raw['stereo_mode']);
   1.825 +                        $thisfile_mpeg_audio_lame['not_optimal_quality']     = (bool) $thisfile_mpeg_audio_lame_raw['not_optimal_quality'];
   1.826 +                        $thisfile_mpeg_audio_lame['source_sample_freq']      = getid3_mp3::LAMEmiscSourceSampleFrequencyLookup($thisfile_mpeg_audio_lame_raw['source_sample_freq']);
   1.827 +
   1.828 +                        // byte $B5  MP3 Gain
   1.829 +                        $thisfile_mpeg_audio_lame_raw['mp3_gain']   = getid3_lib::BigEndian2Int(substr($header_string, $lame_tag_offset_contant + 0xB5, 1), false, true);
   1.830 +                        $thisfile_mpeg_audio_lame['mp3_gain_db']     = (20 * log10(2) / 4) * $thisfile_mpeg_audio_lame_raw['mp3_gain'];
   1.831 +                        $thisfile_mpeg_audio_lame['mp3_gain_factor'] = pow(2, ($thisfile_mpeg_audio_lame['mp3_gain_db'] / 6));
   1.832 +
   1.833 +                        // bytes $B6-$B7  Preset and surround info
   1.834 +                        $PresetSurroundBytes = getid3_lib::BigEndian2Int(substr($header_string, $lame_tag_offset_contant + 0xB6, 2));
   1.835 +                        // Reserved                                                    = ($PresetSurroundBytes & 0xC000);
   1.836 +                        $thisfile_mpeg_audio_lame_raw['surround_info'] = ($PresetSurroundBytes & 0x3800);
   1.837 +                        $thisfile_mpeg_audio_lame['surround_info']     = getid3_mp3::LAMEsurroundInfoLookup($thisfile_mpeg_audio_lame_raw['surround_info']);
   1.838 +                        $thisfile_mpeg_audio_lame['preset_used_id']    = ($PresetSurroundBytes & 0x07FF);
   1.839 +                        $thisfile_mpeg_audio_lame['preset_used']       = getid3_mp3::LAMEpresetUsedLookup($thisfile_mpeg_audio_lame);
   1.840 +                        if (!empty($thisfile_mpeg_audio_lame['preset_used_id']) && empty($thisfile_mpeg_audio_lame['preset_used'])) {
   1.841 +                            $this->getid3->warning('Unknown LAME preset used ('.$thisfile_mpeg_audio_lame['preset_used_id'].') - please report to info@getid3.org');
   1.842 +                        }
   1.843 +                        if (($thisfile_mpeg_audio_lame['short_version'] == 'LAME3.90.') && !empty($thisfile_mpeg_audio_lame['preset_used_id'])) {
   1.844 +                            // this may change if 3.90.4 ever comes out
   1.845 +                            $thisfile_mpeg_audio_lame['short_version'] = 'LAME3.90.3';
   1.846 +                        }
   1.847 +
   1.848 +                        // bytes $B8-$BB  MusicLength
   1.849 +                        $thisfile_mpeg_audio_lame['audio_bytes'] = getid3_lib::BigEndian2Int(substr($header_string, $lame_tag_offset_contant + 0xB8, 4));
   1.850 +                        $expected_number_of_audio_bytes = (($thisfile_mpeg_audio_lame['audio_bytes'] > 0) ? $thisfile_mpeg_audio_lame['audio_bytes'] : $thisfile_mpeg_audio['VBR_bytes']);
   1.851 +
   1.852 +                        // bytes $BC-$BD  MusicCRC
   1.853 +                        $thisfile_mpeg_audio_lame['music_crc']    = getid3_lib::BigEndian2Int(substr($header_string, $lame_tag_offset_contant + 0xBC, 2));
   1.854 +
   1.855 +                        // bytes $BE-$BF  CRC-16 of Info Tag
   1.856 +                        $thisfile_mpeg_audio_lame['lame_tag_crc'] = getid3_lib::BigEndian2Int(substr($header_string, $lame_tag_offset_contant + 0xBE, 2));
   1.857 +
   1.858 +
   1.859 +                        // LAME CBR
   1.860 +                        if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) {
   1.861 +
   1.862 +                            $thisfile_mpeg_audio['bitrate_mode'] = 'cbr';
   1.863 +                            $thisfile_mpeg_audio['bitrate'] = getid3_mp3::ClosestStandardMP3Bitrate($thisfile_mpeg_audio['bitrate']);
   1.864 +                            $info['audio']['bitrate'] = $thisfile_mpeg_audio['bitrate'];
   1.865 +
   1.866 +                        }
   1.867 +
   1.868 +                    }
   1.869 +                }
   1.870 +
   1.871 +            } else {
   1.872 +
   1.873 +                // not Fraunhofer or Xing VBR methods, most likely CBR (but could be VBR with no header)
   1.874 +                $thisfile_mpeg_audio['bitrate_mode'] = 'cbr';
   1.875 +                if ($recursive_search) {
   1.876 +                    $thisfile_mpeg_audio['bitrate_mode'] = 'vbr';
   1.877 +                    if (getid3_mp3::RecursiveFrameScanning($fd, $info, $offset, $next_frame_test_offset, true)) {
   1.878 +                        $recursive_search = false;
   1.879 +                        $thisfile_mpeg_audio['bitrate_mode'] = 'cbr';
   1.880 +                    }
   1.881 +                    if ($thisfile_mpeg_audio['bitrate_mode'] == 'vbr') {
   1.882 +                        $this->getid3->warning('VBR file with no VBR header. Bitrate values calculated from actual frame bitrates.');
   1.883 +                    }
   1.884 +                }
   1.885 +
   1.886 +            }
   1.887 +
   1.888 +        }
   1.889 +
   1.890 +        if (($expected_number_of_audio_bytes > 0) && ($expected_number_of_audio_bytes != ($info['avdataend'] - $info['avdataoffset']))) {
   1.891 +            if ($expected_number_of_audio_bytes > ($info['avdataend'] - $info['avdataoffset'])) {
   1.892 +                if (($expected_number_of_audio_bytes - ($info['avdataend'] - $info['avdataoffset'])) == 1) {
   1.893 +                    $this->getid3->warning('Last byte of data truncated (this is a known bug in Meracl ID3 Tag Writer before v1.3.5)');
   1.894 +                } else {
   1.895 +                    $this->getid3->warning('Probable truncated file: expecting '.$expected_number_of_audio_bytes.' bytes of audio data, only found '.($info['avdataend'] - $info['avdataoffset']).' (short by '.($expected_number_of_audio_bytes - ($info['avdataend'] - $info['avdataoffset'])).' bytes)');
   1.896 +                }
   1.897 +            } else {
   1.898 +                if ((($info['avdataend'] - $info['avdataoffset']) - $expected_number_of_audio_bytes) == 1) {
   1.899 +                        $info['avdataend']--;
   1.900 +                } else {
   1.901 +                    $this->getid3->warning('Too much data in file: expecting '.$expected_number_of_audio_bytes.' bytes of audio data, found '.($info['avdataend'] - $info['avdataoffset']).' ('.(($info['avdataend'] - $info['avdataoffset']) - $expected_number_of_audio_bytes).' bytes too many)');
   1.902 +                }
   1.903 +            }
   1.904 +        }
   1.905 +
   1.906 +        if (($thisfile_mpeg_audio['bitrate'] == 'free') && empty($info['audio']['bitrate'])) {
   1.907 +            if (($offset == $info['avdataoffset']) && empty($thisfile_mpeg_audio['VBR_frames'])) {
   1.908 +                $frame_byte_length = getid3_mp3::FreeFormatFrameLength($fd, $offset, $info, true);
   1.909 +                if ($frame_byte_length > 0) {
   1.910 +                    $thisfile_mpeg_audio['framelength'] = $frame_byte_length;
   1.911 +                    if ($thisfile_mpeg_audio['layer'] == '1') {
   1.912 +                        // BitRate = (((FrameLengthInBytes / 4) - Padding) * SampleRate) / 12
   1.913 +                        $info['audio']['bitrate'] = ((($frame_byte_length / 4) - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 12;
   1.914 +                    } else {
   1.915 +                        // Bitrate = ((FrameLengthInBytes - Padding) * SampleRate) / 144
   1.916 +                        $info['audio']['bitrate'] = (($frame_byte_length - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 144;
   1.917 +                    }
   1.918 +                } else {
   1.919 +                    
   1.920 +                    // non-fatal error: Error calculating frame length of free-format MP3 without Xing/LAME header.
   1.921 +                    return;
   1.922 +                }
   1.923 +            }
   1.924 +        }
   1.925 +
   1.926 +        if (@$thisfile_mpeg_audio['VBR_frames']) {
   1.927 +            switch ($thisfile_mpeg_audio['bitrate_mode']) {
   1.928 +                case 'vbr':
   1.929 +                case 'abr':
   1.930 +                    if (($thisfile_mpeg_audio['version'] == '1') && ($thisfile_mpeg_audio['layer'] == 1)) {
   1.931 +                        $thisfile_mpeg_audio['VBR_bitrate'] = ((@$thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames']) * 8) * ($info['audio']['sample_rate'] / 384);
   1.932 +                    } elseif ((($thisfile_mpeg_audio['version'] == '2') || ($thisfile_mpeg_audio['version'] == '2.5')) && ($thisfile_mpeg_audio['layer'] == 3)) {
   1.933 +                        $thisfile_mpeg_audio['VBR_bitrate'] = ((@$thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames']) * 8) * ($info['audio']['sample_rate'] / 576);
   1.934 +                    } else {
   1.935 +                        $thisfile_mpeg_audio['VBR_bitrate'] = ((@$thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames']) * 8) * ($info['audio']['sample_rate'] / 1152);
   1.936 +                    }
   1.937 +                    if ($thisfile_mpeg_audio['VBR_bitrate'] > 0) {
   1.938 +                        $info['audio']['bitrate']         = $thisfile_mpeg_audio['VBR_bitrate'];
   1.939 +                        $thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio['VBR_bitrate']; // to avoid confusion
   1.940 +                    }
   1.941 +                    break;
   1.942 +            }
   1.943 +        }
   1.944 +
   1.945 +        // End variable-bitrate headers
   1.946 +        ////////////////////////////////////////////////////////////////////////////////////
   1.947 +
   1.948 +        if ($recursive_search) {
   1.949 +
   1.950 +            if (!getid3_mp3::RecursiveFrameScanning($fd, $info, $offset, $next_frame_test_offset, $scan_as_cbr)) {
   1.951 +                return false;
   1.952 +            }
   1.953 +
   1.954 +        }
   1.955 +
   1.956 +        return true;
   1.957 +    }
   1.958 +
   1.959 +    
   1.960 +    
   1.961 +    public function RecursiveFrameScanning(&$fd, &$info, &$offset, &$next_frame_test_offset, $scan_as_cbr) {
   1.962 +        for ($i = 0; $i < getid3_mp3::VALID_CHECK_FRAMES; $i++) {
   1.963 +            // check next getid3_mp3::VALID_CHECK_FRAMES frames for validity, to make sure we haven't run across a false synch
   1.964 +            if (($next_frame_test_offset + 4) >= $info['avdataend']) {
   1.965 +                // end of file
   1.966 +                return true;
   1.967 +            }
   1.968 +
   1.969 +            $next_frame_test_array = array ('avdataend' => $info['avdataend'], 'avdataoffset' => $info['avdataoffset']);
   1.970 +            if ($this->decodeMPEGaudioHeader($fd, $next_frame_test_offset, $next_frame_test_array, false)) {
   1.971 +                if ($scan_as_cbr) {
   1.972 +                    // force CBR mode, used for trying to pick out invalid audio streams with
   1.973 +                    // valid(?) VBR headers, or VBR streams with no VBR header
   1.974 +                    if (!isset($next_frame_test_array['mpeg']['audio']['bitrate']) || !isset($info['mpeg']['audio']['bitrate']) || ($next_frame_test_array['mpeg']['audio']['bitrate'] != $info['mpeg']['audio']['bitrate'])) {
   1.975 +                        return false;
   1.976 +                    }
   1.977 +                }
   1.978 +
   1.979 +
   1.980 +                // next frame is OK, get ready to check the one after that
   1.981 +                if (isset($next_frame_test_array['mpeg']['audio']['framelength']) && ($next_frame_test_array['mpeg']['audio']['framelength'] > 0)) {
   1.982 +                    $next_frame_test_offset += $next_frame_test_array['mpeg']['audio']['framelength'];
   1.983 +                } else {
   1.984 +                    
   1.985 +                    // non-fatal error: Frame at offset $offset has an invalid frame length.
   1.986 +                    return;
   1.987 +                }
   1.988 +
   1.989 +            } else {
   1.990 +
   1.991 +                // non-fatal error: Next frame is not valid.
   1.992 +                return;
   1.993 +            }
   1.994 +        }
   1.995 +        return true;
   1.996 +    }
   1.997 +
   1.998 +    
   1.999 +    
  1.1000 +    public function FreeFormatFrameLength($fd, $offset, &$info, $deep_scan=false) {
  1.1001 +        fseek($fd, $offset, SEEK_SET);
  1.1002 +        $mpeg_audio_data = fread($fd, 32768);
  1.1003 +
  1.1004 +        $sync_pattern1 = substr($mpeg_audio_data, 0, 4);
  1.1005 +        // may be different pattern due to padding
  1.1006 +        $sync_pattern2 = $sync_pattern1{0}.$sync_pattern1{1}.chr(ord($sync_pattern1{2}) | 0x02).$sync_pattern1{3};
  1.1007 +        if ($sync_pattern2 === $sync_pattern1) {
  1.1008 +            $sync_pattern2 = $sync_pattern1{0}.$sync_pattern1{1}.chr(ord($sync_pattern1{2}) & 0xFD).$sync_pattern1{3};
  1.1009 +        }
  1.1010 +
  1.1011 +        $frame_length = false;
  1.1012 +        $frame_length1 = strpos($mpeg_audio_data, $sync_pattern1, 4);
  1.1013 +        $frame_length2 = strpos($mpeg_audio_data, $sync_pattern2, 4);
  1.1014 +        if ($frame_length1 > 4) {
  1.1015 +            $frame_length = $frame_length1;
  1.1016 +        }
  1.1017 +        if (($frame_length2 > 4) && ($frame_length2 < $frame_length1)) {
  1.1018 +            $frame_length = $frame_length2;
  1.1019 +        }
  1.1020 +        if (!$frame_length) {
  1.1021 +
  1.1022 +            // LAME 3.88 has a different value for modeextension on the first frame vs the rest
  1.1023 +            $frame_length1 = strpos($mpeg_audio_data, substr($sync_pattern1, 0, 3), 4);
  1.1024 +            $frame_length2 = strpos($mpeg_audio_data, substr($sync_pattern2, 0, 3), 4);
  1.1025 +
  1.1026 +            if ($frame_length1 > 4) {
  1.1027 +                $frame_length = $frame_length1;
  1.1028 +            }
  1.1029 +            if (($frame_length2 > 4) && ($frame_length2 < $frame_length1)) {
  1.1030 +                $frame_length = $frame_length2;
  1.1031 +            }
  1.1032 +            if (!$frame_length) {
  1.1033 +                throw new getid3_exception('Cannot find next free-format synch pattern ('.getid3_lib::PrintHexBytes($sync_pattern1).' or '.getid3_lib::PrintHexBytes($sync_pattern2).') after offset '.$offset);
  1.1034 +            } else {
  1.1035 +                $this->getid3->warning('ModeExtension varies between first frame and other frames (known free-format issue in LAME 3.88)');
  1.1036 +                $info['audio']['codec']   = 'LAME';
  1.1037 +                $info['audio']['encoder'] = 'LAME3.88';
  1.1038 +                $sync_pattern1 = substr($sync_pattern1, 0, 3);
  1.1039 +                $sync_pattern2 = substr($sync_pattern2, 0, 3);
  1.1040 +            }
  1.1041 +        }
  1.1042 +
  1.1043 +        if ($deep_scan) {
  1.1044 +
  1.1045 +            $actual_frame_length_values = array ();
  1.1046 +            $next_offset = $offset + $frame_length;
  1.1047 +            while ($next_offset < ($info['avdataend'] - 6)) {
  1.1048 +                fseek($fd, $next_offset - 1, SEEK_SET);
  1.1049 +                $NextSyncPattern = fread($fd, 6);
  1.1050 +                if ((substr($NextSyncPattern, 1, strlen($sync_pattern1)) == $sync_pattern1) || (substr($NextSyncPattern, 1, strlen($sync_pattern2)) == $sync_pattern2)) {
  1.1051 +                    // good - found where expected
  1.1052 +                    $actual_frame_length_values[] = $frame_length;
  1.1053 +                } elseif ((substr($NextSyncPattern, 0, strlen($sync_pattern1)) == $sync_pattern1) || (substr($NextSyncPattern, 0, strlen($sync_pattern2)) == $sync_pattern2)) {
  1.1054 +                    // ok - found one byte earlier than expected (last frame wasn't padded, first frame was)
  1.1055 +                    $actual_frame_length_values[] = ($frame_length - 1);
  1.1056 +                    $next_offset--;
  1.1057 +                } elseif ((substr($NextSyncPattern, 2, strlen($sync_pattern1)) == $sync_pattern1) || (substr($NextSyncPattern, 2, strlen($sync_pattern2)) == $sync_pattern2)) {
  1.1058 +                    // ok - found one byte later than expected (last frame was padded, first frame wasn't)
  1.1059 +                    $actual_frame_length_values[] = ($frame_length + 1);
  1.1060 +                    $next_offset++;
  1.1061 +                } else {
  1.1062 +                    throw new getid3_exception('Did not find expected free-format sync pattern at offset '.$next_offset);
  1.1063 +                }
  1.1064 +                $next_offset += $frame_length;
  1.1065 +            }
  1.1066 +            if (count($actual_frame_length_values) > 0) {
  1.1067 +                $frame_length = intval(round(array_sum($actual_frame_length_values) / count($actual_frame_length_values)));
  1.1068 +            }
  1.1069 +        }
  1.1070 +        return $frame_length;
  1.1071 +    }
  1.1072 +
  1.1073 +    
  1.1074 +
  1.1075 +    public function getOnlyMPEGaudioInfo($fd, &$info, $avdata_offset, $bit_rate_histogram=false) {
  1.1076 +
  1.1077 +        // looks for synch, decodes MPEG audio header
  1.1078 +     
  1.1079 +        fseek($fd, $avdata_offset, SEEK_SET);
  1.1080 +        
  1.1081 +        $sync_seek_buffer_size = min(128 * 1024, $info['avdataend'] - $avdata_offset);
  1.1082 +        $header = fread($fd, $sync_seek_buffer_size);
  1.1083 +        $sync_seek_buffer_size = strlen($header);
  1.1084 +        $synch_seek_offset = 0;
  1.1085 +        
  1.1086 +        static $mpeg_audio_version_lookup;
  1.1087 +        static $mpeg_audio_layer_lookup;
  1.1088 +        static $mpeg_audio_bitrate_lookup;
  1.1089 +        if (empty($mpeg_audio_version_lookup)) {
  1.1090 +            $mpeg_audio_version_lookup = getid3_mp3::MPEGaudioVersionarray();
  1.1091 +            $mpeg_audio_layer_lookup   = getid3_mp3::MPEGaudioLayerarray();
  1.1092 +            $mpeg_audio_bitrate_lookup = getid3_mp3::MPEGaudioBitratearray();
  1.1093 +
  1.1094 +        }
  1.1095 +
  1.1096 +        while ($synch_seek_offset < $sync_seek_buffer_size) {
  1.1097 +     
  1.1098 +            if ((($avdata_offset + $synch_seek_offset)  < $info['avdataend']) && !feof($fd)) {
  1.1099 +     
  1.1100 +                // if a synch's not found within the first 128k bytes, then give up               
  1.1101 +                if ($synch_seek_offset > $sync_seek_buffer_size) {
  1.1102 +                    throw new getid3_exception('Could not find valid MPEG audio synch within the first '.round($sync_seek_buffer_size / 1024).'kB');
  1.1103 +                } 
  1.1104 +              
  1.1105 +                if (feof($fd)) {
  1.1106 +                    throw new getid3_exception('Could not find valid MPEG audio synch before end of file');
  1.1107 +                }
  1.1108 +            }
  1.1109 +     
  1.1110 +           if (($synch_seek_offset + 1) >= strlen($header)) {
  1.1111 +                throw new getid3_exception('Could not find valid MPEG synch before end of file');
  1.1112 +           }
  1.1113 +     
  1.1114 +           if (($header{$synch_seek_offset} == "\xFF") && ($header{($synch_seek_offset + 1)} > "\xE0")) { // synch detected 
  1.1115 +
  1.1116 +                if (!isset($first_frame_info) && !isset($info['mpeg']['audio'])) {
  1.1117 +                    $first_frame_info = $info;
  1.1118 +                    $first_frame_avdata_offset = $avdata_offset + $synch_seek_offset;
  1.1119 +                    if (!getid3_mp3::decodeMPEGaudioHeader($fd, $avdata_offset + $synch_seek_offset, $first_frame_info, false)) {
  1.1120 +                        // if this is the first valid MPEG-audio frame, save it in case it's a VBR header frame and there's
  1.1121 +                        // garbage between this frame and a valid sequence of MPEG-audio frames, to be restored below
  1.1122 +                        unset($first_frame_info);
  1.1123 +                    }
  1.1124 +                }
  1.1125 +
  1.1126 +                $dummy = $info; // only overwrite real data if valid header found
  1.1127 +                if (getid3_mp3::decodeMPEGaudioHeader($fd, $avdata_offset + $synch_seek_offset, $dummy, true)) {
  1.1128 +                    $info = $dummy;
  1.1129 +                    $info['avdataoffset'] = $avdata_offset + $synch_seek_offset;
  1.1130 +                    
  1.1131 +                    switch (@$info['fileformat']) {
  1.1132 +                        case '':
  1.1133 +                        case 'mp3':
  1.1134 +                            $info['fileformat']          = 'mp3';
  1.1135 +                            $info['audio']['dataformat'] = 'mp3';
  1.1136 +                            break;
  1.1137 +                    }
  1.1138 +                    if (isset($first_frame_info['mpeg']['audio']['bitrate_mode']) && ($first_frame_info['mpeg']['audio']['bitrate_mode'] == 'vbr')) {
  1.1139 +                        if (!(abs($info['audio']['bitrate'] - $first_frame_info['audio']['bitrate']) <= 1)) {
  1.1140 +                            // If there is garbage data between a valid VBR header frame and a sequence
  1.1141 +                            // of valid MPEG-audio frames the VBR data is no longer discarded.
  1.1142 +                            $info = $first_frame_info;
  1.1143 +                            $info['avdataoffset']        = $first_frame_avdata_offset;
  1.1144 +                            $info['fileformat']          = 'mp3';
  1.1145 +                            $info['audio']['dataformat'] = 'mp3';
  1.1146 +                            $dummy                               = $info;
  1.1147 +                            unset($dummy['mpeg']['audio']);
  1.1148 +                            $GarbageOffsetStart = $first_frame_avdata_offset + $first_frame_info['mpeg']['audio']['framelength'];
  1.1149 +                            $GarbageOffsetEnd   = $avdata_offset + $synch_seek_offset;
  1.1150 +                            if (getid3_mp3::decodeMPEGaudioHeader($fd, $GarbageOffsetEnd, $dummy, true, true)) {
  1.1151 +
  1.1152 +                                $info = $dummy;
  1.1153 +                                $info['avdataoffset'] = $GarbageOffsetEnd;
  1.1154 +                                $this->getid3->warning('apparently-valid VBR header not used because could not find '.getid3_mp3::VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.'), but did find valid CBR stream starting at '.$GarbageOffsetEnd);
  1.1155 +
  1.1156 +                            } else {
  1.1157 +
  1.1158 +                                $this->getid3->warning('using data from VBR header even though could not find '.getid3_mp3::VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.')');
  1.1159 +
  1.1160 +                            }
  1.1161 +                        }
  1.1162 +                    }
  1.1163 +                    if (isset($info['mpeg']['audio']['bitrate_mode']) && ($info['mpeg']['audio']['bitrate_mode'] == 'vbr') && !isset($info['mpeg']['audio']['VBR_method'])) {
  1.1164 +                        // VBR file with no VBR header
  1.1165 +                        $bit_rate_histogram = true;
  1.1166 +                    }
  1.1167 +
  1.1168 +                    if ($bit_rate_histogram) {
  1.1169 +
  1.1170 +                        $info['mpeg']['audio']['stereo_distribution']  = array ('stereo'=>0, 'joint stereo'=>0, 'dual channel'=>0, 'mono'=>0);
  1.1171 +                        $info['mpeg']['audio']['version_distribution'] = array ('1'=>0, '2'=>0, '2.5'=>0);
  1.1172 +
  1.1173 +                        if ($info['mpeg']['audio']['version'] == '1') {
  1.1174 +                            if ($info['mpeg']['audio']['layer'] == 3) {
  1.1175 +                                $info['mpeg']['audio']['bitrate_distribution'] = array ('free'=>0, 32000=>0, 40000=>0, 48000=>0, 56000=>0, 64000=>0, 80000=>0, 96000=>0, 112000=>0, 128000=>0, 160000=>0, 192000=>0, 224000=>0, 256000=>0, 320000=>0);
  1.1176 +                            } elseif ($info['mpeg']['audio']['layer'] == 2) {
  1.1177 +                                $info['mpeg']['audio']['bitrate_distribution'] = array ('free'=>0, 32000=>0, 48000=>0, 56000=>0, 64000=>0, 80000=>0, 96000=>0, 112000=>0, 128000=>0, 160000=>0, 192000=>0, 224000=>0, 256000=>0, 320000=>0, 384000=>0);
  1.1178 +                            } elseif ($info['mpeg']['audio']['layer'] == 1) {
  1.1179 +                                $info['mpeg']['audio']['bitrate_distribution'] = array ('free'=>0, 32000=>0, 64000=>0, 96000=>0, 128000=>0, 160000=>0, 192000=>0, 224000=>0, 256000=>0, 288000=>0, 320000=>0, 352000=>0, 384000=>0, 416000=>0, 448000=>0);
  1.1180 +                            }
  1.1181 +                        } elseif ($info['mpeg']['audio']['layer'] == 1) {
  1.1182 +                            $info['mpeg']['audio']['bitrate_distribution'] = array ('free'=>0, 32000=>0, 48000=>0, 56000=>0, 64000=>0, 80000=>0, 96000=>0, 112000=>0, 128000=>0, 144000=>0, 160000=>0, 176000=>0, 192000=>0, 224000=>0, 256000=>0);
  1.1183 +                        } else {
  1.1184 +                            $info['mpeg']['audio']['bitrate_distribution'] = array ('free'=>0, 8000=>0, 16000=>0, 24000=>0, 32000=>0, 40000=>0, 48000=>0, 56000=>0, 64000=>0, 80000=>0, 96000=>0, 112000=>0, 128000=>0, 144000=>0, 160000=>0);
  1.1185 +                        }
  1.1186 +
  1.1187 +                        $dummy = array ('avdataend' => $info['avdataend'], 'avdataoffset' => $info['avdataoffset']);
  1.1188 +                        $synch_start_offset = $info['avdataoffset'];
  1.1189 +
  1.1190 +                        $fast_mode = false;
  1.1191 +                        $synch_errors_found = 0;
  1.1192 +                        while ($this->decodeMPEGaudioHeader($fd, $synch_start_offset, $dummy, false, false, $fast_mode)) {
  1.1193 +                            $fast_mode = true;
  1.1194 +                            $thisframebitrate = $mpeg_audio_bitrate_lookup[$mpeg_audio_version_lookup[$dummy['mpeg']['audio']['raw']['version']]][$mpeg_audio_layer_lookup[$dummy['mpeg']['audio']['raw']['layer']]][$dummy['mpeg']['audio']['raw']['bitrate']];
  1.1195 +
  1.1196 +                            if (empty($dummy['mpeg']['audio']['framelength'])) {
  1.1197 +                                $synch_errors_found++;
  1.1198 +                            } 
  1.1199 +                            else {
  1.1200 +                                @$info['mpeg']['audio']['bitrate_distribution'][$thisframebitrate]++;
  1.1201 +                                @$info['mpeg']['audio']['stereo_distribution'][$dummy['mpeg']['audio']['channelmode']]++;
  1.1202 +                                @$info['mpeg']['audio']['version_distribution'][$dummy['mpeg']['audio']['version']]++;
  1.1203 +
  1.1204 +                                $synch_start_offset += $dummy['mpeg']['audio']['framelength'];
  1.1205 +                            }
  1.1206 +                        }
  1.1207 +                        if ($synch_errors_found > 0) {
  1.1208 +                            $this->getid3->warning('Found '.$synch_errors_found.' synch errors in histogram analysis');
  1.1209 +                        }
  1.1210 +
  1.1211 +                        $bit_total     = 0;
  1.1212 +                        $frame_counter = 0;
  1.1213 +                        foreach ($info['mpeg']['audio']['bitrate_distribution'] as $bit_rate_value => $bit_rate_count) {
  1.1214 +                            $frame_counter += $bit_rate_count;
  1.1215 +                            if ($bit_rate_value != 'free') {
  1.1216 +                                $bit_total += ($bit_rate_value * $bit_rate_count);
  1.1217 +                            }
  1.1218 +                        }
  1.1219 +                        if ($frame_counter == 0) {
  1.1220 +                            throw new getid3_exception('Corrupt MP3 file: framecounter == zero');
  1.1221 +                        }
  1.1222 +                        $info['mpeg']['audio']['frame_count'] = $frame_counter;
  1.1223 +                        $info['mpeg']['audio']['bitrate']     = ($bit_total / $frame_counter);
  1.1224 +
  1.1225 +                        $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate'];
  1.1226 +
  1.1227 +
  1.1228 +                        // Definitively set VBR vs CBR, even if the Xing/LAME/VBRI header says differently
  1.1229 +                        $distinct_bit_rates = 0;
  1.1230 +                        foreach ($info['mpeg']['audio']['bitrate_distribution'] as $bit_rate_value => $bit_rate_count) {
  1.1231 +                            if ($bit_rate_count > 0) {
  1.1232 +                                $distinct_bit_rates++;
  1.1233 +                            }
  1.1234 +                        }
  1.1235 +                        if ($distinct_bit_rates > 1) {
  1.1236 +                            $info['mpeg']['audio']['bitrate_mode'] = 'vbr';
  1.1237 +                        } else {
  1.1238 +                            $info['mpeg']['audio']['bitrate_mode'] = 'cbr';
  1.1239 +                        }
  1.1240 +                        $info['audio']['bitrate_mode'] = $info['mpeg']['audio']['bitrate_mode'];
  1.1241 +
  1.1242 +                    }
  1.1243 +
  1.1244 +                    break; // exit while()
  1.1245 +                }
  1.1246 +            }
  1.1247 +
  1.1248 +            $synch_seek_offset++;
  1.1249 +            if (($avdata_offset + $synch_seek_offset) >= $info['avdataend']) {
  1.1250 +                // end of file/data
  1.1251 +
  1.1252 +                if (empty($info['mpeg']['audio'])) {
  1.1253 +
  1.1254 +                    throw new getid3_exception('could not find valid MPEG synch before end of file');
  1.1255 +                }
  1.1256 +                break;
  1.1257 +            }
  1.1258 +
  1.1259 +        }
  1.1260 +        
  1.1261 +        $info['audio']['channels']        = $info['mpeg']['audio']['channels'];
  1.1262 +        $info['audio']['channelmode']     = $info['mpeg']['audio']['channelmode'];
  1.1263 +        $info['audio']['sample_rate']     = $info['mpeg']['audio']['sample_rate'];
  1.1264 +        return true;
  1.1265 +    }
  1.1266 +
  1.1267 +
  1.1268 +
  1.1269 +    public static function MPEGaudioVersionarray() {
  1.1270 +        
  1.1271 +        static $array = array ('2.5', false, '2', '1');
  1.1272 +        return $array;
  1.1273 +    }
  1.1274 +
  1.1275 +
  1.1276 +
  1.1277 +    public static function MPEGaudioLayerarray() {
  1.1278 +        
  1.1279 +        static $array = array (false, 3, 2, 1);
  1.1280 +        return $array;
  1.1281 +    }
  1.1282 +
  1.1283 +
  1.1284 +
  1.1285 +    public static function MPEGaudioBitratearray() {
  1.1286 +        
  1.1287 +        static $array;
  1.1288 +        if (empty($array)) {
  1.1289 +            $array = array (
  1.1290 +                '1'  =>  array (1 => array ('free', 32000, 64000, 96000, 128000, 160000, 192000, 224000, 256000, 288000, 320000, 352000, 384000, 416000, 448000),
  1.1291 +                                2 => array ('free', 32000, 48000, 56000,  64000,  80000,  96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, 384000),
  1.1292 +                                3 => array ('free', 32000, 40000, 48000,  56000,  64000,  80000,  96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000)
  1.1293 +                               ),
  1.1294 +
  1.1295 +                '2'  =>  array (1 => array ('free', 32000, 48000, 56000,  64000,  80000,  96000, 112000, 128000, 144000, 160000, 176000, 192000, 224000, 256000),
  1.1296 +                                2 => array ('free',  8000, 16000, 24000,  32000,  40000,  48000,  56000,  64000,  80000,  96000, 112000, 128000, 144000, 160000),
  1.1297 +                               )
  1.1298 +            );
  1.1299 +            $array['2'][3] = $array['2'][2];
  1.1300 +            $array['2.5']  = $array['2'];
  1.1301 +        }
  1.1302 +        return $array;
  1.1303 +    }
  1.1304 +
  1.1305 +
  1.1306 +
  1.1307 +    public static function MPEGaudioFrequencyarray() {
  1.1308 +        
  1.1309 +        static $array = array (
  1.1310 +                '1'   => array (44100, 48000, 32000),
  1.1311 +                '2'   => array (22050, 24000, 16000),
  1.1312 +                '2.5' => array (11025, 12000,  8000)
  1.1313 +        );
  1.1314 +        return $array;
  1.1315 +    }
  1.1316 +
  1.1317 +
  1.1318 +
  1.1319 +    public static function MPEGaudioChannelModearray() {
  1.1320 +        
  1.1321 +        static $array = array ('stereo', 'joint stereo', 'dual channel', 'mono');
  1.1322 +        return $array;
  1.1323 +    }
  1.1324 +
  1.1325 +
  1.1326 +
  1.1327 +    public static function MPEGaudioModeExtensionarray() {
  1.1328 +        
  1.1329 +        static $array = array (
  1.1330 +                1 => array ('4-31', '8-31', '12-31', '16-31'),
  1.1331 +                2 => array ('4-31', '8-31', '12-31', '16-31'),
  1.1332 +                3 => array ('', 'IS', 'MS', 'IS+MS')
  1.1333 +        );
  1.1334 +        return $array;
  1.1335 +    }
  1.1336 +
  1.1337 +
  1.1338 +
  1.1339 +    public static function MPEGaudioEmphasisarray() {
  1.1340 +        
  1.1341 +        static $array = array ('none', '50/15ms', false, 'CCIT J.17');
  1.1342 +        return $array;
  1.1343 +    }
  1.1344 +
  1.1345 +
  1.1346 +
  1.1347 +    public static function MPEGaudioHeaderBytesValid($head4, $allow_bitrate_15=false) {
  1.1348 +        
  1.1349 +        return getid3_mp3::MPEGaudioHeaderValid(getid3_mp3::MPEGaudioHeaderDecode($head4), false, $allow_bitrate_15);
  1.1350 +    }
  1.1351 +
  1.1352 +
  1.1353 +
  1.1354 +    public static function MPEGaudioHeaderValid($raw_array, $echo_errors=false, $allow_bitrate_15=false) {
  1.1355 +        
  1.1356 +        if (($raw_array['synch'] & 0x0FFE) != 0x0FFE) {
  1.1357 +            return false;
  1.1358 +        }
  1.1359 +
  1.1360 +        static $mpeg_audio_version_lookup;
  1.1361 +        static $mpeg_audio_layer_lookup;
  1.1362 +        static $mpeg_audio_bitrate_lookup;
  1.1363 +        static $mpeg_audio_frequency_lookup;
  1.1364 +        static $mpeg_audio_channel_mode_lookup;
  1.1365 +        static $mpeg_audio_mode_extension_lookup;
  1.1366 +        static $mpeg_audio_emphasis_lookup;
  1.1367 +        if (empty($mpeg_audio_version_lookup)) {
  1.1368 +            $mpeg_audio_version_lookup        = getid3_mp3::MPEGaudioVersionarray();
  1.1369 +            $mpeg_audio_layer_lookup          = getid3_mp3::MPEGaudioLayerarray();
  1.1370 +            $mpeg_audio_bitrate_lookup        = getid3_mp3::MPEGaudioBitratearray();
  1.1371 +            $mpeg_audio_frequency_lookup      = getid3_mp3::MPEGaudioFrequencyarray();
  1.1372 +            $mpeg_audio_channel_mode_lookup   = getid3_mp3::MPEGaudioChannelModearray();
  1.1373 +            $mpeg_audio_mode_extension_lookup = getid3_mp3::MPEGaudioModeExtensionarray();
  1.1374 +            $mpeg_audio_emphasis_lookup       = getid3_mp3::MPEGaudioEmphasisarray();
  1.1375 +        }
  1.1376 +
  1.1377 +        if (isset($mpeg_audio_version_lookup[$raw_array['version']])) {
  1.1378 +            $decodedVersion = $mpeg_audio_version_lookup[$raw_array['version']];
  1.1379 +        } else {
  1.1380 +            echo ($echo_errors ? "\n".'invalid Version ('.$raw_array['version'].')' : '');
  1.1381 +            return false;
  1.1382 +        }
  1.1383 +        if (isset($mpeg_audio_layer_lookup[$raw_array['layer']])) {
  1.1384 +            $decodedLayer = $mpeg_audio_layer_lookup[$raw_array['layer']];
  1.1385 +        } else {
  1.1386 +            echo ($echo_errors ? "\n".'invalid Layer ('.$raw_array['layer'].')' : '');
  1.1387 +            return false;
  1.1388 +        }
  1.1389 +        if (!isset($mpeg_audio_bitrate_lookup[$decodedVersion][$decodedLayer][$raw_array['bitrate']])) {
  1.1390 +            echo ($echo_errors ? "\n".'invalid Bitrate ('.$raw_array['bitrate'].')' : '');
  1.1391 +            if ($raw_array['bitrate'] == 15) {
  1.1392 +                // known issue in LAME 3.90 - 3.93.1 where free-format has bitrate ID of 15 instead of 0
  1.1393 +                // let it go through here otherwise file will not be identified
  1.1394 +                if (!$allow_bitrate_15) {
  1.1395 +                    return false;
  1.1396 +                }
  1.1397 +            } else {
  1.1398 +                return false;
  1.1399 +            }
  1.1400 +        }
  1.1401 +        if (!isset($mpeg_audio_frequency_lookup[$decodedVersion][$raw_array['sample_rate']])) {
  1.1402 +            echo ($echo_errors ? "\n".'invalid Frequency ('.$raw_array['sample_rate'].')' : '');
  1.1403 +            return false;
  1.1404 +        }
  1.1405 +        if (!isset($mpeg_audio_channel_mode_lookup[$raw_array['channelmode']])) {
  1.1406 +            echo ($echo_errors ? "\n".'invalid ChannelMode ('.$raw_array['channelmode'].')' : '');
  1.1407 +            return false;
  1.1408 +        }
  1.1409 +        if (!isset($mpeg_audio_mode_extension_lookup[$decodedLayer][$raw_array['modeextension']])) {
  1.1410 +            echo ($echo_errors ? "\n".'invalid Mode Extension ('.$raw_array['modeextension'].')' : '');
  1.1411 +            return false;
  1.1412 +        }
  1.1413 +        if (!isset($mpeg_audio_emphasis_lookup[$raw_array['emphasis']])) {
  1.1414 +            echo ($echo_errors ? "\n".'invalid Emphasis ('.$raw_array['emphasis'].')' : '');
  1.1415 +            return false;
  1.1416 +        }
  1.1417 +        // These are just either set or not set, you can't mess that up :)
  1.1418 +        // $raw_array['protection'];
  1.1419 +        // $raw_array['padding'];
  1.1420 +        // $raw_array['private'];
  1.1421 +        // $raw_array['copyright'];
  1.1422 +        // $raw_array['original'];
  1.1423 +
  1.1424 +        return true;
  1.1425 +    }
  1.1426 +
  1.1427 +
  1.1428 +
  1.1429 +    public static function MPEGaudioHeaderDecode($header_four_bytes) {
  1.1430 +        // AAAA AAAA  AAAB BCCD  EEEE FFGH  IIJJ KLMM
  1.1431 +        // A - Frame sync (all bits set)
  1.1432 +        // B - MPEG Audio version ID
  1.1433 +        // C - Layer description
  1.1434 +        // D - Protection bit
  1.1435 +        // E - Bitrate index
  1.1436 +        // F - Sampling rate frequency index
  1.1437 +        // G - Padding bit
  1.1438 +        // H - Private bit
  1.1439 +        // I - Channel Mode
  1.1440 +        // J - Mode extension (Only if Joint stereo)
  1.1441 +        // K - Copyright
  1.1442 +        // L - Original
  1.1443 +        // M - Emphasis
  1.1444 +
  1.1445 +        if (strlen($header_four_bytes) != 4) {
  1.1446 +            return false;
  1.1447 +        }
  1.1448 +
  1.1449 +        $mpeg_raw_header['synch']         = (getid3_lib::BigEndian2Int(substr($header_four_bytes, 0, 2)) & 0xFFE0) >> 4;
  1.1450 +        $mpeg_raw_header['version']       = (ord($header_four_bytes{1}) & 0x18) >> 3; //    BB
  1.1451 +        $mpeg_raw_header['layer']         = (ord($header_four_bytes{1}) & 0x06) >> 1; //      CC
  1.1452 +        $mpeg_raw_header['protection']    = (ord($header_four_bytes{1}) & 0x01);      //        D
  1.1453 +        $mpeg_raw_header['bitrate']       = (ord($header_four_bytes{2}) & 0xF0) >> 4; // EEEE
  1.1454 +        $mpeg_raw_header['sample_rate']   = (ord($header_four_bytes{2}) & 0x0C) >> 2; //     FF
  1.1455 +        $mpeg_raw_header['padding']       = (ord($header_four_bytes{2}) & 0x02) >> 1; //       G
  1.1456 +        $mpeg_raw_header['private']       = (ord($header_four_bytes{2}) & 0x01);      //        H
  1.1457 +        $mpeg_raw_header['channelmode']   = (ord($header_four_bytes{3}) & 0xC0) >> 6; // II
  1.1458 +        $mpeg_raw_header['modeextension'] = (ord($header_four_bytes{3}) & 0x30) >> 4; //   JJ
  1.1459 +        $mpeg_raw_header['copyright']     = (ord($header_four_bytes{3}) & 0x08) >> 3; //     K
  1.1460 +        $mpeg_raw_header['original']      = (ord($header_four_bytes{3}) & 0x04) >> 2; //      L
  1.1461 +        $mpeg_raw_header['emphasis']      = (ord($header_four_bytes{3}) & 0x03);      //       MM
  1.1462 +
  1.1463 +        return $mpeg_raw_header;
  1.1464 +    }
  1.1465 +
  1.1466 +
  1.1467 +
  1.1468 +    public static function MPEGaudioFrameLength(&$bit_rate, &$version, &$layer, $padding, &$sample_rate) {
  1.1469 +        
  1.1470 +        if (!isset($cache[$bit_rate][$version][$layer][$padding][$sample_rate])) {
  1.1471 +            $cache[$bit_rate][$version][$layer][$padding][$sample_rate] = false;
  1.1472 +            if ($bit_rate != 'free') {
  1.1473 +
  1.1474 +                if ($version == '1') {
  1.1475 +
  1.1476 +                    if ($layer == '1') {
  1.1477 +
  1.1478 +                        // For Layer I slot is 32 bits long
  1.1479 +                        $frame_length_coefficient = 48;
  1.1480 +                        $slot_length = 4;
  1.1481 +
  1.1482 +                    } else { // Layer 2 / 3
  1.1483 +
  1.1484 +                        // for Layer 2 and Layer 3 slot is 8 bits long.
  1.1485 +                        $frame_length_coefficient = 144;
  1.1486 +                        $slot_length = 1;
  1.1487 +
  1.1488 +                    }
  1.1489 +
  1.1490 +                } else { // MPEG-2 / MPEG-2.5
  1.1491 +
  1.1492 +                    if ($layer == '1') {
  1.1493 +
  1.1494 +                        // For Layer I slot is 32 bits long
  1.1495 +                        $frame_length_coefficient = 24;
  1.1496 +                        $slot_length = 4;
  1.1497 +
  1.1498 +                    } elseif ($layer == '2') {
  1.1499 +
  1.1500 +                        // for Layer 2 and Layer 3 slot is 8 bits long.
  1.1501 +                        $frame_length_coefficient = 144;
  1.1502 +                        $slot_length = 1;
  1.1503 +
  1.1504 +                    } else { // layer 3
  1.1505 +
  1.1506 +                        // for Layer 2 and Layer 3 slot is 8 bits long.
  1.1507 +                        $frame_length_coefficient = 72;
  1.1508 +                        $slot_length = 1;
  1.1509 +
  1.1510 +                    }
  1.1511 +
  1.1512 +                }
  1.1513 +
  1.1514 +                // FrameLengthInBytes = ((Coefficient * BitRate) / SampleRate) + Padding
  1.1515 +                if ($sample_rate > 0) {
  1.1516 +                    $new_frame_length  = ($frame_length_coefficient * $bit_rate) / $sample_rate;
  1.1517 +                    $new_frame_length  = floor($new_frame_length / $slot_length) * $slot_length; // round to next-lower multiple of SlotLength (1 byte for Layer 2/3, 4 bytes for Layer I)
  1.1518 +                    if ($padding) {
  1.1519 +                        $new_frame_length += $slot_length;
  1.1520 +                    }
  1.1521 +                    $cache[$bit_rate][$version][$layer][$padding][$sample_rate] = (int) $new_frame_length;
  1.1522 +                }
  1.1523 +            }
  1.1524 +        }
  1.1525 +        return $cache[$bit_rate][$version][$layer][$padding][$sample_rate];
  1.1526 +    }
  1.1527 +
  1.1528 +
  1.1529 +
  1.1530 +    public static function ClosestStandardMP3Bitrate($bit_rate) {
  1.1531 +        
  1.1532 +        static $standard_bit_rates = array (320000, 256000, 224000, 192000, 160000, 128000, 112000, 96000, 80000, 64000, 56000, 48000, 40000, 32000, 24000, 16000, 8000);
  1.1533 +        static $bit_rate_table = array (0=>'-');
  1.1534 +        $round_bit_rate = intval(round($bit_rate, -3));
  1.1535 +        if (!isset($bit_rate_table[$round_bit_rate])) {
  1.1536 +            if ($round_bit_rate > 320000) {
  1.1537 +                $bit_rate_table[$round_bit_rate] = round($bit_rate, -4);
  1.1538 +            } else {
  1.1539 +                $last_bit_rate = 320000;
  1.1540 +                foreach ($standard_bit_rates as $standard_bit_rate) {
  1.1541 +                    $bit_rate_table[$round_bit_rate] = $standard_bit_rate;
  1.1542 +                    if ($round_bit_rate >= $standard_bit_rate - (($last_bit_rate - $standard_bit_rate) / 2)) {
  1.1543 +                        break;
  1.1544 +                    }
  1.1545 +                    $last_bit_rate = $standard_bit_rate;
  1.1546 +                }
  1.1547 +            }
  1.1548 +        }
  1.1549 +        return $bit_rate_table[$round_bit_rate];
  1.1550 +    }
  1.1551 +
  1.1552 +
  1.1553 +
  1.1554 +    public static function XingVBRidOffset($version, $channel_mode) {
  1.1555 +        
  1.1556 +        static $lookup = array (
  1.1557 +                '1'   => array ('mono'          => 0x15, // 4 + 17 = 21
  1.1558 +                                'stereo'        => 0x24, // 4 + 32 = 36
  1.1559 +                                'joint stereo'  => 0x24,
  1.1560 +                                'dual channel'  => 0x24
  1.1561 +                               ),
  1.1562 +
  1.1563 +                '2'   => array ('mono'          => 0x0D, // 4 +  9 = 13
  1.1564 +                                'stereo'        => 0x15, // 4 + 17 = 21
  1.1565 +                                'joint stereo'  => 0x15,
  1.1566 +                                'dual channel'  => 0x15
  1.1567 +                               ),
  1.1568 +
  1.1569 +                '2.5' => array ('mono'          => 0x15,
  1.1570 +                                'stereo'        => 0x15,
  1.1571 +                                'joint stereo'  => 0x15,
  1.1572 +                                'dual channel'  => 0x15
  1.1573 +                               )
  1.1574 +        );
  1.1575 +        
  1.1576 +        return $lookup[$version][$channel_mode];
  1.1577 +    }
  1.1578 +
  1.1579 +
  1.1580 +
  1.1581 +    public static function LAMEvbrMethodLookup($vbr_method_id) {
  1.1582 +        
  1.1583 +        static $lookup = array (
  1.1584 +            0x00 => 'unknown',
  1.1585 +            0x01 => 'cbr',
  1.1586 +            0x02 => 'abr',
  1.1587 +            0x03 => 'vbr-old / vbr-rh',
  1.1588 +            0x04 => 'vbr-new / vbr-mtrh',
  1.1589 +            0x05 => 'vbr-mt',
  1.1590 +            0x06 => 'Full VBR Method 4',
  1.1591 +            0x08 => 'constant bitrate 2 pass',
  1.1592 +            0x09 => 'abr 2 pass',
  1.1593 +            0x0F => 'reserved'
  1.1594 +        );
  1.1595 +        return (isset($lookup[$vbr_method_id]) ? $lookup[$vbr_method_id] : '');
  1.1596 +    }
  1.1597 +
  1.1598 +
  1.1599 +
  1.1600 +    public static function LAMEmiscStereoModeLookup($stereo_mode_id) {
  1.1601 +    
  1.1602 +        static $lookup = array (
  1.1603 +            0 => 'mono',
  1.1604 +            1 => 'stereo',
  1.1605 +            2 => 'dual mono',
  1.1606 +            3 => 'joint stereo',
  1.1607 +            4 => 'forced stereo',
  1.1608 +            5 => 'auto',
  1.1609 +            6 => 'intensity stereo',
  1.1610 +            7 => 'other'
  1.1611 +        );
  1.1612 +        return (isset($lookup[$stereo_mode_id]) ? $lookup[$stereo_mode_id] : '');
  1.1613 +    }
  1.1614 +
  1.1615 +
  1.1616 +
  1.1617 +    public static function LAMEmiscSourceSampleFrequencyLookup($source_sample_frequency_id) {
  1.1618 +        
  1.1619 +        static $lookup = array (
  1.1620 +            0 => '<= 32 kHz',
  1.1621 +            1 => '44.1 kHz',
  1.1622 +            2 => '48 kHz',
  1.1623 +            3 => '> 48kHz'
  1.1624 +        );
  1.1625 +        return (isset($lookup[$source_sample_frequency_id]) ? $lookup[$source_sample_frequency_id] : '');
  1.1626 +    }
  1.1627 +
  1.1628 +
  1.1629 +
  1.1630 +    public static function LAMEsurroundInfoLookup($surround_info_id) {
  1.1631 +        
  1.1632 +        static $lookup = array (
  1.1633 +            0 => 'no surround info',
  1.1634 +            1 => 'DPL encoding',
  1.1635 +            2 => 'DPL2 encoding',
  1.1636 +            3 => 'Ambisonic encoding'
  1.1637 +        );
  1.1638 +        return (isset($lookup[$surround_info_id]) ? $lookup[$surround_info_id] : 'reserved');
  1.1639 +    }
  1.1640 +
  1.1641 +
  1.1642 +
  1.1643 +    public static function LAMEpresetUsedLookup($lame_tag) {
  1.1644 +        
  1.1645 +        if ($lame_tag['preset_used_id'] == 0) {
  1.1646 +            // no preset used (LAME >=3.93)
  1.1647 +            // no preset recorded (LAME <3.93)
  1.1648 +            return '';
  1.1649 +        }
  1.1650 +        
  1.1651 +        $lame_preset_used_lookup = array ();
  1.1652 +        
  1.1653 +        for ($i = 8; $i <= 320; $i++) {
  1.1654 +            switch ($lame_tag['vbr_method']) {
  1.1655 +                case 'cbr':
  1.1656 +                    $lame_preset_used_lookup[$i] = '--alt-preset '.$lame_tag['vbr_method'].' '.$i;
  1.1657 +                    break;
  1.1658 +                case 'abr':
  1.1659 +                default: // other VBR modes shouldn't be here(?)
  1.1660 +                    $lame_preset_used_lookup[$i] = '--alt-preset '.$i;
  1.1661 +                    break;
  1.1662 +            }
  1.1663 +        }
  1.1664 +
  1.1665 +        // named old-style presets (studio, phone, voice, etc) are handled in GuessEncoderOptions()
  1.1666 +
  1.1667 +        // named alt-presets
  1.1668 +        $lame_preset_used_lookup[1000] = '--r3mix';
  1.1669 +        $lame_preset_used_lookup[1001] = '--alt-preset standard';
  1.1670 +        $lame_preset_used_lookup[1002] = '--alt-preset extreme';
  1.1671 +        $lame_preset_used_lookup[1003] = '--alt-preset insane';
  1.1672 +        $lame_preset_used_lookup[1004] = '--alt-preset fast standard';
  1.1673 +        $lame_preset_used_lookup[1005] = '--alt-preset fast extreme';
  1.1674 +        $lame_preset_used_lookup[1006] = '--alt-preset medium';
  1.1675 +        $lame_preset_used_lookup[1007] = '--alt-preset fast medium';
  1.1676 +
  1.1677 +        // LAME 3.94 additions/changes
  1.1678 +        $lame_preset_used_lookup[1010] = '--preset portable';                                                            // 3.94a15 Oct 21 2003
  1.1679 +        $lame_preset_used_lookup[1015] = '--preset radio';                                                               // 3.94a15 Oct 21 2003
  1.1680 +
  1.1681 +        $lame_preset_used_lookup[320]  = '--preset insane';                                                              // 3.94a15 Nov 12 2003
  1.1682 +        $lame_preset_used_lookup[410]  = '-V9';
  1.1683 +        $lame_preset_used_lookup[420]  = '-V8';
  1.1684 +        $lame_preset_used_lookup[430]  = '--preset radio';                                                               // 3.94a15 Nov 12 2003
  1.1685 +        $lame_preset_used_lookup[440]  = '-V6';
  1.1686 +        $lame_preset_used_lookup[450]  = '--preset '.(($lame_tag['raw']['vbr_method'] == 4) ? 'fast ' : '').'portable';  // 3.94a15 Nov 12 2003
  1.1687 +        $lame_preset_used_lookup[460]  = '--preset '.(($lame_tag['raw']['vbr_method'] == 4) ? 'fast ' : '').'medium';    // 3.94a15 Nov 12 2003
  1.1688 +        $lame_preset_used_lookup[470]  = '--r3mix';                                                                      // 3.94b1  Dec 18 2003
  1.1689 +        $lame_preset_used_lookup[480]  = '--preset '.(($lame_tag['raw']['vbr_method'] == 4) ? 'fast ' : '').'standard';  // 3.94a15 Nov 12 2003
  1.1690 +        $lame_preset_used_lookup[490]  = '-V1';
  1.1691 +        $lame_preset_used_lookup[500]  = '--preset '.(($lame_tag['raw']['vbr_method'] == 4) ? 'fast ' : '').'extreme';   // 3.94a15 Nov 12 2003
  1.1692 +        
  1.1693 +        return (isset($lame_preset_used_lookup[$lame_tag['preset_used_id']]) ? $lame_preset_used_lookup[$lame_tag['preset_used_id']] : 'new/unknown preset: '.$lame_tag['preset_used_id'].' - report to info@getid3.org');
  1.1694 +    }
  1.1695 +	
  1.1696 +	
  1.1697 +}
  1.1698 +
  1.1699 +?>
  1.1700 \ No newline at end of file